PS2:
- By default all the PS/2 ports are disabled. They become enabled by the BIOS at the POST step.
- Similarly it is the BIOS POST that sets up the PS/2 controller configuration byte.
- Synchronize the value of bit 2 "System flag" and bit 4 "Keyboard enable flag" in the status register, according to what is set in the controller configuration register. What is the "keyboard enable flag" ? See http://www.os2museum.com/wp/the-dos-4-0-shell-mouse-mystery/ for more details...

HW MOUSE:
- Resetting the mouse sends also an ACKnowledge byte too...

BIOS32:
- Fix the reported number of bytes in the BIOS configuration table.
- Enable the PS/2 ports in the POST.
- Implement the "Pointing Device BIOS Interface" INT 15h, AH=C2h, AL=00h...09h based on VBox OSE & SeaBIOS; we should make our PS/2 mouse driver use it.

The real call to INT 15h, AH=C2h function is still disabled because our mouse driver doesn't react well with it, when we run some applications like MS Diagnostics.

PS2 MOUSE DRV:
- Update copyright notice;
- Remove 2 useless functions;
- I've put in comments in the code the places where calls to the BIOS ps/2 mouse interface are needed.

svn path=/trunk/; revision=68613
This commit is contained in:
Hermès Bélusca-Maïto 2015-08-07 16:10:18 +00:00
parent 33d53d44da
commit f6fbd83783
7 changed files with 721 additions and 158 deletions

View file

