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