mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
[ntoskrnl]
- Reimplement HalpCalibrateStallExecution which was removed in r24964. Real Windows uses a different algorithm, however existing one seems to work acceptably. This patch is critical for devices support on real hardware. The only downside is that uniata initialization takes a substantial amount of time now, this is going to be investigated. Patch by Daniel Zimmermann. See issue #4600 for more details. svn path=/trunk/; revision=43364
This commit is contained in:
@@ -101,7 +101,7 @@ HalInitSystem(IN ULONG BootPhase,
|
||||
HalpInitializeClock();
|
||||
|
||||
/* Setup busy waiting */
|
||||
//HalpCalibrateStallExecution();
|
||||
HalpCalibrateStallExecution();
|
||||
|
||||
/* Fill out the dispatch tables */
|
||||
HalQuerySystemInformation = HaliQuerySystemInformation;
|
||||
|
||||
@@ -54,6 +54,34 @@ Done:
|
||||
ret 4
|
||||
.endfunc
|
||||
|
||||
|
||||
.globl _HalpQuery8254Counter@0
|
||||
.func HalpQuery8254Counter@0
|
||||
_HalpQuery8254Counter@0:
|
||||
|
||||
/* Save EFLAGS and disable interrupts */
|
||||
pushfd
|
||||
cli
|
||||
|
||||
/* Set timer data */
|
||||
mov al, 0
|
||||
out 0x43, al
|
||||
jmp $+2
|
||||
|
||||
/* Read current timer */
|
||||
in al, 0x40
|
||||
jmp $+2
|
||||
movzx ecx, al
|
||||
in al, 0x40
|
||||
mov ch, al
|
||||
|
||||
/* Return it and restore interrupt state */
|
||||
mov eax, ecx
|
||||
popfd
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
.global _KeQueryPerformanceCounter@4
|
||||
.func KeQueryPerformanceCounter@4
|
||||
_KeQueryPerformanceCounter@4:
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* time to wait */
|
||||
#define MICROSECOND_TO_WAIT 1000
|
||||
/* the tick count for 1 ms is 1193.182 (1193182 Hz) round it up */
|
||||
#define TICKCOUNT_TO_WAIT 1194
|
||||
|
||||
BOOLEAN HalpClockSetMSRate;
|
||||
ULONG HalpCurrentTimeIncrement;
|
||||
ULONG HalpCurrentRollOver;
|
||||
@@ -130,4 +135,161 @@ HalSetTimeIncrement(IN ULONG Increment)
|
||||
return HalpRolloverTable[Increment - 1].HighPart;
|
||||
}
|
||||
|
||||
ULONG
|
||||
WaitFor8254Wraparound(VOID)
|
||||
{
|
||||
ULONG StartTicks;
|
||||
ULONG PrevTicks;
|
||||
LONG Delta;
|
||||
|
||||
StartTicks = HalpQuery8254Counter();
|
||||
|
||||
do
|
||||
{
|
||||
PrevTicks = StartTicks;
|
||||
StartTicks = HalpQuery8254Counter();
|
||||
Delta = StartTicks - PrevTicks;
|
||||
|
||||
/*
|
||||
* This limit for delta seems arbitrary, but it isn't, it's
|
||||
* slightly above the level of error a buggy Mercury/Neptune
|
||||
* chipset timer can cause.
|
||||
*/
|
||||
|
||||
}
|
||||
while (Delta < 300);
|
||||
|
||||
return StartTicks;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpCalibrateStallExecution(VOID)
|
||||
{
|
||||
ULONG CalibrationBit;
|
||||
ULONG EndTicks;
|
||||
ULONG StartTicks;
|
||||
ULONG OverheadTicks;
|
||||
PKIPCR Pcr;
|
||||
|
||||
Pcr = (PKIPCR)KeGetPcr();
|
||||
|
||||
/* Measure the delay for the minimum call overhead in ticks */
|
||||
Pcr->StallScaleFactor = 1;
|
||||
StartTicks = WaitFor8254Wraparound();
|
||||
KeStallExecutionProcessor(1);
|
||||
EndTicks = HalpQuery8254Counter();
|
||||
OverheadTicks = (StartTicks - EndTicks);
|
||||
|
||||
do
|
||||
{
|
||||
/* Increase the StallScaleFactor */
|
||||
Pcr->StallScaleFactor = Pcr->StallScaleFactor * 2;
|
||||
|
||||
if (Pcr->StallScaleFactor == 0)
|
||||
{
|
||||
/* Nothing found */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the start ticks */
|
||||
StartTicks = WaitFor8254Wraparound();
|
||||
|
||||
/* Wait for a defined time */
|
||||
KeStallExecutionProcessor(MICROSECOND_TO_WAIT);
|
||||
|
||||
/* Get the end ticks */
|
||||
EndTicks = HalpQuery8254Counter();
|
||||
|
||||
DPRINT("Pcr->StallScaleFactor: %d\n", Pcr->StallScaleFactor);
|
||||
DPRINT("Time1 : StartTicks %i - EndTicks %i = %i\n",
|
||||
StartTicks, EndTicks, StartTicks - EndTicks);
|
||||
} while ((StartTicks - EndTicks) <= (TICKCOUNT_TO_WAIT + OverheadTicks));
|
||||
|
||||
/* A StallScaleFactor lesser than INITIAL_STALL_COUNT makes no sense */
|
||||
if (Pcr->StallScaleFactor >= (INITIAL_STALL_COUNT * 2))
|
||||
{
|
||||
/* Adjust the StallScaleFactor */
|
||||
Pcr->StallScaleFactor = Pcr->StallScaleFactor / 2;
|
||||
|
||||
/* Setup the CalibrationBit */
|
||||
CalibrationBit = Pcr->StallScaleFactor;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Lower the CalibrationBit */
|
||||
CalibrationBit = CalibrationBit / 2;
|
||||
if (CalibrationBit == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add the CalibrationBit */
|
||||
Pcr->StallScaleFactor = Pcr->StallScaleFactor + CalibrationBit;
|
||||
|
||||
/* Get the start ticks */
|
||||
StartTicks = WaitFor8254Wraparound();
|
||||
|
||||
/* Wait for a defined time */
|
||||
KeStallExecutionProcessor(MICROSECOND_TO_WAIT);
|
||||
|
||||
/* Get the end ticks */
|
||||
EndTicks = HalpQuery8254Counter();
|
||||
|
||||
DPRINT("Pcr->StallScaleFactor: %d\n", Pcr->StallScaleFactor);
|
||||
DPRINT("Time2 : StartTicks %i - EndTicks %i = %i\n",
|
||||
StartTicks, EndTicks, StartTicks - EndTicks);
|
||||
|
||||
if ((StartTicks-EndTicks) > (TICKCOUNT_TO_WAIT+OverheadTicks))
|
||||
{
|
||||
/* Too big so subtract the CalibrationBit */
|
||||
Pcr->StallScaleFactor = Pcr->StallScaleFactor - CalibrationBit;
|
||||
}
|
||||
}
|
||||
DPRINT("New StallScaleFactor: %d\n", Pcr->StallScaleFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set StallScaleFactor to the default */
|
||||
Pcr->StallScaleFactor = INITIAL_STALL_COUNT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* For debugging */
|
||||
ULONG i;
|
||||
|
||||
DPRINT1("About to start delay loop test\n");
|
||||
DPRINT1("Waiting for a minute...");
|
||||
for (i = 0; i < (60*1000*20); i++)
|
||||
{
|
||||
KeStallExecutionProcessor(50);
|
||||
}
|
||||
DPRINT1("finished\n");
|
||||
|
||||
|
||||
DPRINT1("About to start delay loop test\n");
|
||||
DPRINT1("Waiting for a minute...");
|
||||
for (i = 0; i < (60*1000); i++)
|
||||
{
|
||||
KeStallExecutionProcessor(1000);
|
||||
}
|
||||
DPRINT1("finished\n");
|
||||
|
||||
|
||||
DPRINT1("About to start delay loop test\n");
|
||||
DPRINT1("Waiting for a minute...");
|
||||
for (i = 0; i < (60*1000*1000); i++)
|
||||
{
|
||||
KeStallExecutionProcessor(1);
|
||||
}
|
||||
DPRINT1("finished\n");
|
||||
|
||||
DPRINT1("About to start delay loop test\n");
|
||||
DPRINT1("Waiting for a minute...");
|
||||
KeStallExecutionProcessor(60*1000000);
|
||||
DPRINT1("finished\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -41,6 +41,16 @@ VOID NTAPI HalpInitPICs(VOID);
|
||||
/* udelay.c */
|
||||
VOID NTAPI HalpInitializeClock(VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpCalibrateStallExecution(VOID);
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
HalpQuery8254Counter(
|
||||
VOID
|
||||
);
|
||||
|
||||
/* pci.c */
|
||||
VOID HalpInitPciBus (VOID);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user