Add changes from the Linux-2.6 tree.
[linux-2.6.git] / arch / m68k / atari / ataints.c
index f195e0e..7f81264 100644 (file)
 /*
  * Atari interrupt handling scheme:
  * --------------------------------
- * 
+ *
  * All interrupt source have an internal number (defined in
  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  * be allocated by atari_register_vme_int().
  *
  * Each interrupt can be of three types:
- * 
+ *
  *  - SLOW: The handler runs with all interrupts enabled, except the one it
  *    was called by (to avoid reentering). This should be the usual method.
  *    But it is currently possible only for MFP ints, since only the MFP
  * the sr copy in the frame.
  */
 
+#if 0
 
 #define        NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
 
@@ -133,13 +134,6 @@ static struct irqhandler irq_handler[NUM_INT_SOURCES];
  */
 static struct irqparam irq_param[NUM_INT_SOURCES];
 
-/*
- * Bitmap for free interrupt vector numbers
- * (new vectors starting from 0x70 can be allocated by
- * atari_register_vme_int())
- */
-static int free_vme_vec_bitmap;
-
 /* check for valid int number (complex, sigh...) */
 #define        IS_VALID_INTNO(n)                                                                                       \
        ((n) > 0 &&                                                                                                             \
@@ -179,16 +173,16 @@ __asm__ (__ALIGN_STR "\n"                                            \
 "      movew   %%d1,%%sr\n"            /* set IPL = previous value */     \
 "      addql   #1,%a0\n"                                                  \
 "      lea     %a1,%%a0\n"                                                \
-"      pea     %%sp@\n"                /* push addr of frame */           \
+"      pea     %%sp@\n"                /* push addr of frame */           \
 "      movel   %%a0@(4),%%sp@-\n"      /* push handler data */            \
-"      pea     (%c3+8)\n"              /* push int number */              \
+"      pea     (%c3+8)\n"              /* push int number */              \
 "      movel   %%a0@,%%a0\n"                                              \
 "      jbsr    %%a0@\n"                /* call the handler */             \
 "      addql   #8,%%sp\n"                                                 \
 "      addql   #4,%%sp\n"                                                 \
 "      orw     #0x0600,%%sr\n"                                            \
 "      andw    #0xfeff,%%sr\n"         /* set IPL = 6 again */            \
-"      orb     #(1<<(%c3&7)),%a4:w\n"  /* now unmask the int again */     \
+"      orb     #(1<<(%c3&7)),%a4:w\n"  /* now unmask the int again */     \
 "      jbra    ret_from_interrupt\n"                                      \
         : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),       \
             "n" (PT_OFF_SR), "n" (n),                                     \
@@ -274,7 +268,7 @@ asmlinkage void atari_prio_irq_handler( void );
 void atari_fast_prio_irq_dummy (void) {
 __asm__ (__ALIGN_STR "\n"
 "atari_fast_irq_handler:\n\t"
-       "orw    #0x700,%%sr\n"          /* disable all interrupts */
+       "orw    #0x700,%%sr\n"          /* disable all interrupts */
 "atari_prio_irq_handler:\n\t"
        "addl   %3,%2\n\t"              /* preempt_count() += HARDIRQ_OFFSET */
        SAVE_ALL_INT "\n\t"
@@ -282,13 +276,13 @@ __asm__ (__ALIGN_STR "\n"
        /* get vector number from stack frame and convert to source */
        "bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
        "subw   #(0x40-8),%%d0\n\t"
-       "jpl    1f\n\t"
+       "jpl    1f\n\t"
        "addw   #(0x40-8-0x18),%%d0\n"
     "1:\tlea   %a0,%%a0\n\t"
        "addql  #1,%%a0@(%%d0:l:4)\n\t"
        "lea    irq_handler,%%a0\n\t"
        "lea    %%a0@(%%d0:l:8),%%a0\n\t"
-       "pea    %%sp@\n\t"              /* push frame address */
+       "pea    %%sp@\n\t"              /* push frame address */
        "movel  %%a0@(4),%%sp@-\n\t"    /* push handler data */
        "movel  %%d0,%%sp@-\n\t"        /* push int number */
        "movel  %%a0@,%%a0\n\t"
@@ -301,6 +295,14 @@ __asm__ (__ALIGN_STR "\n"
 );
        for (;;);
 }
+#endif
+
+/*
+ * Bitmap for free interrupt vector numbers
+ * (new vectors starting from 0x70 can be allocated by
+ * atari_register_vme_int())
+ */
+static int free_vme_vec_bitmap;
 
 /* GK:
  * HBL IRQ handler for Falcon. Nobody needs it :-)
@@ -313,13 +315,37 @@ __ALIGN_STR "\n\t"
        "orw    #0x200,%sp@\n\t"        /* set saved ipl to 2 */
        "rte");
 
-/* Defined in entry.S; only increments 'num_spurious' */
-asmlinkage void bad_interrupt(void);
-
-extern void atari_microwire_cmd( int cmd );
+extern void atari_microwire_cmd(int cmd);
 
 extern int atari_SCC_reset_done;
 
+static int atari_startup_irq(unsigned int irq)
+{
+       m68k_irq_startup(irq);
+       atari_turnon_irq(irq);
+       atari_enable_irq(irq);
+       return 0;
+}
+
+static void atari_shutdown_irq(unsigned int irq)
+{
+       atari_disable_irq(irq);
+       atari_turnoff_irq(irq);
+       m68k_irq_shutdown(irq);
+
+       if (irq == IRQ_AUTO_4)
+           vectors[VEC_INT4] = falcon_hblhandler;
+}
+
+static struct irq_controller atari_irq_controller = {
+       .name           = "atari",
+       .lock           = SPIN_LOCK_UNLOCKED,
+       .startup        = atari_startup_irq,
+       .shutdown       = atari_shutdown_irq,
+       .enable         = atari_enable_irq,
+       .disable        = atari_disable_irq,
+};
+
 /*
  * void atari_init_IRQ (void)
  *
@@ -333,12 +359,8 @@ extern int atari_SCC_reset_done;
 
 void __init atari_init_IRQ(void)
 {
-       int i;
-
-       /* initialize the vector table */
-       for (i = 0; i < NUM_INT_SOURCES; ++i) {
-               vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt;
-       }
+       m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
+       m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
 
        /* Initialize the MFP(s) */
 
@@ -378,15 +400,16 @@ void __init atari_init_IRQ(void)
                                                                         * enabled in VME mask
                                                                         */
                tt_scu.vme_mask = 0x60;         /* enable MFP and SCC ints */
-       }
-       else {
+       } else {
                /* If no SCU and no Hades, the HSYNC interrupt needs to be
                 * disabled this way. (Else _inthandler in kernel/sys_call.S
                 * gets overruns)
                 */
 
-               if (!MACH_IS_HADES)
+               if (!MACH_IS_HADES) {
                        vectors[VEC_INT2] = falcon_hblhandler;
+                       vectors[VEC_INT4] = falcon_hblhandler;
+               }
        }
 
        if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
@@ -395,7 +418,7 @@ void __init atari_init_IRQ(void)
                   be in an atasound_init(), that doesn't exist yet. */
                atari_microwire_cmd(MW_LM1992_PSG_HIGH);
        }
-       
+
        stdma_init();
 
        /* Initialize the PSG: all sounds off, both ports output */
@@ -404,184 +427,6 @@ void __init atari_init_IRQ(void)
 }
 
 
-static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
-{
-       irq_node_t *node;
-
-       for (node = (irq_node_t *)dev_id; node; node = node->next)
-               node->handler(irq, node->dev_id, fp);
-       return IRQ_HANDLED;
-}
-
-
-/*
- * 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_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                      unsigned long flags, const char *devname, void *dev_id)
-{
-       int vector;
-       unsigned long oflags = flags;
-
-       /*
-        * The following is a hack to make some PCI card drivers work,
-        * which set the SA_SHIRQ flag.
-        */
-
-       flags &= ~SA_SHIRQ;
-
-       if (flags == SA_INTERRUPT) {
-               printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n",
-                       __FUNCTION__, devname);
-               flags = IRQ_TYPE_SLOW;
-       }
-       if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
-               printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n",
-                       __FUNCTION__, flags, oflags, 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(irq);
-
-       /*
-        * Check type/source combination: slow ints are (currently)
-        * only possible for MFP-interrupts.
-        */
-       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[irq].handler = handler;
-               irq_handler[irq].dev_id  = dev_id;
-               irq_param[irq].flags   = flags;
-               irq_param[irq].devname = devname;
-               vectors[vector] =
-                       (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(irq);
-               atari_enable_irq(irq);
-
-               return 0;
-       }
-       else if (irq_param[irq].flags == flags) {
-               /* old handler is of same type -> handlers can be chained */
-               irq_node_t *node;
-               unsigned long flags;
-
-               local_irq_save(flags);
-
-               if (irq_handler[irq].handler != atari_call_irq_list) {
-                       /* Only one handler yet, make a node for this first one */
-                       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";
-               }
-
-               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 */
-               node->next = irq_handler[irq].dev_id;
-               irq_handler[irq].dev_id = node;
-
-               local_irq_restore(flags);
-               return 0;
-       } else {
-               printk ("%s: Irq %d allocated by other type int (call from %s)\n",
-                       __FUNCTION__, irq, devname);
-               return -EBUSY;
-       }
-}
-
-void atari_free_irq(unsigned int irq, void *dev_id)
-{
-       unsigned long flags;
-       int vector;
-       irq_node_t **list, *node;
-
-       if (!IS_VALID_INTNO(irq)) {
-               printk("%s: Unknown irq %d\n", __FUNCTION__, irq);
-               return;
-       }
-
-       vector = IRQ_SOURCE_TO_VECTOR(irq);
-       if (vectors[vector] == bad_interrupt)
-               goto not_found;
-
-       local_irq_save(flags);
-
-       if (irq_handler[irq].handler != atari_call_irq_list) {
-               /* It's the only handler for the interrupt */
-               if (irq_handler[irq].dev_id != dev_id) {
-                       local_irq_restore(flags);
-                       goto not_found;
-               }
-               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(irq);
-               atari_turnoff_irq(irq);
-
-               local_irq_restore(flags);
-               return;
-       }
-
-       /* 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 (!*list) {
-               local_irq_restore(flags);
-               goto not_found;
-       }
-
-       (*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_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 */
-       }
-
-       local_irq_restore(flags);
-       return;
-
-not_found:
-       printk("%s: tried to remove invalid irq\n", __FUNCTION__);
-       return;
-}
-
-
 /*
  * atari_register_vme_int() returns the number of a free interrupt vector for
  * hardware with a programmable int vector (probably a VME board).
@@ -591,58 +436,24 @@ unsigned long atari_register_vme_int(void)
 {
        int i;
 
-       for(i = 0; i < 32; i++)
-               if((free_vme_vec_bitmap & (1 << i)) == 0)
+       for (i = 0; i < 32; i++)
+               if ((free_vme_vec_bitmap & (1 << i)) == 0)
                        break;
-       
-       if(i == 16)
+
+       if (i == 16)
                return 0;
 
        free_vme_vec_bitmap |= 1 << i;
-       return (VME_SOURCE_BASE + i);
+       return VME_SOURCE_BASE + i;
 }
 
 
 void atari_unregister_vme_int(unsigned long irq)
 {
-       if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
+       if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
                irq -= VME_SOURCE_BASE;
                free_vme_vec_bitmap &= ~(1 << irq);
        }
 }
 
 
-int show_atari_interrupts(struct seq_file *p, void *v)
-{
-       int i;
-
-       for (i = 0; i < NUM_INT_SOURCES; ++i) {
-               if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
-                       continue;
-               if (i < STMFP_SOURCE_BASE)
-                       seq_printf(p, "auto %2d: %10u ",
-                                      i, kstat_cpu(0).irqs[i]);
-               else
-                       seq_printf(p, "vec $%02x: %10u ",
-                                      IRQ_SOURCE_TO_VECTOR(i),
-                                      kstat_cpu(0).irqs[i]);
-
-               if (irq_handler[i].handler != atari_call_irq_list) {
-                       seq_printf(p, "%s\n", irq_param[i].devname);
-               }
-               else {
-                       irq_node_t *n;
-                       for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) {
-                               seq_printf(p, "%s\n", n->devname);
-                               if (n->next)
-                                       seq_puts(p, "                    " );
-                       }
-               }
-       }
-       if (num_spurious)
-               seq_printf(p, "spurio.: %10u\n", num_spurious);
-       
-       return 0;
-}
-
-