aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac/via.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/mac/via.c')
-rw-r--r--arch/m68k/mac/via.c141
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
67static 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 */
79static u8 nubus_disabled;
68 80
69void via_debug_dump(void); 81void via_debug_dump(void);
70irqreturn_t via1_irq(int, void *); 82irqreturn_t via1_irq(int, void *);
@@ -383,9 +395,6 @@ int via_get_cache_disable(void)
383 395
384void __init via_nubus_init(void) 396void __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)
541void via_irq_enable(int irq) { 558void 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) {
580void via_irq_disable(int irq) { 597void 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;