Revert a previous incorrect fix for the PIT.
Modify the PitDecrementCount function to take a parameter instead
of it being called multiple times (which is slower).


svn path=/branches/ntvdm/; revision=60816
This commit is contained in:
Aleksandar Andrejevic 2013-11-01 01:57:40 +00:00
parent f62b9a81d4
commit 90d7fbd4a8
3 changed files with 92 additions and 49 deletions

View file

@ -140,35 +140,20 @@ INT wmain(INT argc, WCHAR *argv[])
/* Main loop */ /* Main loop */
while (VdmRunning) while (VdmRunning)
{ {
/* Get the resolution of the system timer */
DWORD TimerResolution = PitGetResolution();
/* Get the current number of ticks */ /* Get the current number of ticks */
CurrentTickCount = GetTickCount(); CurrentTickCount = GetTickCount();
if (TimerResolution > 1000) /* Get the current performance counter value */
{ QueryPerformanceCounter(&Counter);
/* Get the current performance counter value */
QueryPerformanceCounter(&Counter);
/* Get the number of PIT ticks that have passed */ /* Get the number of PIT ticks that have passed */
TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart) TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart)
* PIT_BASE_FREQUENCY) / Frequency.QuadPart; * PIT_BASE_FREQUENCY) / Frequency.QuadPart;
}
else
{
/* Use the standard tick count */
Counter.QuadPart = CurrentTickCount;
/* Get the number of PIT ticks that have passed */
TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart)
* PIT_BASE_FREQUENCY) / 1000;
}
/* Update the PIT */ /* Update the PIT */
if (TimerTicks > 0) if (TimerTicks > 0)
{ {
for (i = 0; i < TimerTicks; i++) PitDecrementCount(); PitDecrementCount(TimerTicks);
LastTimerTick = Counter; LastTimerTick = Counter;
} }

View file

@ -146,7 +146,7 @@ VOID PitWriteData(BYTE Channel, BYTE Value)
} }
} }
VOID PitDecrementCount() VOID PitDecrementCount(DWORD Count)
{ {
INT i; INT i;
@ -157,7 +157,12 @@ VOID PitDecrementCount()
case PIT_MODE_INT_ON_TERMINAL_COUNT: case PIT_MODE_INT_ON_TERMINAL_COUNT:
{ {
/* Decrement the value */ /* Decrement the value */
PitChannels[i].CurrentValue--; if (Count > PitChannels[i].CurrentValue)
{
/* The value does not reload in this case */
PitChannels[i].CurrentValue = 0;
}
else PitChannels[i].CurrentValue -= Count;
/* Did it fall to the terminal count? */ /* Did it fall to the terminal count? */
if (PitChannels[i].CurrentValue == 0 && !PitChannels[i].Pulsed) if (PitChannels[i].CurrentValue == 0 && !PitChannels[i].Pulsed)
@ -171,47 +176,100 @@ VOID PitDecrementCount()
case PIT_MODE_RATE_GENERATOR: case PIT_MODE_RATE_GENERATOR:
{ {
/* Decrement the value */ BOOLEAN Reloaded = FALSE;
PitChannels[i].CurrentValue--;
/* Did it fall to zero? */ while (Count)
if (PitChannels[i].CurrentValue != 0) break; {
if ((Count > PitChannels[i].CurrentValue)
&& (PitChannels[i].CurrentValue != 0))
{
/* Decrease the count */
Count -= PitChannels[i].CurrentValue;
/* Yes, raise the output line and reload */ /* Reload the value */
if (i == 0) PicInterruptRequest(0); PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
/* Set the flag */
Reloaded = TRUE;
}
else
{
/* Decrease the value */
PitChannels[i].CurrentValue -= Count;
/* Clear the count */
Count = 0;
/* Did it fall to zero? */
if (PitChannels[i].CurrentValue == 0)
{
PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
Reloaded = TRUE;
}
}
}
/* If there was a reload on channel 0, raise IRQ 0 */
if ((i == 0) && Reloaded) PicInterruptRequest(0);
break; break;
} }
case PIT_MODE_SQUARE_WAVE: case PIT_MODE_SQUARE_WAVE:
{ {
/* Decrement the value by 2 */ INT ReloadCount = 0;
PitChannels[i].CurrentValue -= 2; WORD ReloadValue = PitChannels[i].ReloadValue;
/* Did it fall to zero? */ /* The reload value must be even */
if (PitChannels[i].CurrentValue != 0) break; ReloadValue &= ~1;
/* Yes, toggle the flip-flop */ while (Count)
PitChannels[i].OutputFlipFlop = !PitChannels[i].OutputFlipFlop;
/* Did this create a rising edge in the signal? */
if (PitChannels[i].OutputFlipFlop)
{ {
/* Yes, IRQ 0 if this is channel 0 */ if (((Count * 2) > PitChannels[i].CurrentValue)
if (i == 0) PicInterruptRequest(0); && (PitChannels[i].CurrentValue != 0))
{
/* Decrease the count */
Count -= PitChannels[i].CurrentValue / 2;
/* Reload the value */
PitChannels[i].CurrentValue = ReloadValue;
/* Increment the reload count */
ReloadCount++;
}
else
{
/* Clear the count */
Count = 0;
/* Decrease the value */
PitChannels[i].CurrentValue -= Count * 2;
/* Did it fall to zero? */
if (PitChannels[i].CurrentValue == 0)
{
/* Reload the value */
PitChannels[i].CurrentValue = ReloadValue;
/* Increment the reload count */
ReloadCount++;
}
}
} }
/* Reload the value, but make sure it's even */ if (ReloadCount == 0) break;
if (PitChannels[i].ReloadValue % 2)
/* Toggle the flip-flop if the number of reloads was odd */
if (ReloadCount & 1)
{ {
/* It's odd, reduce it by 1 */ PitChannels[i].OutputFlipFlop = !PitChannels[i].OutputFlipFlop;
PitChannels[i].CurrentValue = PitChannels[i].ReloadValue - 1;
} }
else
/* Was there any rising edge on channel 0 ? */
if ((PitChannels[i].OutputFlipFlop || ReloadCount) && (i == 0))
{ {
/* It was even */ /* Yes, IRQ 0 */
PitChannels[i].CurrentValue = PitChannels[i].ReloadValue; PicInterruptRequest(0);
} }
break; break;

View file

@ -48,7 +48,7 @@ typedef struct _PIT_CHANNEL
VOID PitWriteCommand(BYTE Value); VOID PitWriteCommand(BYTE Value);
BYTE PitReadData(BYTE Channel); BYTE PitReadData(BYTE Channel);
VOID PitWriteData(BYTE Channel, BYTE Value); VOID PitWriteData(BYTE Channel, BYTE Value);
VOID PitDecrementCount(); VOID PitDecrementCount(DWORD Count);
DWORD PitGetResolution(VOID); DWORD PitGetResolution(VOID);
#endif // _TIMER_H_ #endif // _TIMER_H_