m68k: Kill several external declarations in source files
[linux-3.10.git] / arch / m68k / mac / via.c
index 0c1cc45..dfffb9c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     6522 Versatile Interface Adapter (VIA)
  *
- *     There are two of these on the Mac II. Some IRQ's are vectored
+ *     There are two of these on the Mac II. Some IRQs are vectored
  *     via them as are assorted bits and bobs - eg RTC, ADB.
  *
  * CSA: Motorola seems to have removed documentation on the 6522 from
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/ide.h>
+#include <linux/module.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
-#include <asm/machw.h>
 #include <asm/mac_via.h>
 #include <asm/mac_psc.h>
+#include <asm/mac_oss.h>
 
 volatile __u8 *via1, *via2;
-#if 0
-/* See note in mac_via.h about how this is possibly not useful */
-volatile long *via_memory_bogon=(long *)&via_memory_bogon;
-#endif
-int rbv_present, via_alt_mapping;
-__u8 rbv_clear;
+int rbv_present;
+int via_alt_mapping;
+EXPORT_SYMBOL(via_alt_mapping);
+static __u8 rbv_clear;
 
 /*
  * Globals for accessing the VIA chip registers without having to
@@ -64,7 +62,19 @@ static int gIER,gIFR,gBufA,gBufB;
 #define MAC_CLOCK_LOW          (MAC_CLOCK_TICK&0xFF)
 #define MAC_CLOCK_HIGH         (MAC_CLOCK_TICK>>8)
 
-static int  nubus_active;
+/* To disable a NuBus slot on Quadras we make that slot IRQ line an output set
+ * high. On RBV we just use the slot interrupt enable register. On Macs with
+ * genuine VIA chips we must use nubus_disabled to keep track of disabled slot
+ * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1
+ * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt.
+ * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble,
+ * because closing one of those drivers can mask all of the NuBus interrupts.
+ * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's
+ * possible to get interrupts from cards that MacOS or the ROM has configured
+ * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and
+ * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS.
+ */
+static u8 nubus_disabled;
 
 void via_debug_dump(void);
 irqreturn_t via1_irq(int, void *);
@@ -75,7 +85,6 @@ void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
 extern irqreturn_t mac_scc_dispatch(int, void *);
-extern int oss_present;
 
 /*
  * Initialize the VIAs
@@ -166,7 +175,7 @@ void __init via_init(void)
        via1[vT1CH] = 0;
        via1[vT2CL] = 0;
        via1[vT2CH] = 0;
-       via1[vACR] &= 0x3F;
+       via1[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
        via1[vACR] &= ~0x03; /* disable port A & B latches */
 
        /*
@@ -189,40 +198,41 @@ void __init via_init(void)
 
        /* Everything below this point is VIA2/RBV only... */
 
-       if (oss_present) return;
+       if (oss_present)
+               return;
 
-#if 1
        /* Some machines support an alternate IRQ mapping that spreads  */
        /* Ethernet and Sound out to their own autolevel IRQs and moves */
        /* VIA1 to level 6. A/UX uses this mapping and we do too.  Note */
        /* that the IIfx emulates this alternate mapping using the OSS. */
 
