summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/m68k/mac/via.c141
1 files changed, 80 insertions, 61 deletions
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 0c1cc45..83a3bb0 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -64,7 +64,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 the slot IRQ lines outputs, 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 *);
@@ -383,9 +395,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,28 +408,35 @@ 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;
}
}
@@ -489,7 +505,8 @@ irqreturn_t via2_irq(int irq, void *dev_id)
via2[gIER] = irq_bit;
via2[gIFR] = irq_bit | rbv_clear;
m68k_handle_int(irq_num);
- via2[gIER] = irq_bit | 0x80;
+ if (irq_num != IRQ_MAC_NUBUS || nubus_disabled == 0)
+ via2[gIER] = irq_bit | 0x80;
}
++irq_num;
irq_bit <<= 1;
@@ -511,7 +528,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 +550,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 +558,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 +597,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 +657,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;
OpenPOWER on IntegriCloud