ip22-irq.S 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
  3. * Guiness.
  4. *
  5. * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  6. */
  7. #include <asm/asm.h>
  8. #include <asm/mipsregs.h>
  9. #include <asm/regdef.h>
  10. #include <asm/stackframe.h>
  11. /* A lot of complication here is taken away because:
  12. *
  13. * 1) We handle one interrupt and return, sitting in a loop and moving across
  14. * all the pending IRQ bits in the cause register is _NOT_ the answer, the
  15. * common case is one pending IRQ so optimize in that direction.
  16. *
  17. * 2) We need not check against bits in the status register IRQ mask, that
  18. * would make this routine slow as hell.
  19. *
  20. * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
  21. * between like BSD spl() brain-damage.
  22. *
  23. * Furthermore, the IRQs on the INDY look basically (barring software IRQs
  24. * which we don't use at all) like:
  25. *
  26. * MIPS IRQ Source
  27. * -------- ------
  28. * 0 Software (ignored)
  29. * 1 Software (ignored)
  30. * 2 Local IRQ level zero
  31. * 3 Local IRQ level one
  32. * 4 8254 Timer zero
  33. * 5 8254 Timer one
  34. * 6 Bus Error
  35. * 7 R4k timer (what we use)
  36. *
  37. * We handle the IRQ according to _our_ priority which is:
  38. *
  39. * Highest ---- R4k Timer
  40. * Local IRQ zero
  41. * Local IRQ one
  42. * Bus Error
  43. * 8254 Timer zero
  44. * Lowest ---- 8254 Timer one
  45. *
  46. * then we just return, if multiple IRQs are pending then we will just take
  47. * another exception, big deal.
  48. */
  49. .text
  50. .set noreorder
  51. .set noat
  52. .align 5
  53. NESTED(indyIRQ, PT_SIZE, sp)
  54. SAVE_ALL
  55. CLI
  56. .set at
  57. mfc0 s0, CP0_CAUSE # get irq mask
  58. /* First we check for r4k counter/timer IRQ. */
  59. andi a0, s0, CAUSEF_IP7
  60. beq a0, zero, 1f
  61. andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
  62. /* Wheee, a timer interrupt. */
  63. jal indy_r4k_timer_interrupt
  64. move a0, sp # delay slot
  65. j ret_from_irq
  66. nop # delay slot
  67. 1:
  68. beq a0, zero, 1f
  69. andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
  70. /* Wheee, local level zero interrupt. */
  71. jal indy_local0_irqdispatch
  72. move a0, sp # delay slot
  73. j ret_from_irq
  74. nop # delay slot
  75. 1:
  76. beq a0, zero, 1f
  77. andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
  78. /* Wheee, local level one interrupt. */
  79. jal indy_local1_irqdispatch
  80. move a0, sp # delay slot
  81. j ret_from_irq
  82. nop # delay slot
  83. 1:
  84. beq a0, zero, 1f
  85. andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) # delay slot
  86. /* Wheee, an asynchronous bus error... */
  87. jal indy_buserror_irq
  88. move a0, sp # delay slot
  89. j ret_from_irq
  90. nop # delay slot
  91. 1:
  92. /* Here by mistake? It is possible, that by the time we take
  93. * the exception the IRQ pin goes low, so just leave if this
  94. * is the case.
  95. */
  96. beq a0, zero, 1f
  97. nop # delay slot
  98. /* Must be one of the 8254 timers... */
  99. jal indy_8254timer_irq
  100. move a0, sp # delay slot
  101. 1:
  102. j ret_from_irq
  103. nop # delay slot
  104. END(indyIRQ)