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" // aux_command
19 dprintf(3, "init mouse\n");
20 // pointing device installed
21 SETBITS_BDA(equipment_list_flags, 0x04);
24 #define RET_SUCCESS 0x00
25 #define RET_EINVFUNCTION 0x01
26 #define RET_EINVINPUT 0x02
27 #define RET_EINTERFACE 0x03
28 #define RET_ENEEDRESEND 0x04
29 #define RET_ENOHANDLER 0x05
32 disable_mouse(u16 ebda_seg)
34 u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
35 ps2ctr |= I8042_CTR_AUXDIS;
36 ps2ctr &= ~I8042_CTR_AUXINT;
37 SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
39 return aux_command(PSMOUSE_CMD_DISABLE, NULL);
44 mouse_15c20000(struct bregs *regs)
46 u16 ebda_seg = get_ebda_seg();
47 int ret = disable_mouse(ebda_seg);
49 set_code_invalid(regs, RET_ENEEDRESEND);
51 set_code_success(regs);
56 mouse_15c20001(struct bregs *regs)
58 u16 ebda_seg = get_ebda_seg();
59 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
60 if ((mouse_flags_2 & 0x80) == 0) {
61 set_code_invalid(regs, RET_ENOHANDLER);
65 u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
66 ps2ctr &= ~I8042_CTR_AUXDIS;
67 ps2ctr |= I8042_CTR_AUXINT;
68 SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
70 int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
72 set_code_invalid(regs, RET_ENEEDRESEND);
74 set_code_success(regs);
78 mouse_15c200XX(struct bregs *regs)
80 set_code_unimplemented(regs, RET_EINVFUNCTION);
83 // Disable/Enable Mouse
85 mouse_15c200(struct bregs *regs)
88 case 0x00: mouse_15c20000(regs); break;
89 case 0x01: mouse_15c20001(regs); break;
90 default: mouse_15c200XX(regs); break;
96 mouse_15c201(struct bregs *regs)
99 int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param);
101 set_code_invalid(regs, RET_ENEEDRESEND);
106 set_code_success(regs);
111 mouse_15c202(struct bregs *regs)
113 static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
114 if (regs->bh >= ARRAY_SIZE(sample_rates)) {
115 set_code_invalid(regs, RET_EINVINPUT);
118 u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
119 int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
121 set_code_invalid(regs, RET_ENEEDRESEND);
123 set_code_success(regs);
128 mouse_15c203(struct bregs *regs)
131 // 0 = 25 dpi, 1 count per millimeter
132 // 1 = 50 dpi, 2 counts per millimeter
133 // 2 = 100 dpi, 4 counts per millimeter
134 // 3 = 200 dpi, 8 counts per millimeter
136 set_code_invalid(regs, RET_EINVINPUT);
140 int ret = aux_command(PSMOUSE_CMD_SETRES, ¶m);
142 set_code_invalid(regs, RET_ENEEDRESEND);
144 set_code_success(regs);
149 mouse_15c204(struct bregs *regs)
152 int ret = aux_command(PSMOUSE_CMD_GETID, param);
154 set_code_invalid(regs, RET_ENEEDRESEND);
158 set_code_success(regs);
163 mouse_15c205(struct bregs *regs)
166 set_code_invalid(regs, RET_EINTERFACE);
169 u16 ebda_seg = get_ebda_seg();
170 SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
171 SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
179 mouse_15c20600(struct bregs *regs)
182 int ret = aux_command(PSMOUSE_CMD_GETINFO, param);
184 set_code_invalid(regs, RET_ENEEDRESEND);
190 set_code_success(regs);
193 // Set Scaling Factor to 1:1
195 mouse_15c20601(struct bregs *regs)
197 int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL);
199 set_code_invalid(regs, RET_ENEEDRESEND);
201 set_code_success(regs);
204 // Set Scaling Factor to 2:1
206 mouse_15c20602(struct bregs *regs)
208 int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL);
210 set_code_invalid(regs, RET_ENEEDRESEND);
212 set_code_success(regs);
216 mouse_15c206XX(struct bregs *regs)
218 set_code_unimplemented(regs, RET_EINVFUNCTION);
221 // Return Status & Set Scaling Factor...
223 mouse_15c206(struct bregs *regs)
226 case 0x00: mouse_15c20600(regs); break;
227 case 0x01: mouse_15c20601(regs); break;
228 case 0x02: mouse_15c20602(regs); break;
229 default: mouse_15c206XX(regs); break;
233 // Set Mouse Handler Address
235 mouse_15c207(struct bregs *regs)
237 struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
238 u16 ebda_seg = get_ebda_seg();
239 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
240 if (! farptr.segoff) {
242 if ((mouse_flags_2 & 0x80) != 0) {
243 mouse_flags_2 &= ~0x80;
244 disable_mouse(ebda_seg);
247 /* install handler */
248 mouse_flags_2 |= 0x80;
250 SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
251 SET_EBDA2(ebda_seg, far_call_pointer, farptr);
252 set_code_success(regs);
256 mouse_15c2XX(struct bregs *regs)
258 set_code_unimplemented(regs, RET_EINVFUNCTION);
262 handle_15c2(struct bregs *regs)
266 if (! CONFIG_MOUSE) {
267 set_code_invalid(regs, RET_EUNSUPPORTED);
272 case 0x00: mouse_15c200(regs); break;
273 case 0x01: mouse_15c201(regs); break;
274 case 0x02: mouse_15c202(regs); break;
275 case 0x03: mouse_15c203(regs); break;
276 case 0x04: mouse_15c204(regs); break;
277 case 0x05: mouse_15c205(regs); break;
278 case 0x06: mouse_15c206(regs); break;
279 case 0x07: mouse_15c207(regs); break;
280 default: mouse_15c2XX(regs); break;
285 process_mouse(u8 data)
290 u16 ebda_seg = get_ebda_seg();
291 u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1);
292 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
294 if (! (mouse_flags_2 & 0x80))
295 // far call handler not installed
298 u8 package_count = mouse_flags_2 & 0x07;
299 u8 index = mouse_flags_1 & 0x07;
300 SET_EBDA2(ebda_seg, mouse_data[index], data);
302 if ((index+1) < package_count) {
304 SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
308 //BX_DEBUG_INT74("int74_function: make_farcall=1\n");
309 u16 status = GET_EBDA2(ebda_seg, mouse_data[0]);
310 u16 X = GET_EBDA2(ebda_seg, mouse_data[1]);
311 u16 Y = GET_EBDA2(ebda_seg, mouse_data[2]);
312 SET_EBDA2(ebda_seg, mouse_flag1, 0);
314 struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
320 "pushw %w1\n" // status
330 : "r"(func.segoff), "r"(status), "r"(X), "r"(Y)