#define OSS_POWEROFF 0x80
-/*
- * OSS Interrupt levels for various sub-systems
- *
- * This 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_DISABLED 0
-#define OSS_IRQLEV_IOPISM 1 /* ADB? */
-#define OSS_IRQLEV_SCSI IRQ_AUTO_2
-#define OSS_IRQLEV_NUBUS IRQ_AUTO_3 /* keep this on its own level */
-#define OSS_IRQLEV_IOPSCC IRQ_AUTO_4 /* matches VIA alternate mapping */
-#define OSS_IRQLEV_SOUND IRQ_AUTO_5 /* matches VIA alternate mapping */
-#define OSS_IRQLEV_60HZ 6 /* matches VIA alternate mapping */
-#define OSS_IRQLEV_VIA1 IRQ_AUTO_6 /* matches VIA alternate mapping */
-#define OSS_IRQLEV_PARITY 7 /* matches VIA alternate mapping */
-
#ifndef __ASSEMBLY__
struct mac_oss {
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_iop.h>
-#include <asm/mac_oss.h>
/*#define DEBUG_IOP*/
irqreturn_t iop_ism_irq(int, void *);
-extern void oss_irq_enable(int);
-
/*
* Private access functions
*/
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))
* - 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 (?)
*
* 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):
*
* 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>
switch(irq_src) {
case 1:
- via_irq_enable(irq);
- break;
case 2:
case 7:
if (oss_present)
via_irq_enable(irq);
break;
case 3:
+ case 4:
case 5:
case 6:
if (psc_present)
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);
switch(irq_src) {
case 1:
- via_irq_disable(irq);
- break;
case 2:
case 7:
if (oss_present)
via_irq_disable(irq);
break;
case 3:
+ case 4:
case 5:
case 6:
if (psc_present)
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);
/*
- * OSS handling
+ * Operating System Services (OSS) chip handling
* Written by Joshua M. Thompson (funaho@jurai.org)
*
*
/* 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;
}
/*
}
/*
- * 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)) {
(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);
}
}
/*
* 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;
}
/*
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:
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);
}
/*
#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:
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);
}