amiints.c (1da177e4c3f41524e886b7f1b8a0c1fc7321cac2) amiints.c (b4290a23cfa9040e2f0de5ab57d6ea65abaf053b)
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

--- 112 unchanged lines hidden (view full) ---

121 for (i = 0; i < AMI_IRQS; i++)
122 ami_ablecount[i] = 0;
123
124 /* turn off PCMCIA interrupts */
125 if (AMIGAHW_PRESENT(PCMCIA))
126 gayle.inten = GAYLE_IRQ_IDE;
127
128 /* turn off all interrupts and enable the master interrupt bit */
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

--- 112 unchanged lines hidden (view full) ---

121 for (i = 0; i < AMI_IRQS; i++)
122 ami_ablecount[i] = 0;
123
124 /* turn off PCMCIA interrupts */
125 if (AMIGAHW_PRESENT(PCMCIA))
126 gayle.inten = GAYLE_IRQ_IDE;
127
128 /* turn off all interrupts and enable the master interrupt bit */
129 custom.intena = 0x7fff;
130 custom.intreq = 0x7fff;
131 custom.intena = IF_SETCLR | IF_INTEN;
129 amiga_custom.intena = 0x7fff;
130 amiga_custom.intreq = 0x7fff;
131 amiga_custom.intena = IF_SETCLR | IF_INTEN;
132
133 cia_init_IRQ(&ciaa_base);
134 cia_init_IRQ(&ciab_base);
135}
136
137static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
138{
139 unsigned long flags;

--- 100 unchanged lines hidden (view full) ---

240 ami_irq_list[irq]->handler = handler;
241 ami_irq_list[irq]->flags = flags;
242 ami_irq_list[irq]->dev_id = dev_id;
243 ami_irq_list[irq]->devname = devname;
244 }
245
246 /* enable the interrupt */
247 if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
132
133 cia_init_IRQ(&ciaa_base);
134 cia_init_IRQ(&ciab_base);
135}
136
137static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
138{
139 unsigned long flags;

--- 100 unchanged lines hidden (view full) ---

240 ami_irq_list[irq]->handler = handler;
241 ami_irq_list[irq]->flags = flags;
242 ami_irq_list[irq]->dev_id = dev_id;
243 ami_irq_list[irq]->devname = devname;
244 }
245
246 /* enable the interrupt */
247 if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
248 custom.intena = IF_SETCLR | amiga_intena_vals[irq];
248 amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
249
250 return error;
251}
252
253void amiga_free_irq(unsigned int irq, void *dev_id)
254{
255 if (irq >= AMI_IRQS) {
256 printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);

--- 12 unchanged lines hidden (view full) ---

269 cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
270 return;
271 }
272
273 if (ami_servers[irq]) {
274 amiga_delete_irq(&ami_irq_list[irq], dev_id);
275 /* if server list empty, disable the interrupt */
276 if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
249
250 return error;
251}
252
253void amiga_free_irq(unsigned int irq, void *dev_id)
254{
255 if (irq >= AMI_IRQS) {
256 printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);

--- 12 unchanged lines hidden (view full) ---

269 cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
270 return;
271 }
272
273 if (ami_servers[irq]) {
274 amiga_delete_irq(&ami_irq_list[irq], dev_id);
275 /* if server list empty, disable the interrupt */
276 if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
277 custom.intena = amiga_intena_vals[irq];
277 amiga_custom.intena = amiga_intena_vals[irq];
278 } else {
279 if (ami_irq_list[irq]->dev_id != dev_id)
280 printk("%s: removing probably wrong IRQ %d from %s\n",
281 __FUNCTION__, irq, ami_irq_list[irq]->devname);
282 ami_irq_list[irq]->handler = ami_badint;
283 ami_irq_list[irq]->flags = 0;
284 ami_irq_list[irq]->dev_id = NULL;
285 ami_irq_list[irq]->devname = NULL;
278 } else {
279 if (ami_irq_list[irq]->dev_id != dev_id)
280 printk("%s: removing probably wrong IRQ %d from %s\n",
281 __FUNCTION__, irq, ami_irq_list[irq]->devname);
282 ami_irq_list[irq]->handler = ami_badint;
283 ami_irq_list[irq]->flags = 0;
284 ami_irq_list[irq]->dev_id = NULL;
285 ami_irq_list[irq]->devname = NULL;
286 custom.intena = amiga_intena_vals[irq];
286 amiga_custom.intena = amiga_intena_vals[irq];
287 }
288}
289
290/*
291 * Enable/disable a particular machine specific interrupt source.
292 * Note that this may affect other interrupts in case of a shared interrupt.
293 * This function should only be called for a _very_ short time to change some
294 * internal data, that may not be changed by the interrupt at the same time.

--- 27 unchanged lines hidden (view full) ---

322 if (irq >= IRQ_AMIGA_CIAA) {
323 cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA)));
324 cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
325 (1 << (irq - IRQ_AMIGA_CIAA)));
326 return;
327 }
328
329 /* enable the interrupt */
287 }
288}
289
290/*
291 * Enable/disable a particular machine specific interrupt source.
292 * Note that this may affect other interrupts in case of a shared interrupt.
293 * This function should only be called for a _very_ short time to change some
294 * internal data, that may not be changed by the interrupt at the same time.

--- 27 unchanged lines hidden (view full) ---

322 if (irq >= IRQ_AMIGA_CIAA) {
323 cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA)));
324 cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
325 (1 << (irq - IRQ_AMIGA_CIAA)));
326 return;
327 }
328
329 /* enable the interrupt */
330 custom.intena = IF_SETCLR | amiga_intena_vals[irq];
330 amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
331}
332
333void amiga_disable_irq(unsigned int irq)
334{
335 if (irq >= AMI_IRQS) {
336 printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
337 return;
338 }

--- 14 unchanged lines hidden (view full) ---

353 }
354
355 if (irq >= IRQ_AMIGA_CIAA) {
356 cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
357 return;
358 }
359
360 /* disable the interrupt */
331}
332
333void amiga_disable_irq(unsigned int irq)
334{
335 if (irq >= AMI_IRQS) {
336 printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
337 return;
338 }

--- 14 unchanged lines hidden (view full) ---

353 }
354
355 if (irq >= IRQ_AMIGA_CIAA) {
356 cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
357 return;
358 }
359
360 /* disable the interrupt */
361 custom.intena = amiga_intena_vals[irq];
361 amiga_custom.intena = amiga_intena_vals[irq];
362}
363
364inline void amiga_do_irq(int irq, struct pt_regs *fp)
365{
366 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
367 ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
368}
369
370void amiga_do_irq_list(int irq, struct pt_regs *fp)
371{
372 irq_node_t *node;
373
374 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
375
362}
363
364inline void amiga_do_irq(int irq, struct pt_regs *fp)
365{
366 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
367 ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
368}
369
370void amiga_do_irq_list(int irq, struct pt_regs *fp)
371{
372 irq_node_t *node;
373
374 kstat_cpu(0).irqs[SYS_IRQS + irq]++;
375
376 custom.intreq = amiga_intena_vals[irq];
376 amiga_custom.intreq = amiga_intena_vals[irq];
377
378 for (node = ami_irq_list[irq]; node; node = node->next)
379 node->handler(irq, node->dev_id, fp);
380}
381
382/*
383 * The builtin Amiga hardware interrupt handlers.
384 */
385
386static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
387{
377
378 for (node = ami_irq_list[irq]; node; node = node->next)
379 node->handler(irq, node->dev_id, fp);
380}
381
382/*
383 * The builtin Amiga hardware interrupt handlers.
384 */
385
386static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
387{
388 unsigned short ints = custom.intreqr & custom.intenar;
388 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
389
390 /* if serial transmit buffer empty, interrupt */
391 if (ints & IF_TBE) {
389
390 /* if serial transmit buffer empty, interrupt */
391 if (ints & IF_TBE) {
392 custom.intreq = IF_TBE;
392 amiga_custom.intreq = IF_TBE;
393 amiga_do_irq(IRQ_AMIGA_TBE, fp);
394 }
395
396 /* if floppy disk transfer complete, interrupt */
397 if (ints & IF_DSKBLK) {
393 amiga_do_irq(IRQ_AMIGA_TBE, fp);
394 }
395
396 /* if floppy disk transfer complete, interrupt */
397 if (ints & IF_DSKBLK) {
398 custom.intreq = IF_DSKBLK;
398 amiga_custom.intreq = IF_DSKBLK;
399 amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
400 }
401
402 /* if software interrupt set, interrupt */
403 if (ints & IF_SOFT) {
399 amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
400 }
401
402 /* if software interrupt set, interrupt */
403 if (ints & IF_SOFT) {
404 custom.intreq = IF_SOFT;
404 amiga_custom.intreq = IF_SOFT;
405 amiga_do_irq(IRQ_AMIGA_SOFT, fp);
406 }
407 return IRQ_HANDLED;
408}
409
410static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
411{
405 amiga_do_irq(IRQ_AMIGA_SOFT, fp);
406 }
407 return IRQ_HANDLED;
408}
409
410static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
411{
412 unsigned short ints = custom.intreqr & custom.intenar;
412 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
413
414 /* if a blitter interrupt */
415 if (ints & IF_BLIT) {
413
414 /* if a blitter interrupt */
415 if (ints & IF_BLIT) {
416 custom.intreq = IF_BLIT;
416 amiga_custom.intreq = IF_BLIT;
417 amiga_do_irq(IRQ_AMIGA_BLIT, fp);
418 }
419
420 /* if a copper interrupt */
421 if (ints & IF_COPER) {
417 amiga_do_irq(IRQ_AMIGA_BLIT, fp);
418 }
419
420 /* if a copper interrupt */
421 if (ints & IF_COPER) {
422 custom.intreq = IF_COPER;
422 amiga_custom.intreq = IF_COPER;
423 amiga_do_irq(IRQ_AMIGA_COPPER, fp);
424 }
425
426 /* if a vertical blank interrupt */
427 if (ints & IF_VERTB)
428 amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
429 return IRQ_HANDLED;
430}
431
432static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
433{
423 amiga_do_irq(IRQ_AMIGA_COPPER, fp);
424 }
425
426 /* if a vertical blank interrupt */
427 if (ints & IF_VERTB)
428 amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
429 return IRQ_HANDLED;
430}
431
432static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
433{
434 unsigned short ints = custom.intreqr & custom.intenar;
434 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
435
436 /* if audio 0 interrupt */
437 if (ints & IF_AUD0) {
435
436 /* if audio 0 interrupt */
437 if (ints & IF_AUD0) {
438 custom.intreq = IF_AUD0;
438 amiga_custom.intreq = IF_AUD0;
439 amiga_do_irq(IRQ_AMIGA_AUD0, fp);
440 }
441
442 /* if audio 1 interrupt */
443 if (ints & IF_AUD1) {
439 amiga_do_irq(IRQ_AMIGA_AUD0, fp);
440 }
441
442 /* if audio 1 interrupt */
443 if (ints & IF_AUD1) {
444 custom.intreq = IF_AUD1;
444 amiga_custom.intreq = IF_AUD1;
445 amiga_do_irq(IRQ_AMIGA_AUD1, fp);
446 }
447
448 /* if audio 2 interrupt */
449 if (ints & IF_AUD2) {
445 amiga_do_irq(IRQ_AMIGA_AUD1, fp);
446 }
447
448 /* if audio 2 interrupt */
449 if (ints & IF_AUD2) {
450 custom.intreq = IF_AUD2;
450 amiga_custom.intreq = IF_AUD2;
451 amiga_do_irq(IRQ_AMIGA_AUD2, fp);
452 }
453
454 /* if audio 3 interrupt */
455 if (ints & IF_AUD3) {
451 amiga_do_irq(IRQ_AMIGA_AUD2, fp);
452 }
453
454 /* if audio 3 interrupt */
455 if (ints & IF_AUD3) {
456 custom.intreq = IF_AUD3;
456 amiga_custom.intreq = IF_AUD3;
457 amiga_do_irq(IRQ_AMIGA_AUD3, fp);
458 }
459 return IRQ_HANDLED;
460}
461
462static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
463{
457 amiga_do_irq(IRQ_AMIGA_AUD3, fp);
458 }
459 return IRQ_HANDLED;
460}
461
462static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
463{
464 unsigned short ints = custom.intreqr & custom.intenar;
464 unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
465
466 /* if serial receive buffer full interrupt */
467 if (ints & IF_RBF) {
468 /* acknowledge of IF_RBF must be done by the serial interrupt */
469 amiga_do_irq(IRQ_AMIGA_RBF, fp);
470 }
471
472 /* if a disk sync interrupt */
473 if (ints & IF_DSKSYN) {
465
466 /* if serial receive buffer full interrupt */
467 if (ints & IF_RBF) {
468 /* acknowledge of IF_RBF must be done by the serial interrupt */
469 amiga_do_irq(IRQ_AMIGA_RBF, fp);
470 }
471
472 /* if a disk sync interrupt */
473 if (ints & IF_DSKSYN) {
474 custom.intreq = IF_DSKSYN;
474 amiga_custom.intreq = IF_DSKSYN;
475 amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
476 }
477 return IRQ_HANDLED;
478}
479
480static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp)
481{
482 panic ("level 7 interrupt received\n");

--- 38 unchanged lines hidden ---
475 amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
476 }
477 return IRQ_HANDLED;
478}
479
480static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp)
481{
482 panic ("level 7 interrupt received\n");

--- 38 unchanged lines hidden ---