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.c255
1 files changed, 122 insertions, 133 deletions
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index f1600ad26621..2d85662715fb 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -63,24 +63,50 @@ 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);
81void via_irq_enable(int irq);
82void via_irq_disable(int irq);
83void via_irq_clear(int irq);
84 110
85/* 111/*
86 * Initialize the VIAs 112 * Initialize the VIAs
@@ -100,7 +126,7 @@ void __init via_init(void)
100 126
101 /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */ 127 /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */
102 128
103 case MAC_VIA_IIci: 129 case MAC_VIA_IICI:
104 via1 = (void *) VIA1_BASE; 130 via1 = (void *) VIA1_BASE;
105 if (macintosh_config->ident == MAC_MODEL_IIFX) { 131 if (macintosh_config->ident == MAC_MODEL_IIFX) {
106 via2 = NULL; 132 via2 = NULL;
@@ -197,38 +223,17 @@ void __init via_init(void)
197 if (oss_present) 223 if (oss_present)
198 return; 224 return;
199 225
200 /* Some machines support an alternate IRQ mapping that spreads */ 226 if ((macintosh_config->via_type == MAC_VIA_QUADRA) &&
201 /* Ethernet and Sound out to their own autolevel IRQs and moves */ 227 (macintosh_config->adb_type != MAC_ADB_PB1) &&
202 /* VIA1 to level 6. A/UX uses this mapping and we do too. Note */ 228 (macintosh_config->adb_type != MAC_ADB_PB2) &&
203 /* that the IIfx emulates this alternate mapping using the OSS. */ 229 (macintosh_config->ident != MAC_MODEL_C660) &&
204 230 (macintosh_config->ident != MAC_MODEL_Q840)) {
205 via_alt_mapping = 0; 231 via_alt_mapping = 1;
206 if (macintosh_config->via_type == MAC_VIA_QUADRA) 232 via1[vDirB] |= 0x40;
207 switch (macintosh_config->ident) { 233 via1[vBufB] &= ~0x40;
208 case MAC_MODEL_C660: 234 } else {
209 case MAC_MODEL_Q840: 235 via_alt_mapping = 0;
210 /* not applicable */ 236 }
211 break;
212 case MAC_MODEL_P588:
213 case MAC_MODEL_TV:
214 case MAC_MODEL_PB140:
215 case MAC_MODEL_PB145:
216 case MAC_MODEL_PB160:
217 case MAC_MODEL_PB165:
218 case MAC_MODEL_PB165C:
219 case MAC_MODEL_PB170:
220 case MAC_MODEL_PB180:
221 case MAC_MODEL_PB180C:
222 case MAC_MODEL_PB190:
223 case MAC_MODEL_PB520:
224 /* not yet tested */
225 break;
226 default:
227 via_alt_mapping = 1;
228 via1[vDirB] |= 0x40;
229 via1[vBufB] &= ~0x40;
230 break;
231 }
232 237
233 /* 238 /*
234 * Now initialize VIA2. For RBV we just kill all interrupts; 239 * Now initialize VIA2. For RBV we just kill all interrupts;
@@ -248,22 +253,28 @@ void __init via_init(void)
248 via2[vACR] &= ~0x03; /* disable port A & B latches */ 253 via2[vACR] &= ~0x03; /* disable port A & B latches */
249 } 254 }
250 255
256 /* Everything below this point is VIA2 only... */
257
258 if (rbv_present)
259 return;
260
251 /* 261 /*
252 * Set vPCR for control line interrupts (but not on RBV) 262 * Set vPCR for control line interrupts.
263 *
264 * CA1 (SLOTS IRQ), CB1 (ASC IRQ): negative edge trigger.
265 *
266 * Macs with ESP SCSI have a negative edge triggered SCSI interrupt.
267 * Testing reveals that PowerBooks do too. However, the SE/30
268 * schematic diagram shows an active high NCR5380 IRQ line.
253 */ 269 */
254 if (!rbv_present) { 270
255 /* For all VIA types, CA1 (SLOTS IRQ) and CB1 (ASC IRQ) 271 pr_debug("VIA2 vPCR is 0x%02X\n", via2[vPCR]);
256 * are made negative edge triggered here. 272 if (macintosh_config->via_type == MAC_VIA_II) {
257 */ 273 /* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, pos. edge */
258 if (macintosh_config->scsi_type == MAC_SCSI_OLD) { 274 via2[vPCR] = 0x66;
259 /* CB2 (IRQ) indep. input, positive edge */ 275 } else {
260 /* CA2 (DRQ) indep. input, positive edge */ 276 /* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, neg. edge */
261 via2[vPCR] = 0x66; 277 via2[vPCR] = 0x22;
262 } else {
263 /* CB2 (IRQ) indep. input, negative edge */
264 /* CA2 (DRQ) indep. input, negative edge */
265 via2[vPCR] = 0x22;
266 }
267 } 278 }
268} 279}
269 280
@@ -378,34 +389,55 @@ void __init via_nubus_init(void)
378 via2[gBufB] |= 0x02; 389 via2[gBufB] |= 0x02;
379 } 390 }
380 391
381 /* Disable all the slot interrupts (where possible). */ 392 /*
393 * Disable the slot interrupts. On some hardware that's not possible.
394 * On some hardware it's unclear what all of these I/O lines do.
395 */
382 396
383 switch (macintosh_config->via_type) { 397 switch (macintosh_config->via_type) {
384 case MAC_VIA_II: 398 case MAC_VIA_II:
385 /* Just make the port A lines inputs. */ 399 case MAC_VIA_QUADRA:
386 switch(macintosh_config->ident) { 400 pr_debug("VIA2 vDirA is 0x%02X\n", via2[vDirA]);
387 case MAC_MODEL_II:
388 case MAC_MODEL_IIX:
389 case MAC_MODEL_IICX:
390 case MAC_MODEL_SE30:
391 /* The top two bits are RAM size outputs. */
392 via2[vDirA] &= 0xC0;
393 break;
394 default:
395 via2[vDirA] &= 0x80;
396 }
397 break; 401 break;
398 case MAC_VIA_IIci: 402 case MAC_VIA_IICI:
399 /* RBV. Disable all the slot interrupts. SIER works like IER. */ 403 /* RBV. Disable all the slot interrupts. SIER works like IER. */
400 via2[rSIER] = 0x7F; 404 via2[rSIER] = 0x7F;
401 break; 405 break;
406 }
407}
408
409void via_nubus_irq_startup(int irq)
410{
411 int irq_idx = IRQ_IDX(irq);
412
413 switch (macintosh_config->via_type) {
414 case MAC_VIA_II:
402 case MAC_VIA_QUADRA: 415 case MAC_VIA_QUADRA:
403 /* Disable the inactive slot interrupts by making those lines outputs. */ 416 /* Make the port A line an input. Probably redundant. */
404 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 417 if (macintosh_config->via_type == MAC_VIA_II) {
405 (macintosh_config->adb_type != MAC_ADB_PB2)) { 418 /* The top two bits are RAM size outputs. */
406 via2[vBufA] |= 0x7F; 419 via2[vDirA] &= 0xC0 | ~(1 << irq_idx);
407 via2[vDirA] |= 0x7F; 420 } else {
421 /* Allow NuBus slots 9 through F. */
422 via2[vDirA] &= 0x80 | ~(1 << irq_idx);
408 } 423 }
424 /* fall through */
425 case MAC_VIA_IICI:
426 via_irq_enable(irq);
427 break;
428 }
429}
430
431void via_nubus_irq_shutdown(int irq)
432{
433 switch (macintosh_config->via_type) {
434 case MAC_VIA_II:
435 case MAC_VIA_QUADRA:
436 /* Ensure that the umbrella CA1 interrupt remains enabled. */
437 via_irq_enable(irq);
438 break;
439 case MAC_VIA_IICI:
440 via_irq_disable(irq);
409 break; 441 break;
410 } 442 }
411} 443}
@@ -531,25 +563,18 @@ void via_irq_enable(int irq) {
531 } else if (irq_src == 7) { 563 } else if (irq_src == 7) {
532 switch (macintosh_config->via_type) { 564 switch (macintosh_config->via_type) {
533 case MAC_VIA_II: 565 case MAC_VIA_II:
566 case MAC_VIA_QUADRA:
534 nubus_disabled &= ~(1 << irq_idx); 567 nubus_disabled &= ~(1 << irq_idx);
535 /* Enable the CA1 interrupt when no slot is disabled. */ 568 /* Enable the CA1 interrupt when no slot is disabled. */
536 if (!nubus_disabled) 569 if (!nubus_disabled)
537 via2[gIER] = IER_SET_BIT(1); 570 via2[gIER] = IER_SET_BIT(1);
538 break; 571 break;
539 case MAC_VIA_IIci: 572 case MAC_VIA_IICI:
540 /* On RBV, enable the slot interrupt. 573 /* On RBV, enable the slot interrupt.
541 * SIER works like IER. 574 * SIER works like IER.
542 */ 575 */
543 via2[rSIER] = IER_SET_BIT(irq_idx); 576 via2[rSIER] = IER_SET_BIT(irq_idx);
544 break; 577 break;
545 case MAC_VIA_QUADRA:
546 /* Make the port A line an input to enable the slot irq.
547 * But not on PowerBooks, that's ADB.
548 */
549 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
550 (macintosh_config->adb_type != MAC_ADB_PB2))
551 via2[vDirA] &= ~(1 << irq_idx);
552 break;
553 } 578 }
554 } 579 }
555} 580}
@@ -569,60 +594,18 @@ void via_irq_disable(int irq) {
569 } else if (irq_src == 7) { 594 } else if (irq_src == 7) {
570 switch (macintosh_config->via_type) { 595 switch (macintosh_config->via_type) {
571 case MAC_VIA_II: 596 case MAC_VIA_II:
597 case MAC_VIA_QUADRA:
572 nubus_disabled |= 1 << irq_idx; 598 nubus_disabled |= 1 << irq_idx;
573 if (nubus_disabled) 599 if (nubus_disabled)
574 via2[gIER] = IER_CLR_BIT(1); 600 via2[gIER] = IER_CLR_BIT(1);
575 break; 601 break;
576 case MAC_VIA_IIci: 602 case MAC_VIA_IICI:
577 via2[rSIER] = IER_CLR_BIT(irq_idx); 603 via2[rSIER] = IER_CLR_BIT(irq_idx);
578 break; 604 break;
579 case MAC_VIA_QUADRA:
580 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
581 (macintosh_config->adb_type != MAC_ADB_PB2))
582 via2[vDirA] |= 1 << irq_idx;
583 break;
584 } 605 }
585 } 606 }
586} 607}
587 608
588void via_irq_clear(int irq) {
589 int irq_src = IRQ_SRC(irq);
590 int irq_idx = IRQ_IDX(irq);
591 int irq_bit = 1 << irq_idx;
592
593 if (irq_src == 1) {
594 via1[vIFR] = irq_bit;
595 } else if (irq_src == 2) {
596 via2[gIFR] = irq_bit | rbv_clear;
597 } else if (irq_src == 7) {
598 /* FIXME: There is no way to clear an individual nubus slot
599 * IRQ flag, other than getting the device to do it.
600 */
601 }
602}
603
604/*
605 * Returns nonzero if an interrupt is pending on the given
606 * VIA/IRQ combination.
607 */
608
609int via_irq_pending(int irq)
610{
611 int irq_src = IRQ_SRC(irq);
612 int irq_idx = IRQ_IDX(irq);
613 int irq_bit = 1 << irq_idx;
614
615 if (irq_src == 1) {
616 return via1[vIFR] & irq_bit;
617 } else if (irq_src == 2) {
618 return via2[gIFR] & irq_bit;
619 } else if (irq_src == 7) {
620 /* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */
621 return ~via2[gBufA] & irq_bit;
622 }
623 return 0;
624}
625
626void via1_set_head(int head) 609void via1_set_head(int head)
627{ 610{
628 if (head == 0) 611 if (head == 0)
@@ -631,3 +614,9 @@ void via1_set_head(int head)
631 via1[vBufA] |= VIA1A_vHeadSel; 614 via1[vBufA] |= VIA1A_vHeadSel;
632} 615}
633EXPORT_SYMBOL(via1_set_head); 616EXPORT_SYMBOL(via1_set_head);
617
618int via2_scsi_drq_pending(void)
619{
620 return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ));
621}
622EXPORT_SYMBOL(via2_scsi_drq_pending);