mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:32:59 +00:00
- Fix prototype/definition of HalCalibratePerformanceCounter and properly implement it.
- Implement KeStallExecutionProcessor in its own assembly file isntead of using inlined GCC assembly, and align the loop to 16 bytes for more streamlined execution speed. - Mask out clock interrupt during Phase 0 and Initialize clock interrupt on HAL Phase 1. This enables the HAL clock interrupt which was already written. - Make the clock interrupt use HalpCurrentTimeIncrement instead of hardcoding a value. - Re-implement HalpInitializeClock to allow for dynamic increments from 1ms to 15ms with appropriate rollovers and to call KeSetTimeIncrement to update timer values with the kernel. - Implement HalSetTimeIncrement to allow changing the clock ms increment (but this isn't yet respected). - Remove system/runtime update routines from the deprecated IRQ implementation and use the newer assembly ones already written, since we're now using the HAL clock interrupt. Remove other unused code. - Fix more bugs in new hal IRQ implementation (that still isn't used yet due to regressions) and implement HalClearSoftwareInterrupt. svn path=/trunk/; revision=24908
This commit is contained in:
parent
7df718a150
commit
088b3cd98e
12 changed files with 341 additions and 450 deletions
|
@ -173,7 +173,8 @@ HalBeginSystemInterrupt (KIRQL Irql,
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
HalCalibratePerformanceCounter(
|
HalCalibratePerformanceCounter(
|
||||||
ULONG Count)
|
volatile LONG *Count,
|
||||||
|
ULONGLONG NewCount)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ HalAllocateCommonBuffer@16
|
||||||
HalAllocateCrashDumpRegisters@8
|
HalAllocateCrashDumpRegisters@8
|
||||||
HalAssignSlotResources@32
|
HalAssignSlotResources@32
|
||||||
HalBeginSystemInterrupt@12
|
HalBeginSystemInterrupt@12
|
||||||
HalCalibratePerformanceCounter@4
|
HalCalibratePerformanceCounter@12
|
||||||
HalDisableSystemInterrupt@8
|
HalDisableSystemInterrupt@8
|
||||||
HalDisplayString@4
|
HalDisplayString@4
|
||||||
HalEnableSystemInterrupt@12
|
HalEnableSystemInterrupt@12
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
<file>sysbus.c</file>
|
<file>sysbus.c</file>
|
||||||
<file>sysinfo.c</file>
|
<file>sysinfo.c</file>
|
||||||
<file>timer.c</file>
|
<file>timer.c</file>
|
||||||
|
<file>systimer.S</file>
|
||||||
<pch>../include/hal.h</pch>
|
<pch>../include/hal.h</pch>
|
||||||
</module>
|
</module>
|
||||||
<module name="hal_generic_up" type="objectlibrary">
|
<module name="hal_generic_up" type="objectlibrary">
|
||||||
|
@ -28,7 +29,6 @@
|
||||||
<file>irql.c</file>
|
<file>irql.c</file>
|
||||||
<file>processor.c</file>
|
<file>processor.c</file>
|
||||||
<file>spinlock.c</file>
|
<file>spinlock.c</file>
|
||||||
<file>systimer.S</file>
|
|
||||||
</module>
|
</module>
|
||||||
<module name="hal_generic_pc" type="objectlibrary">
|
<module name="hal_generic_pc" type="objectlibrary">
|
||||||
<include base="hal_generic_pc">../include</include>
|
<include base="hal_generic_pc">../include</include>
|
||||||
|
|
|
@ -113,7 +113,7 @@ HalInitSystem(IN ULONG BootPhase,
|
||||||
HalpInitNonBusHandler();
|
HalpInitNonBusHandler();
|
||||||
|
|
||||||
/* Initialize the clock interrupt */
|
/* Initialize the clock interrupt */
|
||||||
//HalpInitPhase1();
|
HalpInitPhase1();
|
||||||
|
|
||||||
/* Initialize DMA. NT does this in Phase 0 */
|
/* Initialize DMA. NT does this in Phase 0 */
|
||||||
HalpInitDma();
|
HalpInitDma();
|
||||||
|
|
|
@ -67,18 +67,21 @@ KiI8259MaskTable:
|
||||||
.long 0xFFFFFFFB /* IRQL 31 */
|
.long 0xFFFFFFFB /* IRQL 31 */
|
||||||
|
|
||||||
HalpSysIntHandler:
|
HalpSysIntHandler:
|
||||||
.rept 8
|
.rept 7
|
||||||
.long GenericIRQ /* IRQ 0-7 */
|
.long GenericIRQ /* IRQ 0-7 */
|
||||||
.endr
|
.endr
|
||||||
.long IRQ7 /* IRQ 7 */
|
.long IRQ7 /* IRQ 7 */
|
||||||
.rept 8
|
.rept 7
|
||||||
.long GenericIRQ /* IRQ 8-15 */
|
.long GenericIRQ /* IRQ 8-15 */
|
||||||
.endr
|
.endr
|
||||||
.long IRQ15 /* IRQ 15 */
|
.long IRQ15 /* IRQ 15 */
|
||||||
.rept 20
|
.rept 20
|
||||||
.long GenericIRQ /* IRQ 16-35 */
|
.long GenericIRQ /* IRQ 16-35 */
|
||||||
|
.endr
|
||||||
|
#if DBG
|
||||||
.rept 172
|
.rept 172
|
||||||
.long InvalidIRQ /* IRQ 36-207 */
|
.long InvalidIRQ /* IRQ 36-207 */
|
||||||
|
#endif
|
||||||
.endr
|
.endr
|
||||||
|
|
||||||
SoftIntByteTable:
|
SoftIntByteTable:
|
||||||
|
@ -147,9 +150,22 @@ InitLoop:
|
||||||
ret
|
ret
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
|
.globl @HalClearSoftwareInterrupt@4
|
||||||
|
.func @HalClearSoftwareInterrupt@4, @HalClearSoftwareInterrupt@4
|
||||||
|
@HalClearSoftwareInterrupt@4:
|
||||||
|
|
||||||
|
/* Get IRR mask */
|
||||||
|
mov eax, 1
|
||||||
|
shl eax, cl
|
||||||
|
not eax
|
||||||
|
|
||||||
|
/* Set IRR */
|
||||||
|
and PCR[KPCR_IRR], eax
|
||||||
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
.globl @HalRequestSoftwareInterrupt@4
|
.globl @HalRequestSoftwareInterrupt@4
|
||||||
.func @HalRequestSoftwareInterrupt@4
|
.func @HalRequestSoftwareInterrupt@4, @HalRequestSoftwareInterrupt@4
|
||||||
_@HalRequestSoftwareInterrupt@4:
|
|
||||||
@HalRequestSoftwareInterrupt@4:
|
@HalRequestSoftwareInterrupt@4:
|
||||||
|
|
||||||
/* Get IRR mask */
|
/* Get IRR mask */
|
||||||
|
@ -161,11 +177,11 @@ _@HalRequestSoftwareInterrupt@4:
|
||||||
cli
|
cli
|
||||||
|
|
||||||
/* Set IRR and get IRQL */
|
/* Set IRR and get IRQL */
|
||||||
or [fs:KPCR_IRR], eax
|
or PCR[KPCR_IRR], eax
|
||||||
mov ecx, [fs:KPCR_IRQL]
|
mov ecx, PCR[KPCR_IRQL]
|
||||||
|
|
||||||
/* Get software IRR mask */
|
/* Get software IRR mask */
|
||||||
mov eax, [fs:KPCR_IRR]
|
mov eax, PCR[KPCR_IRR]
|
||||||
and eax, 3
|
and eax, 3
|
||||||
|
|
||||||
/* Get highest pending software interrupt and check if it's higher */
|
/* Get highest pending software interrupt and check if it's higher */
|
||||||
|
@ -196,7 +212,7 @@ _HalDisableSystemInterrupt@8:
|
||||||
mov edx, 1
|
mov edx, 1
|
||||||
shl edx, cl
|
shl edx, cl
|
||||||
cli
|
cli
|
||||||
or [fs:KPCR_IDR], edx
|
or PCR[KPCR_IDR], edx
|
||||||
|
|
||||||
/* Get the current mask */
|
/* Get the current mask */
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
@ -263,12 +279,12 @@ AfterMask:
|
||||||
shl eax, cl
|
shl eax, cl
|
||||||
not eax
|
not eax
|
||||||
cli
|
cli
|
||||||
and [fs:KPCR_IDR], eax
|
and PCR[KPCR_IDR], eax
|
||||||
|
|
||||||
/* Get the current IRQL and mask the IRQs in the PIC */
|
/* Get the current IRQL and mask the IRQs in the PIC */
|
||||||
mov eax, [fs:KPCR_IRQL]
|
movzx eax, byte ptr PCR[KPCR_IRQL]
|
||||||
mov eax, KiI8259MaskTable[eax*4]
|
mov eax, KiI8259MaskTable[eax*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
@ -281,7 +297,9 @@ AfterMask:
|
||||||
Invalid:
|
Invalid:
|
||||||
|
|
||||||
/* Fail, invalid IRQ */
|
/* Fail, invalid IRQ */
|
||||||
|
#if DBG
|
||||||
int 3
|
int 3
|
||||||
|
#endif
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret 12
|
ret 12
|
||||||
.endfunc
|
.endfunc
|
||||||
|
@ -291,7 +309,7 @@ Invalid:
|
||||||
_HalBeginSystemInterrupt@12:
|
_HalBeginSystemInterrupt@12:
|
||||||
|
|
||||||
/* Convert to IRQ and call the handler */
|
/* Convert to IRQ and call the handler */
|
||||||
mov edx, [esp+8]
|
movzx edx, byte ptr [esp+8]
|
||||||
sub edx, PRIMARY_VECTOR_BASE
|
sub edx, PRIMARY_VECTOR_BASE
|
||||||
jmp HalpSysIntHandler[edx*4]
|
jmp HalpSysIntHandler[edx*4]
|
||||||
|
|
||||||
|
@ -326,22 +344,22 @@ IRQ7:
|
||||||
GenericIRQ:
|
GenericIRQ:
|
||||||
/* Return the current IRQL */
|
/* Return the current IRQL */
|
||||||
mov eax, [esp+12]
|
mov eax, [esp+12]
|
||||||
mov ecx, [fs:KPCR_IRQL]
|
movzx ecx, byte ptr PCR[KPCR_IRQL]
|
||||||
mov [eax], cl
|
mov [eax], cl
|
||||||
|
|
||||||
/* Set the new IRQL */
|
/* Set the new IRQL */
|
||||||
movzx eax, byte ptr [esp+4]
|
movzx eax, byte ptr [esp+4]
|
||||||
mov [fs:KPCR_IRQL], eax
|
mov PCR[KPCR_IRQL], al
|
||||||
|
|
||||||
/* Set IRQ mask in the PIC */
|
/* Set IRQ mask in the PIC */
|
||||||
mov eax, KiI8259MaskTable[eax*4]
|
mov eax, KiI8259MaskTable[eax*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
|
||||||
/* Check to which PIC the EOI was sent */
|
/* Check to which PIC the EOI was sent */
|
||||||
mov eax, ebx
|
mov eax, edx
|
||||||
cmp eax, 8
|
cmp eax, 8
|
||||||
jnb Pic1
|
jnb Pic1
|
||||||
|
|
||||||
|
@ -364,10 +382,12 @@ DoneBegin:
|
||||||
mov eax, 1
|
mov eax, 1
|
||||||
ret 12
|
ret 12
|
||||||
|
|
||||||
|
#if DBG
|
||||||
InvalidIRQ:
|
InvalidIRQ:
|
||||||
/* Dismiss it */
|
/* Dismiss it */
|
||||||
mov eax, 0
|
mov eax, 0
|
||||||
ret 12
|
ret 12
|
||||||
|
#endif
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
.globl _HalEndSystemInterrupt@8
|
.globl _HalEndSystemInterrupt@8
|
||||||
|
@ -376,12 +396,12 @@ _HalEndSystemInterrupt@8:
|
||||||
|
|
||||||
/* Get the IRQL and check if it's a software interrupt */
|
/* Get the IRQL and check if it's a software interrupt */
|
||||||
movzx ecx, byte ptr [esp+4]
|
movzx ecx, byte ptr [esp+4]
|
||||||
cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
cmp byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||||
jbe SkipMask2
|
jbe SkipMask2
|
||||||
|
|
||||||
/* Hardware interrupt, mask the appropriate IRQs in the PIC */
|
/* Hardware interrupt, mask the appropriate IRQs in the PIC */
|
||||||
mov eax, KiI8259MaskTable[ecx*4]
|
mov eax, KiI8259MaskTable[ecx*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
@ -389,8 +409,8 @@ _HalEndSystemInterrupt@8:
|
||||||
SkipMask2:
|
SkipMask2:
|
||||||
|
|
||||||
/* Set IRQL and check if there are pending software interrupts */
|
/* Set IRQL and check if there are pending software interrupts */
|
||||||
mov [fs:KPCR_IRQL], ecx
|
mov PCR[KPCR_IRQL], cl
|
||||||
mov eax, [fs:KPCR_IRR]
|
mov eax, PCR[KPCR_IRR]
|
||||||
mov al, SoftIntByteTable[eax]
|
mov al, SoftIntByteTable[eax]
|
||||||
cmp al, cl
|
cmp al, cl
|
||||||
ja DoCall
|
ja DoCall
|
||||||
|
@ -411,15 +431,21 @@ _@KfLowerIrql@4:
|
||||||
/* Save flags since we'll disable interrupts */
|
/* Save flags since we'll disable interrupts */
|
||||||
pushf
|
pushf
|
||||||
|
|
||||||
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
|
/* Validate IRQL */
|
||||||
movzx ecx, cl
|
movzx ecx, cl
|
||||||
cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
#if DBG
|
||||||
|
cmp cl, PCR[KPCR_IRQL]
|
||||||
|
ja InvalidIrql
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
|
||||||
|
cmp byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||||
cli
|
cli
|
||||||
jbe SkipMask
|
jbe SkipMask
|
||||||
|
|
||||||
/* Clear interrupt masks since there's a pending hardware interrupt */
|
/* Clear interrupt masks since there's a pending hardware interrupt */
|
||||||
mov eax, KiI8259MaskTable[ecx*4]
|
mov eax, KiI8259MaskTable[ecx*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
@ -427,8 +453,8 @@ _@KfLowerIrql@4:
|
||||||
SkipMask:
|
SkipMask:
|
||||||
|
|
||||||
/* Set the new IRQL and check if there's a pending software interrupt */
|
/* Set the new IRQL and check if there's a pending software interrupt */
|
||||||
mov [fs:KPCR_IRQL], ecx
|
mov PCR[KPCR_IRQL], cl
|
||||||
mov eax, [fs:KPCR_IRR]
|
mov eax, PCR[KPCR_IRR]
|
||||||
mov al, SoftIntByteTable[eax]
|
mov al, SoftIntByteTable[eax]
|
||||||
cmp al, cl
|
cmp al, cl
|
||||||
ja DoCall3
|
ja DoCall3
|
||||||
|
@ -436,6 +462,22 @@ SkipMask:
|
||||||
/* Restore interrupts and return */
|
/* Restore interrupts and return */
|
||||||
popf
|
popf
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
InvalidIrql:
|
||||||
|
/* Set HIGH_LEVEL */
|
||||||
|
movzx eax, byte ptr PCR[KPCR_IRQL]
|
||||||
|
mov byte ptr PCR[KPCR_IRQL], HIGH_LEVEL
|
||||||
|
|
||||||
|
/* Bugcheck the system */
|
||||||
|
push 3
|
||||||
|
push 0
|
||||||
|
push ecx
|
||||||
|
push eax
|
||||||
|
push IRQL_NOT_LESS_OR_EQUAL
|
||||||
|
call _KeBugCheckEx@20
|
||||||
|
#endif
|
||||||
|
|
||||||
DoCall3:
|
DoCall3:
|
||||||
/* There is, call it */
|
/* There is, call it */
|
||||||
call SoftIntHandlerTable[eax*4]
|
call SoftIntHandlerTable[eax*4]
|
||||||
|
@ -450,10 +492,19 @@ DoCall3:
|
||||||
_@KfRaiseIrql@4:
|
_@KfRaiseIrql@4:
|
||||||
@KfRaiseIrql@4:
|
@KfRaiseIrql@4:
|
||||||
|
|
||||||
/* Get the IRQL and check if it's Software level only */
|
/* Get the IRQL */
|
||||||
mov eax, [fs:KPCR_IRQL]
|
xor eax, eax
|
||||||
|
mov al, PCR[KPCR_IRQL]
|
||||||
movzx ecx, cl
|
movzx ecx, cl
|
||||||
cmp ecx, DISPATCH_LEVEL
|
|
||||||
|
#if DBG
|
||||||
|
/* Validate it */
|
||||||
|
cmp eax, ecx
|
||||||
|
ja InvalidKfRaise
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if it's in the software level */
|
||||||
|
cmp cl, DISPATCH_LEVEL
|
||||||
jbe SetIrql
|
jbe SetIrql
|
||||||
|
|
||||||
/* Save the current IRQL */
|
/* Save the current IRQL */
|
||||||
|
@ -464,11 +515,11 @@ _@KfRaiseIrql@4:
|
||||||
cli
|
cli
|
||||||
|
|
||||||
/* Set the new IRQL */
|
/* Set the new IRQL */
|
||||||
mov [fs:KPCR_IRQL], cl
|
mov PCR[KPCR_IRQL], cl
|
||||||
|
|
||||||
/* Mask the interrupts in the PIC */
|
/* Mask the interrupts in the PIC */
|
||||||
mov eax, KiI8259MaskTable[ecx*4]
|
mov eax, KiI8259MaskTable[ecx*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
@ -481,8 +532,22 @@ _@KfRaiseIrql@4:
|
||||||
SetIrql:
|
SetIrql:
|
||||||
|
|
||||||
/* Set the IRQL and return */
|
/* Set the IRQL and return */
|
||||||
mov [fs:KPCR_IRQL], ecx
|
mov PCR[KPCR_IRQL], cl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
InvalidKfRaise:
|
||||||
|
/* Set to passive */
|
||||||
|
mov byte ptr PCR[KPCR_IRQL], PASSIVE_LEVEL
|
||||||
|
|
||||||
|
/* Bugcheck the system */
|
||||||
|
push 9
|
||||||
|
push 0
|
||||||
|
push ecx
|
||||||
|
push eax
|
||||||
|
push IRQL_NOT_GREATER_OR_EQUAL
|
||||||
|
call _KeBugCheckEx@20
|
||||||
|
#endif
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
.globl _KeGetCurrentIrql@0
|
.globl _KeGetCurrentIrql@0
|
||||||
|
@ -490,7 +555,7 @@ SetIrql:
|
||||||
_KeGetCurrentIrql@0:
|
_KeGetCurrentIrql@0:
|
||||||
|
|
||||||
/* Return the IRQL */
|
/* Return the IRQL */
|
||||||
mov eax, [fs:KPCR_IRQL]
|
movzx eax, byte ptr PCR[KPCR_IRQL]
|
||||||
ret
|
ret
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
|
@ -499,11 +564,29 @@ _KeGetCurrentIrql@0:
|
||||||
_KeRaiseIrqlToDpcLevel@0:
|
_KeRaiseIrqlToDpcLevel@0:
|
||||||
|
|
||||||
/* Get the current IRQL */
|
/* Get the current IRQL */
|
||||||
mov eax, [fs:KPCR_IRQL]
|
xor eax, eax
|
||||||
|
mov al, PCR[KPCR_IRQL]
|
||||||
|
|
||||||
/* Set DISPATCH_LEVEL */
|
/* Set DISPATCH_LEVEL */
|
||||||
mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
mov byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
/* Make sure we were not higher then dispatch */
|
||||||
|
cmp al, DISPATCH_LEVEL
|
||||||
|
ja InvalidRaise
|
||||||
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
InvalidRaise:
|
||||||
|
/* Bugcheck the system */
|
||||||
|
push 1
|
||||||
|
push 0
|
||||||
|
push DISPATCH_LEVEL
|
||||||
|
push eax
|
||||||
|
push IRQL_NOT_GREATER_OR_EQUAL
|
||||||
|
call _KeBugCheckEx@20
|
||||||
|
#endif
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
.globl _KeRaiseIrqlToSynchLevel@0
|
.globl _KeRaiseIrqlToSynchLevel@0
|
||||||
|
@ -516,16 +599,35 @@ _KeRaiseIrqlToSynchLevel@0:
|
||||||
|
|
||||||
/* Mask out interrupts */
|
/* Mask out interrupts */
|
||||||
mov eax, KiI8259MaskTable[DISPATCH_LEVEL*4]
|
mov eax, KiI8259MaskTable[DISPATCH_LEVEL*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
|
||||||
/* Return the old IRQL, enable interrupts and set to DISPATCH */
|
/* Return the old IRQL, enable interrupts and set to DISPATCH */
|
||||||
mov eax, [fs:KPCR_IRQL]
|
mov al, PCR[KPCR_IRQL]
|
||||||
mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
mov byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||||
popf
|
popf
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
/* Validate raise */
|
||||||
|
cmp al, DISPATCH_LEVEL
|
||||||
|
ja InvalidSyRaise
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
InvalidSyRaise:
|
||||||
|
/* Bugcheck the system */
|
||||||
|
push 2
|
||||||
|
push 0
|
||||||
|
push DISPATCH_LEVEL
|
||||||
|
push eax
|
||||||
|
push IRQL_NOT_GREATER_OR_EQUAL
|
||||||
|
call _KeBugCheckEx@20
|
||||||
|
#endif
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
.globl _HalpApcInterrupt
|
.globl _HalpApcInterrupt
|
||||||
|
@ -547,9 +649,9 @@ _HalpApcInterrupt:
|
||||||
_HalpApcInterrupt2ndEntry:
|
_HalpApcInterrupt2ndEntry:
|
||||||
|
|
||||||
/* Save current IRQL and set to APC level */
|
/* Save current IRQL and set to APC level */
|
||||||
push [fs:KPCR_IRQL]
|
push PCR[KPCR_IRQL]
|
||||||
mov dword ptr [fs:KPCR_IRQL], APC_LEVEL
|
mov dword ptr PCR[KPCR_IRQL], APC_LEVEL
|
||||||
and dword ptr [fs:KPCR_IRR], ~(1 << APC_LEVEL)
|
and dword ptr PCR[KPCR_IRR], ~(1 << APC_LEVEL)
|
||||||
|
|
||||||
/* Enable interrupts and check if we came from User/V86 mode */
|
/* Enable interrupts and check if we came from User/V86 mode */
|
||||||
sti
|
sti
|
||||||
|
@ -594,9 +696,9 @@ _HalpDispatchInterrupt:
|
||||||
_HalpDispatchInterrupt2ndEntry:
|
_HalpDispatchInterrupt2ndEntry:
|
||||||
|
|
||||||
/* Save current IRQL and set to DPC level */
|
/* Save current IRQL and set to DPC level */
|
||||||
push [fs:KPCR_IRQL]
|
push PCR[KPCR_IRQL]
|
||||||
mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
mov dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||||
and dword ptr [fs:KPCR_IRR], ~(1 << DISPATCH_LEVEL)
|
and dword ptr PCR[KPCR_IRR], ~(1 << DISPATCH_LEVEL)
|
||||||
|
|
||||||
/* Enable interrupts and let the kernel handle this */
|
/* Enable interrupts and let the kernel handle this */
|
||||||
sti
|
sti
|
||||||
|
@ -614,20 +716,20 @@ _HalpEndSoftwareInterrupt@4:
|
||||||
|
|
||||||
/* Get the IRQL and check if we're in the software region */
|
/* Get the IRQL and check if we're in the software region */
|
||||||
movzx ecx, byte ptr [esp+4]
|
movzx ecx, byte ptr [esp+4]
|
||||||
cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
||||||
jbe SoftwareInt
|
jbe SoftwareInt
|
||||||
|
|
||||||
/* Set the right mask in the PIC for the hardware IRQ */
|
/* Set the right mask in the PIC for the hardware IRQ */
|
||||||
mov eax, KiI8259MaskTable[ecx*4]
|
mov eax, KiI8259MaskTable[ecx*4]
|
||||||
or eax, [fs:KPCR_IDR]
|
or eax, PCR[KPCR_IDR]
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
shr eax, 8
|
shr eax, 8
|
||||||
out 0xA1, al
|
out 0xA1, al
|
||||||
|
|
||||||
SoftwareInt:
|
SoftwareInt:
|
||||||
/* Check if there are pending software interrupts */
|
/* Check if there are pending software interrupts */
|
||||||
mov [fs:KPCR_IRQL], ecx
|
mov PCR[KPCR_IRQL], ecx
|
||||||
mov eax, [fs:KPCR_IRR]
|
mov eax, PCR[KPCR_IRR]
|
||||||
mov al, SoftIntByteTable[eax]
|
mov al, SoftIntByteTable[eax]
|
||||||
cmp al, cl
|
cmp al, cl
|
||||||
ja DoCall2
|
ja DoCall2
|
||||||
|
|
|
@ -96,8 +96,8 @@ VOID NTAPI HalpInitPICs(VOID)
|
||||||
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
|
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
|
||||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
|
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
|
||||||
/* Enable interrupts */
|
/* Enable interrupts */
|
||||||
WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
|
WRITE_PORT_UCHAR((PUCHAR)0x21, 0xFF);
|
||||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
|
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xFF);
|
||||||
|
|
||||||
/* We can now enable interrupts */
|
/* We can now enable interrupts */
|
||||||
_enable();
|
_enable();
|
||||||
|
@ -305,7 +305,7 @@ KeRaiseIrqlToDpcLevel (VOID)
|
||||||
KIRQL STDCALL
|
KIRQL STDCALL
|
||||||
KeRaiseIrqlToSynchLevel (VOID)
|
KeRaiseIrqlToSynchLevel (VOID)
|
||||||
{
|
{
|
||||||
return KfRaiseIrql (CLOCK2_LEVEL);
|
return KfRaiseIrql (DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,41 @@
|
||||||
#include <asm.h>
|
#include <asm.h>
|
||||||
#include <internal/i386/asmmacro.S>
|
#include <internal/i386/asmmacro.S>
|
||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
.extern _HalpCurrentTimeIncrement
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
.globl _KeStallExecutionProcessor@4
|
||||||
|
.func KeStallExecutionProcessor@4
|
||||||
|
_KeStallExecutionProcessor@4:
|
||||||
|
|
||||||
|
/* Get the number of microseconds required */
|
||||||
|
mov ecx, [esp+4]
|
||||||
|
jecxz Done
|
||||||
|
|
||||||
|
/* Multiply by the stall factor */
|
||||||
|
mov eax, fs:[KPCR_STALL_SCALE_FACTOR]
|
||||||
|
mul ecx
|
||||||
|
|
||||||
|
/* Align to 16 bytes */
|
||||||
|
.align 16
|
||||||
|
|
||||||
|
/* Jump to subtraction loop */
|
||||||
|
jmp SubtractLoop
|
||||||
|
|
||||||
|
/* Align to 16 bytes */
|
||||||
|
.align 16
|
||||||
|
|
||||||
|
/* Subtract one count */
|
||||||
|
SubtractLoop:
|
||||||
|
sub eax, 1
|
||||||
|
jnz SubtractLoop
|
||||||
|
|
||||||
|
Done:
|
||||||
|
/* Return */
|
||||||
|
ret 4
|
||||||
|
.endfunc
|
||||||
|
|
||||||
.globl _HalpClockInterrupt@0
|
.globl _HalpClockInterrupt@0
|
||||||
.func HalpClockInterrupt@0
|
.func HalpClockInterrupt@0
|
||||||
_HalpClockInterrupt@0:
|
_HalpClockInterrupt@0:
|
||||||
|
@ -35,7 +67,8 @@ _HalpClockInterrupt@0:
|
||||||
jz Spurious
|
jz Spurious
|
||||||
|
|
||||||
/* Do a tick */
|
/* Do a tick */
|
||||||
mov eax, 100000
|
mov eax, _HalpCurrentTimeIncrement
|
||||||
|
xor ebx, ebx
|
||||||
jmp _KeUpdateSystemTime@0
|
jmp _KeUpdateSystemTime@0
|
||||||
|
|
||||||
Spurious:
|
Spurious:
|
||||||
|
|
|
@ -38,127 +38,146 @@
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
#define TMR_CTRL 0x43 /* I/O for control */
|
|
||||||
#define TMR_CNT0 0x40 /* I/O for counter 0 */
|
|
||||||
#define TMR_CNT1 0x41 /* I/O for counter 1 */
|
|
||||||
#define TMR_CNT2 0x42 /* I/O for counter 2 */
|
|
||||||
|
|
||||||
#define TMR_SC0 0 /* Select channel 0 */
|
|
||||||
#define TMR_SC1 0x40 /* Select channel 1 */
|
|
||||||
#define TMR_SC2 0x80 /* Select channel 2 */
|
|
||||||
|
|
||||||
#define TMR_LOW 0x10 /* RW low byte only */
|
|
||||||
#define TMR_HIGH 0x20 /* RW high byte only */
|
|
||||||
#define TMR_BOTH 0x30 /* RW both bytes */
|
|
||||||
|
|
||||||
#define TMR_MD0 0 /* Mode 0 */
|
|
||||||
#define TMR_MD1 0x2 /* Mode 1 */
|
|
||||||
#define TMR_MD2 0x4 /* Mode 2 */
|
|
||||||
#define TMR_MD3 0x6 /* Mode 3 */
|
|
||||||
#define TMR_MD4 0x8 /* Mode 4 */
|
|
||||||
#define TMR_MD5 0xA /* Mode 5 */
|
|
||||||
|
|
||||||
#define TMR_BCD 1 /* BCD mode */
|
|
||||||
|
|
||||||
#define TMR_LATCH 0 /* Latch command */
|
|
||||||
|
|
||||||
#define TMR_READ 0xF0 /* Read command */
|
|
||||||
#define TMR_CNT 0x20 /* CNT bit (Active low, subtract it) */
|
|
||||||
#define TMR_STAT 0x10 /* Status bit (Active low, subtract it) */
|
|
||||||
#define TMR_CH2 0x8 /* Channel 2 bit */
|
|
||||||
#define TMR_CH1 0x4 /* Channel 1 bit */
|
|
||||||
#define TMR_CH0 0x2 /* Channel 0 bit */
|
|
||||||
|
|
||||||
#define MILLISEC 10 /* Number of millisec between interrupts */
|
#define MILLISEC 10 /* Number of millisec between interrupts */
|
||||||
#define HZ (1000 / MILLISEC) /* Number of interrupts per second */
|
#define HZ (1000 / MILLISEC) /* Number of interrupts per second */
|
||||||
#define CLOCK_TICK_RATE 1193182 /* Clock frequency of the timer chip */
|
#define CLOCK_TICK_RATE 1193182 /* Clock frequency of the timer chip */
|
||||||
#define LATCH (CLOCK_TICK_RATE / HZ) /* Count to program into the timer chip */
|
#define LATCH (CLOCK_TICK_RATE / HZ) /* Count to program into the timer chip */
|
||||||
#define PRECISION 8 /* Number of bits to calibrate for delay loop */
|
#define PRECISION 8 /* Number of bits to calibrate for delay loop */
|
||||||
|
|
||||||
static BOOLEAN UdelayCalibrated = FALSE;
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
/* FUNCTIONS **************************************************************/
|
BOOLEAN HalpClockSetMSRate;
|
||||||
|
ULONG HalpCurrentTimeIncrement;
|
||||||
|
ULONG HalpCurrentRollOver;
|
||||||
|
ULONG HalpNextMSRate = 14;
|
||||||
|
ULONG HalpLargestClockMS = 15;
|
||||||
|
|
||||||
/*
|
LARGE_INTEGER HalpRolloverTable[15] =
|
||||||
* NOTE: This function MUST NOT be optimized by the compiler!
|
|
||||||
* If it is, it obviously will not delay AT ALL, and the system
|
|
||||||
* will appear completely frozen at boot since
|
|
||||||
* HalpCalibrateStallExecution will never return.
|
|
||||||
* There are three options to stop optimization:
|
|
||||||
* 1. Use a volatile automatic variable. Making it delay quite a bit
|
|
||||||
* due to memory accesses, and keeping the code portable. However,
|
|
||||||
* as this involves memory access it depends on both the CPU cache,
|
|
||||||
* e.g. if the stack used is already in a cache line or not, and
|
|
||||||
* whether or not we're MP. If MP, another CPU could (probably would)
|
|
||||||
* also access RAM at the same time - making the delay imprecise.
|
|
||||||
* 2. Use compiler-specific #pragma's to disable optimization.
|
|
||||||
* 3. Use inline assembly, making it equally unportable as #2.
|
|
||||||
* For supported compilers we use inline assembler. For the others,
|
|
||||||
* portable plain C.
|
|
||||||
*/
|
|
||||||
DECLSPEC_NOINLINE VOID STDCALL
|
|
||||||
__KeStallExecutionProcessor(ULONG Loops)
|
|
||||||
{
|
{
|
||||||
if (!Loops)
|
{{1197, 10032}},
|
||||||
{
|
{{2394, 20064}},
|
||||||
return;
|
{{3591, 30096}},
|
||||||
}
|
{{4767, 39952}},
|
||||||
#if defined(__GNUC__)
|
{{5964, 49984}},
|
||||||
__asm__ __volatile__ (
|
{{7161, 60016}},
|
||||||
"mov %0, %%eax\n"
|
{{8358, 70048}},
|
||||||
"ROSL1: dec %%eax\n"
|
{{9555, 80080}},
|
||||||
"jnz ROSL1" : : "d" (Loops));
|
{{10731, 89936}},
|
||||||
|
{{11949, 100144}},
|
||||||
|
{{13125, 110000}},
|
||||||
|
{{14322, 120032}},
|
||||||
|
{{15519, 130064}},
|
||||||
|
{{16695, 139920}},
|
||||||
|
{{17892, 149952}}
|
||||||
|
};
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
__asm mov eax, Loops
|
|
||||||
ROSL1:
|
|
||||||
__asm dec eax
|
|
||||||
__asm jnz ROSL1
|
|
||||||
#else
|
|
||||||
unsigned int target = Loops;
|
|
||||||
volatile unsigned int i;
|
|
||||||
for (i=0; i<target;i++);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
NTAPI
|
||||||
KeStallExecutionProcessor(ULONG Microseconds)
|
HalpInitializeClock(VOID)
|
||||||
{
|
{
|
||||||
PKIPCR Pcr = (PKIPCR)KeGetPcr();
|
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||||
|
ULONG Increment;
|
||||||
|
USHORT RollOver;
|
||||||
|
|
||||||
if (Pcr->PrcbData.FeatureBits & KF_RDTSC)
|
/* Check the CPU Type */
|
||||||
{
|
if (Prcb->CpuType <= 4)
|
||||||
LARGE_INTEGER EndCount, CurrentCount;
|
{
|
||||||
EndCount.QuadPart = (LONGLONG)__rdtsc();
|
/* 486's or equal can't go higher then 10ms */
|
||||||
EndCount.QuadPart += Microseconds * (ULONGLONG)Pcr->PrcbData.MHz;
|
HalpLargestClockMS = 10;
|
||||||
do
|
HalpNextMSRate = 9;
|
||||||
{
|
}
|
||||||
CurrentCount.QuadPart = (LONGLONG)__rdtsc();
|
|
||||||
}
|
/* Get increment and rollover for the largest time clock ms possible */
|
||||||
while (CurrentCount.QuadPart < EndCount.QuadPart);
|
Increment= HalpRolloverTable[HalpLargestClockMS - 1].HighPart;
|
||||||
}
|
RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart;
|
||||||
else
|
|
||||||
{
|
/* Set the maximum and minimum increment with the kernel */
|
||||||
__KeStallExecutionProcessor((Pcr->StallScaleFactor*Microseconds)/1000);
|
HalpCurrentTimeIncrement = Increment;
|
||||||
}
|
KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart);
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
_disable();
|
||||||
|
|
||||||
|
/* Set the rollover */
|
||||||
|
__outbyte(TIMER_CONTROL_PORT, TIMER_SC0 | TIMER_BOTH | TIMER_MD2);
|
||||||
|
__outbyte(TIMER_DATA_PORT0, RollOver & 0xFF);
|
||||||
|
__outbyte(TIMER_DATA_PORT0, RollOver >> 8);
|
||||||
|
|
||||||
|
/* Restore interrupts */
|
||||||
|
_enable();
|
||||||
|
|
||||||
|
/* Save rollover and return */
|
||||||
|
HalpCurrentRollOver = RollOver;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG Read8254Timer(VOID)
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
HalCalibratePerformanceCounter(IN volatile PLONG Count,
|
||||||
|
IN ULONGLONG NewCount)
|
||||||
{
|
{
|
||||||
ULONG Count;
|
/* Disable interrupts */
|
||||||
|
_disable();
|
||||||
|
|
||||||
/* Disable interrupts */
|
/* Do a decrement for this CPU */
|
||||||
_disable();
|
//_InterlockedDecrement(Count);
|
||||||
|
InterlockedDecrement(Count);
|
||||||
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_LATCH);
|
/* Wait for other CPUs */
|
||||||
Count = READ_PORT_UCHAR((PUCHAR) TMR_CNT0);
|
while (*Count);
|
||||||
Count |= READ_PORT_UCHAR((PUCHAR) TMR_CNT0) << 8;
|
|
||||||
|
|
||||||
_enable();
|
/* Bring interrupts back */
|
||||||
return Count;
|
_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
HalSetTimeIncrement(IN ULONG Increment)
|
||||||
|
{
|
||||||
|
/* Round increment to ms */
|
||||||
|
Increment /= 10000;
|
||||||
|
|
||||||
|
/* Normalize between our minimum (1 ms) and maximum (variable) setting */
|
||||||
|
if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS;
|
||||||
|
if (Increment < 0) Increment = 1;
|
||||||
|
|
||||||
|
/* Set the rate and tell HAL we want to change it */
|
||||||
|
HalpNextMSRate = Increment;
|
||||||
|
HalpClockSetMSRate = TRUE;
|
||||||
|
|
||||||
|
/* Return the increment */
|
||||||
|
return HalpRolloverTable[Increment - 1].HighPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STUFF *********************************************************************/
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
FORCEINLINE
|
||||||
|
Read8254Timer(VOID)
|
||||||
|
{
|
||||||
|
ULONG Count;
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
_disable();
|
||||||
|
|
||||||
|
/* Set the rollover */
|
||||||
|
__outbyte(TIMER_CONTROL_PORT, TIMER_SC0);
|
||||||
|
Count = __inbyte(TIMER_DATA_PORT0);
|
||||||
|
Count |= __inbyte(TIMER_DATA_PORT0) << 8;
|
||||||
|
|
||||||
|
/* Restore interrupts and return count*/
|
||||||
|
_enable();
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
|
||||||
VOID WaitFor8254Wraparound(VOID)
|
VOID WaitFor8254Wraparound(VOID)
|
||||||
{
|
{
|
||||||
|
@ -183,20 +202,6 @@ VOID WaitFor8254Wraparound(VOID)
|
||||||
while (Delta < 300);
|
while (Delta < 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
HalpInitializeClock(VOID)
|
|
||||||
{
|
|
||||||
/* FIXME: Make dynamic */
|
|
||||||
|
|
||||||
/* Initialize the clock */
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_BOTH | TMR_MD2); /* binary, mode 2, LSB/MSB, ch 0 */
|
|
||||||
|
|
||||||
/* Set the increment */
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CNT0, LATCH & 0xff); /* LSB */
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR) TMR_CNT0, LATCH >> 8); /* MSB */
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID HalpCalibrateStallExecution(VOID)
|
VOID HalpCalibrateStallExecution(VOID)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
@ -205,12 +210,6 @@ VOID HalpCalibrateStallExecution(VOID)
|
||||||
PKIPCR Pcr;
|
PKIPCR Pcr;
|
||||||
LARGE_INTEGER StartCount, EndCount;
|
LARGE_INTEGER StartCount, EndCount;
|
||||||
|
|
||||||
if (UdelayCalibrated)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UdelayCalibrated = TRUE;
|
|
||||||
Pcr = (PKIPCR)KeGetPcr();
|
Pcr = (PKIPCR)KeGetPcr();
|
||||||
|
|
||||||
if (Pcr->PrcbData.FeatureBits & KF_RDTSC)
|
if (Pcr->PrcbData.FeatureBits & KF_RDTSC)
|
||||||
|
@ -242,7 +241,7 @@ VOID HalpCalibrateStallExecution(VOID)
|
||||||
|
|
||||||
WaitFor8254Wraparound();
|
WaitFor8254Wraparound();
|
||||||
|
|
||||||
__KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||||
|
|
||||||
CurCount = Read8254Timer();
|
CurCount = Read8254Timer();
|
||||||
}
|
}
|
||||||
|
@ -267,7 +266,7 @@ VOID HalpCalibrateStallExecution(VOID)
|
||||||
|
|
||||||
WaitFor8254Wraparound();
|
WaitFor8254Wraparound();
|
||||||
|
|
||||||
__KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||||
|
|
||||||
CurCount = Read8254Timer();
|
CurCount = Read8254Timer();
|
||||||
if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
|
if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
|
||||||
|
@ -295,19 +294,6 @@ VOID HalpCalibrateStallExecution(VOID)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
HalCalibratePerformanceCounter(ULONG Count)
|
|
||||||
{
|
|
||||||
/* Disable interrupts */
|
|
||||||
_disable();
|
|
||||||
|
|
||||||
__KeStallExecutionProcessor(Count);
|
|
||||||
|
|
||||||
_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LARGE_INTEGER
|
LARGE_INTEGER
|
||||||
STDCALL
|
STDCALL
|
||||||
KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
|
KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
|
||||||
|
@ -360,12 +346,4 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
HalSetTimeIncrement(IN ULONG Increment)
|
|
||||||
{
|
|
||||||
/* FIXME: TODO */
|
|
||||||
return Increment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -22,6 +22,13 @@
|
||||||
#define RTC_REG_A_UIP 0x80
|
#define RTC_REG_A_UIP 0x80
|
||||||
#define RTC_REGISTER_CENTURY 0x32
|
#define RTC_REGISTER_CENTURY 0x32
|
||||||
|
|
||||||
|
/* Timer Registers and Ports */
|
||||||
|
#define TIMER_CONTROL_PORT 0x43
|
||||||
|
#define TIMER_DATA_PORT0 0x40
|
||||||
|
#define TIMER_SC0 0
|
||||||
|
#define TIMER_BOTH 0x30
|
||||||
|
#define TIMER_MD2 0x4
|
||||||
|
|
||||||
/* Conversion functions */
|
/* Conversion functions */
|
||||||
#define BCD_INT(bcd) \
|
#define BCD_INT(bcd) \
|
||||||
(((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F))
|
(((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F))
|
||||||
|
|
|
@ -20,6 +20,17 @@ Author:
|
||||||
#ifndef _ASM_H
|
#ifndef _ASM_H
|
||||||
#define _ASM_H
|
#define _ASM_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// PCR Access
|
||||||
|
//
|
||||||
|
#ifdef __ASM__
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
#define PCR fs:
|
||||||
|
#else
|
||||||
|
#define PCR ds:[0xFF000000]
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// CPU Modes
|
// CPU Modes
|
||||||
//
|
//
|
||||||
|
@ -145,6 +156,7 @@ Author:
|
||||||
#define KPCR_IDT 0x38
|
#define KPCR_IDT 0x38
|
||||||
#define KPCR_GDT 0x3C
|
#define KPCR_GDT 0x3C
|
||||||
#define KPCR_TSS 0x40
|
#define KPCR_TSS 0x40
|
||||||
|
#define KPCR_STALL_SCALE_FACTOR 0x4C
|
||||||
#define KPCR_SET_MEMBER 0x48
|
#define KPCR_SET_MEMBER 0x48
|
||||||
#define KPCR_NUMBER 0x51
|
#define KPCR_NUMBER 0x51
|
||||||
#define KPCR_PRCB_DATA 0x120
|
#define KPCR_PRCB_DATA 0x120
|
||||||
|
@ -489,6 +501,8 @@ Author:
|
||||||
#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
|
#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
|
||||||
#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
|
#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
|
||||||
#define APC_INDEX_MISMATCH 0x01
|
#define APC_INDEX_MISMATCH 0x01
|
||||||
|
#define IRQL_NOT_GREATER_OR_EQUAL 0x09
|
||||||
|
#define IRQL_NOT_LESS_OR_EQUAL 0x0A
|
||||||
#define TRAP_CAUSE_UNKNOWN 0x12
|
#define TRAP_CAUSE_UNKNOWN 0x12
|
||||||
#define KMODE_EXCEPTION_NOT_HANDLED 0x13
|
#define KMODE_EXCEPTION_NOT_HANDLED 0x13
|
||||||
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
|
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
|
||||||
|
|
|
@ -177,231 +177,6 @@ KeInitInterrupts (VOID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
|
||||||
KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
|
|
||||||
PKTRAP_FRAME TrapFrame)
|
|
||||||
{
|
|
||||||
TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs;
|
|
||||||
TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs;
|
|
||||||
TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es;
|
|
||||||
TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds;
|
|
||||||
TrapFrame->Eax = IrqTrapFrame->Eax;
|
|
||||||
TrapFrame->Ecx = IrqTrapFrame->Ecx;
|
|
||||||
TrapFrame->Edx = IrqTrapFrame->Edx;
|
|
||||||
TrapFrame->Ebx = IrqTrapFrame->Ebx;
|
|
||||||
TrapFrame->HardwareEsp = IrqTrapFrame->Esp;
|
|
||||||
TrapFrame->Ebp = IrqTrapFrame->Ebp;
|
|
||||||
TrapFrame->Esi = IrqTrapFrame->Esi;
|
|
||||||
TrapFrame->Edi = IrqTrapFrame->Edi;
|
|
||||||
TrapFrame->Eip = IrqTrapFrame->Eip;
|
|
||||||
TrapFrame->SegCs = IrqTrapFrame->Cs;
|
|
||||||
TrapFrame->EFlags = IrqTrapFrame->Eflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
|
|
||||||
PKIRQ_TRAPFRAME IrqTrapFrame)
|
|
||||||
{
|
|
||||||
IrqTrapFrame->Gs = TrapFrame->SegGs;
|
|
||||||
IrqTrapFrame->Fs = TrapFrame->SegFs;
|
|
||||||
IrqTrapFrame->Es = TrapFrame->SegEs;
|
|
||||||
IrqTrapFrame->Ds = TrapFrame->SegDs;
|
|
||||||
IrqTrapFrame->Eax = TrapFrame->Eax;
|
|
||||||
IrqTrapFrame->Ecx = TrapFrame->Ecx;
|
|
||||||
IrqTrapFrame->Edx = TrapFrame->Edx;
|
|
||||||
IrqTrapFrame->Ebx = TrapFrame->Ebx;
|
|
||||||
IrqTrapFrame->Esp = TrapFrame->HardwareEsp;
|
|
||||||
IrqTrapFrame->Ebp = TrapFrame->Ebp;
|
|
||||||
IrqTrapFrame->Esi = TrapFrame->Esi;
|
|
||||||
IrqTrapFrame->Edi = TrapFrame->Edi;
|
|
||||||
IrqTrapFrame->Eip = TrapFrame->Eip;
|
|
||||||
IrqTrapFrame->Cs = TrapFrame->SegCs;
|
|
||||||
IrqTrapFrame->Eflags = TrapFrame->EFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: On Windows this function takes exactly one parameter and EBP is
|
|
||||||
* guaranteed to point to KTRAP_FRAME. The function is used only
|
|
||||||
* by HAL, so there's no point in keeping that prototype.
|
|
||||||
*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN KIRQL Irql)
|
|
||||||
{
|
|
||||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
|
||||||
PKTHREAD CurrentThread;
|
|
||||||
PKPROCESS CurrentProcess;
|
|
||||||
|
|
||||||
/* Make sure we don't go further if we're in early boot phase. */
|
|
||||||
if (!(Prcb) || !(Prcb->CurrentThread)) return;
|
|
||||||
|
|
||||||
/* Get the current thread and process */
|
|
||||||
CurrentThread = Prcb->CurrentThread;
|
|
||||||
CurrentProcess = CurrentThread->ApcState.Process;
|
|
||||||
|
|
||||||
/* Check if we came from user mode */
|
|
||||||
if (TrapFrame->PreviousPreviousMode != KernelMode)
|
|
||||||
{
|
|
||||||
/* Update user times */
|
|
||||||
CurrentThread->UserTime++;
|
|
||||||
InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
|
|
||||||
Prcb->UserTime++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Check IRQ */
|
|
||||||
if (Irql > DISPATCH_LEVEL)
|
|
||||||
{
|
|
||||||
/* This was an interrupt */
|
|
||||||
Prcb->InterruptTime++;
|
|
||||||
}
|
|
||||||
else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
|
|
||||||
{
|
|
||||||
/* This was normal kernel time */
|
|
||||||
CurrentThread->KernelTime++;
|
|
||||||
InterlockedIncrement((PLONG)&CurrentProcess->KernelTime);
|
|
||||||
}
|
|
||||||
else if (Irql == DISPATCH_LEVEL)
|
|
||||||
{
|
|
||||||
/* This was DPC time */
|
|
||||||
Prcb->DpcTime++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update CPU kernel time in all cases */
|
|
||||||
Prcb->KernelTime++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the last DPC Count and request rate */
|
|
||||||
Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
|
|
||||||
Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
|
|
||||||
Prcb->DpcRequestRate) / 2;
|
|
||||||
|
|
||||||
/* Check if we should request a DPC */
|
|
||||||
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
|
|
||||||
{
|
|
||||||
/* Request one */
|
|
||||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
|
||||||
|
|
||||||
/* Update the depth if needed */
|
|
||||||
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
|
|
||||||
(Prcb->MaximumDpcQueueDepth > 1))
|
|
||||||
{
|
|
||||||
/* Decrease the maximum depth by one */
|
|
||||||
Prcb->MaximumDpcQueueDepth--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Decrease the adjustment threshold */
|
|
||||||
if (!(--Prcb->AdjustDpcThreshold))
|
|
||||||
{
|
|
||||||
/* We've hit 0, reset it */
|
|
||||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
|
||||||
|
|
||||||
/* Check if we've hit queue maximum */
|
|
||||||
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
|
|
||||||
{
|
|
||||||
/* Increase maximum by one */
|
|
||||||
Prcb->MaximumDpcQueueDepth++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're at end of quantum request software interrupt. The rest
|
|
||||||
* is handled in KiDispatchInterrupt.
|
|
||||||
*
|
|
||||||
* NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine
|
|
||||||
* which checks for quantum end will not be executed and decrementing
|
|
||||||
* the quantum here can result in overflow. This is not a problem since
|
|
||||||
* we don't care about the quantum value anymore after the QuantumEnd
|
|
||||||
* flag is set.
|
|
||||||
*/
|
|
||||||
if ((CurrentThread->Quantum -= 3) <= 0)
|
|
||||||
{
|
|
||||||
Prcb->QuantumEnd = TRUE;
|
|
||||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: On Windows this function takes exactly zero parameters and EBP is
|
|
||||||
* guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL.
|
|
||||||
* The function is used only by HAL, so there's no point in keeping
|
|
||||||
* that prototype.
|
|
||||||
*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN KIRQL Irql,
|
|
||||||
IN ULONG Increment)
|
|
||||||
{
|
|
||||||
LONG OldOffset;
|
|
||||||
LARGE_INTEGER Time;
|
|
||||||
ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);
|
|
||||||
if (!KiClockSetupComplete) return;
|
|
||||||
|
|
||||||
/* Update interrupt time */
|
|
||||||
Time.LowPart = SharedUserData->InterruptTime.LowPart;
|
|
||||||
Time.HighPart = SharedUserData->InterruptTime.High1Time;
|
|
||||||
Time.QuadPart += Increment;
|
|
||||||
SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
|
|
||||||
SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
|
|
||||||
SharedUserData->InterruptTime.High1Time = Time.u.HighPart;
|
|
||||||
|
|
||||||
/* Increase the tick offset */
|
|
||||||
KiTickOffset -= Increment;
|
|
||||||
OldOffset = KiTickOffset;
|
|
||||||
|
|
||||||
/* Check if this isn't a tick yet */
|
|
||||||
if (KiTickOffset > 0)
|
|
||||||
{
|
|
||||||
/* Expire timers */
|
|
||||||
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Setup time structure for system time */
|
|
||||||
Time.LowPart = SharedUserData->SystemTime.LowPart;
|
|
||||||
Time.HighPart = SharedUserData->SystemTime.High1Time;
|
|
||||||
Time.QuadPart += KeTimeAdjustment;
|
|
||||||
SharedUserData->SystemTime.High2Time = Time.HighPart;
|
|
||||||
SharedUserData->SystemTime.LowPart = Time.LowPart;
|
|
||||||
SharedUserData->SystemTime.High1Time = Time.HighPart;
|
|
||||||
|
|
||||||
/* Setup time structure for tick time */
|
|
||||||
Time.LowPart = KeTickCount.LowPart;
|
|
||||||
Time.HighPart = KeTickCount.High1Time;
|
|
||||||
Time.QuadPart += 1;
|
|
||||||
KeTickCount.High2Time = Time.HighPart;
|
|
||||||
KeTickCount.LowPart = Time.LowPart;
|
|
||||||
KeTickCount.High1Time = Time.HighPart;
|
|
||||||
SharedUserData->TickCount.High2Time = Time.HighPart;
|
|
||||||
SharedUserData->TickCount.LowPart = Time.LowPart;
|
|
||||||
SharedUserData->TickCount.High1Time = Time.HighPart;
|
|
||||||
|
|
||||||
/* Update tick count in shared user data as well */
|
|
||||||
SharedUserData->TickCountLowDeprecated++;
|
|
||||||
|
|
||||||
/* Queue a DPC that will expire timers */
|
|
||||||
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update process and thread times */
|
|
||||||
if (OldOffset <= 0)
|
|
||||||
{
|
|
||||||
/* This was a tick, calculate the next one */
|
|
||||||
KiTickOffset += KeMaximumIncrement;
|
|
||||||
KeUpdateRunTime(TrapFrame, Irql);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
|
KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
|
||||||
/*
|
/*
|
||||||
|
@ -453,9 +228,7 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
KIRQL old_level;
|
KIRQL old_level;
|
||||||
KTRAP_FRAME KernelTrapFrame;
|
|
||||||
PKTHREAD CurrentThread;
|
PKTHREAD CurrentThread;
|
||||||
PKTRAP_FRAME OldTrapFrame=NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point we have interrupts disabled, nothing has been done to
|
* At this point we have interrupts disabled, nothing has been done to
|
||||||
|
@ -482,20 +255,12 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
||||||
*/
|
*/
|
||||||
_enable();
|
_enable();
|
||||||
|
|
||||||
#ifndef CONFIG_SMP
|
ASSERT (VECTOR2IRQ(vector) != 0);
|
||||||
if (VECTOR2IRQ(vector) == 0)
|
|
||||||
{
|
|
||||||
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
|
||||||
KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* Actually call the ISR.
|
* Actually call the ISR.
|
||||||
*/
|
*/
|
||||||
KiInterruptDispatch2(vector, old_level);
|
KiInterruptDispatch2(vector, old_level);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End the system interrupt.
|
* End the system interrupt.
|
||||||
|
@ -514,23 +279,14 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
||||||
((PETHREAD)CurrentThread)->Cid.UniqueThread,
|
((PETHREAD)CurrentThread)->Cid.UniqueThread,
|
||||||
Trapframe->Cs,
|
Trapframe->Cs,
|
||||||
CurrentThread->TrapFrame ? CurrentThread->TrapFrame->SegCs : 0);
|
CurrentThread->TrapFrame ? CurrentThread->TrapFrame->SegCs : 0);
|
||||||
if (CurrentThread->TrapFrame == NULL)
|
ASSERT (CurrentThread->TrapFrame);
|
||||||
{
|
|
||||||
OldTrapFrame = CurrentThread->TrapFrame;
|
|
||||||
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
|
||||||
CurrentThread->TrapFrame = &KernelTrapFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
_enable();
|
_enable();
|
||||||
KiDeliverApc(UserMode, NULL, NULL);
|
KiDeliverApc(UserMode, NULL, NULL);
|
||||||
_disable();
|
_disable();
|
||||||
|
|
||||||
ASSERT(KeGetCurrentThread() == CurrentThread);
|
ASSERT(KeGetCurrentThread() == CurrentThread);
|
||||||
if (CurrentThread->TrapFrame == &KernelTrapFrame)
|
ASSERT (CurrentThread->TrapFrame);
|
||||||
{
|
|
||||||
KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
|
|
||||||
CurrentThread->TrapFrame = OldTrapFrame;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
KeLowerIrql(PASSIVE_LEVEL);
|
KeLowerIrql(PASSIVE_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
|
||||||
|
|
||||||
/* Set the system affinity and acquire the dispatcher lock */
|
/* Set the system affinity and acquire the dispatcher lock */
|
||||||
KeSetSystemAffinityThread(1 << Number);
|
KeSetSystemAffinityThread(1 << Number);
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KiAcquireDispatcherLock();
|
||||||
|
|
||||||
/* Check if it's already been connected */
|
/* Check if it's already been connected */
|
||||||
if (!Interrupt->Connected)
|
if (!Interrupt->Connected)
|
||||||
|
@ -272,7 +272,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the dispatcher and revert affinity */
|
/* Unlock the dispatcher and revert affinity */
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KiReleaseDispatcherLock(OldIrql);
|
||||||
KeRevertToUserAffinityThread();
|
KeRevertToUserAffinityThread();
|
||||||
|
|
||||||
/* Return to caller */
|
/* Return to caller */
|
||||||
|
@ -296,7 +296,7 @@ KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
|
||||||
KeSetSystemAffinityThread(1 << Interrupt->Number);
|
KeSetSystemAffinityThread(1 << Interrupt->Number);
|
||||||
|
|
||||||
/* Lock the dispatcher */
|
/* Lock the dispatcher */
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KiAcquireDispatcherLock();
|
||||||
|
|
||||||
/* Check if it's actually connected */
|
/* Check if it's actually connected */
|
||||||
State = Interrupt->Connected;
|
State = Interrupt->Connected;
|
||||||
|
@ -354,7 +354,7 @@ KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the dispatcher and revert affinity */
|
/* Unlock the dispatcher and revert affinity */
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KiReleaseDispatcherLock(OldIrql);
|
||||||
KeRevertToUserAffinityThread();
|
KeRevertToUserAffinityThread();
|
||||||
|
|
||||||
/* Return to caller */
|
/* Return to caller */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue