25ff3f610b9eb290cf1b740de4c45d60c305ec5a
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/bios/bios32/moubios32.c
5 * PURPOSE: VDM 32-bit PS/2 Mouse BIOS
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 * NOTE: Based from VirtualBox OSE ROM BIOS, and SeaBIOS.
12 /* INCLUDES *******************************************************************/
18 #include "cpu/cpu.h" // for EMULATOR_FLAG_CF
20 #include "moubios32.h"
24 #include "hardware/mouse.h"
25 #include "hardware/ps2.h"
27 /* PRIVATE VARIABLES **********************************************************/
29 #define MOUSE_IRQ_INT 0x74
31 static BOOLEAN MouseEnabled
= FALSE
;
32 static DWORD OldIrqHandler
;
35 * Far pointer to a device handler. In compatible PS/2, it is stored in the EBDA.
37 * See Ralf Brown: http://www.ctyme.com/intr/rb-1603.htm
38 * for more information. In particular:
39 * when the subroutine is called, it is given 4 WORD values on the stack;
40 * the handler should return with a FAR return without popping the stack.
42 static ULONG DeviceHandler
= 0;
44 /* PRIVATE FUNCTIONS **********************************************************/
46 static VOID
DisableMouseInt(VOID
)
48 BYTE ControllerConfig
;
50 /* Clear the mouse queue */
51 while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
53 /* Disable mouse interrupt and events */
54 IOWriteB(PS2_CONTROL_PORT
, 0x20);
55 ControllerConfig
= IOReadB(PS2_DATA_PORT
);
56 ControllerConfig
&= ~0x02; // Turn off IRQ12
57 ControllerConfig
|= 0x20; // Disable mouse clock line
58 IOWriteB(PS2_CONTROL_PORT
, 0x60);
59 IOWriteB(PS2_DATA_PORT
, ControllerConfig
);
62 static VOID
EnableMouseInt(VOID
)
64 BYTE ControllerConfig
;
66 /* Clear the mouse queue */
67 while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
69 /* Enable mouse interrupt and events */
70 IOWriteB(PS2_CONTROL_PORT
, 0x20);
71 ControllerConfig
= IOReadB(PS2_DATA_PORT
);
72 ControllerConfig
|= 0x02; // Turn on IRQ12
73 ControllerConfig
&= ~0x20; // Enable mouse clock line
74 IOWriteB(PS2_CONTROL_PORT
, 0x60);
75 IOWriteB(PS2_DATA_PORT
, ControllerConfig
);
79 VOID
SendMouseCommand(UCHAR Command
)
81 /* Clear the mouse queue */
82 while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
84 /* Send the command */
85 IOWriteB(PS2_CONTROL_PORT
, 0xD4);
86 IOWriteB(PS2_DATA_PORT
, Command
);
90 UCHAR
ReadMouseData(VOID
)
92 PS2PortQueueRead(1); // NOTE: Should be a IOReadB! But see r67231
93 return IOReadB(PS2_DATA_PORT
);
98 VOID
BiosMouseEnable(VOID
)
100 if (MouseEnabled
) return;
104 /* Get the old IRQ handler */
105 OldIrqHandler
= ((PDWORD
)BaseAddress
)[MOUSE_IRQ_INT
];
107 /* Set the IRQ handler */
108 //RegisterInt32(MAKELONG(FIELD_OFFSET(MOUSE_DRIVER, MouseIrqInt16Stub), MouseDataSegment),
109 // MOUSE_IRQ_INT, DosMouseIrq, NULL);
113 VOID
BiosMouseDisable(VOID
)
115 if (!MouseEnabled
) return;
117 /* Restore the old IRQ handler */
118 // ((PDWORD)BaseAddress)[MOUSE_IRQ_INT] = OldIrqHandler;
120 MouseEnabled
= FALSE
;
125 static VOID WINAPI
BiosMouseIrq(LPWORD Stack
)
127 DPRINT1("PS/2 Mouse IRQ! DeviceHandler = 0x%04X:0x%04X\n",
128 HIWORD(DeviceHandler
), LOWORD(DeviceHandler
));
130 if (DeviceHandler
!= 0)
133 * Prepare the stack for the mouse device handler:
134 * push Status, X and Y data, and a zero word.
136 setSP(getSP() - sizeof(WORD
));
137 *((LPWORD
)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Status
138 setSP(getSP() - sizeof(WORD
));
139 *((LPWORD
)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // X data (high byte = 0)
140 setSP(getSP() - sizeof(WORD
));
141 *((LPWORD
)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Y data (high byte = 0)
142 setSP(getSP() - sizeof(WORD
));
143 *((LPWORD
)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Zero
145 /* Call the device handler */
146 RunCallback16(&BiosContext
, DeviceHandler
);
149 setSP(getSP() + 4*sizeof(WORD
));
152 PicIRQComplete(LOBYTE(Stack
[STACK_INT_NUM
]));
155 VOID
BiosMousePs2Interface(LPWORD Stack
)
157 /* Disable mouse interrupt and events */
162 /* Enable / Disable */
165 UCHAR State
= getBH();
169 /* Invalid function */
171 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
179 /* Disable packet reporting */
180 SendMouseCommand(0xF5);
182 else // if (State == 0x01)
184 /* Check for the presence of the device handler */
185 if (DeviceHandler
== 0)
187 /* No device handler installed */
189 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
195 /* Enable packet reporting */
196 SendMouseCommand(0xF4);
199 if (ReadMouseData() != MOUSE_ACK
)
203 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
209 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
224 SendMouseCommand(0xFF);
225 Answer
= ReadMouseData();
226 /* A "Resend" signal (0xFE) is sent if no mouse is attached */
231 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
234 else if (Answer
!= MOUSE_ACK
)
238 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
242 setBL(ReadMouseData()); // Should be MOUSE_BAT_SUCCESS
243 setBH(ReadMouseData()); // Mouse ID
247 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
251 /* Set Sampling Rate */
254 UCHAR SampleRate
= 0;
258 case 0x00: SampleRate
= 10; break; // 10 reports/sec
259 case 0x01: SampleRate
= 20; break; // 20 " "
260 case 0x02: SampleRate
= 40; break; // 40 " "
261 case 0x03: SampleRate
= 60; break; // 60 " "
262 case 0x04: SampleRate
= 80; break; // 80 " "
263 case 0x05: SampleRate
= 100; break; // 100 " "
264 case 0x06: SampleRate
= 200; break; // 200 " "
265 default: SampleRate
= 0;
272 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
276 SendMouseCommand(0xF3);
277 if (ReadMouseData() != MOUSE_ACK
)
281 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
285 SendMouseCommand(SampleRate
);
286 if (ReadMouseData() != MOUSE_ACK
)
290 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
296 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
303 UCHAR Resolution
= getBH();
306 * 0: 25 dpi, 1 count per millimeter
307 * 1: 50 dpi, 2 counts per millimeter
308 * 2: 100 dpi, 4 counts per millimeter
309 * 3: 200 dpi, 8 counts per millimeter
315 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
319 SendMouseCommand(0xE8);
320 if (ReadMouseData() != MOUSE_ACK
)
324 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
328 SendMouseCommand(Resolution
);
329 if (ReadMouseData() != MOUSE_ACK
)
333 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
339 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
346 SendMouseCommand(0xF2);
347 if (ReadMouseData() != MOUSE_ACK
)
351 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
355 setBH(ReadMouseData());
359 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
363 /* Extended Commands (Return Status and Set Scaling Factor) */
366 UCHAR Command
= getBH();
373 SendMouseCommand(0xE9);
374 if (ReadMouseData() != MOUSE_ACK
)
378 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
382 setBL(ReadMouseData()); // Status
383 setCL(ReadMouseData()); // Resolution
384 setDL(ReadMouseData()); // Sample rate
388 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
392 /* Set Scaling Factor to 1:1 */
394 /* Set Scaling Factor to 2:1 */
397 SendMouseCommand(Command
== 0x01 ? 0xE6 : 0xE7);
398 if (ReadMouseData() != MOUSE_ACK
)
402 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
408 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
414 /* Invalid function */
416 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
424 /* Set Device Handler Address */
427 /* ES:BX == 0000h:0000h removes the device handler */
428 DeviceHandler
= MAKELONG(getBX(), getES());
432 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
436 /* Write to Pointer Port */
439 SendMouseCommand(getBL());
440 if (ReadMouseData() != MOUSE_ACK
)
444 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
450 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
454 /* Read from Pointer Port */
457 setBL(ReadMouseData());
458 setCL(ReadMouseData());
459 setDL(ReadMouseData());
463 Stack
[STACK_FLAGS
] &= ~EMULATOR_FLAG_CF
;
469 DPRINT1("INT 15h, AH = C2h, AL = %02Xh NOT IMPLEMENTED\n",
472 /* Unknown function */
474 Stack
[STACK_FLAGS
] |= EMULATOR_FLAG_CF
;
478 /* Reenable mouse interrupt and events */
482 /* PUBLIC FUNCTIONS ***********************************************************/
484 VOID
MouseBios32Post(VOID
)
488 /* Initialize PS/2 mouse port */
490 IOWriteB(PS2_CONTROL_PORT
, 0xA8);
492 /* Detect mouse presence by attempting a reset */
493 SendMouseCommand(0xFF);
494 Answer
= ReadMouseData();
495 /* A "Resend" signal (0xFE) is sent if no mouse is attached */
498 DPRINT1("No mouse present!\n");
500 else if (Answer
!= MOUSE_ACK
)
502 DPRINT1("Mouse reset failure!\n");
506 /* Mouse present, try to completely enable it */
508 // FIXME: The following is temporary until
509 // this is moved into the mouse driver!!
511 /* Enable packet reporting */
512 SendMouseCommand(0xF4);
513 if (ReadMouseData() != MOUSE_ACK
)
515 DPRINT1("Failed to enable mouse!\n");
519 /* Enable mouse interrupt and events */
524 /* No mouse driver available so far */
525 RegisterBiosInt32(0x33, NULL
);
527 /* Set up the HW vector interrupts */
528 EnableHwIRQ(12, BiosMouseIrq
);
531 BOOLEAN
MouseBiosInitialize(VOID
)
536 VOID
MouseBios32Cleanup(VOID
)