Author: hbelusca Date: Tue Sep 16 00:51:15 2014 New Revision: 64168
URL: http://svn.reactos.org/svn/reactos?rev=64168&view=rev Log: [NTVDM] - Move the mouse driver to DOS since it's our 32bit version of mouse.com, in some sense, - Temporarily disable the mouse user callbacks because currently they went called in a parallel thread than the CPU one, that caused CPU corruption, - In the same way we currently trigger IRQ1 interrupts, we do the same for IRQ12, - Make the console input pump more modular (and mouse presence detection code is WIP), - Put keyboard code into a dedicated file (as done for the mouse), - Adapt the existing PS/2 emulation code to support two PS/2 ports controlled by 1 controller. Please note that some documentations precise that the response byte (answer to a PS/2 controller command) is written directly to the PS/2 output port.
Added: trunk/reactos/subsystems/ntvdm/dos/mouse32.c - copied, changed from r64138, trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c trunk/reactos/subsystems/ntvdm/dos/mouse32.h - copied, changed from r64138, trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h trunk/reactos/subsystems/ntvdm/hardware/keyboard.c (with props) trunk/reactos/subsystems/ntvdm/hardware/keyboard.h (with props) Modified: trunk/reactos/subsystems/ntvdm/CMakeLists.txt trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c trunk/reactos/subsystems/ntvdm/clock.c trunk/reactos/subsystems/ntvdm/dos/dem.c trunk/reactos/subsystems/ntvdm/emulator.c trunk/reactos/subsystems/ntvdm/hardware/mouse.c trunk/reactos/subsystems/ntvdm/hardware/mouse.h trunk/reactos/subsystems/ntvdm/hardware/ps2.c trunk/reactos/subsystems/ntvdm/hardware/ps2.h trunk/reactos/subsystems/ntvdm/hardware/vga.c trunk/reactos/subsystems/ntvdm/hardware/vga.h trunk/reactos/subsystems/ntvdm/ntvdm.c trunk/reactos/subsystems/ntvdm/ntvdm.h
Modified: trunk/reactos/subsystems/ntvdm/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/CMakeLists... ============================================================================== --- trunk/reactos/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -15,15 +15,17 @@ bios/rom.c bios/vidbios.c hardware/cmos.c + hardware/keyboard.c + hardware/mouse.c hardware/pic.c hardware/ps2.c hardware/speaker.c hardware/timer.c hardware/vga.c - hardware/mouse.c dos/dos32krnl/bios.c dos/dos32krnl/dos.c dos/dos32krnl/dosfiles.c + dos/mouse32.c dos/dem.c bop.c callback.c
Modified: trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/bios3... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -21,618 +21,24 @@
/* PRIVATE VARIABLES **********************************************************/
-static BOOLEAN DriverEnabled = TRUE; -static MOUSE_DRIVER_STATE DriverState; - /* PRIVATE FUNCTIONS **********************************************************/
-static VOID PaintMouseCursor(VOID) +// Mouse IRQ 12 +static VOID WINAPI BiosMouseIrq(LPWORD Stack) { - if (Bda->VideoMode <= 3) - { - WORD Character; - DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); - - EmulatorReadMemory(&EmulatorContext, - VideoAddress - + (DriverState.Position.Y * Bda->ScreenColumns - + DriverState.Position.X) * sizeof(WORD), - (LPVOID)&Character, - sizeof(WORD)); - - DriverState.Character = Character; - Character &= DriverState.TextCursor.ScreenMask; - Character ^= DriverState.TextCursor.CursorMask; - - EmulatorWriteMemory(&EmulatorContext, - VideoAddress - + (DriverState.Position.Y * Bda->ScreenColumns - + DriverState.Position.X) * sizeof(WORD), - (LPVOID)&Character, - sizeof(WORD)); - } - else - { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; - } -} - -static VOID EraseMouseCursor(VOID) -{ - if (Bda->VideoMode <= 3) - { - DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); - - EmulatorWriteMemory(&EmulatorContext, - VideoAddress - + (DriverState.Position.Y * Bda->ScreenColumns - + DriverState.Position.X) * sizeof(WORD), - (LPVOID)&DriverState.Character, - sizeof(WORD)); - } - else - { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; - } -} - -static VOID CallMouseUserHandlers(USHORT CallMask) -{ - USHORT i; - - /* Call handler 0 */ - if ((DriverState.Handler0.CallMask & CallMask) != 0 && - DriverState.Handler0.Callback != (ULONG)NULL) - { - /* - * Set the parameters for the callback. - * NOTE: In text modes, the row and column will be reported - * as a multiple of the cell size, typically 8x8 pixels. - */ - setAX(CallMask); - setBX(DriverState.ButtonState); - setCX(DriverState.Position.X); - setDX(DriverState.Position.Y); - setSI(DriverState.MickeysPerCellHoriz); - setDI(DriverState.MickeysPerCellVert); - - DPRINT1("Calling Handler0 0x%08x with CallMask 0x%04x\n", - DriverState.Handler0.Callback, CallMask); - - /* Call the callback */ - RunCallback16(&BiosContext, DriverState.Handler0.Callback); - } - - for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) - { - /* Call the suitable handlers */ - if ((DriverState.Handlers[i].CallMask & CallMask) != 0 && - DriverState.Handlers[i].Callback != (ULONG)NULL) - { - /* - * Set the parameters for the callback. - * NOTE: In text modes, the row and column will be reported - * as a multiple of the cell size, typically 8x8 pixels. - */ - setAX(CallMask); - setBX(DriverState.ButtonState); - setCX(DriverState.Position.X); - setDX(DriverState.Position.Y); - setSI(DriverState.MickeysPerCellHoriz); - setDI(DriverState.MickeysPerCellVert); - - DPRINT1("Calling Handler[%d] 0x%08x with CallMask 0x%04x\n", - i, DriverState.Handlers[i].Callback, CallMask); - - /* Call the callback */ - RunCallback16(&BiosContext, DriverState.Handlers[i].Callback); - } - } -} - -static VOID WINAPI BiosMouseService(LPWORD Stack) -{ - switch (getAX()) - { - /* Reset Driver */ - case 0x00: - { - SHORT i; - - DriverEnabled = TRUE; - DriverState.ShowCount = 0; - DriverState.ButtonState = 0; - - /* Set the default text cursor */ - DriverState.TextCursor.ScreenMask = 0xFFFF; /* Display everything */ - DriverState.TextCursor.CursorMask = 0xFF00; /* ... but with inverted attributes */ - - /* Set the default graphics cursor */ - DriverState.GraphicsCursor.HotSpot.X = 3; - DriverState.GraphicsCursor.HotSpot.Y = 1; - - DriverState.GraphicsCursor.ScreenMask[0] = 0xC3FF; // 1100001111111111 - DriverState.GraphicsCursor.ScreenMask[1] = 0xC0FF; // 1100000011111111 - DriverState.GraphicsCursor.ScreenMask[2] = 0xC07F; // 1100000001111111 - DriverState.GraphicsCursor.ScreenMask[3] = 0xC01F; // 1100000000011111 - DriverState.GraphicsCursor.ScreenMask[4] = 0xC00F; // 1100000000001111 - DriverState.GraphicsCursor.ScreenMask[5] = 0xC007; // 1100000000000111 - DriverState.GraphicsCursor.ScreenMask[6] = 0xC003; // 1100000000000011 - DriverState.GraphicsCursor.ScreenMask[7] = 0xC007; // 1100000000000111 - DriverState.GraphicsCursor.ScreenMask[8] = 0xC01F; // 1100000000011111 - DriverState.GraphicsCursor.ScreenMask[9] = 0xC01F; // 1100000000011111 - DriverState.GraphicsCursor.ScreenMask[10] = 0xC00F; // 1100000000001111 - DriverState.GraphicsCursor.ScreenMask[11] = 0xC60F; // 1100011000001111 - DriverState.GraphicsCursor.ScreenMask[12] = 0xFF07; // 1111111100000111 - DriverState.GraphicsCursor.ScreenMask[13] = 0xFF07; // 1111111100000111 - DriverState.GraphicsCursor.ScreenMask[14] = 0xFF87; // 1111111110000111 - DriverState.GraphicsCursor.ScreenMask[15] = 0xFFCF; // 1111111111001111 - - DriverState.GraphicsCursor.CursorMask[0] = 0x0000; // 0000000000000000 - DriverState.GraphicsCursor.CursorMask[1] = 0x1C00; // 0001110000000000 - DriverState.GraphicsCursor.CursorMask[2] = 0x1F00; // 0001111100000000 - DriverState.GraphicsCursor.CursorMask[3] = 0x1F80; // 0001111110000000 - DriverState.GraphicsCursor.CursorMask[4] = 0x1FE0; // 0001111111100000 - DriverState.GraphicsCursor.CursorMask[5] = 0x1FF0; // 0001111111110000 - DriverState.GraphicsCursor.CursorMask[6] = 0x1FF8; // 0001111111111000 - DriverState.GraphicsCursor.CursorMask[7] = 0x1FE0; // 0001111111100000 - DriverState.GraphicsCursor.CursorMask[8] = 0x1FC0; // 0001111111000000 - DriverState.GraphicsCursor.CursorMask[9] = 0x1FC0; // 0001111111000000 - DriverState.GraphicsCursor.CursorMask[10] = 0x19E0; // 0001100111100000 - DriverState.GraphicsCursor.CursorMask[11] = 0x00E0; // 0000000011100000 - DriverState.GraphicsCursor.CursorMask[12] = 0x0070; // 0000000001110000 - DriverState.GraphicsCursor.CursorMask[13] = 0x0070; // 0000000001110000 - DriverState.GraphicsCursor.CursorMask[14] = 0x0030; // 0000000000110000 - DriverState.GraphicsCursor.CursorMask[15] = 0x0000; // 0000000000000000 - - /* Initialize the counters */ - DriverState.HorizCount = DriverState.VertCount = 0; - - for (i = 0; i < NUM_MOUSE_BUTTONS; i++) - { - DriverState.PressCount[i] = DriverState.ReleaseCount[i] = 0; - } - - /* Initialize the resolution */ - DriverState.MickeysPerCellHoriz = 8; - DriverState.MickeysPerCellVert = 16; - - /* Return mouse information */ - setAX(0xFFFF); // Hardware & driver installed - setBX(NUM_MOUSE_BUTTONS); - - break; - } - - /* Show Mouse Cursor */ - case 0x01: - { - DriverState.ShowCount++; - if (DriverState.ShowCount > 0) PaintMouseCursor(); - - break; - } - - /* Hide Mouse Cursor */ - case 0x02: - { - DriverState.ShowCount--; - if (DriverState.ShowCount <= 0) EraseMouseCursor(); - - break; - } - - /* Return Position And Button Status */ - case 0x03: - { - setBX(DriverState.ButtonState); - setCX(DriverState.Position.X); - setDX(DriverState.Position.Y); - break; - } - - /* Position Mouse Cursor */ - case 0x04: - { - POINT Point; - - Point.x = getCX(); - Point.y = getDX(); - - ClientToScreen(GetConsoleWindow(), &Point); - SetCursorPos(Point.x, Point.y); - - break; - } - - /* Return Button Press Data */ - case 0x05: - { - WORD Button = getBX(); - - setAX(DriverState.ButtonState); - setBX(DriverState.PressCount[Button]); - setCX(DriverState.LastPress[Button].X); - setDX(DriverState.LastPress[Button].Y); - - /* Reset the counter */ - DriverState.PressCount[Button] = 0; - - break; - } - - /* Return Button Release Data */ - case 0x06: - { - WORD Button = getBX(); - - setAX(DriverState.ButtonState); - setBX(DriverState.ReleaseCount[Button]); - setCX(DriverState.LastRelease[Button].X); - setDX(DriverState.LastRelease[Button].Y); - - /* Reset the counter */ - DriverState.ReleaseCount[Button] = 0; - - break; - - } - - /* Define Graphics Cursor */ - case 0x09: - { - PWORD MaskBitmap = (PWORD)SEG_OFF_TO_PTR(getES(), getDX()); - - DriverState.GraphicsCursor.HotSpot.X = getBX(); - DriverState.GraphicsCursor.HotSpot.Y = getCX(); - - RtlMoveMemory(DriverState.GraphicsCursor.ScreenMask, - MaskBitmap, - sizeof(DriverState.GraphicsCursor.ScreenMask)); - - RtlMoveMemory(DriverState.GraphicsCursor.CursorMask, - &MaskBitmap[16], - sizeof(DriverState.GraphicsCursor.CursorMask)); - - break; - } - - /* Define Text Cursor */ - case 0x0A: - { - USHORT BX = getBX(); - - if (BX == 0x0000) - { - /* Define software cursor */ - DriverState.TextCursor.ScreenMask = getCX(); - DriverState.TextCursor.CursorMask = getDX(); - } - else if (BX == 0x0001) - { - /* Define hardware cursor */ - DPRINT1("Defining hardware cursor is unimplemented\n"); - UNIMPLEMENTED; - // CX == start scan line - // DX == end scan line - } - else - { - DPRINT1("Invalid BX value 0x%04x\n", BX); - } - - break; - } - - /* Read Motion Counters */ - case 0x0B: - { - setCX(DriverState.HorizCount); - setDX(DriverState.VertCount); - - /* Reset the counters */ - DriverState.HorizCount = DriverState.VertCount = 0; - - break; - } - - /* Define Interrupt Subroutine Parameters, compatible MS MOUSE v1.0+ */ - case 0x0C: - { - DriverState.Handler0.CallMask = getCX(); - DriverState.Handler0.Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback - DPRINT1("Define callback 0x%04x, 0x%08x\n", - DriverState.Handler0.CallMask, DriverState.Handler0.Callback); - break; - } - - /* Define Mickey/Pixel Ratio */ - case 0x0F: - { - DriverState.MickeysPerCellHoriz = getCX(); - DriverState.MickeysPerCellVert = getDX(); - break; - } - - /* Exchange Interrupt Subroutines, compatible MS MOUSE v3.0+ (see function 0x0C) */ - case 0x14: - { - USHORT OldCallMask = DriverState.Handler0.CallMask; - ULONG OldCallback = DriverState.Handler0.Callback; - - DriverState.Handler0.CallMask = getCX(); - DriverState.Handler0.Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback - - /* Return old callmask in CX and callback vector in ES:DX */ - setCX(OldCallMask); - setES(HIWORD(OldCallback)); - setDX(LOWORD(OldCallback)); - - break; - } - - /* Return Driver Storage Requirements */ - case 0x15: - { - setBX(sizeof(MOUSE_DRIVER_STATE)); - break; - } - - /* Save Driver State */ - case 0x16: - { - *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())) = DriverState; - break; - } - - /* Restore Driver State */ - case 0x17: - { - DriverState = *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())); - break; - } - - /* Set Alternate Mouse User Handler, compatible MS MOUSE v6.0+ */ - case 0x18: - { - /* - * Up to three handlers can be defined by separate calls to this - * function, each with a different combination of shift states in - * the call mask; calling this function again with a call mask of - * 0000h undefines the specified handler (official documentation); - * specifying the same call mask and an address of 0000h:0000h - * undefines the handler (real life). - * See Ralf Brown: http://www.ctyme.com/intr/rb-5981.htm - * for more information. - */ - - USHORT i; - USHORT CallMask = getCX(); - ULONG Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback - BOOLEAN Success = FALSE; - - DPRINT1("Define v6.0+ callback 0x%04x, 0x%08x\n", - CallMask, Callback); - - if (CallMask == 0x0000) - { - /* - * Find the handler entry corresponding to the given - * callback and undefine it. - */ - for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) - { - if (DriverState.Handlers[i].Callback == Callback) - { - /* Found it, undefine the handler */ - DriverState.Handlers[i].CallMask = 0x0000; - DriverState.Handlers[i].Callback = (ULONG)NULL; - Success = TRUE; - break; - } - } - } - else if (Callback == (ULONG)NULL) - { - /* - * Find the handler entry corresponding to the given - * callmask and undefine it. - */ - for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) - { - if (DriverState.Handlers[i].CallMask == CallMask) - { - /* Found it, undefine the handler */ - DriverState.Handlers[i].CallMask = 0x0000; - DriverState.Handlers[i].Callback = (ULONG)NULL; - Success = TRUE; - break; - } - } - } - else - { - /* - * Try to find a handler entry corresponding to the given - * callmask to redefine it, otherwise find an empty handler - * entry and set the new handler in there. - */ - - USHORT EmptyHandler = 0xFFFF; // Invalid handler - - for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) - { - /* Find the first empty handler */ - if (EmptyHandler == 0xFFFF && - DriverState.Handlers[i].CallMask == 0x0000 && - DriverState.Handlers[i].Callback == (ULONG)NULL) - { - EmptyHandler = i; - } - - if (DriverState.Handlers[i].CallMask == CallMask) - { - /* Found it, redefine the handler */ - DriverState.Handlers[i].CallMask = CallMask; - DriverState.Handlers[i].Callback = Callback; - Success = TRUE; - break; - } - } - - /* - * If we haven't found anything and we found - * an empty handler, set it. - */ - if (!Success && EmptyHandler != 0xFFFF - /* && EmptyHandler < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]) */) - { - DriverState.Handlers[EmptyHandler].CallMask = CallMask; - DriverState.Handlers[EmptyHandler].Callback = Callback; - Success = TRUE; - } - } - - /* If we failed, set error code */ - if (!Success) setAX(0xFFFF); - - break; - } - - /* Return User Alternate Interrupt Vector, compatible MS MOUSE v6.0+ */ - case 0x19: - { - USHORT i; - USHORT CallMask = getCX(); - ULONG Callback; - BOOLEAN Success = FALSE; - - /* - * Find the handler entry corresponding to the given callmask. - */ - for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) - { - if (DriverState.Handlers[i].CallMask == CallMask) - { - /* Found it */ - Callback = DriverState.Handlers[i].Callback; - Success = TRUE; - break; - } - } - - if (Success) - { - /* Return the callback vector in BX:DX */ - setBX(HIWORD(Callback)); - setDX(LOWORD(Callback)); - } - else - { - /* We failed, set error code */ - setCX(0x0000); - } - - break; - } - - /* Disable Mouse Driver */ - case 0x1F: - { - setES(0x0000); - setBX(0x0000); - - DriverEnabled = FALSE; - break; - } - - /* Enable Mouse Driver */ - case 0x20: - { - DriverEnabled = TRUE; - break; - } - - default: - { - DPRINT1("BIOS Function INT 33h, AX = 0x%04X NOT IMPLEMENTED\n", getAX()); - } - } + PicIRQComplete(Stack); }
/* PUBLIC FUNCTIONS ***********************************************************/
-VOID MouseBiosUpdatePosition(PCOORD NewPosition) -{ - SHORT DeltaX = NewPosition->X - DriverState.Position.X; - SHORT DeltaY = NewPosition->Y - DriverState.Position.Y; - - if (!DriverEnabled) return; - - DriverState.HorizCount += (DeltaX * (SHORT)DriverState.MickeysPerCellHoriz) / 8; - DriverState.VertCount += (DeltaY * (SHORT)DriverState.MickeysPerCellVert ) / 8; - - if (DriverState.ShowCount > 0) - { - EraseMouseCursor(); - DriverState.Position = *NewPosition; - PaintMouseCursor(); - } - - /* Call the mouse handlers */ - CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format -} - -VOID MouseBiosUpdateButtons(WORD ButtonState) -{ - USHORT i; - USHORT CallMask = 0x0000; // We use MS MOUSE v1.0+ format - - if (!DriverEnabled) return; - - for (i = 0; i < NUM_MOUSE_BUTTONS; i++) - { - BOOLEAN OldState = (DriverState.ButtonState >> i) & 1; - BOOLEAN NewState = (ButtonState >> i) & 1; - - if (NewState > OldState) - { - /* Mouse press */ - DriverState.PressCount[i]++; - DriverState.LastPress[i] = DriverState.Position; - - CallMask |= (1 << (2 * i + 1)); - } - else if (NewState < OldState) - { - /* Mouse release */ - DriverState.ReleaseCount[i]++; - DriverState.LastRelease[i] = DriverState.Position; - - CallMask |= (1 << (2 * i + 2)); - } - } - - DriverState.ButtonState = ButtonState; - - /* Call the mouse handlers */ - CallMouseUserHandlers(CallMask); -} - BOOLEAN MouseBios32Initialize(VOID) { - /* Clear the state */ - ZeroMemory(&DriverState, sizeof(DriverState)); - - /* Initialize the interrupt handler */ - RegisterBiosInt32(BIOS_MOUSE_INTERRUPT, BiosMouseService); + /* Set up the HW vector interrupts */ + EnableHwIRQ(12, BiosMouseIrq);
return TRUE; }
VOID MouseBios32Cleanup(VOID) { - if (DriverState.ShowCount > 0) EraseMouseCursor(); }
Modified: trunk/reactos/subsystems/ntvdm/clock.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/clock.c?re... ============================================================================== --- trunk/reactos/subsystems/ntvdm/clock.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/clock.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -37,7 +37,8 @@
/* Processor speed */ #define STEPS_PER_CYCLE 256 -#define KBD_INT_CYCLES 16 +#define IRQ1_CYCLES 16 +#define IRQ12_CYCLES 16
/* VARIABLES ******************************************************************/
@@ -48,7 +49,9 @@ DWORD StartTickCount, CurrentTickCount; DWORD LastClockUpdate; DWORD LastVerticalRefresh; -INT KeyboardIntCounter = 0; + +UINT Irq1Counter = 0; +UINT Irq12Counter = 0;
#ifdef IPS_DISPLAY DWORD LastCyclePrintout; @@ -118,10 +121,16 @@ LastVerticalRefresh = CurrentTickCount; }
- if (++KeyboardIntCounter == KBD_INT_CYCLES) + if (++Irq1Counter == IRQ1_CYCLES) { - GenerateKeyboardInterrupts(); - KeyboardIntCounter = 0; + GenerateIrq1(); + Irq1Counter = 0; + } + + if (++Irq12Counter == IRQ12_CYCLES) + { + GenerateIrq12(); + Irq12Counter = 0; }
/* Horizontal retrace occurs as fast as possible */
Modified: trunk/reactos/subsystems/ntvdm/dos/dem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/dem.c?... ============================================================================== --- trunk/reactos/subsystems/ntvdm/dos/dem.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/dem.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -21,6 +21,7 @@ #include "bop.h"
#include "bios/bios.h" +#include "mouse32.h"
/* Extra PSDK/NDK Headers */ #include <ndk/obtypes.h> @@ -234,6 +235,7 @@ BOOLEAN Result;
Result = DosBIOSInitialize(); + DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS // Result &= DosKRNLInitialize();
return Result;
Copied: trunk/reactos/subsystems/ntvdm/dos/mouse32.c (from r64138, trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c) URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/mouse3... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/mouse32.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -1,8 +1,8 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: moubios32.c - * PURPOSE: VDM Mouse 32-bit BIOS + * FILE: mouse32.c + * PURPOSE: VDM 32-bit compatible MOUSE.COM driver * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> */
@@ -13,11 +13,11 @@ #include "emulator.h" #include "callback.h"
-#include "moubios32.h" -#include "bios32p.h" +#include "mouse32.h" +#include "bios/bios.h"
#include "io.h" -#include "hardware/mouse.h" +#include "dos32krnl/dos.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -80,7 +80,9 @@
static VOID CallMouseUserHandlers(USHORT CallMask) { +#if 0 USHORT i; + USHORT AX, BX, CX, DX, SI, DI;
/* Call handler 0 */ if ((DriverState.Handler0.CallMask & CallMask) != 0 && @@ -91,6 +93,14 @@ * NOTE: In text modes, the row and column will be reported * as a multiple of the cell size, typically 8x8 pixels. */ + + AX = getAX(); + BX = getBX(); + CX = getCX(); + DX = getDX(); + SI = getSI(); + DI = getDI(); + setAX(CallMask); setBX(DriverState.ButtonState); setCX(DriverState.Position.X); @@ -102,7 +112,14 @@ DriverState.Handler0.Callback, CallMask);
/* Call the callback */ - RunCallback16(&BiosContext, DriverState.Handler0.Callback); + RunCallback16(&DosContext, DriverState.Handler0.Callback); + + setAX(AX); + setBX(BX); + setCX(CX); + setDX(DX); + setSI(SI); + setDI(DI); }
for (i = 0; i < sizeof(DriverState.Handlers)/sizeof(DriverState.Handlers[0]); ++i) @@ -116,6 +133,14 @@ * NOTE: In text modes, the row and column will be reported * as a multiple of the cell size, typically 8x8 pixels. */ + + AX = getAX(); + BX = getBX(); + CX = getCX(); + DX = getDX(); + SI = getSI(); + DI = getDI(); + setAX(CallMask); setBX(DriverState.ButtonState); setCX(DriverState.Position.X); @@ -127,9 +152,17 @@ i, DriverState.Handlers[i].Callback, CallMask);
/* Call the callback */ - RunCallback16(&BiosContext, DriverState.Handlers[i].Callback); - } - } + RunCallback16(&DosContext, DriverState.Handlers[i].Callback); + + setAX(AX); + setBX(BX); + setCX(CX); + setDX(DX); + setSI(SI); + setDI(DI); + } + } +#endif }
static VOID WINAPI BiosMouseService(LPWORD Stack) @@ -621,18 +654,18 @@ CallMouseUserHandlers(CallMask); }
-BOOLEAN MouseBios32Initialize(VOID) +BOOLEAN DosMouseInitialize(VOID) { /* Clear the state */ ZeroMemory(&DriverState, sizeof(DriverState));
/* Initialize the interrupt handler */ - RegisterBiosInt32(BIOS_MOUSE_INTERRUPT, BiosMouseService); + RegisterDosInt32(BIOS_MOUSE_INTERRUPT, BiosMouseService);
return TRUE; }
-VOID MouseBios32Cleanup(VOID) +VOID DosMouseCleanup(VOID) { if (DriverState.ShowCount > 0) EraseMouseCursor(); }
Copied: trunk/reactos/subsystems/ntvdm/dos/mouse32.h (from r64138, trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h) URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/mouse3... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/bios32/moubios32.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/mouse32.h [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -1,13 +1,13 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: moubios32.h - * PURPOSE: VDM Mouse 32-bit BIOS + * FILE: mouse32.h + * PURPOSE: VDM 32-bit compatible MOUSE.COM driver * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> */
-#ifndef _MOUBIOS32_H_ -#define _MOUBIOS32_H_ +#ifndef _MOUSE32_H_ +#define _MOUSE32_H_
/* INCLUDES *******************************************************************/
@@ -74,9 +74,10 @@
VOID MouseBiosUpdatePosition(PCOORD NewPosition); VOID MouseBiosUpdateButtons(WORD ButtonStatus); -BOOLEAN MouseBios32Initialize(VOID); -VOID MouseBios32Cleanup(VOID);
-#endif // _MOUBIOS32_H_ +BOOLEAN DosMouseInitialize(VOID); +VOID DosMouseCleanup(VOID); + +#endif // _MOUSE32_H_
/* EOF */
Modified: trunk/reactos/subsystems/ntvdm/emulator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/emulator.c... ============================================================================== --- trunk/reactos/subsystems/ntvdm/emulator.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/emulator.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -16,6 +16,8 @@ #include "clock.h" #include "bios/rom.h" #include "hardware/cmos.h" +#include "hardware/keyboard.h" +#include "hardware/mouse.h" #include "hardware/pic.h" #include "hardware/ps2.h" #include "hardware/speaker.h" @@ -335,6 +337,95 @@ // SpeakerChange(); }
+ +static DWORD +WINAPI +PumpConsoleInput(LPVOID Parameter) +{ + HANDLE ConsoleInput = (HANDLE)Parameter; + INPUT_RECORD InputRecord; + DWORD Count; + + while (VdmRunning) + { + /* Make sure the task event is signaled */ + WaitForSingleObject(VdmTaskEvent, INFINITE); + + /* Wait for an input record */ + if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count)) + { + DWORD LastError = GetLastError(); + DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError); + return LastError; + } + + ASSERT(Count != 0); + + /* Check the event type */ + switch (InputRecord.EventType) + { + /* + * Hardware events + */ + case KEY_EVENT: + KeyboardEventHandler(&InputRecord.Event.KeyEvent); + break; + + case MOUSE_EVENT: + MouseEventHandler(&InputRecord.Event.MouseEvent); + break; + + case WINDOW_BUFFER_SIZE_EVENT: + ScreenEventHandler(&InputRecord.Event.WindowBufferSizeEvent); + break; + + /* + * Interface events + */ + case MENU_EVENT: + MenuEventHandler(&InputRecord.Event.MenuEvent); + break; + + case FOCUS_EVENT: + FocusEventHandler(&InputRecord.Event.FocusEvent); + break; + + default: + break; + } + } + + return 0; +} + +static VOID EnableExtraHardware(HANDLE ConsoleInput) +{ + DWORD ConInMode; + + if (GetConsoleMode(ConsoleInput, &ConInMode)) + { +#if 0 + // GetNumberOfConsoleMouseButtons(); + // GetSystemMetrics(SM_CMOUSEBUTTONS); + // GetSystemMetrics(SM_MOUSEPRESENT); + if (MousePresent) + { +#endif + /* Support mouse input events if there is a mouse on the system */ + ConInMode |= ENABLE_MOUSE_INPUT; +#if 0 + } + else + { + /* Do not support mouse input events if there is no mouse on the system */ + ConInMode &= ~ENABLE_MOUSE_INPUT; + } +#endif + + SetConsoleMode(ConsoleInput, ConInMode); + } +} + /* PUBLIC FUNCTIONS ***********************************************************/
VOID DumpMemory(VOID) @@ -420,8 +511,6 @@
DPRINT1("Memory dump done\n"); } - -DWORD WINAPI PumpConsoleInput(LPVOID Parameter);
BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) { @@ -476,8 +565,14 @@ SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */); // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
- /* Initialize the PS2 port */ - PS2Initialize(ConsoleInput); + /**/EnableExtraHardware(ConsoleInput);/**/ + + /* Initialize the PS/2 port */ + PS2Initialize(); + + /* Initialize the keyboard and mouse and connect them to their PS/2 ports */ + KeyboardInit(0); + MouseInit(1);
/**************** ATTACH INPUT WITH CONSOLE *****************/ /* Start the input thread */
Added: trunk/reactos/subsystems/ntvdm/hardware/keyboard.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/k... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/keyboard.c (added) +++ trunk/reactos/subsystems/ntvdm/hardware/keyboard.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -0,0 +1,46 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: keyboard.c + * PURPOSE: Keyboard emulation + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "keyboard.h" +#include "ps2.h" + +static BYTE PS2Port = 0; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID KeyboardEventHandler(PKEY_EVENT_RECORD KeyEvent) +{ + WORD i; + BYTE ScanCode = (BYTE)KeyEvent->wVirtualScanCode; + + /* If this is a key release, set the highest bit in the scan code */ + if (!KeyEvent->bKeyDown) ScanCode |= 0x80; + + /* Push the scan code into the PS/2 queue */ + for (i = 0; i < KeyEvent->wRepeatCount; i++) + { + PS2QueuePush(PS2Port, ScanCode); + } + + // PicInterruptRequest(1); +} + +VOID KeyboardCommand(BYTE Command) +{ + UNIMPLEMENTED; +} + +BOOLEAN KeyboardInit(BYTE PS2Connector) +{ + PS2Port = PS2Connector; + return TRUE; +}
Propchange: trunk/reactos/subsystems/ntvdm/hardware/keyboard.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/subsystems/ntvdm/hardware/keyboard.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/k... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/keyboard.h (added) +++ trunk/reactos/subsystems/ntvdm/hardware/keyboard.h [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -0,0 +1,28 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: keyboard.h + * PURPOSE: Keyboard emulation + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +#ifndef _KEYBOARD_H_ +#define _KEYBOARD_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +/* Command responses */ +#define KEYBOARD_ACK 0xFA +#define KEYBOARD_RESEND 0xFE + +/* FUNCTIONS ******************************************************************/ + +VOID KeyboardEventHandler(PKEY_EVENT_RECORD KeyEvent); +VOID KeyboardCommand(BYTE Command); +BOOLEAN KeyboardInit(BYTE PS2Connector); + +#endif // _KEYBOARD_H_
Propchange: trunk/reactos/subsystems/ntvdm/hardware/keyboard.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/subsystems/ntvdm/hardware/mouse.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/m... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/mouse.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/mouse.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -12,6 +12,9 @@
#include "mouse.h" #include "ps2.h" + +// HACK: For the PS/2 bypass and MOUSE.COM driver direct call +#include "dos/mouse32.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -28,6 +31,8 @@ static SHORT VertCounter; static CHAR ScrollCounter;
+static BYTE PS2Port = 1; + /* PRIVATE FUNCTIONS **********************************************************/
static VOID MouseResetConfig(VOID) @@ -56,8 +61,8 @@ MouseId = 0;
/* Send the Basic Assurance Test success code and the device ID */ - KeyboardQueuePush(MOUSE_BAT_SUCCESS); - KeyboardQueuePush(MouseId); + PS2QueuePush(PS2Port, MOUSE_BAT_SUCCESS); + PS2QueuePush(PS2Port, MouseId); }
#if 0 @@ -116,9 +121,7 @@ } #endif
-/* PUBLIC FUNCTIONS ***********************************************************/ - -VOID MouseUpdatePosition(PCOORD NewPosition) +/*static*/ VOID MouseUpdatePosition(PCOORD NewPosition) { /* Update the counters */ HorzCounter += ((NewPosition->X - Position.X) * WidthMm * Resolution) / WidthPixels; @@ -128,9 +131,23 @@ Position = *NewPosition; }
-VOID MouseUpdateButtons(ULONG NewButtonState) +/*static*/ VOID MouseUpdateButtons(ULONG NewButtonState) { ButtonState = NewButtonState; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent) +{ + // FIXME: Sync our private data + + // HACK: Bypass PS/2 and instead, notify the MOUSE.COM driver directly + MouseBiosUpdatePosition(&MouseEvent->dwMousePosition); + MouseBiosUpdateButtons(LOWORD(MouseEvent->dwButtonState)); + + // PS2QueuePush(PS2Port, Data); + // PicInterruptRequest(12); }
VOID MouseScroll(LONG Direction) @@ -151,7 +168,7 @@ case 0xE6: { Scaling = FALSE; - KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
@@ -159,7 +176,7 @@ case 0xE7: { Scaling = TRUE; - KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
@@ -185,7 +202,7 @@ MouseResetCounters(); Mode = MOUSE_STREAMING_MODE;
- KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
@@ -205,9 +222,9 @@ /* Restore the previous mode */ MouseResetCounters(); Mode = PreviousMode; - KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); } - else KeyboardQueuePush(MOUSE_ERROR); + else PS2QueuePush(PS2Port, MOUSE_ERROR);
break; } @@ -224,7 +241,7 @@ MouseResetCounters(); Mode = MOUSE_WRAP_MODE;
- KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
@@ -234,15 +251,15 @@ MouseResetCounters(); Mode = MOUSE_REMOTE_MODE;
- KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
/* Get Mouse ID */ case 0xF2: { - KeyboardQueuePush(MOUSE_ACK); - KeyboardQueuePush(MouseId); + PS2QueuePush(PS2Port, MOUSE_ACK); + PS2QueuePush(PS2Port, MouseId); break; }
@@ -258,7 +275,7 @@ case 0xF4: { Reporting = TRUE; - KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
@@ -266,7 +283,7 @@ case 0xF5: { Reporting = FALSE; - KeyboardQueuePush(MOUSE_ACK); + PS2QueuePush(PS2Port, MOUSE_ACK); break; }
@@ -297,12 +314,12 @@ /* Unknown command */ default: { - KeyboardQueuePush(MOUSE_ERROR); - } - } -} - -BOOLEAN MouseInit(VOID) + PS2QueuePush(PS2Port, MOUSE_ERROR); + } + } +} + +BOOLEAN MouseInit(BYTE PS2Connector) { HWND hWnd; HDC hDC; @@ -324,6 +341,8 @@ /* Release the device context */ ReleaseDC(hWnd, hDC);
+ PS2Port = PS2Connector; + MouseReset(); return TRUE; }
Modified: trunk/reactos/subsystems/ntvdm/hardware/mouse.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/m... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/mouse.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/mouse.h [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -68,11 +68,12 @@
/* FUNCTIONS ******************************************************************/
-VOID MouseUpdatePosition(PCOORD NewPosition); -VOID MouseUpdateButtons(ULONG NewButtonState); +VOID MouseEventHandler(PMOUSE_EVENT_RECORD MouseEvent); + VOID MouseScroll(LONG Direction); COORD MouseGetPosition(VOID); + VOID MouseCommand(BYTE Command); -BOOLEAN MouseInit(VOID); +BOOLEAN MouseInit(BYTE PS2Connector);
#endif // _MOUSE_H_
Modified: trunk/reactos/subsystems/ntvdm/hardware/ps2.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/p... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/ps2.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/ps2.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -4,6 +4,7 @@ * FILE: ps2.c * PURPOSE: PS/2 controller emulation * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */
/* INCLUDES *******************************************************************/ @@ -14,19 +15,39 @@ #include "io.h" #include "ps2.h" #include "pic.h" + +#include "keyboard.h" #include "mouse.h" -#include "../bios/bios32/moubios32.h"
/* PRIVATE VARIABLES **********************************************************/
-static BYTE KeyboardQueue[KEYBOARD_BUFFER_SIZE]; -static BOOLEAN KeyboardQueueEmpty = TRUE; -static UINT KeyboardQueueStart = 0; -static UINT KeyboardQueueEnd = 0; -static BYTE KeyboardData = 0, KeyboardResponse = 0; -static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE; -static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG; -static HANDLE QueueMutex = NULL; +#define BUFFER_SIZE 32 + +typedef struct _PS2_PORT +{ + BOOLEAN IsEnabled; + + BOOLEAN QueueEmpty; + BYTE Queue[BUFFER_SIZE]; + UINT QueueStart; + UINT QueueEnd; + HANDLE QueueMutex; +} PS2_PORT, *PPS2_PORT; + +/* + * Port 1: Keyboard + * Port 2: Mouse + */ +#define PS2_PORTS 2 +static PS2_PORT Ports[PS2_PORTS]; + +#define PS2_DEFAULT_CONFIG 0x47 +static BYTE ControllerConfig = PS2_DEFAULT_CONFIG; +static BYTE ControllerCommand = 0x00; + +static BYTE StatusRegister = 0x00; +// static BYTE InputBuffer = 0x00; // PS/2 Input Buffer +static BYTE OutputBuffer = 0x00; // PS/2 Output Buffer
/* PRIVATE FUNCTIONS **********************************************************/
@@ -34,31 +55,28 @@ { if (Port == PS2_CONTROL_PORT) { - 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; + /* Be sure bit 2 is always set */ + StatusRegister |= 1 << 2; + + // FIXME: Should clear bits 6 and 7 because there are + // no timeouts and no parity errors. + + return StatusRegister; } else if (Port == PS2_DATA_PORT) { - /* If there was a response byte from the controller, return it */ - if (KeyboardReadResponse) - { - KeyboardReadResponse = FALSE; - KeyboardData = KeyboardResponse; - } - - return KeyboardData; - } - else return 0; + /* + * If there is something to read (response byte from the + * controller or data from a PS/2 device), read it. + */ + if (StatusRegister & (1 << 0)) // || StatusRegister & (1 << 5) for second PS/2 port + StatusRegister &= ~(1 << 0); // StatusRegister &= ~(1 << 5); + + /* Always return the available byte stored in the output buffer */ + return OutputBuffer; + } + + return 0; }
static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data) @@ -70,8 +88,8 @@ /* Read configuration byte */ case 0x20: { - KeyboardResponse = KeyboardConfig; - KeyboardReadResponse = TRUE; + OutputBuffer = ControllerConfig; + StatusRegister |= (1 << 0); // There is something to read break; }
@@ -79,60 +97,68 @@ case 0x60: /* Write controller output port */ case 0xD1: - /* Write keyboard output buffer */ + /* Write to the first PS/2 port output buffer */ case 0xD2: - /* Write mouse output buffer */ + /* Write to the second PS/2 port output buffer */ case 0xD3: - /* Write mouse input buffer */ + /* Write to the second PS/2 port input buffer */ case 0xD4: { /* These commands require a response */ - KeyboardResponse = Data; - KeyboardWriteResponse = TRUE; - break; - } - - /* Disable mouse */ + ControllerCommand = Data; + StatusRegister |= (1 << 3); // This is a controller command + break; + } + + /* Disable second PS/2 port */ case 0xA7: { - // TODO: Not implemented - break; - } - - /* Enable mouse */ + Ports[1].IsEnabled = FALSE; + break; + } + + /* Enable second PS/2 port */ case 0xA8: { - // TODO: Not implemented - break; - } - - /* Test mouse port */ + Ports[1].IsEnabled = TRUE; + break; + } + + /* Test second PS/2 port */ case 0xA9: { - KeyboardResponse = 0; - KeyboardReadResponse = TRUE; + OutputBuffer = 0x00; // Success code + StatusRegister |= (1 << 0); // There is something to read break; }
/* Test PS/2 controller */ case 0xAA: { - KeyboardResponse = 0x55; - KeyboardReadResponse = TRUE; - break; - } - - /* Disable keyboard */ + OutputBuffer = 0x55; // Success code + StatusRegister |= (1 << 0); // There is something to read + break; + } + + /* Test first PS/2 port */ + case 0xAB: + { + OutputBuffer = 0x00; // Success code + StatusRegister |= (1 << 0); // There is something to read + break; + } + + /* Disable first PS/2 port */ case 0xAD: { - // TODO: Not implemented - break; - } - - /* Enable keyboard */ + Ports[0].IsEnabled = FALSE; + break; + } + + /* Enable first PS/2 port */ case 0xAE: { - // TODO: Not implemented + Ports[0].IsEnabled = TRUE; break; }
@@ -162,17 +188,17 @@ else if (Port == PS2_DATA_PORT) { /* Check if the controller is waiting for a response */ - if (KeyboardWriteResponse) + if (StatusRegister & (1 << 3)) // If we have data for the controller { - KeyboardWriteResponse = FALSE; + StatusRegister &= ~(1 << 3);
/* Check which command it was */ - switch (KeyboardResponse) + switch (ControllerCommand) { /* Write configuration byte */ case 0x60: { - KeyboardConfig = Data; + ControllerConfig = Data; break; }
@@ -191,23 +217,31 @@
break; } - + + /* Push the data byte into the first PS/2 port queue */ case 0xD2: { - /* Push the data byte to the keyboard queue */ - KeyboardQueuePush(Data); - break; - } - + PS2QueuePush(0, Data); + break; + } + + /* Push the data byte into the second PS/2 port queue */ case 0xD3: { - // TODO: Mouse support - break; - } - + PS2QueuePush(1, Data); + break; + } + + /* + * Send a command to the second PS/2 port (by default + * it is a command for the first PS/2 port) + */ case 0xD4: { - MouseCommand(Data); + if (Ports[1].IsEnabled) + // Ports[1].Function + MouseCommand(Data); + break; } } @@ -216,156 +250,148 @@ }
// TODO: Implement PS/2 device commands - } -} - -/* PUBLIC FUNCTIONS ***********************************************************/ - -BOOLEAN KeyboardQueuePush(BYTE ScanCode) + if (Ports[0].IsEnabled) + // Ports[0].Function + KeyboardCommand(Data); + } +} + +static BOOLEAN PS2PortQueueRead(BYTE PS2Port) { BOOLEAN Result = TRUE; - - WaitForSingleObject(QueueMutex, INFINITE); - - /* Check if the keyboard queue is full */ - if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd)) + PPS2_PORT Port; + + if (PS2Port >= PS2_PORTS) return FALSE; + Port = &Ports[PS2Port]; + + if (!Port->IsEnabled) return FALSE; + + /* Make sure the queue is not empty (fast check) */ + if (Port->QueueEmpty) return FALSE; + + WaitForSingleObject(Port->QueueMutex, INFINITE); + + /* + * Recheck whether the queue is not empty (it may + * have changed after having grabbed the mutex). + */ + if (Port->QueueEmpty) { Result = FALSE; goto Done; }
- /* 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; + /* Get the data */ + OutputBuffer = Port->Queue[Port->QueueStart]; + StatusRegister |= (1 << 0); // There is something to read + // Sometimes StatusRegister |= (1 << 5); for the second PS/2 port + + /* Remove the value from the queue */ + Port->QueueStart++; + Port->QueueStart %= BUFFER_SIZE; + + /* Check if the queue is now empty */ + if (Port->QueueStart == Port->QueueEnd) + Port->QueueEmpty = TRUE;
Done: - ReleaseMutex(QueueMutex); + ReleaseMutex(Port->QueueMutex); return Result; }
-BOOLEAN KeyboardQueuePop(BYTE *ScanCode) +/* PUBLIC FUNCTIONS ***********************************************************/ + +// PS2SendToPort +BOOLEAN PS2QueuePush(BYTE PS2Port, BYTE Data) { BOOLEAN Result = TRUE; - - /* Make sure the keyboard queue is not empty (fast check) */ - if (KeyboardQueueEmpty) return FALSE; - - WaitForSingleObject(QueueMutex, INFINITE); - - /* - * Recheck whether keyboard queue is not empty (it - * may have changed after having grabbed the mutex). - */ - if (KeyboardQueueEmpty) + PPS2_PORT Port; + + if (PS2Port >= PS2_PORTS) return FALSE; + Port = &Ports[PS2Port]; + + if (!Port->IsEnabled) return FALSE; + + WaitForSingleObject(Port->QueueMutex, INFINITE); + + /* Check if the queue is full */ + if (!Port->QueueEmpty && (Port->QueueStart == Port->QueueEnd)) { Result = FALSE; goto Done; }
- /* 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; - } + /* Insert the value in the queue */ + Port->Queue[Port->QueueEnd] = Data; + Port->QueueEnd++; + Port->QueueEnd %= BUFFER_SIZE; + + /* Since we inserted a value, it's not empty anymore */ + Port->QueueEmpty = FALSE; + +/* + // Get the data + OutputBuffer = Port->Queue[Port->QueueStart]; + StatusRegister |= (1 << 0); // There is something to read + // FIXME: Sometimes StatusRegister |= (1 << 5); for the second PS/2 port + + if (PS2Port == 0) + PicInterruptRequest(1); + else if (PS2Port == 1) + PicInterruptRequest(12); +*/
Done: - ReleaseMutex(QueueMutex); + ReleaseMutex(Port->QueueMutex); return Result; }
-VOID PS2Dispatch(PINPUT_RECORD InputRecord) -{ - /* Check the event type */ - switch (InputRecord->EventType) - { - case KEY_EVENT: - { - WORD i; - BYTE ScanCode = (BYTE)InputRecord->Event.KeyEvent.wVirtualScanCode; - - /* If this is a key release, set the highest bit in the scan code */ - if (!InputRecord->Event.KeyEvent.bKeyDown) ScanCode |= 0x80; - - /* Push the scan code onto the keyboard queue */ - for (i = 0; i < InputRecord->Event.KeyEvent.wRepeatCount; i++) - { - KeyboardQueuePush(ScanCode); - } - - break; - } - - case MOUSE_EVENT: - { - /* Notify the BIOS driver */ - MouseBiosUpdatePosition(&InputRecord->Event.MouseEvent.dwMousePosition); - MouseBiosUpdateButtons(LOWORD(InputRecord->Event.MouseEvent.dwButtonState)); - - // TODO: PS/2, other stuff - - break; - } - - /* We ignore all the rest */ - default: - break; - } -} - -VOID GenerateKeyboardInterrupts(VOID) -{ - /* Generate an IRQ 1 if there is a key ready in the queue */ - if (KeyboardQueuePop(&KeyboardData)) PicInterruptRequest(1); -} - -BOOLEAN PS2Initialize(HANDLE ConsoleInput) -{ - DWORD ConInMode; - - /* Create the mutex */ - QueueMutex = CreateMutex(NULL, FALSE, NULL); +VOID GenerateIrq1(VOID) +{ + /* Generate an interrupt if interrupts for the first PS/2 port are enabled */ + if (ControllerConfig & 0x01) + { + /* Generate an IRQ 1 if there is data ready in the output queue */ + if (PS2PortQueueRead(0)) PicInterruptRequest(1); + } +} + +VOID GenerateIrq12(VOID) +{ + /* Generate an interrupt if interrupts for the second PS/2 port are enabled */ + if (ControllerConfig & 0x02) + { + /* Generate an IRQ 12 if there is data ready in the output queue */ + if (PS2PortQueueRead(1)) PicInterruptRequest(12); + } +} + +BOOLEAN PS2Initialize(VOID) +{ + /* Initialize the PS/2 ports */ + Ports[0].IsEnabled = TRUE; + Ports[0].QueueEmpty = TRUE; + Ports[0].QueueStart = 0; + Ports[0].QueueEnd = 0; + Ports[0].QueueMutex = CreateMutex(NULL, FALSE, NULL); + + Ports[1].IsEnabled = TRUE; + Ports[1].QueueEmpty = TRUE; + Ports[1].QueueStart = 0; + Ports[1].QueueEnd = 0; + Ports[1].QueueMutex = CreateMutex(NULL, FALSE, NULL);
/* Register the I/O Ports */ RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort); RegisterIoPort(PS2_DATA_PORT , PS2ReadPort, PS2WritePort);
- if (GetConsoleMode(ConsoleInput, &ConInMode)) - { -#if 0 - if (MousePresent) - { -#endif - /* Support mouse input events if there is a mouse on the system */ - ConInMode |= ENABLE_MOUSE_INPUT; -#if 0 - } - else - { - /* Do not support mouse input events if there is no mouse on the system */ - ConInMode &= ~ENABLE_MOUSE_INPUT; - } -#endif - - SetConsoleMode(ConsoleInput, ConInMode); - } - return TRUE; }
VOID PS2Cleanup(VOID) { - CloseHandle(QueueMutex); + CloseHandle(Ports[1].QueueMutex); + CloseHandle(Ports[0].QueueMutex); }
/* EOF */
Modified: trunk/reactos/subsystems/ntvdm/hardware/ps2.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/p... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/ps2.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/ps2.h [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -4,6 +4,7 @@ * FILE: ps2.h * PURPOSE: PS/2 controller emulation * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */
#ifndef _PS2_H_ @@ -15,21 +16,17 @@
/* 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 +#define PS2_DATA_PORT 0x60 +#define PS2_CONTROL_PORT 0x64
/* FUNCTIONS ******************************************************************/
-BOOLEAN KeyboardQueuePush(BYTE ScanCode); -BOOLEAN KeyboardQueuePop(BYTE *ScanCode); -VOID PS2Dispatch(PINPUT_RECORD InputRecord); -VOID GenerateKeyboardInterrupts(VOID); +BOOLEAN PS2QueuePush(BYTE PS2Port, BYTE Data);
-BOOLEAN PS2Initialize(HANDLE ConsoleInput); +VOID GenerateIrq1(VOID); +VOID GenerateIrq12(VOID); + +BOOLEAN PS2Initialize(VOID); VOID PS2Cleanup(VOID);
#endif // _PS2_H_
Modified: trunk/reactos/subsystems/ntvdm/hardware/vga.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/v... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/vga.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/vga.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -1917,6 +1917,11 @@
+VOID ScreenEventHandler(PWINDOW_BUFFER_SIZE_RECORD ScreenEvent) +{ + DPRINT1("Screen events not handled\n"); +} + BOOL VgaAttachToConsole(VOID) { //
Modified: trunk/reactos/subsystems/ntvdm/hardware/vga.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/v... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/vga.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/vga.h [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -250,6 +250,7 @@
/* FUNCTIONS ******************************************************************/
+VOID ScreenEventHandler(PWINDOW_BUFFER_SIZE_RECORD ScreenEvent); BOOL VgaAttachToConsole(VOID); VOID VgaDetachFromConsole(BOOL ChangeMode);
Modified: trunk/reactos/subsystems/ntvdm/ntvdm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/ntvdm.c?re... ============================================================================== --- trunk/reactos/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/ntvdm.c [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -328,69 +328,32 @@ if (ConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput); }
-DWORD -WINAPI -PumpConsoleInput(LPVOID Parameter) -{ - HANDLE ConsoleInput = (HANDLE)Parameter; - INPUT_RECORD InputRecord; - DWORD Count; - - while (VdmRunning) - { - /* Make sure the task event is signaled */ - WaitForSingleObject(VdmTaskEvent, INFINITE); - - /* Wait for an input record */ - if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count)) - { - DWORD LastError = GetLastError(); - DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError); - return LastError; - } - - ASSERT(Count != 0); - - /* Check the event type */ - switch (InputRecord.EventType) - { - case KEY_EVENT: - case MOUSE_EVENT: - /* Send it to the PS/2 controller */ - PS2Dispatch(&InputRecord); - break; - - case MENU_EVENT: - { - switch (InputRecord.Event.MenuEvent.dwCommandId) - { - case ID_SHOWHIDE_MOUSE: - ShowHideMousePointer(ConsoleOutput, ShowPointer); - ShowPointer = !ShowPointer; - break; - - case ID_VDM_DUMPMEM: - DumpMemory(); - break; - - case ID_VDM_QUIT: - /* Stop the VDM */ - EmulatorTerminate(); - break; - - default: - break; - } - - break; - } - - default: - break; - } - } - - return 0; +VOID MenuEventHandler(PMENU_EVENT_RECORD MenuEvent) +{ + switch (MenuEvent->dwCommandId) + { + case ID_SHOWHIDE_MOUSE: + ShowHideMousePointer(ConsoleOutput, ShowPointer); + ShowPointer = !ShowPointer; + break; + + case ID_VDM_DUMPMEM: + DumpMemory(); + break; + + case ID_VDM_QUIT: + /* Stop the VDM */ + EmulatorTerminate(); + break; + + default: + break; + } +} + +VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent) +{ + DPRINT1("Focus events not handled\n"); }
#ifndef STANDALONE
Modified: trunk/reactos/subsystems/ntvdm/ntvdm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/ntvdm.h?re... ============================================================================== --- trunk/reactos/subsystems/ntvdm/ntvdm.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/ntvdm.h [iso-8859-1] Tue Sep 16 00:51:15 2014 @@ -46,6 +46,9 @@
extern HANDLE VdmTaskEvent;
+/* + * Interface functions + */ VOID DisplayMessage(LPCWSTR Format, ...);
/*static*/ VOID @@ -53,6 +56,9 @@ /*static*/ VOID DestroyVdmMenu(VOID);
+VOID MenuEventHandler(PMENU_EVENT_RECORD MenuEvent); +VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent); + #endif // _NTVDM_H_
/* EOF */