]> Git Repo - qemu.git/blame - hw/adb.c
cmos init for IDE (Ben Pfaf)
[qemu.git] / hw / adb.c
CommitLineData
267002cd
FB
1/*
2 * QEMU ADB support
3 *
4 * Copyright (c) 2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include "vl.h"
25
26/* ADB commands */
27#define ADB_BUSRESET 0x00
28#define ADB_FLUSH 0x01
29#define ADB_WRITEREG 0x08
30#define ADB_READREG 0x0c
31
32/* ADB device commands */
33#define ADB_CMD_SELF_TEST 0xff
34#define ADB_CMD_CHANGE_ID 0xfe
35#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
36#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
37
38/* ADB default device IDs (upper 4 bits of ADB command byte) */
39#define ADB_DONGLE 1
40#define ADB_KEYBOARD 2
41#define ADB_MOUSE 3
42#define ADB_TABLET 4
43#define ADB_MODEM 5
44#define ADB_MISC 7
45
bec9d989
FB
46/* error codes */
47#define ADB_RET_NOTPRESENT (-2)
48
e2733d20 49int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
267002cd
FB
50{
51 ADBDevice *d;
52 int devaddr, cmd, i;
267002cd 53
819e712b 54 cmd = buf[0] & 0xf;
bec9d989
FB
55 if (cmd == ADB_BUSRESET) {
56 for(i = 0; i < s->nb_devices; i++) {
57 d = &s->devices[i];
58 if (d->devreset) {
59 d->devreset(d);
60 }
61 }
62 return 0;
267002cd 63 }
bec9d989 64 devaddr = buf[0] >> 4;
267002cd
FB
65 for(i = 0; i < s->nb_devices; i++) {
66 d = &s->devices[i];
67 if (d->devaddr == devaddr) {
e2733d20 68 return d->devreq(d, obuf, buf, len);
267002cd
FB
69 }
70 }
bec9d989 71 return ADB_RET_NOTPRESENT;
e2733d20
FB
72}
73
bec9d989 74/* XXX: move that to cuda ? */
e2733d20
FB
75int adb_poll(ADBBusState *s, uint8_t *obuf)
76{
77 ADBDevice *d;
78 int olen, i;
bec9d989 79 uint8_t buf[1];
e2733d20
FB
80
81 olen = 0;
82 for(i = 0; i < s->nb_devices; i++) {
83 if (s->poll_index >= s->nb_devices)
84 s->poll_index = 0;
85 d = &s->devices[s->poll_index];
bec9d989
FB
86 buf[0] = ADB_READREG | (d->devaddr << 4);
87 olen = adb_request(s, obuf + 1, buf, 1);
88 /* if there is data, we poll again the same device */
89 if (olen > 0) {
90 obuf[0] = buf[0];
91 olen++;
e2733d20 92 break;
bec9d989
FB
93 }
94 s->poll_index++;
e2733d20
FB
95 }
96 return olen;
267002cd
FB
97}
98
99ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
e2733d20 100 ADBDeviceRequest *devreq,
bec9d989 101 ADBDeviceReset *devreset,
267002cd
FB
102 void *opaque)
103{
104 ADBDevice *d;
105 if (s->nb_devices >= MAX_ADB_DEVICES)
106 return NULL;
107 d = &s->devices[s->nb_devices++];
108 d->bus = s;
109 d->devaddr = devaddr;
e2733d20 110 d->devreq = devreq;
bec9d989 111 d->devreset = devreset;
267002cd
FB
112 d->opaque = opaque;
113 return d;
114}
115
116/***************************************************************/
117/* Keyboard ADB device */
118
e2733d20
FB
119typedef struct KBDState {
120 uint8_t data[128];
121 int rptr, wptr, count;
122} KBDState;
123
267002cd
FB
124static const uint8_t pc_to_adb_keycode[256] = {
125 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
126 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
127 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
128 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
129 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
e2733d20 130 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
267002cd
FB
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20
FB
133 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
138 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
267002cd 139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20 140 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267002cd
FB
141};
142
143static void adb_kbd_put_keycode(void *opaque, int keycode)
144{
267002cd 145 ADBDevice *d = opaque;
e2733d20
FB
146 KBDState *s = d->opaque;
147
148 if (s->count < sizeof(s->data)) {
149 s->data[s->wptr] = keycode;
150 if (++s->wptr == sizeof(s->data))
151 s->wptr = 0;
152 s->count++;
267002cd
FB
153 }
154}
155
e2733d20 156static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
267002cd 157{
e2733d20
FB
158 static int ext_keycode;
159 KBDState *s = d->opaque;
160 int adb_keycode, keycode;
161 int olen;
162
163 olen = 0;
164 for(;;) {
165 if (s->count == 0)
166 break;
167 keycode = s->data[s->rptr];
168 if (++s->rptr == sizeof(s->data))
169 s->rptr = 0;
170 s->count--;
171
172 if (keycode == 0xe0) {
173 ext_keycode = 1;
174 } else {
175 if (ext_keycode)
176 adb_keycode = pc_to_adb_keycode[keycode | 0x80];
177 else
178 adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
bec9d989
FB
179 obuf[0] = adb_keycode | (keycode & 0x80);
180 /* NOTE: could put a second keycode if needed */
181 obuf[1] = 0xff;
182 olen = 2;
e2733d20
FB
183 ext_keycode = 0;
184 break;
185 }
186 }
187 return olen;
188}
189
190static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
191 const uint8_t *buf, int len)
192{
bec9d989 193 KBDState *s = d->opaque;
e2733d20
FB
194 int cmd, reg, olen;
195
bec9d989
FB
196 if ((buf[0] & 0x0f) == ADB_FLUSH) {
197 /* flush keyboard fifo */
198 s->wptr = s->rptr = s->count = 0;
199 return 0;
e2733d20 200 }
267002cd
FB
201
202 cmd = buf[0] & 0xc;
203 reg = buf[0] & 0x3;
e2733d20 204 olen = 0;
267002cd
FB
205 switch(cmd) {
206 case ADB_WRITEREG:
207 switch(reg) {
208 case 2:
209 /* LED status */
267002cd
FB
210 break;
211 case 3:
212 switch(buf[2]) {
213 case ADB_CMD_SELF_TEST:
267002cd
FB
214 break;
215 case ADB_CMD_CHANGE_ID:
216 case ADB_CMD_CHANGE_ID_AND_ACT:
217 case ADB_CMD_CHANGE_ID_AND_ENABLE:
218 d->devaddr = buf[1] & 0xf;
267002cd
FB
219 break;
220 default:
221 /* XXX: check this */
222 d->devaddr = buf[1] & 0xf;
223 d->handler = buf[2];
267002cd
FB
224 break;
225 }
226 }
227 break;
228 case ADB_READREG:
229 switch(reg) {
bec9d989
FB
230 case 0:
231 olen = adb_kbd_poll(d, obuf);
232 break;
267002cd 233 case 1:
267002cd
FB
234 break;
235 case 2:
e2733d20
FB
236 obuf[0] = 0x00; /* XXX: check this */
237 obuf[1] = 0x07; /* led status */
238 olen = 2;
267002cd
FB
239 break;
240 case 3:
e2733d20
FB
241 obuf[0] = d->handler;
242 obuf[1] = d->devaddr;
243 olen = 2;
267002cd
FB
244 break;
245 }
246 break;
247 }
e2733d20 248 return olen;
267002cd
FB
249}
250
251void adb_kbd_init(ADBBusState *bus)
252{
253 ADBDevice *d;
e2733d20
FB
254 KBDState *s;
255 s = qemu_mallocz(sizeof(KBDState));
bec9d989 256 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, NULL, s);
e2733d20 257 d->handler = 1;
267002cd
FB
258 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
259}
260
261/***************************************************************/
262/* Mouse ADB device */
263
e2733d20
FB
264typedef struct MouseState {
265 int buttons_state, last_buttons_state;
266 int dx, dy, dz;
267} MouseState;
268
267002cd
FB
269static void adb_mouse_event(void *opaque,
270 int dx1, int dy1, int dz1, int buttons_state)
271{
272 ADBDevice *d = opaque;
e2733d20
FB
273 MouseState *s = d->opaque;
274
275 s->dx += dx1;
276 s->dy += dy1;
277 s->dz += dz1;
278 s->buttons_state = buttons_state;
279}
280
281
282static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
283{
284 MouseState *s = d->opaque;
267002cd
FB
285 int dx, dy;
286
e2733d20
FB
287 if (s->last_buttons_state == s->buttons_state &&
288 s->dx == 0 && s->dy == 0)
289 return 0;
290
291 dx = s->dx;
267002cd
FB
292 if (dx < -63)
293 dx = -63;
294 else if (dx > 63)
295 dx = 63;
e2733d20
FB
296
297 dy = s->dy;
267002cd
FB
298 if (dy < -63)
299 dy = -63;
300 else if (dy > 63)
301 dy = 63;
e2733d20
FB
302
303 s->dx -= dx;
304 s->dy -= dy;
305 s->last_buttons_state = s->buttons_state;
306
267002cd
FB
307 dx &= 0x7f;
308 dy &= 0x7f;
e2733d20 309
bec9d989 310 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
267002cd 311 dy |= 0x80;
bec9d989 312 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
267002cd 313 dx |= 0x80;
e2733d20 314
bec9d989
FB
315 obuf[0] = dy;
316 obuf[1] = dx;
317 return 2;
267002cd
FB
318}
319
e2733d20
FB
320static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
321 const uint8_t *buf, int len)
267002cd 322{
bec9d989 323 MouseState *s = d->opaque;
e2733d20
FB
324 int cmd, reg, olen;
325
bec9d989
FB
326 if ((buf[0] & 0x0f) == ADB_FLUSH) {
327 /* flush mouse fifo */
328 s->buttons_state = s->last_buttons_state;
329 s->dx = 0;
330 s->dy = 0;
331 s->dz = 0;
332 return 0;
e2733d20 333 }
267002cd
FB
334
335 cmd = buf[0] & 0xc;
336 reg = buf[0] & 0x3;
e2733d20 337 olen = 0;
267002cd
FB
338 switch(cmd) {
339 case ADB_WRITEREG:
340 switch(reg) {
341 case 2:
267002cd
FB
342 break;
343 case 3:
344 switch(buf[2]) {
345 case ADB_CMD_SELF_TEST:
267002cd
FB
346 break;
347 case ADB_CMD_CHANGE_ID:
348 case ADB_CMD_CHANGE_ID_AND_ACT:
349 case ADB_CMD_CHANGE_ID_AND_ENABLE:
350 d->devaddr = buf[1] & 0xf;
267002cd
FB
351 break;
352 default:
353 /* XXX: check this */
354 d->devaddr = buf[1] & 0xf;
267002cd
FB
355 break;
356 }
357 }
358 break;
359 case ADB_READREG:
360 switch(reg) {
bec9d989
FB
361 case 0:
362 olen = adb_mouse_poll(d, obuf);
363 break;
267002cd 364 case 1:
267002cd
FB
365 break;
366 case 3:
e2733d20
FB
367 obuf[0] = d->handler;
368 obuf[1] = d->devaddr;
369 olen = 2;
267002cd
FB
370 break;
371 }
372 break;
373 }
e2733d20 374 return olen;
267002cd
FB
375}
376
377void adb_mouse_init(ADBBusState *bus)
378{
379 ADBDevice *d;
e2733d20 380 MouseState *s;
267002cd 381
e2733d20 382 s = qemu_mallocz(sizeof(MouseState));
bec9d989 383 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, NULL, s);
e2733d20 384 d->handler = 2;
267002cd
FB
385 qemu_add_mouse_event_handler(adb_mouse_event, d);
386}
This page took 0.072197 seconds and 4 git commands to generate.