ReactOS 0.4.15-dev-7677-g8209aa5
moubios32.c
Go to the documentation of this file.
1/*
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)
8 *
9 * NOTE: Based from VirtualBox OSE ROM BIOS, and SeaBIOS.
10 */
11
12/* INCLUDES *******************************************************************/
13
14#include "ntvdm.h"
15
16#define NDEBUG
17#include <debug.h>
18
19#include "emulator.h"
20#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
21
22#include "moubios32.h"
23#include "bios32p.h"
24
25#include "io.h"
26#include "hardware/mouse.h"
27#include "hardware/ps2.h"
28
29/* PRIVATE VARIABLES **********************************************************/
30
31#define MOUSE_IRQ_INT 0x74
32
35
36/*
37 * Far pointer to a device handler. In compatible PS/2, it is stored in the EBDA.
38 *
39 * See Ralf Brown: http://www.ctyme.com/intr/rb-1603.htm
40 * for more information. In particular:
41 * when the subroutine is called, it is given 4 WORD values on the stack;
42 * the handler should return with a FAR return without popping the stack.
43 */
45
46/* PRIVATE FUNCTIONS **********************************************************/
47
49{
51
52 /* Clear the mouse queue */
53 while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
54
55 /* Disable mouse interrupt and events */
58 ControllerConfig &= ~0x02; // Turn off IRQ12
59 ControllerConfig |= 0x20; // Disable mouse clock line
62}
63
65{
67
68 /* Clear the mouse queue */
69 while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
70
71 /* Enable mouse interrupt and events */
74 ControllerConfig |= 0x02; // Turn on IRQ12
75 ControllerConfig &= ~0x20; // Enable mouse clock line
78}
79
80static inline
82{
83 /* Clear the mouse queue */
84 while (PS2PortQueueRead(1)) ; // NOTE: Should be a IOReadB! But see r67231
85
86 /* Send the command */
89}
90
91static inline
93{
94 PS2PortQueueRead(1); // NOTE: Should be a IOReadB! But see r67231
95 return IOReadB(PS2_DATA_PORT);
96}
97
98
99static
101{
102 if (MouseEnabled) return;
103
105
106 /* Get the old IRQ handler */
108
109 /* Set the IRQ handler */
110 //RegisterInt32(MAKELONG(FIELD_OFFSET(MOUSE_DRIVER, MouseIrqInt16Stub), MouseDataSegment),
111 // MOUSE_IRQ_INT, DosMouseIrq, NULL);
112}
113
114static
116{
117 if (!MouseEnabled) return;
118
119 /* Restore the old IRQ handler */
120 // ((PDWORD)BaseAddress)[MOUSE_IRQ_INT] = OldIrqHandler;
121
123}
124
125
126// Mouse IRQ 12
128{
129 DPRINT1("PS/2 Mouse IRQ! DeviceHandler = 0x%04X:0x%04X\n",
131
132 if (DeviceHandler != 0)
133 {
134 /*
135 * Prepare the stack for the mouse device handler:
136 * push Status, X and Y data, and a zero word.
137 */
138 setSP(getSP() - sizeof(WORD));
139 *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Status
140 setSP(getSP() - sizeof(WORD));
141 *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // X data (high byte = 0)
142 setSP(getSP() - sizeof(WORD));
143 *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Y data (high byte = 0)
144 setSP(getSP() - sizeof(WORD));
145 *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = 0; // Zero
146
147 /* Call the device handler */
149
150 /* Pop the stack */
151 setSP(getSP() + 4*sizeof(WORD));
152 }
153
155}
156
158{
159 /* Disable mouse interrupt and events */
161
162 switch (getAL())
163 {
164 /* Enable / Disable */
165 case 0x00:
166 {
167 UCHAR State = getBH();
168
169 if (State > 2)
170 {
171 /* Invalid function */
172 setAH(0x01);
174 break;
175 }
176
177 if (State == 0x00)
178 {
180
181 /* Disable packet reporting */
182 SendMouseCommand(0xF5);
183 }
184 else // if (State == 0x01)
185 {
186 /* Check for the presence of the device handler */
187 if (DeviceHandler == 0)
188 {
189 /* No device handler installed */
190 setAH(0x05);
192 break;
193 }
194
196
197 /* Enable packet reporting */
198 SendMouseCommand(0xF4);
199 }
200
201 if (ReadMouseData() != MOUSE_ACK)
202 {
203 /* Failure */
204 setAH(0x03);
206 break;
207 }
208
209 /* Success */
210 setAH(0x00);
211 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
212 break;
213 }
214
215 /* Initialize */
216 case 0x05:
217 {
218 // Fall through
219 }
220
221 /* Reset */
222 case 0x01:
223 {
224 UCHAR Answer;
225
226 SendMouseCommand(0xFF);
227 Answer = ReadMouseData();
228 /* A "Resend" signal (0xFE) is sent if no mouse is attached */
229 if (Answer == 0xFE)
230 {
231 /* Resend */
232 setAH(0x04);
234 break;
235 }
236 else if (Answer != MOUSE_ACK)
237 {
238 /* Failure */
239 setAH(0x03);
241 break;
242 }
243
244 setBL(ReadMouseData()); // Should be MOUSE_BAT_SUCCESS
245 setBH(ReadMouseData()); // Mouse ID
246
247 /* Success */
248 setAH(0x00);
249 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
250 break;
251 }
252
253 /* Set Sampling Rate */
254 case 0x02:
255 {
256 UCHAR SampleRate = 0;
257
258 switch (getBH())
259 {
260 case 0x00: SampleRate = 10; break; // 10 reports/sec
261 case 0x01: SampleRate = 20; break; // 20 " "
262 case 0x02: SampleRate = 40; break; // 40 " "
263 case 0x03: SampleRate = 60; break; // 60 " "
264 case 0x04: SampleRate = 80; break; // 80 " "
265 case 0x05: SampleRate = 100; break; // 100 " "
266 case 0x06: SampleRate = 200; break; // 200 " "
267 default: SampleRate = 0;
268 }
269
270 if (SampleRate == 0)
271 {
272 /* Invalid input */
273 setAH(0x02);
275 break;
276 }
277
278 SendMouseCommand(0xF3);
279 if (ReadMouseData() != MOUSE_ACK)
280 {
281 /* Failure */
282 setAH(0x03);
284 break;
285 }
286
287 SendMouseCommand(SampleRate);
288 if (ReadMouseData() != MOUSE_ACK)
289 {
290 /* Failure */
291 setAH(0x03);
293 break;
294 }
295
296 /* Success */
297 setAH(0x00);
298 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
299 break;
300 }
301
302 /* Set Resolution */
303 case 0x03:
304 {
306
307 /*
308 * 0: 25 dpi, 1 count per millimeter
309 * 1: 50 dpi, 2 counts per millimeter
310 * 2: 100 dpi, 4 counts per millimeter
311 * 3: 200 dpi, 8 counts per millimeter
312 */
313 if (Resolution > 3)
314 {
315 /* Invalid input */
316 setAH(0x02);
318 break;
319 }
320
321 SendMouseCommand(0xE8);
322 if (ReadMouseData() != MOUSE_ACK)
323 {
324 /* Failure */
325 setAH(0x03);
327 break;
328 }
329
331 if (ReadMouseData() != MOUSE_ACK)
332 {
333 /* Failure */
334 setAH(0x03);
336 break;
337 }
338
339 /* Success */
340 setAH(0x00);
341 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
342 break;
343 }
344
345 /* Get Type */
346 case 0x04:
347 {
348 SendMouseCommand(0xF2);
349 if (ReadMouseData() != MOUSE_ACK)
350 {
351 /* Failure */
352 setAH(0x03);
354 break;
355 }
356
358
359 /* Success */
360 setAH(0x00);
361 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
362 break;
363 }
364
365 /* Extended Commands (Return Status and Set Scaling Factor) */
366 case 0x06:
367 {
368 UCHAR Command = getBH();
369
370 switch (Command)
371 {
372 /* Return Status */
373 case 0x00:
374 {
375 SendMouseCommand(0xE9);
376 if (ReadMouseData() != MOUSE_ACK)
377 {
378 /* Failure */
379 setAH(0x03);
381 break;
382 }
383
384 setBL(ReadMouseData()); // Status
385 setCL(ReadMouseData()); // Resolution
386 setDL(ReadMouseData()); // Sample rate
387
388 /* Success */
389 setAH(0x00);
390 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
391 break;
392 }
393
394 /* Set Scaling Factor to 1:1 */
395 case 0x01:
396 /* Set Scaling Factor to 2:1 */
397 case 0x02:
398 {
399 SendMouseCommand(Command == 0x01 ? 0xE6 : 0xE7);
400 if (ReadMouseData() != MOUSE_ACK)
401 {
402 /* Failure */
403 setAH(0x03);
405 break;
406 }
407
408 /* Success */
409 setAH(0x00);
410 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
411 break;
412 }
413
414 default:
415 {
416 /* Invalid function */
417 setAH(0x01);
419 break;
420 }
421 }
422
423 break;
424 }
425
426 /* Set Device Handler Address */
427 case 0x07:
428 {
429 /* ES:BX == 0000h:0000h removes the device handler */
431
432 /* Success */
433 setAH(0x00);
434 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
435 break;
436 }
437
438 /* Write to Pointer Port */
439 case 0x08:
440 {
442 if (ReadMouseData() != MOUSE_ACK)
443 {
444 /* Failure */
445 setAH(0x03);
447 break;
448 }
449
450 /* Success */
451 setAH(0x00);
452 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
453 break;
454 }
455
456 /* Read from Pointer Port */
457 case 0x09:
458 {
462
463 /* Success */
464 setAH(0x00);
465 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
466 break;
467 }
468
469 default:
470 {
471 DPRINT1("INT 15h, AH = C2h, AL = %02Xh NOT IMPLEMENTED\n",
472 getAL());
473
474 /* Unknown function */
475 setAH(0x01);
477 }
478 }
479
480 /* Reenable mouse interrupt and events */
482}
483
484/* PUBLIC FUNCTIONS ***********************************************************/
485
487{
488 UCHAR Answer;
489
490 /* Initialize PS/2 mouse port */
491 // Enable the port
493
494 /* Detect mouse presence by attempting a reset */
495 SendMouseCommand(0xFF);
496 Answer = ReadMouseData();
497 /* A "Resend" signal (0xFE) is sent if no mouse is attached */
498 if (Answer == 0xFE)
499 {
500 DPRINT1("No mouse present!\n");
501 }
502 else if (Answer != MOUSE_ACK)
503 {
504 DPRINT1("Mouse reset failure!\n");
505 }
506 else
507 {
508 /* Mouse present, try to completely enable it */
509
510 // FIXME: The following is temporary until
511 // this is moved into the mouse driver!!
512
513 /* Enable packet reporting */
514 SendMouseCommand(0xF4);
515 if (ReadMouseData() != MOUSE_ACK)
516 {
517 DPRINT1("Failed to enable mouse!\n");
518 }
519 else
520 {
521 /* Enable mouse interrupt and events */
523 }
524 }
525
526 /* No mouse driver available so far */
527 RegisterBiosInt32(0x33, NULL);
528
529 /* Set up the HW vector interrupts */
531}
532
534{
535 return TRUE;
536}
537
539{
540}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
VOID PicIRQComplete(BYTE IntNum)
Definition: bios32.c:816
CALLBACK16 BiosContext
Definition: bios32.c:45
VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
Definition: bios32.c:802
#define RegisterBiosInt32(IntNumber, IntHandler)
Definition: bios32p.h:34
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
#define MOUSE_ACK
Definition: i8042prt.h:285
#define STACK_FLAGS
Definition: int32.h:35
#define STACK_INT_NUM
Definition: int32.h:30
#define LOBYTE(W)
Definition: jmemdos.c:487
VOID MouseBios32Post(VOID)
Definition: moubios32.c:486
VOID BiosMousePs2Interface(LPWORD Stack)
Definition: moubios32.c:157
static DWORD OldIrqHandler
Definition: moubios32.c:34
static VOID BiosMouseEnable(VOID)
Definition: moubios32.c:100
#define MOUSE_IRQ_INT
Definition: moubios32.c:31
static VOID DisableMouseInt(VOID)
Definition: moubios32.c:48
static VOID WINAPI BiosMouseIrq(LPWORD Stack)
Definition: moubios32.c:127
static ULONG DeviceHandler
Definition: moubios32.c:44
BOOLEAN MouseBiosInitialize(VOID)
Definition: moubios32.c:533
VOID MouseBios32Cleanup(VOID)
Definition: moubios32.c:538
static VOID SendMouseCommand(UCHAR Command)
Definition: moubios32.c:81
static VOID EnableMouseInt(VOID)
Definition: moubios32.c:64
static BOOLEAN MouseEnabled
Definition: moubios32.c:33
static UCHAR ReadMouseData(VOID)
Definition: moubios32.c:92
static VOID BiosMouseDisable(VOID)
Definition: moubios32.c:115
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define LOWORD(l)
Definition: pedump.c:82
DWORD * PDWORD
Definition: pedump.c:68
BOOLEAN PS2PortQueueRead(BYTE PS2Port)
Definition: ps2.c:415
#define ControllerConfig
Definition: ps2.c:55
#define PS2_DATA_PORT
Definition: ps2.h:16
#define PS2_CONTROL_PORT
Definition: ps2.h:17
Definition: shell.h:41
VOID RunCallback16(IN PCALLBACK16 Context, IN ULONG FarPtr)
Definition: callback.c:93
#define EMULATOR_FLAG_CF
Definition: cpu.h:19
static BYTE Resolution
Definition: mouse.c:35
VOID IOWriteB(USHORT Port, UCHAR Buffer)
Definition: io.c:111
UCHAR IOReadB(USHORT Port)
Definition: io.c:64
uint16_t * LPWORD
Definition: typedefs.h:56
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
UCHAR WINAPI getBH(VOID)
Definition: registers.c:184
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
VOID WINAPI setDL(UCHAR)
Definition: registers.c:321
UCHAR WINAPI getAL(VOID)
Definition: registers.c:142
VOID WINAPI setAH(UCHAR)
Definition: registers.c:135
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
VOID WINAPI setBL(UCHAR)
Definition: registers.c:205
VOID WINAPI setBH(UCHAR)
Definition: registers.c:191
USHORT WINAPI getES(VOID)
Definition: registers.c:522
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
UCHAR WINAPI getBL(VOID)
Definition: registers.c:198
VOID WINAPI setCL(UCHAR)
Definition: registers.c:263
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define WINAPI
Definition: msvc.h:6
unsigned char UCHAR
Definition: xmlstorage.h:181
unsigned char BYTE
Definition: xxhash.c:193