diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2006-06-25 08:47:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:00:57 -0400 |
commit | 734085651c9b80aa3f9e6027b156102de214a0b2 (patch) | |
tree | a3f8c691b0c0298307784fc7e55b6c3c68812a0b /arch/m68k/atari/ataints.c | |
parent | 0aa78106c661cf6c251fd56e92f0c76a7459d244 (diff) |
[PATCH] m68k: convert atari irq code
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/m68k/atari/ataints.c')
-rw-r--r-- | arch/m68k/atari/ataints.c | 278 |
1 files changed, 42 insertions, 236 deletions
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index bb54741dd6cd..ece13cbf9950 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c | |||
@@ -104,6 +104,7 @@ | |||
104 | * the sr copy in the frame. | 104 | * the sr copy in the frame. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | #if 0 | ||
107 | 108 | ||
108 | #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES) | 109 | #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES) |
109 | 110 | ||
@@ -133,13 +134,6 @@ static struct irqhandler irq_handler[NUM_INT_SOURCES]; | |||
133 | */ | 134 | */ |
134 | static struct irqparam irq_param[NUM_INT_SOURCES]; | 135 | static struct irqparam irq_param[NUM_INT_SOURCES]; |
135 | 136 | ||
136 | /* | ||
137 | * Bitmap for free interrupt vector numbers | ||
138 | * (new vectors starting from 0x70 can be allocated by | ||
139 | * atari_register_vme_int()) | ||
140 | */ | ||
141 | static int free_vme_vec_bitmap; | ||
142 | |||
143 | /* check for valid int number (complex, sigh...) */ | 137 | /* check for valid int number (complex, sigh...) */ |
144 | #define IS_VALID_INTNO(n) \ | 138 | #define IS_VALID_INTNO(n) \ |
145 | ((n) > 0 && \ | 139 | ((n) > 0 && \ |
@@ -301,6 +295,14 @@ __asm__ (__ALIGN_STR "\n" | |||
301 | ); | 295 | ); |
302 | for (;;); | 296 | for (;;); |
303 | } | 297 | } |
298 | #endif | ||
299 | |||
300 | /* | ||
301 | * Bitmap for free interrupt vector numbers | ||
302 | * (new vectors starting from 0x70 can be allocated by | ||
303 | * atari_register_vme_int()) | ||
304 | */ | ||
305 | static int free_vme_vec_bitmap; | ||
304 | 306 | ||
305 | /* GK: | 307 | /* GK: |
306 | * HBL IRQ handler for Falcon. Nobody needs it :-) | 308 | * HBL IRQ handler for Falcon. Nobody needs it :-) |
@@ -313,13 +315,34 @@ __ALIGN_STR "\n\t" | |||
313 | "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ | 315 | "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ |
314 | "rte"); | 316 | "rte"); |
315 | 317 | ||
316 | /* Defined in entry.S; only increments 'num_spurious' */ | 318 | extern void atari_microwire_cmd(int cmd); |
317 | asmlinkage void bad_inthandler(void); | ||
318 | |||
319 | extern void atari_microwire_cmd( int cmd ); | ||
320 | 319 | ||
321 | extern int atari_SCC_reset_done; | 320 | extern int atari_SCC_reset_done; |
322 | 321 | ||
322 | static int atari_startup_irq(unsigned int irq) | ||
323 | { | ||
324 | m68k_irq_startup(irq); | ||
325 | atari_turnon_irq(irq); | ||
326 | atari_enable_irq(irq); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static void atari_shutdown_irq(unsigned int irq) | ||
331 | { | ||
332 | atari_disable_irq(irq); | ||
333 | atari_turnoff_irq(irq); | ||
334 | m68k_irq_shutdown(irq); | ||
335 | } | ||
336 | |||
337 | static struct irq_controller atari_irq_controller = { | ||
338 | .name = "atari", | ||
339 | .lock = SPIN_LOCK_UNLOCKED, | ||
340 | .startup = atari_startup_irq, | ||
341 | .shutdown = atari_shutdown_irq, | ||
342 | .enable = atari_enable_irq, | ||
343 | .disable = atari_disable_irq, | ||
344 | }; | ||
345 | |||
323 | /* | 346 | /* |
324 | * void atari_init_IRQ (void) | 347 | * void atari_init_IRQ (void) |
325 | * | 348 | * |
@@ -333,12 +356,8 @@ extern int atari_SCC_reset_done; | |||
333 | 356 | ||
334 | void __init atari_init_IRQ(void) | 357 | void __init atari_init_IRQ(void) |
335 | { | 358 | { |
336 | int i; | 359 | m68k_setup_user_interrupt(VEC_USER, 192, NULL); |
337 | 360 | m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1); | |
338 | /* initialize the vector table */ | ||
339 | for (i = 0; i < NUM_INT_SOURCES; ++i) { | ||
340 | vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_inthandler; | ||
341 | } | ||
342 | 361 | ||
343 | /* Initialize the MFP(s) */ | 362 | /* Initialize the MFP(s) */ |
344 | 363 | ||
@@ -378,8 +397,7 @@ void __init atari_init_IRQ(void) | |||
378 | * enabled in VME mask | 397 | * enabled in VME mask |
379 | */ | 398 | */ |
380 | tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ | 399 | tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ |
381 | } | 400 | } else { |
382 | else { | ||
383 | /* If no SCU and no Hades, the HSYNC interrupt needs to be | 401 | /* If no SCU and no Hades, the HSYNC interrupt needs to be |
384 | * disabled this way. (Else _inthandler in kernel/sys_call.S | 402 | * disabled this way. (Else _inthandler in kernel/sys_call.S |
385 | * gets overruns) | 403 | * gets overruns) |
@@ -404,184 +422,6 @@ void __init atari_init_IRQ(void) | |||
404 | } | 422 | } |
405 | 423 | ||
406 | 424 | ||
407 | static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp ) | ||
408 | { | ||
409 | irq_node_t *node; | ||
410 | |||
411 | for (node = (irq_node_t *)dev_id; node; node = node->next) | ||
412 | node->handler(irq, node->dev_id, fp); | ||
413 | return IRQ_HANDLED; | ||
414 | } | ||
415 | |||
416 | |||
417 | /* | ||
418 | * atari_request_irq : add an interrupt service routine for a particular | ||
419 | * machine specific interrupt source. | ||
420 | * If the addition was successful, it returns 0. | ||
421 | */ | ||
422 | |||
423 | int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
424 | unsigned long flags, const char *devname, void *dev_id) | ||
425 | { | ||
426 | int vector; | ||
427 | unsigned long oflags = flags; | ||
428 | |||
429 | /* | ||
430 | * The following is a hack to make some PCI card drivers work, | ||
431 | * which set the SA_SHIRQ flag. | ||
432 | */ | ||
433 | |||
434 | flags &= ~SA_SHIRQ; | ||
435 | |||
436 | if (flags == SA_INTERRUPT) { | ||
437 | printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n", | ||
438 | __FUNCTION__, devname); | ||
439 | flags = IRQ_TYPE_SLOW; | ||
440 | } | ||
441 | if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) { | ||
442 | printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n", | ||
443 | __FUNCTION__, flags, oflags, devname); | ||
444 | return -EINVAL; | ||
445 | } | ||
446 | if (!IS_VALID_INTNO(irq)) { | ||
447 | printk ("%s: Unknown irq %d requested from %s\n", | ||
448 | __FUNCTION__, irq, devname); | ||
449 | return -ENXIO; | ||
450 | } | ||
451 | vector = IRQ_SOURCE_TO_VECTOR(irq); | ||
452 | |||
453 | /* | ||
454 | * Check type/source combination: slow ints are (currently) | ||
455 | * only possible for MFP-interrupts. | ||
456 | */ | ||
457 | if (flags == IRQ_TYPE_SLOW && | ||
458 | (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) { | ||
459 | printk ("%s: Slow irq requested for non-MFP source %d from %s\n", | ||
460 | __FUNCTION__, irq, devname); | ||
461 | return -EINVAL; | ||
462 | } | ||
463 | |||
464 | if (vectors[vector] == bad_inthandler) { | ||
465 | /* int has no handler yet */ | ||
466 | irq_handler[irq].handler = handler; | ||
467 | irq_handler[irq].dev_id = dev_id; | ||
468 | irq_param[irq].flags = flags; | ||
469 | irq_param[irq].devname = devname; | ||
470 | vectors[vector] = | ||
471 | (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] : | ||
472 | (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler : | ||
473 | atari_prio_irq_handler; | ||
474 | /* If MFP int, also enable and umask it */ | ||
475 | atari_turnon_irq(irq); | ||
476 | atari_enable_irq(irq); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | else if (irq_param[irq].flags == flags) { | ||
481 | /* old handler is of same type -> handlers can be chained */ | ||
482 | irq_node_t *node; | ||
483 | unsigned long flags; | ||
484 | |||
485 | local_irq_save(flags); | ||
486 | |||
487 | if (irq_handler[irq].handler != atari_call_irq_list) { | ||
488 | /* Only one handler yet, make a node for this first one */ | ||
489 | if (!(node = new_irq_node())) | ||
490 | return -ENOMEM; | ||
491 | node->handler = irq_handler[irq].handler; | ||
492 | node->dev_id = irq_handler[irq].dev_id; | ||
493 | node->devname = irq_param[irq].devname; | ||
494 | node->next = NULL; | ||
495 | |||
496 | irq_handler[irq].handler = atari_call_irq_list; | ||
497 | irq_handler[irq].dev_id = node; | ||
498 | irq_param[irq].devname = "chained"; | ||
499 | } | ||
500 | |||
501 | if (!(node = new_irq_node())) | ||
502 | return -ENOMEM; | ||
503 | node->handler = handler; | ||
504 | node->dev_id = dev_id; | ||
505 | node->devname = devname; | ||
506 | /* new handlers are put in front of the queue */ | ||
507 | node->next = irq_handler[irq].dev_id; | ||
508 | irq_handler[irq].dev_id = node; | ||
509 | |||
510 | local_irq_restore(flags); | ||
511 | return 0; | ||
512 | } else { | ||
513 | printk ("%s: Irq %d allocated by other type int (call from %s)\n", | ||
514 | __FUNCTION__, irq, devname); | ||
515 | return -EBUSY; | ||
516 | } | ||
517 | } | ||
518 | |||
519 | void atari_free_irq(unsigned int irq, void *dev_id) | ||
520 | { | ||
521 | unsigned long flags; | ||
522 | int vector; | ||
523 | irq_node_t **list, *node; | ||
524 | |||
525 | if (!IS_VALID_INTNO(irq)) { | ||
526 | printk("%s: Unknown irq %d\n", __FUNCTION__, irq); | ||
527 | return; | ||
528 | } | ||
529 | |||
530 | vector = IRQ_SOURCE_TO_VECTOR(irq); | ||
531 | if (vectors[vector] == bad_inthandler) | ||
532 | goto not_found; | ||
533 | |||
534 | local_irq_save(flags); | ||
535 | |||
536 | if (irq_handler[irq].handler != atari_call_irq_list) { | ||
537 | /* It's the only handler for the interrupt */ | ||
538 | if (irq_handler[irq].dev_id != dev_id) { | ||
539 | local_irq_restore(flags); | ||
540 | goto not_found; | ||
541 | } | ||
542 | irq_handler[irq].handler = NULL; | ||
543 | irq_handler[irq].dev_id = NULL; | ||
544 | irq_param[irq].devname = NULL; | ||
545 | vectors[vector] = bad_inthandler; | ||
546 | /* If MFP int, also disable it */ | ||
547 | atari_disable_irq(irq); | ||
548 | atari_turnoff_irq(irq); | ||
549 | |||
550 | local_irq_restore(flags); | ||
551 | return; | ||
552 | } | ||
553 | |||
554 | /* The interrupt is chained, find the irq on the list */ | ||
555 | for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) { | ||
556 | if ((*list)->dev_id == dev_id) break; | ||
557 | } | ||
558 | if (!*list) { | ||
559 | local_irq_restore(flags); | ||
560 | goto not_found; | ||
561 | } | ||
562 | |||
563 | (*list)->handler = NULL; /* Mark it as free for reallocation */ | ||
564 | *list = (*list)->next; | ||
565 | |||
566 | /* If there's now only one handler, unchain the interrupt, i.e. plug in | ||
567 | * the handler directly again and omit atari_call_irq_list */ | ||
568 | node = (irq_node_t *)irq_handler[irq].dev_id; | ||
569 | if (node && !node->next) { | ||
570 | irq_handler[irq].handler = node->handler; | ||
571 | irq_handler[irq].dev_id = node->dev_id; | ||
572 | irq_param[irq].devname = node->devname; | ||
573 | node->handler = NULL; /* Mark it as free for reallocation */ | ||
574 | } | ||
575 | |||
576 | local_irq_restore(flags); | ||
577 | return; | ||
578 | |||
579 | not_found: | ||
580 | printk("%s: tried to remove invalid irq\n", __FUNCTION__); | ||
581 | return; | ||
582 | } | ||
583 | |||
584 | |||
585 | /* | 425 | /* |
586 | * atari_register_vme_int() returns the number of a free interrupt vector for | 426 | * atari_register_vme_int() returns the number of a free interrupt vector for |
587 | * hardware with a programmable int vector (probably a VME board). | 427 | * hardware with a programmable int vector (probably a VME board). |
@@ -591,58 +431,24 @@ unsigned long atari_register_vme_int(void) | |||
591 | { | 431 | { |
592 | int i; | 432 | int i; |
593 | 433 | ||
594 | for(i = 0; i < 32; i++) | 434 | for (i = 0; i < 32; i++) |
595 | if((free_vme_vec_bitmap & (1 << i)) == 0) | 435 | if ((free_vme_vec_bitmap & (1 << i)) == 0) |
596 | break; | 436 | break; |
597 | 437 | ||
598 | if(i == 16) | 438 | if (i == 16) |
599 | return 0; | 439 | return 0; |
600 | 440 | ||
601 | free_vme_vec_bitmap |= 1 << i; | 441 | free_vme_vec_bitmap |= 1 << i; |
602 | return (VME_SOURCE_BASE + i); | 442 | return VME_SOURCE_BASE + i; |
603 | } | 443 | } |
604 | 444 | ||
605 | 445 | ||
606 | void atari_unregister_vme_int(unsigned long irq) | 446 | void atari_unregister_vme_int(unsigned long irq) |
607 | { | 447 | { |
608 | if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { | 448 | if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { |
609 | irq -= VME_SOURCE_BASE; | 449 | irq -= VME_SOURCE_BASE; |
610 | free_vme_vec_bitmap &= ~(1 << irq); | 450 | free_vme_vec_bitmap &= ~(1 << irq); |
611 | } | 451 | } |
612 | } | 452 | } |
613 | 453 | ||
614 | 454 | ||
615 | int show_atari_interrupts(struct seq_file *p, void *v) | ||
616 | { | ||
617 | int i; | ||
618 | |||
619 | for (i = 0; i < NUM_INT_SOURCES; ++i) { | ||
620 | if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_inthandler) | ||
621 | continue; | ||
622 | if (i < STMFP_SOURCE_BASE) | ||
623 | seq_printf(p, "auto %2d: %10u ", | ||
624 | i, kstat_cpu(0).irqs[i]); | ||
625 | else | ||
626 | seq_printf(p, "vec $%02x: %10u ", | ||
627 | IRQ_SOURCE_TO_VECTOR(i), | ||
628 | kstat_cpu(0).irqs[i]); | ||
629 | |||
630 | if (irq_handler[i].handler != atari_call_irq_list) { | ||
631 | seq_printf(p, "%s\n", irq_param[i].devname); | ||
632 | } | ||
633 | else { | ||
634 | irq_node_t *n; | ||
635 | for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) { | ||
636 | seq_printf(p, "%s\n", n->devname); | ||
637 | if (n->next) | ||
638 | seq_puts(p, " " ); | ||
639 | } | ||
640 | } | ||
641 | } | ||
642 | if (num_spurious) | ||
643 | seq_printf(p, "spurio.: %10u\n", num_spurious); | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | |||