diff options
| -rw-r--r-- | arch/m68k/include/asm/mac_via.h | 2 | ||||
| -rw-r--r-- | arch/m68k/mac/macints.c | 27 | ||||
| -rw-r--r-- | arch/m68k/mac/via.c | 123 |
3 files changed, 110 insertions, 42 deletions
diff --git a/arch/m68k/include/asm/mac_via.h b/arch/m68k/include/asm/mac_via.h index 53e831c4097e..aeeedf8b2d25 100644 --- a/arch/m68k/include/asm/mac_via.h +++ b/arch/m68k/include/asm/mac_via.h | |||
| @@ -257,6 +257,8 @@ extern int rbv_present,via_alt_mapping; | |||
| 257 | extern void via_register_interrupts(void); | 257 | extern void via_register_interrupts(void); |
| 258 | extern void via_irq_enable(int); | 258 | extern void via_irq_enable(int); |
| 259 | extern void via_irq_disable(int); | 259 | extern void via_irq_disable(int); |
| 260 | extern void via_nubus_irq_startup(int irq); | ||
| 261 | extern void via_nubus_irq_shutdown(int irq); | ||
| 260 | extern void via1_irq(unsigned int irq, struct irq_desc *desc); | 262 | extern void via1_irq(unsigned int irq, struct irq_desc *desc); |
| 261 | extern void via1_set_head(int); | 263 | extern void via1_set_head(int); |
| 262 | extern int via2_scsi_drq_pending(void); | 264 | extern int via2_scsi_drq_pending(void); |
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 | ||
| 154 | static unsigned int mac_irq_startup(struct irq_data *); | ||
| 155 | static void mac_irq_shutdown(struct irq_data *); | ||
| 156 | |||
| 154 | static struct irq_chip mac_irq_chip = { | 157 | static 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 | ||
| 160 | void __init mac_init_IRQ(void) | 165 | void __init mac_init_IRQ(void) |
| @@ -274,6 +279,28 @@ void mac_irq_disable(struct irq_data *data) | |||
| 274 | } | 279 | } |
| 275 | } | 280 | } |
| 276 | 281 | ||
| 282 | static 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 | |||
| 294 | static 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 | |||
| 277 | static int num_debug[8]; | 304 | static int num_debug[8]; |
| 278 | 305 | ||
| 279 | irqreturn_t mac_debug_handler(int irq, void *dev_id) | 306 | irqreturn_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 | |||
| 78 | static u8 nubus_disabled; | 107 | static u8 nubus_disabled; |
| 79 | 108 | ||
| 80 | void via_debug_dump(void); | 109 | void 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 | |||
| 403 | void 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 | |||
| 425 | void 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 | } |
