|
|
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: // Disable Mouse
41: static void
42: mouse_15c20000(struct bregs *regs)
43: {
1.1.1.4 ! root 44: int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL);
1.1 root 45: if (ret)
46: set_code_invalid(regs, RET_ENEEDRESEND);
47: else
48: set_code_success(regs);
49: }
50:
51: // Enable Mouse
52: static void
53: mouse_15c20001(struct bregs *regs)
54: {
1.1.1.4 ! root 55: u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
1.1 root 56: if ((mouse_flags_2 & 0x80) == 0) {
57: set_code_invalid(regs, RET_ENOHANDLER);
58: return;
59: }
60:
1.1.1.3 root 61: int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
1.1 root 62: if (ret)
63: set_code_invalid(regs, RET_ENEEDRESEND);
64: else
65: set_code_success(regs);
66: }
67:
68: static void
69: mouse_15c200XX(struct bregs *regs)
70: {
71: set_code_unimplemented(regs, RET_EINVFUNCTION);
72: }
73:
74: // Disable/Enable Mouse
75: static void
76: mouse_15c200(struct bregs *regs)
77: {
78: switch (regs->bh) {
79: case 0x00: mouse_15c20000(regs); break;
80: case 0x01: mouse_15c20001(regs); break;
81: default: mouse_15c200XX(regs); break;
82: }
83: }
84:
85: // Reset Mouse
86: static void
87: mouse_15c201(struct bregs *regs)
88: {
89: u8 param[2];
1.1.1.3 root 90: int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
1.1 root 91: if (ret) {
92: set_code_invalid(regs, RET_ENEEDRESEND);
93: return;
94: }
95: regs->bl = param[0];
96: regs->bh = param[1];
97: set_code_success(regs);
98: }
99:
100: // Set Sample Rate
101: static void
102: mouse_15c202(struct bregs *regs)
103: {
104: static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
105: if (regs->bh >= ARRAY_SIZE(sample_rates)) {
106: set_code_invalid(regs, RET_EINVINPUT);
107: return;
108: }
109: u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
1.1.1.3 root 110: int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
1.1 root 111: if (ret)
112: set_code_invalid(regs, RET_ENEEDRESEND);
113: else
114: set_code_success(regs);
115: }
116:
117: // Set Resolution
118: static void
119: mouse_15c203(struct bregs *regs)
120: {
121: // BH:
122: // 0 = 25 dpi, 1 count per millimeter
123: // 1 = 50 dpi, 2 counts per millimeter
124: // 2 = 100 dpi, 4 counts per millimeter
125: // 3 = 200 dpi, 8 counts per millimeter
126: if (regs->bh >= 4) {
127: set_code_invalid(regs, RET_EINVINPUT);
128: return;
129: }
130: u8 param = regs->bh;
1.1.1.3 root 131: int ret = mouse_command(PSMOUSE_CMD_SETRES, ¶m);
1.1 root 132: if (ret)
133: set_code_invalid(regs, RET_ENEEDRESEND);
134: else
135: set_code_success(regs);
136: }
137:
138: // Get Device ID
139: static void
140: mouse_15c204(struct bregs *regs)
141: {
142: u8 param[2];
1.1.1.3 root 143: int ret = mouse_command(PSMOUSE_CMD_GETID, param);
1.1 root 144: if (ret) {
145: set_code_invalid(regs, RET_ENEEDRESEND);
146: return;
147: }
148: regs->bh = param[0];
149: set_code_success(regs);
150: }
151:
152: // Initialize Mouse
153: static void
154: mouse_15c205(struct bregs *regs)
155: {
156: if (regs->bh != 3) {
157: set_code_invalid(regs, RET_EINTERFACE);
158: return;
159: }
160: u16 ebda_seg = get_ebda_seg();
161: SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
162: SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
163:
164: // Reset Mouse
165: mouse_15c201(regs);
166: }
167:
168: // Return Status
169: static void
170: mouse_15c20600(struct bregs *regs)
171: {
172: u8 param[3];
1.1.1.3 root 173: int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
1.1 root 174: if (ret) {
175: set_code_invalid(regs, RET_ENEEDRESEND);
176: return;
177: }
178: regs->bl = param[0];
179: regs->cl = param[1];
180: regs->dl = param[2];
181: set_code_success(regs);
182: }
183:
184: // Set Scaling Factor to 1:1
185: static void
186: mouse_15c20601(struct bregs *regs)
187: {
1.1.1.3 root 188: int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
1.1 root 189: if (ret)
190: set_code_invalid(regs, RET_ENEEDRESEND);
191: else
192: set_code_success(regs);
193: }
194:
195: // Set Scaling Factor to 2:1
196: static void
197: mouse_15c20602(struct bregs *regs)
198: {
1.1.1.3 root 199: int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
1.1 root 200: if (ret)
201: set_code_invalid(regs, RET_ENEEDRESEND);
202: else
203: set_code_success(regs);
204: }
205:
206: static void
207: mouse_15c206XX(struct bregs *regs)
208: {
209: set_code_unimplemented(regs, RET_EINVFUNCTION);
210: }
211:
212: // Return Status & Set Scaling Factor...
213: static void
214: mouse_15c206(struct bregs *regs)
215: {
216: switch (regs->bh) {
217: case 0x00: mouse_15c20600(regs); break;
218: case 0x01: mouse_15c20601(regs); break;
219: case 0x02: mouse_15c20602(regs); break;
220: default: mouse_15c206XX(regs); break;
221: }
222: }
223:
224: // Set Mouse Handler Address
225: static void
226: mouse_15c207(struct bregs *regs)
227: {
228: struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
229: u16 ebda_seg = get_ebda_seg();
230: u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
231: if (! farptr.segoff) {
232: /* remove handler */
233: if ((mouse_flags_2 & 0x80) != 0) {
234: mouse_flags_2 &= ~0x80;
1.1.1.4 ! root 235: mouse_command(PSMOUSE_CMD_DISABLE, NULL);
1.1 root 236: }
237: } else {
238: /* install handler */
239: mouse_flags_2 |= 0x80;
240: }
241: SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
242: SET_EBDA2(ebda_seg, far_call_pointer, farptr);
243: set_code_success(regs);
244: }
245:
246: static void
247: mouse_15c2XX(struct bregs *regs)
248: {
249: set_code_unimplemented(regs, RET_EINVFUNCTION);
250: }
251:
252: void
253: handle_15c2(struct bregs *regs)
254: {
255: //debug_stub(regs);
256:
257: if (! CONFIG_MOUSE) {
258: set_code_invalid(regs, RET_EUNSUPPORTED);
259: return;
260: }
261:
262: switch (regs->al) {
263: case 0x00: mouse_15c200(regs); break;
264: case 0x01: mouse_15c201(regs); break;
265: case 0x02: mouse_15c202(regs); break;
266: case 0x03: mouse_15c203(regs); break;
267: case 0x04: mouse_15c204(regs); break;
268: case 0x05: mouse_15c205(regs); break;
269: case 0x06: mouse_15c206(regs); break;
270: case 0x07: mouse_15c207(regs); break;
271: default: mouse_15c2XX(regs); break;
272: }
273: }
274:
1.1.1.3 root 275: void noinline
1.1 root 276: process_mouse(u8 data)
277: {
278: if (!CONFIG_MOUSE)
279: return;
280:
281: u16 ebda_seg = get_ebda_seg();
282: u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1);
283: u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
284:
285: if (! (mouse_flags_2 & 0x80))
286: // far call handler not installed
287: return;
288:
289: u8 package_count = mouse_flags_2 & 0x07;
290: u8 index = mouse_flags_1 & 0x07;
291: SET_EBDA2(ebda_seg, mouse_data[index], data);
292:
293: if ((index+1) < package_count) {
294: mouse_flags_1++;
295: SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
296: return;
297: }
298:
299: u16 status = GET_EBDA2(ebda_seg, mouse_data[0]);
300: u16 X = GET_EBDA2(ebda_seg, mouse_data[1]);
301: u16 Y = GET_EBDA2(ebda_seg, mouse_data[2]);
302: SET_EBDA2(ebda_seg, mouse_flag1, 0);
303:
304: struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
1.1.1.3 root 305: dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
306: , status, X, Y, func.seg, func.offset);
1.1 root 307:
308: asm volatile(
1.1.1.3 root 309: "pushl %%ebp\n"
1.1 root 310: "sti\n"
311:
312: "pushl %0\n"
313: "pushw %w1\n" // status
314: "pushw %w2\n" // X
315: "pushw %w3\n" // Y
316: "pushw $0\n" // Z
317: "lcallw *8(%%esp)\n"
318: "addl $12, %%esp\n"
319:
320: "cli\n"
321: "cld\n"
1.1.1.3 root 322: "popl %%ebp"
323: : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
1.1 root 324: :
1.1.1.3 root 325: : "edi", "esi", "cc", "memory");
1.1 root 326: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.