Author: hbelusca
Date: Tue Jan 28 20:24:24 2014
New Revision: 61866
URL:
http://svn.reactos.org/svn/reactos?rev=61866&view=rev
Log:
[NTVDM]
Part 2 of PIT + sound fix.
- Move port 61h management from speaker.c to the emulator.c module;
- Add PIT OUT callbacks support;
- Add (unimplemented) PitSetGate function (will be used later on).
Still WIP.
Modified:
branches/ntvdm/subsystems/ntvdm/emulator.c
branches/ntvdm/subsystems/ntvdm/emulator.h
branches/ntvdm/subsystems/ntvdm/hardware/speaker.c
branches/ntvdm/subsystems/ntvdm/hardware/speaker.h
branches/ntvdm/subsystems/ntvdm/hardware/timer.c
branches/ntvdm/subsystems/ntvdm/hardware/timer.h
Modified: branches/ntvdm/subsystems/ntvdm/emulator.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] Tue Jan 28 20:24:24 2014
@@ -31,6 +31,7 @@
BOOLEAN VdmRunning = TRUE;
static BOOLEAN A20Line = FALSE;
+static BYTE Port61hState = 0x00;
LPCWSTR ExceptionName[] =
{
@@ -123,6 +124,79 @@
{
DPRINT1("NTVDM: BOP_DEBUGGER\n");
DebugBreak();
+}
+
+
+static BYTE WINAPI Port61hRead(ULONG Port)
+{
+ return Port61hState;
+}
+
+static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
+{
+ BYTE OldPort61hState = Port61hState;
+
+ /* Only the four lowest bytes can be written */
+ Port61hState = (Port61hState & 0xF0) | (Data & 0x0F);
+
+ if ((OldPort61hState ^ Port61hState) & 0x01)
+ {
+ DPRINT1("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" :
"off");
+ }
+
+ PitSetGate(2, !!(Port61hState & 0x01));
+
+ if ((OldPort61hState ^ Port61hState) & 0x02)
+ {
+ /* There were some change for the speaker... */
+ DPRINT1("Speaker %s\n", Port61hState & 0x02 ? "on" :
"off");
+ }
+}
+
+static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State)
+{
+ if (State)
+ {
+ DPRINT("PicInterruptRequest\n");
+ PicInterruptRequest(0); // Raise IRQ 0
+ }
+ // else < Lower IRQ 0 >
+}
+
+static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State)
+{
+#if 0
+ if (State)
+ {
+ /* Set bit 4 of Port 61h */
+ Port61hState |= 1 << 4;
+ }
+ else
+ {
+ /* Clear bit 4 of Port 61h */
+ Port61hState &= ~(1 << 4);
+ }
+#else
+ Port61hState = (Port61hState & 0xEF) | (State << 4);
+#endif
+}
+
+static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
+{
+#if 0
+ if (State)
+ {
+ /* Set bit 5 of Port 61h */
+ Port61hState |= 1 << 5;
+ }
+ else
+ {
+ /* Clear bit 5 of Port 61h */
+ Port61hState &= ~(1 << 5);
+ }
+#else
+ Port61hState = (Port61hState & 0xDF) | (State << 5);
+#endif
}
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -159,6 +233,14 @@
PitInitialize();
CmosInitialize();
SpeakerInitialize();
+
+ /* Set output functions */
+ PitSetOutFunction(0, NULL, PitChan0Out);
+ PitSetOutFunction(1, NULL, PitChan1Out);
+ PitSetOutFunction(2, NULL, PitChan2Out);
+
+ /* Register the I/O Ports */
+ RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite);
/* Initialize the PS2 port */
PS2Initialize(ConsoleInput);
Modified: branches/ntvdm/subsystems/ntvdm/emulator.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.h [iso-8859-1] Tue Jan 28 20:24:24 2014
@@ -61,6 +61,10 @@
#define BCD_TO_BINARY(x) (((x) >> 12) * 1000 + ((x) >> 8) * 100 + ((x)
>> 4) * 10 + ((x) & 0x0F))
+/* System I/O ports */
+#define CONTROL_SYSTEM_PORT61H 0x61
+
+
enum
{
EMULATOR_EXCEPTION_DIVISION_BY_ZERO,
Modified: branches/ntvdm/subsystems/ntvdm/hardware/speaker.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/hardware…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/hardware/speaker.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/hardware/speaker.c [iso-8859-1] Tue Jan 28 20:24:24
2014
@@ -25,37 +25,19 @@
/* PRIVATE VARIABLES **********************************************************/
-static BYTE Port61hState = 0x00;
-HANDLE hBeep = NULL;
+static HANDLE hBeep = NULL;
/* PRIVATE FUNCTIONS **********************************************************/
-static BYTE SpeakerReadStatus(VOID)
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID SpeakerPool(VOID)
{
- return Port61hState;
-}
+ BYTE Port61hState = IOReadB(CONTROL_SYSTEM_PORT61H);
+ BOOLEAN IsConnectedToPITChannel2 = !!(Port61hState & 0x01);
+ BOOLEAN SpeakerDataOn = !!(Port61hState & 0x02);
-static VOID SpeakerWriteCommand(BYTE Value)
-{
- BOOLEAN IsConnectedToPITChannel2;
- UCHAR SpeakerData;
-
- Port61hState = Value;
- IsConnectedToPITChannel2 = ((Port61hState & 0x01) != 0);
- SpeakerData = (Port61hState & 0x02);
-
- if (PitChannel2 && IsConnectedToPITChannel2)
- {
- /* Set bit 5 of Port 61h */
- Port61hState |= 1 << 5;
- }
- else
- {
- /* Clear bit 5 of Port 61h */
- Port61hState &= ~(1 << 5);
- }
-
- if (PitChannel2 && IsConnectedToPITChannel2 && (SpeakerData != 0))
+ if (PitChannel2 && IsConnectedToPITChannel2 && SpeakerDataOn)
{
/* Start beeping - Adapted from kernel32:Beep() */
NTSTATUS Status;
@@ -121,18 +103,6 @@
}
}
-static BYTE WINAPI SpeakerReadPort(ULONG Port)
-{
- return SpeakerReadStatus();
-}
-
-static VOID WINAPI SpeakerWritePort(ULONG Port, BYTE Data)
-{
- SpeakerWriteCommand(Data);
-}
-
-/* PUBLIC FUNCTIONS ***********************************************************/
-
VOID SpeakerInitialize(VOID)
{
NTSTATUS Status;
@@ -165,9 +135,6 @@
{
DPRINT1("Failed to open Beep driver, Status 0x%08lx\n", Status);
}
-
- /* Register the I/O Ports */
- RegisterIoPort(SPEAKER_CONTROL_PORT, SpeakerReadPort, SpeakerWritePort);
}
VOID SpeakerCleanup(VOID)
Modified: branches/ntvdm/subsystems/ntvdm/hardware/speaker.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/hardware…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/hardware/speaker.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/hardware/speaker.h [iso-8859-1] Tue Jan 28 20:24:24
2014
@@ -15,9 +15,9 @@
/* DEFINES ********************************************************************/
-#define SPEAKER_CONTROL_PORT 0x61
+/* FUNCTIONS ******************************************************************/
-/* FUNCTIONS ******************************************************************/
+VOID SpeakerPool(VOID);
VOID SpeakerInitialize(VOID);
VOID SpeakerCleanup(VOID);
Modified: branches/ntvdm/subsystems/ntvdm/hardware/timer.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/hardware…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/hardware/timer.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/hardware/timer.c [iso-8859-1] Tue Jan 28 20:24:24
2014
@@ -37,13 +37,14 @@
if (PitChannels[Channel].LatchStatusSet == FALSE)
{
BYTE StatusLatch = 0;
- /* HACK!! */BYTE NullCount = 0;/* HACK!! */
-
- StatusLatch = PitChannels[Channel].Out << 7 | NullCount << 6;
+ /** HACK!! **/BYTE NullCount = 0;/** HACK!! **/
+
+ StatusLatch = PitChannels[Channel].Out << 7 | NullCount << 6;
StatusLatch |= (PitChannels[Channel].ReadWriteMode & 0x03) << 4;
StatusLatch |= (PitChannels[Channel].Mode & 0x07) << 1;
StatusLatch |= (PitChannels[Channel].Bcd & 0x01);
+ /* Latch the counter's status */
PitChannels[Channel].LatchStatusSet = TRUE;
PitChannels[Channel].StatusLatch = StatusLatch;
}
@@ -61,23 +62,24 @@
*/
if (PitChannels[Channel].ReadStatus == 0x00)
{
+ /* Latch the counter's value */
PitChannels[Channel].ReadStatus = PitChannels[Channel].ReadWriteMode;
/* Convert the current value to BCD if needed */
- PitChannels[Channel].OutputLatch = READ_PIT_VALUE(PitChannels[Channel],
-
PitChannels[Channel].CurrentValue);
+ PitChannels[Channel].OutputLatch =
+ READ_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CurrentValue);
}
}
static VOID PitSetOut(PPIT_CHANNEL Channel, BOOLEAN State)
{
- if (State == Channel->Out) return;
+ /** HACK!! **\ if (State == Channel->Out) return; \** HACK!! **/
/* Set the new state of the OUT pin */
Channel->Out = State;
- // /* Call the callback */
- // if (Channel->OutFunction) Channel->OutFunction(Channel->OutParam,
State);
+ /* Call the callback */
+ if (Channel->OutFunction) Channel->OutFunction(Channel->OutParam, State);
}
static VOID PitInitCounter(PPIT_CHANNEL Channel)
@@ -138,20 +140,16 @@
/* ... otherwise, set the modes and reset flip-flops */
PitChannels[Channel].ReadWriteMode = ReadWriteMode;
+ PitChannels[Channel].ReadStatus = 0x00;
+ PitChannels[Channel].WriteStatus = 0x00;
PitChannels[Channel].LatchStatusSet = FALSE;
PitChannels[Channel].StatusLatch = 0x00;
- PitChannels[Channel].ReadStatus = 0x00;
- PitChannels[Channel].WriteStatus = 0x00;
-
PitChannels[Channel].CountRegister = 0x00;
PitChannels[Channel].OutputLatch = 0x00;
- PitChannels[Channel].Pulsed = FALSE;
-
-
- // PitChannels[Channel].Out = FALSE; // <-- unneeded, see the PitInitCounter call
below.
+ /** HACK!! **/PitChannels[Channel].FlipFlop = FALSE;/** HACK!! **/
/* Fix the current value if we switch to BCD counting */
PitChannels[Channel].Bcd = IsBcd;
@@ -192,9 +190,8 @@
LPWORD CurrentValue = NULL;
/*
- * If the status was latched, the first read operation
- * will return the latched status, whichever the count
- * value or the status was latched first.
+ * If the status was latched, the first read operation will return the
+ * latched status, whichever value (count or status) was latched first.
*/
if (PitChannels[Channel].LatchStatusSet)
{
@@ -238,6 +235,8 @@
{
PitChannels[Channel].WriteStatus = PitChannels[Channel].ReadWriteMode;
}
+
+ ASSERT(PitChannels[Channel].WriteStatus != 0);
ReadWriteMode = &PitChannels[Channel].WriteStatus;
@@ -261,6 +260,7 @@
{
if (PitChannels[Channel].CountRegister == 0x0000)
{
+ /* Wrap around to the highest count */
if (PitChannels[Channel].Bcd)
PitChannels[Channel].CountRegister = 9999;
else
@@ -268,8 +268,8 @@
}
/* Convert the current value from BCD if needed */
- PitChannels[Channel].CountRegister = WRITE_PIT_VALUE(PitChannels[Channel],
-
PitChannels[Channel].CountRegister);
+ PitChannels[Channel].CountRegister =
+ WRITE_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CountRegister);
PitChannels[Channel].ReloadValue = PitChannels[Channel].CountRegister;
}
}
@@ -311,6 +311,8 @@
static VOID PitDecrementCount(PPIT_CHANNEL Channel, DWORD Count)
{
+ if (Count == 0) return;
+
switch (Channel->Mode)
{
case PIT_MODE_INT_ON_TERMINAL_COUNT:
@@ -324,11 +326,10 @@
else Channel->CurrentValue -= Count;
/* Did it fall to the terminal count? */
- if (Channel->CurrentValue == 0 && !Channel->Pulsed)
+ if (Channel->CurrentValue == 0 && !Channel->Out)
{
/* Yes, raise the output line */
- if (Channel == &PitChannels[0]) PicInterruptRequest(0);
- Channel->Pulsed = TRUE;
+ PitSetOut(Channel, TRUE);
}
break;
}
@@ -342,7 +343,7 @@
if ((Count > Channel->CurrentValue)
&& (Channel->CurrentValue != 0))
{
- /* Decrease the count */
+ /* Decrement the count */
Count -= Channel->CurrentValue;
/* Reload the value */
@@ -353,7 +354,7 @@
}
else
{
- /* Decrease the value */
+ /* Decrement the value */
Channel->CurrentValue -= Count;
/* Clear the count */
@@ -368,8 +369,8 @@
}
}
- /* If there was a reload on channel 0, raise IRQ 0 */
- if ((Channel == &PitChannels[0]) && Reloaded)
PicInterruptRequest(0);
+ /* If there was a reload, raise the output line */
+ if (Reloaded) PitSetOut(Channel, TRUE);
break;
}
@@ -387,7 +388,7 @@
if (((Count * 2) > Channel->CurrentValue)
&& (Channel->CurrentValue != 0))
{
- /* Decrease the count */
+ /* Decrement the count */
Count -= Channel->CurrentValue / 2;
/* Reload the value */
@@ -398,7 +399,7 @@
}
else
{
- /* Decrease the value */
+ /* Decrement the value */
Channel->CurrentValue -= Count * 2;
/* Clear the count */
@@ -421,16 +422,15 @@
/* Toggle the flip-flop if the number of reloads was odd */
if (ReloadCount & 1)
{
- Channel->Out = !Channel->Out;
+ Channel->FlipFlop = !Channel->FlipFlop;
+ // PitSetOut(Channel, !Channel->Out);
}
- /* Was there any rising edge on channel 0 ? */
- if (((Channel->Out && (ReloadCount == 1))
- || (ReloadCount > 1))
- && (Channel == &PitChannels[0]))
+ /* Was there any rising edge? */
+ if ((Channel->FlipFlop && (ReloadCount == 1)) || (ReloadCount >
1))
{
- /* Yes, IRQ 0 */
- PicInterruptRequest(0);
+ /* Yes, raise the output line */
+ PitSetOut(Channel, TRUE);
}
break;
@@ -453,6 +453,23 @@
/* PUBLIC FUNCTIONS ***********************************************************/
+VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction)
+{
+ if (Channel >= PIT_CHANNELS) return;
+
+ PitChannels[Channel].OutParam = Param;
+ PitChannels[Channel].OutFunction = OutFunction;
+}
+
+VOID PitSetGate(BYTE Channel, BOOLEAN State)
+{
+ if (Channel >= PIT_CHANNELS) return;
+ if (State == PitChannels[Channel].Gate) return;
+
+ /* UNIMPLEMENTED */
+ PitChannels[Channel].Gate = State;
+}
+
VOID PitClock(DWORD Count)
{
UINT i;
@@ -461,7 +478,7 @@
for (i = 0; i < PIT_CHANNELS; i++)
{
- // if (!PitChannels[i].Couting) continue;
+ // if (!PitChannels[i].Counting) continue;
PitDecrementCount(&PitChannels[i], Count);
}
}
@@ -487,6 +504,14 @@
VOID PitInitialize(VOID)
{
+ /* Set up the timers to their default value */
+ PitSetOutFunction(0, NULL, NULL);
+ PitSetGate(0, TRUE);
+ PitSetOutFunction(1, NULL, NULL);
+ PitSetGate(1, TRUE);
+ PitSetOutFunction(2, NULL, NULL);
+ PitSetGate(2, FALSE);
+
/* Register the I/O Ports */
RegisterIoPort(PIT_COMMAND_PORT, NULL , PitWritePort);
RegisterIoPort(PIT_DATA_PORT(0), PitReadPort, PitWritePort);
Modified: branches/ntvdm/subsystems/ntvdm/hardware/timer.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/hardware…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/hardware/timer.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/hardware/timer.h [iso-8859-1] Tue Jan 28 20:24:24
2014
@@ -38,23 +38,25 @@
PIT_MODE_HARDWARE_STROBE
} PIT_MODE, *PPIT_MODE;
+typedef VOID (WINAPI *PIT_OUT_FUNCTION)(LPVOID Param, BOOLEAN State);
+
typedef struct _PIT_CHANNEL
{
- BOOLEAN Pulsed;
-
-
- /* PIT Status members */
+ /* PIT Status fields */
PIT_MODE Mode;
BOOLEAN Bcd;
BYTE ReadWriteMode; // 0 --> Counter Latch ; 1 --> LSB R/W ; 2 --> MSB
R/W ; 3 --> LSB then MSB R/W
- /* Reading the PIT status byte */
+ /* For interleaved reading and writing in 2-byte RW mode */
+ BYTE ReadStatus; // Same convention as ReadWriteMode
+ BYTE WriteStatus; // Same convention as ReadWriteMode
+
+ /* For reading the PIT status byte */
BOOLEAN LatchStatusSet;
BYTE StatusLatch;
- /* For interleaving reading and writing in 2-byte RW mode */
- BYTE ReadStatus; // Same convention as ReadWriteMode
- BYTE WriteStatus; // Same convention as ReadWriteMode
+ /* Counting */
+ BOOLEAN Gate;
/**/WORD CountRegister;/**/ // Our ReloadValue ???
WORD OutputLatch;
@@ -65,12 +67,18 @@
/* PIT Output */
BOOLEAN Out; // 0: Low ; 1: High
+ /** HACK!! **/BOOLEAN FlipFlop;/** HACK!! **/
+ LPVOID OutParam;
+ PIT_OUT_FUNCTION OutFunction;
} PIT_CHANNEL, *PPIT_CHANNEL;
extern PPIT_CHANNEL PitChannel2; // Needed for PC Speaker
/* FUNCTIONS ******************************************************************/
+
+VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction);
+VOID PitSetGate(BYTE Channel, BOOLEAN State);
VOID PitClock(DWORD Count);
DWORD PitGetResolution(VOID);