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