diff options
Diffstat (limited to 'arch/m68k/mac/via.c')
-rw-r--r-- | arch/m68k/mac/via.c | 255 |
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 | |||
78 | static u8 nubus_disabled; | 107 | static u8 nubus_disabled; |
79 | 108 | ||
80 | void via_debug_dump(void); | 109 | void via_debug_dump(void); |
81 | void via_irq_enable(int irq); | ||
82 | void via_irq_disable(int irq); | ||
83 | void 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 | |||
409 | void 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 | |||
431 | void 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 | ||
588 | void 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 | |||
609 | int 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 | |||
626 | void via1_set_head(int head) | 609 | void 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 | } |
633 | EXPORT_SYMBOL(via1_set_head); | 616 | EXPORT_SYMBOL(via1_set_head); |
617 | |||
618 | int via2_scsi_drq_pending(void) | ||
619 | { | ||
620 | return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ)); | ||
621 | } | ||
622 | EXPORT_SYMBOL(via2_scsi_drq_pending); | ||