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 GPLv3 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
17 if (! CONFIG_PS2_MOUSE)
19 dprintf(3, "init mouse\n");
20 // pointing device installed
21 SETBITS_BDA(equipment_list_flags, 0x04);
22 enable_hwirq(12, entry_74);
25 #define RET_SUCCESS 0x00
26 #define RET_EINVFUNCTION 0x01
27 #define RET_EINVINPUT 0x02
28 #define RET_EINTERFACE 0x03
29 #define RET_ENEEDRESEND 0x04
30 #define RET_ENOHANDLER 0x05
35 u8 ps2ctr = GET_EBDA(ps2ctr);
36 ps2ctr |= I8042_CTR_AUXDIS;
37 ps2ctr &= ~I8042_CTR_AUXINT;
38 SET_EBDA(ps2ctr, ps2ctr);
40 return aux_command(PSMOUSE_CMD_DISABLE, NULL);
45 mouse_15c20000(struct bregs *regs)
47 int ret = disable_mouse();
49 set_code_fail(regs, RET_ENEEDRESEND);
51 set_code_success(regs);
56 mouse_15c20001(struct bregs *regs)
58 u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
59 if ((mouse_flags_2 & 0x80) == 0) {
60 set_code_fail(regs, RET_ENOHANDLER);
64 u8 ps2ctr = GET_EBDA(ps2ctr);
65 ps2ctr &= ~I8042_CTR_AUXDIS;
66 ps2ctr |= I8042_CTR_AUXINT;
67 SET_EBDA(ps2ctr, ps2ctr);
69 int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
71 set_code_fail(regs, RET_ENEEDRESEND);
73 set_code_success(regs);
77 mouse_15c200XX(struct bregs *regs)
79 set_code_fail(regs, RET_EINVFUNCTION);
82 // Disable/Enable Mouse
84 mouse_15c200(struct bregs *regs)
87 case 0x00: mouse_15c20000(regs); break;
88 case 0x01: mouse_15c20001(regs); break;
89 default: mouse_15c200XX(regs); break;
95 mouse_15c201(struct bregs *regs)
98 int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param);
99 if (ret != 0 && ret != 2) {
100 set_code_fail(regs, RET_ENEEDRESEND);
105 set_code_success(regs);
110 mouse_15c202(struct bregs *regs)
112 static u8 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
113 if (regs->bh >= ARRAY_SIZE(sample_rates)) {
114 set_code_fail(regs, RET_EINVINPUT);
117 u8 mouse_data1 = GET_VAR(CS, sample_rates[regs->bh]);
118 int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
120 set_code_fail(regs, RET_ENEEDRESEND);
122 set_code_success(regs);
127 mouse_15c203(struct bregs *regs)
130 // 0 = 25 dpi, 1 count per millimeter
131 // 1 = 50 dpi, 2 counts per millimeter
132 // 2 = 100 dpi, 4 counts per millimeter
133 // 3 = 200 dpi, 8 counts per millimeter
135 set_code_fail(regs, RET_EINVINPUT);
139 int ret = aux_command(PSMOUSE_CMD_SETRES, ¶m);
141 set_code_fail(regs, RET_ENEEDRESEND);
143 set_code_success(regs);
148 mouse_15c204(struct bregs *regs)
151 int ret = aux_command(PSMOUSE_CMD_GETID, param);
153 set_code_fail(regs, RET_ENEEDRESEND);
157 set_code_success(regs);
162 mouse_15c205(struct bregs *regs)
165 set_code_fail(regs, RET_EINTERFACE);
168 SET_EBDA(mouse_flag1, 0x00);
169 SET_EBDA(mouse_flag2, regs->bh);
177 mouse_15c20600(struct bregs *regs)
180 int ret = aux_command(PSMOUSE_CMD_GETINFO, param);
182 set_code_fail(regs, RET_ENEEDRESEND);
188 set_code_success(regs);
191 // Set Scaling Factor to 1:1
193 mouse_15c20601(struct bregs *regs)
195 int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL);
197 set_code_fail(regs, RET_ENEEDRESEND);
199 set_code_success(regs);
202 // Set Scaling Factor to 2:1
204 mouse_15c20602(struct bregs *regs)
206 int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL);
208 set_code_fail(regs, RET_ENEEDRESEND);
210 set_code_success(regs);
214 mouse_15c206XX(struct bregs *regs)
216 set_code_fail(regs, RET_EINVFUNCTION);
219 // Return Status & Set Scaling Factor...
221 mouse_15c206(struct bregs *regs)
224 case 0x00: mouse_15c20600(regs); break;
225 case 0x01: mouse_15c20601(regs); break;
226 case 0x02: mouse_15c20602(regs); break;
227 default: mouse_15c206XX(regs); break;
231 // Set Mouse Handler Address
233 mouse_15c207(struct bregs *regs)
235 u32 farptr = (regs->es << 16) | regs->bx;
236 u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
239 if ((mouse_flags_2 & 0x80) != 0) {
240 mouse_flags_2 &= ~0x80;
244 /* install handler */
245 mouse_flags_2 |= 0x80;
247 SET_EBDA(mouse_flag2, mouse_flags_2);
248 SET_EBDA(far_call_pointer, farptr);
249 set_code_success(regs);
253 mouse_15c2XX(struct bregs *regs)
255 set_code_fail(regs, RET_EINVFUNCTION);
259 handle_15c2(struct bregs *regs)
263 if (! CONFIG_PS2_MOUSE) {
264 set_code_fail(regs, RET_EUNSUPPORTED);
271 case 0x00: mouse_15c200(regs); break;
272 case 0x01: mouse_15c201(regs); break;
273 case 0x02: mouse_15c202(regs); break;
274 case 0x03: mouse_15c203(regs); break;
275 case 0x04: mouse_15c204(regs); break;
276 case 0x05: mouse_15c205(regs); break;
277 case 0x06: mouse_15c206(regs); break;
278 case 0x07: mouse_15c207(regs); break;
279 default: mouse_15c2XX(regs); break;
286 u8 v = inb(PORT_PS2_STATUS);
287 if ((v & 0x21) != 0x21) {
288 dprintf(1, "int74 but no mouse data.\n");
291 v = inb(PORT_PS2_DATA);
293 u8 mouse_flags_1 = GET_EBDA(mouse_flag1);
294 u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
296 if (! (mouse_flags_2 & 0x80))
297 // far call handler not installed
300 u8 package_count = mouse_flags_2 & 0x07;
301 u8 index = mouse_flags_1 & 0x07;
302 SET_EBDA(mouse_data[index], v);
304 if ((index+1) < package_count) {
306 SET_EBDA(mouse_flag1, mouse_flags_1);
310 //BX_DEBUG_INT74("int74_function: make_farcall=1\n");
311 u16 status = GET_EBDA(mouse_data[0]);
312 u16 X = GET_EBDA(mouse_data[1]);
313 u16 Y = GET_EBDA(mouse_data[2]);
314 SET_EBDA(mouse_flag1, 0);
316 u32 func = GET_EBDA(far_call_pointer);
319 "pushw %w1\n" // status
326 : "+a" (func), "+b" (status), "+c" (X), "+d" (Y)
328 : "esi", "edi", "ebp", "cc"
332 // INT74h : PS/2 mouse hardware interrupt
336 debug_isr(DEBUG_ISR_74);
337 if (! CONFIG_PS2_MOUSE)