patch-2.0.21-2.1.0 linux/arch/m68k/atari/ataints.c
Next file: linux/arch/m68k/atari/atakeyb.c
Previous file: linux/arch/m68k/atari/atafb.c
Back to the patch index
Back to the overall index
- Lines: 576
- Date:
Wed Sep 25 10:47:38 1996
- Orig file:
lx2.0/v2.0.21/linux/arch/m68k/atari/ataints.c
- Orig date:
Mon May 20 07:54:26 1996
diff -u --recursive --new-file lx2.0/v2.0.21/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c
@@ -9,9 +9,9 @@
* about non-autovec ints yet. It hardcoded the number of possible ints to
* 7 (IRQ1...IRQ7). But the Atari has lots of non-autovec ints! I made the
* number of possible ints a constant defined in interrupt.h, which is
- * 47 for the Atari. So we can call add_isr() for all Atari interrupts just
- * the normal way. Additionally, all vectors >= 48 are initialized to call
- * trap() instead of inthandler(). This must be changed here, too.
+ * 47 for the Atari. So we can call request_irq() for all Atari interrupts
+ * just the normal way. Additionally, all vectors >= 48 are initialized to
+ * call trap() instead of inthandler(). This must be changed here, too.
*
* 1995-07-16 Lars Brinkhoff <f93labr@dd.chalmers.se>:
* Corrected a bug in atari_add_isr() which rejected all SCC
@@ -24,6 +24,11 @@
* Total rewrite of Atari interrupt handling, for new scheme see comments
* below.
*
+ * 1996-09-03 lars brinkhoff <f93labr@dd.chalmers.se>:
+ * Added new function atari_unregister_vme_int(), and
+ * modified atari_register_vme_int() as well as IS_VALID_INTNO()
+ * to work with it.
+ *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
@@ -35,13 +40,13 @@
#include <linux/ptrace.h>
#include <linux/kernel_stat.h>
+#include <asm/setup.h>
#include <asm/system.h>
#include <asm/traps.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
#include <asm/atari_stdma.h>
-#include <asm/bootinfo.h>
#include <asm/irq.h>
@@ -74,14 +79,14 @@
* The feature of more than one handler for one int source is still there, but
* only applicable if all handers are of the same type. To not slow down
* processing of ints with only one handler by the chaining feature, the list
- * calling function atari_call_isr_list() is only plugged in at the time the
+ * calling function atari_call_irq_list() is only plugged in at the time the
* second handler is registered.
*
* Implementation notes: For fast-as-possible int handling, there are separate
* entry points for each type (slow/fast/prio). The assembler handler calls
- * the isr directly in the usual case, no C wrapper is involved. In case of
- * multiple handlers, atari_call_isr_list() is registered as handler and calls
- * in turn the real isr's. To ease access from assembler level to the isr
+ * the irq directly in the usual case, no C wrapper is involved. In case of
+ * multiple handlers, atari_call_irq_list() is registered as handler and calls
+ * in turn the real irq's. To ease access from assembler level to the irq
* function pointer and accompanying data, these two are stored in a separate
* array, irq_handler[]. The rest of data (type, name) are put into a second
* array, irq_param, that is accessed from C only. For each slow interrupt (32
@@ -106,17 +111,17 @@
typedef void (*asm_irq_handler)(void);
struct irqhandler {
- isrfunc isr;
- void *data;
+ void (*handler)(int, void *, struct pt_regs *);
+ void *dev_id;
};
struct irqparam {
- int type;
- char *name;
+ unsigned long flags;
+ const char *devname;
};
/*
- * Array with isr's and their parameter data. This array is accessed from low
+ * Array with irq's and their parameter data. This array is accessed from low
* level assembler code, so an element size of 8 allows usage of index scaling
* addressing mode.
*/
@@ -130,11 +135,11 @@
static struct irqparam irq_param[NUM_INT_SOURCES];
/*
- * Counter for next free interrupt vector number
+ * Bitmap for free interrupt vector numbers
* (new vectors starting from 0x70 can be allocated by
* atari_register_vme_int())
*/
-static int next_free_vme_vec = VME_SOURCE_BASE;
+static int free_vme_vec_bitmap = 0;
/* check for valid int number (complex, sigh...) */
#define IS_VALID_INTNO(n) \
@@ -147,8 +152,9 @@
/* SCC ok if present and number even */ \
((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \
!((n) & 1) && ATARIHW_PRESENT(SCC)) || \
- /* greater numbers ok if less than #registered VME vectors */ \
- ((n) >= VME_SOURCE_BASE && (n) < next_free_vme_vec)))
+ /* greater numbers ok if they are registered VME vectors */ \
+ ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
+ free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
/*
@@ -165,8 +171,7 @@
#define SR "0x28"
#define SAVE_ALL \
"clrl %%sp@-;" /* stk_adj */ \
- "clrl %%sp@-;" \
- "subql #1,%%sp@;" /* orig d0 = -1 */ \
+ "pea -1:w;" /* orig d0 = -1 */ \
"movel %%d0,%%sp@-;" /* d0 */ \
"moveml %%d1-%%d5/%%a0-%%a1,%%sp@-"
@@ -176,21 +181,19 @@
void atari_slow_irq_##n##_dummy (void) { \
__asm__ (ALIGN_STR "\n" \
SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \
- SAVE_ALL "\n" \
" addql #1,"SYMBOL_NAME_STR(intr_count)"\n" \
+ SAVE_ALL "\n" \
" andb #~(1<<(" #n "&7))," /* mask this interrupt */ \
"("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n" \
-" movew %%sp@("SR"),%%d0\n" /* get old IPL from stack frame */ \
+" bfextu %%sp@("SR"){#5,#3},%%d0\n" /* get old IPL from stack frame */ \
" movew %%sr,%%d1\n" \
-" andw #0x0700,%%d0\n" \
-" andw #0xf8ff,%%d1\n" \
-" orw %%d0,%%d1\n" \
+" bfins %%d0,%%d1{#21,#3}\n" \
" movew %%d1,%%sr\n" /* set IPL = previous value */ \
" addql #1,%a0\n" \
" lea "SYMBOL_NAME_STR(irq_handler)"+("#n"+8)*8,%%a0\n" \
+" pea %%sp@\n" /* push addr of frame */ \
" movel %%a0@(4),%%sp@-\n" /* push handler data */ \
-" pea %%sp@(4)\n" /* push addr of frame */ \
-" pea (" #n "+8):w\n" /* push int number */ \
+" pea (" #n "+0x10000008)\n" /* push int number */ \
" movel %%a0@,%%a0\n" \
" jbsr %%a0@\n" /* call the handler */ \
" addql #8,%%sp\n" \
@@ -280,21 +283,21 @@
__asm__ (ALIGN_STR "\n"
SYMBOL_NAME_STR(atari_fast_irq_handler) ":
orw #0x700,%%sr /* disable all interrupts */
-"SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t"
+"SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t
+ addql #1,"SYMBOL_NAME_STR(intr_count)"\n"
SAVE_ALL "
- addql #1,"SYMBOL_NAME_STR(intr_count)"
- movew %%sp@(" FORMATVEC "),%%d0 /* get vector number from stack frame */
- andil #0xfff,%%d0 /* mask off format nibble */
- lsrl #2,%%d0 /* convert vector to source */
- subl #(0x40-8),%%d0
+ /* get vector number from stack frame and convert to source */
+ bfextu %%sp@(" FORMATVEC "){#4,#10},%%d0
+ subw #(0x40-8),%%d0
jpl 1f
- addl #(0x40-8-0x18),%%d0
+ addw #(0x40-8-0x18),%%d0
1: lea %a0,%%a0
addql #1,%%a0@(%%d0:l:4)
lea "SYMBOL_NAME_STR(irq_handler)",%%a0
lea %%a0@(%%d0:l:8),%%a0
+ pea %%sp@ /* push frame address */
movel %%a0@(4),%%sp@- /* push handler data */
- pea %%sp@(4) /* push frame address */
+ bset #28,%%d0 /* set MACHSPEC bit */
movel %%d0,%%sp@- /* push int number */
movel %%a0@,%%a0
jsr %%a0@ /* and call the handler */
@@ -313,12 +316,7 @@
asm(".text\n"
ALIGN_STR "\n"
SYMBOL_NAME_STR(falcon_hblhandler) ":
- movel %d0,%sp@-
- movew %sp@(4),%d0
- andw #0xf8ff,%d0
- orw #0x0200,%d0 /* set saved ipl to 2 */
- movew %d0,%sp@(4)
- movel %sp@+,%d0
+ orw #0x200,%sp@ /* set saved ipl to 2 */
rte");
/* Defined in entry.S; only increments 'num_spurious' */
@@ -327,7 +325,7 @@
extern void atari_microwire_cmd( int cmd );
/*
- * void atari_init_INTS (void)
+ * void atari_init_IRQ (void)
*
* Parameters: None
*
@@ -337,7 +335,7 @@
* the atari IRQ handling routines.
*/
-void atari_init_INTS(void)
+void atari_init_IRQ(void)
{
int i;
@@ -353,9 +351,9 @@
#else
mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
#endif
- mfp.int_en_a = /* turn off MFP-Ints */
+ mfp.int_en_a = 0x00; /* turn off MFP-Ints */
mfp.int_en_b = 0x00;
- mfp.int_mk_a = /* no Masking */
+ mfp.int_mk_a = 0xff; /* no Masking */
mfp.int_mk_b = 0xff;
if (ATARIHW_PRESENT(TT_MFP)) {
@@ -364,9 +362,9 @@
#else
tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */
#endif
- tt_mfp.int_en_a = /* turn off MFP-Ints */
+ tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
tt_mfp.int_en_b = 0x00;
- tt_mfp.int_mk_a = /* no Masking */
+ tt_mfp.int_mk_a = 0xff; /* no Masking */
tt_mfp.int_mk_b = 0xff;
}
@@ -407,177 +405,169 @@
}
-static void atari_call_isr_list( int irq, struct pt_regs *fp, void *_p )
+static void atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
{
- isr_node_t *p;
-
- for( p = (isr_node_t *)_p; p; p = p->next )
- p->isr( irq, fp, p->data );
+ irq_node_t *node;
+
+ for (node = (irq_node_t *)dev_id; node; node = node->next)
+ node->handler(irq, node->dev_id, fp);
}
/*
- * atari_add_isr : add an interrupt service routine for a particular
- * machine specific interrupt source.
- * If the addition was successful, it returns 1, otherwise
- * it returns 0. It will fail if the interrupt is already
- * occupied of another handler with different type
+ * atari_request_irq : add an interrupt service routine for a particular
+ * machine specific interrupt source.
+ * If the addition was successful, it returns 0.
*/
-int atari_add_isr(unsigned long source, isrfunc isr, int type, void
- *data, char *name)
+int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
{
int vector;
- source &= ~IRQ_MACHSPEC;
- if (type < IRQ_TYPE_SLOW || type > IRQ_TYPE_PRIO) {
- printk ("atari_add_isr: Bad irq type %d requested from %s\n",
- type, name );
- return( 0 );
- }
- if (!IS_VALID_INTNO(source)) {
- printk ("atari_add_isr: Unknown irq %ld requested from %s\n",
- source, name );
- return( 0 );
+ if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
+ printk ("%s: Bad irq type %ld requested from %s\n",
+ __FUNCTION__, flags, devname);
+ return -EINVAL;
+ }
+ if (!IS_VALID_INTNO(irq)) {
+ printk ("%s: Unknown irq %d requested from %s\n",
+ __FUNCTION__, irq, devname);
+ return -ENXIO;
}
- vector = IRQ_SOURCE_TO_VECTOR(source);
+ vector = IRQ_SOURCE_TO_VECTOR(irq);
/*
* Check type/source combination: slow ints are (currently)
* only possible for MFP-interrupts.
*/
- if (type == IRQ_TYPE_SLOW &&
- (source < STMFP_SOURCE_BASE || source >= SCC_SOURCE_BASE)) {
- printk ("atari_add_isr: Slow irq requested for non-MFP source %ld from %s\n",
- source, name );
- return( 0 );
+ if (flags == IRQ_TYPE_SLOW &&
+ (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) {
+ printk ("%s: Slow irq requested for non-MFP source %d from %s\n",
+ __FUNCTION__, irq, devname);
+ return -EINVAL;
}
if (vectors[vector] == bad_interrupt) {
/* int has no handler yet */
- irq_handler[source].isr = isr;
- irq_handler[source].data = data;
- irq_param[source].type = type;
- irq_param[source].name = name;
+ irq_handler[irq].handler = handler;
+ irq_handler[irq].dev_id = dev_id;
+ irq_param[irq].flags = flags;
+ irq_param[irq].devname = devname;
vectors[vector] =
- (type == IRQ_TYPE_SLOW) ? slow_handlers[source-STMFP_SOURCE_BASE] :
- (type == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
- atari_prio_irq_handler;
+ (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] :
+ (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
+ atari_prio_irq_handler;
/* If MFP int, also enable and umask it */
- atari_turnon_irq(source);
- atari_enable_irq(source);
+ atari_turnon_irq(irq);
+ atari_enable_irq(irq);
- return 1;
+ return 0;
}
- else if (irq_param[source].type == type) {
+ else if (irq_param[irq].flags == flags) {
/* old handler is of same type -> handlers can be chained */
- isr_node_t *p;
+ irq_node_t *node;
unsigned long flags;
save_flags(flags);
cli();
- if (irq_handler[source].isr != atari_call_isr_list) {
+ if (irq_handler[irq].handler != atari_call_irq_list) {
/* Only one handler yet, make a node for this first one */
- p = new_isr_node();
- if (p == NULL) return 0;
- p->isr = irq_handler[source].isr;
- p->data = irq_handler[source].data;
- p->name = irq_param[source].name;
- p->next = NULL;
-
- irq_handler[source].isr = atari_call_isr_list;
- irq_handler[source].data = p;
- irq_param[source].name = "chained";
+ if (!(node = new_irq_node()))
+ return -ENOMEM;
+ node->handler = irq_handler[irq].handler;
+ node->dev_id = irq_handler[irq].dev_id;
+ node->devname = irq_param[irq].devname;
+ node->next = NULL;
+
+ irq_handler[irq].handler = atari_call_irq_list;
+ irq_handler[irq].dev_id = node;
+ irq_param[irq].devname = "chained";
}
- p = new_isr_node();
- if (p == NULL) return 0;
- p->isr = isr;
- p->data = data;
- p->name = name;
+ if (!(node = new_irq_node()))
+ return -ENOMEM;
+ node->handler = handler;
+ node->dev_id = dev_id;
+ node->devname = devname;
/* new handlers are put in front of the queue */
- p->next = irq_handler[source].data;
- irq_handler[source].data = p;
+ node->next = irq_handler[irq].dev_id;
+ irq_handler[irq].dev_id = node;
restore_flags(flags);
- return 1;
- }
- else {
- printk ("atari_add_isr: Irq %ld allocated by other type int (call from %s)\n",
- source, name );
- return( 0 );
+ return 0;
+ } else {
+ printk ("%s: Irq %d allocated by other type int (call from %s)\n",
+ __FUNCTION__, irq, devname);
+ return -EBUSY;
}
}
-
-int atari_remove_isr(unsigned long source, isrfunc isr, void *data)
+void atari_free_irq(unsigned int irq, void *dev_id)
{
unsigned long flags;
int vector;
- isr_node_t **p, *q;
-
- source &= ~IRQ_MACHSPEC;
+ irq_node_t **list, *node;
- if (!IS_VALID_INTNO(source)) {
- printk("atari_remove_isr: Unknown irq %ld\n", source);
- return 0;
+ if (!IS_VALID_INTNO(irq)) {
+ printk("%s: Unknown irq %d\n", __FUNCTION__, irq);
+ return;
}
- vector = IRQ_SOURCE_TO_VECTOR(source);
+ vector = IRQ_SOURCE_TO_VECTOR(irq);
if (vectors[vector] == bad_interrupt)
goto not_found;
save_flags(flags);
cli();
- if (irq_handler[source].isr != atari_call_isr_list) {
+ if (irq_handler[irq].handler != atari_call_irq_list) {
/* It's the only handler for the interrupt */
- if (irq_handler[source].isr != isr &&
- irq_handler[source].data != data) {
+ if (irq_handler[irq].dev_id != dev_id) {
restore_flags(flags);
goto not_found;
}
- irq_handler[source].isr = NULL;
- irq_handler[source].data = NULL;
- irq_param[source].name = NULL;
+ irq_handler[irq].handler = NULL;
+ irq_handler[irq].dev_id = NULL;
+ irq_param[irq].devname = NULL;
vectors[vector] = bad_interrupt;
/* If MFP int, also disable it */
- atari_disable_irq(source);
- atari_turnoff_irq(source);
+ atari_disable_irq(irq);
+ atari_turnoff_irq(irq);
restore_flags(flags);
- return 1;
+ return;
}
- /* The interrupt is chained, find the isr on the list */
- for( p = (isr_node_t **)&irq_handler[source].data; *p; p = &(*p)->next ) {
- if ((*p)->isr == isr) break;
+ /* The interrupt is chained, find the irq on the list */
+ for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) {
+ if ((*list)->dev_id == dev_id) break;
}
- if (!*p) {
+ if (!*list) {
restore_flags(flags);
goto not_found;
}
- (*p)->isr = NULL; /* Mark it as free for reallocation */
- *p = (*p)->next;
+ (*list)->handler = NULL; /* Mark it as free for reallocation */
+ *list = (*list)->next;
/* If there's now only one handler, unchain the interrupt, i.e. plug in
- * the handler directly again and omit atari_call_isr_list */
- q = (isr_node_t *)irq_handler[source].data;
- if (q && !q->next) {
- irq_handler[source].isr = q->isr;
- irq_handler[source].data = q->data;
- irq_param[source].name = q->name;
- q->isr = NULL; /* Mark it as free for reallocation */
+ * the handler directly again and omit atari_call_irq_list */
+ node = (irq_node_t *)irq_handler[irq].dev_id;
+ if (node && !node->next) {
+ irq_handler[irq].handler = node->handler;
+ irq_handler[irq].dev_id = node->dev_id;
+ irq_param[irq].devname = node->devname;
+ node->handler = NULL; /* Mark it as free for reallocation */
}
restore_flags(flags);
- return 1;
+ return;
- not_found:
- printk("atari_remove_isr: isr %p not found on list!\n", isr);
- return 0;
+not_found:
+ printk("%s: tried to remove invalid irq\n", __FUNCTION__);
+ return;
}
@@ -588,46 +578,60 @@
unsigned long atari_register_vme_int(void)
{
- unsigned long source;
+ int i;
+
+ for(i = 0; i < 32; i++)
+ if((free_vme_vec_bitmap & (1 << i)) == 0)
+ break;
- if (next_free_vme_vec == NUM_ATARI_SOURCES)
+ if(i == 16)
return 0;
- source = next_free_vme_vec | IRQ_MACHSPEC;
- next_free_vme_vec++;
- return source;
+ free_vme_vec_bitmap |= 1 << i;
+ return (VME_SOURCE_BASE + i) | IRQ_MACHSPEC;
}
-int atari_get_irq_list(char *buf, int len)
+void atari_unregister_vme_int(unsigned long irq)
{
- int i;
+ irq &= ~IRQ_MACHSPEC;
+
+ if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
+ irq -= VME_SOURCE_BASE;
+ free_vme_vec_bitmap &= ~(1 << irq);
+ }
+}
+
+
+int atari_get_irq_list(char *buf)
+{
+ int i, len = 0;
for (i = 0; i < NUM_INT_SOURCES; ++i) {
if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
continue;
if (i < STMFP_SOURCE_BASE)
- len += sprintf(buf+len, "auto %2d: %8d ",
+ len += sprintf(buf+len, "auto %2d: %10u ",
i, kstat.interrupts[i]);
else
- len += sprintf(buf+len, "vec $%02x: %8d ",
+ len += sprintf(buf+len, "vec $%02x: %10u ",
IRQ_SOURCE_TO_VECTOR(i),
kstat.interrupts[i]);
- if (irq_handler[i].isr != atari_call_isr_list) {
- len += sprintf(buf+len, "%s\n", irq_param[i].name);
+ if (irq_handler[i].handler != atari_call_irq_list) {
+ len += sprintf(buf+len, "%s\n", irq_param[i].devname);
}
else {
- isr_node_t *p;
- for( p = (isr_node_t *)irq_handler[i].data; p; p = p->next ) {
- len += sprintf(buf+len, "%s\n", p->name);
+ irq_node_t *p;
+ for( p = (irq_node_t *)irq_handler[i].dev_id; p; p = p->next ) {
+ len += sprintf(buf+len, "%s\n", p->devname);
if (p->next)
len += sprintf( buf+len, " " );
}
}
}
if (num_spurious)
- len += sprintf(buf+len, "spurio.: %8ld\n", num_spurious);
+ len += sprintf(buf+len, "spurio.: %10u\n", num_spurious);
return len;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov