2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: VDM 32-bit compatible MOUSE.COM driver
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
18 #include "hardware/mouse.h"
19 #include "hardware/ps2.h"
20 #include "hardware/pic.h"
21 #include "hardware/video/vga.h"
24 #include "bios/bios.h"
25 #include "bios/bios32/bios32p.h"
28 #include "dos32krnl/dos.h"
30 /* PRIVATE VARIABLES **********************************************************/
32 // FIXME: Because I don't know a better place to store the string
33 // I temporarily put it in BIOS space. This need to be moved to a
34 // proper place when this driver is interfaced correctly with DOS.
35 #define COPYRIGHT_POINTER MAKELONG(0xE100, 0xF000)
36 static const CHAR MouseCopyright
[] = "ROS PS/2 16/32-bit Mouse Driver Compatible MS-MOUSE 6.26 Copyright (C) ReactOS Team 1996-2015";
38 // See FIXME from above.
39 #define VERSION_POINTER MAKELONG(0xE160, 0xF000)
42 #define MICKEYS_PER_CELL_HORIZ 8
43 #define MICKEYS_PER_CELL_VERT 16
45 static BOOLEAN DriverEnabled
= FALSE
;
46 static MOUSE_DRIVER_STATE DriverState
;
47 static DWORD OldIrqHandler
;
48 static DWORD OldIntHandler
;
50 /* PRIVATE FUNCTIONS **********************************************************/
52 static VOID
PaintMouseCursor(VOID
)
54 COORD Position
= DriverState
.Position
;
56 /* Apply the clipping rectangle */
57 if (Position
.X
< DriverState
.MinX
) Position
.X
= DriverState
.MinX
;
58 if (Position
.X
> DriverState
.MaxX
) Position
.X
= DriverState
.MaxX
;
59 if (Position
.Y
< DriverState
.MinY
) Position
.Y
= DriverState
.MinY
;
60 if (Position
.Y
> DriverState
.MaxY
) Position
.Y
= DriverState
.MaxY
;
62 if (Bda
->VideoMode
<= 3)
65 WORD CellX
= Position
.X
/ 8;
66 WORD CellY
= Position
.Y
/ 8;
67 DWORD VideoAddress
= TO_LINEAR(TEXT_VIDEO_SEG
, Bda
->VideoPage
* Bda
->VideoPageSize
);
69 EmulatorReadMemory(&EmulatorContext
,
71 + (CellY
* Bda
->ScreenColumns
+ CellX
) * sizeof(WORD
),
75 DriverState
.Character
= Character
;
76 Character
&= DriverState
.TextCursor
.ScreenMask
;
77 Character
^= DriverState
.TextCursor
.CursorMask
;
79 EmulatorWriteMemory(&EmulatorContext
,
81 + (CellY
* Bda
->ScreenColumns
+ CellX
) * sizeof(WORD
),
87 // TODO: NOT IMPLEMENTED
92 static VOID
EraseMouseCursor(VOID
)
94 COORD Position
= DriverState
.Position
;
96 /* Apply the clipping rectangle */
97 if (Position
.X
< DriverState
.MinX
) Position
.X
= DriverState
.MinX
;
98 if (Position
.X
> DriverState
.MaxX
) Position
.X
= DriverState
.MaxX
;
99 if (Position
.Y
< DriverState
.MinY
) Position
.Y
= DriverState
.MinY
;
100 if (Position
.Y
> DriverState
.MaxY
) Position
.Y
= DriverState
.MaxY
;
102 if (Bda
->VideoMode
<= 3)
104 WORD CellX
= Position
.X
/ 8;
105 WORD CellY
= Position
.Y
/ 8;
106 DWORD VideoAddress
= TO_LINEAR(TEXT_VIDEO_SEG
, Bda
->VideoPage
* Bda
->VideoPageSize
);
108 EmulatorWriteMemory(&EmulatorContext
,
110 + (CellY
* Bda
->ScreenColumns
+ CellX
) * sizeof(WORD
),
111 (LPVOID
)&DriverState
.Character
,
116 // TODO: NOT IMPLEMENTED
121 static VOID
ToMouseCoordinates(PCOORD Position
)
123 COORD Resolution
= VgaGetDisplayResolution();
124 WORD Width
= DriverState
.MaxX
- DriverState
.MinX
+ 1;
125 WORD Height
= DriverState
.MaxY
- DriverState
.MinY
+ 1;
127 if (!VgaGetDoubleVisionState(NULL
, NULL
))
133 Position
->X
= DriverState
.MinX
+ ((Position
->X
* Width
) / Resolution
.X
);
134 Position
->Y
= DriverState
.MinY
+ ((Position
->Y
* Height
) / Resolution
.Y
);
137 static VOID
FromMouseCoordinates(PCOORD Position
)
139 COORD Resolution
= VgaGetDisplayResolution();
140 WORD Width
= DriverState
.MaxX
- DriverState
.MinX
+ 1;
141 WORD Height
= DriverState
.MaxY
- DriverState
.MinY
+ 1;
143 if (!VgaGetDoubleVisionState(NULL
, NULL
))
149 Position
->X
= ((Position
->X
- DriverState
.MinX
) * Resolution
.X
) / Width
;
150 Position
->Y
= ((Position
->Y
- DriverState
.MinY
) * Resolution
.Y
) / Height
;
153 static VOID
CallMouseUserHandlers(USHORT CallMask
)
156 USHORT AX
, BX
, CX
, DX
, SI
, DI
;
157 COORD Position
= DriverState
.Position
;
159 ToMouseCoordinates(&Position
);
162 if ((DriverState
.Handler0
.CallMask
& CallMask
) != 0 &&
163 DriverState
.Handler0
.Callback
!= (ULONG
)NULL
)
166 * Set the parameters for the callback.
167 * NOTE: In text modes, the row and column will be reported
168 * as a multiple of the cell size, typically 8x8 pixels.
179 setBX(DriverState
.ButtonState
);
182 setSI(MICKEYS_PER_CELL_HORIZ
);
183 setDI(MICKEYS_PER_CELL_VERT
);
185 DPRINT("Calling Handler0 %04X:%04X with CallMask 0x%04X\n",
186 HIWORD(DriverState
.Handler0
.Callback
),
187 LOWORD(DriverState
.Handler0
.Callback
),
190 /* Call the callback */
191 RunCallback16(&DosContext
, DriverState
.Handler0
.Callback
);
201 for (i
= 0; i
< ARRAYSIZE(DriverState
.Handlers
); ++i
)
203 /* Call the suitable handlers */
204 if ((DriverState
.Handlers
[i
].CallMask
& CallMask
) != 0 &&
205 DriverState
.Handlers
[i
].Callback
!= (ULONG
)NULL
)
208 * Set the parameters for the callback.
209 * NOTE: In text modes, the row and column will be reported
210 * as a multiple of the cell size, typically 8x8 pixels.
221 setBX(DriverState
.ButtonState
);
224 setSI(MICKEYS_PER_CELL_HORIZ
);
225 setDI(MICKEYS_PER_CELL_VERT
);
227 DPRINT1("Calling Handler[%d] %04X:%04X with CallMask 0x%04X\n",
229 HIWORD(DriverState
.Handlers
[i
].Callback
),
230 LOWORD(DriverState
.Handlers
[i
].Callback
),
233 /* Call the callback */
234 RunCallback16(&DosContext
, DriverState
.Handlers
[i
].Callback
);
246 static inline VOID
DosUpdatePosition(PCOORD NewPosition
)
248 COORD Resolution
= VgaGetDisplayResolution();
250 /* Check for text mode */
251 if (!VgaGetDoubleVisionState(NULL
, NULL
))
257 if (DriverState
.ShowCount
> 0) EraseMouseCursor();
258 DriverState
.Position
= *NewPosition
;
259 if (DriverState
.ShowCount
> 0) PaintMouseCursor();
261 /* Call the mouse handlers */
262 CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format
265 static inline VOID
DosUpdateButtons(BYTE ButtonState
)
268 USHORT CallMask
= 0x0000; // We use MS MOUSE v1.0+ format
270 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++)
272 BOOLEAN OldState
= (DriverState
.ButtonState
>> i
) & 1;
273 BOOLEAN NewState
= (ButtonState
>> i
) & 1;
275 if (NewState
> OldState
)
278 DriverState
.PressCount
[i
]++;
279 DriverState
.LastPress
[i
] = DriverState
.Position
;
281 CallMask
|= (1 << (2 * i
+ 1));
283 else if (NewState
< OldState
)
286 DriverState
.ReleaseCount
[i
]++;
287 DriverState
.LastRelease
[i
] = DriverState
.Position
;
289 CallMask
|= (1 << (2 * i
+ 2));
293 DriverState
.ButtonState
= ButtonState
;
295 /* Call the mouse handlers */
296 CallMouseUserHandlers(CallMask
);
299 static VOID WINAPI
DosMouseIrq(LPWORD Stack
)
302 SHORT DeltaX
, DeltaY
;
306 /* Read the whole packet at once */
307 Flags
= IOReadB(PS2_DATA_PORT
);
309 DeltaX
= IOReadB(PS2_DATA_PORT
);
311 DeltaY
= IOReadB(PS2_DATA_PORT
);
313 /* Adjust the sign */
314 if (Flags
& MOUSE_X_SIGN
) DeltaX
= -DeltaX
;
315 if (Flags
& MOUSE_Y_SIGN
) DeltaY
= -DeltaY
;
317 /* Update the counters */
318 DriverState
.HorizCount
+= DeltaX
;
319 DriverState
.VertCount
+= DeltaY
;
322 * Get the absolute position directly from the mouse, this is the only
323 * way to perfectly synchronize the host and guest mouse pointer.
325 MouseGetDataFast(&Position
, &ButtonState
);
327 /* Call the update subroutines */
328 DosUpdatePosition(&Position
);
329 DosUpdateButtons(ButtonState
);
331 /* Complete the IRQ */
332 PicIRQComplete(Stack
);
335 static VOID WINAPI
DosMouseService(LPWORD Stack
)
344 DriverState
.ShowCount
= 0;
345 DriverState
.ButtonState
= 0;
347 /* Initialize the default clipping range */
348 DriverState
.MinX
= 0;
349 DriverState
.MaxX
= MOUSE_MAX_HORIZ
- 1;
350 DriverState
.MinY
= 0;
351 DriverState
.MaxY
= MOUSE_MAX_VERT
- 1;
353 /* Set the default text cursor */
354 DriverState
.TextCursor
.ScreenMask
= 0xFFFF; /* Display everything */
355 DriverState
.TextCursor
.CursorMask
= 0xFF00; /* ... but with inverted attributes */
357 /* Set the default graphics cursor */
358 DriverState
.GraphicsCursor
.HotSpot
.X
= 3;
359 DriverState
.GraphicsCursor
.HotSpot
.Y
= 1;
361 DriverState
.GraphicsCursor
.ScreenMask
[0] = 0xC3FF; // 1100001111111111
362 DriverState
.GraphicsCursor
.ScreenMask
[1] = 0xC0FF; // 1100000011111111
363 DriverState
.GraphicsCursor
.ScreenMask
[2] = 0xC07F; // 1100000001111111
364 DriverState
.GraphicsCursor
.ScreenMask
[3] = 0xC01F; // 1100000000011111
365 DriverState
.GraphicsCursor
.ScreenMask
[4] = 0xC00F; // 1100000000001111
366 DriverState
.GraphicsCursor
.ScreenMask
[5] = 0xC007; // 1100000000000111
367 DriverState
.GraphicsCursor
.ScreenMask
[6] = 0xC003; // 1100000000000011
368 DriverState
.GraphicsCursor
.ScreenMask
[7] = 0xC007; // 1100000000000111
369 DriverState
.GraphicsCursor
.ScreenMask
[8] = 0xC01F; // 1100000000011111
370 DriverState
.GraphicsCursor
.ScreenMask
[9] = 0xC01F; // 1100000000011111
371 DriverState
.GraphicsCursor
.ScreenMask
[10] = 0xC00F; // 1100000000001111
372 DriverState
.GraphicsCursor
.ScreenMask
[11] = 0xC60F; // 1100011000001111
373 DriverState
.GraphicsCursor
.ScreenMask
[12] = 0xFF07; // 1111111100000111
374 DriverState
.GraphicsCursor
.ScreenMask
[13] = 0xFF07; // 1111111100000111
375 DriverState
.GraphicsCursor
.ScreenMask
[14] = 0xFF87; // 1111111110000111
376 DriverState
.GraphicsCursor
.ScreenMask
[15] = 0xFFCF; // 1111111111001111
378 DriverState
.GraphicsCursor
.CursorMask
[0] = 0x0000; // 0000000000000000
379 DriverState
.GraphicsCursor
.CursorMask
[1] = 0x1C00; // 0001110000000000
380 DriverState
.GraphicsCursor
.CursorMask
[2] = 0x1F00; // 0001111100000000
381 DriverState
.GraphicsCursor
.CursorMask
[3] = 0x1F80; // 0001111110000000
382 DriverState
.GraphicsCursor
.CursorMask
[4] = 0x1FE0; // 0001111111100000
383 DriverState
.GraphicsCursor
.CursorMask
[5] = 0x1FF0; // 0001111111110000
384 DriverState
.GraphicsCursor
.CursorMask
[6] = 0x1FF8; // 0001111111111000
385 DriverState
.GraphicsCursor
.CursorMask
[7] = 0x1FE0; // 0001111111100000
386 DriverState
.GraphicsCursor
.CursorMask
[8] = 0x1FC0; // 0001111111000000
387 DriverState
.GraphicsCursor
.CursorMask
[9] = 0x1FC0; // 0001111111000000
388 DriverState
.GraphicsCursor
.CursorMask
[10] = 0x19E0; // 0001100111100000
389 DriverState
.GraphicsCursor
.CursorMask
[11] = 0x00E0; // 0000000011100000
390 DriverState
.GraphicsCursor
.CursorMask
[12] = 0x0070; // 0000000001110000
391 DriverState
.GraphicsCursor
.CursorMask
[13] = 0x0070; // 0000000001110000
392 DriverState
.GraphicsCursor
.CursorMask
[14] = 0x0030; // 0000000000110000
393 DriverState
.GraphicsCursor
.CursorMask
[15] = 0x0000; // 0000000000000000
395 /* Initialize the counters */
396 DriverState
.HorizCount
= DriverState
.VertCount
= 0;
398 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++)
400 DriverState
.PressCount
[i
] = DriverState
.ReleaseCount
[i
] = 0;
403 /* Return mouse information */
404 setAX(0xFFFF); // Hardware & driver installed
405 setBX(NUM_MOUSE_BUTTONS
);
410 /* Show Mouse Cursor */
413 DriverState
.ShowCount
++;
414 if (DriverState
.ShowCount
== 1) PaintMouseCursor();
419 /* Hide Mouse Cursor */
422 DriverState
.ShowCount
--;
423 if (DriverState
.ShowCount
== 0) EraseMouseCursor();
428 /* Return Position And Button Status */
431 COORD Position
= DriverState
.Position
;
432 ToMouseCoordinates(&Position
);
434 setBX(DriverState
.ButtonState
);
440 /* Position Mouse Cursor */
443 COORD Position
= { getCX(), getDX() };
444 FromMouseCoordinates(&Position
);
446 DriverState
.Position
= Position
;
450 /* Return Button Press Data */
453 WORD Button
= getBX();
454 COORD LastPress
= DriverState
.LastPress
[Button
];
455 ToMouseCoordinates(&LastPress
);
457 setAX(DriverState
.ButtonState
);
458 setBX(DriverState
.PressCount
[Button
]);
462 /* Reset the counter */
463 DriverState
.PressCount
[Button
] = 0;
468 /* Return Button Release Data */
471 WORD Button
= getBX();
472 COORD LastRelease
= DriverState
.LastRelease
[Button
];
473 ToMouseCoordinates(&LastRelease
);
475 setAX(DriverState
.ButtonState
);
476 setBX(DriverState
.ReleaseCount
[Button
]);
477 setCX(LastRelease
.X
);
478 setDX(LastRelease
.Y
);
480 /* Reset the counter */
481 DriverState
.ReleaseCount
[Button
] = 0;
487 /* Define Horizontal Cursor Range */
493 if (!VgaGetDoubleVisionState(NULL
, NULL
))
500 DPRINT("Setting mouse horizontal range: %u - %u\n", Min
, Max
);
501 DriverState
.MinX
= Min
;
502 DriverState
.MaxX
= Max
;
506 /* Define Vertical Cursor Range */
512 if (!VgaGetDoubleVisionState(NULL
, NULL
))
519 DPRINT("Setting mouse vertical range: %u - %u\n", Min
, Max
);
520 DriverState
.MinY
= Min
;
521 DriverState
.MaxY
= Max
;
525 /* Define Graphics Cursor */
528 PWORD MaskBitmap
= (PWORD
)SEG_OFF_TO_PTR(getES(), getDX());
530 DriverState
.GraphicsCursor
.HotSpot
.X
= getBX();
531 DriverState
.GraphicsCursor
.HotSpot
.Y
= getCX();
533 RtlCopyMemory(DriverState
.GraphicsCursor
.ScreenMask
,
535 sizeof(DriverState
.GraphicsCursor
.ScreenMask
));
537 RtlCopyMemory(DriverState
.GraphicsCursor
.CursorMask
,
539 sizeof(DriverState
.GraphicsCursor
.CursorMask
));
544 /* Define Text Cursor */
551 /* Define software cursor */
552 DriverState
.TextCursor
.ScreenMask
= getCX();
553 DriverState
.TextCursor
.CursorMask
= getDX();
555 else if (BX
== 0x0001)
557 /* Define hardware cursor */
558 DPRINT1("Defining hardware cursor is unimplemented\n");
560 // CX == start scan line
561 // DX == end scan line
565 DPRINT1("Invalid BX value 0x%04X\n", BX
);
571 /* Read Motion Counters */
574 setCX(DriverState
.HorizCount
);
575 setDX(DriverState
.VertCount
);
577 /* Reset the counters */
578 DriverState
.HorizCount
= DriverState
.VertCount
= 0;
583 /* Define Interrupt Subroutine Parameters, compatible MS MOUSE v1.0+ */
586 DriverState
.Handler0
.CallMask
= getCX();
587 DriverState
.Handler0
.Callback
= MAKELONG(getDX(), getES()); // Far pointer to the callback
588 DPRINT1("Define callback 0x%04X, %04X:%04X\n",
589 DriverState
.Handler0
.CallMask
,
590 HIWORD(DriverState
.Handler0
.Callback
),
591 LOWORD(DriverState
.Handler0
.Callback
));
595 /* Define Mickey/Pixel Ratio */
598 /* This call should be completely ignored */
602 /* Define Double-Speed Threshold */
605 DPRINT1("INT 33h, AH=13h: Mouse double-speed threshold is UNSUPPORTED\n");
609 /* Exchange Interrupt Subroutines, compatible MS MOUSE v3.0+ (see function 0x0C) */
612 USHORT OldCallMask
= DriverState
.Handler0
.CallMask
;
613 ULONG OldCallback
= DriverState
.Handler0
.Callback
;
615 DriverState
.Handler0
.CallMask
= getCX();
616 DriverState
.Handler0
.Callback
= MAKELONG(getDX(), getES()); // Far pointer to the callback
618 /* Return old callmask in CX and callback vector in ES:DX */
620 setES(HIWORD(OldCallback
));
621 setDX(LOWORD(OldCallback
));
626 /* Return Driver Storage Requirements */
629 setBX(sizeof(MOUSE_DRIVER_STATE
));
633 /* Save Driver State */
636 *((PMOUSE_DRIVER_STATE
)SEG_OFF_TO_PTR(getES(), getDX())) = DriverState
;
640 /* Restore Driver State */
643 DriverState
= *((PMOUSE_DRIVER_STATE
)SEG_OFF_TO_PTR(getES(), getDX()));
647 /* Set Alternate Mouse User Handler, compatible MS MOUSE v6.0+ */
651 * Up to three handlers can be defined by separate calls to this
652 * function, each with a different combination of shift states in
653 * the call mask; calling this function again with a call mask of
654 * 0000h undefines the specified handler (official documentation);
655 * specifying the same call mask and an address of 0000h:0000h
656 * undefines the handler (real life).
657 * See Ralf Brown: http://www.ctyme.com/intr/rb-5981.htm
658 * for more information.
662 USHORT CallMask
= getCX();
663 ULONG Callback
= MAKELONG(getDX(), getES()); // Far pointer to the callback
664 BOOLEAN Success
= FALSE
;
666 DPRINT1("Define v6.0+ callback 0x%04X, %04X:%04X\n",
667 CallMask
, HIWORD(Callback
), LOWORD(Callback
));
669 if (CallMask
== 0x0000)
672 * Find the handler entry corresponding to the given
673 * callback and undefine it.
675 for (i
= 0; i
< ARRAYSIZE(DriverState
.Handlers
); ++i
)
677 if (DriverState
.Handlers
[i
].Callback
== Callback
)
679 /* Found it, undefine the handler */
680 DriverState
.Handlers
[i
].CallMask
= 0x0000;
681 DriverState
.Handlers
[i
].Callback
= (ULONG
)NULL
;
687 else if (Callback
== (ULONG
)NULL
)
690 * Find the handler entry corresponding to the given
691 * callmask and undefine it.
693 for (i
= 0; i
< ARRAYSIZE(DriverState
.Handlers
); ++i
)
695 if (DriverState
.Handlers
[i
].CallMask
== CallMask
)
697 /* Found it, undefine the handler */
698 DriverState
.Handlers
[i
].CallMask
= 0x0000;
699 DriverState
.Handlers
[i
].Callback
= (ULONG
)NULL
;
708 * Try to find a handler entry corresponding to the given
709 * callmask to redefine it, otherwise find an empty handler
710 * entry and set the new handler in there.
713 USHORT EmptyHandler
= 0xFFFF; // Invalid handler
715 for (i
= 0; i
< ARRAYSIZE(DriverState
.Handlers
); ++i
)
717 /* Find the first empty handler */
718 if (EmptyHandler
== 0xFFFF &&
719 DriverState
.Handlers
[i
].CallMask
== 0x0000 &&
720 DriverState
.Handlers
[i
].Callback
== (ULONG
)NULL
)
725 if (DriverState
.Handlers
[i
].CallMask
== CallMask
)
727 /* Found it, redefine the handler */
728 DriverState
.Handlers
[i
].CallMask
= CallMask
;
729 DriverState
.Handlers
[i
].Callback
= Callback
;
736 * If we haven't found anything and we found
737 * an empty handler, set it.
739 if (!Success
&& EmptyHandler
!= 0xFFFF
740 /* && EmptyHandler < ARRAYSIZE(DriverState.Handlers) */)
742 DriverState
.Handlers
[EmptyHandler
].CallMask
= CallMask
;
743 DriverState
.Handlers
[EmptyHandler
].Callback
= Callback
;
748 /* If we failed, set error code */
749 if (!Success
) setAX(0xFFFF);
754 /* Return User Alternate Interrupt Vector, compatible MS MOUSE v6.0+ */
758 USHORT CallMask
= getCX();
760 BOOLEAN Success
= FALSE
;
763 * Find the handler entry corresponding to the given callmask.
765 for (i
= 0; i
< ARRAYSIZE(DriverState
.Handlers
); ++i
)
767 if (DriverState
.Handlers
[i
].CallMask
== CallMask
)
770 Callback
= DriverState
.Handlers
[i
].Callback
;
778 /* Return the callback vector in BX:DX */
779 setBX(HIWORD(Callback
));
780 setDX(LOWORD(Callback
));
784 /* We failed, set error code */
791 /* Set Mouse Sensitivity */
794 DPRINT1("INT 33h, AH=1Ah: Mouse sensitivity is UNSUPPORTED\n");
798 /* Return Mouse Sensitivity */
801 DPRINT1("INT 33h, AH=1Bh: Mouse sensitivity is UNSUPPORTED\n");
803 /* Return default values */
804 setBX(50); // Horizontal speed
805 setCX(50); // Vertical speed
806 setDX(50); // Double speed threshold
810 /* Disable Mouse Driver */
813 /* INT 33h vector before the mouse driver was first installed */
814 setES(HIWORD(OldIntHandler
));
815 setBX(LOWORD(OldIntHandler
));
821 /* Enable Mouse Driver */
832 * See: http://www.htl-steyr.ac.at/~morg/pcinfo/hardware/interrupts/inte3sq8.htm
833 * for detailed information and differences with respect to subfunction 0x00:
834 * http://www.htl-steyr.ac.at/~morg/pcinfo/hardware/interrupts/inte3j74.htm
839 DriverState
.ShowCount
= 0;
840 DriverState
.ButtonState
= 0;
842 /* Initialize the default clipping range */
843 DriverState
.MinX
= 0;
844 DriverState
.MaxX
= MOUSE_MAX_HORIZ
- 1;
845 DriverState
.MinY
= 0;
846 DriverState
.MaxY
= MOUSE_MAX_VERT
- 1;
848 /* Initialize the counters */
849 DriverState
.HorizCount
= DriverState
.VertCount
= 0;
851 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++)
853 DriverState
.PressCount
[i
] = DriverState
.ReleaseCount
[i
] = 0;
856 /* Return mouse information */
857 setAX(0xFFFF); // Hardware & driver installed
858 setBX(NUM_MOUSE_BUTTONS
);
863 /* Get Software Version, Mouse Type, and IRQ Number, compatible MS MOUSE v6.26+ */
866 setBX(MOUSE_VERSION
); // Version Number
868 // FIXME: To be determined at runtime!
869 setCH(0x04); // PS/2 Type
870 setCL(0x00); // PS/2 Interrupt
875 /* Return Pointer to Copyright String */
878 setES(HIWORD(COPYRIGHT_POINTER
));
879 setDI(LOWORD(COPYRIGHT_POINTER
));
883 /* Get Version String (pointer) */
887 * The format of the version "string" is:
888 * Offset Size Description
889 * 00h BYTE major version
890 * 01h BYTE minor version (BCD)
892 setES(HIWORD(VERSION_POINTER
));
893 setDI(LOWORD(VERSION_POINTER
));
899 DPRINT1("BIOS Function INT 33h, AX = 0x%04X NOT IMPLEMENTED\n", getAX());
904 /* PUBLIC FUNCTIONS ***********************************************************/
906 VOID
DosMouseEnable(VOID
)
910 DriverEnabled
= TRUE
;
912 /* Get the old IRQ handler */
913 OldIrqHandler
= ((PDWORD
)BaseAddress
)[MOUSE_IRQ_INT
];
915 /* Set the IRQ handler */
916 RegisterDosInt32(MOUSE_IRQ_INT
, DosMouseIrq
);
920 VOID
DosMouseDisable(VOID
)
924 /* Restore the old IRQ handler */
925 ((PDWORD
)BaseAddress
)[MOUSE_IRQ_INT
] = OldIrqHandler
;
927 DriverEnabled
= FALSE
;
931 VOID
DosMouseUpdatePosition(PCOORD NewPosition
)
933 SHORT DeltaX
= NewPosition
->X
- DriverState
.Position
.X
;
934 SHORT DeltaY
= NewPosition
->Y
- DriverState
.Position
.Y
;
936 if (!DriverEnabled
) return;
938 DriverState
.HorizCount
+= (DeltaX
* MICKEYS_PER_CELL_HORIZ
) / 8;
939 DriverState
.VertCount
+= (DeltaY
* MICKEYS_PER_CELL_VERT
) / 8;
941 if (DriverState
.ShowCount
> 0) EraseMouseCursor();
942 DriverState
.Position
= *NewPosition
;
943 if (DriverState
.ShowCount
> 0) PaintMouseCursor();
945 /* Call the mouse handlers */
946 // if (DeltaX || DeltaY)
947 CallMouseUserHandlers(0x0001); // We use MS MOUSE v1.0+ format
950 VOID
DosMouseUpdateButtons(WORD ButtonState
)
953 USHORT CallMask
= 0x0000; // We use MS MOUSE v1.0+ format
955 if (!DriverEnabled
) return;
957 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++)
959 BOOLEAN OldState
= (DriverState
.ButtonState
>> i
) & 1;
960 BOOLEAN NewState
= (ButtonState
>> i
) & 1;
962 if (NewState
> OldState
)
965 DriverState
.PressCount
[i
]++;
966 DriverState
.LastPress
[i
] = DriverState
.Position
;
968 CallMask
|= (1 << (2 * i
+ 1));
970 else if (NewState
< OldState
)
973 DriverState
.ReleaseCount
[i
]++;
974 DriverState
.LastRelease
[i
] = DriverState
.Position
;
976 CallMask
|= (1 << (2 * i
+ 2));
980 DriverState
.ButtonState
= ButtonState
;
982 /* Call the mouse handlers */
983 CallMouseUserHandlers(CallMask
);
986 BOOLEAN
DosMouseInitialize(VOID
)
988 /* Clear the state */
989 RtlZeroMemory(&DriverState
, sizeof(DriverState
));
991 /* Setup the version variable in BCD format, compatible MS-MOUSE */
992 Version
= (PWORD
)FAR_POINTER(VERSION_POINTER
);
993 *Version
= MAKEWORD(MOUSE_VERSION
/0x0100, MOUSE_VERSION
%0x0100);
995 /* Mouse Driver Copyright */
996 RtlCopyMemory(FAR_POINTER(COPYRIGHT_POINTER
), MouseCopyright
, sizeof(MouseCopyright
)-1);
998 /* Get the old mouse service interrupt handler */
999 OldIntHandler
= ((PDWORD
)BaseAddress
)[DOS_MOUSE_INTERRUPT
];
1001 /* Initialize the interrupt handler */
1002 RegisterDosInt32(DOS_MOUSE_INTERRUPT
, DosMouseService
);
1008 VOID
DosMouseCleanup(VOID
)
1010 /* Restore the old mouse service interrupt handler */
1011 ((PDWORD
)BaseAddress
)[DOS_MOUSE_INTERRUPT
] = OldIntHandler
;
1013 if (DriverState
.ShowCount
> 0) EraseMouseCursor();