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.

417 lines
11 KiB

  1. ;++
  2. ;
  3. ;Copyright (c) 1991 Microsoft Corporation
  4. ;
  5. ;Module Name:
  6. ;
  7. ; ixsysint.asm
  8. ;
  9. ;Abstract:
  10. ;
  11. ; This module implements the HAL routines to enable/disable system
  12. ; interrupts.
  13. ;
  14. ;Author:
  15. ;
  16. ; John Vert (jvert) 22-Jul-1991
  17. ;
  18. ;Environment:
  19. ;
  20. ; Kernel Mode
  21. ;
  22. ;Revision History:
  23. ;
  24. ;--
  25. .386p
  26. .xlist
  27. include hal386.inc
  28. include i386\ix8259.inc
  29. include i386\kimacro.inc
  30. include mac386.inc
  31. include callconv.inc
  32. include xxacpi.h
  33. .list
  34. extrn KiI8259MaskTable:DWORD
  35. EXTRNP _KeBugCheck,1,IMPORT
  36. ;
  37. ; Constants used to initialize CMOS/Real Time Clock
  38. ;
  39. CMOS_CONTROL_PORT EQU 70h ; command port for cmos
  40. CMOS_DATA_PORT EQU 71h ; cmos data port
  41. ;
  42. ; Macros to Read/Write/Reset CMOS to initialize RTC
  43. ;
  44. ; CMOS_READ
  45. ;
  46. ; Description: This macro read a byte from the CMOS register specified
  47. ; in (AL).
  48. ;
  49. ; Parameter: (AL) = address/register to read
  50. ; Return: (AL) = data
  51. ;
  52. CMOS_READ MACRO
  53. OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI
  54. IODelay ; I/O DELAY
  55. IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA
  56. IODelay ; I/O DELAY
  57. ENDM
  58. _TEXT SEGMENT DWORD PUBLIC 'DATA'
  59. align dword
  60. ;
  61. ; HalDismissSystemInterrupt does an indirect jump through this table so it
  62. ; can quickly execute specific code for different interrupts.
  63. ;
  64. public HalpSpecialDismissTable
  65. HalpSpecialDismissTable label dword
  66. dd offset FLAT:HalpDismissNormal ; irq 0
  67. dd offset FLAT:HalpDismissNormal ; irq 1
  68. dd offset FLAT:HalpDismissNormal ; irq 2
  69. dd offset FLAT:HalpDismissNormal ; irq 3
  70. dd offset FLAT:HalpDismissNormal ; irq 4
  71. dd offset FLAT:HalpDismissNormal ; irq 5
  72. dd offset FLAT:HalpDismissNormal ; irq 6
  73. dd offset FLAT:HalpDismissIrq07 ; irq 7
  74. dd offset FLAT:HalpDismissNormal ; irq 8
  75. dd offset FLAT:HalpDismissNormal ; irq 9
  76. dd offset FLAT:HalpDismissNormal ; irq A
  77. dd offset FLAT:HalpDismissNormal ; irq B
  78. dd offset FLAT:HalpDismissNormal ; irq C
  79. dd offset FLAT:HalpDismissNormal ; irq D
  80. dd offset FLAT:HalpDismissNormal ; irq E
  81. dd offset FLAT:HalpDismissIrq0f ; irq F
  82. dd offset FLAT:HalpDismissNormal ; irq 10
  83. dd offset FLAT:HalpDismissNormal ; irq 11
  84. dd offset FLAT:HalpDismissNormal ; irq 12
  85. dd offset FLAT:HalpDismissNormal ; irq 13
  86. dd offset FLAT:HalpDismissNormal ; irq 14
  87. dd offset FLAT:HalpDismissNormal ; irq 15
  88. dd offset FLAT:HalpDismissNormal ; irq 16
  89. dd offset FLAT:HalpDismissNormal ; irq 17
  90. dd offset FLAT:HalpDismissNormal ; irq 18
  91. dd offset FLAT:HalpDismissNormal ; irq 19
  92. dd offset FLAT:HalpDismissNormal ; irq 1A
  93. dd offset FLAT:HalpDismissNormal ; irq 1B
  94. dd offset FLAT:HalpDismissNormal ; irq 1C
  95. dd offset FLAT:HalpDismissNormal ; irq 1D
  96. dd offset FLAT:HalpDismissNormal ; irq 1E
  97. dd offset FLAT:HalpDismissNormal ; irq 1F
  98. dd offset FLAT:HalpDismissNormal ; irq 20
  99. dd offset FLAT:HalpDismissNormal ; irq 21
  100. dd offset FLAT:HalpDismissNormal ; irq 22
  101. dd offset FLAT:HalpDismissNormal ; irq 23
  102. _TEXT ENDS
  103. _TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
  104. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  105. ;++
  106. ;BOOLEAN
  107. ;HalBeginSystemInterrupt(
  108. ; IN KIRQL Irql
  109. ; IN ULONG Vector,
  110. ; OUT PKIRQL OldIrql
  111. ; )
  112. ;
  113. ;
  114. ;
  115. ;Routine Description:
  116. ;
  117. ; This routine is used to dismiss the specified vector number. It is called
  118. ; before any interrupt service routine code is executed.
  119. ;
  120. ; N.B. This routine does NOT preserve EAX or EBX
  121. ;
  122. ; On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
  123. ; This is fine since the irql is being raise to mask it off.
  124. ; HalEndSystemInterrupt is simply a LowerIrql request.
  125. ;
  126. ;
  127. ;Arguments:
  128. ;
  129. ; Irql - Supplies the IRQL to raise to
  130. ;
  131. ; Vector - Supplies the vector of the interrupt to be processed
  132. ;
  133. ; OldIrql- Location to return OldIrql
  134. ;
  135. ;
  136. ;Return Value:
  137. ;
  138. ; FALSE - Interrupt is spurious and should be ignored
  139. ;
  140. ; TRUE - Interrupt successfully dismissed and Irql raised.
  141. ;
  142. ;--
  143. align dword
  144. HbsiIrql equ byte ptr [esp+4]
  145. HbsiVector equ byte ptr [esp+8]
  146. HbsiOldIrql equ dword ptr [esp+12]
  147. cPublicProc _HalBeginSystemInterrupt ,3
  148. cPublicFpo 3, 0
  149. movzx ebx,HbsiVector ; (ebx) = IDTEntry
  150. sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ #
  151. if DBG
  152. cmp ebx, 23h
  153. jbe hbsi00
  154. int 3
  155. hbsi00:
  156. endif
  157. jmp HalpSpecialDismissTable[ebx*4] ; jmp to proper dismiss code
  158. HalpDismissIrq0f:
  159. ;
  160. ; Check to see if this is a spurious interrupt
  161. ;
  162. mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
  163. out PIC2_PORT0, al
  164. IODelay ; delay
  165. in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR
  166. test al, 10000000B ; Is In-Service register set?
  167. jnz short HalpDismissNormal ; No, this is NOT a spurious int,
  168. ; go do the normal interrupt stuff
  169. ;
  170. ; This is a spurious interrupt.
  171. ; Because the slave PIC is cascaded to irq2 of master PIC, we need to
  172. ; dismiss the interupt on master PIC's irq2.
  173. ;
  174. mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi
  175. out PIC1_PORT0, al ; send irq2 specific eoi to master
  176. mov eax,0 ; return FALSE
  177. ; sti
  178. stdRET _HalBeginSystemInterrupt
  179. HalpDismissIrq07:
  180. ;
  181. ; Check to see if this is a spurious interrupt
  182. ;
  183. mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR
  184. out PIC1_PORT0, al
  185. IODelay ; delay
  186. in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR
  187. test al, 10000000B ; Is In-Service register set?
  188. jnz short HalpDismissNormal ; No, so this is NOT a spurious int
  189. mov eax, 0 ; return FALSE
  190. ; sti
  191. stdRET _HalBeginSystemInterrupt
  192. HalpDismissNormal:
  193. ;
  194. ; Store OldIrql
  195. ;
  196. mov eax, HbsiOldIrql
  197. movzx ecx, word ptr PCR[PcIrql]
  198. mov byte ptr [eax], cl
  199. ;
  200. ; Raise IRQL to requested level
  201. ;
  202. movzx eax, HbsiIrql ; (eax) = irql
  203. ; (ebx) = IRQ #
  204. mov PCR[PcIrql], al ; set new Irql
  205. mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
  206. or eax, PCR[PcIDR] ; mask disabled irqs
  207. SET_8259_MASK ; send mask to 8259s
  208. ;
  209. ; Dismiss interrupt. Current interrupt is already masked off.
  210. ;
  211. mov eax, ebx ; (eax) = IRQ #
  212. cmp eax, 8 ; EOI to master or slave?
  213. jae short Hbsi100 ; EIO to both master and slave
  214. or al, PIC1_EOI_MASK ; create specific eoi mask for master
  215. out PIC1_PORT0, al ; dismiss the interrupt
  216. jmp short Hbsi200 ; IO delay - This is not enough for 486
  217. Hbsi100:
  218. mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave
  219. out PIC2_PORT0, al
  220. mov al, PIC2_EOI ; specific eoi to master for pic2 eoi
  221. out PIC1_PORT0, al ; send irq2 specific eoi to master
  222. Hbsi200:
  223. PIC1DELAY ; *MUST* wait for 8259 before sti
  224. sti
  225. mov eax, 1 ; return TRUE, interrupt dismissed
  226. stdRET _HalBeginSystemInterrupt
  227. stdENDP _HalBeginSystemInterrupt
  228. ;++
  229. ;VOID
  230. ;HalDisableSystemInterrupt(
  231. ; IN CCHAR Vector,
  232. ; IN KIRQL Irql
  233. ; )
  234. ;
  235. ;
  236. ;
  237. ;Routine Description:
  238. ;
  239. ; Disables a system interrupt.
  240. ;
  241. ;Arguments:
  242. ;
  243. ; Vector - Supplies the vector of the interrupt to be disabled
  244. ;
  245. ; Irql - Supplies the interrupt level of the interrupt to be disabled
  246. ;
  247. ;Return Value:
  248. ;
  249. ; None.
  250. ;
  251. ;--
  252. cPublicProc _HalDisableSystemInterrupt ,2
  253. cPublicFpo 2, 0
  254. ;
  255. movzx ecx, byte ptr [esp+4] ; (ecx) = IDTEntry
  256. sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
  257. mov edx, 1
  258. shl edx, cl ; (ebx) = bit in IMR to disable
  259. cli
  260. or PCR[PcIDR], edx
  261. xor eax, eax
  262. ;
  263. ; Get the current interrupt mask register from the 8259
  264. ;
  265. in al, PIC2_PORT1
  266. shl eax, 8
  267. in al, PIC1_PORT1
  268. ;
  269. ; Mask off the interrupt to be disabled
  270. ;
  271. or eax, edx
  272. ;
  273. ; Write the new interrupt mask register back to the 8259
  274. ;
  275. out PIC1_PORT1, al
  276. shr eax, 8
  277. out PIC2_PORT1, al
  278. PIC2DELAY
  279. sti
  280. stdRET _HalDisableSystemInterrupt
  281. stdENDP _HalDisableSystemInterrupt
  282. ;++
  283. ;
  284. ;BOOLEAN
  285. ;HalEnableSystemInterrupt(
  286. ; IN ULONG Vector,
  287. ; IN KIRQL Irql,
  288. ; IN KINTERRUPT_MODE InterruptMode
  289. ; )
  290. ;
  291. ;
  292. ;Routine Description:
  293. ;
  294. ; Enables a system interrupt
  295. ;
  296. ;Arguments:
  297. ;
  298. ; Vector - Supplies the vector of the interrupt to be enabled
  299. ;
  300. ; Irql - Supplies the interrupt level of the interrupt to be enabled.
  301. ;
  302. ;Return Value:
  303. ;
  304. ; None.
  305. ;
  306. ;--
  307. Vector EQU [esp+4]
  308. Irql EQU [esp+8]
  309. InterruptMode EQU [esp+12]
  310. cPublicProc _HalEnableSystemInterrupt ,3
  311. cPublicFpo 3, 0
  312. movzx ecx, byte ptr Vector ; (ecx) = IDTEntry
  313. sub ecx, PRIMARY_VECTOR_BASE
  314. jc hes_error
  315. cmp ecx, CLOCK2_LEVEL
  316. jnc hes_error
  317. ;
  318. ; Set Edge/Level bit in the interrupt controller
  319. ;
  320. ; read the edge/level control bits into ax
  321. mov edx, EISA_EDGE_LEVEL1
  322. in al, dx
  323. shl ax, 8
  324. mov edx, EISA_EDGE_LEVEL0
  325. in al, dx
  326. mov dx, 1
  327. shl dx, cl ; set the bit corresponding to this Vector
  328. .IF InterruptMode == 0 ; if level,
  329. or ax, dx ; set the bit
  330. .ELSE ; else (edge)
  331. not dx
  332. and ax, dx ; clear the bit
  333. .ENDIF
  334. ; write it back
  335. mov edx, EISA_EDGE_LEVEL0
  336. out dx, al
  337. shr ax, 8
  338. mov edx, EISA_EDGE_LEVEL1
  339. out dx, al
  340. mov eax, 1
  341. shl eax, cl ; (ebx) = bit in IMR to enable
  342. not eax
  343. cli
  344. and PCR[PcIDR], eax
  345. ;
  346. ; Get the PIC masks for the current Irql
  347. ;
  348. movzx eax, byte ptr PCR[PcIrql]
  349. mov eax, KiI8259MaskTable[eax*4]
  350. or eax, PCR[PcIDR]
  351. ;
  352. ; Write the new interrupt mask register back to the 8259
  353. ;
  354. SET_8259_MASK
  355. sti
  356. mov eax, 1 ; return TRUE
  357. stdRET _HalEnableSystemInterrupt
  358. hes_error:
  359. if DBG
  360. int 3
  361. endif
  362. xor eax, eax ; FALSE
  363. stdRET _HalEnableSystemInterrupt
  364. stdENDP _HalEnableSystemInterrupt
  365. _TEXT$01 ENDS
  366. END