diff options
| -rw-r--r-- | arch/m68k/mac/via.c | 141 |
1 files changed, 80 insertions, 61 deletions
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 0c1cc45c570d..83a3bb0c0325 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c | |||
| @@ -64,7 +64,19 @@ static int gIER,gIFR,gBufA,gBufB; | |||
| 64 | #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) | 64 | #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) |
| 65 | #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) | 65 | #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) |
| 66 | 66 | ||
| 67 | static int nubus_active; | 67 | /* To disable a NuBus slot on Quadras we make the slot IRQ lines outputs, set |
| 68 | * high. On RBV we just use the slot interrupt enable register. On Macs with | ||
| 69 | * genuine VIA chips we must use nubus_disabled to keep track of disabled slot | ||
| 70 | * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1 | ||
| 71 | * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt. | ||
| 72 | * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble, | ||
| 73 | * because closing one of those drivers can mask all of the NuBus interrupts. | ||
| 74 | * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's | ||
| 75 | * possible to get interrupts from cards that MacOS or the ROM has configured | ||
| 76 | * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and | ||
| 77 | * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS. | ||
| 78 | */ | ||
| 79 | static u8 nubus_disabled; | ||
| 68 | 80 | ||
| 69 | void via_debug_dump(void); | 81 | void via_debug_dump(void); |
| 70 | irqreturn_t via1_irq(int, void *); | 82 | irqreturn_t via1_irq(int, void *); |
| @@ -383,9 +395,6 @@ int via_get_cache_disable(void) | |||
| 383 | 395 | ||
| 384 | void __init via_nubus_init(void) | 396 | void __init via_nubus_init(void) |
| 385 | { | 397 | { |
| 386 | /* don't set nubus_active = 0 here, it kills the Baboon */ | ||
| 387 | /* interrupt that we've already registered. */ | ||
| 388 | |||
| 389 | /* unlock nubus transactions */ | 398 | /* unlock nubus transactions */ |
| 390 | 399 | ||
| 391 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && | 400 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && |
| @@ -399,28 +408,35 @@ void __init via_nubus_init(void) | |||
| 399 | via2[gBufB] |= 0x02; | 408 | via2[gBufB] |= 0x02; |
| 400 | } | 409 | } |
| 401 | 410 | ||
| 402 | /* disable nubus slot interrupts. */ | 411 | /* Disable all the slot interrupts (where possible). */ |
| 403 | if (rbv_present) { | 412 | |
| 413 | switch (macintosh_config->via_type) { | ||
| 414 | case MAC_VIA_II: | ||
| 415 | /* Just make the port A lines inputs. */ | ||
| 416 | switch(macintosh_config->ident) { | ||
| 417 | case MAC_MODEL_II: | ||
| 418 | case MAC_MODEL_IIX: | ||
| 419 | case MAC_MODEL_IICX: | ||
| 420 | case MAC_MODEL_SE30: | ||
| 421 | /* The top two bits are RAM size outputs. */ | ||
| 422 | via2[vDirA] &= 0xC0; | ||
| 423 | break; | ||
| 424 | default: | ||
| 425 | via2[vDirA] &= 0x80; | ||
| 426 | } | ||
| 427 | break; | ||
| 428 | case MAC_VIA_IIci: | ||
| 429 | /* RBV. Disable all the slot interrupts. SIER works like IER. */ | ||
| 404 | via2[rSIER] = 0x7F; | 430 | via2[rSIER] = 0x7F; |
| 405 | via2[rSIER] = nubus_active | 0x80; | 431 | break; |
| 406 | } else { | 432 | case MAC_VIA_QUADRA: |
| 407 | /* These are ADB bits on PMU */ | 433 | /* Disable the inactive slot interrupts by making those lines outputs. */ |
| 408 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && | 434 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && |
| 409 | (macintosh_config->adb_type != MAC_ADB_PB2)) { | 435 | (macintosh_config->adb_type != MAC_ADB_PB2)) { |
| 410 | switch(macintosh_config->ident) | 436 | via2[vBufA] |= 0x7F; |
| 411 | { | 437 | via2[vDirA] |= 0x7F; |
| 412 | case MAC_MODEL_II: | ||
| 413 | case MAC_MODEL_IIX: | ||
| 414 | case MAC_MODEL_IICX: | ||
| 415 | case MAC_MODEL_SE30: | ||
| 416 | via2[vBufA] |= 0x3F; | ||
| 417 | via2[vDirA] = ~nubus_active | 0xc0; | ||
| 418 | break; | ||
| 419 | default: | ||
| 420 | via2[vBufA] = 0xFF; | ||
| 421 | via2[vDirA] = ~nubus_active; | ||
| 422 | } | ||
| 423 | } | 438 | } |
| 439 | break; | ||
| 424 | } | 440 | } |
| 425 | } | 441 | } |
| 426 | 442 | ||
| @@ -489,7 +505,8 @@ irqreturn_t via2_irq(int irq, void *dev_id) | |||
| 489 | via2[gIER] = irq_bit; | 505 | via2[gIER] = irq_bit; |
| 490 | via2[gIFR] = irq_bit | rbv_clear; | 506 | via2[gIFR] = irq_bit | rbv_clear; |
| 491 | m68k_handle_int(irq_num); | 507 | m68k_handle_int(irq_num); |
| 492 | via2[gIER] = irq_bit | 0x80; | 508 | if (irq_num != IRQ_MAC_NUBUS || nubus_disabled == 0) |
| 509 | via2[gIER] = irq_bit | 0x80; | ||
| 493 | } | 510 | } |
| 494 | ++irq_num; | 511 | ++irq_num; |
| 495 | irq_bit <<= 1; | 512 | irq_bit <<= 1; |
| @@ -511,7 +528,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) | |||
| 511 | if (rbv_present) | 528 | if (rbv_present) |
| 512 | events &= via2[rSIER]; | 529 | events &= via2[rSIER]; |
| 513 | else | 530 | else |
| 514 | events &= nubus_active; | 531 | events &= ~via2[vDirA]; |
| 515 | if (!events) | 532 | if (!events) |
| 516 | return IRQ_NONE; | 533 | return IRQ_NONE; |
| 517 | 534 | ||
| @@ -533,7 +550,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) | |||
| 533 | if (rbv_present) | 550 | if (rbv_present) |
| 534 | events &= via2[rSIER]; | 551 | events &= via2[rSIER]; |
| 535 | else | 552 | else |
| 536 | events &= nubus_active; | 553 | events &= ~via2[vDirA]; |
| 537 | } while (events); | 554 | } while (events); |
| 538 | return IRQ_HANDLED; | 555 | return IRQ_HANDLED; |
| 539 | } | 556 | } |
| @@ -541,38 +558,38 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) | |||
| 541 | void via_irq_enable(int irq) { | 558 | void via_irq_enable(int irq) { |
| 542 | int irq_src = IRQ_SRC(irq); | 559 | int irq_src = IRQ_SRC(irq); |
| 543 | int irq_idx = IRQ_IDX(irq); | 560 | int irq_idx = IRQ_IDX(irq); |
| 544 | int irq_bit = 1 << irq_idx; | ||
| 545 | 561 | ||
| 546 | #ifdef DEBUG_IRQUSE | 562 | #ifdef DEBUG_IRQUSE |
| 547 | printk(KERN_DEBUG "via_irq_enable(%d)\n", irq); | 563 | printk(KERN_DEBUG "via_irq_enable(%d)\n", irq); |
| 548 | #endif | 564 | #endif |
| 549 | 565 | ||
| 550 | if (irq_src == 1) { | 566 | if (irq_src == 1) { |
| 551 | via1[vIER] = irq_bit | 0x80; | 567 | via1[vIER] = IER_SET_BIT(irq_idx); |
| 552 | } else if (irq_src == 2) { | 568 | } else if (irq_src == 2) { |
| 553 | via2[gIER] = irq_bit | 0x80; | 569 | if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0) |
| 570 | via2[gIER] = IER_SET_BIT(irq_idx); | ||
| 554 | } else if (irq_src == 7) { | 571 | } else if (irq_src == 7) { |
| 555 | nubus_active |= irq_bit; | 572 | switch (macintosh_config->via_type) { |
| 556 | if (rbv_present) { | 573 | case MAC_VIA_II: |
| 557 | /* enable the slot interrupt. SIER works like IER. */ | 574 | nubus_disabled &= ~(1 << irq_idx); |
| 575 | /* Enable the CA1 interrupt when no slot is disabled. */ | ||
| 576 | if (!nubus_disabled) | ||
| 577 | via2[gIER] = IER_SET_BIT(1); | ||
| 578 | break; | ||
| 579 | case MAC_VIA_IIci: | ||
| 580 | /* On RBV, enable the slot interrupt. | ||
| 581 | * SIER works like IER. | ||
| 582 | */ | ||
| 558 | via2[rSIER] = IER_SET_BIT(irq_idx); | 583 | via2[rSIER] = IER_SET_BIT(irq_idx); |
| 559 | } else { | 584 | break; |
| 560 | /* Make sure the bit is an input, to enable the irq */ | 585 | case MAC_VIA_QUADRA: |
| 561 | /* But not on PowerBooks, that's ADB... */ | 586 | /* Make the port A line an input to enable the slot irq. |
| 587 | * But not on PowerBooks, that's ADB. | ||
| 588 | */ | ||
| 562 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && | 589 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && |
| 563 | (macintosh_config->adb_type != MAC_ADB_PB2)) { | 590 | (macintosh_config->adb_type != MAC_ADB_PB2)) |
| 564 | switch(macintosh_config->ident) | 591 | via2[vDirA] &= ~(1 << irq_idx); |
| 565 | { | 592 | break; |
| 566 | case MAC_MODEL_II: | ||
| 567 | case MAC_MODEL_IIX: | ||
| 568 | case MAC_MODEL_IICX: | ||
| 569 | case MAC_MODEL_SE30: | ||
| 570 | via2[vDirA] &= (~irq_bit | 0xc0); | ||
| 571 | break; | ||
| 572 | default: | ||
| 573 | via2[vDirA] &= ~irq_bit; | ||
| 574 | } | ||
| 575 | } | ||
| 576 | } | 593 | } |
| 577 | } | 594 | } |
| 578 | } | 595 | } |
| @@ -580,29 +597,31 @@ void via_irq_enable(int irq) { | |||
| 580 | void via_irq_disable(int irq) { | 597 | void via_irq_disable(int irq) { |
| 581 | int irq_src = IRQ_SRC(irq); | 598 | int irq_src = IRQ_SRC(irq); |
| 582 | int irq_idx = IRQ_IDX(irq); | 599 | int irq_idx = IRQ_IDX(irq); |
| 583 | int irq_bit = 1 << irq_idx; | ||
| 584 | 600 | ||
| 585 | #ifdef DEBUG_IRQUSE | 601 | #ifdef DEBUG_IRQUSE |
| 586 | printk(KERN_DEBUG "via_irq_disable(%d)\n", irq); | 602 | printk(KERN_DEBUG "via_irq_disable(%d)\n", irq); |
| 587 | #endif | 603 | #endif |
| 588 | 604 | ||
| 589 | if (irq_src == 1) { | 605 | if (irq_src == 1) { |
| 590 | via1[vIER] = irq_bit & 0x7F; | 606 | via1[vIER] = IER_CLR_BIT(irq_idx); |
| 591 | } else if (irq_src == 2) { | 607 | } else if (irq_src == 2) { |
| 592 | via2[gIER] = irq_bit & 0x7F; | 608 | via2[gIER] = IER_CLR_BIT(irq_idx); |
| 593 | } else if (irq_src == 7) { | 609 | } else if (irq_src == 7) { |
| 594 | if (rbv_present) { | 610 | switch (macintosh_config->via_type) { |
| 595 | /* disable the slot interrupt. SIER works like IER. */ | 611 | case MAC_VIA_II: |
| 612 | nubus_disabled |= 1 << irq_idx; | ||
| 613 | if (nubus_disabled) | ||
| 614 | via2[gIER] = IER_CLR_BIT(1); | ||
| 615 | break; | ||
| 616 | case MAC_VIA_IIci: | ||
| 596 | via2[rSIER] = IER_CLR_BIT(irq_idx); | 617 | via2[rSIER] = IER_CLR_BIT(irq_idx); |
| 597 | } else { | 618 | break; |
| 598 | /* disable the nubus irq by changing dir to output */ | 619 | case MAC_VIA_QUADRA: |
| 599 | /* except on PMU */ | ||
| 600 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && | 620 | if ((macintosh_config->adb_type != MAC_ADB_PB1) && |
| 601 | (macintosh_config->adb_type != MAC_ADB_PB2)) { | 621 | (macintosh_config->adb_type != MAC_ADB_PB2)) |
| 602 | via2[vDirA] |= irq_bit; | 622 | via2[vDirA] |= 1 << irq_idx; |
| 603 | } | 623 | break; |
| 604 | } | 624 | } |
| 605 | nubus_active &= ~irq_bit; | ||
| 606 | } | 625 | } |
| 607 | } | 626 | } |
| 608 | 627 | ||
| @@ -638,7 +657,7 @@ int via_irq_pending(int irq) | |||
| 638 | } else if (irq_src == 2) { | 657 | } else if (irq_src == 2) { |
| 639 | return via2[gIFR] & irq_bit; | 658 | return via2[gIFR] & irq_bit; |
| 640 | } else if (irq_src == 7) { | 659 | } else if (irq_src == 7) { |
| 641 | /* FIXME: this can't work while a slot irq is disabled! */ | 660 | /* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */ |
| 642 | return ~via2[gBufA] & irq_bit; | 661 | return ~via2[gBufA] & irq_bit; |
| 643 | } | 662 | } |
| 644 | return 0; | 663 | return 0; |