@ -142,7 +142,7 @@ C_ASSERT(sizeof(USER_DATA_AREA) == 0x34);
*/
typedef struct _BIOS_CONFIG_TABLE
{
WORD Length; // 0x00
WORD Length; // 0x00 - Number of bytes following
BYTE Model; // 0x02
BYTE SubModel; // 0x03
BYTE Revision; // 0x04

View file

@ -4,6 +4,7 @@
* FILE: bios32.c
* PURPOSE: VDM 32-bit BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
@ -109,7 +110,7 @@ $fffe ; System Model ID
static const BIOS_CONFIG_TABLE BiosConfigTable =
{
sizeof(BIOS_CONFIG_TABLE), // Length
sizeof(BIOS_CONFIG_TABLE) - sizeof(((BIOS_CONFIG_TABLE*)0)->Length), // Length: Number of bytes following
BIOS_MODEL, // BIOS Model
BIOS_SUBMODEL, // BIOS Sub-Model
@ -325,7 +326,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
{
setAX(0x80);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
@ -394,8 +394,11 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
/* Pointing Device BIOS Interface (PS) */
case 0xC2:
{
BiosMousePs2Interface(Stack);
UNIMPLEMENTED; // Remove it when BiosMousePs2Interface is implemented!
// FIXME: Reenable this call when we understand why
// our included mouse driver doesn't correctly reeanble
// mouse reporting!
// BiosMousePs2Interface(Stack);
// break;
goto Default;
}
@ -429,7 +432,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
ULONG Above1M = (min(MAX_ADDRESS, 0x01000000) - 0x00100000) >> 10;
/* The amount of memory above 16M, in 64K blocks */
ULONG Above16M = (MAX_ADDRESS > 0x01000000) ? (MAX_ADDRESS - 0x01000000) >> 16: 0;
ULONG Above16M = (MAX_ADDRESS > 0x01000000) ? ((MAX_ADDRESS - 0x01000000) >> 16) : 0;
setAX(Above1M);
setBX(Above16M);
@ -476,8 +479,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
else
{
DPRINT1("BIOS Function INT 15h, AH = 0xE8 - unexpected AL = %02X, EDX = %08X\n",
getAL(),
getEDX());
getAL(), getEDX());
}
break;
@ -773,6 +775,16 @@ static VOID BiosHwSetup(VOID)
IOWriteB(PIT_DATA_PORT(2), 0x97);
IOWriteB(PIT_DATA_PORT(2), 0x0A);
/* Initialize PS/2 keyboard port */
// Enable the port
IOWriteB(PS2_CONTROL_PORT, 0xAE);
IOWriteB(PS2_CONTROL_PORT, 0x60);
// Port interrupts and clock enabled,
// enable keyboard scancode translation.
// POST passed, force keyboard unlocking.
IOWriteB(PS2_DATA_PORT , 0x4D);
EnableHwIRQ(0, BiosTimerIrq);
}
@ -785,7 +797,10 @@ static VOID InitializeBiosInt32(VOID)
/* Register the default BIOS interrupt vectors */
/* Zero out all of the IVT (0x00 -- 0xFF) */
/*
* Zero out all of the IVT (0x00 -- 0xFF). Some applications
* indeed expect to have free vectors at the end of the IVT.
*/
RtlZeroMemory(BaseAddress, 0x0100 * sizeof(ULONG));
#if defined(ADVANCED_DEBUGGING) && (ADVANCED_DEBUGGING_LEVEL >= 3)

View file

@ -2,8 +2,11 @@
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: moubios32.c
* PURPOSE: VDM Mouse 32-bit BIOS
* PURPOSE: VDM 32-bit PS/2 Mouse BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*
* NOTE: Based from VirtualBox OSE ROM BIOS, and SeaBIOS.
*/
/* INCLUDES *******************************************************************/
@ -12,118 +15,512 @@
#include "ntvdm.h"
#include "emulator.h"
#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
#include "moubios32.h"
#include "bios32p.h"
#include "io.h"
#include "hardware/mouse.h"
#include "hardware/ps2.h"
/* PRIVATE VARIABLES **********************************************************/
#define MOUSE_IRQ_INT 0x74
static BOOLEAN MouseEnabled = FALSE;
static DWORD OldIrqHandler;
/*
* Far pointer to a device handler. In compatible PS/2, it is stored in the EBDA.
*
* See Ralf Brown: http://www.ctyme.com/intr/rb-1603.htm
* for more information. In particular:
* when the subroutine is called, it is given 4 WORD values on the stack;
* the handler should return with a FAR return without popping the stack.
*/
static ULONG DeviceHandler = 0;
/* PRIVATE FUNCTIONS **********************************************************/
static VOID DisableMouseInt(VOID)
{
BYTE ControllerConfig;
/* Clear the mouse queue */
while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
/* Disable mouse interrupt and events */
IOWriteB(PS2_CONTROL_PORT, 0x20);
ControllerConfig = IOReadB(PS2_DATA_PORT);
ControllerConfig &= ~0x02; // Turn off IRQ12
ControllerConfig |= 0x20; // Disable mouse clock line
IOWriteB(PS2_CONTROL_PORT, 0x60);
IOWriteB(PS2_DATA_PORT, ControllerConfig);
}
static VOID EnableMouseInt(VOID)
{
BYTE ControllerConfig;
/* Clear the mouse queue */
while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
/* Enable mouse interrupt and events */
IOWriteB(PS2_CONTROL_PORT, 0x20);
ControllerConfig = IOReadB(PS2_DATA_PORT);
ControllerConfig |= 0x02; // Turn on IRQ12
ControllerConfig &= ~0x20; // Enable mouse clock line
IOWriteB(PS2_CONTROL_PORT, 0x60);
IOWriteB(PS2_DATA_PORT, ControllerConfig);
}
static inline
VOID SendMouseCommand(UCHAR Command)
{
/* Clear the mouse queue */
while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
/* Send the command */
IOWriteB(PS2_CONTROL_PORT, 0xD4);
IOWriteB(PS2_DATA_PORT, Command);
}
static inline
UCHAR ReadMouseData(VOID)
{
PS2PortQueueRead(1); // NOTE: Should be a IOReadB! But see r67231
return IOReadB(PS2_DATA_PORT);
}
static
VOID BiosMouseEnable(VOID)
{
if (MouseEnabled) return;
MouseEnabled = TRUE;
/* Get the old IRQ handler */
OldIrqHandler = ((PDWORD)BaseAddress)[MOUSE_IRQ_INT];
/* Set the IRQ handler */
//RegisterInt32(MAKELONG(FIELD_OFFSET(MOUSE_DRIVER, MouseIrqInt16Stub), MouseDataSegment),
// MOUSE_IRQ_INT, DosMouseIrq, NULL);
}
static
VOID BiosMouseDisable(VOID)
{
if (!MouseEnabled) return;
/* Restore the old IRQ handler */
// ((PDWORD)BaseAddress)[MOUSE_IRQ_INT] = OldIrqHandler;
MouseEnabled = FALSE;
}
// Mouse IRQ 12
static VOID WINAPI BiosMouseIrq(LPWORD Stack)
{
DPRINT1("PS/2 Mouse IRQ! DeviceHandler = 0x%04X:0x%04X\n",
HIWORD(DeviceHandler), LOWORD(DeviceHandler));
if (DeviceHandler != 0)
{
/*
* Prepare the stack for the mouse device handler:
* push Status, X and Y data, and a zero word.
*/
setSP(getSP() - sizeof(WORD));
*((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Status
setSP(getSP() - sizeof(WORD));
*((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // X data (high byte = 0)
setSP(getSP() - sizeof(WORD));
*((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Y data (high byte = 0)
setSP(getSP() - sizeof(WORD));
*((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Zero
/* Call the device handler */
RunCallback16(&BiosContext, DeviceHandler);
/* Pop the stack */
setSP(getSP() + 4*sizeof(WORD));
}
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
}
VOID BiosMousePs2Interface(LPWORD Stack)
{
DPRINT1("INT 15h, AH = C2h must be implemented in order to support vendor mouse drivers\n");
/* Disable mouse interrupt and events */
DisableMouseInt();
switch (getAL())
{
/* Enable / Disable */
case 0x00:
{
break;
}
UCHAR State = getBH();
/* Reset */
case 0x01:
{
break;
}
if (State > 2)
{
/* Invalid function */
setAH(0x01);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Set Sampling Rate */
case 0x02:
{
break;
}
if (State == 0x00)
{
BiosMouseDisable();
/* Set Resolution */
case 0x03:
{
break;
}
/* Disable packet reporting */
SendMouseCommand(0xF5);
}
else // if (State == 0x01)
{
/* Check for the presence of the device handler */
if (DeviceHandler == 0)
{
/* No device handler installed */
setAH(0x05);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Get Type */
case 0x04:
{
BiosMouseEnable();
/* Enable packet reporting */
SendMouseCommand(0xF4);
}
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Initialize */
case 0x05:
{
// Fall through
}
/* Reset */
case 0x01:
{
UCHAR Answer;
SendMouseCommand(0xFF);
Answer = ReadMouseData();
/* A "Resend" (0xFE) signal is sent if no mouse is attached */
if (Answer == 0xFE)
{
/* Resend */
setAH(0x04);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
else if (Answer != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
setBL(ReadMouseData()); // Should be MOUSE_BAT_SUCCESS
setBH(ReadMouseData()); // Mouse ID
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Extended Commands */
/* Set Sampling Rate */
case 0x02:
{
UCHAR SampleRate = 0;
switch (getBH())
{
case 0x00: SampleRate = 10; break; // 10 reports/sec
case 0x01: SampleRate = 20; break; // 20 " "
case 0x02: SampleRate = 40; break; // 40 " "
case 0x03: SampleRate = 60; break; // 60 " "
case 0x04: SampleRate = 80; break; // 80 " "
case 0x05: SampleRate = 100; break; // 100 " "
case 0x06: SampleRate = 200; break; // 200 " "
default: SampleRate = 0;
}
if (SampleRate == 0)
{
/* Invalid input */
setAH(0x02);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
SendMouseCommand(0xF3);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
SendMouseCommand(SampleRate);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Set Resolution */
case 0x03:
{
UCHAR Resolution = getBH();
/*
* 0: 25 dpi, 1 count per millimeter
* 1: 50 dpi, 2 counts per millimeter
* 2: 100 dpi, 4 counts per millimeter
* 3: 200 dpi, 8 counts per millimeter
*/
if (Resolution > 3)
{
/* Invalid input */
setAH(0x02);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
SendMouseCommand(0xE8);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
SendMouseCommand(Resolution);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Get Type */
case 0x04:
{
SendMouseCommand(0xF2);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
setBH(ReadMouseData());
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Extended Commands (Return Status and Set Scaling Factor) */
case 0x06:
{
UCHAR Command = getBH();
switch (Command)
{
/* Return Status */
case 0x00:
{
SendMouseCommand(0xE9);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
}
setBL(ReadMouseData()); // Status
setCL(ReadMouseData()); // Resolution
setDL(ReadMouseData()); // Sample rate
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Set Scaling Factor to 1:1 */
case 0x01:
/* Set Scaling Factor to 2:1 */
case 0x02:
{
SendMouseCommand(Command == 0x01 ? 0xE6 : 0xE7);
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
}
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
default:
{
/* Invalid function */
setAH(0x01);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
}
break;
}
/* Set Device Handler Address */
case 0x07:
{
/* ES:BX == 0000h:0000h removes the device handler */
DeviceHandler = MAKELONG(getBX(), getES());
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Write to Pointer Port */
case 0x08:
{
SendMouseCommand(getBL());
if (ReadMouseData() != MOUSE_ACK)
{
/* Failure */
setAH(0x03);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Read from Pointer Port */
case 0x09:
{
setBL(ReadMouseData());
setCL(ReadMouseData());
setDL(ReadMouseData());
/* Success */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
default:
{
DPRINT1("INT 15h, AH = C2h, AL = 0x%02X NOT IMPLEMENTED\n",
DPRINT1("INT 15h, AH = C2h, AL = %02Xh NOT IMPLEMENTED\n",
getAL());
/* Unknown function */
setAH(0x01);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
}
}
/* Reenable mouse interrupt and events */
EnableMouseInt();
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID MouseBios32Post(VOID)
{
BYTE ControllerConfig;
UCHAR Answer;
/* Clear the mouse queue */
while (PS2PortQueueRead(1)) continue;
/* Initialize PS/2 mouse port */
// Enable the port
IOWriteB(PS2_CONTROL_PORT, 0xA8);
/* Enable packet reporting */
IOWriteB(PS2_CONTROL_PORT, 0xD4);
IOWriteB(PS2_DATA_PORT, 0xF4);
/* Detect mouse presence by attempting a reset */
SendMouseCommand(0xFF);
Answer = ReadMouseData();
/* If no mouse attached, it will return RESEND (0xFE) */
if (Answer == 0xFE)
{
DPRINT1("No mouse present!\n");
}
else if (Answer != MOUSE_ACK)
{
DPRINT1("Mouse reset failure!\n");
}
else
{
/* Mouse present, try to completely enable it */
/* Read the mouse ACK reply */
PS2PortQueueRead(1);
// FIXME: The following is temporary until
// this is moved into the mouse driver!!
/* Enable IRQ12 */
IOWriteB(PS2_CONTROL_PORT, 0x20);
ControllerConfig = IOReadB(PS2_DATA_PORT);
IOWriteB(PS2_CONTROL_PORT, 0x60);
IOWriteB(PS2_DATA_PORT, ControllerConfig | 0x02);
/* Enable packet reporting */
SendMouseCommand(0xF4);
if (ReadMouseData() != MOUSE_ACK)
{
DPRINT1("Failed to enable mouse!\n");
}
else
{
/* Enable mouse interrupt and events */
EnableMouseInt();
}
}
/* No mouse driver available so far */
RegisterBiosInt32(0x33, NULL);
/* Set up the HW vector interrupts */
EnableHwIRQ(12, BiosMouseIrq);

View file

@ -2,7 +2,7 @@
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: mouse32.c
* PURPOSE: VDM 32-bit compatible MOUSE.COM driver
* PURPOSE: VDM 32-bit compatible PS/2 MOUSE.COM driver
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
@ -10,6 +10,10 @@
#define NDEBUG
/* Driver Version number and Copyright */
#include <reactos/buildno.h>
#include <reactos/version.h>
#include "ntvdm.h"
#include "emulator.h"
@ -30,7 +34,10 @@
/* PRIVATE VARIABLES **********************************************************/
static const CHAR MouseCopyright[] = "ROS PS/2 16/32-bit Mouse Driver Compatible MS-MOUSE 6.26 Copyright (C) ReactOS Team 1996-2015\0";
static const CHAR MouseCopyright[] =
"ReactOS PS/2 16/32-bit Mouse Driver Compatible MS-MOUSE 6.26\r\n"
"Version "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\r\n"
"Copyright (C) ReactOS Team 1996-"COPYRIGHT_YEAR"\0";
#pragma pack(push, 1)
@ -58,8 +65,80 @@ static MOUSE_DRIVER_STATE DriverState;
static DWORD OldIrqHandler;
static DWORD OldIntHandler;
static WORD DefaultGfxScreenMask[16] =
{
0xC3FF, // 1100001111111111
0xC0FF, // 1100000011111111
0xC07F, // 1100000001111111
0xC01F, // 1100000000011111
0xC00F, // 1100000000001111
0xC007, // 1100000000000111
0xC003, // 1100000000000011
0xC007, // 1100000000000111
0xC01F, // 1100000000011111
0xC01F, // 1100000000011111
0xC00F, // 1100000000001111
0xC60F, // 1100011000001111
0xFF07, // 1111111100000111
0xFF07, // 1111111100000111
0xFF87, // 1111111110000111
0xFFCF, // 1111111111001111
};
static WORD DefaultGfxCursorMask[16] =
{
0x0000, // 0000000000000000
0x1C00, // 0001110000000000
0x1F00, // 0001111100000000
0x1F80, // 0001111110000000
0x1FE0, // 0001111111100000
0x1FF0, // 0001111111110000
0x1FF8, // 0001111111111000
0x1FE0, // 0001111111100000
0x1FC0, // 0001111111000000
0x1FC0, // 0001111111000000
0x19E0, // 0001100111100000
0x00E0, // 0000000011100000
0x0070, // 0000000001110000
0x0070, // 0000000001110000
0x0030, // 0000000000110000
0x0000, // 0000000000000000
};
/* PRIVATE FUNCTIONS **********************************************************/
/* static */
VOID BiosPs2Service(UCHAR Function)
{
/* Save AX and BX */
USHORT AX = getAX();
// USHORT BX = getBX();
/*
* Set the parameters:
* AL contains the character to print (already set),
* BL contains the character attribute,
* BH contains the video page to use.
*/
// setBL(DOS_CHAR_ATTRIBUTE);
// setBH(Bda->VideoPage);
setAL(Function);
/* Call the BIOS INT 15h, AH=C2h "Pointing Device BIOS Interface (PS)" */
setAH(0xC2);
Int32Call(&MouseContext, BIOS_MISC_INTERRUPT);
/* Restore AX and BX */
// setBX(BX);
setAX(AX);
}
static VOID DosMouseEnable(VOID);
static VOID DosMouseDisable(VOID);
static VOID PaintMouseCursor(VOID)
{
COORD Position = DriverState.Position;
@ -273,7 +352,7 @@ static inline VOID DosUpdatePosition(PCOORD NewPosition)
CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format
}
static inline VOID DosUpdateButtons(BYTE ButtonState)
static inline VOID DosUpdateButtons(BYTE ButtonState) // WORD ButtonState
{
USHORT i;
USHORT CallMask = 0x0000; // We use MS MOUSE v1.0+ format
@ -316,9 +395,9 @@ static VOID WINAPI DosMouseIrq(LPWORD Stack)
/* Read the whole packet at once */
Flags = IOReadB(PS2_DATA_PORT);
PS2PortQueueRead(1);
PS2PortQueueRead(1); // NOTE: Should be a IOReadB! But see r67231
DeltaX = IOReadB(PS2_DATA_PORT);
PS2PortQueueRead(1);
PS2PortQueueRead(1); // NOTE: Should be a IOReadB! But see r67231
DeltaY = IOReadB(PS2_DATA_PORT);
/* Adjust the sign */
@ -369,39 +448,13 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
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
RtlCopyMemory(DriverState.GraphicsCursor.ScreenMask,
DefaultGfxScreenMask,
sizeof(DriverState.GraphicsCursor.ScreenMask));
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
RtlCopyMemory(DriverState.GraphicsCursor.CursorMask,
DefaultGfxCursorMask,
sizeof(DriverState.GraphicsCursor.CursorMask));
/* Initialize the counters */
DriverState.HorizCount = DriverState.VertCount = 0;
@ -436,7 +489,7 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
break;
}
/* Return Position And Button Status */
/* Return Position and Button Status */
case 0x03:
{
COORD Position = DriverState.Position;
@ -610,6 +663,13 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
break;
}
/* Set Exclusion Area */
// http://www.ctyme.com/intr/rb-5972.htm
// http://www.techhelpmanual.com/849-int_33h_0010h__set_exclusion_area.html
//case 0x10:
//{
//}
/* Define Double-Speed Threshold */
case 0x13:
{
@ -625,12 +685,18 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
DriverState.Handler0.CallMask = getCX();
DriverState.Handler0.Callback = MAKELONG(getDX(), getES()); // Far pointer to the callback
DPRINT1("Exchange old callback 0x%04X, %04X:%04X with new callback 0x%04X, %04X:%04X\n",
OldCallMask,
HIWORD(OldCallback),
LOWORD(OldCallback),
DriverState.Handler0.CallMask,
HIWORD(DriverState.Handler0.Callback),
LOWORD(DriverState.Handler0.Callback));
/* Return old callmask in CX and callback vector in ES:DX */
setCX(OldCallMask);
setES(HIWORD(OldCallback));
setDX(LOWORD(OldCallback));
break;
}
@ -644,6 +710,9 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
/* Save Driver State */
case 0x16:
{
/* Check whether the user buffer has correct size and fail if not */
if (getBX() != sizeof(MOUSE_DRIVER_STATE)) break;
*((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())) = DriverState;
break;
}
@ -651,6 +720,9 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
/* Restore Driver State */
case 0x17:
{
/* Check whether the user buffer has correct size and fail if not */
if (getBX() != sizeof(MOUSE_DRIVER_STATE)) break;
DriverState = *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX()));
break;
}
@ -803,6 +875,15 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
case 0x1A:
{
DPRINT1("INT 33h, AH=1Ah: Mouse sensitivity is UNSUPPORTED\n");
// FIXME: Do that at runtime!
// UCHAR BH = getBH();
// setBH(0x00);
// BiosPs2Service(0x00);
// FIXME: Check for return status in AH and CF
// setBH(BH);
break;
}
@ -815,6 +896,15 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
setBX(50); // Horizontal speed
setCX(50); // Vertical speed
setDX(50); // Double speed threshold
// FIXME: Get that at runtime!
// UCHAR BH = getBH();
// setBH(0x00);
// BiosPs2Service(0x00);
// FIXME: Check for return status in AH and CF
// setBH(BH);
break;
}
@ -826,6 +916,11 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
setBX(LOWORD(OldIntHandler));
DosMouseDisable();
// UCHAR BH = getBH();
// setBH(0x00);
// BiosPs2Service(0x00);
// FIXME: Check for return status in AH and CF
// setBH(BH);
break;
}
@ -833,6 +928,11 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
case 0x20:
{
DosMouseEnable();
// UCHAR BH = getBH();
// setBH(0x01);
// BiosPs2Service(0x00);
// FIXME: Check for return status in AH and CF
// setBH(BH);
break;
}
@ -876,6 +976,10 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
{
setBX(MOUSE_VERSION); // Version Number
/*
* See Ralf Brown: http://www.ctyme.com/intr/rb-5993.htm
* for the list of possible values.
*/
// FIXME: To be determined at runtime!
setCH(0x04); // PS/2 Type
setCL(0x00); // PS/2 Interrupt
@ -883,6 +987,60 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
break;
}
// BIOS Function INT 33h, AX = 0x0025 NOT IMPLEMENTED
case 0x25:
{
setAX(0);
setBX(0);
setCX(0);
setDX(0);
UNIMPLEMENTED;
break;
}
/* Get Maximum Virtual Coordinates */
case 0x26:
{
setBX(!DriverEnabled);
// FIXME: In fact the MaxX and MaxY here are
// theoretical values for the current video mode.
// They therefore can be different from the current
// min/max values.
// See http://www.ctyme.com/intr/rb-5995.htm
// for more details.
setCX(DriverState.MaxX);
setDX(DriverState.MaxY);
break;
}
/* Get Current Minimum/Maximum Virtual Coordinates */
case 0x31:
{
setAX(DriverState.MinX);
setBX(DriverState.MinY);
setCX(DriverState.MaxX);
setDX(DriverState.MaxY);
break;
}
#if 0
case 0x33:
{
/*
* Related to http://www.ctyme.com/intr/rb-5985.htm
* INT 33h, AX=001Ch "SET INTERRUPT RATE":
* Values for mouse interrupt rate:
* BX = rate
00h no interrupts allowed
01h 30 per second
02h 50 per second
03h 100 per second
04h 200 per second
*/
}
#endif
/* Return Pointer to Copyright String */
case 0x4D:
{
@ -914,6 +1072,7 @@ static VOID WINAPI DosMouseService(LPWORD Stack)
/* PUBLIC FUNCTIONS ***********************************************************/
static
VOID DosMouseEnable(VOID)
{
if (DriverEnabled) return;
@ -928,6 +1087,7 @@ VOID DosMouseEnable(VOID)
MOUSE_IRQ_INT, DosMouseIrq, NULL);
}
static
VOID DosMouseDisable(VOID)
{
if (!DriverEnabled) return;
@ -938,61 +1098,6 @@ VOID DosMouseDisable(VOID)
DriverEnabled = FALSE;
}
VOID DosMouseUpdatePosition(PCOORD NewPosition)
{
SHORT DeltaX = NewPosition->X - DriverState.Position.X;
SHORT DeltaY = NewPosition->Y - DriverState.Position.Y;
if (!DriverEnabled) return;
DriverState.HorizCount += (DeltaX * MICKEYS_PER_CELL_HORIZ) / 8;
DriverState.VertCount += (DeltaY * MICKEYS_PER_CELL_VERT) / 8;
if (DriverState.ShowCount > 0) EraseMouseCursor();
DriverState.Position = *NewPosition;
if (DriverState.ShowCount > 0) PaintMouseCursor();
/* Call the mouse handlers */
// if (DeltaX || DeltaY)
CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format
}
VOID DosMouseUpdateButtons(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 DosMouseInitialize(VOID)
{
/* Initialize some memory for storing our data that should be available to DOS */
@ -1020,6 +1125,12 @@ BOOLEAN DosMouseInitialize(VOID)
DOS_MOUSE_INTERRUPT, DosMouseService, NULL);
DosMouseEnable();
// UCHAR BH = getBH();
// setBH(0x01);
// BiosPs2Service(0x00);
// FIXME: Check for return status in AH and CF
// setBH(BH);
return TRUE;
}
@ -1027,6 +1138,11 @@ VOID DosMouseCleanup(VOID)
{
if (DriverState.ShowCount > 0) EraseMouseCursor();
DosMouseDisable();
// UCHAR BH = getBH();
// setBH(0x00);
// BiosPs2Service(0x00);
// FIXME: Check for return status in AH and CF
// setBH(BH);
/* Restore the old mouse service interrupt handler */
((PDWORD)BaseAddress)[DOS_MOUSE_INTERRUPT] = OldIntHandler;

View file

@ -2,7 +2,7 @@
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: mouse32.h
* PURPOSE: VDM 32-bit compatible MOUSE.COM driver
* PURPOSE: VDM 32-bit compatible PS/2 MOUSE.COM driver
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
@ -12,7 +12,7 @@
/* DEFINES ********************************************************************/
//
// We are ROS PS/2 Mouse Driver Version 6.26, compatible MS-MOUSE 6.26
// We are ReactOS PS/2 Mouse Driver Version 6.26, compatible MS-MOUSE 6.26
//
#define MOUSE_VERSION MAKEWORD(0x26, 0x06)
@ -75,8 +75,6 @@ typedef struct _MOUSE_DRIVER_STATE
/* FUNCTIONS ******************************************************************/
VOID DosMouseEnable(VOID);
VOID DosMouseDisable(VOID);
BOOLEAN DosMouseInitialize(VOID);
VOID DosMouseCleanup(VOID);

View file

@ -2,7 +2,7 @@
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: mouse.c
* PURPOSE: Mouse emulation
* PURPOSE: PS/2 Mouse emulation
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
@ -39,12 +39,12 @@ static BOOLEAN EventsOccurred = FALSE;
static BYTE DataByteWait = 0;
static BYTE ScrollMagicCounter = 0, ExtraButtonMagicCounter = 0;
static UINT MouseCycles = 10;
static BYTE PS2Port = 1;
/* PUBLIC VARIABLES ***********************************************************/
UINT MouseCycles = 10;
/* PRIVATE FUNCTIONS **********************************************************/
static VOID MouseResetConfig(VOID)
@ -73,6 +73,8 @@ static VOID MouseReset(VOID)
MouseId = 0;
ScrollMagicCounter = ExtraButtonMagicCounter = 0;
PS2QueuePush(PS2Port, MOUSE_ACK);
/* Send the Basic Assurance Test success code and the device ID */
PS2QueuePush(PS2Port, MOUSE_BAT_SUCCESS);
PS2QueuePush(PS2Port, MouseId);
@ -118,7 +120,7 @@ static VOID MouseGetPacket(PMOUSE_PACKET Packet)
/* Set the button flags */
if (ButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) Packet->Flags |= MOUSE_LEFT_BUTTON;
if (ButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) Packet->Flags |= MOUSE_MIDDLE_BUTTON;
if (ButtonState & RIGHTMOST_BUTTON_PRESSED) Packet->Flags |= MOUSE_RIGHT_BUTTON;
if (ButtonState & RIGHTMOST_BUTTON_PRESSED) Packet->Flags |= MOUSE_RIGHT_BUTTON;
if (MouseId == 4)
{
@ -250,8 +252,8 @@ static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
/* Set Sample Rate */
case 0xF3:
{
PS2QueuePush(PS2Port, MOUSE_ACK);
DataByteWait = Command;
PS2QueuePush(PS2Port, MOUSE_ACK);
break;
}
@ -259,12 +261,12 @@ static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
case 0xE9:
{
BYTE Status = ButtonState & 7;
PS2QueuePush(PS2Port, MOUSE_ACK);
if (Scaling) Status |= 1 << 4;
if (Reporting) Status |= 1 << 5;
if (Mode == MOUSE_REMOTE_MODE) Status |= 1 << 6;
PS2QueuePush(PS2Port, MOUSE_ACK);
PS2QueuePush(PS2Port, Status);
PS2QueuePush(PS2Port, Resolution);
PS2QueuePush(PS2Port, (BYTE)(1000 / MouseCycles));
@ -290,7 +292,7 @@ static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
break;
}
/* Return From Wrap Mode */
/* Return from Wrap Mode */
case 0xEC:
{
if (Mode == MOUSE_WRAP_MODE)
@ -300,7 +302,10 @@ static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
Mode = PreviousMode;
PS2QueuePush(PS2Port, MOUSE_ACK);
}
else PS2QueuePush(PS2Port, MOUSE_ERROR);
else
{
PS2QueuePush(PS2Port, MOUSE_ERROR);
}
break;
}

View file

@ -45,8 +45,7 @@ typedef struct _PS2_PORT
#define PS2_PORTS 2
static PS2_PORT Ports[PS2_PORTS];
#define PS2_DEFAULT_CONFIG 0x45
static BYTE ControllerConfig = PS2_DEFAULT_CONFIG;
static BYTE ControllerConfig = 0x00;
static BYTE ControllerCommand = 0x00;
static BYTE StatusRegister = 0x00;
@ -69,8 +68,16 @@ static BYTE WINAPI PS2ReadPort(USHORT Port)
{
if (Port == PS2_CONTROL_PORT)
{
/* Be sure bit 2 is always set */
StatusRegister |= 1 << 2;
/*
* Be sure bit 4 "Keyboard enable flag" is always set.
* Keyboard enable (or keyboard lock) flag values are:
* 0: Locked; 1: Not locked.
* On IBM PC-ATs this is the state of the hardware keyboard
* lock mechanism. It is not widely used, but some programs
* still use it: see for example:
* http://www.os2museum.com/wp/the-dos-4-0-shell-mouse-mystery/
*/
StatusRegister |= (1 << 4);
// FIXME: Should clear bits 6 and 7 because there are
// no timeouts and no parity errors.
@ -220,6 +227,31 @@ static VOID WINAPI PS2WritePort(USHORT Port, BYTE Data)
case 0x60:
{
ControllerConfig = Data;
/*
* Update bit 2 "System flag" of the status register
* with bit 2 of the controller configuration byte.
* See: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html#kccb2
* for more details.
*/
if (ControllerConfig & (1 << 2))
StatusRegister |= (1 << 2);
else
StatusRegister &= ~(1 << 2);
/*
* Update bit 4 "Keyboard enable flag" of the status register
* with bit 3 "Ignore keyboard lock" of the controller
* configuration byte (if set), then reset the latter one.
* See: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html#kccb3
* for more details.
*/
if (ControllerConfig & (1 << 3))
{
StatusRegister |= (1 << 4);
ControllerConfig &= ~(1 << 3);
}
break;
}
@ -399,13 +431,13 @@ Done:
BOOLEAN PS2Initialize(VOID)
{
/* Initialize the PS/2 ports */
Ports[0].IsEnabled = TRUE;
Ports[0].IsEnabled = FALSE;
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].IsEnabled = FALSE;
Ports[1].QueueEmpty = TRUE;
Ports[1].QueueStart = 0;
Ports[1].QueueEnd = 0;