Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

932 lines
29 KiB

  1. // TITLE("Interrupt Object Support Routines")
  2. //++
  3. //
  4. // Copyright (c) 1990 Microsoft Corporation
  5. // Copyright (c) 1992 Digital Equipment Corporation
  6. //
  7. // Module Name:
  8. //
  9. // intsup.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements the code necessary to support interrupt objects.
  14. // It contains the interrupt dispatch code and the code template that gets
  15. // copied into an interrupt object.
  16. //
  17. // Author:
  18. //
  19. // David N. Cutler (davec) 2-Apr-1990
  20. // Joe Notarangelo 07-Apr-1992 (based on xxintsup.s by Dave Cutler)
  21. //
  22. // Environment:
  23. //
  24. // Kernel mode only.
  25. //
  26. // Revision History:
  27. //
  28. //--
  29. #include "ksalpha.h"
  30. SBTTL("Synchronize Execution")
  31. //++
  32. //
  33. // BOOLEAN
  34. // KeSynchronizeExecution (
  35. // IN PKINTERRUPT Interrupt,
  36. // IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  37. // IN PVOID SynchronizeContext
  38. // )
  39. //
  40. // Routine Description:
  41. //
  42. // This function synchronizes the execution of the specified routine with the
  43. // execution of the service routine associated with the specified interrupt
  44. // object.
  45. //
  46. // Arguments:
  47. //
  48. // Interrupt (a0) - Supplies a pointer to a control object of type interrupt.
  49. //
  50. // SynchronizeRoutine (a1) - Supplies a pointer to a function whose execution
  51. // is to be synchronized with the execution of the service routine associated
  52. // with the specified interrupt object.
  53. //
  54. // SynchronizeContext (a2) - Supplies a pointer to an arbitrary data structure
  55. // which is to be passed to the function specified by the SynchronizeRoutine
  56. // parameter.
  57. //
  58. // Return Value:
  59. //
  60. // The value returned by the SynchronizeRoutine function is returned as the
  61. // function value.
  62. //
  63. //--
  64. .struct 0
  65. SyS0: .space 8 // saved integer register s0
  66. SyIrql: .space 4 // saved IRQL value
  67. .space 4 // fill for alignment
  68. SyRa: .space 8 // saved return address
  69. SyA0: .space 8 // saved argument registers a0 - a2
  70. SyA1: .space 8 //
  71. SyA2: .space 8 //
  72. SyFrameLength: // length of stack frame
  73. NESTED_ENTRY(KeSynchronizeExecution, SyFrameLength, zero)
  74. lda sp, -SyFrameLength(sp) // allocate stack frame
  75. stq ra, SyRa(sp) // save return address
  76. stq s0, SyS0(sp) // save integer register s0
  77. PROLOGUE_END
  78. stq a1, SyA1(sp) // save synchronization routine address
  79. stq a2, SyA2(sp) // save synchronization routine context
  80. //
  81. // Raise IRQL to the synchronization level and acquire the associated
  82. // spin lock.
  83. //
  84. #if !defined(NT_UP)
  85. LDP s0, InActualLock(a0) // get address of spin lock
  86. #endif
  87. ldq_u t1, InSynchronizeIrql(a0) // get synchronization IRQL
  88. lda t2, InSynchronizeIrql(a0) //
  89. extbl t1, t2, a0 //
  90. SWAP_IRQL // raise IRQL to synchronization level
  91. stl v0, SyIrql(sp) // save old irql
  92. #if !defined(NT_UP)
  93. 10: LDP_L t0, 0(s0) // get current lock value
  94. bis s0, zero, t1 // set lock ownership value
  95. bne t0, 15f // if ne, spin lock owned
  96. STP_C t1, 0(s0) // set spin lock owned
  97. beq t1, 15f // if eq, store conditional failed
  98. mb // synchronize memory access
  99. #endif
  100. //
  101. // Call specified routine passing the specified context parameter.
  102. //
  103. LDP t5, SyA1(sp) // get synchronize routine address
  104. LDP a0, SyA2(sp) // get synchronzie routine context
  105. jsr ra, (t5) // call routine
  106. //
  107. // Release spin lock, lower IRQL to its previous level, and return the value
  108. // returned by the specified routine.
  109. //
  110. #if !defined(NT_UP)
  111. mb // synchronize memory access
  112. STP zero, 0(s0) // set spin lock not owned
  113. #endif
  114. ldl a0, SyIrql(sp) // get saved IRQL
  115. extbl a0, 0, a0 // this is a uchar
  116. bis v0, zero, s0 // save return value
  117. SWAP_IRQL // lower IRQL to previous level
  118. bis s0, zero, v0 // restore return value
  119. ldq s0, SyS0(sp) // restore s0
  120. ldq ra, SyRa(sp) // restore ra
  121. lda sp, SyFrameLength(sp) // deallocate stack frame
  122. ret zero, (ra) // return
  123. //
  124. // Attempt to acquire lock failed.
  125. //
  126. #if !defined(NT_UP)
  127. 15: LDP t0, 0(s0) // read current lock value
  128. beq t0, 10b // if lock available, retry spinlock
  129. br zero, 15b // spin in cache until lock available
  130. #endif
  131. .end KeSynchronizeExecution
  132. SBTTL("Dispatch Chained Interrupt")
  133. //++
  134. //
  135. // Routine Description:
  136. //
  137. // This routine is entered as the result of an interrupt being generated
  138. // via a vector that is connected to more than one interrupt object. Its
  139. // function is to walk the list of connected interrupt objects and call
  140. // each interrupt service routine. If the mode of the interrupt is latched,
  141. // then a complete traversal of the chain must be performed. If any of the
  142. // routines require saving the volatile floating point machine state, then
  143. // it is only saved once.
  144. //
  145. // N.B. On entry to this routine only the volatile integer registers have
  146. // been saved.
  147. //
  148. // Arguments:
  149. //
  150. // a0 - Supplies a pointer to the interrupt object.
  151. //
  152. // s6/fp - Supplies a pointer to a trap frame.
  153. //
  154. // Return Value:
  155. //
  156. // None.
  157. //
  158. //--
  159. .struct 0
  160. ChS0: .space 8 // saved integer registers s0 - s5
  161. ChS1: .space 8 //
  162. ChS2: .space 8 //
  163. ChS3: .space 8 //
  164. ChS4: .space 8 //
  165. ChS5: .space 8 //
  166. ChRa: .space 8 // saved return address
  167. ChIrql: .space 4 // saved IRQL value
  168. ChSpinL: .space 4 // address of spin lock
  169. ChFrameLength: // length of stack frame
  170. NESTED_ENTRY(KiChainedDispatch, ChFrameLength, zero)
  171. lda sp, -ChFrameLength(sp) // allocate stack frame
  172. stq ra, ChRa(sp) // save return address
  173. stq s0, ChS0(sp) // save integer registers s0 - s6
  174. stq s1, ChS1(sp) //
  175. stq s2, ChS2(sp) //
  176. stq s3, ChS3(sp) //
  177. stq s4, ChS4(sp) //
  178. stq s5, ChS5(sp) //
  179. PROLOGUE_END
  180. //
  181. // Register usage:
  182. //
  183. // s0 = address of listhead
  184. // s1 = address of current item in list
  185. // s2 = floating status saved flag
  186. // s3 = mode of interrupt
  187. // s4 = irql of interrupt source
  188. // s5 = synchronization level requested for current list item
  189. //
  190. // Initialize loop variables.
  191. //
  192. ADDP a0, InInterruptListEntry, s0 // set address of listhead
  193. bis s0, zero, s1 // set address of first entry
  194. bis zero, zero, s2 // clear floating state saved flag
  195. ldq_u t0, InMode(a0) // get mode of interrupt
  196. lda t2, InMode(a0) //
  197. extbl t0, t2, s3 //
  198. ldq_u t1, InIrql(a0) // get interrupt source IRQL
  199. lda t3, InIrql(a0) //
  200. extbl t1, t3, s4 //
  201. //
  202. // Walk the list of connected interrupt objects and call the respective
  203. // interrupt service routines.
  204. //
  205. 10: SUBP s1, InInterruptListEntry, a0 // compute interrupt object address
  206. ldq_u t2, InFloatingSave(a0) // get floating save flag
  207. lda t1, InFloatingSave(a0) //
  208. extbl t2, t1, t0 //
  209. bne s2, 20f // if ne, floating state already saved
  210. beq t0, 20f // if eq, don't save floating state
  211. //
  212. // Save volatile floating registers in trap frame.
  213. //
  214. bsr ra, KiSaveVolatileFloatState // save floating state
  215. ldil s2, 1 // set floating state saved flag
  216. //
  217. // Raise IRQL to synchronization level if synchronization level is not
  218. // equal to the interrupt source level.
  219. //
  220. 20: ldq_u t1, InSynchronizeIrql(a0) // get synchronization IRQL
  221. lda t2, InSynchronizeIrql(a0) //
  222. extbl t1, t2, s5 //
  223. cmpeq s4, s5, t0 // Check if synchronization equals source level?
  224. bne t0, 25f // if ne[true], IRQL levels are same
  225. bis s5, zero, a0 // set synchronization IRQL
  226. SWAP_IRQL // raise IRQL to synchronization level
  227. stl v0, ChIrql(sp) // save old IRQL
  228. SUBP s1, InInterruptListEntry, a0 // recompute interrupt object address
  229. //
  230. //
  231. // Acquire the service routine spin lock and call the service routine.
  232. //
  233. 25: //
  234. #if !defined(NT_UP)
  235. LDP t5, InActualLock(a0) // get address of spin lock
  236. 30: LDP_L t1, 0(t5) // get current lock value
  237. bis t5, zero, t2 // set ownership value
  238. bne t1, 35f // if ne, spin lock owned
  239. STP_C t2, 0(t5) // set spin lock owned
  240. beq t2, 35f // if eq, store conditional failed
  241. mb // synchronize memory access
  242. STP t5, ChSpinL(sp) // save spin lock address
  243. #endif
  244. LDP t5, InServiceRoutine(a0) // get address of service routine
  245. LDP a1, InServiceContext(a0) // get service context
  246. jsr ra, (t5) // call interrupt service routine
  247. //
  248. // Release the service routine spin lock.
  249. //
  250. #if !defined(NT_UP)
  251. LDP t5, ChSpinL(sp) // get address of spin lock
  252. mb // synchronize memory access
  253. STP zero, 0(t5) // set spin lock not owned
  254. #endif
  255. //
  256. // Lower IRQL to the interrupt source level if synchronization level is not
  257. // the same as the interrupt source level.
  258. //
  259. cmpeq s4, s5, t0 // check if synchronization equals source level
  260. bne t0, 37f // if ne[true], IRQL levels are same
  261. bis s4, zero, a0 // set interrupt source IRQL
  262. SWAP_IRQL // lower to interrupt source IRQL
  263. //
  264. // Get next list entry and check for end of loop.
  265. //
  266. 37: LDP s1, LsFlink(s1) // get next interrupt object address
  267. beq v0, 40f // if eq, interrupt not handled
  268. beq s3, 50f // if eq, level sensitive interrupt
  269. 40: cmpeq s0, s1, t0 // check if end of list
  270. beq t0, 10b // if eq[false], not end of list
  271. //
  272. // Either the interrupt is level sensitive and has been handled or the end of
  273. // the interrupt object chain has been reached. Check to determine if floating
  274. // machine state needs to be restored.
  275. //
  276. 50: beq s2, 60f // if eq, floating state not saved
  277. //
  278. // Restore volatile floating registers from trap frame.
  279. //
  280. bsr ra, KiRestoreVolatileFloatState // restore floating state
  281. //
  282. // Restore integer registers s0 - s5, retrieve return address, deallocate
  283. // stack frame, and return.
  284. //
  285. 60: ldq s0, ChS0(sp) // restore integer registers s0 - s6
  286. ldq s1, ChS1(sp) //
  287. ldq s2, ChS2(sp) //
  288. ldq s3, ChS3(sp) //
  289. ldq s4, ChS4(sp) //
  290. ldq s5, ChS5(sp) //
  291. ldq ra, ChRa(sp) // restore return address
  292. lda sp, ChFrameLength(sp) // deallocate stack frame
  293. ret zero, (ra) // return
  294. //
  295. // Attempt to acquire spinlock failed.
  296. //
  297. #if !defined(NT_UP)
  298. 35: LDP t1, 0(t5) // read current lock value
  299. beq t1, 30b // if eq, lock available
  300. br zero, 35b // spin in cache until lock available
  301. #endif
  302. .end KiChainedDispatch
  303. SBTTL("Floating Dispatch")
  304. //++
  305. //
  306. // Routine Description:
  307. //
  308. // This routine is entered as the result of an interrupt being generated
  309. // via a vector that is connected to an interrupt object. Its function is
  310. // to save the volatile floating machine state and then call the specified
  311. // interrupt service routine.
  312. //
  313. // N.B. On entry to this routine only the volatile integer registers have
  314. // been saved.
  315. //
  316. // Arguments:
  317. //
  318. // a0 - Supplies a pointer to the interrupt object.
  319. //
  320. // s6/fp - Supplies a pointer to a trap frame.
  321. //
  322. // Return Value:
  323. //
  324. // None.
  325. //
  326. //--
  327. .struct 0
  328. FlS0: .space 8 // saved integer registers s0 - s1
  329. FlS1: .space 8 //
  330. FlIrql: .space 4 // saved IRQL value
  331. .space 4 // for alignment
  332. FlRa: .space 8 // saved return address
  333. FlFrameLength: // length of stack frame
  334. NESTED_ENTRY(KiFloatingDispatch, FlFrameLength, zero)
  335. lda sp, -FlFrameLength(sp) // allocate stack frame
  336. stq ra, FlRa(sp) // save return address
  337. stq s0, FlS0(sp) // save integer registers s0 - s1
  338. #if !defined(NT_UP)
  339. stq s1, FlS1(sp) //
  340. #endif
  341. PROLOGUE_END
  342. //
  343. // Save volatile floating registers f0 - f19 in trap frame.
  344. //
  345. bsr ra, KiSaveVolatileFloatState // save floating state
  346. //
  347. // Raise IRQL to synchronization level if synchronization level is not
  348. // equal to the interrupt source level.
  349. //
  350. bis a0, zero, s0 // save address of interrupt object
  351. ldq_u t2, InSynchronizeIrql(s0) // get synchronization IRQL
  352. lda t1, InSynchronizeIrql(s0) //
  353. extbl t2, t1, a0 //
  354. ldq_u t3, InIrql(s0) // get interrupt source IRQL
  355. lda t4, InIrql(s0) //
  356. extbl t3, t4, t0 //
  357. cmpeq a0, t0, t1 // check if synchronize equals source IRQL ?
  358. bne t1, 10f // if ne[true], IRQL levels same
  359. SWAP_IRQL // raise IRQL to synchronization level
  360. stl v0, FlIrql(sp) // save old irql
  361. 10: bis s0, zero, a0 // restore address of interrupt object
  362. //
  363. //
  364. // Acquire the service routine spin lock and call the service routine.
  365. //
  366. #if !defined(NT_UP)
  367. LDP s1, InActualLock(a0) // get address of spin lock
  368. 20: LDP_L t1, 0(s1) // get current lock value
  369. bis s1, s1, t2 // set ownership value
  370. bne t1, 25f // if ne, spin lock owned
  371. STP_C t2, 0(s1) // set spin lock owned
  372. beq t2, 25f // if eq, store conditional failed
  373. mb // synchronize memory access
  374. #endif
  375. LDP t5, InServiceRoutine(a0) // get address of service routine
  376. LDP a1, InServiceContext(a0) // get service context
  377. jsr ra, (t5) // call service routine
  378. //
  379. // Release the service routine spin lock.
  380. //
  381. #if !defined(NT_UP)
  382. mb // synchronize memory access
  383. STP zero, 0(s1) // set spin lock not owned
  384. #endif
  385. //
  386. // Lower IRQL to the interrupt source level if synchronization level is not
  387. // the same as the interrupt source level.
  388. //
  389. ldq_u t3, InIrql(s0) // get interrupt source IRQL
  390. lda t1, InIrql(s0) //
  391. extbl t3, t1, a0 //
  392. ldq_u t4, InSynchronizeIrql(s0) // get synchronization IRQL
  393. lda t2, InSynchronizeIrql(s0) //
  394. extbl t4, t2, t0 //
  395. cmpeq a0, t0, t1 // check if synchronize equal source IRQL?
  396. bne t1, 30f // if eq, IRQL levels are the same
  397. SWAP_IRQL // lower IRQL to interrupt source
  398. //
  399. // Restore volatile floating registers f0 - f19 from trap frame.
  400. //
  401. 30: bsr ra, KiRestoreVolatileFloatState // restore floating state
  402. //
  403. // Restore integer registers s0 - s1, retrieve return address, deallocate
  404. // stack frame, and return.
  405. //
  406. ldq s0, FlS0(sp) // restore integer registers s0 - s1
  407. #if !defined(NT_UP)
  408. ldq s1, FlS1(sp) //
  409. #endif
  410. ldq ra, FlRa(sp) // restore return address
  411. lda sp, FlFrameLength(sp) // deallocate stack frame
  412. ret zero, (ra) // return
  413. //
  414. // Attempt to acquire spinlock failed.
  415. //
  416. #if !defined(NT_UP)
  417. 25: LDP t1, 0(s1) // read current lock value
  418. beq t1, 20b // if lock available, retry spinlock
  419. br zero, 25b // spin in cache until lock available
  420. #endif
  421. .end KiFloatingDispatch
  422. SBTTL("Interrupt Dispatch - Raise IRQL")
  423. //++
  424. //
  425. // Routine Description:
  426. //
  427. // This routine is entered as the result of an interrupt being generated
  428. // via a vector that is connected to an interrupt object. Its function is
  429. // to directly call the specified interrupt service routine.
  430. //
  431. // N.B. On entry to this routine only the volatile integer registers have
  432. // been saved.
  433. //
  434. // N.B. This routine raises the interrupt level to the synchronization
  435. // level specified in the interrupt object.
  436. //
  437. // Arguments:
  438. //
  439. // a0 - Supplies a pointer to the interrupt object.
  440. //
  441. // s6/fp - Supplies a pointer to a trap frame.
  442. //
  443. // Return Value:
  444. //
  445. // None.
  446. //
  447. //--
  448. .struct 0
  449. .space 8 // insure octaword alignment
  450. RdS0: .space 8 // saved integer registers s0
  451. RdIrql: .space 4 // saved IRQL value
  452. .space 4 // for alignment
  453. RdRa: .space 8 // saved return address
  454. RdFrameLength: // length of stack frame
  455. NESTED_ENTRY(KiInterruptDispatchRaise, RdFrameLength, zero)
  456. lda sp, -RdFrameLength(sp) // allocate stack frame
  457. stq ra, RdRa(sp) // save return address
  458. stq s0, RdS0(sp) // save integer registers s0
  459. PROLOGUE_END
  460. //
  461. // Raise IRQL to synchronization level
  462. //
  463. bis a0, zero, s0 // save address of interrupt object
  464. ldq_u t3, InSynchronizeIrql(s0) // get synchronization IRQL
  465. lda t1, InSynchronizeIrql(s0) //
  466. extbl t3, t1, a0 //
  467. SWAP_IRQL // raise IRQL to synchronization level
  468. stl v0, RdIrql(sp) // save old irql
  469. bis s0, zero, a0 // restore address of interrupt object
  470. //
  471. //
  472. // Acquire the service routine spin lock and call the service routine.
  473. //
  474. #if !defined(NT_UP)
  475. LDP t3, InActualLock(a0) // get address of actual lock
  476. 20: LDP_L t1, 0(t3) // get current lock value
  477. bis t3, t3, t2 // set lock ownership value
  478. bne t1, 25f // if ne, spin lock owned
  479. STP_C t2, 0(t3) // set spin lock owned
  480. beq t2, 25f // if eq, store conditional failed
  481. mb // synchronize memory access
  482. #endif
  483. LDP t5, InServiceRoutine(a0) // get address of service routine
  484. LDP a1, InServiceContext(a0) // get service context
  485. jsr ra, (t5) // call service routine
  486. //
  487. // Release the service routine spin lock.
  488. //
  489. #if !defined(NT_UP)
  490. LDP t2, InActualLock(s0) // get address of actual lock
  491. mb // synchronize memory access
  492. STP zero, 0(t2) // set spin lock not owned
  493. #endif
  494. //
  495. // Lower IRQL to the previous level.
  496. //
  497. ldl a0, RdIrql(sp) // get previous IRQL
  498. SWAP_IRQL // lower to interrupt source IRQL
  499. //
  500. // Restore integer register s0, retrieve return address, deallocate
  501. // stack frame, and return.
  502. //
  503. 30: ldq s0, RdS0(sp) // restore integer register s0
  504. ldq ra, RdRa(sp) // restore return address
  505. lda sp, RdFrameLength(sp) // deallocate stack frame
  506. ret zero, (ra) // return
  507. //
  508. // Attempt to acquire spinlock failed.
  509. #if !defined(NT_UP)
  510. 25: LDP t1, 0(t3) // read current lock value
  511. beq t1, 20b // if lock available, retry spinlock
  512. br zero, 25b // spin in cache until lock available
  513. #endif
  514. .end KiInterruptDispatchRaise
  515. SBTTL("Interrupt Dispatch - Same IRQL")
  516. //++
  517. //
  518. // Routine Description:
  519. //
  520. // This routine is entered as the result of an interrupt being generated
  521. // via a vector that is connected to an interrupt object. Its function is
  522. // to directly call the specified interrupt service routine.
  523. //
  524. // N.B. On entry to this routine only the volatile integer registers have
  525. // been saved.
  526. //
  527. // Arguments:
  528. //
  529. // a0 - Supplies a pointer to the interrupt object.
  530. //
  531. // s6/fp - Supplies a pointer to a trap frame.
  532. //
  533. // Return Value:
  534. //
  535. // None.
  536. //
  537. //--
  538. #if defined(NT_UP)
  539. LEAF_ENTRY(KiInterruptDispatchSame)
  540. LDP t5, InServiceRoutine(a0) // get address of service routine
  541. LDP a1, InServiceContext(a0) // get service context
  542. jsr zero, (t5) // jump to service routine
  543. #else
  544. .struct 0
  545. .space 8 // insure octaword alignment
  546. SdS0: .space 8 // saved integer registers s0
  547. SdIrql: .space 4 // saved IRQL value
  548. .space 4 // for alignment
  549. SdRa: .space 8 // saved return address
  550. SdFrameLength: // length of stack frame
  551. NESTED_ENTRY(KiInterruptDispatchSame, SdFrameLength, zero)
  552. lda sp, -SdFrameLength(sp) // allocate stack frame
  553. stq ra, SdRa(sp) // save return address
  554. stq s0, SdS0(sp) // save integer registers s0
  555. PROLOGUE_END
  556. //
  557. //
  558. // Acquire the service routine spin lock and call the service routine.
  559. //
  560. LDP t3, InActualLock(a0) // get actual lock address
  561. bis a0, zero, s0 // save interrupt object address
  562. 20: LDP_L t1, 0(t3) // get current lock value
  563. bis t3, t3, t2 // set lock ownership value
  564. bne t1, 25f // if ne, spin lock owned
  565. STP_C t2, 0(t3) // set spin lock owned
  566. beq t2, 25f // if eq, store conditional failed
  567. mb // synchronize memory access
  568. LDP t5, InServiceRoutine(a0) // get address of service routine
  569. LDP a1, InServiceContext(a0) // get service context
  570. jsr ra, (t5) // call service routine
  571. //
  572. // Release the service routine spin lock.
  573. //
  574. LDP t2, InActualLock(s0) // get actual lock address
  575. mb // synchronize memory access
  576. STP zero, 0(t2) // set spin lock not owned
  577. //
  578. // Restore integer registers s0, retrieve return address, deallocate
  579. // stack frame, and return.
  580. //
  581. 30: ldq s0, SdS0(sp) // restore integer register s0
  582. ldq ra, SdRa(sp) // restore return address
  583. lda sp, SdFrameLength(sp) // deallocate stack frame
  584. ret zero, (ra) // return
  585. //
  586. // Attempt to acquire spinlock failed.
  587. //
  588. 25: LDP t1, 0(t3) // read current lock value
  589. beq t1, 20b // if lock available, retry spinlock
  590. br zero, 25b // spin in cache until lock available
  591. #endif
  592. .end KiInterruptDispatchSame
  593. SBTTL("Interrupt Template")
  594. //++
  595. //
  596. // Routine Description:
  597. //
  598. // This routine is a template that is copied into each interrupt object. Its
  599. // function is to determine the address of the respective interrupt object
  600. // and then transfer control to the appropriate interrupt dispatcher.
  601. //
  602. // N.B. On entry to this routine only the volatile integer registers have
  603. // been saved.
  604. //
  605. // Arguments:
  606. //
  607. // a0 - Supplies a pointer to the interrupt template within an interrupt
  608. // object.
  609. //
  610. // s6/fp - Supplies a pointer to a trap frame.
  611. //
  612. // Return Value:
  613. //
  614. // None.
  615. //
  616. //--
  617. LEAF_ENTRY(KiInterruptTemplate)
  618. .set noreorder
  619. .set noat
  620. LDP t5, InDispatchAddress - InDispatchCode(a0) // get dispatcher address
  621. SUBP a0, InDispatchCode, a0 // compute address of interrupt object
  622. jmp zero, (t5) // transfer to dispatch routine
  623. bis zero, zero, zero // nop for alignment
  624. .set at
  625. .set reorder
  626. .end KiInterruptTemplate
  627. SBTTL("Disable Interrupts")
  628. //++
  629. //
  630. // Routine Description:
  631. //
  632. // This routine disables interrupts on the current processor and
  633. // returns the previous state of the interrrupt enable bit.
  634. //
  635. // Arguments:
  636. //
  637. // None.
  638. //
  639. // Return Value:
  640. //
  641. // A boolean value, if true interrupts were previously turned on,
  642. // false indicates interrupts were previously off.
  643. //
  644. //--
  645. LEAF_ENTRY(KiDisableInterrupts)
  646. GET_CURRENT_PROCESSOR_STATUS_REGISTER // get current prcb address
  647. DISABLE_INTERRUPTS // disable interrupts
  648. and v0, PSR_IE_MASK, v0 // isolate interrupt enable
  649. srl v0, PSR_IE, v0 // shift to bit 0
  650. ret zero, (ra) // return
  651. .end KiDisableInterrupts
  652. SBTTL("Restore Interrupts")
  653. //++
  654. //
  655. // Routine Description:
  656. //
  657. // This routine enables interrupts according to the the previous
  658. // interrupt enable passed as input.
  659. //
  660. // Arguments:
  661. //
  662. // a0 - Supplies previous interrupt enable state (returned by
  663. // KiDisableInterrupts)
  664. //
  665. // Return Value:
  666. //
  667. // None.
  668. //
  669. //--
  670. LEAF_ENTRY(KiRestoreInterrupts)
  671. beq a0, 10f // if eq, then interrupts disabled
  672. ENABLE_INTERRUPTS // enable interrupts
  673. ret zero, (ra) // return
  674. 10: DISABLE_INTERRUPTS // disable interrupts
  675. ret zero, (ra) // return
  676. .end KiRestoreInterrupts
  677. SBTTL("Unexpected Interrupts")
  678. //++
  679. //
  680. // Routine Description:
  681. //
  682. // This routine is entered as the result of an interrupt being generated
  683. // via a vector that is not connected to an interrupt object. Its function
  684. // is to report the error and dismiss the interrupt.
  685. //
  686. // N.B. On entry to this routine only the volatile integer registers have
  687. // been saved.
  688. //
  689. // N.B. - This routine relies upon a private convention with the
  690. // interrupt exception dispatcher that register t12 contains the
  691. // interrupt vector of the unexpected interrupt. This convention
  692. // will only work if the first level dispatch causes the
  693. // unexpected interrupt.
  694. //
  695. // Arguments:
  696. //
  697. // a0 - Supplies a pointer to the interrupt object.
  698. // t12 - Supplies the interrupt vector.
  699. //
  700. // s6/fp - Supplies a pointer to a trap frame.
  701. //
  702. // Return Value:
  703. //
  704. // None.
  705. //
  706. //--
  707. .struct 0
  708. .space 8 // filler for 16 byte alignment
  709. UiRa: .space 8 // return address
  710. UiFrameLength: // frame length
  711. NESTED_ENTRY(KiUnexpectedInterrupt, UiFrameLength, zero)
  712. lda sp, -UiFrameLength(sp) // allocate stack frame
  713. stq ra, UiRa(sp) // save return address
  714. PROLOGUE_END //
  715. ldil a0, 0xfacefeed // ****** temp ******
  716. bis t12, zero, a1 // pass interrupt vector
  717. bis zero, zero, a2 // zero remaining parameters
  718. bis zero, zero, a3 //
  719. bis zero, zero, a4 //
  720. bis zero, zero, a5 //
  721. bsr ra, KeBugCheckEx // perform system crash
  722. .end KiUnexpectedInterrupt
  723. SBTTL(KiPassiveRelease)
  724. //++
  725. //
  726. // RoutineDescription:
  727. //
  728. // KiPassiveRelease passively releases an interrupt that cannot/will not
  729. // be serviced at this time. Or there is no reason to service it and
  730. // maybe this routine will never be called in a million years.
  731. //
  732. //
  733. // Arguments:
  734. //
  735. // None.
  736. //
  737. // Return Value:
  738. //
  739. // None.
  740. //
  741. //--
  742. LEAF_ENTRY( KiPassiveRelease )
  743. ret zero, (ra) // return
  744. .end KiPassiveRelease
  745.