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, 87 insertions, 54 deletions
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 21b03180d9f4..0c1cc45c570d 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -13,6 +13,10 @@
13 * for info. A full-text web search on 6522 AND VIA will probably also 13 * for info. A full-text web search on 6522 AND VIA will probably also
14 * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999 14 * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
15 * 15 *
16 * Additional data is here (the SY6522 was used in the Mac II etc):
17 * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
18 * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
19 *
16 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b 20 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
17 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org) 21 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
18 * 22 *
@@ -37,7 +41,7 @@ volatile __u8 *via1, *via2;
37/* See note in mac_via.h about how this is possibly not useful */ 41/* See note in mac_via.h about how this is possibly not useful */
38volatile long *via_memory_bogon=(long *)&via_memory_bogon; 42volatile long *via_memory_bogon=(long *)&via_memory_bogon;
39#endif 43#endif
40int rbv_present,via_alt_mapping; 44int rbv_present, via_alt_mapping;
41__u8 rbv_clear; 45__u8 rbv_clear;
42 46
43/* 47/*
@@ -138,11 +142,11 @@ void __init via_init(void)
138 142
139 printk(KERN_INFO "VIA2 at %p is ", via2); 143 printk(KERN_INFO "VIA2 at %p is ", via2);
140 if (rbv_present) { 144 if (rbv_present) {
141 printk(KERN_INFO "an RBV\n"); 145 printk("an RBV\n");
142 } else if (oss_present) { 146 } else if (oss_present) {
143 printk(KERN_INFO "an OSS\n"); 147 printk("an OSS\n");
144 } else { 148 } else {
145 printk(KERN_INFO "a 6522 or clone\n"); 149 printk("a 6522 or clone\n");
146 } 150 }
147 151
148#ifdef DEBUG_VIA 152#ifdef DEBUG_VIA
@@ -163,6 +167,7 @@ void __init via_init(void)
163 via1[vT2CL] = 0; 167 via1[vT2CL] = 0;
164 via1[vT2CH] = 0; 168 via1[vT2CH] = 0;
165 via1[vACR] &= 0x3F; 169 via1[vACR] &= 0x3F;
170 via1[vACR] &= ~0x03; /* disable port A & B latches */
166 171
167 /* 172 /*
168 * SE/30: disable video IRQ 173 * SE/30: disable video IRQ
@@ -234,6 +239,22 @@ void __init via_init(void)
234 via2[vT2CL] = 0; 239 via2[vT2CL] = 0;
235 via2[vT2CH] = 0; 240 via2[vT2CH] = 0;
236 via2[vACR] &= 0x3F; 241 via2[vACR] &= 0x3F;
242 via2[vACR] &= ~0x03; /* disable port A & B latches */
243 }
244
245 /*
246 * Set vPCR for SCSI interrupts (but not on RBV)
247 */
248 if (!rbv_present) {
249 if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
250 /* CB2 (IRQ) indep. input, positive edge */
251 /* CA2 (DRQ) indep. input, positive edge */
252 via2[vPCR] = 0x66;
253 } else {
254 /* CB2 (IRQ) indep. input, negative edge */
255 /* CA2 (DRQ) indep. input, negative edge */
256 via2[vPCR] = 0x22;
257 }
237 } 258 }
238} 259}
239 260
@@ -367,19 +388,14 @@ void __init via_nubus_init(void)
367 388
368 /* unlock nubus transactions */ 389 /* unlock nubus transactions */
369 390
370 if (!rbv_present) { 391 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
392 (macintosh_config->adb_type != MAC_ADB_PB2)) {
371 /* set the line to be an output on non-RBV machines */ 393 /* set the line to be an output on non-RBV machines */
372 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 394 if (!rbv_present)
373 (macintosh_config->adb_type != MAC_ADB_PB2)) {
374 via2[vDirB] |= 0x02; 395 via2[vDirB] |= 0x02;
375 }
376 }
377
378 /* this seems to be an ADB bit on PMU machines */
379 /* according to MkLinux. -- jmt */
380 396
381 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 397 /* this seems to be an ADB bit on PMU machines */
382 (macintosh_config->adb_type != MAC_ADB_PB2)) { 398 /* according to MkLinux. -- jmt */
383 via2[gBufB] |= 0x02; 399 via2[gBufB] |= 0x02;
384 } 400 }
385 401
@@ -420,20 +436,25 @@ void __init via_nubus_init(void)
420 436
421irqreturn_t via1_irq(int irq, void *dev_id) 437irqreturn_t via1_irq(int irq, void *dev_id)
422{ 438{
423 int irq_bit, i; 439 int irq_num;
424 unsigned char events, mask; 440 unsigned char irq_bit, events;
425 441
426 mask = via1[vIER] & 0x7F; 442 events = via1[vIFR] & via1[vIER] & 0x7F;
427 if (!(events = via1[vIFR] & mask)) 443 if (!events)
428 return IRQ_NONE; 444 return IRQ_NONE;
429 445
430 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) 446 irq_num = VIA1_SOURCE_BASE;
447 irq_bit = 1;
448 do {
431 if (events & irq_bit) { 449 if (events & irq_bit) {
432 via1[vIER] = irq_bit; 450 via1[vIER] = irq_bit;
433 via1[vIFR] = irq_bit; 451 via1[vIFR] = irq_bit;
434 m68k_handle_int(VIA1_SOURCE_BASE + i); 452 m68k_handle_int(irq_num);
435 via1[vIER] = irq_bit | 0x80; 453 via1[vIER] = irq_bit | 0x80;
436 } 454 }
455 ++irq_num;
456 irq_bit <<= 1;
457 } while (events >= irq_bit);
437 458
438#if 0 /* freakin' pmu is doing weird stuff */ 459#if 0 /* freakin' pmu is doing weird stuff */
439 if (!oss_present) { 460 if (!oss_present) {
@@ -454,20 +475,25 @@ irqreturn_t via1_irq(int irq, void *dev_id)
454 475
455irqreturn_t via2_irq(int irq, void *dev_id) 476irqreturn_t via2_irq(int irq, void *dev_id)
456{ 477{
457 int irq_bit, i; 478 int irq_num;
458 unsigned char events, mask; 479 unsigned char irq_bit, events;
459 480
460 mask = via2[gIER] & 0x7F; 481 events = via2[gIFR] & via2[gIER] & 0x7F;
461 if (!(events = via2[gIFR] & mask)) 482 if (!events)
462 return IRQ_NONE; 483 return IRQ_NONE;
463 484
464 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) 485 irq_num = VIA2_SOURCE_BASE;
486 irq_bit = 1;
487 do {
465 if (events & irq_bit) { 488 if (events & irq_bit) {
466 via2[gIER] = irq_bit; 489 via2[gIER] = irq_bit;
467 via2[gIFR] = irq_bit | rbv_clear; 490 via2[gIFR] = irq_bit | rbv_clear;
468 m68k_handle_int(VIA2_SOURCE_BASE + i); 491 m68k_handle_int(irq_num);
469 via2[gIER] = irq_bit | 0x80; 492 via2[gIER] = irq_bit | 0x80;
470 } 493 }
494 ++irq_num;
495 irq_bit <<= 1;
496 } while (events >= irq_bit);
471 return IRQ_HANDLED; 497 return IRQ_HANDLED;
472} 498}
473 499
@@ -478,19 +504,37 @@ irqreturn_t via2_irq(int irq, void *dev_id)
478 504
479irqreturn_t via_nubus_irq(int irq, void *dev_id) 505irqreturn_t via_nubus_irq(int irq, void *dev_id)
480{ 506{
481 int irq_bit, i; 507 int slot_irq;
482 unsigned char events; 508 unsigned char slot_bit, events;
483 509
484 if (!(events = ~via2[gBufA] & nubus_active)) 510 events = ~via2[gBufA] & 0x7F;
511 if (rbv_present)
512 events &= via2[rSIER];
513 else
514 events &= nubus_active;
515 if (!events)
485 return IRQ_NONE; 516 return IRQ_NONE;
486 517
487 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) { 518 do {
488 if (events & irq_bit) { 519 slot_irq = IRQ_NUBUS_F;
489 via_irq_disable(NUBUS_SOURCE_BASE + i); 520 slot_bit = 0x40;
490 m68k_handle_int(NUBUS_SOURCE_BASE + i); 521 do {
491 via_irq_enable(NUBUS_SOURCE_BASE + i); 522 if (events & slot_bit) {
492 } 523 events &= ~slot_bit;
493 } 524 m68k_handle_int(slot_irq);
525 }
526 --slot_irq;
527 slot_bit >>= 1;
528 } while (events);
529
530 /* clear the CA1 interrupt and make certain there's no more. */
531 via2[gIFR] = 0x02 | rbv_clear;
532 events = ~via2[gBufA] & 0x7F;
533 if (rbv_present)
534 events &= via2[rSIER];
535 else
536 events &= nubus_active;
537 } while (events);
494 return IRQ_HANDLED; 538 return IRQ_HANDLED;
495} 539}
496 540
@@ -506,20 +550,6 @@ void via_irq_enable(int irq) {
506 if (irq_src == 1) { 550 if (irq_src == 1) {
507 via1[vIER] = irq_bit | 0x80; 551 via1[vIER] = irq_bit | 0x80;
508 } else if (irq_src == 2) { 552 } else if (irq_src == 2) {
509 /*
510 * Set vPCR for SCSI interrupts (but not on RBV)
511 */
512 if ((irq_idx == 0) && !rbv_present) {
513 if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
514 /* CB2 (IRQ) indep. input, positive edge */
515 /* CA2 (DRQ) indep. input, positive edge */
516 via2[vPCR] = 0x66;
517 } else {
518 /* CB2 (IRQ) indep. input, negative edge */
519 /* CA2 (DRQ) indep. input, negative edge */
520 via2[vPCR] = 0x22;
521 }
522 }
523 via2[gIER] = irq_bit | 0x80; 553 via2[gIER] = irq_bit | 0x80;
524 } else if (irq_src == 7) { 554 } else if (irq_src == 7) {
525 nubus_active |= irq_bit; 555 nubus_active |= irq_bit;
@@ -557,9 +587,9 @@ void via_irq_disable(int irq) {
557#endif 587#endif
558 588
559 if (irq_src == 1) { 589 if (irq_src == 1) {
560 via1[vIER] = irq_bit; 590 via1[vIER] = irq_bit & 0x7F;
561 } else if (irq_src == 2) { 591 } else if (irq_src == 2) {
562 via2[gIER] = irq_bit; 592 via2[gIER] = irq_bit & 0x7F;
563 } else if (irq_src == 7) { 593 } else if (irq_src == 7) {
564 if (rbv_present) { 594 if (rbv_present) {
565 /* disable the slot interrupt. SIER works like IER. */ 595 /* disable the slot interrupt. SIER works like IER. */
@@ -586,7 +616,9 @@ void via_irq_clear(int irq) {
586 } else if (irq_src == 2) { 616 } else if (irq_src == 2) {
587 via2[gIFR] = irq_bit | rbv_clear; 617 via2[gIFR] = irq_bit | rbv_clear;
588 } else if (irq_src == 7) { 618 } else if (irq_src == 7) {
589 /* FIXME: hmm.. */ 619 /* FIXME: There is no way to clear an individual nubus slot
620 * IRQ flag, other than getting the device to do it.
621 */
590 } 622 }
591} 623}
592 624
@@ -606,6 +638,7 @@ int via_irq_pending(int irq)
606 } else if (irq_src == 2) { 638 } else if (irq_src == 2) {
607 return via2[gIFR] & irq_bit; 639 return via2[gIFR] & irq_bit;
608 } else if (irq_src == 7) { 640 } else if (irq_src == 7) {
641 /* FIXME: this can't work while a slot irq is disabled! */
609 return ~via2[gBufA] & irq_bit; 642 return ~via2[gBufA] & irq_bit;
610 } 643 }
611 return 0; 644 return 0;