Author: aandrejevic
Date: Wed Jun 26 22:58:41 2013
New Revision: 59344
URL:
http://svn.reactos.org/svn/reactos?rev=59344&view=rev
Log:
[NTVDM]
Clean up the code and properly separate different modules into different files.
Added:
branches/ntvdm/subsystems/ntvdm/bios.h (with props)
branches/ntvdm/subsystems/ntvdm/dos.h (with props)
branches/ntvdm/subsystems/ntvdm/emulator.h (with props)
branches/ntvdm/subsystems/ntvdm/pic.c (with props)
branches/ntvdm/subsystems/ntvdm/pic.h (with props)
branches/ntvdm/subsystems/ntvdm/ps2.c (with props)
branches/ntvdm/subsystems/ntvdm/ps2.h (with props)
branches/ntvdm/subsystems/ntvdm/timer.c (with props)
branches/ntvdm/subsystems/ntvdm/timer.h (with props)
Removed:
branches/ntvdm/subsystems/ntvdm/hardware.c
Modified:
branches/ntvdm/subsystems/ntvdm/CMakeLists.txt
branches/ntvdm/subsystems/ntvdm/bios.c
branches/ntvdm/subsystems/ntvdm/dos.c
branches/ntvdm/subsystems/ntvdm/emulator.c
branches/ntvdm/subsystems/ntvdm/ntvdm.c
branches/ntvdm/subsystems/ntvdm/ntvdm.h
Modified: branches/ntvdm/subsystems/ntvdm/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/CMakeLis…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -5,7 +5,9 @@
bios.c
dos.c
emulator.c
- hardware.c
+ pic.c
+ timer.c
+ ps2.c
ntvdm.c
ntvdm.rc)
Modified: branches/ntvdm/subsystems/ntvdm/bios.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -6,10 +6,39 @@
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
-#include "ntvdm.h"
-
-BYTE CursorRow, CursorCol;
-WORD ConsoleWidth, ConsoleHeight;
+/* INCLUDES *******************************************************************/
+
+#include "bios.h"
+#include "emulator.h"
+#include "pic.h"
+#include "timer.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static BYTE CursorRow, CursorCol;
+static WORD ConsoleWidth, ConsoleHeight;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static COORD BiosVideoAddressToCoord(ULONG Address)
+{
+ COORD Result = {0, 0};
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ if (!GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo))
+ {
+ ASSERT(FALSE);
+ return Result;
+ }
+
+ Result.X = ((Address - CONSOLE_VIDEO_MEM_START) >> 1) % ConsoleInfo.dwSize.X;
+ Result.Y = ((Address - CONSOLE_VIDEO_MEM_START) >> 1) / ConsoleInfo.dwSize.X;
+
+ return Result;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN BiosInitialize()
{
@@ -81,24 +110,6 @@
PitWriteData(0, 0x00);
return TRUE;
-}
-
-static COORD BiosVideoAddressToCoord(ULONG Address)
-{
- COORD Result = {0, 0};
- CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
- HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (!GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo))
- {
- ASSERT(FALSE);
- return Result;
- }
-
- Result.X = ((Address - CONSOLE_VIDEO_MEM_START) >> 1) % ConsoleInfo.dwSize.X;
- Result.Y = ((Address - CONSOLE_VIDEO_MEM_START) >> 1) / ConsoleInfo.dwSize.X;
-
- return Result;
}
VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress)
Added: branches/ntvdm/subsystems/ntvdm/bios.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.h?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.h (added)
+++ branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: bios.h
+ * PURPOSE: VDM BIOS (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _BIOS_H_
+#define _BIOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define CONSOLE_VIDEO_MEM_START 0xB8000
+#define CONSOLE_VIDEO_MEM_END 0xBFFFF
+#define ROM_AREA_START 0xC0000
+#define ROM_AREA_END 0xFFFFF
+#define BIOS_PIC_MASTER_INT 0x08
+#define BIOS_PIC_SLAVE_INT 0x70
+#define BIOS_SEGMENT 0xF000
+#define VIDEO_BIOS_INTERRUPT 0x10
+#define CONSOLE_FONT_HEIGHT 8
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN BiosInitialize();
+VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress);
+VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress);
+VOID BiosVideoService();
+VOID BiosHandleIrq(BYTE IrqNumber);
+
+#endif
Propchange: branches/ntvdm/subsystems/ntvdm/bios.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: branches/ntvdm/subsystems/ntvdm/dos.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -6,10 +6,17 @@
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
-#include "ntvdm.h"
-
-WORD CurrentPsp = SYSTEM_PSP, LastError = 0;
-DWORD DiskTransferArea;
+/* INCLUDES *******************************************************************/
+
+#include "dos.h"
+#include "emulator.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static WORD CurrentPsp = SYSTEM_PSP;
+static DWORD DiskTransferArea;
+
+/* PRIVATE FUNCTIONS **********************************************************/
static VOID DosCombineFreeBlocks(WORD StartBlock)
{
@@ -77,6 +84,8 @@
return DestSegment;
}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
{
Added: branches/ntvdm/subsystems/ntvdm/dos.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos.h (added)
+++ branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,133 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: dos.h
+ * PURPOSE: VDM DOS Kernel (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _DOS_H_
+#define _DOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define DOS_VERSION 0x0600
+#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT"
+#define DOS_COMMAND_INTERPRETER
L"%SystemRoot%\\system32\\COMMAND.COM /k
%SystemRoot%\\system32\\AUTOEXEC.NT"
+#define FIRST_MCB_SEGMENT 0x1000
+#define USER_MEMORY_SIZE 0x8FFFF
+#define SYSTEM_PSP 0x08
+#define SYSTEM_ENV_BLOCK 0x800
+#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
+#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
+
+#pragma pack(push, 1)
+
+typedef struct _DOS_MCB
+{
+ CHAR BlockType;
+ WORD OwnerPsp;
+ WORD Size;
+ BYTE Unused[3];
+ CHAR Name[8];
+} DOS_MCB, *PDOS_MCB;
+
+typedef struct _DOS_FCB
+{
+ BYTE DriveNumber;
+ CHAR FileName[8];
+ CHAR FileExt[3];
+ WORD BlockNumber;
+ WORD RecordSize;
+ DWORD FileSize;
+ WORD LastWriteDate;
+ WORD LastWriteTime;
+ BYTE Reserved[8];
+ BYTE BlockRecord;
+ BYTE RecordNumber[3];
+} DOS_FCB, *PDOS_FCB;
+
+typedef struct _DOS_PSP
+{
+ BYTE Exit[2];
+ WORD MemSize;
+ BYTE Reserved0[6];
+ DWORD TerminateAddress;
+ DWORD BreakAddress;
+ DWORD CriticalAddress;
+ WORD ParentPsp;
+ BYTE HandleTable[20];
+ WORD EnvBlock;
+ DWORD LastStack;
+ WORD HandleTableSize;
+ DWORD HandleTablePtr;
+ DWORD PreviousPsp;
+ DWORD Reserved1;
+ WORD DosVersion;
+ BYTE Reserved2[14];
+ BYTE FarCall[3];
+ BYTE Reserved3[9];
+ DOS_FCB Fcb;
+ BYTE CommandLineSize;
+ CHAR CommandLine[127];
+} DOS_PSP, *PDOS_PSP;
+
+typedef struct _DOS_SFT_ENTRY
+{
+ WORD ReferenceCount;
+ WORD Mode;
+ BYTE Attribute;
+ WORD DeviceInfo;
+ DWORD DriveParamBlock;
+ WORD FirstCluster;
+ WORD FileTime;
+ WORD FileDate;
+ DWORD FileSize;
+ DWORD CurrentOffset;
+ WORD LastClusterAccessed;
+ DWORD DirEntSector;
+ BYTE DirEntryIndex;
+ CHAR FileName[11];
+ BYTE Reserved0[6];
+ WORD OwnerPsp;
+ BYTE Reserved1[8];
+} DOS_SFT_ENTRY, *PDOS_SFT_ENTRY;
+
+typedef struct _DOS_SFT
+{
+ DWORD NextTablePtr;
+ WORD FileCount;
+ DOS_SFT_ENTRY Entry[ANYSIZE_ARRAY];
+} DOS_SFT, *PDOS_SFT;
+
+typedef struct _DOS_INPUT_BUFFER
+{
+ BYTE MaxLength, Length;
+ CHAR Buffer[ANYSIZE_ARRAY];
+} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER;
+
+#pragma pack(pop)
+
+/* FUNCTIONS ******************************************************************/
+
+WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable);
+BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable);
+BOOLEAN DosFreeMemory(WORD BlockData);
+VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD
Environment);
+BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock);
+VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
+CHAR DosReadCharacter();
+VOID DosPrintCharacter(CHAR Character);
+VOID DosInt20h(WORD CodeSegment);
+VOID DosInt21h(WORD CodeSegment);
+VOID DosBreakInterrupt();
+BOOLEAN DosInitialize();
+
+#endif
+
+/* EOF */
+
Propchange: branches/ntvdm/subsystems/ntvdm/dos.h
------------------------------------------------------------------------------
svn:eol-style = native
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] Wed Jun 26 22:58:41 2013
@@ -8,13 +8,20 @@
/* INCLUDES *******************************************************************/
-#include "ntvdm.h"
-#include <softx86/softx86.h>
-#include <softx86/softx87.h>
-
-softx86_ctx EmulatorContext;
-softx87_ctx FpuEmulatorContext;
+#include "emulator.h"
+#include "bios.h"
+#include "dos.h"
+#include "pic.h"
+#include "ps2.h"
+#include "timer.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static softx86_ctx EmulatorContext;
+static softx87_ctx FpuEmulatorContext;
static BOOLEAN A20Line = FALSE;
+
+/* PRIVATE FUNCTIONS **********************************************************/
static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
{
Added: branches/ntvdm/subsystems/ntvdm/emulator.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.h (added)
+++ branches/ntvdm/subsystems/ntvdm/emulator.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,85 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: emulator.h
+ * PURPOSE: Minimal x86 machine emulator for the VDM (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _EMULATOR_H_
+#define _EMULATOR_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+#include <softx86/softx86.h>
+#include <softx86/softx87.h>
+
+/* DEFINES ********************************************************************/
+
+#define EMULATOR_FLAG_CF (1 << 0)
+#define EMULATOR_FLAG_PF (1 << 2)
+#define EMULATOR_FLAG_AF (1 << 4)
+#define EMULATOR_FLAG_ZF (1 << 6)
+#define EMULATOR_FLAG_SF (1 << 7)
+#define EMULATOR_FLAG_TF (1 << 8)
+#define EMULATOR_FLAG_IF (1 << 9)
+#define EMULATOR_FLAG_DF (1 << 10)
+#define EMULATOR_FLAG_OF (1 << 11)
+#define EMULATOR_FLAG_NT (1 << 14)
+#define EMULATOR_FLAG_RF (1 << 16)
+#define EMULATOR_FLAG_VM (1 << 17)
+#define EMULATOR_FLAG_AC (1 << 18)
+#define EMULATOR_FLAG_VIF (1 << 19)
+#define EMULATOR_FLAG_VIP (1 << 20)
+#define EMULATOR_FLAG_ID (1 << 21)
+#define SPECIAL_INT_NUM 0xFF
+
+enum
+{
+ EMULATOR_EXCEPTION_DIVISION_BY_ZERO,
+ EMULATOR_EXCEPTION_DEBUG,
+ EMULATOR_EXCEPTION_NMI,
+ EMULATOR_EXCEPTION_BREAKPOINT,
+ EMULATOR_EXCEPTION_OVERFLOW,
+ EMULATOR_EXCEPTION_BOUND,
+ EMULATOR_EXCEPTION_INVALID_OPCODE,
+ EMULATOR_EXCEPTION_NO_FPU
+};
+
+typedef enum
+{
+ EMULATOR_REG_AX,
+ EMULATOR_REG_CX,
+ EMULATOR_REG_DX,
+ EMULATOR_REG_BX,
+ EMULATOR_REG_SI,
+ EMULATOR_REG_DI,
+ EMULATOR_REG_SP,
+ EMULATOR_REG_BP,
+ EMULATOR_REG_ES,
+ EMULATOR_REG_CS,
+ EMULATOR_REG_SS,
+ EMULATOR_REG_DS,
+} EMULATOR_REGISTER;
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN EmulatorInitialize();
+VOID EmulatorSetStack(WORD Segment, WORD Offset);
+VOID EmulatorExecute(WORD Segment, WORD Offset);
+VOID EmulatorInterrupt(BYTE Number);
+VOID EmulatorExternalInterrupt(BYTE Number);
+ULONG EmulatorGetRegister(ULONG Register);
+VOID EmulatorSetRegister(ULONG Register, ULONG Value);
+BOOLEAN EmulatorGetFlag(ULONG Flag);
+VOID EmulatorSetFlag(ULONG Flag);
+VOID EmulatorClearFlag(ULONG Flag);
+VOID EmulatorStep();
+VOID EmulatorCleanup();
+VOID EmulatorSetA20(BOOLEAN Enabled);
+
+#endif
+
+/* EOF */
+
Propchange: branches/ntvdm/subsystems/ntvdm/emulator.h
------------------------------------------------------------------------------
svn:eol-style = native
Removed: branches/ntvdm/subsystems/ntvdm/hardware.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/hardware…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/hardware.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/hardware.c (removed)
@@ -1,742 +0,0 @@
-/*
- * COPYRIGHT: GPL - See COPYING in the top level directory
- * PROJECT: ReactOS Virtual DOS Machine
- * FILE: hardware.c
- * PURPOSE: Minimal hardware emulation
- * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
- */
-
-/* INCLUDES *******************************************************************/
-
-#include "ntvdm.h"
-
-typedef struct _PIC
-{
- BOOLEAN Initialization;
- BYTE MaskRegister;
- BYTE InServiceRegister;
- BYTE IntOffset;
- BYTE ConfigRegister;
- BYTE CascadeRegister;
- BOOLEAN CascadeRegisterSet;
- BOOLEAN AutoEoi;
- BOOLEAN Slave;
- BOOLEAN ReadIsr;
-} PIC, *PPIC;
-
-enum
-{
- PIT_MODE_INT_ON_TERMINAL_COUNT,
- PIT_MODE_HARDWARE_ONE_SHOT,
- PIT_MODE_RATE_GENERATOR,
- PIT_MODE_SQUARE_WAVE,
- PIT_MODE_SOFTWARE_STROBE,
- PIT_MODE_HARDWARE_STROBE
-};
-
-typedef struct _PIT_CHANNEL
-{
- WORD ReloadValue;
- WORD CurrentValue;
- WORD LatchedValue;
- INT Mode;
- BOOLEAN Pulsed;
- BOOLEAN LatchSet;
- BOOLEAN InputFlipFlop;
- BOOLEAN OutputFlipFlop;
- BYTE AccessMode;
-} PIT_CHANNEL, *PPIT_CHANNEL;
-
-static PIC MasterPic, SlavePic;
-static PIT_CHANNEL PitChannels[PIT_CHANNELS];
-static BYTE KeyboardQueue[KEYBOARD_BUFFER_SIZE];
-static BOOLEAN KeyboardQueueEmpty = TRUE;
-static UINT KeyboardQueueStart = 0;
-static UINT KeyboardQueueEnd = 0;
-static BYTE KeyboardResponse = 0;
-static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE;
-static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG;
-
-static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
-{
- /* Check if the keyboard queue is full */
- if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
- {
- return FALSE;
- }
-
- /* Insert the value in the queue */
- KeyboardQueue[KeyboardQueueEnd] = ScanCode;
- KeyboardQueueEnd++;
- KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE;
-
- /* Since we inserted a value, it's not empty anymore */
- KeyboardQueueEmpty = FALSE;
-
- return TRUE;
-}
-
-static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
-{
- /* Make sure the keyboard queue is not empty */
- if (KeyboardQueueEmpty) return FALSE;
-
- /* Get the scan code */
- *ScanCode = KeyboardQueue[KeyboardQueueStart];
-
- /* Remove the value from the queue */
- KeyboardQueueStart++;
- KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE;
-
- /* Check if the queue is now empty */
- if (KeyboardQueueStart == KeyboardQueueEnd)
- {
- KeyboardQueueEmpty = TRUE;
- }
-
- return TRUE;
-}
-
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-BYTE PicReadCommand(BYTE Port)
-{
- PPIC Pic;
-
- /* Which PIC are we accessing? */
- if (Port == PIC_MASTER_CMD) Pic = &MasterPic;
- else Pic = &SlavePic;
-
- if (Pic->ReadIsr)
- {
- /* Read the in-service register */
- Pic->ReadIsr = FALSE;
- return Pic->InServiceRegister;
- }
- else
- {
- /* The IRR is always 0, as the emulated CPU receives the interrupt instantly */
- return 0;
- }
-}
-
-VOID PicWriteCommand(BYTE Port, BYTE Value)
-{
- PPIC Pic;
-
- /* Which PIC are we accessing? */
- if (Port == PIC_MASTER_CMD) Pic = &MasterPic;
- else Pic = &SlavePic;
-
- if (Value & PIC_ICW1)
- {
- /* Start initialization */
- Pic->Initialization = TRUE;
- Pic->IntOffset = 0xFF;
- Pic->CascadeRegisterSet = FALSE;
- Pic->ConfigRegister = Value;
- return;
- }
-
- if (Value & PIC_OCW3)
- {
- /* This is an OCR3 */
- if (Value == PIC_OCW3_READ_ISR)
- {
- /* Return the ISR on next read from command port */
- Pic->ReadIsr = TRUE;
- }
-
- return;
- }
-
- /* This is an OCW2 */
- if (Value & PIC_OCW2_EOI)
- {
- if (Value & PIC_OCW2_SL)
- {
- /* If the SL bit is set, clear a specific IRQ */
- Pic->InServiceRegister &= ~(1 << (Value &
PIC_OCW2_NUM_MASK));
- }
- else
- {
- /* Otherwise, clear all of them */
- Pic->InServiceRegister = 0;
- }
- }
-}
-
-BYTE PicReadData(BYTE Port)
-{
- /* Read the mask register */
- if (Port == PIC_MASTER_DATA) return MasterPic.MaskRegister;
- else return SlavePic.MaskRegister;
-}
-
-VOID PicWriteData(BYTE Port, BYTE Value)
-{
- PPIC Pic;
-
- /* Which PIC are we accessing? */
- if (Port == PIC_MASTER_DATA) Pic = &MasterPic;
- else Pic = &SlavePic;
-
- /* Is the PIC ready? */
- if (!Pic->Initialization)
- {
- /* Yes, this is an OCW1 */
- Pic->MaskRegister = Value;
- return;
- }
-
- /* Has the interrupt offset been set? */
- if (Pic->IntOffset == 0xFF)
- {
- /* This is an ICW2, set the offset (last three bits always zero) */
- Pic->IntOffset = Value & 0xF8;
-
- /* Check if we are in single mode and don't need an ICW4 */
- if ((Pic->ConfigRegister & PIC_ICW1_SINGLE)
- && !(Pic->ConfigRegister & PIC_ICW1_ICW4))
- {
- /* Yes, done initializing */
- Pic->Initialization = FALSE;
- }
- return;
- }
-
- /* Check if we are in cascade mode and the cascade register was not set */
- if (!(Pic->ConfigRegister & PIC_ICW1_SINGLE) &&
!Pic->CascadeRegisterSet)
- {
- /* This is an ICW3 */
- Pic->CascadeRegister = Value;
- Pic->CascadeRegisterSet = TRUE;
-
- /* Check if we need an ICW4 */
- if (!(Pic->ConfigRegister & PIC_ICW1_ICW4))
- {
- /* No, done initializing */
- Pic->Initialization = FALSE;
- }
- return;
- }
-
- /* This must be an ICW4, we will ignore the 8086 bit (assume always set) */
- if (Value & PIC_ICW4_AEOI)
- {
- /* Use automatic end-of-interrupt */
- Pic->AutoEoi = TRUE;
- }
-
- /* Done initializing */
- Pic->Initialization = FALSE;
-}
-
-VOID PicInterruptRequest(BYTE Number)
-{
- BYTE i;
-
- if (Number >= 0 && Number < 8)
- {
- /* Check if any of the higher-priorirty interrupts are busy */
- for (i = 0; i <= Number ; i++)
- {
- if (MasterPic.InServiceRegister & (1 << Number)) return;
- }
-
- /* Check if the interrupt is masked */
- if (MasterPic.MaskRegister & (1 << Number)) return;
-
- /* Set the appropriate bit in the ISR and interrupt the CPU */
- if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << Number;
- EmulatorExternalInterrupt(MasterPic.IntOffset + Number);
- }
- else if (Number >= 8 && Number < 16)
- {
- Number -= 8;
-
- /*
- * The slave PIC is connected to IRQ 2, always! If the master PIC
- * was misconfigured, don't do anything.
- */
- if (!(MasterPic.CascadeRegister & (1 << 2))
- || SlavePic.CascadeRegister != 2)
- {
- return;
- }
-
- /* Check if any of the higher-priorirty interrupts are busy */
- if (MasterPic.InServiceRegister != 0) return;
- for (i = 0; i <= Number ; i++)
- {
- if (SlavePic.InServiceRegister & (1 << Number)) return;
- }
-
- /* Check if the interrupt is masked */
- if (SlavePic.MaskRegister & (1 << Number)) return;
-
- /* Set the IRQ 2 bit in the master ISR */
- if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << 2;
-
- /* Set the appropriate bit in the ISR and interrupt the CPU */
- if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= 1 << Number;
- EmulatorExternalInterrupt(SlavePic.IntOffset + Number);
- }
-}
-
-VOID PitWriteCommand(BYTE Value)
-{
- BYTE Channel = Value >> 6;
- BYTE Mode = (Value >> 1) & 0x07;
-
- /* Check if this is a counter latch command */
- if (((Value >> 4) & 3) == 0)
- {
- PitChannels[Channel].LatchSet = TRUE;
- PitChannels[Channel].LatchedValue = PitChannels[Channel].CurrentValue;
- return;
- }
-
- /* Set the access mode and reset flip-flops */
- PitChannels[Channel].AccessMode = (Value >> 4) & 3;
- PitChannels[Channel].Pulsed = FALSE;
- PitChannels[Channel].LatchSet = FALSE;
- PitChannels[Channel].InputFlipFlop = FALSE;
- PitChannels[Channel].OutputFlipFlop = FALSE;
-
- switch (Mode)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- {
- PitChannels[Channel].Mode = Mode;
- break;
- }
-
- case 6:
- {
- PitChannels[Channel].Mode = PIT_MODE_RATE_GENERATOR;
- break;
- }
-
- case 7:
- {
- PitChannels[Channel].Mode = PIT_MODE_SQUARE_WAVE;
- break;
- }
- }
-}
-
-BYTE PitReadData(BYTE Channel)
-{
- WORD CurrentValue = PitChannels[Channel].CurrentValue;
- BYTE AccessMode = PitChannels[Channel].AccessMode;
-
- /* Check if the value was latched */
- if (PitChannels[Channel].LatchSet)
- {
- CurrentValue = PitChannels[Channel].LatchedValue;
-
- if (AccessMode == 1 || AccessMode == 2)
- {
- /* The latched value was read as one byte */
- PitChannels[Channel].LatchSet = FALSE;
- }
- }
-
- /* Use the flip-flop for access mode 3 */
- if (AccessMode == 3)
- {
- AccessMode = PitChannels[Channel].InputFlipFlop ? 1 : 2;
- PitChannels[Channel].InputFlipFlop = !PitChannels[Channel].InputFlipFlop;
-
- /* Check if this was the last read for the latched value */
- if (!PitChannels[Channel].InputFlipFlop)
- {
- /* Yes, the latch value was read as two bytes */
- PitChannels[Channel].LatchSet = FALSE;
- }
- }
-
- switch (AccessMode)
- {
- case 1:
- {
- /* Low byte */
- return CurrentValue & 0x00FF;
- }
-
- case 2:
- {
- /* High byte */
- return CurrentValue >> 8;
- }
- }
-
- /* Shouldn't get here */
- return 0;
-}
-
-VOID PitWriteData(BYTE Channel, BYTE Value)
-{
- BYTE AccessMode = PitChannels[Channel].AccessMode;
-
- /* Use the flip-flop for access mode 3 */
- if (PitChannels[Channel].AccessMode == 3)
- {
- AccessMode = PitChannels[Channel].InputFlipFlop ? 1 : 2;
- PitChannels[Channel].InputFlipFlop = !PitChannels[Channel].InputFlipFlop;
- }
-
- switch (AccessMode)
- {
- case 1:
- {
- /* Low byte */
- PitChannels[Channel].ReloadValue &= 0xFF00;
- PitChannels[Channel].ReloadValue |= Value;
- break;
- }
-
- case 2:
- {
- /* High byte */
- PitChannels[Channel].ReloadValue &= 0x00FF;
- PitChannels[Channel].ReloadValue |= Value << 8;
- }
- }
-}
-
-VOID PitDecrementCount()
-{
- INT i;
-
- for (i = 0; i < PIT_CHANNELS; i++)
- {
- switch (PitChannels[i].Mode)
- {
- case PIT_MODE_INT_ON_TERMINAL_COUNT:
- {
- /* Decrement the value */
- PitChannels[i].CurrentValue--;
-
- /* Did it fall to the terminal count? */
- if (PitChannels[i].CurrentValue == 0 && !PitChannels[i].Pulsed)
- {
- /* Yes, raise the output line */
- if (i == 0) PicInterruptRequest(0);
- PitChannels[i].Pulsed = TRUE;
- }
- break;
- }
-
- case PIT_MODE_RATE_GENERATOR:
- {
- /* Decrement the value */
- PitChannels[i].CurrentValue--;
-
- /* Did it fall to zero? */
- if (PitChannels[i].CurrentValue != 0) break;
-
- /* Yes, raise the output line and reload */
- if (i == 0) PicInterruptRequest(0);
- PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
-
- break;
- }
-
- case PIT_MODE_SQUARE_WAVE:
- {
- /* Decrement the value by 2 */
- PitChannels[i].CurrentValue -= 2;
-
- /* Did it fall to zero? */
- if (PitChannels[i].CurrentValue != 0) break;
-
- /* Yes, toggle the flip-flop */
- 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 (i == 0) PicInterruptRequest(0);
- }
-
- /* Reload the value, but make sure it's even */
- if (PitChannels[i].ReloadValue % 2)
- {
- /* It's odd, reduce it by 1 */
- PitChannels[i].CurrentValue = PitChannels[i].ReloadValue - 1;
- }
- else
- {
- /* It was even */
- PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
- }
-
- break;
- }
-
- case PIT_MODE_SOFTWARE_STROBE:
- {
- // TODO: NOT IMPLEMENTED
- break;
- }
-
- case PIT_MODE_HARDWARE_ONE_SHOT:
- case PIT_MODE_HARDWARE_STROBE:
- {
- /* These modes do not work on x86 PCs */
- break;
- }
- }
- }
-}
-
-BYTE KeyboardReadStatus()
-{
- BYTE Status = 0;
-
- /* Set the first bit if the data can be read */
- if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0;
-
- /* Always set bit 2 */
- Status |= 1 << 2;
-
- /* Set bit 3 if the next byte goes to the controller */
- if (KeyboardWriteResponse) Status |= 1 << 3;
-
- return Status;
-}
-
-VOID KeyboardWriteCommand(BYTE Command)
-{
- switch (Command)
- {
- /* Read configuration byte */
- case 0x20:
- {
- KeyboardResponse = KeyboardConfig;
- KeyboardReadResponse = TRUE;
-
- break;
- }
-
- /* Write configuration byte */
- case 0x60:
- /* Write controller output port */
- case 0xD1:
- /* Write keyboard output buffer */
- case 0xD2:
- /* Write mouse output buffer */
- case 0xD3:
- /* Write mouse input buffer */
- case 0xD4:
- {
- /* These commands require a response */
- KeyboardResponse = Command;
- KeyboardWriteResponse = TRUE;
-
- break;
- }
-
- /* Disable mouse */
- case 0xA7:
- {
- // TODO: Mouse support
-
- break;
- }
-
- /* Enable mouse */
- case 0xA8:
- {
- // TODO: Mouse support
-
- break;
- }
-
- /* Test mouse port */
- case 0xA9:
- {
- KeyboardResponse = 0;
- KeyboardReadResponse = TRUE;
-
- break;
- }
-
- /* Test PS/2 controller */
- case 0xAA:
- {
- KeyboardResponse = 0x55;
- KeyboardReadResponse = TRUE;
-
- break;
- }
-
- /* Disable keyboard */
- case 0xAD:
- {
- // TODO: Not implemented
- break;
- }
-
- /* Enable keyboard */
- case 0xAE:
- {
- // TODO: Not implemented
- break;
- }
-
- /* Read controller output port */
- case 0xD0:
- {
- // TODO: Not implemented
- break;
- }
-
- /* CPU Reset */
- case 0xF0:
- case 0xF2:
- case 0xF4:
- case 0xF6:
- case 0xF8:
- case 0xFA:
- case 0xFC:
- case 0xFE:
- {
- /* Stop the simulation */
- VdmRunning = FALSE;
-
- break;
- }
- }
-}
-
-BYTE KeyboardReadData()
-{
- BYTE Value = 0;
-
- /* If there was a response byte from the controller, return it */
- if (KeyboardReadResponse)
- {
- KeyboardReadResponse = FALSE;
- return KeyboardResponse;
- }
-
- /* Otherwise, read the data from the queue */
- KeyboardQueuePop(&Value);
-
- return Value;
-}
-
-VOID KeyboardWriteData(BYTE Data)
-{
- /* Check if the controller is waiting for a response */
- if (KeyboardWriteResponse)
- {
- KeyboardWriteResponse = FALSE;
-
- /* Check which command it was */
- switch (KeyboardResponse)
- {
- /* Write configuration byte */
- case 0x60:
- {
- KeyboardConfig = Data;
- break;
- }
-
- /* Write controller output */
- case 0xD1:
- {
- /* Check if bit 0 is unset */
- if (!(Data & (1 << 0)))
- {
- /* CPU disabled - end simulation */
- VdmRunning = FALSE;
- }
-
- /* Update the A20 line setting */
- EmulatorSetA20(Data & (1 << 1));
-
- break;
- }
-
- case 0xD2:
- {
- /* Push the data byte to the keyboard queue */
- KeyboardQueuePush(Data);
-
- break;
- }
-
- case 0xD3:
- {
- // TODO: Mouse support
- break;
- }
-
- case 0xD4:
- {
- // TODO: Mouse support
- break;
- }
- }
-
- return;
- }
-
- // TODO: Implement PS/2 device commands
-}
-
-VOID CheckForInputEvents()
-{
- PINPUT_RECORD Buffer;
- HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
- DWORD i, j, Count, TotalEvents;
- BYTE ScanCode;
-
- /* Get the number of input events */
- if (!GetNumberOfConsoleInputEvents(ConsoleInput, &Count)) return;
- if (Count == 0) return;
-
- /* Allocate the buffer */
- Buffer = (PINPUT_RECORD)HeapAlloc(GetProcessHeap(), 0, Count *
sizeof(INPUT_RECORD));
- if (Buffer == NULL) return;
-
- /* Peek the input events */
- if (!ReadConsoleInput(ConsoleInput, Buffer, Count, &TotalEvents)) goto Cleanup;
-
- for (i = 0; i < TotalEvents; i++)
- {
- /* Check if this is a key event */
- if (Buffer[i].EventType != KEY_EVENT) continue;
-
- /* Get the scan code */
- ScanCode = Buffer[i].Event.KeyEvent.wVirtualScanCode;
-
- /* If this is a key release, set the highest bit in the scan code */
- if (!Buffer[i].Event.KeyEvent.bKeyDown) ScanCode |= 0x80;
-
- /* Push the scan code onto the keyboard queue */
- for (j = 0; j < Buffer[i].Event.KeyEvent.wRepeatCount; j++)
- {
- KeyboardQueuePush(ScanCode);
- }
-
- /* Yes, IRQ 1 */
- PicInterruptRequest(1);
-
- /* Stop the loop */
- break;
- }
-
-Cleanup:
- HeapFree(GetProcessHeap(), 0, Buffer);
-}
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -6,7 +6,17 @@
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
+/* INCLUDES *******************************************************************/
+
#include "ntvdm.h"
+#include "emulator.h"
+#include "bios.h"
+#include "dos.h"
+#include "timer.h"
+#include "pic.h"
+#include "ps2.h"
+
+/* PUBLIC VARIABLES ***********************************************************/
BOOLEAN VdmRunning = TRUE;
LPVOID BaseAddress = NULL;
@@ -21,6 +31,8 @@
L"Invalid Opcode",
L"FPU Not Available"
};
+
+/* PUBLIC FUNCTIONS ***********************************************************/
VOID DisplayMessage(LPCWSTR Format, ...)
{
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.h?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ntvdm.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ntvdm.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -5,6 +5,9 @@
* PURPOSE: Header file to define commonly used stuff
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
+
+#ifndef _NTVDM_H_
+#define _NTVDM_H_
/* INCLUDES *******************************************************************/
@@ -23,192 +26,7 @@
#define MAX_SEGMENT 0xFFFF
#define MAX_OFFSET 0xFFFF
#define MAX_ADDRESS TO_LINEAR(MAX_SEGMENT, MAX_OFFSET)
-#define ROM_AREA_START 0xC0000
-#define ROM_AREA_END 0xFFFFF
-#define BIOS_PIC_MASTER_INT 0x08
-#define BIOS_PIC_SLAVE_INT 0x70
-#define BIOS_SEGMENT 0xF000
-#define VIDEO_BIOS_INTERRUPT 0x10
-#define SPECIAL_INT_NUM 0xFF
-#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
-#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
#define STEPS_PER_CYCLE 256
-
-/* DOS constants */
-#define DOS_VERSION 0x0600
-#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT"
-#define DOS_COMMAND_INTERPRETER
L"%SystemRoot%\\system32\\COMMAND.COM /k
%SystemRoot%\\system32\\AUTOEXEC.NT"
-#define FIRST_MCB_SEGMENT 0x1000
-#define USER_MEMORY_SIZE 0x8FFFF
-#define SYSTEM_PSP 0x08
-#define SYSTEM_ENV_BLOCK 0x800
-
-/* System console constants */
-#define CONSOLE_FONT_HEIGHT 8
-#define CONSOLE_VIDEO_MEM_START 0xB8000
-#define CONSOLE_VIDEO_MEM_END 0xBFFFF
-
-/* Programmable interval timer (PIT) */
-#define PIT_CHANNELS 3
-#define PIT_BASE_FREQUENCY 1193182LL
-#define PIT_DATA_PORT(x) (0x40 + (x))
-#define PIT_COMMAND_PORT 0x43
-
-/* Programmable interrupt controller (PIC) */
-#define PIC_MASTER_CMD 0x20
-#define PIC_MASTER_DATA 0x21
-#define PIC_SLAVE_CMD 0xA0
-#define PIC_SLAVE_DATA 0xA1
-#define PIC_ICW1 0x10
-#define PIC_ICW1_ICW4 (1 << 0)
-#define PIC_ICW1_SINGLE (1 << 1)
-#define PIC_ICW4_8086 (1 << 0)
-#define PIC_ICW4_AEOI (1 << 1)
-#define PIC_OCW2_NUM_MASK 0x07
-#define PIC_OCW2_EOI (1 << 5)
-#define PIC_OCW2_SL (1 << 6)
-#define PIC_OCW3 (1 << 3)
-#define PIC_OCW3_READ_ISR 0x0B
-
-/* 8042 PS/2 controller */
-#define KEYBOARD_BUFFER_SIZE 32
-#define PS2_DATA_PORT 0x60
-#define PS2_CONTROL_PORT 0x64
-#define PS2_DEFAULT_CONFIG 0x05
-#define KEYBOARD_ACK 0xFA
-#define KEYBOARD_RESEND 0xFE
-
-#define EMULATOR_FLAG_CF (1 << 0)
-#define EMULATOR_FLAG_PF (1 << 2)
-#define EMULATOR_FLAG_AF (1 << 4)
-#define EMULATOR_FLAG_ZF (1 << 6)
-#define EMULATOR_FLAG_SF (1 << 7)
-#define EMULATOR_FLAG_TF (1 << 8)
-#define EMULATOR_FLAG_IF (1 << 9)
-#define EMULATOR_FLAG_DF (1 << 10)
-#define EMULATOR_FLAG_OF (1 << 11)
-#define EMULATOR_FLAG_NT (1 << 14)
-#define EMULATOR_FLAG_RF (1 << 16)
-#define EMULATOR_FLAG_VM (1 << 17)
-#define EMULATOR_FLAG_AC (1 << 18)
-#define EMULATOR_FLAG_VIF (1 << 19)
-#define EMULATOR_FLAG_VIP (1 << 20)
-#define EMULATOR_FLAG_ID (1 << 21)
-
-enum
-{
- EMULATOR_EXCEPTION_DIVISION_BY_ZERO,
- EMULATOR_EXCEPTION_DEBUG,
- EMULATOR_EXCEPTION_NMI,
- EMULATOR_EXCEPTION_BREAKPOINT,
- EMULATOR_EXCEPTION_OVERFLOW,
- EMULATOR_EXCEPTION_BOUND,
- EMULATOR_EXCEPTION_INVALID_OPCODE,
- EMULATOR_EXCEPTION_NO_FPU
-};
-
-typedef enum
-{
- EMULATOR_REG_AX,
- EMULATOR_REG_CX,
- EMULATOR_REG_DX,
- EMULATOR_REG_BX,
- EMULATOR_REG_SI,
- EMULATOR_REG_DI,
- EMULATOR_REG_SP,
- EMULATOR_REG_BP,
- EMULATOR_REG_ES,
- EMULATOR_REG_CS,
- EMULATOR_REG_SS,
- EMULATOR_REG_DS,
-} EMULATOR_REGISTER;
-
-#pragma pack(push, 1)
-
-typedef struct _DOS_MCB
-{
- CHAR BlockType;
- WORD OwnerPsp;
- WORD Size;
- BYTE Unused[3];
- CHAR Name[8];
-} DOS_MCB, *PDOS_MCB;
-
-typedef struct _DOS_FCB
-{
- BYTE DriveNumber;
- CHAR FileName[8];
- CHAR FileExt[3];
- WORD BlockNumber;
- WORD RecordSize;
- DWORD FileSize;
- WORD LastWriteDate;
- WORD LastWriteTime;
- BYTE Reserved[8];
- BYTE BlockRecord;
- BYTE RecordNumber[3];
-} DOS_FCB, *PDOS_FCB;
-
-typedef struct _DOS_PSP
-{
- BYTE Exit[2];
- WORD MemSize;
- BYTE Reserved0[6];
- DWORD TerminateAddress;
- DWORD BreakAddress;
- DWORD CriticalAddress;
- WORD ParentPsp;
- BYTE HandleTable[20];
- WORD EnvBlock;
- DWORD LastStack;
- WORD HandleTableSize;
- DWORD HandleTablePtr;
- DWORD PreviousPsp;
- DWORD Reserved1;
- WORD DosVersion;
- BYTE Reserved2[14];
- BYTE FarCall[3];
- BYTE Reserved3[9];
- DOS_FCB Fcb;
- BYTE CommandLineSize;
- CHAR CommandLine[127];
-} DOS_PSP, *PDOS_PSP;
-
-typedef struct _DOS_SFT_ENTRY
-{
- WORD ReferenceCount;
- WORD Mode;
- BYTE Attribute;
- WORD DeviceInfo;
- DWORD DriveParamBlock;
- WORD FirstCluster;
- WORD FileTime;
- WORD FileDate;
- DWORD FileSize;
- DWORD CurrentOffset;
- WORD LastClusterAccessed;
- DWORD DirEntSector;
- BYTE DirEntryIndex;
- CHAR FileName[11];
- BYTE Reserved0[6];
- WORD OwnerPsp;
- BYTE Reserved1[8];
-} DOS_SFT_ENTRY, *PDOS_SFT_ENTRY;
-
-typedef struct _DOS_SFT
-{
- DWORD NextTablePtr;
- WORD FileCount;
- DOS_SFT_ENTRY Entry[ANYSIZE_ARRAY];
-} DOS_SFT, *PDOS_SFT;
-
-typedef struct _DOS_INPUT_BUFFER
-{
- BYTE MaxLength, Length;
- CHAR Buffer[ANYSIZE_ARRAY];
-} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER;
-
-#pragma pack(pop)
/* FUNCTIONS ******************************************************************/
@@ -217,47 +35,7 @@
extern LPCWSTR ExceptionName[];
VOID DisplayMessage(LPCWSTR Format, ...);
-BOOLEAN BiosInitialize();
-VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress);
-VOID BiosPrintCharacter(CHAR Character, BYTE Attribute);
-BOOLEAN DosInitialize();
-WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable);
-BOOLEAN DosFreeMemory(WORD BlockData);
-BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable);
-BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock);
-VOID DosInt20h(WORD CodeSegment);
-VOID DosInt21h(WORD CodeSegment);
-VOID DosBreakInterrupt();
-VOID BiosVideoService();
-VOID BiosHandleIrq(BYTE IrqNumber);
-BYTE PicReadCommand(BYTE Port);
-VOID PicWriteCommand(BYTE Port, BYTE Value);
-BYTE PicReadData(BYTE Port);
-VOID PicWriteData(BYTE Port, BYTE Value);
-VOID PicInterruptRequest(BYTE Number);
-VOID PitInitialize();
-VOID PitWriteCommand(BYTE Value);
-BYTE PitReadData(BYTE Channel);
-VOID PitWriteData(BYTE Channel, BYTE Value);
-VOID PitDecrementCount();
-VOID CheckForInputEvents();
-BYTE KeyboardReadStatus();
-VOID KeyboardWriteCommand(BYTE Command);
-BYTE KeyboardReadData();
-VOID KeyboardWriteData(BYTE Data);
-VOID EmulatorSetStack(WORD Segment, WORD Offset);
-VOID EmulatorExecute(WORD Segment, WORD Offset);
-VOID EmulatorInterrupt(BYTE Number);
-VOID EmulatorExternalInterrupt(BYTE Number);
-ULONG EmulatorGetRegister(ULONG Register);
-VOID EmulatorSetRegister(ULONG Register, ULONG Value);
-VOID EmulatorSetFlag(ULONG Flag);
-VOID EmulatorClearFlag(ULONG Flag);
-BOOLEAN EmulatorGetFlag(ULONG Flag);
-BOOLEAN EmulatorInitialize();
-VOID EmulatorStep();
-VOID EmulatorCleanup();
-VOID EmulatorHalt();
-VOID EmulatorSetA20(BOOLEAN Enabled);
+
+#endif
/* EOF */
Added: branches/ntvdm/subsystems/ntvdm/pic.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/pic.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/pic.c (added)
+++ branches/ntvdm/subsystems/ntvdm/pic.c [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,205 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: pic.c
+ * PURPOSE: Programmable Interrupt Controller emulation
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "pic.h"
+#include "emulator.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static PIC MasterPic, SlavePic;
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BYTE PicReadCommand(BYTE Port)
+{
+ PPIC Pic;
+
+ /* Which PIC are we accessing? */
+ if (Port == PIC_MASTER_CMD) Pic = &MasterPic;
+ else Pic = &SlavePic;
+
+ if (Pic->ReadIsr)
+ {
+ /* Read the in-service register */
+ Pic->ReadIsr = FALSE;
+ return Pic->InServiceRegister;
+ }
+ else
+ {
+ /* The IRR is always 0, as the emulated CPU receives the interrupt instantly */
+ return 0;
+ }
+}
+
+VOID PicWriteCommand(BYTE Port, BYTE Value)
+{
+ PPIC Pic;
+
+ /* Which PIC are we accessing? */
+ if (Port == PIC_MASTER_CMD) Pic = &MasterPic;
+ else Pic = &SlavePic;
+
+ if (Value & PIC_ICW1)
+ {
+ /* Start initialization */
+ Pic->Initialization = TRUE;
+ Pic->IntOffset = 0xFF;
+ Pic->CascadeRegisterSet = FALSE;
+ Pic->ConfigRegister = Value;
+ return;
+ }
+
+ if (Value & PIC_OCW3)
+ {
+ /* This is an OCR3 */
+ if (Value == PIC_OCW3_READ_ISR)
+ {
+ /* Return the ISR on next read from command port */
+ Pic->ReadIsr = TRUE;
+ }
+
+ return;
+ }
+
+ /* This is an OCW2 */
+ if (Value & PIC_OCW2_EOI)
+ {
+ if (Value & PIC_OCW2_SL)
+ {
+ /* If the SL bit is set, clear a specific IRQ */
+ Pic->InServiceRegister &= ~(1 << (Value &
PIC_OCW2_NUM_MASK));
+ }
+ else
+ {
+ /* Otherwise, clear all of them */
+ Pic->InServiceRegister = 0;
+ }
+ }
+}
+
+BYTE PicReadData(BYTE Port)
+{
+ /* Read the mask register */
+ if (Port == PIC_MASTER_DATA) return MasterPic.MaskRegister;
+ else return SlavePic.MaskRegister;
+}
+
+VOID PicWriteData(BYTE Port, BYTE Value)
+{
+ PPIC Pic;
+
+ /* Which PIC are we accessing? */
+ if (Port == PIC_MASTER_DATA) Pic = &MasterPic;
+ else Pic = &SlavePic;
+
+ /* Is the PIC ready? */
+ if (!Pic->Initialization)
+ {
+ /* Yes, this is an OCW1 */
+ Pic->MaskRegister = Value;
+ return;
+ }
+
+ /* Has the interrupt offset been set? */
+ if (Pic->IntOffset == 0xFF)
+ {
+ /* This is an ICW2, set the offset (last three bits always zero) */
+ Pic->IntOffset = Value & 0xF8;
+
+ /* Check if we are in single mode and don't need an ICW4 */
+ if ((Pic->ConfigRegister & PIC_ICW1_SINGLE)
+ && !(Pic->ConfigRegister & PIC_ICW1_ICW4))
+ {
+ /* Yes, done initializing */
+ Pic->Initialization = FALSE;
+ }
+ return;
+ }
+
+ /* Check if we are in cascade mode and the cascade register was not set */
+ if (!(Pic->ConfigRegister & PIC_ICW1_SINGLE) &&
!Pic->CascadeRegisterSet)
+ {
+ /* This is an ICW3 */
+ Pic->CascadeRegister = Value;
+ Pic->CascadeRegisterSet = TRUE;
+
+ /* Check if we need an ICW4 */
+ if (!(Pic->ConfigRegister & PIC_ICW1_ICW4))
+ {
+ /* No, done initializing */
+ Pic->Initialization = FALSE;
+ }
+ return;
+ }
+
+ /* This must be an ICW4, we will ignore the 8086 bit (assume always set) */
+ if (Value & PIC_ICW4_AEOI)
+ {
+ /* Use automatic end-of-interrupt */
+ Pic->AutoEoi = TRUE;
+ }
+
+ /* Done initializing */
+ Pic->Initialization = FALSE;
+}
+
+VOID PicInterruptRequest(BYTE Number)
+{
+ BYTE i;
+
+ if (Number >= 0 && Number < 8)
+ {
+ /* Check if any of the higher-priorirty interrupts are busy */
+ for (i = 0; i <= Number ; i++)
+ {
+ if (MasterPic.InServiceRegister & (1 << Number)) return;
+ }
+
+ /* Check if the interrupt is masked */
+ if (MasterPic.MaskRegister & (1 << Number)) return;
+
+ /* Set the appropriate bit in the ISR and interrupt the CPU */
+ if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << Number;
+ EmulatorExternalInterrupt(MasterPic.IntOffset + Number);
+ }
+ else if (Number >= 8 && Number < 16)
+ {
+ Number -= 8;
+
+ /*
+ * The slave PIC is connected to IRQ 2, always! If the master PIC
+ * was misconfigured, don't do anything.
+ */
+ if (!(MasterPic.CascadeRegister & (1 << 2))
+ || SlavePic.CascadeRegister != 2)
+ {
+ return;
+ }
+
+ /* Check if any of the higher-priorirty interrupts are busy */
+ if (MasterPic.InServiceRegister != 0) return;
+ for (i = 0; i <= Number ; i++)
+ {
+ if (SlavePic.InServiceRegister & (1 << Number)) return;
+ }
+
+ /* Check if the interrupt is masked */
+ if (SlavePic.MaskRegister & (1 << Number)) return;
+
+ /* Set the IRQ 2 bit in the master ISR */
+ if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << 2;
+
+ /* Set the appropriate bit in the ISR and interrupt the CPU */
+ if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= 1 << Number;
+ EmulatorExternalInterrupt(SlavePic.IntOffset + Number);
+ }
+}
+
+/* EOF */
Propchange: branches/ntvdm/subsystems/ntvdm/pic.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/ntvdm/subsystems/ntvdm/pic.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/pic.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/pic.h (added)
+++ branches/ntvdm/subsystems/ntvdm/pic.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,57 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: pic.h
+ * PURPOSE: Programmable Interrupt Controller emulation (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _PIC_H_
+#define _PIC_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define PIC_MASTER_CMD 0x20
+#define PIC_MASTER_DATA 0x21
+#define PIC_SLAVE_CMD 0xA0
+#define PIC_SLAVE_DATA 0xA1
+#define PIC_ICW1 0x10
+#define PIC_ICW1_ICW4 (1 << 0)
+#define PIC_ICW1_SINGLE (1 << 1)
+#define PIC_ICW4_8086 (1 << 0)
+#define PIC_ICW4_AEOI (1 << 1)
+#define PIC_OCW2_NUM_MASK 0x07
+#define PIC_OCW2_EOI (1 << 5)
+#define PIC_OCW2_SL (1 << 6)
+#define PIC_OCW3 (1 << 3)
+#define PIC_OCW3_READ_ISR 0x0B
+
+typedef struct _PIC
+{
+ BOOLEAN Initialization;
+ BYTE MaskRegister;
+ BYTE InServiceRegister;
+ BYTE IntOffset;
+ BYTE ConfigRegister;
+ BYTE CascadeRegister;
+ BOOLEAN CascadeRegisterSet;
+ BOOLEAN AutoEoi;
+ BOOLEAN Slave;
+ BOOLEAN ReadIsr;
+} PIC, *PPIC;
+
+/* FUNCTIONS ******************************************************************/
+
+BYTE PicReadCommand(BYTE Port);
+VOID PicWriteCommand(BYTE Port, BYTE Value);
+BYTE PicReadData(BYTE Port);
+VOID PicWriteData(BYTE Port, BYTE Value);
+VOID PicInterruptRequest(BYTE Number);
+
+#endif
+
+/* EOF */
Propchange: branches/ntvdm/subsystems/ntvdm/pic.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/ntvdm/subsystems/ntvdm/ps2.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ps2.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ps2.c (added)
+++ branches/ntvdm/subsystems/ntvdm/ps2.c [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,313 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: ps2.c
+ * PURPOSE: PS/2 controller emulation
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "ps2.h"
+#include "emulator.h"
+#include "pic.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static BYTE KeyboardQueue[KEYBOARD_BUFFER_SIZE];
+static BOOLEAN KeyboardQueueEmpty = TRUE;
+static UINT KeyboardQueueStart = 0;
+static UINT KeyboardQueueEnd = 0;
+static BYTE KeyboardResponse = 0;
+static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE;
+static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
+{
+ /* Check if the keyboard queue is full */
+ if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
+ {
+ return FALSE;
+ }
+
+ /* Insert the value in the queue */
+ KeyboardQueue[KeyboardQueueEnd] = ScanCode;
+ KeyboardQueueEnd++;
+ KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE;
+
+ /* Since we inserted a value, it's not empty anymore */
+ KeyboardQueueEmpty = FALSE;
+
+ return TRUE;
+}
+
+static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
+{
+ /* Make sure the keyboard queue is not empty */
+ if (KeyboardQueueEmpty) return FALSE;
+
+ /* Get the scan code */
+ *ScanCode = KeyboardQueue[KeyboardQueueStart];
+
+ /* Remove the value from the queue */
+ KeyboardQueueStart++;
+ KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE;
+
+ /* Check if the queue is now empty */
+ if (KeyboardQueueStart == KeyboardQueueEnd)
+ {
+ KeyboardQueueEmpty = TRUE;
+ }
+
+ return TRUE;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BYTE KeyboardReadStatus()
+{
+ BYTE Status = 0;
+
+ /* Set the first bit if the data can be read */
+ if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0;
+
+ /* Always set bit 2 */
+ Status |= 1 << 2;
+
+ /* Set bit 3 if the next byte goes to the controller */
+ if (KeyboardWriteResponse) Status |= 1 << 3;
+
+ return Status;
+}
+
+VOID KeyboardWriteCommand(BYTE Command)
+{
+ switch (Command)
+ {
+ /* Read configuration byte */
+ case 0x20:
+ {
+ KeyboardResponse = KeyboardConfig;
+ KeyboardReadResponse = TRUE;
+
+ break;
+ }
+
+ /* Write configuration byte */
+ case 0x60:
+ /* Write controller output port */
+ case 0xD1:
+ /* Write keyboard output buffer */
+ case 0xD2:
+ /* Write mouse output buffer */
+ case 0xD3:
+ /* Write mouse input buffer */
+ case 0xD4:
+ {
+ /* These commands require a response */
+ KeyboardResponse = Command;
+ KeyboardWriteResponse = TRUE;
+
+ break;
+ }
+
+ /* Disable mouse */
+ case 0xA7:
+ {
+ // TODO: Mouse support
+
+ break;
+ }
+
+ /* Enable mouse */
+ case 0xA8:
+ {
+ // TODO: Mouse support
+
+ break;
+ }
+
+ /* Test mouse port */
+ case 0xA9:
+ {
+ KeyboardResponse = 0;
+ KeyboardReadResponse = TRUE;
+
+ break;
+ }
+
+ /* Test PS/2 controller */
+ case 0xAA:
+ {
+ KeyboardResponse = 0x55;
+ KeyboardReadResponse = TRUE;
+
+ break;
+ }
+
+ /* Disable keyboard */
+ case 0xAD:
+ {
+ // TODO: Not implemented
+ break;
+ }
+
+ /* Enable keyboard */
+ case 0xAE:
+ {
+ // TODO: Not implemented
+ break;
+ }
+
+ /* Read controller output port */
+ case 0xD0:
+ {
+ // TODO: Not implemented
+ break;
+ }
+
+ /* CPU Reset */
+ case 0xF0:
+ case 0xF2:
+ case 0xF4:
+ case 0xF6:
+ case 0xF8:
+ case 0xFA:
+ case 0xFC:
+ case 0xFE:
+ {
+ /* Stop the simulation */
+ VdmRunning = FALSE;
+
+ break;
+ }
+ }
+}
+
+BYTE KeyboardReadData()
+{
+ BYTE Value = 0;
+
+ /* If there was a response byte from the controller, return it */
+ if (KeyboardReadResponse)
+ {
+ KeyboardReadResponse = FALSE;
+ return KeyboardResponse;
+ }
+
+ /* Otherwise, read the data from the queue */
+ KeyboardQueuePop(&Value);
+
+ return Value;
+}
+
+VOID KeyboardWriteData(BYTE Data)
+{
+ /* Check if the controller is waiting for a response */
+ if (KeyboardWriteResponse)
+ {
+ KeyboardWriteResponse = FALSE;
+
+ /* Check which command it was */
+ switch (KeyboardResponse)
+ {
+ /* Write configuration byte */
+ case 0x60:
+ {
+ KeyboardConfig = Data;
+ break;
+ }
+
+ /* Write controller output */
+ case 0xD1:
+ {
+ /* Check if bit 0 is unset */
+ if (!(Data & (1 << 0)))
+ {
+ /* CPU disabled - end simulation */
+ VdmRunning = FALSE;
+ }
+
+ /* Update the A20 line setting */
+ EmulatorSetA20(Data & (1 << 1));
+
+ break;
+ }
+
+ case 0xD2:
+ {
+ /* Push the data byte to the keyboard queue */
+ KeyboardQueuePush(Data);
+
+ break;
+ }
+
+ case 0xD3:
+ {
+ // TODO: Mouse support
+ break;
+ }
+
+ case 0xD4:
+ {
+ // TODO: Mouse support
+ break;
+ }
+ }
+
+ return;
+ }
+
+ // TODO: Implement PS/2 device commands
+}
+
+VOID CheckForInputEvents()
+{
+ PINPUT_RECORD Buffer;
+ HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD i, j, Count, TotalEvents;
+ BYTE ScanCode;
+
+ /* Get the number of input events */
+ if (!GetNumberOfConsoleInputEvents(ConsoleInput, &Count)) return;
+ if (Count == 0) return;
+
+ /* Allocate the buffer */
+ Buffer = (PINPUT_RECORD)HeapAlloc(GetProcessHeap(), 0, Count *
sizeof(INPUT_RECORD));
+ if (Buffer == NULL) return;
+
+ /* Peek the input events */
+ if (!ReadConsoleInput(ConsoleInput, Buffer, Count, &TotalEvents)) goto Cleanup;
+
+ for (i = 0; i < TotalEvents; i++)
+ {
+ /* Check if this is a key event */
+ if (Buffer[i].EventType != KEY_EVENT) continue;
+
+ /* Get the scan code */
+ ScanCode = Buffer[i].Event.KeyEvent.wVirtualScanCode;
+
+ /* If this is a key release, set the highest bit in the scan code */
+ if (!Buffer[i].Event.KeyEvent.bKeyDown) ScanCode |= 0x80;
+
+ /* Push the scan code onto the keyboard queue */
+ for (j = 0; j < Buffer[i].Event.KeyEvent.wRepeatCount; j++)
+ {
+ KeyboardQueuePush(ScanCode);
+ }
+
+ /* Yes, IRQ 1 */
+ PicInterruptRequest(1);
+
+ /* Stop the loop */
+ break;
+ }
+
+Cleanup:
+ HeapFree(GetProcessHeap(), 0, Buffer);
+}
+
+/* EOF */
+
Propchange: branches/ntvdm/subsystems/ntvdm/ps2.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/ntvdm/subsystems/ntvdm/ps2.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ps2.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ps2.h (added)
+++ branches/ntvdm/subsystems/ntvdm/ps2.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: ps2.h
+ * PURPOSE: PS/2 controller emulation (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _PS2_H_
+#define _PS2_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define KEYBOARD_BUFFER_SIZE 32
+#define PS2_DATA_PORT 0x60
+#define PS2_CONTROL_PORT 0x64
+#define PS2_DEFAULT_CONFIG 0x05
+#define KEYBOARD_ACK 0xFA
+#define KEYBOARD_RESEND 0xFE
+
+/* FUNCTIONS ******************************************************************/
+
+BYTE KeyboardReadStatus();
+VOID KeyboardWriteCommand(BYTE Command);
+BYTE KeyboardReadData();
+VOID KeyboardWriteData(BYTE Data);
+VOID CheckForInputEvents();
+
+#endif
Propchange: branches/ntvdm/subsystems/ntvdm/ps2.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/ntvdm/subsystems/ntvdm/timer.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/timer.c?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/timer.c (added)
+++ branches/ntvdm/subsystems/ntvdm/timer.c [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,235 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: timer.c
+ * PURPOSE: Programmable Interval Timer emulation
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "timer.h"
+#include "pic.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static PIT_CHANNEL PitChannels[PIT_CHANNELS];
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID PitWriteCommand(BYTE Value)
+{
+ BYTE Channel = Value >> 6;
+ BYTE Mode = (Value >> 1) & 0x07;
+
+ /* Check if this is a counter latch command */
+ if (((Value >> 4) & 3) == 0)
+ {
+ PitChannels[Channel].LatchSet = TRUE;
+ PitChannels[Channel].LatchedValue = PitChannels[Channel].CurrentValue;
+ return;
+ }
+
+ /* Set the access mode and reset flip-flops */
+ PitChannels[Channel].AccessMode = (Value >> 4) & 3;
+ PitChannels[Channel].Pulsed = FALSE;
+ PitChannels[Channel].LatchSet = FALSE;
+ PitChannels[Channel].InputFlipFlop = FALSE;
+ PitChannels[Channel].OutputFlipFlop = FALSE;
+
+ switch (Mode)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ {
+ PitChannels[Channel].Mode = Mode;
+ break;
+ }
+
+ case 6:
+ {
+ PitChannels[Channel].Mode = PIT_MODE_RATE_GENERATOR;
+ break;
+ }
+
+ case 7:
+ {
+ PitChannels[Channel].Mode = PIT_MODE_SQUARE_WAVE;
+ break;
+ }
+ }
+}
+
+BYTE PitReadData(BYTE Channel)
+{
+ WORD CurrentValue = PitChannels[Channel].CurrentValue;
+ BYTE AccessMode = PitChannels[Channel].AccessMode;
+
+ /* Check if the value was latched */
+ if (PitChannels[Channel].LatchSet)
+ {
+ CurrentValue = PitChannels[Channel].LatchedValue;
+
+ if (AccessMode == 1 || AccessMode == 2)
+ {
+ /* The latched value was read as one byte */
+ PitChannels[Channel].LatchSet = FALSE;
+ }
+ }
+
+ /* Use the flip-flop for access mode 3 */
+ if (AccessMode == 3)
+ {
+ AccessMode = PitChannels[Channel].InputFlipFlop ? 1 : 2;
+ PitChannels[Channel].InputFlipFlop = !PitChannels[Channel].InputFlipFlop;
+
+ /* Check if this was the last read for the latched value */
+ if (!PitChannels[Channel].InputFlipFlop)
+ {
+ /* Yes, the latch value was read as two bytes */
+ PitChannels[Channel].LatchSet = FALSE;
+ }
+ }
+
+ switch (AccessMode)
+ {
+ case 1:
+ {
+ /* Low byte */
+ return CurrentValue & 0x00FF;
+ }
+
+ case 2:
+ {
+ /* High byte */
+ return CurrentValue >> 8;
+ }
+ }
+
+ /* Shouldn't get here */
+ return 0;
+}
+
+VOID PitWriteData(BYTE Channel, BYTE Value)
+{
+ BYTE AccessMode = PitChannels[Channel].AccessMode;
+
+ /* Use the flip-flop for access mode 3 */
+ if (PitChannels[Channel].AccessMode == 3)
+ {
+ AccessMode = PitChannels[Channel].InputFlipFlop ? 1 : 2;
+ PitChannels[Channel].InputFlipFlop = !PitChannels[Channel].InputFlipFlop;
+ }
+
+ switch (AccessMode)
+ {
+ case 1:
+ {
+ /* Low byte */
+ PitChannels[Channel].ReloadValue &= 0xFF00;
+ PitChannels[Channel].ReloadValue |= Value;
+ break;
+ }
+
+ case 2:
+ {
+ /* High byte */
+ PitChannels[Channel].ReloadValue &= 0x00FF;
+ PitChannels[Channel].ReloadValue |= Value << 8;
+ }
+ }
+}
+
+VOID PitDecrementCount()
+{
+ INT i;
+
+ for (i = 0; i < PIT_CHANNELS; i++)
+ {
+ switch (PitChannels[i].Mode)
+ {
+ case PIT_MODE_INT_ON_TERMINAL_COUNT:
+ {
+ /* Decrement the value */
+ PitChannels[i].CurrentValue--;
+
+ /* Did it fall to the terminal count? */
+ if (PitChannels[i].CurrentValue == 0 && !PitChannels[i].Pulsed)
+ {
+ /* Yes, raise the output line */
+ if (i == 0) PicInterruptRequest(0);
+ PitChannels[i].Pulsed = TRUE;
+ }
+ break;
+ }
+
+ case PIT_MODE_RATE_GENERATOR:
+ {
+ /* Decrement the value */
+ PitChannels[i].CurrentValue--;
+
+ /* Did it fall to zero? */
+ if (PitChannels[i].CurrentValue != 0) break;
+
+ /* Yes, raise the output line and reload */
+ if (i == 0) PicInterruptRequest(0);
+ PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
+
+ break;
+ }
+
+ case PIT_MODE_SQUARE_WAVE:
+ {
+ /* Decrement the value by 2 */
+ PitChannels[i].CurrentValue -= 2;
+
+ /* Did it fall to zero? */
+ if (PitChannels[i].CurrentValue != 0) break;
+
+ /* Yes, toggle the flip-flop */
+ 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 (i == 0) PicInterruptRequest(0);
+ }
+
+ /* Reload the value, but make sure it's even */
+ if (PitChannels[i].ReloadValue % 2)
+ {
+ /* It's odd, reduce it by 1 */
+ PitChannels[i].CurrentValue = PitChannels[i].ReloadValue - 1;
+ }
+ else
+ {
+ /* It was even */
+ PitChannels[i].CurrentValue = PitChannels[i].ReloadValue;
+ }
+
+ break;
+ }
+
+ case PIT_MODE_SOFTWARE_STROBE:
+ {
+ // TODO: NOT IMPLEMENTED
+ break;
+ }
+
+ case PIT_MODE_HARDWARE_ONE_SHOT:
+ case PIT_MODE_HARDWARE_STROBE:
+ {
+ /* These modes do not work on x86 PCs */
+ break;
+ }
+ }
+ }
+}
+
+/* EOF */
+
Propchange: branches/ntvdm/subsystems/ntvdm/timer.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/ntvdm/subsystems/ntvdm/timer.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/timer.h?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/timer.h (added)
+++ branches/ntvdm/subsystems/ntvdm/timer.h [iso-8859-1] Wed Jun 26 22:58:41 2013
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: timer.h
+ * PURPOSE: Programmable Interval Timer emulation (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define PIT_CHANNELS 3
+#define PIT_BASE_FREQUENCY 1193182LL
+#define PIT_DATA_PORT(x) (0x40 + (x))
+#define PIT_COMMAND_PORT 0x43
+
+enum
+{
+ PIT_MODE_INT_ON_TERMINAL_COUNT,
+ PIT_MODE_HARDWARE_ONE_SHOT,
+ PIT_MODE_RATE_GENERATOR,
+ PIT_MODE_SQUARE_WAVE,
+ PIT_MODE_SOFTWARE_STROBE,
+ PIT_MODE_HARDWARE_STROBE
+};
+
+typedef struct _PIT_CHANNEL
+{
+ WORD ReloadValue;
+ WORD CurrentValue;
+ WORD LatchedValue;
+ INT Mode;
+ BOOLEAN Pulsed;
+ BOOLEAN LatchSet;
+ BOOLEAN InputFlipFlop;
+ BOOLEAN OutputFlipFlop;
+ BYTE AccessMode;
+} PIT_CHANNEL, *PPIT_CHANNEL;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID PitWriteCommand(BYTE Value);
+BYTE PitReadData(BYTE Channel);
+VOID PitWriteData(BYTE Channel, BYTE Value);
+VOID PitDecrementCount();
+
+#endif
+
+/* EOF */
+
Propchange: branches/ntvdm/subsystems/ntvdm/timer.h
------------------------------------------------------------------------------
svn:eol-style = native