Author: ion Date: Tue Nov 28 11:11:14 2006 New Revision: 24908
URL: http://svn.reactos.org/svn/reactos?rev=24908&view=rev Log: - 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.
Modified: trunk/reactos/hal/hal/hal.c trunk/reactos/hal/hal/hal.def trunk/reactos/hal/halx86/generic/generic.rbuild trunk/reactos/hal/halx86/generic/halinit.c trunk/reactos/hal/halx86/generic/irq.S trunk/reactos/hal/halx86/generic/irql.c trunk/reactos/hal/halx86/generic/systimer.S trunk/reactos/hal/halx86/generic/timer.c trunk/reactos/hal/halx86/include/halp.h trunk/reactos/include/ndk/asm.h trunk/reactos/ntoskrnl/deprecated/irq.c trunk/reactos/ntoskrnl/ke/i386/irq.c
Modified: trunk/reactos/hal/hal/hal.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/hal/hal.c?rev=24908&... ============================================================================== --- trunk/reactos/hal/hal/hal.c (original) +++ trunk/reactos/hal/hal/hal.c Tue Nov 28 11:11:14 2006 @@ -173,7 +173,8 @@ VOID NTAPI HalCalibratePerformanceCounter( - ULONG Count) + volatile LONG *Count, + ULONGLONG NewCount) { UNIMPLEMENTED; }
Modified: trunk/reactos/hal/hal/hal.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/hal/hal.def?rev=24908&a... ============================================================================== --- trunk/reactos/hal/hal/hal.def (original) +++ trunk/reactos/hal/hal/hal.def Tue Nov 28 11:11:14 2006 @@ -30,7 +30,7 @@ HalAllocateCrashDumpRegisters@8 HalAssignSlotResources@32 HalBeginSystemInterrupt@12 -HalCalibratePerformanceCounter@4 +HalCalibratePerformanceCounter@12 HalDisableSystemInterrupt@8 HalDisplayString@4 HalEnableSystemInterrupt@12
Modified: trunk/reactos/hal/halx86/generic/generic.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/generic.... ============================================================================== --- trunk/reactos/hal/halx86/generic/generic.rbuild (original) +++ trunk/reactos/hal/halx86/generic/generic.rbuild Tue Nov 28 11:11:14 2006 @@ -17,6 +17,7 @@ <file>sysbus.c</file> <file>sysinfo.c</file> <file>timer.c</file> + <file>systimer.S</file> <pch>../include/hal.h</pch> </module> <module name="hal_generic_up" type="objectlibrary"> @@ -28,7 +29,6 @@ <file>irql.c</file> <file>processor.c</file> <file>spinlock.c</file> - <file>systimer.S</file> </module> <module name="hal_generic_pc" type="objectlibrary"> <include base="hal_generic_pc">../include</include>
Modified: trunk/reactos/hal/halx86/generic/halinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/halinit.... ============================================================================== --- trunk/reactos/hal/halx86/generic/halinit.c (original) +++ trunk/reactos/hal/halx86/generic/halinit.c Tue Nov 28 11:11:14 2006 @@ -113,7 +113,7 @@ HalpInitNonBusHandler();
/* Initialize the clock interrupt */ - //HalpInitPhase1(); + HalpInitPhase1();
/* Initialize DMA. NT does this in Phase 0 */ HalpInitDma();
Modified: trunk/reactos/hal/halx86/generic/irq.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/irq.S?re... ============================================================================== --- trunk/reactos/hal/halx86/generic/irq.S (original) +++ trunk/reactos/hal/halx86/generic/irq.S Tue Nov 28 11:11:14 2006 @@ -67,18 +67,21 @@ .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,25 +150,38 @@ ret .endfunc
-.globl @HalRequestSoftwareInterrupt@4 -.func @HalRequestSoftwareInterrupt@4 -_@HalRequestSoftwareInterrupt@4: -@HalRequestSoftwareInterrupt@4: +.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 +@HalRequestSoftwareInterrupt@4: + + /* Get IRR mask */ + mov eax, 1 + shl eax, cl
/* Disable interrupts */ pushf 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 @@ 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 @@ 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 @@ Invalid:
/* Fail, invalid IRQ */ +#if DBG int 3 +#endif xor eax, eax ret 12 .endfunc @@ -291,7 +309,7 @@ _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 @@ 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 @@ 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 @@
/* 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 @@ 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 @@ /* Save flags since we'll disable interrupts */ pushf
+ /* Validate IRQL */ + movzx ecx, cl +#if DBG + cmp cl, PCR[KPCR_IRQL] + ja InvalidIrql +#endif + /* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */ - movzx ecx, cl - cmp dword ptr [fs:KPCR_IRQL], 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 @@ 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 @@ /* 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 @@ _@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 @@ 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 @@ SetIrql:
/* Set the IRQL and return */ - mov [fs:KPCR_IRQL], ecx - ret + 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 @@ _KeGetCurrentIrql@0:
/* Return the IRQL */ - mov eax, [fs:KPCR_IRQL] + movzx eax, byte ptr PCR[KPCR_IRQL] ret .endfunc
@@ -499,11 +564,29 @@ _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 - ret + 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 @@
/* 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 - ret + +#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 @@ _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 @@ _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 @@
/* 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
Modified: trunk/reactos/hal/halx86/generic/irql.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/irql.c?r... ============================================================================== --- trunk/reactos/hal/halx86/generic/irql.c (original) +++ trunk/reactos/hal/halx86/generic/irql.c Tue Nov 28 11:11:14 2006 @@ -96,8 +96,8 @@ 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 @@ KIRQL STDCALL KeRaiseIrqlToSynchLevel (VOID) { - return KfRaiseIrql (CLOCK2_LEVEL); + return KfRaiseIrql (DISPATCH_LEVEL); }
Modified: trunk/reactos/hal/halx86/generic/systimer.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/systimer... ============================================================================== --- trunk/reactos/hal/halx86/generic/systimer.S (original) +++ trunk/reactos/hal/halx86/generic/systimer.S Tue Nov 28 11:11:14 2006 @@ -10,8 +10,40 @@ #include <asm.h> #include <internal/i386/asmmacro.S> .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 @@ -35,7 +67,8 @@ jz Spurious
/* Do a tick */ - mov eax, 100000 + mov eax, _HalpCurrentTimeIncrement + xor ebx, ebx jmp _KeUpdateSystemTime@0
Spurious:
Modified: trunk/reactos/hal/halx86/generic/timer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/timer.c?... ============================================================================== --- trunk/reactos/hal/halx86/generic/timer.c (original) +++ trunk/reactos/hal/halx86/generic/timer.c Tue Nov 28 11:11:14 2006 @@ -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; - -/* FUNCTIONS **************************************************************/ +/* GLOBALS *******************************************************************/ + +BOOLEAN HalpClockSetMSRate; +ULONG HalpCurrentTimeIncrement; +ULONG HalpCurrentRollOver; +ULONG HalpNextMSRate = 14; +ULONG HalpLargestClockMS = 15; + +LARGE_INTEGER HalpRolloverTable[15] = +{ + {{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}} +}; + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +NTAPI +HalpInitializeClock(VOID) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + ULONG Increment; + USHORT RollOver; + + /* 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; +} + +/* PUBLIC FUNCTIONS ***********************************************************/
/* - * 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) - { - return; - } -#if defined(__GNUC__) - __asm__ __volatile__ ( - "mov %0, %%eax\n" - "ROSL1: dec %%eax\n" - "jnz ROSL1" : : "d" (Loops)); - -#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; i<target;i++); -#endif -} - + * @implemented + */ VOID -STDCALL -KeStallExecutionProcessor(ULONG Microseconds) -{ - PKIPCR Pcr = (PKIPCR)KeGetPcr(); - - if (Pcr->PrcbData.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); - } -} - -static ULONG Read8254Timer(VOID) -{ - ULONG Count; - - /* Disable interrupts */ - _disable(); - - 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; - - _enable(); - return Count; -} - +NTAPI +HalCalibratePerformanceCounter(IN volatile PLONG Count, + IN ULONGLONG NewCount) +{ + /* Disable interrupts */ + _disable(); + + /* Do a decrement for this CPU */ + //_InterlockedDecrement(Count); + InterlockedDecrement(Count); + + /* Wait for other CPUs */ + while (*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 @@ 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 @@ PKIPCR Pcr; LARGE_INTEGER StartCount, EndCount;
- if (UdelayCalibrated) - { - return; - } - - UdelayCalibrated = TRUE; Pcr = (PKIPCR)KeGetPcr();
if (Pcr->PrcbData.FeatureBits & KF_RDTSC) @@ -242,7 +241,7 @@
WaitFor8254Wraparound();
- __KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */ + KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
CurCount = Read8254Timer(); } @@ -267,7 +266,7 @@
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 */ @@ -294,19 +293,6 @@ for(;;); #endif } - - -VOID STDCALL -HalCalibratePerformanceCounter(ULONG Count) -{ - /* Disable interrupts */ - _disable(); - - __KeStallExecutionProcessor(Count); - - _enable(); -} -
LARGE_INTEGER STDCALL @@ -360,12 +346,4 @@ return Value; }
-ULONG -NTAPI -HalSetTimeIncrement(IN ULONG Increment) -{ - /* FIXME: TODO */ - return Increment; -} - /* EOF */
Modified: trunk/reactos/hal/halx86/include/halp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/include/halp.h?r... ============================================================================== --- trunk/reactos/hal/halx86/include/halp.h (original) +++ trunk/reactos/hal/halx86/include/halp.h Tue Nov 28 11:11:14 2006 @@ -21,6 +21,13 @@ #define RTC_REGISTER_B 0x0B #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) \
Modified: trunk/reactos/include/ndk/asm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/asm.h?rev=24908... ============================================================================== --- trunk/reactos/include/ndk/asm.h (original) +++ trunk/reactos/include/ndk/asm.h Tue Nov 28 11:11:14 2006 @@ -19,6 +19,17 @@
#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 @@ #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 @@ #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
Modified: trunk/reactos/ntoskrnl/deprecated/irq.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/deprecated/irq.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/deprecated/irq.c (original) +++ trunk/reactos/ntoskrnl/deprecated/irq.c Tue Nov 28 11:11:14 2006 @@ -177,231 +177,6 @@ } }
-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 @@ */ { 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 @@ */ _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 @@ ((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); }
Modified: trunk/reactos/ntoskrnl/ke/i386/irq.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/irq.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/irq.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/irq.c Tue Nov 28 11:11:14 2006 @@ -226,7 +226,7 @@
/* 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 @@ }
/* Unlock the dispatcher and revert affinity */ - KeReleaseDispatcherDatabaseLock(OldIrql); + KiReleaseDispatcherLock(OldIrql); KeRevertToUserAffinityThread();
/* Return to caller */ @@ -296,7 +296,7 @@ KeSetSystemAffinityThread(1 << Interrupt->Number);
/* Lock the dispatcher */ - OldIrql = KeAcquireDispatcherDatabaseLock(); + OldIrql = KiAcquireDispatcherLock();
/* Check if it's actually connected */ State = Interrupt->Connected; @@ -354,7 +354,7 @@ }
/* Unlock the dispatcher and revert affinity */ - KeReleaseDispatcherDatabaseLock(OldIrql); + KiReleaseDispatcherLock(OldIrql); KeRevertToUserAffinityThread();
/* Return to caller */