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