amiints.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * 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. #include <linux/init.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/errno.h>
  11. #include <asm/irq.h>
  12. #include <asm/traps.h>
  13. #include <asm/amigahw.h>
  14. #include <asm/amigaints.h>
  15. #include <asm/amipcmcia.h>
  16. /*
  17. * Enable/disable a particular machine specific interrupt source.
  18. * Note that this may affect other interrupts in case of a shared interrupt.
  19. * This function should only be called for a _very_ short time to change some
  20. * internal data, that may not be changed by the interrupt at the same time.
  21. */
  22. static void amiga_irq_enable(struct irq_data *data)
  23. {
  24. amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
  25. }
  26. static void amiga_irq_disable(struct irq_data *data)
  27. {
  28. amiga_custom.intena = 1 << (data->irq - IRQ_USER);
  29. }
  30. static struct irq_chip amiga_irq_chip = {
  31. .name = "amiga",
  32. .irq_enable = amiga_irq_enable,
  33. .irq_disable = amiga_irq_disable,
  34. };
  35. /*
  36. * The builtin Amiga hardware interrupt handlers.
  37. */
  38. static irqreturn_t ami_int1(int irq, void *dev_id)
  39. {
  40. unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
  41. /* if serial transmit buffer empty, interrupt */
  42. if (ints & IF_TBE) {
  43. amiga_custom.intreq = IF_TBE;
  44. generic_handle_irq(IRQ_AMIGA_TBE);
  45. }
  46. /* if floppy disk transfer complete, interrupt */
  47. if (ints & IF_DSKBLK) {
  48. amiga_custom.intreq = IF_DSKBLK;
  49. generic_handle_irq(IRQ_AMIGA_DSKBLK);
  50. }
  51. /* if software interrupt set, interrupt */
  52. if (ints & IF_SOFT) {
  53. amiga_custom.intreq = IF_SOFT;
  54. generic_handle_irq(IRQ_AMIGA_SOFT);
  55. }
  56. return IRQ_HANDLED;
  57. }
  58. static irqreturn_t ami_int3(int irq, void *dev_id)
  59. {
  60. unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
  61. /* if a blitter interrupt */
  62. if (ints & IF_BLIT) {
  63. amiga_custom.intreq = IF_BLIT;
  64. generic_handle_irq(IRQ_AMIGA_BLIT);
  65. }
  66. /* if a copper interrupt */
  67. if (ints & IF_COPER) {
  68. amiga_custom.intreq = IF_COPER;
  69. generic_handle_irq(IRQ_AMIGA_COPPER);
  70. }
  71. /* if a vertical blank interrupt */
  72. if (ints & IF_VERTB) {
  73. amiga_custom.intreq = IF_VERTB;
  74. generic_handle_irq(IRQ_AMIGA_VERTB);
  75. }
  76. return IRQ_HANDLED;
  77. }
  78. static irqreturn_t ami_int4(int irq, void *dev_id)
  79. {
  80. unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
  81. /* if audio 0 interrupt */
  82. if (ints & IF_AUD0) {
  83. amiga_custom.intreq = IF_AUD0;
  84. generic_handle_irq(IRQ_AMIGA_AUD0);
  85. }
  86. /* if audio 1 interrupt */
  87. if (ints & IF_AUD1) {
  88. amiga_custom.intreq = IF_AUD1;
  89. generic_handle_irq(IRQ_AMIGA_AUD1);
  90. }
  91. /* if audio 2 interrupt */
  92. if (ints & IF_AUD2) {
  93. amiga_custom.intreq = IF_AUD2;
  94. generic_handle_irq(IRQ_AMIGA_AUD2);
  95. }
  96. /* if audio 3 interrupt */
  97. if (ints & IF_AUD3) {
  98. amiga_custom.intreq = IF_AUD3;
  99. generic_handle_irq(IRQ_AMIGA_AUD3);
  100. }
  101. return IRQ_HANDLED;
  102. }
  103. static irqreturn_t ami_int5(int irq, void *dev_id)
  104. {
  105. unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
  106. /* if serial receive buffer full interrupt */
  107. if (ints & IF_RBF) {
  108. /* acknowledge of IF_RBF must be done by the serial interrupt */
  109. generic_handle_irq(IRQ_AMIGA_RBF);
  110. }
  111. /* if a disk sync interrupt */
  112. if (ints & IF_DSKSYN) {
  113. amiga_custom.intreq = IF_DSKSYN;
  114. generic_handle_irq(IRQ_AMIGA_DSKSYN);
  115. }
  116. return IRQ_HANDLED;
  117. }
  118. /*
  119. * void amiga_init_IRQ(void)
  120. *
  121. * Parameters: None
  122. *
  123. * Returns: Nothing
  124. *
  125. * This function should be called during kernel startup to initialize
  126. * the amiga IRQ handling routines.
  127. */
  128. void __init amiga_init_IRQ(void)
  129. {
  130. if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
  131. pr_err("Couldn't register int%d\n", 1);
  132. if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
  133. pr_err("Couldn't register int%d\n", 3);
  134. if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
  135. pr_err("Couldn't register int%d\n", 4);
  136. if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
  137. pr_err("Couldn't register int%d\n", 5);
  138. m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
  139. AMI_STD_IRQS);
  140. /* turn off PCMCIA interrupts */
  141. if (AMIGAHW_PRESENT(PCMCIA))
  142. gayle.inten = GAYLE_IRQ_IDE;
  143. /* turn off all interrupts and enable the master interrupt bit */
  144. amiga_custom.intena = 0x7fff;
  145. amiga_custom.intreq = 0x7fff;
  146. amiga_custom.intena = IF_SETCLR | IF_INTEN;
  147. cia_init_IRQ(&ciaa_base);
  148. cia_init_IRQ(&ciab_base);
  149. }