-       switch(macintosh_config->ident) {
-               case MAC_MODEL_P475:
-               case MAC_MODEL_P475F:
-               case MAC_MODEL_P575:
-               case MAC_MODEL_Q605:
-               case MAC_MODEL_Q605_ACC:
-               case MAC_MODEL_C610:
-               case MAC_MODEL_Q610:
-               case MAC_MODEL_Q630:
-               case MAC_MODEL_C650:
-               case MAC_MODEL_Q650:
-               case MAC_MODEL_Q700:
-               case MAC_MODEL_Q800:
-               case MAC_MODEL_Q900:
-               case MAC_MODEL_Q950:
+       via_alt_mapping = 0;
+       if (macintosh_config->via_type == MAC_VIA_QUADRA)
+               switch (macintosh_config->ident) {
+               case MAC_MODEL_C660:
+               case MAC_MODEL_Q840:
+                       /* not applicable */
+                       break;
+               case MAC_MODEL_P588:
+               case MAC_MODEL_TV:
+               case MAC_MODEL_PB140:
+               case MAC_MODEL_PB145:
+               case MAC_MODEL_PB160:
+               case MAC_MODEL_PB165:
+               case MAC_MODEL_PB165C:
+               case MAC_MODEL_PB170:
+               case MAC_MODEL_PB180:
+               case MAC_MODEL_PB180C:
+               case MAC_MODEL_PB190:
+               case MAC_MODEL_PB520:
+                       /* not yet tested */
+                       break;
+               default:
                        via_alt_mapping = 1;
                        via1[vDirB] |= 0x40;
                        via1[vBufB] &= ~0x40;
                        break;
-               default:
-                       via_alt_mapping = 0;
-                       break;
-       }
-#else
-       via_alt_mapping = 0;
-#endif
+               }
 
        /*
         * Now initialize VIA2. For RBV we just kill all interrupts;
@@ -238,14 +248,17 @@ void __init via_init(void)
                via2[vT1CH] = 0;
                via2[vT2CL] = 0;
                via2[vT2CH] = 0;
-               via2[vACR] &= 0x3F;
+               via2[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
                via2[vACR] &= ~0x03; /* disable port A & B latches */
        }
 
        /*
-        * Set vPCR for SCSI interrupts (but not on RBV)
+        * Set vPCR for control line interrupts (but not on RBV)
         */
        if (!rbv_present) {
+               /* For all VIA types, CA1 (SLOTS IRQ) and CB1 (ASC IRQ)
+                * are made negative edge triggered here.
+                */
                if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
                        /* CB2 (IRQ) indep. input, positive edge */
                        /* CA2 (DRQ) indep. input, positive edge */
@@ -383,9 +396,6 @@ int via_get_cache_disable(void)
 
 void __init via_nubus_init(void)
 {
-       /* don't set nubus_active = 0 here, it kills the Baboon */
-       /* interrupt that we've already registered.             */
-
        /* unlock nubus transactions */
 
        if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
@@ -399,39 +409,41 @@ void __init via_nubus_init(void)
                via2[gBufB] |= 0x02;
        }
 
-       /* disable nubus slot interrupts. */
-       if (rbv_present) {
+       /* Disable all the slot interrupts (where possible). */
+
+       switch (macintosh_config->via_type) {
+       case MAC_VIA_II:
+               /* Just make the port A lines inputs. */
+               switch(macintosh_config->ident) {
+               case MAC_MODEL_II:
+               case MAC_MODEL_IIX:
+               case MAC_MODEL_IICX:
+               case MAC_MODEL_SE30:
+                       /* The top two bits are RAM size outputs. */
+                       via2[vDirA] &= 0xC0;
+                       break;
+               default:
+                       via2[vDirA] &= 0x80;
+               }
+               break;
+       case MAC_VIA_IIci:
+               /* RBV. Disable all the slot interrupts. SIER works like IER. */
                via2[rSIER] = 0x7F;
-               via2[rSIER] = nubus_active | 0x80;
-       } else {
-               /* These are ADB bits on PMU */
+               break;
+       case MAC_VIA_QUADRA:
+               /* Disable the inactive slot interrupts by making those lines outputs. */
                if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                  (macintosh_config->adb_type != MAC_ADB_PB2)) {
-                       switch(macintosh_config->ident)
-                       {
-                               case MAC_MODEL_II:
-                               case MAC_MODEL_IIX:
-                               case MAC_MODEL_IICX:
-                               case MAC_MODEL_SE30:
-                                       via2[vBufA] |= 0x3F;
-                                       via2[vDirA] = ~nubus_active | 0xc0;
-                                       break;
-                               default:
-                                       via2[vBufA] = 0xFF;
-                                       via2[vDirA] = ~nubus_active;
-                       }
+                   (macintosh_config->adb_type != MAC_ADB_PB2)) {
+                       via2[vBufA] |= 0x7F;
+                       via2[vDirA] |= 0x7F;
                }
+               break;
        }
 }
 
 /*
  * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
  * via6522.c :-), disable/pending masks added.
- *
- * The new interrupt architecture in macints.c takes care of a lot of the
- * gruntwork for us, including tallying the interrupts and calling the
- * handlers on the linked list. All we need to do here is basically generate
- * the machspec interrupt number after clearing the interrupt.
  */
 
 irqreturn_t via1_irq(int irq, void *dev_id)
@@ -447,29 +459,12 @@ irqreturn_t via1_irq(int irq, void *dev_id)
        irq_bit = 1;
        do {
                if (events & irq_bit) {
-                       via1[vIER] = irq_bit;
                        via1[vIFR] = irq_bit;
                        m68k_handle_int(irq_num);
-                       via1[vIER] = irq_bit | 0x80;
                }
                ++irq_num;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-
-#if 0 /* freakin' pmu is doing weird stuff */
-       if (!oss_present) {
-               /* This (still) seems to be necessary to get IDE
-                  working.  However, if you enable VBL interrupts,
-                  you're screwed... */
-               /* FIXME: should we check the SLOTIRQ bit before
-                   pulling this stunt? */
-               /* No, it won't be set. that's why we're doing this. */
-               via_irq_disable(IRQ_MAC_NUBUS);
-               via_irq_clear(IRQ_MAC_NUBUS);
-               m68k_handle_int(IRQ_MAC_NUBUS);
-               via_irq_enable(IRQ_MAC_NUBUS);
-       }
-#endif
        return IRQ_HANDLED;
 }
 
