diff options
Diffstat (limited to 'arch/m68k/mac/oss.c')
-rw-r--r-- | arch/m68k/mac/oss.c | 106 |
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 @@ | |||
32 | int oss_present; | 32 | int oss_present; |
33 | volatile struct mac_oss *oss; | 33 | volatile struct mac_oss *oss; |
34 | 34 | ||
35 | static irqreturn_t oss_irq(int, void *); | 35 | #ifdef CONFIG_GENERIC_HARDIRQS |
36 | static irqreturn_t oss_nubus_irq(int, void *); | 36 | extern void via1_irq(unsigned int irq, struct irq_desc *desc); |
37 | 37 | #else | |
38 | extern irqreturn_t via1_irq(int, void *); | 38 | extern 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 | |||
69 | void __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 | ||
80 | static 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 | ||
95 | static irqreturn_t oss_irq(int irq, void *dev_id) | 107 | static 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 | ||
143 | static 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 | ||
129 | static irqreturn_t oss_nubus_irq(int irq, void *dev_id) | 170 | static 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 | |||
203 | void __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 |