|
|
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
12: #include "ps2port.h" // aux_command
13:
14: void
15: mouse_setup()
16: {
17: if (! CONFIG_MOUSE)
18: return;
19: dprintf(3, "init mouse\n");
20: // pointing device installed
21: SETBITS_BDA(equipment_list_flags, 0x04);
22: }
23:
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
30:
31: static int
32: disable_mouse(u16 ebda_seg)
33: {
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);
38:
39: return aux_command(PSMOUSE_CMD_DISABLE, NULL);
40: }
41:
42: // Disable Mouse
43: static void
44: mouse_15c20000(struct bregs *regs)
45: {
46: u16 ebda_seg = get_ebda_seg();
47: int ret = disable_mouse(ebda_seg);
48: if (ret)
49: set_code_invalid(regs, RET_ENEEDRESEND);
50: else
51: set_code_success(regs);
52: }
53:
54: // Enable Mouse
55: static void
56: mouse_15c20001(struct bregs *regs)
57: {
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);
62: return;
63: }
64:
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);
69:
70: int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
71: if (ret)
72: set_code_invalid(regs, RET_ENEEDRESEND);
73: else
74: set_code_success(regs);
75: }
76:
77: static void
78: mouse_15c200XX(struct bregs *regs)
79: {
80: set_code_unimplemented(regs, RET_EINVFUNCTION);
81: }
82:
83: // Disable/Enable Mouse
84: static void
85: mouse_15c200(struct bregs *regs)
86: {
87: switch (regs->bh) {
88: case 0x00: mouse_15c20000(regs); break;
89: case 0x01: mouse_15c20001(regs); break;
90: default: mouse_15c200XX(regs); break;
91: }
92: }
93:
94: // Reset Mouse
95: static void
96: mouse_15c201(struct bregs *regs)
97: {
98: u8 param[2];
99: int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param);
100: if (ret) {
101: set_code_invalid(regs, RET_ENEEDRESEND);
102: return;
103: }
104: regs->bl = param[0];
105: regs->bh = param[1];
106: set_code_success(regs);
107: }
108:
109: // Set Sample Rate
110: static void
111: mouse_15c202(struct bregs *regs)
112: {
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);
116: return;
117: }
118: u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
119: int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
120: if (ret)
121: set_code_invalid(regs, RET_ENEEDRESEND);
122: else
123: set_code_success(regs);
124: }
125:
126: // Set Resolution
127: static void
128: mouse_15c203(struct bregs *regs)
129: {
130: // BH:
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
135: if (regs->bh >= 4) {
136: set_code_invalid(regs, RET_EINVINPUT);
137: return;
138: }
139: u8 param = regs->bh;
140: int ret = aux_command(PSMOUSE_CMD_SETRES, ¶m);
141: if (ret)
142: set_code_invalid(regs, RET_ENEEDRESEND);
143: else
144: set_code_success(regs);
145: }
146:
147: // Get Device ID
148: static void
149: mouse_15c204(struct bregs *regs)
150: {
151: u8 param[2];
152: int ret = aux_command(PSMOUSE_CMD_GETID, param);
153: if (ret) {
154: set_code_invalid(regs, RET_ENEEDRESEND);
155: return;
156: }
157: regs->bh = param[0];
158: set_code_success(regs);
159: }
160:
161: // Initialize Mouse
162: static void
163: mouse_15c205(struct bregs *regs)
164: {
165: if (regs->bh != 3) {
166: set_code_invalid(regs, RET_EINTERFACE);
167: return;
168: }
169: u16 ebda_seg = get_ebda_seg();
170: SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
171: SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
172:
173: // Reset Mouse
174: mouse_15c201(regs);
175: }
176:
177: // Return Status
178: static void
179: mouse_15c20600(struct bregs *regs)
180: {
181: u8 param[3];
182: int ret = aux_command(PSMOUSE_CMD_GETINFO, param);
183: if (ret) {
184: set_code_invalid(regs, RET_ENEEDRESEND);
185: return;
186: }
187: regs->bl = param[0];
188: regs->cl = param[1];
189: regs->dl = param[2];
190: set_code_success(regs);
191: }
192:
193: // Set Scaling Factor to 1:1
194: static void
195: mouse_15c20601(struct bregs *regs)
196: {
197: int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL);
198: if (ret)
199: set_code_invalid(regs, RET_ENEEDRESEND);
200: else
201: set_code_success(regs);
202: }
203:
204: // Set Scaling Factor to 2:1
205: static void
206: mouse_15c20602(struct bregs *regs)
207: {
208: int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL);
209: if (ret)
210: set_code_invalid(regs, RET_ENEEDRESEND);
211: else
212: set_code_success(regs);
213: }
214:
215: static void
216: mouse_15c206XX(struct bregs *regs)
217: {
218: set_code_unimplemented(regs, RET_EINVFUNCTION);
219: }
220:
221: // Return Status & Set Scaling Factor...
222: static void
223: mouse_15c206(struct bregs *regs)
224: {
225: switch (regs->bh) {
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;
230: }
231: }
232:
233: // Set Mouse Handler Address
234: static void
235: mouse_15c207(struct bregs *regs)
236: {
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) {
241: /* remove handler */
242: if ((mouse_flags_2 & 0x80) != 0) {
243: mouse_flags_2 &= ~0x80;
244: disable_mouse(ebda_seg);
245: }
246: } else {
247: /* install handler */
248: mouse_flags_2 |= 0x80;
249: }
250: SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
251: SET_EBDA2(ebda_seg, far_call_pointer, farptr);
252: set_code_success(regs);
253: }
254:
255: static void
256: mouse_15c2XX(struct bregs *regs)
257: {
258: set_code_unimplemented(regs, RET_EINVFUNCTION);
259: }
260:
261: void
262: handle_15c2(struct bregs *regs)
263: {
264: //debug_stub(regs);
265:
266: if (! CONFIG_MOUSE) {
267: set_code_invalid(regs, RET_EUNSUPPORTED);
268: return;
269: }
270:
271: switch (regs->al) {
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;
281: }
282: }
283:
284: void
285: process_mouse(u8 data)
286: {
287: if (!CONFIG_MOUSE)
288: return;
289:
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);
293:
294: if (! (mouse_flags_2 & 0x80))
295: // far call handler not installed
296: return;
297:
298: u8 package_count = mouse_flags_2 & 0x07;
299: u8 index = mouse_flags_1 & 0x07;
300: SET_EBDA2(ebda_seg, mouse_data[index], data);
301:
302: if ((index+1) < package_count) {
303: mouse_flags_1++;
304: SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
305: return;
306: }
307:
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);
313:
314: struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
315:
316: asm volatile(
317: "sti\n"
318:
319: "pushl %0\n"
320: "pushw %w1\n" // status
321: "pushw %w2\n" // X
322: "pushw %w3\n" // Y
323: "pushw $0\n" // Z
324: "lcallw *8(%%esp)\n"
325: "addl $12, %%esp\n"
326:
327: "cli\n"
328: "cld\n"
329: :
330: : "r"(func.segoff), "r"(status), "r"(X), "r"(Y)
331: : "cc"
332: );
333: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.