aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/bugfix/m68k/mac68k-irq-prep.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/bugfix/m68k/mac68k-irq-prep.diff')
-rw-r--r--debian/patches/bugfix/m68k/mac68k-irq-prep.diff375
1 files changed, 375 insertions, 0 deletions
diff --git a/debian/patches/bugfix/m68k/mac68k-irq-prep.diff b/debian/patches/bugfix/m68k/mac68k-irq-prep.diff
new file mode 100644
index 000000000000..e43e329e9adc
--- /dev/null
+++ b/debian/patches/bugfix/m68k/mac68k-irq-prep.diff
@@ -0,0 +1,375 @@
+Subject: [PATCH 6/13] m68k: Mac IRQ prep
+
+From: Finn Thain <fthain@telegraphics.com.au>
+
+Make sure that there are no slot IRQs asserted before leaving the nubus
+handler. If there are and we don't then the nubus gets wedged because this
+prevents a CA1 transition, which means no more nubus IRQs.
+
+Make the interrupt dispatch loops terminate sooner.
+
+Explicitly initialise the VIA latches to make the code more easily understood.
+
+Also some cleanups.
+
+Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+---
+ arch/m68k/mac/baboon.c | 12 ++--
+ arch/m68k/mac/oss.c | 8 ++
+ arch/m68k/mac/psc.c | 19 +++---
+ arch/m68k/mac/via.c | 139 ++++++++++++++++++++++++++++++-------------------
+ 4 files changed, 110 insertions(+), 68 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/baboon.c
++++ linux-m68k-2.6.21/arch/m68k/mac/baboon.c
+@@ -66,7 +66,7 @@ void __init baboon_register_interrupts(v
+
+ irqreturn_t baboon_irq(int irq, void *dev_id)
+ {
+- int irq_bit,i;
++ int irq_bit, irq_num;
+ unsigned char events;
+
+ #ifdef DEBUG_IRQS
+@@ -78,14 +78,18 @@ irqreturn_t baboon_irq(int irq, void *de
+ if (!(events = baboon->mb_ifr & 0x07))
+ return IRQ_NONE;
+
+- for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
++ irq_num = IRQ_BABOON_0;
++ irq_bit = 1;
++ do {
+ if (events & irq_bit/* & baboon_active*/) {
+ baboon_active &= ~irq_bit;
+ baboon->mb_ifr &= ~irq_bit;
+- m68k_handle_int(IRQ_BABOON_0 + i);
++ m68k_handle_int(irq_num);
+ baboon_active |= irq_bit;
+ }
+- }
++ irq_bit <<= 1;
++ irq_num++;
++ } while(events >= irq_bit);
+ #if 0
+ if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
+ /* for now we need to smash all interrupts */
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/oss.c
++++ linux-m68k-2.6.21/arch/m68k/mac/oss.c
+@@ -143,14 +143,18 @@ irqreturn_t oss_nubus_irq(int irq, void
+ #endif
+ /* There are only six slots on the OSS, not seven */
+
+- for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
++ i = 6;
++ irq_bit = 0x40;
++ do {
++ --i;
++ irq_bit >>= 1;
+ if (events & irq_bit) {
+ oss->irq_level[i] = OSS_IRQLEV_DISABLED;
+ oss->irq_pending &= ~irq_bit;
+ m68k_handle_int(NUBUS_SOURCE_BASE + i);
+ oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+ }
+- }
++ } while(events & (irq_bit - 1));
+ return IRQ_HANDLED;
+ }
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/psc.c
++++ linux-m68k-2.6.21/arch/m68k/mac/psc.c
+@@ -131,11 +131,8 @@ irqreturn_t psc_irq(int irq, void *dev_i
+ {
+ int pIFR = pIFRbase + ((int) dev_id);
+ int pIER = pIERbase + ((int) dev_id);
+- int base_irq;
+- int irq_bit,i;
+- unsigned char events;
+-
+- base_irq = irq << 3;
++ int irq_num;
++ unsigned char irq_bit, events;
+
+ #ifdef DEBUG_IRQS
+ printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
+@@ -146,14 +143,18 @@ irqreturn_t psc_irq(int irq, void *dev_i
+ if (!events)
+ return IRQ_NONE;
+
+- for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
+- if (events & irq_bit) {
++ irq_num = irq << 3;
++ irq_bit = 1;
++ do {
++ if (events & irq_bit) {
+ psc_write_byte(pIER, irq_bit);
+ psc_write_byte(pIFR, irq_bit);
+- m68k_handle_int(base_irq + i);
++ m68k_handle_int(irq_num);
+ psc_write_byte(pIER, irq_bit | 0x80);
+ }
+- }
++ irq_num++;
++ irq_bit <<= 1;
++ } while (events >= irq_bit);
+ return IRQ_HANDLED;
+ }
+
+--- linux-m68k-2.6.21.orig/arch/m68k/mac/via.c
++++ linux-m68k-2.6.21/arch/m68k/mac/via.c
+@@ -13,6 +13,10 @@
+ * for info. A full-text web search on 6522 AND VIA will probably also
+ * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
+ *
++ * Additional data is here (the SY6522 was used in the Mac II etc):
++ * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
++ * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
++ *
+ * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
+ * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
+ *
+@@ -37,7 +41,7 @@ volatile __u8 *via1, *via2;
+ /* See note in mac_via.h about how this is possibly not useful */
+ volatile long *via_memory_bogon=(long *)&via_memory_bogon;
+ #endif
+-int rbv_present,via_alt_mapping;
++int rbv_present, via_alt_mapping;
+ __u8 rbv_clear;
+
+ /*
+@@ -138,11 +142,11 @@ void __init via_init(void)
+
+ printk(KERN_INFO "VIA2 at %p is ", via2);
+ if (rbv_present) {
+- printk(KERN_INFO "an RBV\n");
++ printk("an RBV\n");
+ } else if (oss_present) {
+- printk(KERN_INFO "an OSS\n");
++ printk("an OSS\n");
+ } else {
+- printk(KERN_INFO "a 6522 or clone\n");
++ printk("a 6522 or clone\n");
+ }
+
+ #ifdef DEBUG_VIA
+@@ -163,6 +167,7 @@ void __init via_init(void)
+ via1[vT2CL] = 0;
+ via1[vT2CH] = 0;
+ via1[vACR] &= 0x3F;
++ via1[vACR] &= ~0x03; /* disable port A & B latches */
+
+ /*
+ * SE/30: disable video IRQ
+@@ -234,6 +239,22 @@ void __init via_init(void)
+ via2[vT2CL] = 0;
+ via2[vT2CH] = 0;
+ via2[vACR] &= 0x3F;
++ via2[vACR] &= ~0x03; /* disable port A & B latches */
++ }
++
++ /*
++ * Set vPCR for SCSI interrupts (but not on RBV)
++ */
++ if (!rbv_present) {
++ if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
++ /* CB2 (IRQ) indep. input, positive edge */
++ /* CA2 (DRQ) indep. input, positive edge */
++ via2[vPCR] = 0x66;
++ } else {
++ /* CB2 (IRQ) indep. input, negative edge */
++ /* CA2 (DRQ) indep. input, negative edge */
++ via2[vPCR] = 0x22;
++ }
+ }
+ }
+
+@@ -367,19 +388,14 @@ void __init via_nubus_init(void)
+
+ /* unlock nubus transactions */
+
+- if (!rbv_present) {
++ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
++ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ /* set the line to be an output on non-RBV machines */
+- if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+- (macintosh_config->adb_type != MAC_ADB_PB2)) {
++ if (!rbv_present)
+ via2[vDirB] |= 0x02;
+- }
+- }
+-
+- /* this seems to be an ADB bit on PMU machines */
+- /* according to MkLinux. -- jmt */
+
+- if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+- (macintosh_config->adb_type != MAC_ADB_PB2)) {
++ /* this seems to be an ADB bit on PMU machines */
++ /* according to MkLinux. -- jmt */
+ via2[gBufB] |= 0x02;
+ }
+
+@@ -420,20 +436,25 @@ void __init via_nubus_init(void)
+
+ irqreturn_t via1_irq(int irq, void *dev_id)
+ {
+- int irq_bit, i;
+- unsigned char events, mask;
++ int irq_num;
++ unsigned char irq_bit, events;
+
+- mask = via1[vIER] & 0x7F;
+- if (!(events = via1[vIFR] & mask))
++ events = via1[vIFR] & via1[vIER] & 0x7F;
++ if (!events)
+ return IRQ_NONE;
+
+- for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
++ irq_num = VIA1_SOURCE_BASE;
++ irq_bit = 1;
++ do {
+ if (events & irq_bit) {
+ via1[vIER] = irq_bit;
+ via1[vIFR] = irq_bit;
+- m68k_handle_int(VIA1_SOURCE_BASE + i);
++ m68k_handle_int(irq_num);
+ via1[vIER] = irq_bit | 0x80;
+ }
++ ++irq_num;
++ irq_bit <<= 1;
++ } while (events >= irq_bit);
+
+ #if 0 /* freakin' pmu is doing weird stuff */
+ if (!oss_present) {
+@@ -454,20 +475,25 @@ irqreturn_t via1_irq(int irq, void *dev_
+
+ irqreturn_t via2_irq(int irq, void *dev_id)
+ {
+- int irq_bit, i;
+- unsigned char events, mask;
++ int irq_num;
++ unsigned char irq_bit, events;
+
+- mask = via2[gIER] & 0x7F;
+- if (!(events = via2[gIFR] & mask))
++ events = via2[gIFR] & via2[gIER] & 0x7F;
++ if (!events)
+ return IRQ_NONE;
+
+- for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
++ irq_num = VIA2_SOURCE_BASE;
++ irq_bit = 1;
++ do {
+ if (events & irq_bit) {
+ via2[gIER] = irq_bit;
+ via2[gIFR] = irq_bit | rbv_clear;
+- m68k_handle_int(VIA2_SOURCE_BASE + i);
++ m68k_handle_int(irq_num);
+ via2[gIER] = irq_bit | 0x80;
+ }
++ ++irq_num;
++ irq_bit <<= 1;
++ } while (events >= irq_bit);
+ return IRQ_HANDLED;
+ }
+
+@@ -478,19 +504,37 @@ irqreturn_t via2_irq(int irq, void *dev_
+
+ irqreturn_t via_nubus_irq(int irq, void *dev_id)
+ {
+- int irq_bit, i;
+- unsigned char events;
++ int slot_irq;
++ unsigned char slot_bit, events;
+
+- if (!(events = ~via2[gBufA] & nubus_active))
++ events = ~via2[gBufA] & 0x7F;
++ if (rbv_present)
++ events &= via2[rSIER];
++ else
++ events &= nubus_active;
++ if (!events)
+ return IRQ_NONE;
+
+- for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
+- if (events & irq_bit) {
+- via_irq_disable(NUBUS_SOURCE_BASE + i);
+- m68k_handle_int(NUBUS_SOURCE_BASE + i);
+- via_irq_enable(NUBUS_SOURCE_BASE + i);
+- }
+- }
++ do {
++ slot_irq = IRQ_NUBUS_F;
++ slot_bit = 0x40;
++ do {
++ if (events & slot_bit) {
++ events &= ~slot_bit;
++ m68k_handle_int(slot_irq);
++ }
++ --slot_irq;
++ slot_bit >>= 1;
++ } while (events);
++
++ /* clear the CA1 interrupt and make certain there's no more. */
++ via2[gIFR] = 0x02 | rbv_clear;
++ events = ~via2[gBufA] & 0x7F;
++ if (rbv_present)
++ events &= via2[rSIER];
++ else
++ events &= nubus_active;
++ } while (events);
+ return IRQ_HANDLED;
+ }
+
+@@ -506,20 +550,6 @@ void via_irq_enable(int irq) {
+ if (irq_src == 1) {
+ via1[vIER] = irq_bit | 0x80;
+ } else if (irq_src == 2) {
+- /*
+- * Set vPCR for SCSI interrupts (but not on RBV)
+- */
+- if ((irq_idx == 0) && !rbv_present) {
+- if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
+- /* CB2 (IRQ) indep. input, positive edge */
+- /* CA2 (DRQ) indep. input, positive edge */
+- via2[vPCR] = 0x66;
+- } else {
+- /* CB2 (IRQ) indep. input, negative edge */
+- /* CA2 (DRQ) indep. input, negative edge */
+- via2[vPCR] = 0x22;
+- }
+- }
+ via2[gIER] = irq_bit | 0x80;
+ } else if (irq_src == 7) {
+ nubus_active |= irq_bit;
+@@ -557,9 +587,9 @@ void via_irq_disable(int irq) {
+ #endif
+
+ if (irq_src == 1) {
+- via1[vIER] = irq_bit;
++ via1[vIER] = irq_bit & 0x7F;
+ } else if (irq_src == 2) {
+- via2[gIER] = irq_bit;
++ via2[gIER] = irq_bit & 0x7F;
+ } else if (irq_src == 7) {
+ if (rbv_present) {
+ /* disable the slot interrupt. SIER works like IER. */
+@@ -586,7 +616,9 @@ void via_irq_clear(int irq) {
+ } else if (irq_src == 2) {
+ via2[gIFR] = irq_bit | rbv_clear;
+ } else if (irq_src == 7) {
+- /* FIXME: hmm.. */
++ /* FIXME: There is no way to clear an individual nubus slot
++ * IRQ flag, other than getting the device to do it.
++ */
+ }
+ }
+
+@@ -606,6 +638,7 @@ int via_irq_pending(int irq)
+ } else if (irq_src == 2) {
+ return via2[gIFR] & irq_bit;
+ } else if (irq_src == 7) {
++ /* FIXME: this can't work while a slot irq is disabled! */
+ return ~via2[gBufA] & irq_bit;
+ }
+ return 0;