summaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/mac')
-rw-r--r--arch/m68k/mac/config.c10
-rw-r--r--arch/m68k/mac/iop.c8
-rw-r--r--arch/m68k/mac/macints.c45
-rw-r--r--arch/m68k/mac/oss.c97
4 files changed, 73 insertions, 87 deletions
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 12e564c6295..101a8b7e2d5 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -893,8 +893,14 @@ static void __init mac_identify(void)
scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC_B;
break;
default:
- scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC;
- scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC;
+ /* On non-PSC machines, the serial ports share an IRQ. */
+ if (macintosh_config->ident == MAC_MODEL_IIFX) {
+ scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC;
+ scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC;
+ } else {
+ scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_AUTO_4;
+ scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_AUTO_4;
+ }
break;
}
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index a5462cc0bfd..7d8d46127ad 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -115,7 +115,6 @@
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_iop.h>
-#include <asm/mac_oss.h>
/*#define DEBUG_IOP*/
@@ -149,8 +148,6 @@ static struct listener iop_listeners[NUM_IOPS][NUM_IOP_CHAN];
irqreturn_t iop_ism_irq(int, void *);
-extern void oss_irq_enable(int);
-
/*
* Private access functions
*/
@@ -304,11 +301,10 @@ void __init iop_init(void)
void __init iop_register_interrupts(void)
{
if (iop_ism_present) {
- if (oss_present) {
- if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
+ if (macintosh_config->ident == MAC_MODEL_IIFX) {
+ if (request_irq(IRQ_MAC_ADB, iop_ism_irq, 0,
"ISM IOP", (void *)IOP_NUM_ISM))
pr_err("Couldn't register ISM IOP interrupt\n");
- oss_irq_enable(IRQ_MAC_ADB);
} else {
if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
(void *)IOP_NUM_ISM))
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 74f5a97c986..5c1a6b2ff0a 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -26,10 +26,6 @@
* - slot 6: timer 1 (not on IIci)
* - slot 7: status of IRQ; signals 'any enabled int.'
*
- * 2 - OSS (IIfx only?)
- * - slot 0: SCSI interrupt
- * - slot 1: Sound interrupt
- *
* Levels 3-6 vary by machine type. For VIA or RBV Macintoshes:
*
* 3 - unused (?)
@@ -54,21 +50,18 @@
*
* 6 - VIA1
*
- * For OSS Macintoshes (IIfx only at this point):
+ * For OSS Macintoshes (IIfx only), we apply an interrupt mapping similar to
+ * the Quadra (A/UX) mapping:
*
- * 3 - Nubus interrupt
- * - slot 0: Slot $9
- * - slot 1: Slot $A
- * - slot 2: Slot $B
- * - slot 3: Slot $C
- * - slot 4: Slot $D
- * - slot 5: Slot $E
+ * 1 - ISM IOP (ADB)
*
- * 4 - SCC IOP
+ * 2 - SCSI
*
- * 5 - ISM IOP (ADB?)
+ * 3 - NuBus
*
- * 6 - unused
+ * 4 - SCC IOP
+ *
+ * 6 - VIA1
*
* For PSC Macintoshes (660AV, 840AV):
*
@@ -112,14 +105,6 @@
* case. They're hidden behind the Nubus slot $C interrupt thus adding a
* third layer of indirection. Why oh why did the Apple engineers do that?
*
- * - We support "fast" and "slow" handlers, just like the Amiga port. The
- * fast handlers are called first and with all interrupts disabled. They
- * are expected to execute quickly (hence the name). The slow handlers are
- * called last with interrupts enabled and the interrupt level restored.
- * They must therefore be reentrant.
- *
- * TODO:
- *
*/
#include <linux/types.h>
@@ -216,8 +201,6 @@ void mac_irq_enable(struct irq_data *data)
switch(irq_src) {
case 1:
- via_irq_enable(irq);
- break;
case 2:
case 7:
if (oss_present)
@@ -226,6 +209,7 @@ void mac_irq_enable(struct irq_data *data)
via_irq_enable(irq);
break;
case 3:
+ case 4:
case 5:
case 6:
if (psc_present)
@@ -233,10 +217,6 @@ void mac_irq_enable(struct irq_data *data)
else if (oss_present)
oss_irq_enable(irq);
break;
- case 4:
- if (psc_present)
- psc_irq_enable(irq);
- break;
case 8:
if (baboon_present)
baboon_irq_enable(irq);
@@ -251,8 +231,6 @@ void mac_irq_disable(struct irq_data *data)
switch(irq_src) {
case 1:
- via_irq_disable(irq);
- break;
case 2:
case 7:
if (oss_present)
@@ -261,6 +239,7 @@ void mac_irq_disable(struct irq_data *data)
via_irq_disable(irq);
break;
case 3:
+ case 4:
case 5:
case 6:
if (psc_present)
@@ -268,10 +247,6 @@ void mac_irq_disable(struct irq_data *data)
else if (oss_present)
oss_irq_disable(irq);
break;
- case 4:
- if (psc_present)
- psc_irq_disable(irq);
- break;
case 8:
if (baboon_present)
baboon_irq_disable(irq);
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index fdc0f843ff6..6c4c882c126 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -1,5 +1,5 @@
/*
- * OSS handling
+ * Operating System Services (OSS) chip handling
* Written by Joshua M. Thompson (funaho@jurai.org)
*
*
@@ -49,10 +49,8 @@ void __init oss_init(void)
/* do this by setting the source's interrupt level to zero. */
for (i = 0; i <= OSS_NUM_SOURCES; i++) {
- oss->irq_level[i] = OSS_IRQLEV_DISABLED;
+ oss->irq_level[i] = 0;
}
- /* If we disable VIA1 here, we never really handle it... */
- oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
}
/*
@@ -64,17 +62,13 @@ void __init oss_nubus_init(void)
}
/*
- * Handle miscellaneous OSS interrupts. Right now that's just sound
- * and SCSI; everything else is routed to its own autovector IRQ.
+ * Handle miscellaneous OSS interrupts.
*/
static void oss_irq(unsigned int irq, struct irq_desc *desc)
{
- int events;
-
- events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
- if (!events)
- return;
+ int events = oss->irq_pending &
+ (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM);
#ifdef DEBUG_IRQS
if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
@@ -82,16 +76,20 @@ static void oss_irq(unsigned int irq, struct irq_desc *desc)
(int) oss->irq_pending);
}
#endif
- /* FIXME: how do you clear a pending IRQ? */
- if (events & OSS_IP_SOUND) {
- oss->irq_pending &= ~OSS_IP_SOUND;
- /* FIXME: call sound handler */
- } else if (events & OSS_IP_SCSI) {
+ if (events & OSS_IP_IOPSCC) {
+ oss->irq_pending &= ~OSS_IP_IOPSCC;
+ generic_handle_irq(IRQ_MAC_SCC);
+ }
+
+ if (events & OSS_IP_SCSI) {
oss->irq_pending &= ~OSS_IP_SCSI;
generic_handle_irq(IRQ_MAC_SCSI);
- } else {
- /* FIXME: error check here? */
+ }
+
+ if (events & OSS_IP_IOPISM) {
+ oss->irq_pending &= ~OSS_IP_IOPISM;
+ generic_handle_irq(IRQ_MAC_ADB);
}
}
@@ -130,14 +128,29 @@ static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
/*
* Register the OSS and NuBus interrupt dispatchers.
+ *
+ * This IRQ mapping is laid out with two things in mind: first, we try to keep
+ * things on their own levels to avoid having to do double-dispatches. Second,
+ * the levels match as closely as possible the alternate IRQ mapping mode (aka
+ * "A/UX mode") available on some VIA machines.
*/
+#define OSS_IRQLEV_IOPISM IRQ_AUTO_1
+#define OSS_IRQLEV_SCSI IRQ_AUTO_2
+#define OSS_IRQLEV_NUBUS IRQ_AUTO_3
+#define OSS_IRQLEV_IOPSCC IRQ_AUTO_4
+#define OSS_IRQLEV_VIA1 IRQ_AUTO_6
+
void __init oss_register_interrupts(void)
{
- irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
- irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
- irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
- irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
+ irq_set_chained_handler(OSS_IRQLEV_IOPISM, oss_irq);
+ irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
+ irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
+ irq_set_chained_handler(OSS_IRQLEV_IOPSCC, oss_irq);
+ irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
+
+ /* OSS_VIA1 gets enabled here because it has no machspec interrupt. */
+ oss->irq_level[OSS_VIA1] = IRQ_AUTO_6;
}
/*
@@ -156,13 +169,13 @@ void oss_irq_enable(int irq) {
switch(irq) {
case IRQ_MAC_SCC:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC;
- break;
+ return;
case IRQ_MAC_ADB:
oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_IOPISM;
- break;
+ return;
case IRQ_MAC_SCSI:
oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
- break;
+ return;
case IRQ_NUBUS_9:
case IRQ_NUBUS_A:
case IRQ_NUBUS_B:
@@ -171,13 +184,11 @@ void oss_irq_enable(int irq) {
case IRQ_NUBUS_E:
irq -= NUBUS_SOURCE_BASE;
oss->irq_level[irq] = OSS_IRQLEV_NUBUS;
- break;
-#ifdef DEBUG_IRQUSE
- default:
- printk("%s unknown irq %d\n", __func__, irq);
- break;
-#endif
+ return;
}
+
+ if (IRQ_SRC(irq) == 1)
+ via_irq_enable(irq);
}
/*
@@ -193,14 +204,14 @@ void oss_irq_disable(int irq) {
#endif
switch(irq) {
case IRQ_MAC_SCC:
- oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED;
- break;
+ oss->irq_level[OSS_IOPSCC] = 0;
+ return;
case IRQ_MAC_ADB:
- oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_DISABLED;
- break;
+ oss->irq_level[OSS_IOPISM] = 0;
+ return;
case IRQ_MAC_SCSI:
- oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
- break;
+ oss->irq_level[OSS_SCSI] = 0;
+ return;
case IRQ_NUBUS_9:
case IRQ_NUBUS_A:
case IRQ_NUBUS_B:
@@ -208,12 +219,10 @@ void oss_irq_disable(int irq) {
case IRQ_NUBUS_D:
case IRQ_NUBUS_E:
irq -= NUBUS_SOURCE_BASE;
- oss->irq_level[irq] = OSS_IRQLEV_DISABLED;
- break;
-#ifdef DEBUG_IRQUSE
- default:
- printk("%s unknown irq %d\n", __func__, irq);
- break;
-#endif
+ oss->irq_level[irq] = 0;
+ return;
}
+
+ if (IRQ_SRC(irq) == 1)
+ via_irq_disable(irq);
}