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
34 return aux_command(PSMOUSE_CMD_DISABLE, NULL);
39 mouse_15c20000(struct bregs *regs)
41 int ret = disable_mouse();
43 set_code_invalid(regs, RET_ENEEDRESEND);
45 set_code_success(regs);
50 mouse_15c20001(struct bregs *regs)
52 u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
53 if ((mouse_flags_2 & 0x80) == 0) {
54 set_code_invalid(regs, RET_ENOHANDLER);
58 int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
60 set_code_invalid(regs, RET_ENEEDRESEND);
62 set_code_success(regs);
66 mouse_15c200XX(struct bregs *regs)
68 set_code_unimplemented(regs, RET_EINVFUNCTION);
71 // Disable/Enable Mouse
73 mouse_15c200(struct bregs *regs)
76 case 0x00: mouse_15c20000(regs); break;
77 case 0x01: mouse_15c20001(regs); break;
78 default: mouse_15c200XX(regs); break;
84 mouse_15c201(struct bregs *regs)
87 int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param);
89 set_code_invalid(regs, RET_ENEEDRESEND);
94 set_code_success(regs);
99 mouse_15c202(struct bregs *regs)
101 static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
102 if (regs->bh >= ARRAY_SIZE(sample_rates)) {
103 set_code_invalid(regs, RET_EINVINPUT);
106 u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
107 int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
109 set_code_invalid(regs, RET_ENEEDRESEND);
111 set_code_success(regs);
116 mouse_15c203(struct bregs *regs)
119 // 0 = 25 dpi, 1 count per millimeter
120 // 1 = 50 dpi, 2 counts per millimeter
121 // 2 = 100 dpi, 4 counts per millimeter
122 // 3 = 200 dpi, 8 counts per millimeter
124 set_code_invalid(regs, RET_EINVINPUT);
128 int ret = aux_command(PSMOUSE_CMD_SETRES, ¶m);
130 set_code_invalid(regs, RET_ENEEDRESEND);
132 set_code_success(regs);
137 mouse_15c204(struct bregs *regs)
140 int ret = aux_command(PSMOUSE_CMD_GETID, param);
142 set_code_invalid(regs, RET_ENEEDRESEND);
146 set_code_success(regs);
151 mouse_15c205(struct bregs *regs)
154 set_code_invalid(regs, RET_EINTERFACE);
157 u16 ebda_seg = get_ebda_seg();
158 SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
159 SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
167 mouse_15c20600(struct bregs *regs)
170 int ret = aux_command(PSMOUSE_CMD_GETINFO, param);
172 set_code_invalid(regs, RET_ENEEDRESEND);
178 set_code_success(regs);
181 // Set Scaling Factor to 1:1
183 mouse_15c20601(struct bregs *regs)
185 int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL);
187 set_code_invalid(regs, RET_ENEEDRESEND);
189 set_code_success(regs);
192 // Set Scaling Factor to 2:1
194 mouse_15c20602(struct bregs *regs)
196 int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL);
198 set_code_invalid(regs, RET_ENEEDRESEND);
200 set_code_success(regs);
204 mouse_15c206XX(struct bregs *regs)
206 set_code_unimplemented(regs, RET_EINVFUNCTION);
209 // Return Status & Set Scaling Factor...
211 mouse_15c206(struct bregs *regs)
214 case 0x00: mouse_15c20600(regs); break;
215 case 0x01: mouse_15c20601(regs); break;
216 case 0x02: mouse_15c20602(regs); break;
217 default: mouse_15c206XX(regs); break;
221 // Set Mouse Handler Address
223 mouse_15c207(struct bregs *regs)
225 struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
226 u16 ebda_seg = get_ebda_seg();
227 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
228 if (! farptr.segoff) {
230 if ((mouse_flags_2 & 0x80) != 0) {
231 mouse_flags_2 &= ~0x80;
235 /* install handler */
236 mouse_flags_2 |= 0x80;
238 SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
239 SET_EBDA2(ebda_seg, far_call_pointer, farptr);
240 set_code_success(regs);
244 mouse_15c2XX(struct bregs *regs)
246 set_code_unimplemented(regs, RET_EINVFUNCTION);
250 handle_15c2(struct bregs *regs)
254 if (! CONFIG_MOUSE) {
255 set_code_invalid(regs, RET_EUNSUPPORTED);
260 case 0x00: mouse_15c200(regs); break;
261 case 0x01: mouse_15c201(regs); break;
262 case 0x02: mouse_15c202(regs); break;
263 case 0x03: mouse_15c203(regs); break;
264 case 0x04: mouse_15c204(regs); break;
265 case 0x05: mouse_15c205(regs); break;
266 case 0x06: mouse_15c206(regs); break;
267 case 0x07: mouse_15c207(regs); break;
268 default: mouse_15c2XX(regs); break;
273 process_mouse(u8 data)
278 u16 ebda_seg = get_ebda_seg();
279 u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1);
280 u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
282 if (! (mouse_flags_2 & 0x80))
283 // far call handler not installed
286 u8 package_count = mouse_flags_2 & 0x07;
287 u8 index = mouse_flags_1 & 0x07;
288 SET_EBDA2(ebda_seg, mouse_data[index], data);
290 if ((index+1) < package_count) {
292 SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
296 //BX_DEBUG_INT74("int74_function: make_farcall=1\n");
297 u16 status = GET_EBDA2(ebda_seg, mouse_data[0]);
298 u16 X = GET_EBDA2(ebda_seg, mouse_data[1]);
299 u16 Y = GET_EBDA2(ebda_seg, mouse_data[2]);
300 SET_EBDA2(ebda_seg, mouse_flag1, 0);
302 struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
308 "pushw %w1\n" // status
318 : "r"(func.segoff), "r"(status), "r"(X), "r"(Y)