VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS-new/ps2mouse.c@ 38699

Last change on this file since 38699 was 38699, checked in by vboxsync, 13 years ago

Converted system BIOS to Watcom C.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 KB
Line 
1/*
2 * Copyright (C) 2006-2011 Oracle Corporation
3 *
4 * This file is part of VirtualBox Open Source Edition (OSE), as
5 * available from http://www.virtualbox.org. This file is free software;
6 * you can redistribute it and/or modify it under the terms of the GNU
7 * General Public License (GPL) as published by the Free Software
8 * Foundation, in version 2 as it comes in the "COPYING" file of the
9 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11 * --------------------------------------------------------------------
12 *
13 * This code is based on:
14 *
15 * ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
16 *
17 * Copyright (C) 2002 MandrakeSoft S.A.
18 *
19 * MandrakeSoft S.A.
20 * 43, rue d'Aboukir
21 * 75002 Paris - France
22 * http://www.linux-mandrake.com/
23 * http://www.mandrakesoft.com/
24 *
25 * This library is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU Lesser General Public
27 * License as published by the Free Software Foundation; either
28 * version 2 of the License, or (at your option) any later version.
29 *
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 * Lesser General Public License for more details.
34 *
35 * You should have received a copy of the GNU Lesser General Public
36 * License along with this library; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38 *
39 */
40
41
42#include <stdint.h>
43#include "biosint.h"
44#include "inlines.h"
45
46
47#if DEBUG_INT15_MS
48# define BX_DEBUG_INT15_MS(...) BX_DEBUG(__VA_ARGS__)
49#else
50# define BX_DEBUG_INT15_MS(...)
51#endif
52
53#if DEBUG_INT74
54# define BX_DEBUG_INT74(...) BX_DEBUG(__VA_ARGS__)
55#else
56# define BX_DEBUG_INT74(...)
57#endif
58
59#if BX_USE_PS2_MOUSE
60
61static const char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n";
62
63uint8_t send_to_mouse_ctrl(uint8_t sendbyte)
64{
65 // wait for chance to write to ctrl
66 if ( inb(0x64) & 0x02 )
67 BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse");
68 outb(0x64, 0xD4);
69 outb(0x60, sendbyte);
70 return(0);
71}
72
73
74uint8_t get_mouse_data(uint8_t __far *data)
75{
76 uint8_t response;
77
78 //@todo: timeout?
79 while ((inb(0x64) & 0x21) != 0x21)
80 ;
81
82 response = inb(0x60);
83 *data = response;
84 return(0);
85}
86
87void set_kbd_command_byte(uint8_t command_byte)
88{
89 if (inb(0x64) & 0x02)
90 BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm");
91
92 outb(0x64, 0x60); // write command byte
93 outb(0x60, command_byte);
94}
95
96
97void BIOSCALL int74_function(volatile uint16_t make_farcall, volatile uint16_t Z,
98 volatile uint16_t Y, volatile uint16_t X, volatile uint16_t status)
99{
100 uint16_t ebda_seg=read_word(0x0040,0x000E);
101 uint8_t in_byte, index, package_count;
102 uint8_t mouse_flags_1, mouse_flags_2;
103
104 BX_DEBUG_INT74("entering int74_function\n");
105 make_farcall = 0;
106
107 in_byte = inb(0x64);
108 if ( (in_byte & 0x21) != 0x21 ) {
109 return;
110 }
111 in_byte = inb(0x60);
112 BX_DEBUG_INT74("int74: read byte %02x\n", in_byte);
113
114 mouse_flags_1 = read_byte(ebda_seg, 0x0026);
115 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
116
117 if ( (mouse_flags_2 & 0x80) != 0x80 ) {
118 return;
119 }
120
121 package_count = mouse_flags_2 & 0x07;
122 index = mouse_flags_1 & 0x07;
123 write_byte(ebda_seg, 0x28 + index, in_byte);
124
125 if ( index >= package_count ) {
126 BX_DEBUG_INT74("int74_function: make_farcall=1\n");
127 status = read_byte(ebda_seg, 0x0028 + 0);
128 X = read_byte(ebda_seg, 0x0028 + 1);
129 Y = read_byte(ebda_seg, 0x0028 + 2);
130 Z = 0;
131 mouse_flags_1 = 0;
132 // check if far call handler installed
133 if (mouse_flags_2 & 0x80)
134 make_farcall = 1;
135 }
136 else {
137 mouse_flags_1++;
138 }
139 write_byte(ebda_seg, 0x0026, mouse_flags_1);
140}
141
142void BIOSCALL int15_function_mouse(pusha_regs_t regs, uint16_t ES, uint16_t DS, volatile uint16_t FLAGS)
143{
144 uint16_t ebda_seg=read_word(0x0040,0x000E);
145 uint8_t mouse_flags_1, mouse_flags_2;
146 uint16_t mouse_driver_seg;
147 uint16_t mouse_driver_offset;
148 uint8_t mouse_cmd;
149 uint8_t ret, mouse_data1, mouse_data2, mouse_data3;
150
151 BX_DEBUG_INT15_MS("int15 AX=%04x\n",regs.u.r16.ax);
152
153 // Return Codes status in AH
154 // =========================
155 // 00: success
156 // 01: invalid subfunction (AL > 7)
157 // 02: invalid input value (out of allowable range)
158 // 03: interface error
159 // 04: resend command received from mouse controller,
160 // device driver should attempt command again
161 // 05: cannot enable mouse, since no far call has been installed
162 // 80/86: mouse service not implemented
163
164 if (regs.u.r8.al > 7) {
165 BX_DEBUG_INT15_MS("unsupported subfn\n");
166 // invalid function
167 SET_CF();
168 regs.u.r8.ah = 1;
169 return;
170 }
171
172 // Valid subfn; disable AUX input and IRQ12, assume no error
173 set_kbd_command_byte(0x65);
174 CLEAR_CF();
175 regs.u.r8.ah = 0;
176
177 switch (regs.u.r8.al) {
178 case 0: // Disable/Enable Mouse
179 BX_DEBUG_INT15_MS("case 0: ");
180 if (regs.u.r8.bh > 1) {
181 BX_DEBUG_INT15_MS("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh);
182 // invalid subfunction
183 SET_CF();
184 regs.u.r8.ah = 1;
185 break;
186 }
187 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
188 if ( (mouse_flags_2 & 0x80) == 0 ) {
189 BX_DEBUG_INT15_MS("INT 15h C2 Enable/Disable Mouse, no far call handler\n");
190 SET_CF();
191 regs.u.r8.ah = 5; // no far call installed
192 break;
193 }
194 if (regs.u.r8.bh == 0) {
195 BX_DEBUG_INT15_MS("Disable Mouse\n");
196 mouse_cmd = 0xF5; // disable mouse command
197 } else {
198 BX_DEBUG_INT15_MS("Enable Mouse\n");
199 mouse_cmd = 0xF4; // enable mouse command
200 }
201
202 ret = send_to_mouse_ctrl(mouse_cmd); // disable mouse command
203 if (ret == 0) {
204 ret = get_mouse_data(&mouse_data1);
205 if ( (ret == 0) || (mouse_data1 == 0xFA) ) {
206 // success
207 break;
208 }
209 }
210
211 // interface error
212 SET_CF();
213 regs.u.r8.ah = 3;
214 break;
215
216 case 5: // Initialize Mouse
217 // Valid package sizes are 1 to 8
218 if ( (regs.u.r8.bh < 1) || (regs.u.r8.bh > 8) ) {
219 SET_CF();
220 regs.u.r8.ah = 2; // invalid input
221 break;
222 }
223 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
224 mouse_flags_2 = (mouse_flags_2 & 0xf8) | (regs.u.r8.bh - 1);
225 write_byte(ebda_seg, 0x0027, mouse_flags_2);
226 // fall through!
227
228 case 1: // Reset Mouse
229 BX_DEBUG_INT15_MS("case 1 or 5:\n");
230 // clear current package byte index
231 mouse_flags_1 = read_byte(ebda_seg, 0x0026);
232 mouse_flags_1 = mouse_flags_1 & 0xf8;
233 write_byte(ebda_seg, 0x0026, mouse_flags_1);
234 ret = send_to_mouse_ctrl(0xFF); // reset mouse command
235 if (ret == 0) {
236 ret = get_mouse_data(&mouse_data3);
237 // if no mouse attached, it will return RESEND
238 if (mouse_data3 == 0xfe) {
239 SET_CF();
240 regs.u.r8.ah = 4; // resend
241 break;
242 }
243 if (mouse_data3 != 0xfa)
244 BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3);
245 if ( ret == 0 ) {
246 ret = get_mouse_data(&mouse_data1);
247 if ( ret == 0 ) {
248 ret = get_mouse_data(&mouse_data2);
249 if ( ret == 0 ) {
250 // success
251 regs.u.r8.bl = mouse_data1;
252 regs.u.r8.bh = mouse_data2;
253 break;
254 }
255 }
256 }
257 }
258
259 // interface error
260 SET_CF();
261 regs.u.r8.ah = 3;
262 break;
263
264 case 2: // Set Sample Rate
265 BX_DEBUG_INT15_MS("case 2:\n");
266 switch (regs.u.r8.bh) {
267 case 0: mouse_data1 = 10; break; // 10 reports/sec
268 case 1: mouse_data1 = 20; break; // 20 reports/sec
269 case 2: mouse_data1 = 40; break; // 40 reports/sec
270 case 3: mouse_data1 = 60; break; // 60 reports/sec
271 case 4: mouse_data1 = 80; break; // 80 reports/sec
272 case 5: mouse_data1 = 100; break; // 100 reports/sec (default)
273 case 6: mouse_data1 = 200; break; // 200 reports/sec
274 default: mouse_data1 = 0;
275 }
276 if (mouse_data1 > 0) {
277 ret = send_to_mouse_ctrl(0xF3); // set sample rate command
278 if (ret == 0) {
279 ret = get_mouse_data(&mouse_data2);
280 ret = send_to_mouse_ctrl(mouse_data1);
281 ret = get_mouse_data(&mouse_data2);
282 // success
283 } else {
284 // interface error
285 SET_CF();
286 regs.u.r8.ah = 3;
287 }
288 } else {
289 // invalid input
290 SET_CF();
291 regs.u.r8.ah = 2;
292 }
293 break;
294
295 case 3: // Set Resolution
296 BX_DEBUG_INT15_MS("case 3:\n");
297 // BX:
298 // 0 = 25 dpi, 1 count per millimeter
299 // 1 = 50 dpi, 2 counts per millimeter
300 // 2 = 100 dpi, 4 counts per millimeter
301 // 3 = 200 dpi, 8 counts per millimeter
302 if (regs.u.r8.bh < 4) {
303 ret = send_to_mouse_ctrl(0xE8); // set resolution command
304 if (ret == 0) {
305 ret = get_mouse_data(&mouse_data1);
306 if (mouse_data1 != 0xfa)
307 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
308 ret = send_to_mouse_ctrl(regs.u.r8.bh);
309 ret = get_mouse_data(&mouse_data1);
310 if (mouse_data1 != 0xfa)
311 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
312 // success
313 } else {
314 // interface error
315 SET_CF();
316 regs.u.r8.ah = 3;
317 }
318 } else {
319 // invalid input
320 SET_CF();
321 regs.u.r8.ah = 2;
322 }
323 break;
324
325 case 4: // Get Device ID
326 BX_DEBUG_INT15_MS("case 4:\n");
327 ret = send_to_mouse_ctrl(0xF2); // get mouse ID command
328 if (ret == 0) {
329 ret = get_mouse_data(&mouse_data1);
330 ret = get_mouse_data(&mouse_data2);
331 regs.u.r8.bh = mouse_data2;
332 // success
333 } else {
334 // interface error
335 SET_CF();
336 regs.u.r8.ah = 3;
337 }
338 break;
339
340 case 6: // Return Status & Set Scaling Factor...
341 BX_DEBUG_INT15_MS("case 6:\n");
342 switch (regs.u.r8.bh) {
343 case 0: // Return Status
344 ret = send_to_mouse_ctrl(0xE9); // get mouse info command
345 if (ret == 0) {
346 ret = get_mouse_data(&mouse_data1);
347 if (mouse_data1 != 0xfa)
348 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
349 if (ret == 0) {
350 ret = get_mouse_data(&mouse_data1);
351 if ( ret == 0 ) {
352 ret = get_mouse_data(&mouse_data2);
353 if ( ret == 0 ) {
354 ret = get_mouse_data(&mouse_data3);
355 if ( ret == 0 ) {
356 regs.u.r8.bl = mouse_data1;
357 regs.u.r8.cl = mouse_data2;
358 regs.u.r8.dl = mouse_data3;
359 // success
360 break;
361 }
362 }
363 }
364 }
365 }
366
367 // interface error
368 SET_CF();
369 regs.u.r8.ah = 3;
370 break;
371
372 case 1: // Set Scaling Factor to 1:1
373 case 2: // Set Scaling Factor to 2:1
374 if (regs.u.r8.bh == 1) {
375 ret = send_to_mouse_ctrl(0xE6);
376 } else {
377 ret = send_to_mouse_ctrl(0xE7);
378 }
379 if (ret == 0) {
380 get_mouse_data(&mouse_data1);
381 ret = (mouse_data1 != 0xFA);
382 }
383 if (ret != 0) {
384 // interface error
385 SET_CF();
386 regs.u.r8.ah = 3;
387 }
388 break;
389
390 default:
391 BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh);
392 // invalid subfunction
393 SET_CF();
394 regs.u.r8.ah = 1;
395 }
396 break;
397
398 case 7: // Set Mouse Handler Address
399 BX_DEBUG_INT15_MS("case 7:\n");
400 mouse_driver_seg = ES;
401 mouse_driver_offset = regs.u.r16.bx;
402 write_word(ebda_seg, 0x0022, mouse_driver_offset);
403 write_word(ebda_seg, 0x0024, mouse_driver_seg);
404 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
405 if (mouse_driver_offset == 0 && mouse_driver_seg == 0) {
406 /* remove handler */
407 if ( (mouse_flags_2 & 0x80) != 0 ) {
408 mouse_flags_2 &= ~0x80;
409 }
410 }
411 else {
412 /* install handler */
413 mouse_flags_2 |= 0x80;
414 }
415 write_byte(ebda_seg, 0x0027, mouse_flags_2);
416 break;
417
418 default:
419 BX_PANIC("INT 15h C2 default case entered\n");
420 // invalid subfunction
421 SET_CF();
422 regs.u.r8.ah = 1;
423 }
424 BX_DEBUG_INT15_MS("returning cf = %u, ah = %02x\n", (unsigned)GET_CF(), (unsigned)regs.u.r8.ah);
425 // Re-enable AUX input and IRQ12
426 set_kbd_command_byte(0x47);
427}
428#endif // BX_USE_PS2_MOUSE
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette