aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2011-10-23 10:11:17 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2011-12-10 13:52:47 -0500
commitc4af5da7f24ff1bf60db2d6ff3e9d9bd912ca47a (patch)
tree2f653a61672f5720e436411526ab6339838fb3bc /arch/m68k/mac
parent8d9f014ad16711d79c8a575f2d3d009d2a16c7b7 (diff)
m68k/mac: fix nubus slot irq disable and shutdown
Improve NuBus slot interrupt handling code and documentation. This patch fixes the NuBus NIC (mac8390) in my Quadra 700. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k/mac')
-rw-r--r--arch/m68k/mac/macints.c27
-rw-r--r--arch/m68k/mac/via.c123
2 files changed, 108 insertions, 42 deletions
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 41dd164aac27..74f5a97c9860 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -151,10 +151,15 @@ irqreturn_t mac_debug_handler(int, void *);
151 151
152/* #define DEBUG_MACINTS */ 152/* #define DEBUG_MACINTS */
153 153
154static unsigned int mac_irq_startup(struct irq_data *);
155static void mac_irq_shutdown(struct irq_data *);
156
154static struct irq_chip mac_irq_chip = { 157static struct irq_chip mac_irq_chip = {
155 .name = "mac", 158 .name = "mac",
156 .irq_enable = mac_irq_enable, 159 .irq_enable = mac_irq_enable,
157 .irq_disable = mac_irq_disable, 160 .irq_disable = mac_irq_disable,
161 .irq_startup = mac_irq_startup,
162 .irq_shutdown = mac_irq_shutdown,
158}; 163};
159 164
160void __init mac_init_IRQ(void) 165void __init mac_init_IRQ(void)
@@ -274,6 +279,28 @@ void mac_irq_disable(struct irq_data *data)
274 } 279 }
275} 280}
276 281
282static unsigned int mac_irq_startup(struct irq_data *data)
283{
284 int irq = data->irq;
285
286 if (IRQ_SRC(irq) == 7 && !oss_present)
287 via_nubus_irq_startup(irq);
288 else
289 mac_irq_enable(data);
290
291 return 0;
292}
293
294static void mac_irq_shutdown(struct irq_data *data)
295{
296 int irq = data->irq;
297
298 if (IRQ_SRC(irq) == 7 && !oss_present)
299 via_nubus_irq_shutdown(irq);
300 else
301 mac_irq_disable(data);
302}
303
277static int num_debug[8]; 304static int num_debug[8];
278 305
279irqreturn_t mac_debug_handler(int irq, void *dev_id) 306irqreturn_t mac_debug_handler(int irq, void *dev_id)
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 642b44615f78..97996a48b048 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -63,18 +63,47 @@ static int gIER,gIFR,gBufA,gBufB;
63#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) 63#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
64#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) 64#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
65 65
66/* To disable a NuBus slot on Quadras we make that slot IRQ line an output set 66
67 * high. On RBV we just use the slot interrupt enable register. On Macs with 67/*
68 * genuine VIA chips we must use nubus_disabled to keep track of disabled slot 68 * On Macs with a genuine VIA chip there is no way to mask an individual slot
69 * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1 69 * interrupt. This limitation also seems to apply to VIA clone logic cores in
70 * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt. 70 * Quadra-like ASICs. (RBV and OSS machines don't have this limitation.)
71 * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble, 71 *
72 * because closing one of those drivers can mask all of the NuBus interrupts. 72 * We used to fake it by configuring the relevent VIA pin as an output
73 * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's 73 * (to mask the interrupt) or input (to unmask). That scheme did not work on
74 * possible to get interrupts from cards that MacOS or the ROM has configured 74 * (at least) the Quadra 700. A NuBus card's /NMRQ signal is an open-collector
75 * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and 75 * circuit (see Designing Cards and Drivers for Macintosh II and Macintosh SE,
76 * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS. 76 * p. 10-11 etc) but VIA outputs are not (see datasheet).
77 *
78 * Driving these outputs high must cause the VIA to source current and the
79 * card to sink current when it asserts /NMRQ. Current will flow but the pin
80 * voltage is uncertain and so the /NMRQ condition may still cause a transition
81 * at the VIA2 CA1 input (which explains the lost interrupts). A side effect
82 * is that a disabled slot IRQ can never be tested as pending or not.
83 *
84 * Driving these outputs low doesn't work either. All the slot /NMRQ lines are
85 * (active low) OR'd together to generate the CA1 (aka "SLOTS") interrupt (see
86 * The Guide To Macintosh Family Hardware, 2nd edition p. 167). If we drive a
87 * disabled /NMRQ line low, the falling edge immediately triggers a CA1
88 * interrupt and all slot interrupts after that will generate no transition
89 * and therefore no interrupt, even after being re-enabled.
90 *
91 * So we make the VIA port A I/O lines inputs and use nubus_disabled to keep
92 * track of their states. When any slot IRQ becomes disabled we mask the CA1
93 * umbrella interrupt. Only when all slot IRQs become enabled do we unmask
94 * the CA1 interrupt. It must remain enabled even when cards have no interrupt
95 * handler registered. Drivers must therefore disable a slot interrupt at the
96 * device before they call free_irq (like shared and autovector interrupts).
97 *
98 * There is also a related problem when MacOS is used to boot Linux. A network
99 * card brought up by a MacOS driver may raise an interrupt while Linux boots.
100 * This can be fatal since it can't be handled until the right driver loads
101 * (if such a driver exists at all). Apparently related to this hardware
102 * limitation, "Designing Cards and Drivers", p. 9-8, says that a slot
103 * interrupt with no driver would crash MacOS (the book was written before
104 * the appearance of Macs with RBV or OSS).
77 */ 105 */
106
78static u8 nubus_disabled; 107static u8 nubus_disabled;
79 108
80void via_debug_dump(void); 109void via_debug_dump(void);
@@ -354,34 +383,55 @@ void __init via_nubus_init(void)
354 via2[gBufB] |= 0x02; 383 via2[gBufB] |= 0x02;
355 } 384 }
356 385
357 /* Disable all the slot interrupts (where possible). */ 386 /*
387 * Disable the slot interrupts. On some hardware that's not possible.
388 * On some hardware it's unclear what all of these I/O lines do.
389 */
358 390
359 switch (macintosh_config->via_type) { 391 switch (macintosh_config->via_type) {
360 case MAC_VIA_II: 392 case MAC_VIA_II:
361 /* Just make the port A lines inputs. */ 393 case MAC_VIA_QUADRA:
362 switch(macintosh_config->ident) { 394 pr_debug("VIA2 vDirA is 0x%02X\n", via2[vDirA]);
363 case MAC_MODEL_II:
364 case MAC_MODEL_IIX:
365 case MAC_MODEL_IICX:
366 case MAC_MODEL_SE30:
367 /* The top two bits are RAM size outputs. */
368 via2[vDirA] &= 0xC0;
369 break;
370 default:
371 via2[vDirA] &= 0x80;
372 }
373 break; 395 break;
374 case MAC_VIA_IIci: 396 case MAC_VIA_IIci:
375 /* RBV. Disable all the slot interrupts. SIER works like IER. */ 397 /* RBV. Disable all the slot interrupts. SIER works like IER. */
376 via2[rSIER] = 0x7F; 398 via2[rSIER] = 0x7F;
377 break; 399 break;
400 }
401}
402
403void via_nubus_irq_startup(int irq)
404{
405 int irq_idx = IRQ_IDX(irq);
406
407 switch (macintosh_config->via_type) {
408 case MAC_VIA_II:
378 case MAC_VIA_QUADRA: 409 case MAC_VIA_QUADRA:
379 /* Disable the inactive slot interrupts by making those lines outputs. */ 410 /* Make the port A line an input. Probably redundant. */
380 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 411 if (macintosh_config->via_type == MAC_VIA_II) {
381 (macintosh_config->adb_type != MAC_ADB_PB2)) { 412 /* The top two bits are RAM size outputs. */
382 via2[vBufA] |= 0x7F; 413 via2[vDirA] &= 0xC0 | ~(1 << irq_idx);
383 via2[vDirA] |= 0x7F; 414 } else {
415 /* Allow NuBus slots 9 through F. */
416 via2[vDirA] &= 0x80 | ~(1 << irq_idx);
384 } 417 }
418 /* fall through */
419 case MAC_VIA_IIci:
420 via_irq_enable(irq);
421 break;
422 }
423}
424
425void via_nubus_irq_shutdown(int irq)
426{
427 switch (macintosh_config->via_type) {
428 case MAC_VIA_II:
429 case MAC_VIA_QUADRA:
430 /* Ensure that the umbrella CA1 interrupt remains enabled. */
431 via_irq_enable(irq);
432 break;
433 case MAC_VIA_IIci:
434 via_irq_disable(irq);
385 break; 435 break;
386 } 436 }
387} 437}
@@ -507,6 +557,7 @@ void via_irq_enable(int irq) {
507 } else if (irq_src == 7) { 557 } else if (irq_src == 7) {
508 switch (macintosh_config->via_type) { 558 switch (macintosh_config->via_type) {
509 case MAC_VIA_II: 559 case MAC_VIA_II:
560 case MAC_VIA_QUADRA:
510 nubus_disabled &= ~(1 << irq_idx); 561 nubus_disabled &= ~(1 << irq_idx);
511 /* Enable the CA1 interrupt when no slot is disabled. */ 562 /* Enable the CA1 interrupt when no slot is disabled. */
512 if (!nubus_disabled) 563 if (!nubus_disabled)
@@ -518,14 +569,6 @@ void via_irq_enable(int irq) {
518 */ 569 */
519 via2[rSIER] = IER_SET_BIT(irq_idx); 570 via2[rSIER] = IER_SET_BIT(irq_idx);
520 break; 571 break;
521 case MAC_VIA_QUADRA:
522 /* Make the port A line an input to enable the slot irq.
523 * But not on PowerBooks, that's ADB.
524 */
525 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
526 (macintosh_config->adb_type != MAC_ADB_PB2))
527 via2[vDirA] &= ~(1 << irq_idx);
528 break;
529 } 572 }
530 } 573 }
531} 574}
@@ -545,6 +588,7 @@ void via_irq_disable(int irq) {
545 } else if (irq_src == 7) { 588 } else if (irq_src == 7) {
546 switch (macintosh_config->via_type) { 589 switch (macintosh_config->via_type) {
547 case MAC_VIA_II: 590 case MAC_VIA_II:
591 case MAC_VIA_QUADRA:
548 nubus_disabled |= 1 << irq_idx; 592 nubus_disabled |= 1 << irq_idx;
549 if (nubus_disabled) 593 if (nubus_disabled)
550 via2[gIER] = IER_CLR_BIT(1); 594 via2[gIER] = IER_CLR_BIT(1);
@@ -552,11 +596,6 @@ void via_irq_disable(int irq) {
552 case MAC_VIA_IIci: 596 case MAC_VIA_IIci:
553 via2[rSIER] = IER_CLR_BIT(irq_idx); 597 via2[rSIER] = IER_CLR_BIT(irq_idx);
554 break; 598 break;
555 case MAC_VIA_QUADRA:
556 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
557 (macintosh_config->adb_type != MAC_ADB_PB2))
558 via2[vDirA] |= 1 << irq_idx;
559 break;
560 } 599 }
561 } 600 }
562} 601}