]> git.proxmox.com Git - mirror_qemu.git/blame - hw/slavio_serial.c
find -type f | xargs sed -i 's/[\t ]*$//g' # Yes, again. Note the star in the regex.
[mirror_qemu.git] / hw / slavio_serial.c
CommitLineData
e80cfcfc
FB
1/*
2 * QEMU Sparc SLAVIO serial port emulation
5fafdf24 3 *
8be1f5c8 4 * Copyright (c) 2003-2005 Fabrice Bellard
5fafdf24 5 *
e80cfcfc
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 */
24#include "vl.h"
8be1f5c8 25/* debug serial */
e80cfcfc
FB
26//#define DEBUG_SERIAL
27
28/* debug keyboard */
29//#define DEBUG_KBD
30
8be1f5c8 31/* debug mouse */
e80cfcfc
FB
32//#define DEBUG_MOUSE
33
34/*
35 * This is the serial port, mouse and keyboard part of chip STP2001
36 * (Slave I/O), also produced as NCR89C105. See
37 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
5fafdf24 38 *
e80cfcfc
FB
39 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
40 * mouse and keyboard ports don't implement all functions and they are
41 * only asynchronous. There is no DMA.
42 *
43 */
44
715748fa
FB
45/*
46 * Modifications:
47 * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented
48 * serial mouse queue.
49 * Implemented serial mouse protocol.
50 */
51
8be1f5c8
FB
52#ifdef DEBUG_SERIAL
53#define SER_DPRINTF(fmt, args...) \
54do { printf("SER: " fmt , ##args); } while (0)
55#else
56#define SER_DPRINTF(fmt, args...)
57#endif
58#ifdef DEBUG_KBD
59#define KBD_DPRINTF(fmt, args...) \
60do { printf("KBD: " fmt , ##args); } while (0)
61#else
62#define KBD_DPRINTF(fmt, args...)
63#endif
64#ifdef DEBUG_MOUSE
65#define MS_DPRINTF(fmt, args...) \
715748fa 66do { printf("MSC: " fmt , ##args); } while (0)
8be1f5c8
FB
67#else
68#define MS_DPRINTF(fmt, args...)
69#endif
70
71typedef enum {
72 chn_a, chn_b,
73} chn_id_t;
74
35db099d
FB
75#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
76
8be1f5c8
FB
77typedef enum {
78 ser, kbd, mouse,
79} chn_type_t;
80
715748fa 81#define SERIO_QUEUE_SIZE 256
8be1f5c8
FB
82
83typedef struct {
715748fa 84 uint8_t data[SERIO_QUEUE_SIZE];
8be1f5c8 85 int rptr, wptr, count;
715748fa 86} SERIOQueue;
8be1f5c8 87
e80cfcfc 88typedef struct ChannelState {
d537cf6c 89 qemu_irq irq;
e80cfcfc 90 int reg;
e4a89056 91 int rxint, txint, rxint_under_svc, txint_under_svc;
8be1f5c8
FB
92 chn_id_t chn; // this channel, A (base+4) or B (base+0)
93 chn_type_t type;
94 struct ChannelState *otherchn;
e80cfcfc 95 uint8_t rx, tx, wregs[16], rregs[16];
715748fa 96 SERIOQueue queue;
e80cfcfc
FB
97 CharDriverState *chr;
98} ChannelState;
99
100struct SerialState {
101 struct ChannelState chn[2];
102};
103
104#define SERIAL_MAXADDR 7
5aca8c3b 105#define SERIAL_SIZE (SERIAL_MAXADDR + 1)
e80cfcfc 106
8be1f5c8
FB
107static void handle_kbd_command(ChannelState *s, int val);
108static int serial_can_receive(void *opaque);
109static void serial_receive_byte(ChannelState *s, int ch);
e4a89056 110static inline void set_txint(ChannelState *s);
8be1f5c8 111
67deb562
BS
112static void clear_queue(void *opaque)
113{
114 ChannelState *s = opaque;
115 SERIOQueue *q = &s->queue;
116 q->rptr = q->wptr = q->count = 0;
117}
118
8be1f5c8
FB
119static void put_queue(void *opaque, int b)
120{
121 ChannelState *s = opaque;
715748fa 122 SERIOQueue *q = &s->queue;
8be1f5c8 123
35db099d 124 SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
715748fa 125 if (q->count >= SERIO_QUEUE_SIZE)
8be1f5c8
FB
126 return;
127 q->data[q->wptr] = b;
715748fa 128 if (++q->wptr == SERIO_QUEUE_SIZE)
8be1f5c8
FB
129 q->wptr = 0;
130 q->count++;
131 serial_receive_byte(s, 0);
132}
133
134static uint32_t get_queue(void *opaque)
135{
136 ChannelState *s = opaque;
715748fa 137 SERIOQueue *q = &s->queue;
8be1f5c8 138 int val;
3b46e624 139
8be1f5c8
FB
140 if (q->count == 0) {
141 return 0;
142 } else {
143 val = q->data[q->rptr];
715748fa 144 if (++q->rptr == SERIO_QUEUE_SIZE)
8be1f5c8
FB
145 q->rptr = 0;
146 q->count--;
147 }
67deb562 148 SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
8be1f5c8
FB
149 if (q->count > 0)
150 serial_receive_byte(s, 0);
151 return val;
152}
153
e4a89056 154static int slavio_serial_update_irq_chn(ChannelState *s)
e80cfcfc
FB
155{
156 if ((s->wregs[1] & 1) && // interrupts enabled
157 (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
158 ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
159 s->rxint == 1) || // rx ints enabled, pending
160 ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
e4a89056 161 return 1;
e80cfcfc 162 }
e4a89056
FB
163 return 0;
164}
165
166static void slavio_serial_update_irq(ChannelState *s)
167{
168 int irq;
169
170 irq = slavio_serial_update_irq_chn(s);
171 irq |= slavio_serial_update_irq_chn(s->otherchn);
172
d537cf6c
PB
173 SER_DPRINTF("IRQ = %d\n", irq);
174 qemu_set_irq(s->irq, irq);
e80cfcfc
FB
175}
176
177static void slavio_serial_reset_chn(ChannelState *s)
178{
179 int i;
180
181 s->reg = 0;
5aca8c3b 182 for (i = 0; i < SERIAL_SIZE; i++) {
e80cfcfc
FB
183 s->rregs[i] = 0;
184 s->wregs[i] = 0;
185 }
186 s->wregs[4] = 4;
187 s->wregs[9] = 0xc0;
188 s->wregs[11] = 8;
189 s->wregs[14] = 0x30;
190 s->wregs[15] = 0xf8;
191 s->rregs[0] = 0x44;
192 s->rregs[1] = 6;
193
194 s->rx = s->tx = 0;
195 s->rxint = s->txint = 0;
e4a89056 196 s->rxint_under_svc = s->txint_under_svc = 0;
67deb562 197 clear_queue(s);
e80cfcfc
FB
198}
199
200static void slavio_serial_reset(void *opaque)
201{
202 SerialState *s = opaque;
203 slavio_serial_reset_chn(&s->chn[0]);
204 slavio_serial_reset_chn(&s->chn[1]);
205}
206
ba3c64fb
FB
207static inline void clr_rxint(ChannelState *s)
208{
209 s->rxint = 0;
e4a89056 210 s->rxint_under_svc = 0;
67deb562
BS
211 if (s->chn == chn_a) {
212 if (s->wregs[9] & 0x10)
213 s->otherchn->rregs[2] = 0x60;
214 else
215 s->otherchn->rregs[2] = 0x06;
ba3c64fb 216 s->rregs[3] &= ~0x20;
67deb562
BS
217 } else {
218 if (s->wregs[9] & 0x10)
219 s->rregs[2] = 0x60;
220 else
221 s->rregs[2] = 0x06;
ba3c64fb 222 s->otherchn->rregs[3] &= ~4;
67deb562 223 }
e4a89056
FB
224 if (s->txint)
225 set_txint(s);
ba3c64fb
FB
226 slavio_serial_update_irq(s);
227}
228
229static inline void set_rxint(ChannelState *s)
230{
231 s->rxint = 1;
e4a89056
FB
232 if (!s->txint_under_svc) {
233 s->rxint_under_svc = 1;
67deb562
BS
234 if (s->chn == chn_a) {
235 if (s->wregs[9] & 0x10)
236 s->otherchn->rregs[2] = 0x30;
237 else
238 s->otherchn->rregs[2] = 0x0c;
67deb562
BS
239 } else {
240 if (s->wregs[9] & 0x10)
241 s->rregs[2] = 0x20;
242 else
243 s->rregs[2] = 0x04;
67deb562 244 }
ba3c64fb 245 }
b9652ca3
BS
246 if (s->chn == chn_a)
247 s->rregs[3] |= 0x20;
248 else
249 s->otherchn->rregs[3] |= 4;
250 slavio_serial_update_irq(s);
ba3c64fb
FB
251}
252
253static inline void clr_txint(ChannelState *s)
254{
255 s->txint = 0;
e4a89056 256 s->txint_under_svc = 0;
b9652ca3
BS
257 if (s->chn == chn_a) {
258 if (s->wregs[9] & 0x10)
259 s->otherchn->rregs[2] = 0x60;
260 else
261 s->otherchn->rregs[2] = 0x06;
ba3c64fb 262 s->rregs[3] &= ~0x10;
b9652ca3
BS
263 } else {
264 if (s->wregs[9] & 0x10)
265 s->rregs[2] = 0x60;
266 else
267 s->rregs[2] = 0x06;
ba3c64fb 268 s->otherchn->rregs[3] &= ~2;
b9652ca3 269 }
e4a89056
FB
270 if (s->rxint)
271 set_rxint(s);
ba3c64fb
FB
272 slavio_serial_update_irq(s);
273}
274
275static inline void set_txint(ChannelState *s)
276{
277 s->txint = 1;
e4a89056
FB
278 if (!s->rxint_under_svc) {
279 s->txint_under_svc = 1;
b9652ca3
BS
280 if (s->chn == chn_a) {
281 if (s->wregs[9] & 0x10)
282 s->otherchn->rregs[2] = 0x10;
283 else
284 s->otherchn->rregs[2] = 0x08;
285 } else {
286 s->rregs[2] = 0;
287 }
ba3c64fb 288 }
b9652ca3
BS
289 if (s->chn == chn_a)
290 s->rregs[3] |= 0x10;
291 else
292 s->otherchn->rregs[3] |= 2;
293 slavio_serial_update_irq(s);
ba3c64fb
FB
294}
295
35db099d
FB
296static void slavio_serial_update_parameters(ChannelState *s)
297{
298 int speed, parity, data_bits, stop_bits;
299 QEMUSerialSetParams ssp;
300
301 if (!s->chr || s->type != ser)
302 return;
303
304 if (s->wregs[4] & 1) {
305 if (s->wregs[4] & 2)
306 parity = 'E';
307 else
308 parity = 'O';
309 } else {
310 parity = 'N';
311 }
312 if ((s->wregs[4] & 0x0c) == 0x0c)
313 stop_bits = 2;
314 else
315 stop_bits = 1;
316 switch (s->wregs[5] & 0x60) {
317 case 0x00:
318 data_bits = 5;
319 break;
320 case 0x20:
321 data_bits = 7;
322 break;
323 case 0x40:
324 data_bits = 6;
325 break;
326 default:
327 case 0x60:
328 data_bits = 8;
329 break;
330 }
331 speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
332 switch (s->wregs[4] & 0xc0) {
333 case 0x00:
334 break;
335 case 0x40:
336 speed /= 16;
337 break;
338 case 0x80:
339 speed /= 32;
340 break;
341 default:
342 case 0xc0:
343 speed /= 64;
344 break;
345 }
346 ssp.speed = speed;
347 ssp.parity = parity;
348 ssp.data_bits = data_bits;
349 ssp.stop_bits = stop_bits;
350 SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
351 speed, parity, data_bits, stop_bits);
352 qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
353}
354
3a5c3138 355static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
e80cfcfc 356{
b3ceef24 357 SerialState *serial = opaque;
e80cfcfc
FB
358 ChannelState *s;
359 uint32_t saddr;
360 int newreg, channel;
361
362 val &= 0xff;
363 saddr = (addr & 3) >> 1;
364 channel = (addr & SERIAL_MAXADDR) >> 2;
b3ceef24 365 s = &serial->chn[channel];
e80cfcfc
FB
366 switch (saddr) {
367 case 0:
35db099d 368 SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
e80cfcfc
FB
369 newreg = 0;
370 switch (s->reg) {
371 case 0:
372 newreg = val & 7;
373 val &= 0x38;
374 switch (val) {
375 case 8:
f69a8695 376 newreg |= 0x8;
e80cfcfc 377 break;
e80cfcfc 378 case 0x28:
ba3c64fb
FB
379 clr_txint(s);
380 break;
381 case 0x38:
e4a89056
FB
382 if (s->rxint_under_svc)
383 clr_rxint(s);
384 else if (s->txint_under_svc)
385 clr_txint(s);
e80cfcfc
FB
386 break;
387 default:
388 break;
389 }
390 break;
35db099d
FB
391 case 1 ... 3:
392 case 6 ... 8:
393 case 10 ... 11:
394 case 14 ... 15:
395 s->wregs[s->reg] = val;
396 break;
397 case 4:
398 case 5:
399 case 12:
400 case 13:
e80cfcfc 401 s->wregs[s->reg] = val;
35db099d 402 slavio_serial_update_parameters(s);
e80cfcfc
FB
403 break;
404 case 9:
405 switch (val & 0xc0) {
406 case 0:
407 default:
408 break;
409 case 0x40:
b3ceef24 410 slavio_serial_reset_chn(&serial->chn[1]);
e80cfcfc
FB
411 return;
412 case 0x80:
b3ceef24 413 slavio_serial_reset_chn(&serial->chn[0]);
e80cfcfc
FB
414 return;
415 case 0xc0:
b3ceef24 416 slavio_serial_reset(serial);
e80cfcfc
FB
417 return;
418 }
419 break;
420 default:
421 break;
422 }
423 if (s->reg == 0)
424 s->reg = newreg;
425 else
426 s->reg = 0;
427 break;
428 case 1:
35db099d 429 SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
96c4f569 430 s->tx = val;
e80cfcfc 431 if (s->wregs[5] & 8) { // tx enabled
e80cfcfc
FB
432 if (s->chr)
433 qemu_chr_write(s->chr, &s->tx, 1);
8be1f5c8
FB
434 else if (s->type == kbd) {
435 handle_kbd_command(s, val);
436 }
e80cfcfc 437 }
96c4f569
BS
438 s->rregs[0] |= 4; // Tx buffer empty
439 s->rregs[1] |= 1; // All sent
440 set_txint(s);
e80cfcfc
FB
441 break;
442 default:
443 break;
444 }
445}
446
3a5c3138 447static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
e80cfcfc 448{
b3ceef24 449 SerialState *serial = opaque;
e80cfcfc
FB
450 ChannelState *s;
451 uint32_t saddr;
452 uint32_t ret;
453 int channel;
454
455 saddr = (addr & 3) >> 1;
456 channel = (addr & SERIAL_MAXADDR) >> 2;
b3ceef24 457 s = &serial->chn[channel];
e80cfcfc
FB
458 switch (saddr) {
459 case 0:
35db099d 460 SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
e80cfcfc
FB
461 ret = s->rregs[s->reg];
462 s->reg = 0;
463 return ret;
464 case 1:
465 s->rregs[0] &= ~1;
ba3c64fb 466 clr_rxint(s);
715748fa 467 if (s->type == kbd || s->type == mouse)
8be1f5c8
FB
468 ret = get_queue(s);
469 else
470 ret = s->rx;
35db099d 471 SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
8be1f5c8 472 return ret;
e80cfcfc
FB
473 default:
474 break;
475 }
476 return 0;
477}
478
479static int serial_can_receive(void *opaque)
480{
481 ChannelState *s = opaque;
e4a89056
FB
482 int ret;
483
e80cfcfc
FB
484 if (((s->wregs[3] & 1) == 0) // Rx not enabled
485 || ((s->rregs[0] & 1) == 1)) // char already available
e4a89056 486 ret = 0;
e80cfcfc 487 else
e4a89056 488 ret = 1;
35db099d 489 //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
e4a89056 490 return ret;
e80cfcfc
FB
491}
492
493static void serial_receive_byte(ChannelState *s, int ch)
494{
35db099d 495 SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
e80cfcfc
FB
496 s->rregs[0] |= 1;
497 s->rx = ch;
ba3c64fb 498 set_rxint(s);
e80cfcfc
FB
499}
500
501static void serial_receive_break(ChannelState *s)
502{
503 s->rregs[0] |= 0x80;
504 slavio_serial_update_irq(s);
505}
506
507static void serial_receive1(void *opaque, const uint8_t *buf, int size)
508{
509 ChannelState *s = opaque;
510 serial_receive_byte(s, buf[0]);
511}
512
513static void serial_event(void *opaque, int event)
514{
515 ChannelState *s = opaque;
516 if (event == CHR_EVENT_BREAK)
517 serial_receive_break(s);
518}
519
520static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
521 slavio_serial_mem_readb,
522 slavio_serial_mem_readb,
523 slavio_serial_mem_readb,
524};
525
526static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
527 slavio_serial_mem_writeb,
528 slavio_serial_mem_writeb,
529 slavio_serial_mem_writeb,
530};
531
532static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
533{
d537cf6c
PB
534 int tmp;
535 tmp = 0;
536 qemu_put_be32s(f, &tmp); /* unused, was IRQ. */
e80cfcfc
FB
537 qemu_put_be32s(f, &s->reg);
538 qemu_put_be32s(f, &s->rxint);
539 qemu_put_be32s(f, &s->txint);
e4a89056
FB
540 qemu_put_be32s(f, &s->rxint_under_svc);
541 qemu_put_be32s(f, &s->txint_under_svc);
e80cfcfc
FB
542 qemu_put_8s(f, &s->rx);
543 qemu_put_8s(f, &s->tx);
544 qemu_put_buffer(f, s->wregs, 16);
545 qemu_put_buffer(f, s->rregs, 16);
546}
547
548static void slavio_serial_save(QEMUFile *f, void *opaque)
549{
550 SerialState *s = opaque;
551
552 slavio_serial_save_chn(f, &s->chn[0]);
553 slavio_serial_save_chn(f, &s->chn[1]);
554}
555
556static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
557{
d537cf6c
PB
558 int tmp;
559
e4a89056 560 if (version_id > 2)
e80cfcfc
FB
561 return -EINVAL;
562
d537cf6c 563 qemu_get_be32s(f, &tmp); /* unused */
e80cfcfc
FB
564 qemu_get_be32s(f, &s->reg);
565 qemu_get_be32s(f, &s->rxint);
566 qemu_get_be32s(f, &s->txint);
e4a89056
FB
567 if (version_id >= 2) {
568 qemu_get_be32s(f, &s->rxint_under_svc);
569 qemu_get_be32s(f, &s->txint_under_svc);
570 }
e80cfcfc
FB
571 qemu_get_8s(f, &s->rx);
572 qemu_get_8s(f, &s->tx);
573 qemu_get_buffer(f, s->wregs, 16);
574 qemu_get_buffer(f, s->rregs, 16);
575 return 0;
576}
577
578static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
579{
580 SerialState *s = opaque;
581 int ret;
582
583 ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
584 if (ret != 0)
585 return ret;
586 ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
587 return ret;
588
589}
590
5dcb6b91
BS
591SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
592 CharDriverState *chr1, CharDriverState *chr2)
e80cfcfc 593{
8be1f5c8 594 int slavio_serial_io_memory, i;
e80cfcfc
FB
595 SerialState *s;
596
597 s = qemu_mallocz(sizeof(SerialState));
598 if (!s)
599 return NULL;
e80cfcfc
FB
600
601 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
5aca8c3b 602 cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
e80cfcfc 603
8be1f5c8
FB
604 s->chn[0].chr = chr1;
605 s->chn[1].chr = chr2;
606
607 for (i = 0; i < 2; i++) {
608 s->chn[i].irq = irq;
609 s->chn[i].chn = 1 - i;
610 s->chn[i].type = ser;
611 if (s->chn[i].chr) {
e5b0bc44
PB
612 qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
613 serial_receive1, serial_event, &s->chn[i]);
8be1f5c8 614 }
e80cfcfc 615 }
8be1f5c8
FB
616 s->chn[0].otherchn = &s->chn[1];
617 s->chn[1].otherchn = &s->chn[0];
e4a89056 618 register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s);
e80cfcfc
FB
619 qemu_register_reset(slavio_serial_reset, s);
620 slavio_serial_reset(s);
621 return s;
622}
623
8be1f5c8
FB
624static const uint8_t keycodes[128] = {
625 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
626 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
627 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
628 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
629 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
630 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
631 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
632 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
633};
634
e80cfcfc
FB
635static void sunkbd_event(void *opaque, int ch)
636{
637 ChannelState *s = opaque;
8be1f5c8
FB
638 int release = ch & 0x80;
639
640 ch = keycodes[ch & 0x7f];
641 KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
642 put_queue(s, ch | release);
643}
644
645static void handle_kbd_command(ChannelState *s, int val)
646{
647 KBD_DPRINTF("Command %d\n", val);
648 switch (val) {
649 case 1: // Reset, return type code
67deb562 650 clear_queue(s);
8be1f5c8 651 put_queue(s, 0xff);
67deb562 652 put_queue(s, 4); // Type 4
8be1f5c8
FB
653 break;
654 case 7: // Query layout
67deb562
BS
655 case 0xf:
656 clear_queue(s);
8be1f5c8 657 put_queue(s, 0xfe);
67deb562 658 put_queue(s, 19); // XXX, layout?
8be1f5c8
FB
659 break;
660 default:
661 break;
662 }
e80cfcfc
FB
663}
664
5fafdf24 665static void sunmouse_event(void *opaque,
e80cfcfc
FB
666 int dx, int dy, int dz, int buttons_state)
667{
668 ChannelState *s = opaque;
669 int ch;
670
715748fa
FB
671 MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
672
673 ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
674
675 if (buttons_state & MOUSE_EVENT_LBUTTON)
676 ch ^= 0x4;
677 if (buttons_state & MOUSE_EVENT_MBUTTON)
678 ch ^= 0x2;
679 if (buttons_state & MOUSE_EVENT_RBUTTON)
680 ch ^= 0x1;
681
682 put_queue(s, ch);
683
684 ch = dx;
685
686 if (ch > 127)
687 ch=127;
688 else if (ch < -127)
689 ch=-127;
690
691 put_queue(s, ch & 0xff);
692
693 ch = -dy;
694
695 if (ch > 127)
696 ch=127;
697 else if (ch < -127)
698 ch=-127;
699
700 put_queue(s, ch & 0xff);
701
702 // MSC protocol specify two extra motion bytes
703
704 put_queue(s, 0);
705 put_queue(s, 0);
e80cfcfc
FB
706}
707
5dcb6b91 708void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq)
e80cfcfc 709{
8be1f5c8 710 int slavio_serial_io_memory, i;
e80cfcfc
FB
711 SerialState *s;
712
713 s = qemu_mallocz(sizeof(SerialState));
714 if (!s)
715 return;
8be1f5c8
FB
716 for (i = 0; i < 2; i++) {
717 s->chn[i].irq = irq;
718 s->chn[i].chn = 1 - i;
719 s->chn[i].chr = NULL;
720 }
721 s->chn[0].otherchn = &s->chn[1];
722 s->chn[1].otherchn = &s->chn[0];
723 s->chn[0].type = mouse;
724 s->chn[1].type = kbd;
e80cfcfc
FB
725
726 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
5aca8c3b 727 cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
e80cfcfc 728
455204eb 729 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
8be1f5c8 730 qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
5425a216 731 register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save, slavio_serial_load, s);
e80cfcfc
FB
732 qemu_register_reset(slavio_serial_reset, s);
733 slavio_serial_reset(s);
734}