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