|
@@ -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;
|