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