diff options
Diffstat (limited to 'arch/m68k/mac/via.c')
-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; |