aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac/oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/mac/oss.c')
-rw-r--r--arch/m68k/mac/oss.c106
1 files changed, 86 insertions, 20 deletions
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index ed952704e6ee..cc784c2ff6e8 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -32,10 +32,11 @@
32int oss_present; 32int oss_present;
33volatile struct mac_oss *oss; 33volatile struct mac_oss *oss;
34 34
35static irqreturn_t oss_irq(int, void *); 35#ifdef CONFIG_GENERIC_HARDIRQS
36static irqreturn_t oss_nubus_irq(int, void *); 36extern void via1_irq(unsigned int irq, struct irq_desc *desc);
37 37#else
38extern irqreturn_t via1_irq(int, void *); 38extern irqreturn_t via1_irq(int, void *);
39#endif
39 40
40/* 41/*
41 * Initialize the OSS 42 * Initialize the OSS
@@ -63,23 +64,6 @@ void __init oss_init(void)
63} 64}
64 65
65/* 66/*
66 * Register the OSS and NuBus interrupt dispatchers.
67 */
68
69void __init oss_register_interrupts(void)
70{
71 if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss))
72 pr_err("Couldn't register %s interrupt\n", "scsi");
73 if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus",
74 (void *)oss))
75 pr_err("Couldn't register %s interrupt\n", "nubus");
76 if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss))
77 pr_err("Couldn't register %s interrupt\n", "sound");
78 if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1))
79 pr_err("Couldn't register %s interrupt\n", "via1");
80}
81
82/*
83 * Initialize OSS for Nubus access 67 * Initialize OSS for Nubus access
84 */ 68 */
85 69
@@ -92,6 +76,34 @@ void __init oss_nubus_init(void)
92 * and SCSI; everything else is routed to its own autovector IRQ. 76 * and SCSI; everything else is routed to its own autovector IRQ.
93 */ 77 */
94 78
79#ifdef CONFIG_GENERIC_HARDIRQS
80static void oss_irq(unsigned int irq, struct irq_desc *desc)
81{
82 int events;
83
84 events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
85 if (!events)
86 return;
87
88#ifdef DEBUG_IRQS
89 if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
90 printk("oss_irq: irq %u events = 0x%04X\n", irq,
91 (int) oss->irq_pending);
92 }
93#endif
94 /* FIXME: how do you clear a pending IRQ? */
95
96 if (events & OSS_IP_SOUND) {
97 oss->irq_pending &= ~OSS_IP_SOUND;
98 /* FIXME: call sound handler */
99 } else if (events & OSS_IP_SCSI) {
100 oss->irq_pending &= ~OSS_IP_SCSI;
101 generic_handle_irq(IRQ_MAC_SCSI);
102 } else {
103 /* FIXME: error check here? */
104 }
105}
106#else
95static irqreturn_t oss_irq(int irq, void *dev_id) 107static irqreturn_t oss_irq(int irq, void *dev_id)
96{ 108{
97 int events; 109 int events;
@@ -119,6 +131,7 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
119 } 131 }
120 return IRQ_HANDLED; 132 return IRQ_HANDLED;
121} 133}
134#endif
122 135
123/* 136/*
124 * Nubus IRQ handler, OSS style 137 * Nubus IRQ handler, OSS style
@@ -126,6 +139,34 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
126 * Unlike the VIA/RBV this is on its own autovector interrupt level. 139 * Unlike the VIA/RBV this is on its own autovector interrupt level.
127 */ 140 */
128 141
142#ifdef CONFIG_GENERIC_HARDIRQS
143static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
144{
145 int events, irq_bit, i;
146
147 events = oss->irq_pending & OSS_IP_NUBUS;
148 if (!events)
149 return;
150
151#ifdef DEBUG_NUBUS_INT
152 if (console_loglevel > 7) {
153 printk("oss_nubus_irq: events = 0x%04X\n", events);
154 }
155#endif
156 /* There are only six slots on the OSS, not seven */
157
158 i = 6;
159 irq_bit = 0x40;
160 do {
161 --i;
162 irq_bit >>= 1;
163 if (events & irq_bit) {
164 oss->irq_pending &= ~irq_bit;
165 generic_handle_irq(NUBUS_SOURCE_BASE + i);
166 }
167 } while(events & (irq_bit - 1));
168}
169#else
129static irqreturn_t oss_nubus_irq(int irq, void *dev_id) 170static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
130{ 171{
131 int events, irq_bit, i; 172 int events, irq_bit, i;
@@ -153,6 +194,31 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
153 } while(events & (irq_bit - 1)); 194 } while(events & (irq_bit - 1));
154 return IRQ_HANDLED; 195 return IRQ_HANDLED;
155} 196}
197#endif
198
199/*
200 * Register the OSS and NuBus interrupt dispatchers.
201 */
202
203void __init oss_register_interrupts(void)
204{
205#ifdef CONFIG_GENERIC_HARDIRQS
206 irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
207 irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
208 irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
209 irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
210#else /* !CONFIG_GENERIC_HARDIRQS */
211 if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss))
212 pr_err("Couldn't register %s interrupt\n", "scsi");
213 if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus",
214 (void *)oss))
215 pr_err("Couldn't register %s interrupt\n", "nubus");
216 if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss))
217 pr_err("Couldn't register %s interrupt\n", "sound");
218 if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1))
219 pr_err("Couldn't register %s interrupt\n", "via1");
220#endif /* !CONFIG_GENERIC_HARDIRQS */
221}
156 222
157/* 223/*
158 * Enable an OSS interrupt 224 * Enable an OSS interrupt