diff --git a/reactos/hal/hal/hal.c b/reactos/hal/hal/hal.c index 630a86f6dd4..576097f166c 100644 --- a/reactos/hal/hal/hal.c +++ b/reactos/hal/hal/hal.c @@ -173,7 +173,8 @@ HalBeginSystemInterrupt (KIRQL Irql, VOID NTAPI HalCalibratePerformanceCounter( - ULONG Count) + volatile LONG *Count, + ULONGLONG NewCount) { UNIMPLEMENTED; } diff --git a/reactos/hal/hal/hal.def b/reactos/hal/hal/hal.def index 97878a593e1..c3586628b48 100644 --- a/reactos/hal/hal/hal.def +++ b/reactos/hal/hal/hal.def @@ -30,7 +30,7 @@ HalAllocateCommonBuffer@16 HalAllocateCrashDumpRegisters@8 HalAssignSlotResources@32 HalBeginSystemInterrupt@12 -HalCalibratePerformanceCounter@4 +HalCalibratePerformanceCounter@12 HalDisableSystemInterrupt@8 HalDisplayString@4 HalEnableSystemInterrupt@12 diff --git a/reactos/hal/halx86/generic/generic.rbuild b/reactos/hal/halx86/generic/generic.rbuild index 6e23d9eaad6..ce334a9a34f 100644 --- a/reactos/hal/halx86/generic/generic.rbuild +++ b/reactos/hal/halx86/generic/generic.rbuild @@ -17,6 +17,7 @@ sysbus.c sysinfo.c timer.c + systimer.S ../include/hal.h @@ -28,7 +29,6 @@ irql.c processor.c spinlock.c - systimer.S ../include diff --git a/reactos/hal/halx86/generic/halinit.c b/reactos/hal/halx86/generic/halinit.c index 171434fedcf..e4e1d978eed 100644 --- a/reactos/hal/halx86/generic/halinit.c +++ b/reactos/hal/halx86/generic/halinit.c @@ -113,7 +113,7 @@ HalInitSystem(IN ULONG BootPhase, HalpInitNonBusHandler(); /* Initialize the clock interrupt */ - //HalpInitPhase1(); + HalpInitPhase1(); /* Initialize DMA. NT does this in Phase 0 */ HalpInitDma(); diff --git a/reactos/hal/halx86/generic/irq.S b/reactos/hal/halx86/generic/irq.S index 2cad74774b4..938654768b8 100644 --- a/reactos/hal/halx86/generic/irq.S +++ b/reactos/hal/halx86/generic/irq.S @@ -67,18 +67,21 @@ KiI8259MaskTable: .long 0xFFFFFFFB /* IRQL 31 */ HalpSysIntHandler: -.rept 8 +.rept 7 .long GenericIRQ /* IRQ 0-7 */ .endr .long IRQ7 /* IRQ 7 */ -.rept 8 +.rept 7 .long GenericIRQ /* IRQ 8-15 */ .endr .long IRQ15 /* IRQ 15 */ .rept 20 .long GenericIRQ /* IRQ 16-35 */ +.endr +#if DBG .rept 172 .long InvalidIRQ /* IRQ 36-207 */ +#endif .endr SoftIntByteTable: @@ -147,9 +150,22 @@ InitLoop: ret .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 -.func @HalRequestSoftwareInterrupt@4 -_@HalRequestSoftwareInterrupt@4: +.func @HalRequestSoftwareInterrupt@4, @HalRequestSoftwareInterrupt@4 @HalRequestSoftwareInterrupt@4: /* Get IRR mask */ @@ -161,11 +177,11 @@ _@HalRequestSoftwareInterrupt@4: cli /* Set IRR and get IRQL */ - or [fs:KPCR_IRR], eax - mov ecx, [fs:KPCR_IRQL] + or PCR[KPCR_IRR], eax + mov ecx, PCR[KPCR_IRQL] /* Get software IRR mask */ - mov eax, [fs:KPCR_IRR] + mov eax, PCR[KPCR_IRR] and eax, 3 /* Get highest pending software interrupt and check if it's higher */ @@ -196,7 +212,7 @@ _HalDisableSystemInterrupt@8: mov edx, 1 shl edx, cl cli - or [fs:KPCR_IDR], edx + or PCR[KPCR_IDR], edx /* Get the current mask */ xor eax, eax @@ -263,12 +279,12 @@ AfterMask: shl eax, cl not eax cli - and [fs:KPCR_IDR], eax + and PCR[KPCR_IDR], eax /* 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] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al @@ -281,7 +297,9 @@ AfterMask: Invalid: /* Fail, invalid IRQ */ +#if DBG int 3 +#endif xor eax, eax ret 12 .endfunc @@ -291,7 +309,7 @@ Invalid: _HalBeginSystemInterrupt@12: /* Convert to IRQ and call the handler */ - mov edx, [esp+8] + movzx edx, byte ptr [esp+8] sub edx, PRIMARY_VECTOR_BASE jmp HalpSysIntHandler[edx*4] @@ -326,22 +344,22 @@ IRQ7: GenericIRQ: /* Return the current IRQL */ mov eax, [esp+12] - mov ecx, [fs:KPCR_IRQL] + movzx ecx, byte ptr PCR[KPCR_IRQL] mov [eax], cl /* Set the new IRQL */ movzx eax, byte ptr [esp+4] - mov [fs:KPCR_IRQL], eax + mov PCR[KPCR_IRQL], al /* Set IRQ mask in the PIC */ mov eax, KiI8259MaskTable[eax*4] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al /* Check to which PIC the EOI was sent */ - mov eax, ebx + mov eax, edx cmp eax, 8 jnb Pic1 @@ -363,11 +381,13 @@ DoneBegin: sti mov eax, 1 ret 12 - + +#if DBG InvalidIRQ: /* Dismiss it */ mov eax, 0 ret 12 +#endif .endfunc .globl _HalEndSystemInterrupt@8 @@ -376,12 +396,12 @@ _HalEndSystemInterrupt@8: /* Get the IRQL and check if it's a software interrupt */ movzx ecx, byte ptr [esp+4] - cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL + cmp byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL jbe SkipMask2 /* Hardware interrupt, mask the appropriate IRQs in the PIC */ mov eax, KiI8259MaskTable[ecx*4] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al @@ -389,8 +409,8 @@ _HalEndSystemInterrupt@8: SkipMask2: /* Set IRQL and check if there are pending software interrupts */ - mov [fs:KPCR_IRQL], ecx - mov eax, [fs:KPCR_IRR] + mov PCR[KPCR_IRQL], cl + mov eax, PCR[KPCR_IRR] mov al, SoftIntByteTable[eax] cmp al, cl ja DoCall @@ -411,15 +431,21 @@ _@KfLowerIrql@4: /* Save flags since we'll disable interrupts */ pushf - /* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */ + /* Validate IRQL */ 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 jbe SkipMask /* Clear interrupt masks since there's a pending hardware interrupt */ mov eax, KiI8259MaskTable[ecx*4] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al @@ -427,8 +453,8 @@ _@KfLowerIrql@4: SkipMask: /* Set the new IRQL and check if there's a pending software interrupt */ - mov [fs:KPCR_IRQL], ecx - mov eax, [fs:KPCR_IRR] + mov PCR[KPCR_IRQL], cl + mov eax, PCR[KPCR_IRR] mov al, SoftIntByteTable[eax] cmp al, cl ja DoCall3 @@ -436,6 +462,22 @@ SkipMask: /* Restore interrupts and return */ popf 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: /* There is, call it */ call SoftIntHandlerTable[eax*4] @@ -450,10 +492,19 @@ DoCall3: _@KfRaiseIrql@4: @KfRaiseIrql@4: - /* Get the IRQL and check if it's Software level only */ - mov eax, [fs:KPCR_IRQL] + /* Get the IRQL */ + xor eax, eax + mov al, PCR[KPCR_IRQL] 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 /* Save the current IRQL */ @@ -464,11 +515,11 @@ _@KfRaiseIrql@4: cli /* Set the new IRQL */ - mov [fs:KPCR_IRQL], cl + mov PCR[KPCR_IRQL], cl /* Mask the interrupts in the PIC */ mov eax, KiI8259MaskTable[ecx*4] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al @@ -481,8 +532,22 @@ _@KfRaiseIrql@4: SetIrql: /* Set the IRQL and return */ - mov [fs:KPCR_IRQL], ecx + mov PCR[KPCR_IRQL], cl 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 .globl _KeGetCurrentIrql@0 @@ -490,7 +555,7 @@ SetIrql: _KeGetCurrentIrql@0: /* Return the IRQL */ - mov eax, [fs:KPCR_IRQL] + movzx eax, byte ptr PCR[KPCR_IRQL] ret .endfunc @@ -499,11 +564,29 @@ _KeGetCurrentIrql@0: _KeRaiseIrqlToDpcLevel@0: /* Get the current IRQL */ - mov eax, [fs:KPCR_IRQL] + xor eax, eax + mov al, PCR[KPCR_IRQL] /* 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 + +#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 .globl _KeRaiseIrqlToSynchLevel@0 @@ -516,16 +599,35 @@ _KeRaiseIrqlToSynchLevel@0: /* Mask out interrupts */ mov eax, KiI8259MaskTable[DISPATCH_LEVEL*4] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al /* Return the old IRQL, enable interrupts and set to DISPATCH */ - mov eax, [fs:KPCR_IRQL] - mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL + mov al, PCR[KPCR_IRQL] + mov byte ptr PCR[KPCR_IRQL], DISPATCH_LEVEL popf + +#if DBG + /* Validate raise */ + cmp al, DISPATCH_LEVEL + ja InvalidSyRaise +#endif + + /* Return */ 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 .globl _HalpApcInterrupt @@ -547,9 +649,9 @@ _HalpApcInterrupt: _HalpApcInterrupt2ndEntry: /* Save current IRQL and set to APC level */ - push [fs:KPCR_IRQL] - mov dword ptr [fs:KPCR_IRQL], APC_LEVEL - and dword ptr [fs:KPCR_IRR], ~(1 << APC_LEVEL) + push PCR[KPCR_IRQL] + mov dword ptr PCR[KPCR_IRQL], APC_LEVEL + and dword ptr PCR[KPCR_IRR], ~(1 << APC_LEVEL) /* Enable interrupts and check if we came from User/V86 mode */ sti @@ -594,9 +696,9 @@ _HalpDispatchInterrupt: _HalpDispatchInterrupt2ndEntry: /* Save current IRQL and set to DPC level */ - push [fs:KPCR_IRQL] - mov dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL - and dword ptr [fs:KPCR_IRR], ~(1 << DISPATCH_LEVEL) + push PCR[KPCR_IRQL] + mov dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL + and dword ptr PCR[KPCR_IRR], ~(1 << DISPATCH_LEVEL) /* Enable interrupts and let the kernel handle this */ sti @@ -614,20 +716,20 @@ _HalpEndSoftwareInterrupt@4: /* Get the IRQL and check if we're in the software region */ movzx ecx, byte ptr [esp+4] - cmp dword ptr [fs:KPCR_IRQL], DISPATCH_LEVEL + cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL jbe SoftwareInt /* Set the right mask in the PIC for the hardware IRQ */ mov eax, KiI8259MaskTable[ecx*4] - or eax, [fs:KPCR_IDR] + or eax, PCR[KPCR_IDR] out 0x21, al shr eax, 8 out 0xA1, al SoftwareInt: /* Check if there are pending software interrupts */ - mov [fs:KPCR_IRQL], ecx - mov eax, [fs:KPCR_IRR] + mov PCR[KPCR_IRQL], ecx + mov eax, PCR[KPCR_IRR] mov al, SoftIntByteTable[eax] cmp al, cl ja DoCall2 diff --git a/reactos/hal/halx86/generic/irql.c b/reactos/hal/halx86/generic/irql.c index 673d72c85cc..fab62c6df22 100644 --- a/reactos/hal/halx86/generic/irql.c +++ b/reactos/hal/halx86/generic/irql.c @@ -96,8 +96,8 @@ VOID NTAPI HalpInitPICs(VOID) WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1); WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1); /* Enable interrupts */ - WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master); - WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave); + WRITE_PORT_UCHAR((PUCHAR)0x21, 0xFF); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xFF); /* We can now enable interrupts */ _enable(); @@ -305,7 +305,7 @@ KeRaiseIrqlToDpcLevel (VOID) KIRQL STDCALL KeRaiseIrqlToSynchLevel (VOID) { - return KfRaiseIrql (CLOCK2_LEVEL); + return KfRaiseIrql (DISPATCH_LEVEL); } diff --git a/reactos/hal/halx86/generic/systimer.S b/reactos/hal/halx86/generic/systimer.S index eb638d7dfee..03bae396fc2 100644 --- a/reactos/hal/halx86/generic/systimer.S +++ b/reactos/hal/halx86/generic/systimer.S @@ -10,9 +10,41 @@ #include #include .intel_syntax noprefix +.extern _HalpCurrentTimeIncrement /* 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 .func HalpClockInterrupt@0 _HalpClockInterrupt@0: @@ -35,7 +67,8 @@ _HalpClockInterrupt@0: jz Spurious /* Do a tick */ - mov eax, 100000 + mov eax, _HalpCurrentTimeIncrement + xor ebx, ebx jmp _KeUpdateSystemTime@0 Spurious: diff --git a/reactos/hal/halx86/generic/timer.c b/reactos/hal/halx86/generic/timer.c index 3ffc6eeec98..7ba249d0168 100644 --- a/reactos/hal/halx86/generic/timer.c +++ b/reactos/hal/halx86/generic/timer.c @@ -38,127 +38,146 @@ /* 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 HZ (1000 / MILLISEC) /* Number of interrupts per second */ #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 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; -/* - * 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) +LARGE_INTEGER HalpRolloverTable[15] = { - if (!Loops) - { - return; - } -#if defined(__GNUC__) - __asm__ __volatile__ ( - "mov %0, %%eax\n" - "ROSL1: dec %%eax\n" - "jnz ROSL1" : : "d" (Loops)); + {{1197, 10032}}, + {{2394, 20064}}, + {{3591, 30096}}, + {{4767, 39952}}, + {{5964, 49984}}, + {{7161, 60016}}, + {{8358, 70048}}, + {{9555, 80080}}, + {{10731, 89936}}, + {{11949, 100144}}, + {{13125, 110000}}, + {{14322, 120032}}, + {{15519, 130064}}, + {{16695, 139920}}, + {{17892, 149952}} +}; -#elif defined(_MSC_VER) - __asm mov eax, Loops -ROSL1: - __asm dec eax - __asm jnz ROSL1 -#else - unsigned int target = Loops; - volatile unsigned int i; - for (i=0; iPrcbData.FeatureBits & KF_RDTSC) - { - LARGE_INTEGER EndCount, CurrentCount; - EndCount.QuadPart = (LONGLONG)__rdtsc(); - EndCount.QuadPart += Microseconds * (ULONGLONG)Pcr->PrcbData.MHz; - do - { - CurrentCount.QuadPart = (LONGLONG)__rdtsc(); - } - while (CurrentCount.QuadPart < EndCount.QuadPart); - } - else - { - __KeStallExecutionProcessor((Pcr->StallScaleFactor*Microseconds)/1000); - } + /* Check the CPU Type */ + if (Prcb->CpuType <= 4) + { + /* 486's or equal can't go higher then 10ms */ + HalpLargestClockMS = 10; + HalpNextMSRate = 9; + } + + /* Get increment and rollover for the largest time clock ms possible */ + Increment= HalpRolloverTable[HalpLargestClockMS - 1].HighPart; + RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart; + + /* Set the maximum and minimum increment with the kernel */ + 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 */ - _disable(); + /* Do a decrement for this CPU */ + //_InterlockedDecrement(Count); + InterlockedDecrement(Count); - WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_LATCH); - Count = READ_PORT_UCHAR((PUCHAR) TMR_CNT0); - Count |= READ_PORT_UCHAR((PUCHAR) TMR_CNT0) << 8; + /* Wait for other CPUs */ + while (*Count); - _enable(); - return Count; + /* Bring interrupts back */ + _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) { @@ -183,20 +202,6 @@ VOID WaitFor8254Wraparound(VOID) 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) { ULONG i; @@ -205,12 +210,6 @@ VOID HalpCalibrateStallExecution(VOID) PKIPCR Pcr; LARGE_INTEGER StartCount, EndCount; - if (UdelayCalibrated) - { - return; - } - - UdelayCalibrated = TRUE; Pcr = (PKIPCR)KeGetPcr(); if (Pcr->PrcbData.FeatureBits & KF_RDTSC) @@ -242,7 +241,7 @@ VOID HalpCalibrateStallExecution(VOID) WaitFor8254Wraparound(); - __KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */ + KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */ CurCount = Read8254Timer(); } @@ -267,7 +266,7 @@ VOID HalpCalibrateStallExecution(VOID) WaitFor8254Wraparound(); - __KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */ + KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */ CurCount = Read8254Timer(); if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */ @@ -295,19 +294,6 @@ VOID HalpCalibrateStallExecution(VOID) #endif } - -VOID STDCALL -HalCalibratePerformanceCounter(ULONG Count) -{ - /* Disable interrupts */ - _disable(); - - __KeStallExecutionProcessor(Count); - - _enable(); -} - - LARGE_INTEGER STDCALL KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq) @@ -360,12 +346,4 @@ KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq) return Value; } -ULONG -NTAPI -HalSetTimeIncrement(IN ULONG Increment) -{ - /* FIXME: TODO */ - return Increment; -} - /* EOF */ diff --git a/reactos/hal/halx86/include/halp.h b/reactos/hal/halx86/include/halp.h index cd2043c3d0d..a1be71641fb 100644 --- a/reactos/hal/halx86/include/halp.h +++ b/reactos/hal/halx86/include/halp.h @@ -22,6 +22,13 @@ #define RTC_REG_A_UIP 0x80 #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 */ #define BCD_INT(bcd) \ (((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F)) diff --git a/reactos/include/ndk/asm.h b/reactos/include/ndk/asm.h index 5851bcaa5ad..b4c9177c8bd 100644 --- a/reactos/include/ndk/asm.h +++ b/reactos/include/ndk/asm.h @@ -20,6 +20,17 @@ Author: #ifndef _ASM_H #define _ASM_H +// +// PCR Access +// +#ifdef __ASM__ +#ifdef CONFIG_SMP +#define PCR fs: +#else +#define PCR ds:[0xFF000000] +#endif +#endif + // // CPU Modes // @@ -145,6 +156,7 @@ Author: #define KPCR_IDT 0x38 #define KPCR_GDT 0x3C #define KPCR_TSS 0x40 +#define KPCR_STALL_SCALE_FACTOR 0x4C #define KPCR_SET_MEMBER 0x48 #define KPCR_NUMBER 0x51 #define KPCR_PRCB_DATA 0x120 @@ -489,6 +501,8 @@ Author: #define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4 #define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5 #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 KMODE_EXCEPTION_NOT_HANDLED 0x13 #define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A diff --git a/reactos/ntoskrnl/deprecated/irq.c b/reactos/ntoskrnl/deprecated/irq.c index 26b0056b32c..f7e2a586959 100644 --- a/reactos/ntoskrnl/deprecated/irq.c +++ b/reactos/ntoskrnl/deprecated/irq.c @@ -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 KiInterruptDispatch2 (ULONG vector, KIRQL old_level) /* @@ -453,9 +228,7 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe) */ { KIRQL old_level; - KTRAP_FRAME KernelTrapFrame; PKTHREAD CurrentThread; - PKTRAP_FRAME OldTrapFrame=NULL; /* * At this point we have interrupts disabled, nothing has been done to @@ -482,20 +255,12 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe) */ _enable(); -#ifndef CONFIG_SMP - if (VECTOR2IRQ(vector) == 0) - { - KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); - KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000); - } - else -#endif - { + ASSERT (VECTOR2IRQ(vector) != 0); + /* * Actually call the ISR. */ KiInterruptDispatch2(vector, old_level); - } /* * End the system interrupt. @@ -514,23 +279,14 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe) ((PETHREAD)CurrentThread)->Cid.UniqueThread, Trapframe->Cs, CurrentThread->TrapFrame ? CurrentThread->TrapFrame->SegCs : 0); - if (CurrentThread->TrapFrame == NULL) - { - OldTrapFrame = CurrentThread->TrapFrame; - KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); - CurrentThread->TrapFrame = &KernelTrapFrame; - } + ASSERT (CurrentThread->TrapFrame); _enable(); KiDeliverApc(UserMode, NULL, NULL); _disable(); ASSERT(KeGetCurrentThread() == CurrentThread); - if (CurrentThread->TrapFrame == &KernelTrapFrame) - { - KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe); - CurrentThread->TrapFrame = OldTrapFrame; - } + ASSERT (CurrentThread->TrapFrame); } KeLowerIrql(PASSIVE_LEVEL); } diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index 5954322df6b..9b07ea9127b 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -226,7 +226,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt) /* Set the system affinity and acquire the dispatcher lock */ KeSetSystemAffinityThread(1 << Number); - OldIrql = KeAcquireDispatcherDatabaseLock(); + OldIrql = KiAcquireDispatcherLock(); /* Check if it's already been connected */ if (!Interrupt->Connected) @@ -272,7 +272,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt) } /* Unlock the dispatcher and revert affinity */ - KeReleaseDispatcherDatabaseLock(OldIrql); + KiReleaseDispatcherLock(OldIrql); KeRevertToUserAffinityThread(); /* Return to caller */ @@ -296,7 +296,7 @@ KeDisconnectInterrupt(IN PKINTERRUPT Interrupt) KeSetSystemAffinityThread(1 << Interrupt->Number); /* Lock the dispatcher */ - OldIrql = KeAcquireDispatcherDatabaseLock(); + OldIrql = KiAcquireDispatcherLock(); /* Check if it's actually connected */ State = Interrupt->Connected; @@ -354,7 +354,7 @@ KeDisconnectInterrupt(IN PKINTERRUPT Interrupt) } /* Unlock the dispatcher and revert affinity */ - KeReleaseDispatcherDatabaseLock(OldIrql); + KiReleaseDispatcherLock(OldIrql); KeRevertToUserAffinityThread(); /* Return to caller */