Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / src / mouse.c
1 // 16bit code to handle mouse events.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
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" // ps2_mouse_command
13 #include "usb-hid.h" // usb_mouse_command
14
15 void
16 mouse_setup(void)
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
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
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 {
44     int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL);
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 {
55     u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
56     if ((mouse_flags_2 & 0x80) == 0) {
57         set_code_invalid(regs, RET_ENOHANDLER);
58         return;
59     }
60
61     int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
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];
90     int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
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]);
110     int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
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;
131     int ret = mouse_command(PSMOUSE_CMD_SETRES, &param);
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];
143     int ret = mouse_command(PSMOUSE_CMD_GETID, param);
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];
173     int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
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 {
188     int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
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 {
199     int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
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;
235             mouse_command(PSMOUSE_CMD_DISABLE, NULL);
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
275 void noinline
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);
305     dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
306             , status, X, Y, func.seg, func.offset);
307
308     asm volatile(
309         "pushl %%ebp\n"
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"
322         "popl %%ebp"
323         : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
324         :
325         : "edi", "esi", "cc", "memory");
326 }