|
|
1.1 root 1: // 16bit code to handle mouse events.
2: //
3: // Copyright (C) 2008 Kevin O'Connor <[email protected]>
4: // Copyright (C) 2002 MandrakeSoft S.A.
5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
8: #include "biosvar.h" // GET_EBDA
9: #include "util.h" // debug_isr
10: #include "pic.h" // eoi_pic2
11: #include "bregs.h" // struct bregs
1.1.1.3 ! root 12: #include "ps2port.h" // ps2_mouse_command
! 13: #include "usb-hid.h" // usb_mouse_command
1.1 root 14:
15: void
1.1.1.2 root 16: mouse_setup(void)
1.1 root 17: {
18: if (! CONFIG_MOUSE)
19: return;
20: dprintf(3, "init mouse\n");
21: // pointing device installed
22: SETBITS_BDA(equipment_list_flags, 0x04);
23: }
24:
1.1.1.3 ! root 25: static inline int
! 26: mouse_command(int command, u8 *param)
! 27: {
! 28: if (usb_mouse_active())
! 29: return usb_mouse_command(command, param);
! 30: return ps2_mouse_command(command, param);
! 31: }
! 32:
1.1 root 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
39:
40: static int
41: disable_mouse(u16 ebda_seg)
42: {
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);
47:
1.1.1.3 ! root 48: return mouse_command(PSMOUSE_CMD_DISABLE, NULL);
1.1 root 49: }
50:
51: // Disable Mouse
52: static void
53: mouse_15c20000(struct bregs *regs)
54: {
55: u16 ebda_seg = get_ebda_seg();
56: int ret = disable_mouse(ebda_seg);
57: if (ret)
58: set_code_invalid(regs, RET_ENEEDRESEND);
59: else
60: set_code_success(regs);
61: }
62:
63: // Enable Mouse
64: static void
65: mouse_15c20001(struct bregs *regs)
66: {
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);
71: return;
72: }
73:
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);
78:
1.1.1.3 ! root 79: int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
1.1 root 80: if (ret)
81: set_code_invalid(regs, RET_ENEEDRESEND);
82: else
83: set_code_success(regs);
84: }
85:
86: static void
87: mouse_15c200XX(struct bregs *regs)
88: {
89: set_code_unimplemented(regs, RET_EINVFUNCTION);
90: }
91:
92: // Disable/Enable Mouse
93: static void
94: mouse_15c200(struct bregs *regs)
95: {
96: switch (regs->bh) {
97: case 0x00: mouse_15c20000(regs); break;
98: case 0x01: mouse_15c20001(regs); break;
99: default: mouse_15c200XX(regs); break;
100: }
101: }
102:
103: // Reset Mouse
104: static void
105: mouse_15c201(struct bregs *regs)
106: {
107: u8 param[2];
1.1.1.3 ! root 108: int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
1.1 root 109: if (ret) {
110: set_code_invalid(regs, RET_ENEEDRESEND);
111: return;
112: }
113: regs->bl = param[0];
114: regs->bh = param[1];
115: set_code_success(regs);
116: }
117:
118: // Set Sample Rate
119: static void
120: mouse_15c202(struct bregs *regs)
121: {
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);
125: return;
126: }
127: u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
1.1.1.3 ! root 128: int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
1.1 root 129: if (ret)
130: set_code_invalid(regs, RET_ENEEDRESEND);
131: else
132: set_code_success(regs);
133: }
134:
135: // Set Resolution
136: static void
137: mouse_15c203(struct bregs *regs)
138: {
139: // BH:
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
144: if (regs->bh >= 4) {
145: set_code_invalid(regs, RET_EINVINPUT);
146: return;
147: }
148: u8 param = regs->bh;
1.1.1.3 ! root 149: int ret = mouse_command(PSMOUSE_CMD_SETRES, ¶m);
1.1 root 150: if (ret)
151: set_code_invalid(regs, RET_ENEEDRESEND);
152: else
153: set_code_success(regs);
154: }
155:
156: // Get Device ID
157: static void
158: mouse_15c204(struct bregs *regs)
159: {
160: u8 param[2];
1.1.1.3 ! root 161: int ret = mouse_command(PSMOUSE_CMD_GETID, param);
1.1 root 162: if (ret) {
163: set_code_invalid(regs, RET_ENEEDRESEND);
164: return;
165: }
166: regs->bh = param[0];
167: set_code_success(regs);
168: }
169:
170: // Initialize Mouse
171: static void
172: mouse_15c205(struct bregs *regs)
173: {
174: if (regs->bh != 3) {
175: set_code_invalid(regs, RET_EINTERFACE);
176: return;
177: }
178: u16 ebda_seg = get_ebda_seg();
179: SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
180: SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
181:
182: // Reset Mouse
183: mouse_15c201(regs);
184: }
185:
186: // Return Status
187: static void
188: mouse_15c20600(struct bregs *regs)
189: {
190: u8 param[3];
1.1.1.3 ! root 191: int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
1.1 root 192: if (ret) {
193: set_code_invalid(regs, RET_ENEEDRESEND);
194: return;
195: }
196: regs->bl = param[0];
197: regs->cl = param[1];
198: regs->dl = param[2];
199: set_code_success(regs);
200: }
201:
202: // Set Scaling Factor to 1:1
203: static void
204: mouse_15c20601(struct bregs *regs)
205: {
1.1.1.3 ! root 206: int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
1.1 root 207: if (ret)
208: set_code_invalid(regs, RET_ENEEDRESEND);
209: else
210: set_code_success(regs);
211: }
212:
213: // Set Scaling Factor to 2:1
214: static void
215: mouse_15c20602(struct bregs *regs)
216: {
1.1.1.3 ! root 217: int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
1.1 root 218: if (ret)
219: set_code_invalid(regs, RET_ENEEDRESEND);
220: else
221: set_code_success(regs);
222: }
223:
224: static void
225: mouse_15c206XX(struct bregs *regs)
226: {
227: set_code_unimplemented(regs, RET_EINVFUNCTION);
228: }
229:
230: // Return Status & Set Scaling Factor...
231: static void
232: mouse_15c206(struct bregs *regs)
233: {
234: switch (regs->bh) {
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;
239: }
240: }
241:
242: // Set Mouse Handler Address
243: static void
244: mouse_15c207(struct bregs *regs)
245: {
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) {
250: /* remove handler */
251: if ((mouse_flags_2 & 0x80) != 0) {
252: mouse_flags_2 &= ~0x80;
253: disable_mouse(ebda_seg);
254: }
255: } else {
256: /* install handler */
257: mouse_flags_2 |= 0x80;
258: }
259: SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
260: SET_EBDA2(ebda_seg, far_call_pointer, farptr);
261: set_code_success(regs);
262: }
263:
264: static void
265: mouse_15c2XX(struct bregs *regs)
266: {
267: set_code_unimplemented(regs, RET_EINVFUNCTION);
268: }
269:
270: void
271: handle_15c2(struct bregs *regs)
272: {
273: //debug_stub(regs);
274:
275: if (! CONFIG_MOUSE) {
276: set_code_invalid(regs, RET_EUNSUPPORTED);
277: return;
278: }
279:
280: switch (regs->al) {
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;
290: }
291: }
292:
1.1.1.3 ! root 293: void noinline
1.1 root 294: process_mouse(u8 data)
295: {
296: if (!CONFIG_MOUSE)
297: return;
298:
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);
302:
303: if (! (mouse_flags_2 & 0x80))
304: // far call handler not installed
305: return;
306:
307: u8 package_count = mouse_flags_2 & 0x07;
308: u8 index = mouse_flags_1 & 0x07;
309: SET_EBDA2(ebda_seg, mouse_data[index], data);
310:
311: if ((index+1) < package_count) {
312: mouse_flags_1++;
313: SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
314: return;
315: }
316:
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);
321:
322: struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
1.1.1.3 ! root 323: dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
! 324: , status, X, Y, func.seg, func.offset);
1.1 root 325:
326: asm volatile(
1.1.1.3 ! root 327: "pushl %%ebp\n"
1.1 root 328: "sti\n"
329:
330: "pushl %0\n"
331: "pushw %w1\n" // status
332: "pushw %w2\n" // X
333: "pushw %w3\n" // Y
334: "pushw $0\n" // Z
335: "lcallw *8(%%esp)\n"
336: "addl $12, %%esp\n"
337:
338: "cli\n"
339: "cld\n"
1.1.1.3 ! root 340: "popl %%ebp"
! 341: : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
1.1 root 342: :
1.1.1.3 ! root 343: : "edi", "esi", "cc", "memory");
1.1 root 344: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.