1
// 16bit code to handle mouse events.
3
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4
// Copyright (C) 2002 MandrakeSoft S.A.
6
// This file may be distributed under the terms of the GNU LGPLv3 license.
8
#include "biosvar.h" // GET_EBDA
9
#include "bregs.h" // struct bregs
10
#include "hw/ps2port.h" // ps2_mouse_command
11
#include "hw/usb-hid.h" // usb_mouse_command
12
#include "output.h" // dprintf
13
#include "stacks.h" // stack_hop_back
14
#include "util.h" // mouse_init
21
dprintf(3, "init mouse\n");
22
// pointing device installed
23
set_equipment_flags(0x04, 0x04);
27
mouse_command(int command, u8 *param)
29
if (usb_mouse_active())
30
return usb_mouse_command(command, param);
31
return ps2_mouse_command(command, param);
34
#define RET_SUCCESS 0x00
35
#define RET_EINVFUNCTION 0x01
36
#define RET_EINVINPUT 0x02
37
#define RET_EINTERFACE 0x03
38
#define RET_ENEEDRESEND 0x04
39
#define RET_ENOHANDLER 0x05
43
mouse_15c20000(struct bregs *regs)
45
int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL);
47
set_code_invalid(regs, RET_ENEEDRESEND);
49
set_code_success(regs);
54
mouse_15c20001(struct bregs *regs)
56
u16 ebda_seg = get_ebda_seg();
57
u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2);
58
if ((mouse_flags_2 & 0x80) == 0) {
59
set_code_invalid(regs, RET_ENOHANDLER);
63
int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
65
set_code_invalid(regs, RET_ENEEDRESEND);
67
set_code_success(regs);
71
mouse_15c200XX(struct bregs *regs)
73
set_code_unimplemented(regs, RET_EINVFUNCTION);
76
// Disable/Enable Mouse
78
mouse_15c200(struct bregs *regs)
81
case 0x00: mouse_15c20000(regs); break;
82
case 0x01: mouse_15c20001(regs); break;
83
default: mouse_15c200XX(regs); break;
89
mouse_15c201(struct bregs *regs)
92
int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
94
set_code_invalid(regs, RET_ENEEDRESEND);
99
set_code_success(regs);
104
mouse_15c202(struct bregs *regs)
106
static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
107
if (regs->bh >= ARRAY_SIZE(sample_rates)) {
108
set_code_invalid(regs, RET_EINVINPUT);
111
u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
112
int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
114
set_code_invalid(regs, RET_ENEEDRESEND);
116
set_code_success(regs);
121
mouse_15c203(struct bregs *regs)
124
// 0 = 25 dpi, 1 count per millimeter
125
// 1 = 50 dpi, 2 counts per millimeter
126
// 2 = 100 dpi, 4 counts per millimeter
127
// 3 = 200 dpi, 8 counts per millimeter
129
set_code_invalid(regs, RET_EINVINPUT);
133
int ret = mouse_command(PSMOUSE_CMD_SETRES, ¶m);
135
set_code_invalid(regs, RET_ENEEDRESEND);
137
set_code_success(regs);
142
mouse_15c204(struct bregs *regs)
145
int ret = mouse_command(PSMOUSE_CMD_GETID, param);
147
set_code_invalid(regs, RET_ENEEDRESEND);
151
set_code_success(regs);
156
mouse_15c205(struct bregs *regs)
159
set_code_invalid(regs, RET_EINTERFACE);
162
u16 ebda_seg = get_ebda_seg();
163
SET_EBDA(ebda_seg, mouse_flag1, 0x00);
164
SET_EBDA(ebda_seg, mouse_flag2, regs->bh);
172
mouse_15c20600(struct bregs *regs)
175
int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
177
set_code_invalid(regs, RET_ENEEDRESEND);
183
set_code_success(regs);
186
// Set Scaling Factor to 1:1
188
mouse_15c20601(struct bregs *regs)
190
int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
192
set_code_invalid(regs, RET_ENEEDRESEND);
194
set_code_success(regs);
197
// Set Scaling Factor to 2:1
199
mouse_15c20602(struct bregs *regs)
201
int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
203
set_code_invalid(regs, RET_ENEEDRESEND);
205
set_code_success(regs);
209
mouse_15c206XX(struct bregs *regs)
211
set_code_unimplemented(regs, RET_EINVFUNCTION);
214
// Return Status & Set Scaling Factor...
216
mouse_15c206(struct bregs *regs)
219
case 0x00: mouse_15c20600(regs); break;
220
case 0x01: mouse_15c20601(regs); break;
221
case 0x02: mouse_15c20602(regs); break;
222
default: mouse_15c206XX(regs); break;
226
// Set Mouse Handler Address
228
mouse_15c207(struct bregs *regs)
230
struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
231
u16 ebda_seg = get_ebda_seg();
232
u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2);
233
if (! farptr.segoff) {
235
if ((mouse_flags_2 & 0x80) != 0) {
236
mouse_flags_2 &= ~0x80;
237
mouse_command(PSMOUSE_CMD_DISABLE, NULL);
240
/* install handler */
241
mouse_flags_2 |= 0x80;
243
SET_EBDA(ebda_seg, mouse_flag2, mouse_flags_2);
244
SET_EBDA(ebda_seg, far_call_pointer, farptr);
245
set_code_success(regs);
249
mouse_15c2XX(struct bregs *regs)
251
set_code_unimplemented(regs, RET_EINVFUNCTION);
255
handle_15c2(struct bregs *regs)
259
if (! CONFIG_MOUSE) {
260
set_code_invalid(regs, RET_EUNSUPPORTED);
265
case 0x00: mouse_15c200(regs); break;
266
case 0x01: mouse_15c201(regs); break;
267
case 0x02: mouse_15c202(regs); break;
268
case 0x03: mouse_15c203(regs); break;
269
case 0x04: mouse_15c204(regs); break;
270
case 0x05: mouse_15c205(regs); break;
271
case 0x06: mouse_15c206(regs); break;
272
case 0x07: mouse_15c207(regs); break;
273
default: mouse_15c2XX(regs); break;
278
invoke_mouse_handler(void)
282
if (need_hop_back()) {
283
stack_hop_back(invoke_mouse_handler, 0, 0);
287
u16 ebda_seg = get_ebda_seg();
288
u16 status = GET_EBDA(ebda_seg, mouse_data[0]);
289
u16 X = GET_EBDA(ebda_seg, mouse_data[1]);
290
u16 Y = GET_EBDA(ebda_seg, mouse_data[2]);
292
struct segoff_s func = GET_EBDA(ebda_seg, far_call_pointer);
293
dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
294
, status, X, Y, func.seg, func.offset);
301
"pushw %w1\n" // status
311
: "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
313
: "edi", "esi", "cc", "memory");
317
process_mouse(u8 data)
322
u16 ebda_seg = get_ebda_seg();
323
u8 mouse_flags_1 = GET_EBDA(ebda_seg, mouse_flag1);
324
u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2);
326
if (! (mouse_flags_2 & 0x80))
327
// far call handler not installed
330
u8 package_count = mouse_flags_2 & 0x07;
331
u8 index = mouse_flags_1 & 0x07;
332
SET_EBDA(ebda_seg, mouse_data[index], data);
334
if ((index+1) < package_count) {
336
SET_EBDA(ebda_seg, mouse_flag1, mouse_flags_1);
340
SET_EBDA(ebda_seg, mouse_flag1, 0);
341
invoke_mouse_handler();