]> git.proxmox.com Git - mirror_qemu.git/blame - hw/adb.c
Add SuperSPARC MMU breakpoint registers (Robert Reif)
[mirror_qemu.git] / hw / adb.c
CommitLineData
267002cd
FB
1/*
2 * QEMU ADB support
5fafdf24 3 *
267002cd 4 * Copyright (c) 2004 Fabrice Bellard
5fafdf24 5 *
267002cd
FB
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 */
87ecb68b
PB
24#include "hw.h"
25#include "ppc_mac.h"
26#include "console.h"
267002cd
FB
27
28/* ADB commands */
29#define ADB_BUSRESET 0x00
30#define ADB_FLUSH 0x01
31#define ADB_WRITEREG 0x08
32#define ADB_READREG 0x0c
33
34/* ADB device commands */
35#define ADB_CMD_SELF_TEST 0xff
36#define ADB_CMD_CHANGE_ID 0xfe
37#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
38#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
39
40/* ADB default device IDs (upper 4 bits of ADB command byte) */
41#define ADB_DONGLE 1
42#define ADB_KEYBOARD 2
43#define ADB_MOUSE 3
44#define ADB_TABLET 4
45#define ADB_MODEM 5
46#define ADB_MISC 7
47
bec9d989
FB
48/* error codes */
49#define ADB_RET_NOTPRESENT (-2)
50
e2733d20 51int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
267002cd
FB
52{
53 ADBDevice *d;
54 int devaddr, cmd, i;
267002cd 55
819e712b 56 cmd = buf[0] & 0xf;
bec9d989
FB
57 if (cmd == ADB_BUSRESET) {
58 for(i = 0; i < s->nb_devices; i++) {
59 d = &s->devices[i];
60 if (d->devreset) {
61 d->devreset(d);
62 }
63 }
64 return 0;
267002cd 65 }
bec9d989 66 devaddr = buf[0] >> 4;
267002cd
FB
67 for(i = 0; i < s->nb_devices; i++) {
68 d = &s->devices[i];
69 if (d->devaddr == devaddr) {
e2733d20 70 return d->devreq(d, obuf, buf, len);
267002cd
FB
71 }
72 }
bec9d989 73 return ADB_RET_NOTPRESENT;
e2733d20
FB
74}
75
bec9d989 76/* XXX: move that to cuda ? */
e2733d20
FB
77int adb_poll(ADBBusState *s, uint8_t *obuf)
78{
79 ADBDevice *d;
80 int olen, i;
bec9d989 81 uint8_t buf[1];
e2733d20
FB
82
83 olen = 0;
84 for(i = 0; i < s->nb_devices; i++) {
85 if (s->poll_index >= s->nb_devices)
86 s->poll_index = 0;
87 d = &s->devices[s->poll_index];
bec9d989
FB
88 buf[0] = ADB_READREG | (d->devaddr << 4);
89 olen = adb_request(s, obuf + 1, buf, 1);
90 /* if there is data, we poll again the same device */
91 if (olen > 0) {
92 obuf[0] = buf[0];
93 olen++;
e2733d20 94 break;
bec9d989
FB
95 }
96 s->poll_index++;
e2733d20
FB
97 }
98 return olen;
267002cd
FB
99}
100
5fafdf24
TS
101ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
102 ADBDeviceRequest *devreq,
103 ADBDeviceReset *devreset,
267002cd
FB
104 void *opaque)
105{
106 ADBDevice *d;
107 if (s->nb_devices >= MAX_ADB_DEVICES)
108 return NULL;
109 d = &s->devices[s->nb_devices++];
110 d->bus = s;
111 d->devaddr = devaddr;
e2733d20 112 d->devreq = devreq;
bec9d989 113 d->devreset = devreset;
267002cd
FB
114 d->opaque = opaque;
115 return d;
116}
117
118/***************************************************************/
119/* Keyboard ADB device */
120
e2733d20
FB
121typedef struct KBDState {
122 uint8_t data[128];
123 int rptr, wptr, count;
124} KBDState;
125
267002cd
FB
126static const uint8_t pc_to_adb_keycode[256] = {
127 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
128 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
129 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
130 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
131 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
e2733d20 132 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
267002cd
FB
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20
FB
135 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
140 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
267002cd 141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20 142 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267002cd
FB
143};
144
145static void adb_kbd_put_keycode(void *opaque, int keycode)
146{
267002cd 147 ADBDevice *d = opaque;
e2733d20
FB
148 KBDState *s = d->opaque;
149
150 if (s->count < sizeof(s->data)) {
151 s->data[s->wptr] = keycode;
152 if (++s->wptr == sizeof(s->data))
153 s->wptr = 0;
154 s->count++;
267002cd
FB
155 }
156}
157
e2733d20 158static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
267002cd 159{
e2733d20
FB
160 static int ext_keycode;
161 KBDState *s = d->opaque;
162 int adb_keycode, keycode;
163 int olen;
164
165 olen = 0;
166 for(;;) {
167 if (s->count == 0)
168 break;
169 keycode = s->data[s->rptr];
170 if (++s->rptr == sizeof(s->data))
171 s->rptr = 0;
172 s->count--;
173
174 if (keycode == 0xe0) {
175 ext_keycode = 1;
176 } else {
177 if (ext_keycode)
178 adb_keycode = pc_to_adb_keycode[keycode | 0x80];
179 else
180 adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
bec9d989
FB
181 obuf[0] = adb_keycode | (keycode & 0x80);
182 /* NOTE: could put a second keycode if needed */
183 obuf[1] = 0xff;
184 olen = 2;
e2733d20
FB
185 ext_keycode = 0;
186 break;
187 }
188 }
189 return olen;
190}
191
192static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
193 const uint8_t *buf, int len)
194{
bec9d989 195 KBDState *s = d->opaque;
e2733d20
FB
196 int cmd, reg, olen;
197
bec9d989
FB
198 if ((buf[0] & 0x0f) == ADB_FLUSH) {
199 /* flush keyboard fifo */
200 s->wptr = s->rptr = s->count = 0;
201 return 0;
e2733d20 202 }
267002cd
FB
203
204 cmd = buf[0] & 0xc;
205 reg = buf[0] & 0x3;
e2733d20 206 olen = 0;
267002cd
FB
207 switch(cmd) {
208 case ADB_WRITEREG:
209 switch(reg) {
210 case 2:
211 /* LED status */
267002cd
FB
212 break;
213 case 3:
214 switch(buf[2]) {
215 case ADB_CMD_SELF_TEST:
267002cd
FB
216 break;
217 case ADB_CMD_CHANGE_ID:
218 case ADB_CMD_CHANGE_ID_AND_ACT:
219 case ADB_CMD_CHANGE_ID_AND_ENABLE:
220 d->devaddr = buf[1] & 0xf;
267002cd
FB
221 break;
222 default:
223 /* XXX: check this */
224 d->devaddr = buf[1] & 0xf;
225 d->handler = buf[2];
267002cd
FB
226 break;
227 }
228 }
229 break;
230 case ADB_READREG:
231 switch(reg) {
bec9d989
FB
232 case 0:
233 olen = adb_kbd_poll(d, obuf);
234 break;
267002cd 235 case 1:
267002cd
FB
236 break;
237 case 2:
e2733d20
FB
238 obuf[0] = 0x00; /* XXX: check this */
239 obuf[1] = 0x07; /* led status */
240 olen = 2;
267002cd
FB
241 break;
242 case 3:
e2733d20
FB
243 obuf[0] = d->handler;
244 obuf[1] = d->devaddr;
245 olen = 2;
267002cd
FB
246 break;
247 }
248 break;
249 }
e2733d20 250 return olen;
267002cd
FB
251}
252
3988e897
FB
253static int adb_kbd_reset(ADBDevice *d)
254{
255 KBDState *s = d->opaque;
256
257 d->handler = 1;
258 d->devaddr = ADB_KEYBOARD;
259 memset(s, 0, sizeof(KBDState));
260
261 return 0;
262}
263
267002cd
FB
264void adb_kbd_init(ADBBusState *bus)
265{
266 ADBDevice *d;
e2733d20
FB
267 KBDState *s;
268 s = qemu_mallocz(sizeof(KBDState));
3988e897
FB
269 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
270 adb_kbd_reset, s);
271 adb_kbd_reset(d);
267002cd
FB
272 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
273}
274
275/***************************************************************/
276/* Mouse ADB device */
277
e2733d20
FB
278typedef struct MouseState {
279 int buttons_state, last_buttons_state;
280 int dx, dy, dz;
281} MouseState;
282
267002cd
FB
283static void adb_mouse_event(void *opaque,
284 int dx1, int dy1, int dz1, int buttons_state)
285{
286 ADBDevice *d = opaque;
e2733d20
FB
287 MouseState *s = d->opaque;
288
289 s->dx += dx1;
290 s->dy += dy1;
291 s->dz += dz1;
292 s->buttons_state = buttons_state;
293}
294
295
296static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
297{
298 MouseState *s = d->opaque;
267002cd
FB
299 int dx, dy;
300
e2733d20
FB
301 if (s->last_buttons_state == s->buttons_state &&
302 s->dx == 0 && s->dy == 0)
303 return 0;
3b46e624 304
e2733d20 305 dx = s->dx;
267002cd
FB
306 if (dx < -63)
307 dx = -63;
308 else if (dx > 63)
309 dx = 63;
3b46e624 310
e2733d20 311 dy = s->dy;
267002cd
FB
312 if (dy < -63)
313 dy = -63;
314 else if (dy > 63)
315 dy = 63;
3b46e624 316
e2733d20
FB
317 s->dx -= dx;
318 s->dy -= dy;
319 s->last_buttons_state = s->buttons_state;
3b46e624 320
267002cd
FB
321 dx &= 0x7f;
322 dy &= 0x7f;
3b46e624 323
bec9d989 324 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
267002cd 325 dy |= 0x80;
bec9d989 326 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
267002cd 327 dx |= 0x80;
3b46e624 328
bec9d989
FB
329 obuf[0] = dy;
330 obuf[1] = dx;
331 return 2;
267002cd
FB
332}
333
e2733d20
FB
334static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
335 const uint8_t *buf, int len)
267002cd 336{
bec9d989 337 MouseState *s = d->opaque;
e2733d20 338 int cmd, reg, olen;
3b46e624 339
bec9d989
FB
340 if ((buf[0] & 0x0f) == ADB_FLUSH) {
341 /* flush mouse fifo */
342 s->buttons_state = s->last_buttons_state;
343 s->dx = 0;
344 s->dy = 0;
345 s->dz = 0;
346 return 0;
e2733d20 347 }
267002cd
FB
348
349 cmd = buf[0] & 0xc;
350 reg = buf[0] & 0x3;
e2733d20 351 olen = 0;
267002cd
FB
352 switch(cmd) {
353 case ADB_WRITEREG:
354 switch(reg) {
355 case 2:
267002cd
FB
356 break;
357 case 3:
358 switch(buf[2]) {
359 case ADB_CMD_SELF_TEST:
267002cd
FB
360 break;
361 case ADB_CMD_CHANGE_ID:
362 case ADB_CMD_CHANGE_ID_AND_ACT:
363 case ADB_CMD_CHANGE_ID_AND_ENABLE:
364 d->devaddr = buf[1] & 0xf;
267002cd
FB
365 break;
366 default:
367 /* XXX: check this */
368 d->devaddr = buf[1] & 0xf;
267002cd
FB
369 break;
370 }
371 }
372 break;
373 case ADB_READREG:
374 switch(reg) {
bec9d989
FB
375 case 0:
376 olen = adb_mouse_poll(d, obuf);
377 break;
267002cd 378 case 1:
267002cd
FB
379 break;
380 case 3:
e2733d20
FB
381 obuf[0] = d->handler;
382 obuf[1] = d->devaddr;
383 olen = 2;
267002cd
FB
384 break;
385 }
386 break;
387 }
e2733d20 388 return olen;
267002cd
FB
389}
390
3988e897
FB
391static int adb_mouse_reset(ADBDevice *d)
392{
393 MouseState *s = d->opaque;
394
395 d->handler = 2;
396 d->devaddr = ADB_MOUSE;
397 memset(s, 0, sizeof(MouseState));
398
399 return 0;
400}
401
267002cd
FB
402void adb_mouse_init(ADBBusState *bus)
403{
404 ADBDevice *d;
e2733d20 405 MouseState *s;
267002cd 406
e2733d20 407 s = qemu_mallocz(sizeof(MouseState));
3988e897
FB
408 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
409 adb_mouse_reset, s);
410 adb_mouse_reset(d);
455204eb 411 qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
267002cd 412}