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 "util.h" // debug_isr
10 #include "pic.h" // eoi_pic2
11 #include "bregs.h" // struct bregs
12 #include "ps2port.h" // ps2_mouse_command
13 #include "usb-hid.h" // usb_mouse_command
20 dprintf(3, "init mouse\n");
21 // pointing device installed
22 SETBITS_BDA(equipment_list_flags, 0x04);
26 mouse_command(int command, u8 *param)
28 if (usb_mouse_active())
29 return usb_mouse_command(command, param);
30 return ps2_mouse_command(command, param);
33 #define RET_SUCCESS 0x00
34 #define RET_EINVFUNCTION 0x01
35 #define RET_EINVINPUT 0x02
36 #define RET_EINTERFACE 0x03
37 #define RET_ENEEDRESEND 0x04
38 #define RET_ENOHANDLER 0x05
41 disable_mouse(u16 ebda_seg)
43 u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
44 ps2ctr |= I8042_CTR_AUXDIS;
45 ps2ctr &= ~I8042_CTR_AUXINT;
46 SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
48 return mouse_command(PSMOUSE_CMD_DISABLE, NULL);
53 mouse_15c20000(struct bregs *regs)
55 u16 ebda_seg = get_ebda_seg();
56 int ret = disable_mouse(ebda_seg);
58 set_code_invalid(regs, RET_ENEEDRESEND);
60 set_code_success(regs);
65 mouse_15c20001(struct bregs *regs)
67 u16 ebda_seg = get_ebda_seg();
68 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
69 if ((mouse_flags_2 & 0x80) == 0) {
70 set_code_invalid(regs, RET_ENOHANDLER);
74 u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
75 ps2ctr &= ~I8042_CTR_AUXDIS;
76 ps2ctr |= I8042_CTR_AUXINT;
77 SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
79 int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
81 set_code_invalid(regs, RET_ENEEDRESEND);
83 set_code_success(regs);
87 mouse_15c200XX(struct bregs *regs)
89 set_code_unimplemented(regs, RET_EINVFUNCTION);
92 // Disable/Enable Mouse
94 mouse_15c200(struct bregs *regs)
97 case 0x00: mouse_15c20000(regs); break;
98 case 0x01: mouse_15c20001(regs); break;
99 default: mouse_15c200XX(regs); break;
105 mouse_15c201(struct bregs *regs)
108 int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
110 set_code_invalid(regs, RET_ENEEDRESEND);
115 set_code_success(regs);
120 mouse_15c202(struct bregs *regs)
122 static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
123 if (regs->bh >= ARRAY_SIZE(sample_rates)) {
124 set_code_invalid(regs, RET_EINVINPUT);
127 u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
128 int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
130 set_code_invalid(regs, RET_ENEEDRESEND);
132 set_code_success(regs);
137 mouse_15c203(struct bregs *regs)
140 // 0 = 25 dpi, 1 count per millimeter
141 // 1 = 50 dpi, 2 counts per millimeter
142 // 2 = 100 dpi, 4 counts per millimeter
143 // 3 = 200 dpi, 8 counts per millimeter
145 set_code_invalid(regs, RET_EINVINPUT);
149 int ret = mouse_command(PSMOUSE_CMD_SETRES, ¶m);
151 set_code_invalid(regs, RET_ENEEDRESEND);
153 set_code_success(regs);
158 mouse_15c204(struct bregs *regs)
161 int ret = mouse_command(PSMOUSE_CMD_GETID, param);
163 set_code_invalid(regs, RET_ENEEDRESEND);
167 set_code_success(regs);
172 mouse_15c205(struct bregs *regs)
175 set_code_invalid(regs, RET_EINTERFACE);
178 u16 ebda_seg = get_ebda_seg();
179 SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
180 SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
188 mouse_15c20600(struct bregs *regs)
191 int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
193 set_code_invalid(regs, RET_ENEEDRESEND);
199 set_code_success(regs);
202 // Set Scaling Factor to 1:1
204 mouse_15c20601(struct bregs *regs)
206 int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
208 set_code_invalid(regs, RET_ENEEDRESEND);
210 set_code_success(regs);
213 // Set Scaling Factor to 2:1
215 mouse_15c20602(struct bregs *regs)
217 int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
219 set_code_invalid(regs, RET_ENEEDRESEND);
221 set_code_success(regs);
225 mouse_15c206XX(struct bregs *regs)
227 set_code_unimplemented(regs, RET_EINVFUNCTION);
230 // Return Status & Set Scaling Factor...
232 mouse_15c206(struct bregs *regs)
235 case 0x00: mouse_15c20600(regs); break;
236 case 0x01: mouse_15c20601(regs); break;
237 case 0x02: mouse_15c20602(regs); break;
238 default: mouse_15c206XX(regs); break;
242 // Set Mouse Handler Address
244 mouse_15c207(struct bregs *regs)
246 struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
247 u16 ebda_seg = get_ebda_seg();
248 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
249 if (! farptr.segoff) {
251 if ((mouse_flags_2 & 0x80) != 0) {
252 mouse_flags_2 &= ~0x80;
253 disable_mouse(ebda_seg);
256 /* install handler */
257 mouse_flags_2 |= 0x80;
259 SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
260 SET_EBDA2(ebda_seg, far_call_pointer, farptr);
261 set_code_success(regs);
265 mouse_15c2XX(struct bregs *regs)
267 set_code_unimplemented(regs, RET_EINVFUNCTION);
271 handle_15c2(struct bregs *regs)
275 if (! CONFIG_MOUSE) {
276 set_code_invalid(regs, RET_EUNSUPPORTED);
281 case 0x00: mouse_15c200(regs); break;
282 case 0x01: mouse_15c201(regs); break;
283 case 0x02: mouse_15c202(regs); break;
284 case 0x03: mouse_15c203(regs); break;
285 case 0x04: mouse_15c204(regs); break;
286 case 0x05: mouse_15c205(regs); break;
287 case 0x06: mouse_15c206(regs); break;
288 case 0x07: mouse_15c207(regs); break;
289 default: mouse_15c2XX(regs); break;
294 process_mouse(u8 data)
299 u16 ebda_seg = get_ebda_seg();
300 u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1);
301 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
303 if (! (mouse_flags_2 & 0x80))
304 // far call handler not installed
307 u8 package_count = mouse_flags_2 & 0x07;
308 u8 index = mouse_flags_1 & 0x07;
309 SET_EBDA2(ebda_seg, mouse_data[index], data);
311 if ((index+1) < package_count) {
313 SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
317 u16 status = GET_EBDA2(ebda_seg, mouse_data[0]);
318 u16 X = GET_EBDA2(ebda_seg, mouse_data[1]);
319 u16 Y = GET_EBDA2(ebda_seg, mouse_data[2]);
320 SET_EBDA2(ebda_seg, mouse_flag1, 0);
322 struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
323 dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
324 , status, X, Y, func.seg, func.offset);
331 "pushw %w1\n" // status
341 : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
343 : "edi", "esi", "cc", "memory");