Sync to trunk (r44371)
[reactos.git] / reactos / hal / halx86 / generic / irq.S
1 /*
2 * FILE: hal/halx86/generic/irq.S
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: Software, System and Hardware IRQ Management
5 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
6 */
7
8 /* INCLUDES ******************************************************************/
9
10 /* Enable this (and the define in spinlock.c) to make UP HAL work for MP Kernel */
11 /* #define CONFIG_SMP */
12
13 #include <asm.h>
14 #include <internal/i386/asmmacro.S>
15 .intel_syntax noprefix
16
17 /* GLOBALS *******************************************************************/
18
19 PICInitTable:
20
21 /* Master PIC */
22 .short 0x20 /* Port */
23 .byte 0x11 /* Edge, cascade, CAI 8, ICW4 */
24 .byte PRIMARY_VECTOR_BASE /* Base */
25 .byte 4 /* IRQ 4 connected to slave */
26 .byte 1 /* Non buffered, not nested, 8086 */
27
28 /* Slave PIC */
29 .short 0xA0 /* Port */
30 .byte 0x11 /* Edge, cascade, CAI 8, ICW4 */
31 .byte PRIMARY_VECTOR_BASE + 8 /* Base */
32 .byte 2 /* Slave ID: Slave 2 */
33 .byte 1 /* Non buffered, not nested, 8086 */
34
35 /* End of initialization table */
36 .short 0
37
38 KiI8259MaskTable:
39 .long 0 /* IRQL 0 */
40 .long 0 /* IRQL 1 */
41 .long 0 /* IRQL 2 */
42 .long 0 /* IRQL 3 */
43 .long 0xFF800000 /* IRQL 4 */
44 .long 0xFFC00000 /* IRQL 5 */
45 .long 0xFFE00000 /* IRQL 6 */
46 .long 0xFFF00000 /* IRQL 7 */
47 .long 0xFFF80000 /* IRQL 8 */
48 .long 0xFFFC0000 /* IRQL 9 */
49 .long 0xFFFE0000 /* IRQL 10 */
50 .long 0xFFFF0000 /* IRQL 11 */
51 .long 0xFFFF8000 /* IRQL 12 */
52 .long 0xFFFFC000 /* IRQL 13 */
53 .long 0xFFFFE000 /* IRQL 14 */
54 .long 0xFFFFF000 /* IRQL 15 */
55 .long 0xFFFFF800 /* IRQL 16 */
56 .long 0xFFFFFC00 /* IRQL 17 */
57 .long 0xFFFFFE00 /* IRQL 18 */
58 .long 0xFFFFFE00 /* IRQL 19 */
59 .long 0xFFFFFE80 /* IRQL 20 */
60 .long 0xFFFFFEC0 /* IRQL 21 */
61 .long 0xFFFFFEE0 /* IRQL 22 */
62 .long 0xFFFFFEF0 /* IRQL 23 */
63 .long 0xFFFFFEF8 /* IRQL 24 */
64 .long 0xFFFFFEF8 /* IRQL 25 */
65 .long 0xFFFFFEFA /* IRQL 26 */
66 .long 0xFFFFFFFA /* IRQL 27 */
67 .long 0xFFFFFFFB /* IRQL 28 */
68 .long 0xFFFFFFFB /* IRQL 29 */
69 .long 0xFFFFFFFB /* IRQL 30 */
70 .long 0xFFFFFFFB /* IRQL 31 */
71
72 FindHigherIrqlMask:
73 .long 0xFFFFFFFE /* IRQL 0 */
74 .long 0xFFFFFFFC /* IRQL 1 */
75 .long 0xFFFFFFF8 /* IRQL 2 */
76 .long 0xFFFFFFF0 /* IRQL 3 */
77 .long 0x7FFFFF0 /* IRQL 4 */
78 .long 0x3FFFFF0 /* IRQL 5 */
79 .long 0x1FFFFF0 /* IRQL 6 */
80 .long 0x0FFFFF0 /* IRQL 7 */
81 .long 0x7FFFF0 /* IRQL 8 */
82 .long 0x3FFFF0 /* IRQL 9 */
83 .long 0x1FFFF0 /* IRQL 10 */
84 .long 0x0FFFF0 /* IRQL 11 */
85 .long 0x7FFF0 /* IRQL 12 */
86 .long 0x3FFF0 /* IRQL 13 */
87 .long 0x1FFF0 /* IRQL 14 */
88 .long 0x0FFF0 /* IRQL 15 */
89 .long 0x7FF0 /* IRQL 16 */
90 .long 0x3FF0 /* IRQL 17 */
91 .long 0x1FF0 /* IRQL 18 */
92 .long 0x1FF0 /* IRQL 19 */
93 .long 0x17F0 /* IRQL 20 */
94 .long 0x13F0 /* IRQL 21 */
95 .long 0x11F0 /* IRQL 22 */
96 .long 0x10F0 /* IRQL 23 */
97 .long 0x1070 /* IRQL 24 */
98 .long 0x1030 /* IRQL 25 */
99 .long 0x1010 /* IRQL 26 */
100 .long 0x10 /* IRQL 27 */
101 .long 0 /* IRQL 28 */
102 .long 0 /* IRQL 29 */
103 .long 0 /* IRQL 30 */
104 .long 0 /* IRQL 31 */
105
106 HalpSpecialDismissTable:
107 .rept 7
108 .long GenericIRQ /* IRQ 0-7 */
109 .endr
110 .long IRQ7 /* IRQ 7 */
111 .rept 5
112 .long GenericIRQ /* IRQ 8-12 */
113 .endr
114 .long IRQ13 /* IRQ 13 */
115 .long GenericIRQ /* IRQ 14 */
116 .long IRQ15 /* IRQ 15 */
117 .rept 20
118 .long GenericIRQ /* IRQ 16-35 */
119 .endr
120 #if DBG
121 .rept 172
122 .long InvalidIRQ /* IRQ 36-207 */
123 .endr
124 #endif
125
126 HalpSpecialDismissLevelTable:
127 .rept 7
128 .long GenericIRQLevel /* IRQ 0-7 */
129 .endr
130 .long IRQ7Level /* IRQ 7 */
131 .rept 5
132 .long GenericIRQLevel /* IRQ 8-12 */
133 .endr
134 .long IRQ13Level /* IRQ 13 */
135 .long GenericIRQLevel /* IRQ 14 */
136 .long IRQ15Level /* IRQ 15 */
137
138 SWInterruptLookUpTable:
139 .byte PASSIVE_LEVEL /* IRR 0 */
140 .byte PASSIVE_LEVEL /* IRR 1 */
141 .byte APC_LEVEL /* IRR 2 */
142 .byte APC_LEVEL /* IRR 3 */
143 .byte DISPATCH_LEVEL /* IRR 4 */
144 .byte DISPATCH_LEVEL /* IRR 5 */
145 .byte DISPATCH_LEVEL /* IRR 6 */
146 .byte DISPATCH_LEVEL /* IRR 7 */
147
148 SWInterruptHandlerTable:
149 .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
150 .long _HalpApcInterrupt /* APC_LEVEL */
151 .long _HalpDispatchInterrupt /* DISPATCH_LEVEL */
152
153 SWInterruptHandlerTable2:
154 .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
155 .long _HalpApcInterrupt2ndEntry /* APC_LEVEL */
156 .long _HalpDispatchInterrupt2ndEntry /* DISPATCH_LEVEL */
157
158 _UnhandledMsg:
159 .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
160
161 /* FUNCTIONS *****************************************************************/
162
163 /* HAL interrupt handlers */
164 GENERATE_HAL_INT_HANDLERS
165
166 .globl _HalpHardwareInterruptLevel
167 .func HalpHardwareInterruptLevel
168 _HalpHardwareInterruptLevel:
169
170 /* Get IRQL and check for pending interrupts */
171 mov eax, PCR[KPCR_IRQL]
172 mov ecx, PCR[KPCR_IRR]
173 and ecx, FindHigherIrqlMask[eax*4]
174 jz NothingHardware
175
176 /* Check the active IRR */
177 test dword ptr PCR[KPCR_IRR_ACTIVE], 0xFFFFFFF0
178 jnz NothingHardware
179
180 /* Check for pending software interrupts */
181 mov eax, ecx
182 bsr ecx, eax
183 mov eax, 1
184 shl eax, cl
185
186 /* Clear IRR */
187 xor PCR[KPCR_IRR], eax
188
189 /* Now dispatch the interrupt */
190 call SWInterruptHandlerTable[ecx*4]
191
192 NothingHardware:
193 ret
194 .endfunc
195
196 .globl _HalpInitPICs@0
197 .func HalpInitPICs@0
198 _HalpInitPICs@0:
199
200 /* Save ESI and disable interrupts */
201 push esi
202 pushf
203 cli
204
205 /* Read the init table */
206 lea esi, PICInitTable
207 lodsw
208
209 InitLoop:
210
211 /* Put the port in EDX */
212 movzx edx, ax
213
214 /* Initialize the PIC, using a delay for each command */
215 outsb
216 jmp $+2
217 inc edx
218 outsb
219 jmp $+2
220 outsb
221 jmp $+2
222 outsb
223 jmp $+2
224
225 /* Mask all interrupts */
226 mov al, 0xFF
227 out dx, al
228
229 /* Check if we're done, otherwise initialize next PIC */
230 lodsw
231 cmp ax, 0
232 jnz InitLoop
233
234 /* Read EISA Edge/Level Register */
235 mov edx, 0x4D1
236 in al, dx
237 mov ah, al
238 dec edx
239 in al, dx
240
241 /* Clear reserved bits and see if there's anything there */
242 and eax, 0xDEF8
243 cmp eax, 0xDEF8
244 jz NoEisa
245
246 /* FIXME */
247 //UNHANDLED_PATH
248
249 /* Restore interrupts and return */
250 NoEisa:
251 popf
252 pop esi
253 ret
254 .endfunc
255
256 .globl @HalClearSoftwareInterrupt@4
257 .func @HalClearSoftwareInterrupt@4, @HalClearSoftwareInterrupt@4
258 @HalClearSoftwareInterrupt@4:
259
260 /* Get IRR mask */
261 mov eax, 1
262 shl eax, cl
263 not eax
264
265 /* Set IRR */
266 and PCR[KPCR_IRR], eax
267 ret
268 .endfunc
269
270 .globl @HalRequestSoftwareInterrupt@4
271 .func @HalRequestSoftwareInterrupt@4, @HalRequestSoftwareInterrupt@4
272 @HalRequestSoftwareInterrupt@4:
273
274 /* Get IRR mask */
275 mov eax, 1
276 shl eax, cl
277
278 /* Disable interrupts */
279 pushf
280 cli
281
282 /* Set IRR and get IRQL */
283 or PCR[KPCR_IRR], eax
284 mov ecx, PCR[KPCR_IRQL]
285
286 /* Get software IRR mask */
287 mov eax, PCR[KPCR_IRR]
288 and eax, 3
289
290 /* Get highest pending software interrupt and check if it's higher */
291 xor edx, edx
292 mov dl, SWInterruptLookUpTable[eax]
293 cmp dl, cl
294 jbe AfterCall
295
296 /* Call the pending interrupt */
297 call SWInterruptHandlerTable[edx*4]
298
299 AfterCall:
300
301 /* Retore interrupts and return */
302 popf
303 ret
304 .endfunc
305
306 .globl _HalDisableSystemInterrupt@8
307 .func HalDisableSystemInterrupt@8
308 _HalDisableSystemInterrupt@8:
309
310 /* Convert to vector */
311 movzx ecx, byte ptr [esp+4]
312 sub ecx, PRIMARY_VECTOR_BASE
313
314 /* Disable interrupts and set the new IDR */
315 mov edx, 1
316 shl edx, cl
317 cli
318 or PCR[KPCR_IDR], edx
319
320 /* Get the current mask */
321 xor eax, eax
322 in al, 0xA1
323 shl eax, 8
324 in al, 0x21
325
326 /* Mask off the interrupt and write the new mask */
327 or eax, edx
328 out 0x21, al
329 shr eax, 8
330 out 0xA1, al
331
332 /* Return with interrupts enabled */
333 in al, 0xA1
334 sti
335 ret 8
336 .endfunc
337
338 .globl _HalEnableSystemInterrupt@12
339 .func HalEnableSystemInterrupt@12
340 _HalEnableSystemInterrupt@12:
341
342 /* Get the vector and validate it */
343 movzx ecx, byte ptr [esp+4]
344 sub ecx, PRIMARY_VECTOR_BASE
345 jb Invalid
346 cmp ecx, CLOCK2_LEVEL
347 jnb Invalid
348
349 #if 0
350 /* Is PCI IRQ Routing enabled? */
351 cmp byte ptr _HalpIrqMiniportInitialized, 0
352 jz NoMiniport
353
354 /* UNHANDLED */
355 UNHANDLED_PATH
356
357 NoMiniport:
358 /* Check if this is an EISA IRQ */
359 bt _HalpEisaIrqIgnore, ecx
360 jb IgnoredIrq
361
362 /* Clear the EISA Edge/Level Control Register */
363 btr _HalpEisaELCR, ecx
364
365 /* Get the interrupt type */
366 mov al, [esp+12]
367 cmp al, 0
368 jnz Latched
369
370 /* Check the register again */
371 bt _HalpEisaELCR, ecx
372 jb Dismiss
373
374 /* Check if the miniport is active */
375 cmp byte ptr _HalpIrqMiniportInitialized, 0
376 jz Dismiss
377
378 /* Update the EISA Edge/Level Control Register */
379 bts _HalpEisaELCR, ecx
380
381 Dismiss:
382 /* Use the level hardware interrupt handler */
383 mov dword ptr SWInterruptHandlerTableHardware[ecx*4], offset _HalpHardwareInterruptLevel
384 mov edx, HalpSpecialDismissLevelTable[ecx*4]
385 mov HalpSpecialDismissTable[ecx*4], edx
386
387 Latched:
388 /* Is PCI IRQ Routing enabled? */
389 cmp byte ptr _HalpIrqMiniportInitialized, 0
390 jz IgnoredIrq
391
392 /* UNHANDLED */
393 UNHANDLED_PATH
394 #endif
395 IgnoredIrq:
396 /* Calculate the new IDR */
397 mov eax, 1
398 shl eax, cl
399 not eax
400 cli
401 and PCR[KPCR_IDR], eax
402
403 /* Get the current IRQL and mask the IRQs in the PIC */
404 mov eax, PCR[KPCR_IRQL]
405 mov eax, KiI8259MaskTable[eax*4]
406 or eax, PCR[KPCR_IDR]
407 out 0x21, al
408 shr eax, 8
409 out 0xA1, al
410
411 /* Enable interrupts and return TRUE */
412 sti
413 mov eax, 1
414 ret 12
415
416 Invalid:
417
418 /* Fail, invalid IRQ */
419 #if DBG
420 int 3
421 #endif
422 xor eax, eax
423 ret 12
424 .endfunc
425
426 .globl _HalBeginSystemInterrupt@12
427 .func HalBeginSystemInterrupt@12
428 _HalBeginSystemInterrupt@12:
429
430 /* Convert to IRQ and call the handler */
431 xor ecx, ecx
432 mov cl, byte ptr [esp+8]
433 sub ecx, PRIMARY_VECTOR_BASE
434 jmp HalpSpecialDismissTable[ecx*4]
435
436 IRQ15:
437 /* This is IRQ 15, check if it's spurious */
438 mov al, 0xB
439 out 0xA0, al
440 jmp $+2
441 in al, 0xA0
442 test al, 0x80
443 jnz GenericIRQ
444
445 /* Cascaded interrupt... dismiss it and return FALSE */
446 CascadedInterrupt:
447 mov al, 0x62
448 out 0x20, al
449 mov eax, 0
450 ret 12
451
452 IRQ7:
453 /* This is IRQ 7, check if it's spurious */
454 mov al, 0xB
455 out 0x20, al
456 jmp $+2
457 in al, 0x20
458 test al, 0x80
459 jnz GenericIRQ
460
461 /* It is, return FALSE */
462 mov eax, 0
463 ret 12
464
465 IRQ13:
466 /* AT 80287 latch clear */
467 xor al, al
468 out 0xF0, al
469
470 GenericIRQ:
471 /* Get current and new IRQL */
472 xor eax, eax
473 mov al, byte ptr [esp+4]
474 mov ebx, PCR[KPCR_IRQL]
475
476 /* Set and save old */
477 mov PCR[KPCR_IRQL], eax
478 mov edx, [esp+12]
479 mov [edx], bl
480
481 /* Set IRQ mask in the PIC */
482 mov eax, KiI8259MaskTable[eax*4]
483 or eax, PCR[KPCR_IDR]
484 out 0x21, al
485 shr eax, 8
486 out 0xA1, al
487
488 /* Check to which PIC the EOI was sent */
489 mov eax, ecx
490 cmp eax, 8
491 jnb Pic1
492
493 /* Write mask to master PIC */
494 or al, 0x60
495 out 0x20, al
496
497 /* Enable interrupts and return TRUE */
498 sti
499 mov eax, 1
500 ret 12
501
502 Pic1:
503 /* Write mask to slave PIC */
504 mov al, 0x20
505 out 0xA0, al
506 mov al, 0x62
507 out 0x20, al
508
509 /* Enable interrupts and return TRUE */
510 sti
511 mov eax, 1
512 ret 12
513
514 #if DBG
515 InvalidIRQ:
516 /* Dismiss it */
517 mov eax, 0
518 ret 12
519 #endif
520 .endfunc
521
522 IRQ15Level:
523 /* This is IRQ 15, check if it's spurious */
524 mov al, 0xB
525 out 0xA0, al
526 jmp $+2
527 in al, 0xA0
528 test al, 0x80
529 jnz GenericIRQLevel
530 jmp CascadedInterrupt
531
532 IRQ7Level:
533 /* This is IRQ 7, check if it's spurious */
534 mov al, 0xB
535 out 0x20, al
536 jmp $+2
537 in al, 0x20
538 test al, 0x80
539 jnz GenericIRQLevel
540
541 /* It is, return FALSE */
542 SpuriousInterrupt:
543 mov eax, 0
544 ret 12
545
546 IRQ13Level:
547 /* AT 80287 latch clear */
548 xor al, al
549 out 0xF0, al
550
551 GenericIRQLevel:
552 /* Save IRQL */
553 xor eax, eax
554 mov al, [esp+4]
555
556 /* Set IRQ mask in the PIC */
557 mov eax, KiI8259MaskTable[eax*4]
558 or eax, PCR[KPCR_IDR]
559 out 0x21, al
560 shr eax, 8
561 out 0xA1, al
562
563 /* Compute new IRR */
564 mov eax, ecx
565 mov ebx, 1
566 add ecx, 4
567 shl ebx, cl
568 or PCR[KPCR_IRR], ebx
569
570 /* Get IRQLs */
571 mov cl, [esp+4]
572 mov bl, PCR[KPCR_IRQL]
573 mov edx, [esp+12]
574
575 /* Check to which PIC the EOI was sent */
576 cmp eax, 8
577 jnb Pic1Level
578
579 /* Write mask to master PIC */
580 or al, 0x60
581 out 0x20, al
582
583 /* Check for spurious */
584 cmp cl, bl
585 jbe SpuriousInterrupt
586
587 /* Write IRQL values */
588 movzx ecx, cl
589 mov PCR[KPCR_IRQL], ecx
590 mov [edx], bl
591
592 /* Enable interrupts and return TRUE */
593 sti
594 mov eax, 1
595 ret 12
596
597 Pic1Level:
598 /* Write mask to slave and master PIC */
599 add al, 0x58
600 out 0xA0, al
601 mov al, 0x62
602 out 0x20, al
603
604 /* Was this a lower interrupt? */
605 cmp cl, bl
606 jbe SpuriousInterrupt
607
608 /* Write IRQL values */
609 movzx ecx, cl
610 mov PCR[KPCR_IRQL], ecx
611 mov [edx], bl
612
613 /* Enable interrupts and return TRUE */
614 sti
615 mov eax, 1
616 ret 12
617
618 .globl _HalEndSystemInterrupt@8
619 .func HalEndSystemInterrupt@8
620 _HalEndSystemInterrupt@8:
621
622 /* Read IRQL */
623 xor ecx, ecx
624 mov cl, [esp+4]
625
626 /* Check if it's a software interrupt */
627 cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
628 jbe SkipMask2
629
630 /* Hardware interrupt, mask the appropriate IRQs in the PIC */
631 mov eax, KiI8259MaskTable[ecx*4]
632 or eax, PCR[KPCR_IDR]
633 out 0x21, al
634 shr eax, 8
635 out 0xA1, al
636
637 SkipMask2:
638
639 /* Set IRQL and check if there are pending software interrupts */
640 mov PCR[KPCR_IRQL], ecx
641 mov eax, PCR[KPCR_IRR]
642 mov al, SWInterruptLookUpTable[eax]
643 cmp al, cl
644 ja DoCall
645 ret 8
646
647 DoCall:
648
649 /* There are pending software interrupts, call their handlers */
650 add esp, 12
651 jmp SWInterruptHandlerTable2[eax*4]
652 .endfunc
653
654 .globl @KfLowerIrql@4
655 .func @KfLowerIrql@4
656 _@KfLowerIrql@4:
657 @KfLowerIrql@4:
658
659 /* Cleanup IRQL */
660 and ecx, 0xFF
661
662 /* Validate IRQL */
663 #if DBG
664 cmp cl, PCR[KPCR_IRQL]
665 ja InvalidIrql
666 #endif
667
668 /* Save flags since we'll disable interrupts */
669 pushf
670 cli
671
672 /* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
673 cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
674 jbe SkipMask
675
676 /* Clear interrupt masks since there's a pending hardware interrupt */
677 mov eax, KiI8259MaskTable[ecx*4]
678 or eax, PCR[KPCR_IDR]
679 out 0x21, al
680 shr eax, 8
681 out 0xA1, al
682
683 SkipMask:
684
685 /* Set the new IRQL and check if there's a pending software interrupt */
686 mov PCR[KPCR_IRQL], ecx
687 mov eax, PCR[KPCR_IRR]
688 mov al, SWInterruptLookUpTable[eax]
689 cmp al, cl
690 ja DoCall3
691
692 /* Restore interrupts and return */
693 popf
694 ret
695
696 #if DBG
697 InvalidIrql:
698 /* Set HIGH_LEVEL */
699 mov eax, PCR[KPCR_IRQL]
700 mov dword ptr PCR[KPCR_IRQL], HIGH_LEVEL
701
702 /* Bugcheck the system */
703 push 3
704 push 0
705 push ecx
706 push eax
707 push IRQL_NOT_LESS_OR_EQUAL
708 call _KeBugCheckEx@20
709 #endif
710
711 DoCall3:
712 /* There is, call it */
713 call SWInterruptHandlerTable[eax*4]
714
715 /* Restore interrupts and return */
716 popf
717 ret
718 .endfunc
719
720 .globl @KfRaiseIrql@4
721 .func @KfRaiseIrql@4
722 _@KfRaiseIrql@4:
723 @KfRaiseIrql@4:
724
725 /* Get the IRQL */
726 movzx ecx, cl
727 mov eax, PCR[KPCR_IRQL]
728
729 #if DBG
730 /* Validate it */
731 cmp eax, ecx
732 ja InvalidKfRaise
733 #endif
734
735 /* Check if it's in the software level */
736 cmp cl, DISPATCH_LEVEL
737 jbe SetIrql
738
739 /* Save the current IRQL */
740 mov edx, eax
741
742 /* It's a hardware IRQL, so disable interrupts */
743 pushf
744 cli
745
746 /* Set the new IRQL */
747 mov PCR[KPCR_IRQL], ecx
748
749 /* Mask the interrupts in the PIC */
750 mov eax, KiI8259MaskTable[ecx*4]
751 or eax, PCR[KPCR_IDR]
752 out 0x21, al
753 shr eax, 8
754 out 0xA1, al
755
756 /* Restore interrupts and return old IRQL */
757 popf
758 mov eax, edx
759 ret
760
761 SetIrql:
762 /* Set the IRQL and return */
763 mov PCR[KPCR_IRQL], ecx
764 ret
765
766 #if DBG
767 InvalidKfRaise:
768 /* Set to passive */
769 mov dword ptr PCR[KPCR_IRQL], PASSIVE_LEVEL
770
771 /* Bugcheck the system */
772 push 9
773 push 0
774 push ecx
775 push eax
776 push IRQL_NOT_GREATER_OR_EQUAL
777 call _KeBugCheckEx@20
778 #endif
779 .endfunc
780
781 .globl _KeGetCurrentIrql@0
782 .func KeGetCurrentIrql@0
783 _KeGetCurrentIrql@0:
784
785 /* Return the IRQL */
786 mov eax, PCR[KPCR_IRQL]
787 ret
788 .endfunc
789
790 .globl _KeRaiseIrqlToDpcLevel@0
791 .func KeRaiseIrqlToDpcLevel@0
792 _KeRaiseIrqlToDpcLevel@0:
793
794 /* Get the current IRQL */
795 mov eax, PCR[KPCR_IRQL]
796
797 /* Set DISPATCH_LEVEL */
798 mov dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
799
800 #if DBG
801 /* Make sure we were not higher then synch */
802 cmp eax, DISPATCH_LEVEL
803 ja InvalidRaise
804 #endif
805 ret
806
807 #if DBG
808 InvalidRaise:
809 /* Bugcheck the system */
810 push 1
811 push 0
812 push DISPATCH_LEVEL
813 push eax
814 push IRQL_NOT_GREATER_OR_EQUAL
815 call _KeBugCheckEx@20
816 #endif
817 .endfunc
818
819 .globl _KeRaiseIrqlToSynchLevel@0
820 .func KeRaiseIrqlToSynchLevel@0
821 _KeRaiseIrqlToSynchLevel@0:
822
823 /* Get the current IRQL */
824 mov eax, PCR[KPCR_IRQL]
825
826 /* Set SYNCH_LEVEL */
827 mov dword ptr PCR[KPCR_IRQL], SYNCH_LEVEL
828
829 #if DBG
830 /* Make sure we were not higher then dispatch */
831 cmp eax, SYNCH_LEVEL
832 ja InvalidSyRaise
833 #endif
834 ret
835
836 #if DBG
837 InvalidSyRaise:
838 /* Bugcheck the system */
839 push 2
840 push 0
841 push SYNCH_LEVEL
842 push eax
843 push IRQL_NOT_GREATER_OR_EQUAL
844 call _KeBugCheckEx@20
845 #endif
846 .endfunc
847
848 .globl _HalpApcInterrupt
849 .func HalpApcInterrupt
850 TRAP_FIXUPS hapc_a, hapc_t, DoFixupV86, DoFixupAbios
851 _HalpApcInterrupt:
852
853 /* Create fake interrupt stack */
854 pop eax
855 pushf
856 push cs
857 push eax
858
859 /* Enter interrupt */
860 INT_PROLOG hapc_a, hapc_t, DoPushFakeErrorCode
861 .endfunc
862
863 .globl _HalpApcInterrupt2ndEntry
864 .func HalpApcInterrupt2ndEntry
865 _HalpApcInterrupt2ndEntry:
866
867 /* Save current IRQL and set to APC level */
868 push PCR[KPCR_IRQL]
869 mov dword ptr PCR[KPCR_IRQL], APC_LEVEL
870 and dword ptr PCR[KPCR_IRR], ~(1 << APC_LEVEL)
871
872 /* Enable interrupts and check if we came from User/V86 mode */
873 sti
874 mov eax, [ebp+KTRAP_FRAME_CS]
875 and eax, MODE_MASK
876 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
877 jz DeliverApc
878
879 /* Set user mode delivery */
880 or eax, UserMode
881
882 DeliverApc:
883
884 /* Deliver the APCs */
885 push ebp
886 push 0
887 push eax
888 call _KiDeliverApc@12
889
890 /* Disable interrupts and end it */
891 cli
892 call _HalpEndSoftwareInterrupt@4
893 jmp _Kei386EoiHelper@0
894 .endfunc
895
896 .globl _HalpDispatchInterrupt
897 .func HalpDispatchInterrupt
898 TRAP_FIXUPS hdpc_a, hdpc_t, DoFixupV86, DoFixupAbios
899 _HalpDispatchInterrupt:
900
901 /* Create fake interrupt stack */
902 pop eax
903 pushf
904 push cs
905 push eax
906
907 /* Enter interrupt */
908 INT_PROLOG hdpc_a, hdpc_t, DoPushFakeErrorCode
909 .endfunc
910
911 .globl _HalpDispatchInterrupt2ndEntry
912 .func HalpDispatchInterrupt2ndEntry
913 _HalpDispatchInterrupt2ndEntry:
914
915 /* Save current IRQL and set to DPC level */
916 push PCR[KPCR_IRQL]
917 mov dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
918 and dword ptr PCR[KPCR_IRR], ~(1 << DISPATCH_LEVEL)
919
920 /* Enable interrupts and let the kernel handle this */
921 sti
922 call _KiDispatchInterrupt@0
923
924 /* Disable interrupts and end it */
925 cli
926 call _HalpEndSoftwareInterrupt@4
927 jmp _Kei386EoiHelper@0
928 .endfunc
929
930 .globl _HalpEndSoftwareInterrupt@4
931 .func HalpEndSoftwareInterrupt@4
932 _HalpEndSoftwareInterrupt@4:
933
934 /* Get the IRQL and check if we're in the software region */
935 movzx ecx, byte ptr [esp+4]
936 cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
937 jbe SoftwareInt
938
939 /* Set the right mask in the PIC for the hardware IRQ */
940 mov eax, KiI8259MaskTable[ecx*4]
941 or eax, PCR[KPCR_IDR]
942 out 0x21, al
943 shr eax, 8
944 out 0xA1, al
945
946 SoftwareInt:
947 /* Check if there are pending software interrupts */
948 mov PCR[KPCR_IRQL], ecx
949 mov eax, PCR[KPCR_IRR]
950 mov al, SWInterruptLookUpTable[eax]
951 cmp al, cl
952 ja DoCall2
953 ret 4
954
955 DoCall2:
956 /* There are pending softwate interrupts, call their handlers */
957 add esp, 8
958 jmp SWInterruptHandlerTable2[eax*4]
959 .endfunc