1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/interrupt.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/irq.h>
22#include <asm/traps.h>
23
24#include <asm/q40_master.h>
25#include <asm/q40ints.h>
26
27
28
29
30
31
32
33
34
35
36
37static void q40_irq_handler(unsigned int, struct pt_regs *fp);
38static void q40_enable_irq(unsigned int);
39static void q40_disable_irq(unsigned int);
40
41unsigned short q40_ablecount[35];
42unsigned short q40_state[35];
43
44static int q40_irq_startup(unsigned int irq)
45{
46
47 switch (irq) {
48 case 1: case 2: case 8: case 9:
49 case 11: case 12: case 13:
50 printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
51 return -ENXIO;
52 }
53 return 0;
54}
55
56static void q40_irq_shutdown(unsigned int irq)
57{
58}
59
60static struct irq_controller q40_irq_controller = {
61 .name = "q40",
62 .lock = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
63 .startup = q40_irq_startup,
64 .shutdown = q40_irq_shutdown,
65 .enable = q40_enable_irq,
66 .disable = q40_disable_irq,
67};
68
69
70
71
72
73
74
75
76
77
78
79
80static int disabled;
81
82void __init q40_init_IRQ(void)
83{
84 m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
85
86
87 m68k_setup_auto_interrupt(q40_irq_handler);
88
89 m68k_irq_startup(IRQ_AUTO_2);
90 m68k_irq_startup(IRQ_AUTO_4);
91
92
93 master_outb(1, EXT_ENABLE_REG);
94
95
96 master_outb(0, KEY_IRQ_ENABLE_REG);
97}
98
99
100
101
102
103
104int ql_ticks;
105static int sound_ticks;
106
107#define SVOL 45
108
109void q40_mksound(unsigned int hz, unsigned int ticks)
110{
111
112
113 if (hz == 0) {
114 if (sound_ticks)
115 sound_ticks = 1;
116
117 *DAC_LEFT = 128;
118 *DAC_RIGHT = 128;
119
120 return;
121 }
122
123 if (sound_ticks == 0)
124 sound_ticks = 1000;
125 sound_ticks = ticks << 1;
126}
127
128static irq_handler_t q40_timer_routine;
129
130static irqreturn_t q40_timer_int (int irq, void * dev)
131{
132 ql_ticks = ql_ticks ? 0 : 1;
133 if (sound_ticks) {
134 unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
135 sound_ticks--;
136 *DAC_LEFT=sval;
137 *DAC_RIGHT=sval;
138 }
139
140 if (!ql_ticks)
141 q40_timer_routine(irq, dev);
142 return IRQ_HANDLED;
143}
144
145void q40_sched_init (irq_handler_t timer_routine)
146{
147 int timer_irq;
148
149 q40_timer_routine = timer_routine;
150 timer_irq = Q40_IRQ_FRAME;
151
152 if (request_irq(timer_irq, q40_timer_int, 0,
153 "timer", q40_timer_int))
154 panic("Couldn't register timer int");
155
156 master_outb(-1, FRAME_CLEAR_REG);
157 master_outb( 1, FRAME_RATE_REG);
158}
159
160
161
162
163
164
165
166
167struct IRQ_TABLE{ unsigned mask; int irq ;};
168#if 0
169static struct IRQ_TABLE iirqs[]={
170 {Q40_IRQ_FRAME_MASK,Q40_IRQ_FRAME},
171 {Q40_IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
172 {0,0}};
173#endif
174static struct IRQ_TABLE eirqs[] = {
175 { .mask = Q40_IRQ3_MASK, .irq = 3 },
176 { .mask = Q40_IRQ4_MASK, .irq = 4 },
177 { .mask = Q40_IRQ14_MASK, .irq = 14 },
178 { .mask = Q40_IRQ15_MASK, .irq = 15 },
179 { .mask = Q40_IRQ6_MASK, .irq = 6 },
180 { .mask = Q40_IRQ7_MASK, .irq = 7 },
181 { .mask = Q40_IRQ5_MASK, .irq = 5 },
182 { .mask = Q40_IRQ10_MASK, .irq = 10 },
183 {0,0}
184};
185
186
187static int ccleirq=60;
188
189
190
191
192#define IRQ_INPROGRESS 1
193
194
195
196#define DEBUG_Q40INT
197
198
199static int mext_disabled=0;
200static int aliased_irq=0;
201
202
203
204static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
205{
206 unsigned mir, mer;
207 int i;
208
209
210 mir = master_inb(IIRQ_REG);
211#ifdef CONFIG_BLK_DEV_FD
212 if ((mir & Q40_IRQ_EXT_MASK) &&
213 (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) {
214 floppy_hardint();
215 return;
216 }
217#endif
218 switch (irq) {
219 case 4:
220 case 6:
221 __m68k_handle_int(Q40_IRQ_SAMPLE, fp);
222 return;
223 }
224 if (mir & Q40_IRQ_FRAME_MASK) {
225 __m68k_handle_int(Q40_IRQ_FRAME, fp);
226 master_outb(-1, FRAME_CLEAR_REG);
227 }
228 if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
229 mer = master_inb(EIRQ_REG);
230 for (i = 0; eirqs[i].mask; i++) {
231 if (mer & eirqs[i].mask) {
232 irq = eirqs[i].irq;
233
234
235
236
237
238
239 if (irq > 4 && irq <= 15 && mext_disabled) {
240
241 goto iirq;
242 }
243 if (q40_state[irq] & IRQ_INPROGRESS) {
244
245
246#ifdef IP_USE_DISABLE
247
248
249 disable_irq(irq);
250 disabled = 1;
251#else
252
253
254 fp->sr = (((fp->sr) & (~0x700))+0x200);
255 disabled = 1;
256#endif
257 goto iirq;
258 }
259 q40_state[irq] |= IRQ_INPROGRESS;
260 __m68k_handle_int(irq, fp);
261 q40_state[irq] &= ~IRQ_INPROGRESS;
262
263
264
265
266
267 if (disabled) {
268#ifdef IP_USE_DISABLE
269 if (irq > 4) {
270 disabled = 0;
271 enable_irq(irq);
272 }
273#else
274 disabled = 0;
275
276#endif
277 }
278
279 return;
280 }
281 }
282 if (mer && ccleirq > 0 && !aliased_irq) {
283 printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer);
284 ccleirq--;
285 }
286 }
287 iirq:
288 mir = master_inb(IIRQ_REG);
289
290 if (mir & Q40_IRQ_KEYB_MASK)
291 __m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
292
293 return;
294}
295
296void q40_enable_irq(unsigned int irq)
297{
298 if (irq >= 5 && irq <= 15) {
299 mext_disabled--;
300 if (mext_disabled > 0)
301 printk("q40_enable_irq : nested disable/enable\n");
302 if (mext_disabled == 0)
303 master_outb(1, EXT_ENABLE_REG);
304 }
305}
306
307
308void q40_disable_irq(unsigned int irq)
309{
310
311
312
313
314
315 if (irq >= 5 && irq <= 15) {
316 master_outb(0, EXT_ENABLE_REG);
317 mext_disabled++;
318 if (mext_disabled > 1)
319 printk("disable_irq nesting count %d\n",mext_disabled);
320 }
321}
322
323unsigned long q40_probe_irq_on(void)
324{
325 printk("irq probing not working - reconfigure the driver to avoid this\n");
326 return -1;
327}
328int q40_probe_irq_off(unsigned long irqs)
329{
330 return -1;
331}
332