]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code | |
3 | * | |
4 | * This file is subject to the terms and conditions of the GNU General Public | |
5 | * License. See the file COPYING in the main directory of this archive | |
6 | * for more details. | |
7 | * | |
8 | * 11/07/96: rewritten interrupt handling, irq lists are exists now only for | |
9 | * this sources where it makes sense (VERTB/PORTS/EXTER) and you must | |
10 | * be careful that dev_id for this sources is unique since this the | |
11 | * only possibility to distinguish between different handlers for | |
12 | * free_irq. irq lists also have different irq flags: | |
13 | * - IRQ_FLG_FAST: handler is inserted at top of list (after other | |
14 | * fast handlers) | |
15 | * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before | |
16 | * they're executed irq level is set to the previous | |
17 | * one, but handlers don't need to be reentrant, if | |
18 | * reentrance occurred, slow handlers will be just | |
19 | * called again. | |
20 | * The whole interrupt handling for CIAs is moved to cia.c | |
21 | * /Roman Zippel | |
22 | * | |
23 | * 07/08/99: rewamp of the interrupt handling - we now have two types of | |
24 | * interrupts, normal and fast handlers, fast handlers being | |
25 | * marked with SA_INTERRUPT and runs with all other interrupts | |
26 | * disabled. Normal interrupts disable their own source but | |
27 | * run with all other interrupt sources enabled. | |
28 | * PORTS and EXTER interrupts are always shared even if the | |
29 | * drivers do not explicitly mark this when calling | |
30 | * request_irq which they really should do. | |
31 | * This is similar to the way interrupts are handled on all | |
32 | * other architectures and makes a ton of sense besides | |
33 | * having the advantage of making it easier to share | |
34 | * drivers. | |
35 | * /Jes | |
36 | */ | |
37 | ||
38 | #include <linux/types.h> | |
39 | #include <linux/kernel.h> | |
40 | #include <linux/sched.h> | |
41 | #include <linux/kernel_stat.h> | |
42 | #include <linux/init.h> | |
b5dc7840 | 43 | #include <linux/interrupt.h> |
1da177e4 LT |
44 | #include <linux/errno.h> |
45 | #include <linux/seq_file.h> | |
46 | ||
47 | #include <asm/system.h> | |
48 | #include <asm/irq.h> | |
49 | #include <asm/traps.h> | |
50 | #include <asm/amigahw.h> | |
51 | #include <asm/amigaints.h> | |
52 | #include <asm/amipcmcia.h> | |
53 | ||
54 | extern int cia_request_irq(struct ciabase *base,int irq, | |
55 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | |
56 | unsigned long flags, const char *devname, void *dev_id); | |
57 | extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id); | |
58 | extern void cia_init_IRQ(struct ciabase *base); | |
59 | extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p); | |
60 | ||
61 | /* irq node variables for amiga interrupt sources */ | |
62 | static irq_node_t *ami_irq_list[AMI_STD_IRQS]; | |
63 | ||
64 | static unsigned short amiga_intena_vals[AMI_STD_IRQS] = { | |
1d174cfb RZ |
65 | [IRQ_AMIGA_VERTB-IRQ_USER] = IF_VERTB, |
66 | [IRQ_AMIGA_COPPER-IRQ_USER] = IF_COPER, | |
67 | [IRQ_AMIGA_AUD0-IRQ_USER] = IF_AUD0, | |
68 | [IRQ_AMIGA_AUD1-IRQ_USER] = IF_AUD1, | |
69 | [IRQ_AMIGA_AUD2-IRQ_USER] = IF_AUD2, | |
70 | [IRQ_AMIGA_AUD3-IRQ_USER] = IF_AUD3, | |
71 | [IRQ_AMIGA_BLIT-IRQ_USER] = IF_BLIT, | |
72 | [IRQ_AMIGA_DSKSYN-IRQ_USER] = IF_DSKSYN, | |
73 | [IRQ_AMIGA_DSKBLK-IRQ_USER] = IF_DSKBLK, | |
74 | [IRQ_AMIGA_RBF-IRQ_USER] = IF_RBF, | |
75 | [IRQ_AMIGA_TBE-IRQ_USER] = IF_TBE, | |
76 | [IRQ_AMIGA_SOFT-IRQ_USER] = IF_SOFT, | |
77 | [IRQ_AMIGA_PORTS-IRQ_USER] = IF_PORTS, | |
78 | [IRQ_AMIGA_EXTER-IRQ_USER] = IF_EXTER | |
1da177e4 LT |
79 | }; |
80 | static const unsigned char ami_servers[AMI_STD_IRQS] = { | |
1d174cfb RZ |
81 | [IRQ_AMIGA_VERTB-IRQ_USER] = 1, |
82 | [IRQ_AMIGA_PORTS-IRQ_USER] = 1, | |
83 | [IRQ_AMIGA_EXTER-IRQ_USER] = 1 | |
1da177e4 LT |
84 | }; |
85 | ||
86 | static short ami_ablecount[AMI_IRQS]; | |
87 | ||
88 | static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp) | |
89 | { | |
90 | num_spurious += 1; | |
91 | return IRQ_NONE; | |
92 | } | |
93 | ||
94 | /* | |
95 | * void amiga_init_IRQ(void) | |
96 | * | |
97 | * Parameters: None | |
98 | * | |
99 | * Returns: Nothing | |
100 | * | |
101 | * This function should be called during kernel startup to initialize | |
102 | * the amiga IRQ handling routines. | |
103 | */ | |
104 | ||
105 | void __init amiga_init_IRQ(void) | |
106 | { | |
107 | int i; | |
108 | ||
109 | /* initialize handlers */ | |
110 | for (i = 0; i < AMI_STD_IRQS; i++) { | |
111 | if (ami_servers[i]) { | |
112 | ami_irq_list[i] = NULL; | |
113 | } else { | |
114 | ami_irq_list[i] = new_irq_node(); | |
115 | ami_irq_list[i]->handler = ami_badint; | |
116 | ami_irq_list[i]->flags = 0; | |
117 | ami_irq_list[i]->dev_id = NULL; | |
118 | ami_irq_list[i]->devname = NULL; | |
119 | ami_irq_list[i]->next = NULL; | |
120 | } | |
121 | } | |
122 | for (i = 0; i < AMI_IRQS; i++) | |
123 | ami_ablecount[i] = 0; | |
124 | ||
125 | /* turn off PCMCIA interrupts */ | |
126 | if (AMIGAHW_PRESENT(PCMCIA)) | |
127 | gayle.inten = GAYLE_IRQ_IDE; | |
128 | ||
129 | /* turn off all interrupts and enable the master interrupt bit */ | |
b4290a23 AV |
130 | amiga_custom.intena = 0x7fff; |
131 | amiga_custom.intreq = 0x7fff; | |
132 | amiga_custom.intena = IF_SETCLR | IF_INTEN; | |
1da177e4 LT |
133 | |
134 | cia_init_IRQ(&ciaa_base); | |
135 | cia_init_IRQ(&ciab_base); | |
136 | } | |
137 | ||
138 | static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node) | |
139 | { | |
140 | unsigned long flags; | |
141 | irq_node_t *cur; | |
142 | ||
143 | if (!node->dev_id) | |
144 | printk("%s: Warning: dev_id of %s is zero\n", | |
145 | __FUNCTION__, node->devname); | |
146 | ||
147 | local_irq_save(flags); | |
148 | ||
149 | cur = *list; | |
150 | ||
151 | if (node->flags & SA_INTERRUPT) { | |
152 | if (node->flags & SA_SHIRQ) | |
153 | return -EBUSY; | |
154 | /* | |
155 | * There should never be more than one | |
156 | */ | |
157 | while (cur && cur->flags & SA_INTERRUPT) { | |
158 | list = &cur->next; | |
159 | cur = cur->next; | |
160 | } | |
161 | } else { | |
162 | while (cur) { | |
163 | list = &cur->next; | |
164 | cur = cur->next; | |
165 | } | |
166 | } | |
167 | ||
168 | node->next = cur; | |
169 | *list = node; | |
170 | ||
171 | local_irq_restore(flags); | |
172 | return 0; | |
173 | } | |
174 | ||
175 | static inline void amiga_delete_irq(irq_node_t **list, void *dev_id) | |
176 | { | |
177 | unsigned long flags; | |
178 | irq_node_t *node; | |
179 | ||
180 | local_irq_save(flags); | |
181 | ||
182 | for (node = *list; node; list = &node->next, node = *list) { | |
183 | if (node->dev_id == dev_id) { | |
184 | *list = node->next; | |
185 | /* Mark it as free. */ | |
186 | node->handler = NULL; | |
187 | local_irq_restore(flags); | |
188 | return; | |
189 | } | |
190 | } | |
191 | local_irq_restore(flags); | |
192 | printk ("%s: tried to remove invalid irq\n", __FUNCTION__); | |
193 | } | |
194 | ||
195 | /* | |
196 | * amiga_request_irq : add an interrupt service routine for a particular | |
197 | * machine specific interrupt source. | |
198 | * If the addition was successful, it returns 0. | |
199 | */ | |
200 | ||
201 | int amiga_request_irq(unsigned int irq, | |
202 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | |
203 | unsigned long flags, const char *devname, void *dev_id) | |
204 | { | |
205 | irq_node_t *node; | |
206 | int error = 0; | |
207 | ||
208 | if (irq >= AMI_IRQS) { | |
209 | printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, | |
210 | irq, devname); | |
211 | return -ENXIO; | |
212 | } | |
213 | ||
1d174cfb RZ |
214 | if (irq < IRQ_USER) |
215 | return cpu_request_irq(irq, handler, flags, devname, dev_id); | |
1da177e4 LT |
216 | |
217 | if (irq >= IRQ_AMIGA_CIAB) | |
218 | return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, | |
219 | handler, flags, devname, dev_id); | |
220 | ||
221 | if (irq >= IRQ_AMIGA_CIAA) | |
222 | return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, | |
223 | handler, flags, devname, dev_id); | |
224 | ||
1d174cfb | 225 | irq -= IRQ_USER; |
1da177e4 LT |
226 | /* |
227 | * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared, | |
228 | * we could add a check here for the SA_SHIRQ flag but all drivers | |
229 | * should be aware of sharing anyway. | |
230 | */ | |
231 | if (ami_servers[irq]) { | |
232 | if (!(node = new_irq_node())) | |
233 | return -ENOMEM; | |
234 | node->handler = handler; | |
235 | node->flags = flags; | |
236 | node->dev_id = dev_id; | |
237 | node->devname = devname; | |
238 | node->next = NULL; | |
239 | error = amiga_insert_irq(&ami_irq_list[irq], node); | |
240 | } else { | |
241 | ami_irq_list[irq]->handler = handler; | |
242 | ami_irq_list[irq]->flags = flags; | |
243 | ami_irq_list[irq]->dev_id = dev_id; | |
244 | ami_irq_list[irq]->devname = devname; | |
245 | } | |
246 | ||
247 | /* enable the interrupt */ | |
248 | if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) | |
b4290a23 | 249 | amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; |
1da177e4 LT |
250 | |
251 | return error; | |
252 | } | |
253 | ||
254 | void amiga_free_irq(unsigned int irq, void *dev_id) | |
255 | { | |
256 | if (irq >= AMI_IRQS) { | |
257 | printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); | |
258 | return; | |
259 | } | |
260 | ||
1d174cfb RZ |
261 | if (irq < IRQ_USER) |
262 | cpu_free_irq(irq, dev_id); | |
1da177e4 LT |
263 | |
264 | if (irq >= IRQ_AMIGA_CIAB) { | |
265 | cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id); | |
266 | return; | |
267 | } | |
268 | ||
269 | if (irq >= IRQ_AMIGA_CIAA) { | |
270 | cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id); | |
271 | return; | |
272 | } | |
273 | ||
1d174cfb | 274 | irq -= IRQ_USER; |
1da177e4 LT |
275 | if (ami_servers[irq]) { |
276 | amiga_delete_irq(&ami_irq_list[irq], dev_id); | |
277 | /* if server list empty, disable the interrupt */ | |
278 | if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) | |
b4290a23 | 279 | amiga_custom.intena = amiga_intena_vals[irq]; |
1da177e4 LT |
280 | } else { |
281 | if (ami_irq_list[irq]->dev_id != dev_id) | |
282 | printk("%s: removing probably wrong IRQ %d from %s\n", | |
283 | __FUNCTION__, irq, ami_irq_list[irq]->devname); | |
284 | ami_irq_list[irq]->handler = ami_badint; | |
285 | ami_irq_list[irq]->flags = 0; | |
286 | ami_irq_list[irq]->dev_id = NULL; | |
287 | ami_irq_list[irq]->devname = NULL; | |
b4290a23 | 288 | amiga_custom.intena = amiga_intena_vals[irq]; |
1da177e4 LT |
289 | } |
290 | } | |
291 | ||
292 | /* | |
293 | * Enable/disable a particular machine specific interrupt source. | |
294 | * Note that this may affect other interrupts in case of a shared interrupt. | |
295 | * This function should only be called for a _very_ short time to change some | |
296 | * internal data, that may not be changed by the interrupt at the same time. | |
297 | * ami_(enable|disable)_irq calls may also be nested. | |
298 | */ | |
299 | ||
300 | void amiga_enable_irq(unsigned int irq) | |
301 | { | |
302 | if (irq >= AMI_IRQS) { | |
303 | printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); | |
304 | return; | |
305 | } | |
306 | ||
307 | if (--ami_ablecount[irq]) | |
308 | return; | |
309 | ||
310 | /* No action for auto-vector interrupts */ | |
1d174cfb | 311 | if (irq < IRQ_USER) { |
1da177e4 | 312 | printk("%s: Trying to enable auto-vector IRQ %i\n", |
1d174cfb | 313 | __FUNCTION__, irq); |
1da177e4 LT |
314 | return; |
315 | } | |
316 | ||
317 | if (irq >= IRQ_AMIGA_CIAB) { | |
318 | cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB))); | |
319 | cia_able_irq(&ciab_base, CIA_ICR_SETCLR | | |
320 | (1 << (irq - IRQ_AMIGA_CIAB))); | |
321 | return; | |
322 | } | |
323 | ||
324 | if (irq >= IRQ_AMIGA_CIAA) { | |
325 | cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA))); | |
326 | cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | | |
327 | (1 << (irq - IRQ_AMIGA_CIAA))); | |
328 | return; | |
329 | } | |
330 | ||
331 | /* enable the interrupt */ | |
1d174cfb | 332 | amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq-IRQ_USER]; |
1da177e4 LT |
333 | } |
334 | ||
335 | void amiga_disable_irq(unsigned int irq) | |
336 | { | |
337 | if (irq >= AMI_IRQS) { | |
338 | printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); | |
339 | return; | |
340 | } | |
341 | ||
342 | if (ami_ablecount[irq]++) | |
343 | return; | |
344 | ||
345 | /* No action for auto-vector interrupts */ | |
1d174cfb | 346 | if (irq < IRQ_USER) { |
1da177e4 | 347 | printk("%s: Trying to disable auto-vector IRQ %i\n", |
1d174cfb | 348 | __FUNCTION__, irq); |
1da177e4 LT |
349 | return; |
350 | } | |
351 | ||
352 | if (irq >= IRQ_AMIGA_CIAB) { | |
353 | cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); | |
354 | return; | |
355 | } | |
356 | ||
357 | if (irq >= IRQ_AMIGA_CIAA) { | |
358 | cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); | |
359 | return; | |
360 | } | |
361 | ||
362 | /* disable the interrupt */ | |
1d174cfb | 363 | amiga_custom.intena = amiga_intena_vals[irq-IRQ_USER]; |
1da177e4 LT |
364 | } |
365 | ||
366 | inline void amiga_do_irq(int irq, struct pt_regs *fp) | |
367 | { | |
1d174cfb RZ |
368 | kstat_cpu(0).irqs[irq]++; |
369 | ami_irq_list[irq-IRQ_USER]->handler(irq, ami_irq_list[irq-IRQ_USER]->dev_id, fp); | |
1da177e4 LT |
370 | } |
371 | ||
372 | void amiga_do_irq_list(int irq, struct pt_regs *fp) | |
373 | { | |
374 | irq_node_t *node; | |
375 | ||
1d174cfb | 376 | kstat_cpu(0).irqs[irq]++; |
1da177e4 | 377 | |
1d174cfb | 378 | amiga_custom.intreq = amiga_intena_vals[irq-IRQ_USER]; |
1da177e4 | 379 | |
1d174cfb | 380 | for (node = ami_irq_list[irq-IRQ_USER]; node; node = node->next) |
1da177e4 LT |
381 | node->handler(irq, node->dev_id, fp); |
382 | } | |
383 | ||
384 | /* | |
385 | * The builtin Amiga hardware interrupt handlers. | |
386 | */ | |
387 | ||
388 | static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp) | |
389 | { | |
b4290a23 | 390 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
1da177e4 LT |
391 | |
392 | /* if serial transmit buffer empty, interrupt */ | |
393 | if (ints & IF_TBE) { | |
b4290a23 | 394 | amiga_custom.intreq = IF_TBE; |
1da177e4 LT |
395 | amiga_do_irq(IRQ_AMIGA_TBE, fp); |
396 | } | |
397 | ||
398 | /* if floppy disk transfer complete, interrupt */ | |
399 | if (ints & IF_DSKBLK) { | |
b4290a23 | 400 | amiga_custom.intreq = IF_DSKBLK; |
1da177e4 LT |
401 | amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); |
402 | } | |
403 | ||
404 | /* if software interrupt set, interrupt */ | |
405 | if (ints & IF_SOFT) { | |
b4290a23 | 406 | amiga_custom.intreq = IF_SOFT; |
1da177e4 LT |
407 | amiga_do_irq(IRQ_AMIGA_SOFT, fp); |
408 | } | |
409 | return IRQ_HANDLED; | |
410 | } | |
411 | ||
412 | static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp) | |
413 | { | |
b4290a23 | 414 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
1da177e4 LT |
415 | |
416 | /* if a blitter interrupt */ | |
417 | if (ints & IF_BLIT) { | |
b4290a23 | 418 | amiga_custom.intreq = IF_BLIT; |
1da177e4 LT |
419 | amiga_do_irq(IRQ_AMIGA_BLIT, fp); |
420 | } | |
421 | ||
422 | /* if a copper interrupt */ | |
423 | if (ints & IF_COPER) { | |
b4290a23 | 424 | amiga_custom.intreq = IF_COPER; |
1da177e4 LT |
425 | amiga_do_irq(IRQ_AMIGA_COPPER, fp); |
426 | } | |
427 | ||
428 | /* if a vertical blank interrupt */ | |
429 | if (ints & IF_VERTB) | |
430 | amiga_do_irq_list(IRQ_AMIGA_VERTB, fp); | |
431 | return IRQ_HANDLED; | |
432 | } | |
433 | ||
434 | static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp) | |
435 | { | |
b4290a23 | 436 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
1da177e4 LT |
437 | |
438 | /* if audio 0 interrupt */ | |
439 | if (ints & IF_AUD0) { | |
b4290a23 | 440 | amiga_custom.intreq = IF_AUD0; |
1da177e4 LT |
441 | amiga_do_irq(IRQ_AMIGA_AUD0, fp); |
442 | } | |
443 | ||
444 | /* if audio 1 interrupt */ | |
445 | if (ints & IF_AUD1) { | |
b4290a23 | 446 | amiga_custom.intreq = IF_AUD1; |
1da177e4 LT |
447 | amiga_do_irq(IRQ_AMIGA_AUD1, fp); |
448 | } | |
449 | ||
450 | /* if audio 2 interrupt */ | |
451 | if (ints & IF_AUD2) { | |
b4290a23 | 452 | amiga_custom.intreq = IF_AUD2; |
1da177e4 LT |
453 | amiga_do_irq(IRQ_AMIGA_AUD2, fp); |
454 | } | |
455 | ||
456 | /* if audio 3 interrupt */ | |
457 | if (ints & IF_AUD3) { | |
b4290a23 | 458 | amiga_custom.intreq = IF_AUD3; |
1da177e4 LT |
459 | amiga_do_irq(IRQ_AMIGA_AUD3, fp); |
460 | } | |
461 | return IRQ_HANDLED; | |
462 | } | |
463 | ||
464 | static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp) | |
465 | { | |
b4290a23 | 466 | unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; |
1da177e4 LT |
467 | |
468 | /* if serial receive buffer full interrupt */ | |
469 | if (ints & IF_RBF) { | |
470 | /* acknowledge of IF_RBF must be done by the serial interrupt */ | |
471 | amiga_do_irq(IRQ_AMIGA_RBF, fp); | |
472 | } | |
473 | ||
474 | /* if a disk sync interrupt */ | |
475 | if (ints & IF_DSKSYN) { | |
b4290a23 | 476 | amiga_custom.intreq = IF_DSKSYN; |
1da177e4 LT |
477 | amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); |
478 | } | |
479 | return IRQ_HANDLED; | |
480 | } | |
481 | ||
482 | static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp) | |
483 | { | |
484 | panic ("level 7 interrupt received\n"); | |
485 | } | |
486 | ||
487 | irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { | |
1da177e4 | 488 | [1] = ami_int1, |
1da177e4 LT |
489 | [3] = ami_int3, |
490 | [4] = ami_int4, | |
491 | [5] = ami_int5, | |
1da177e4 LT |
492 | [7] = ami_int7 |
493 | }; | |
494 | ||
495 | int show_amiga_interrupts(struct seq_file *p, void *v) | |
496 | { | |
497 | int i; | |
498 | irq_node_t *node; | |
499 | ||
1d174cfb RZ |
500 | for (i = IRQ_USER; i < IRQ_AMIGA_CIAA; i++) { |
501 | node = ami_irq_list[i - IRQ_USER]; | |
502 | if (!node) | |
1da177e4 LT |
503 | continue; |
504 | seq_printf(p, "ami %2d: %10u ", i, | |
1d174cfb | 505 | kstat_cpu(0).irqs[i]); |
1da177e4 LT |
506 | do { |
507 | if (node->flags & SA_INTERRUPT) | |
508 | seq_puts(p, "F "); | |
509 | else | |
510 | seq_puts(p, " "); | |
511 | seq_printf(p, "%s\n", node->devname); | |
512 | if ((node = node->next)) | |
513 | seq_puts(p, " "); | |
514 | } while (node); | |
515 | } | |
516 | ||
517 | cia_get_irq_list(&ciaa_base, p); | |
518 | cia_get_irq_list(&ciab_base, p); | |
519 | return 0; | |
520 | } |