@@ -486,10 +481,8 @@ irqreturn_t via2_irq(int irq, void *dev_id)
        irq_bit = 1;
        do {
                if (events & irq_bit) {
-                       via2[gIER] = irq_bit;
                        via2[gIFR] = irq_bit | rbv_clear;
                        m68k_handle_int(irq_num);
-                       via2[gIER] = irq_bit | 0x80;
                }
                ++irq_num;
                irq_bit <<= 1;
@@ -511,7 +504,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
        if (rbv_present)
                events &= via2[rSIER];
        else
-               events &= nubus_active;
+               events &= ~via2[vDirA];
        if (!events)
                return IRQ_NONE;
 
@@ -533,7 +526,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
                if (rbv_present)
                        events &= via2[rSIER];
                else
-                       events &= nubus_active;
+                       events &= ~via2[vDirA];
        } while (events);
        return IRQ_HANDLED;
 }
@@ -541,38 +534,38 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
 void via_irq_enable(int irq) {
        int irq_src     = IRQ_SRC(irq);
        int irq_idx     = IRQ_IDX(irq);
-       int irq_bit     = 1 << irq_idx;
 
 #ifdef DEBUG_IRQUSE
        printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
 #endif
 
        if (irq_src == 1) {
-               via1[vIER] = irq_bit | 0x80;
+               via1[vIER] = IER_SET_BIT(irq_idx);
        } else if (irq_src == 2) {
-               via2[gIER] = irq_bit | 0x80;
+               if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0)
+                       via2[gIER] = IER_SET_BIT(irq_idx);
        } else if (irq_src == 7) {
-               nubus_active |= irq_bit;
-               if (rbv_present) {
-                       /* enable the slot interrupt. SIER works like IER. */
+               switch (macintosh_config->via_type) {
+               case MAC_VIA_II:
+                       nubus_disabled &= ~(1 << irq_idx);
+                       /* Enable the CA1 interrupt when no slot is disabled. */
+                       if (!nubus_disabled)
+                               via2[gIER] = IER_SET_BIT(1);
+                       break;
+               case MAC_VIA_IIci:
+                       /* On RBV, enable the slot interrupt.
+                        * SIER works like IER.
+                        */
                        via2[rSIER] = IER_SET_BIT(irq_idx);
-               } else {
-                       /* Make sure the bit is an input, to enable the irq */
-                       /* But not on PowerBooks, that's ADB... */
+                       break;
+               case MAC_VIA_QUADRA:
+                       /* Make the port A line an input to enable the slot irq.
+                        * But not on PowerBooks, that's ADB.
+                        */
                        if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                          (macintosh_config->adb_type != MAC_ADB_PB2)) {
-                               switch(macintosh_config->ident)
-                               {
-                                       case MAC_MODEL_II:
-                                       case MAC_MODEL_IIX:
-                                       case MAC_MODEL_IICX:
-                                       case MAC_MODEL_SE30:
-                                               via2[vDirA] &= (~irq_bit | 0xc0);
-                                               break;
-                                       default:
-                                               via2[vDirA] &= ~irq_bit;
-                               }
-                       }
+                           (macintosh_config->adb_type != MAC_ADB_PB2))
+                               via2[vDirA] &= ~(1 << irq_idx);
+                       break;
                }
        }
 }
@@ -580,29 +573,31 @@ void via_irq_enable(int irq) {
 void via_irq_disable(int irq) {
        int irq_src     = IRQ_SRC(irq);
        int irq_idx     = IRQ_IDX(irq);
-       int irq_bit     = 1 << irq_idx;
 
 #ifdef DEBUG_IRQUSE
        printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
 #endif
 
        if (irq_src == 1) {
-               via1[vIER] = irq_bit & 0x7F;
+               via1[vIER] = IER_CLR_BIT(irq_idx);
        } else if (irq_src == 2) {
-               via2[gIER] = irq_bit & 0x7F;
+               via2[gIER] = IER_CLR_BIT(irq_idx);
        } else if (irq_src == 7) {
-               if (rbv_present) {
-                       /* disable the slot interrupt.  SIER works like IER. */
+               switch (macintosh_config->via_type) {
+               case MAC_VIA_II:
+                       nubus_disabled |= 1 << irq_idx;
+                       if (nubus_disabled)
+                               via2[gIER] = IER_CLR_BIT(1);
+                       break;
+               case MAC_VIA_IIci:
                        via2[rSIER] = IER_CLR_BIT(irq_idx);
-               } else {
-                       /* disable the nubus irq by changing dir to output */
-                       /* except on PMU */
+                       break;
+               case MAC_VIA_QUADRA:
                        if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                          (macintosh_config->adb_type != MAC_ADB_PB2)) {
-                               via2[vDirA] |= irq_bit;
-                       }
+                           (macintosh_config->adb_type != MAC_ADB_PB2))
+                               via2[vDirA] |= 1 << irq_idx;
+                       break;
                }
-               nubus_active &= ~irq_bit;
        }
 }
 
@@ -638,7 +633,7 @@ int via_irq_pending(int irq)
        } else if (irq_src == 2) {
                return via2[gIFR] & irq_bit;
        } else if (irq_src == 7) {
-               /* FIXME: this can't work while a slot irq is disabled! */
+               /* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */
                return ~via2[gBufA] & irq_bit;
        }
        return 0;