int-handler.S 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
  3. *
  4. * Based on arch/mips/sgi/kernel/indyIRQ.S
  5. *
  6. * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  7. *
  8. * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  9. * Sony Software Development Center Europe (SDCE), Brussels
  10. */
  11. #include <asm/asm.h>
  12. #include <asm/mipsregs.h>
  13. #include <asm/regdef.h>
  14. #include <asm/stackframe.h>
  15. /* A lot of complication here is taken away because:
  16. *
  17. * 1) We handle one interrupt and return, sitting in a loop and moving across
  18. * all the pending IRQ bits in the cause register is _NOT_ the answer, the
  19. * common case is one pending IRQ so optimize in that direction.
  20. *
  21. * 2) We need not check against bits in the status register IRQ mask, that
  22. * would make this routine slow as hell.
  23. *
  24. * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
  25. * between like BSD spl() brain-damage.
  26. *
  27. * Furthermore, the IRQs on the INDY look basically (barring software IRQs
  28. * which we don't use at all) like:
  29. *
  30. * MIPS IRQ Source
  31. * -------- ------
  32. * 0 Software (ignored)
  33. * 1 Software (ignored)
  34. * 2 Local IRQ level zero
  35. * 3 Local IRQ level one
  36. * 4 8254 Timer zero
  37. * 5 8254 Timer one
  38. * 6 Bus Error
  39. * 7 R4k timer (what we use)
  40. *
  41. * We handle the IRQ according to _our_ priority which is:
  42. *
  43. * Highest ---- R4k Timer
  44. * Local IRQ zero
  45. * Local IRQ one
  46. * Bus Error
  47. * 8254 Timer zero
  48. * Lowest ---- 8254 Timer one
  49. *
  50. * then we just return, if multiple IRQs are pending then we will just take
  51. * another exception, big deal.
  52. */
  53. .text
  54. .set noreorder
  55. .set noat
  56. .align 5
  57. NESTED(ddbIRQ, PT_SIZE, sp)
  58. SAVE_ALL
  59. CLI
  60. .set at
  61. mfc0 s0, CP0_CAUSE # get irq mask
  62. #if 1
  63. mfc0 t2,CP0_STATUS # get enabled interrupts
  64. and s0,t2 # isolate allowed ones
  65. #endif
  66. /* First we check for r4k counter/timer IRQ. */
  67. andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
  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 ddb_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. move a0, sp
  80. jal ddb_local1_irqdispatch
  81. nop
  82. j ret_from_irq
  83. nop
  84. 1:
  85. beq a0, zero, 1f
  86. nop
  87. /* Wheee, an asynchronous bus error... */
  88. move a0, sp
  89. jal ddb_buserror_irq
  90. nop
  91. j ret_from_irq
  92. nop
  93. 1:
  94. /* Here by mistake? This is possible, what can happen
  95. * is that by the time we take the exception the IRQ
  96. * pin goes low, so just leave if this is the case.
  97. */
  98. andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
  99. beq a0, zero, 1f
  100. /* Must be one of the 8254 timers... */
  101. move a0, sp
  102. jal ddb_8254timer_irq
  103. nop
  104. 1:
  105. j ret_from_irq
  106. nop
  107. END(ddbIRQ)