]> git.proxmox.com Git - qemu.git/blame - hw/slavio_serial.c
PowerPC 64 fixes
[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)
52cc07d0
BS
55#define pic_set_irq_new(intctl, irq, level) \
56 do { printf("SER: set_irq(%d): %d\n", (irq), (level)); \
57 pic_set_irq_new((intctl), (irq),(level));} while (0)
8be1f5c8
FB
58#else
59#define SER_DPRINTF(fmt, args...)
60#endif
61#ifdef DEBUG_KBD
62#define KBD_DPRINTF(fmt, args...) \
63do { printf("KBD: " fmt , ##args); } while (0)
64#else
65#define KBD_DPRINTF(fmt, args...)
66#endif
67#ifdef DEBUG_MOUSE
68#define MS_DPRINTF(fmt, args...) \
715748fa 69do { printf("MSC: " fmt , ##args); } while (0)
8be1f5c8
FB
70#else
71#define MS_DPRINTF(fmt, args...)
72#endif
73
74typedef enum {
75 chn_a, chn_b,
76} chn_id_t;
77
35db099d
FB
78#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
79
8be1f5c8
FB
80typedef enum {
81 ser, kbd, mouse,
82} chn_type_t;
83
715748fa 84#define SERIO_QUEUE_SIZE 256
8be1f5c8
FB
85
86typedef struct {
715748fa 87 uint8_t data[SERIO_QUEUE_SIZE];
8be1f5c8 88 int rptr, wptr, count;
715748fa 89} SERIOQueue;
8be1f5c8 90
e80cfcfc
FB
91typedef struct ChannelState {
92 int irq;
93 int reg;
e4a89056 94 int rxint, txint, rxint_under_svc, txint_under_svc;
8be1f5c8
FB
95 chn_id_t chn; // this channel, A (base+4) or B (base+0)
96 chn_type_t type;
97 struct ChannelState *otherchn;
e80cfcfc 98 uint8_t rx, tx, wregs[16], rregs[16];
715748fa 99 SERIOQueue queue;
e80cfcfc 100 CharDriverState *chr;
52cc07d0 101 void *intctl;
e80cfcfc
FB
102} ChannelState;
103
104struct SerialState {
105 struct ChannelState chn[2];
106};
107
108#define SERIAL_MAXADDR 7
109
8be1f5c8
FB
110static void handle_kbd_command(ChannelState *s, int val);
111static int serial_can_receive(void *opaque);
112static void serial_receive_byte(ChannelState *s, int ch);
e4a89056 113static inline void set_txint(ChannelState *s);
8be1f5c8
FB
114
115static void put_queue(void *opaque, int b)
116{
117 ChannelState *s = opaque;
715748fa 118 SERIOQueue *q = &s->queue;
8be1f5c8 119
35db099d 120 SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
715748fa 121 if (q->count >= SERIO_QUEUE_SIZE)
8be1f5c8
FB
122 return;
123 q->data[q->wptr] = b;
715748fa 124 if (++q->wptr == SERIO_QUEUE_SIZE)
8be1f5c8
FB
125 q->wptr = 0;
126 q->count++;
127 serial_receive_byte(s, 0);
128}
129
130static uint32_t get_queue(void *opaque)
131{
132 ChannelState *s = opaque;
715748fa 133 SERIOQueue *q = &s->queue;
8be1f5c8
FB
134 int val;
135
136 if (q->count == 0) {
137 return 0;
138 } else {
139 val = q->data[q->rptr];
715748fa 140 if (++q->rptr == SERIO_QUEUE_SIZE)
8be1f5c8
FB
141 q->rptr = 0;
142 q->count--;
143 }
35db099d 144 KBD_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
8be1f5c8
FB
145 if (q->count > 0)
146 serial_receive_byte(s, 0);
147 return val;
148}
149
e4a89056 150static int slavio_serial_update_irq_chn(ChannelState *s)
e80cfcfc
FB
151{
152 if ((s->wregs[1] & 1) && // interrupts enabled
153 (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
154 ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
155 s->rxint == 1) || // rx ints enabled, pending
156 ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
e4a89056 157 return 1;
e80cfcfc 158 }
e4a89056
FB
159 return 0;
160}
161
162static void slavio_serial_update_irq(ChannelState *s)
163{
164 int irq;
165
166 irq = slavio_serial_update_irq_chn(s);
167 irq |= slavio_serial_update_irq_chn(s->otherchn);
168
52cc07d0 169 pic_set_irq_new(s->intctl, s->irq, irq);
e80cfcfc
FB
170}
171
172static void slavio_serial_reset_chn(ChannelState *s)
173{
174 int i;
175
176 s->reg = 0;
177 for (i = 0; i < SERIAL_MAXADDR; i++) {
178 s->rregs[i] = 0;
179 s->wregs[i] = 0;
180 }
181 s->wregs[4] = 4;
182 s->wregs[9] = 0xc0;
183 s->wregs[11] = 8;
184 s->wregs[14] = 0x30;
185 s->wregs[15] = 0xf8;
186 s->rregs[0] = 0x44;
187 s->rregs[1] = 6;
188
189 s->rx = s->tx = 0;
190 s->rxint = s->txint = 0;
e4a89056 191 s->rxint_under_svc = s->txint_under_svc = 0;
e80cfcfc
FB
192}
193
194static void slavio_serial_reset(void *opaque)
195{
196 SerialState *s = opaque;
197 slavio_serial_reset_chn(&s->chn[0]);
198 slavio_serial_reset_chn(&s->chn[1]);
199}
200
ba3c64fb
FB
201static inline void clr_rxint(ChannelState *s)
202{
203 s->rxint = 0;
e4a89056 204 s->rxint_under_svc = 0;
35db099d 205 if (s->chn == chn_a)
ba3c64fb 206 s->rregs[3] &= ~0x20;
35db099d 207 else
ba3c64fb 208 s->otherchn->rregs[3] &= ~4;
e4a89056
FB
209 if (s->txint)
210 set_txint(s);
211 else
212 s->rregs[2] = 6;
ba3c64fb
FB
213 slavio_serial_update_irq(s);
214}
215
216static inline void set_rxint(ChannelState *s)
217{
218 s->rxint = 1;
e4a89056
FB
219 if (!s->txint_under_svc) {
220 s->rxint_under_svc = 1;
35db099d 221 if (s->chn == chn_a)
e4a89056 222 s->rregs[3] |= 0x20;
35db099d 223 else
e4a89056 224 s->otherchn->rregs[3] |= 4;
e4a89056
FB
225 s->rregs[2] = 4;
226 slavio_serial_update_irq(s);
ba3c64fb 227 }
ba3c64fb
FB
228}
229
230static inline void clr_txint(ChannelState *s)
231{
232 s->txint = 0;
e4a89056 233 s->txint_under_svc = 0;
35db099d 234 if (s->chn == chn_a)
ba3c64fb 235 s->rregs[3] &= ~0x10;
35db099d 236 else
ba3c64fb 237 s->otherchn->rregs[3] &= ~2;
e4a89056
FB
238 if (s->rxint)
239 set_rxint(s);
240 else
241 s->rregs[2] = 6;
ba3c64fb
FB
242 slavio_serial_update_irq(s);
243}
244
245static inline void set_txint(ChannelState *s)
246{
247 s->txint = 1;
e4a89056
FB
248 if (!s->rxint_under_svc) {
249 s->txint_under_svc = 1;
35db099d 250 if (s->chn == chn_a)
e4a89056 251 s->rregs[3] |= 0x10;
35db099d 252 else
e4a89056 253 s->otherchn->rregs[3] |= 2;
e4a89056
FB
254 s->rregs[2] = 0;
255 slavio_serial_update_irq(s);
ba3c64fb 256 }
ba3c64fb
FB
257}
258
35db099d
FB
259static void slavio_serial_update_parameters(ChannelState *s)
260{
261 int speed, parity, data_bits, stop_bits;
262 QEMUSerialSetParams ssp;
263
264 if (!s->chr || s->type != ser)
265 return;
266
267 if (s->wregs[4] & 1) {
268 if (s->wregs[4] & 2)
269 parity = 'E';
270 else
271 parity = 'O';
272 } else {
273 parity = 'N';
274 }
275 if ((s->wregs[4] & 0x0c) == 0x0c)
276 stop_bits = 2;
277 else
278 stop_bits = 1;
279 switch (s->wregs[5] & 0x60) {
280 case 0x00:
281 data_bits = 5;
282 break;
283 case 0x20:
284 data_bits = 7;
285 break;
286 case 0x40:
287 data_bits = 6;
288 break;
289 default:
290 case 0x60:
291 data_bits = 8;
292 break;
293 }
294 speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
295 switch (s->wregs[4] & 0xc0) {
296 case 0x00:
297 break;
298 case 0x40:
299 speed /= 16;
300 break;
301 case 0x80:
302 speed /= 32;
303 break;
304 default:
305 case 0xc0:
306 speed /= 64;
307 break;
308 }
309 ssp.speed = speed;
310 ssp.parity = parity;
311 ssp.data_bits = data_bits;
312 ssp.stop_bits = stop_bits;
313 SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
314 speed, parity, data_bits, stop_bits);
315 qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
316}
317
3a5c3138 318static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
e80cfcfc
FB
319{
320 SerialState *ser = opaque;
321 ChannelState *s;
322 uint32_t saddr;
323 int newreg, channel;
324
325 val &= 0xff;
326 saddr = (addr & 3) >> 1;
327 channel = (addr & SERIAL_MAXADDR) >> 2;
328 s = &ser->chn[channel];
329 switch (saddr) {
330 case 0:
35db099d 331 SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
e80cfcfc
FB
332 newreg = 0;
333 switch (s->reg) {
334 case 0:
335 newreg = val & 7;
336 val &= 0x38;
337 switch (val) {
338 case 8:
f69a8695 339 newreg |= 0x8;
e80cfcfc 340 break;
e80cfcfc 341 case 0x28:
ba3c64fb
FB
342 clr_txint(s);
343 break;
344 case 0x38:
e4a89056
FB
345 if (s->rxint_under_svc)
346 clr_rxint(s);
347 else if (s->txint_under_svc)
348 clr_txint(s);
e80cfcfc
FB
349 break;
350 default:
351 break;
352 }
353 break;
35db099d
FB
354 case 1 ... 3:
355 case 6 ... 8:
356 case 10 ... 11:
357 case 14 ... 15:
358 s->wregs[s->reg] = val;
359 break;
360 case 4:
361 case 5:
362 case 12:
363 case 13:
e80cfcfc 364 s->wregs[s->reg] = val;
35db099d 365 slavio_serial_update_parameters(s);
e80cfcfc
FB
366 break;
367 case 9:
368 switch (val & 0xc0) {
369 case 0:
370 default:
371 break;
372 case 0x40:
373 slavio_serial_reset_chn(&ser->chn[1]);
374 return;
375 case 0x80:
376 slavio_serial_reset_chn(&ser->chn[0]);
377 return;
378 case 0xc0:
379 slavio_serial_reset(ser);
380 return;
381 }
382 break;
383 default:
384 break;
385 }
386 if (s->reg == 0)
387 s->reg = newreg;
388 else
389 s->reg = 0;
390 break;
391 case 1:
35db099d 392 SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
e80cfcfc
FB
393 if (s->wregs[5] & 8) { // tx enabled
394 s->tx = val;
395 if (s->chr)
396 qemu_chr_write(s->chr, &s->tx, 1);
8be1f5c8
FB
397 else if (s->type == kbd) {
398 handle_kbd_command(s, val);
399 }
f69a8695
FB
400 s->rregs[0] |= 4; // Tx buffer empty
401 s->rregs[1] |= 1; // All sent
ba3c64fb 402 set_txint(s);
e80cfcfc
FB
403 }
404 break;
405 default:
406 break;
407 }
408}
409
3a5c3138 410static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
e80cfcfc
FB
411{
412 SerialState *ser = opaque;
413 ChannelState *s;
414 uint32_t saddr;
415 uint32_t ret;
416 int channel;
417
418 saddr = (addr & 3) >> 1;
419 channel = (addr & SERIAL_MAXADDR) >> 2;
420 s = &ser->chn[channel];
421 switch (saddr) {
422 case 0:
35db099d 423 SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
e80cfcfc
FB
424 ret = s->rregs[s->reg];
425 s->reg = 0;
426 return ret;
427 case 1:
428 s->rregs[0] &= ~1;
ba3c64fb 429 clr_rxint(s);
715748fa 430 if (s->type == kbd || s->type == mouse)
8be1f5c8
FB
431 ret = get_queue(s);
432 else
433 ret = s->rx;
35db099d 434 SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
8be1f5c8 435 return ret;
e80cfcfc
FB
436 default:
437 break;
438 }
439 return 0;
440}
441
442static int serial_can_receive(void *opaque)
443{
444 ChannelState *s = opaque;
e4a89056
FB
445 int ret;
446
e80cfcfc
FB
447 if (((s->wregs[3] & 1) == 0) // Rx not enabled
448 || ((s->rregs[0] & 1) == 1)) // char already available
e4a89056 449 ret = 0;
e80cfcfc 450 else
e4a89056 451 ret = 1;
35db099d 452 //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
e4a89056 453 return ret;
e80cfcfc
FB
454}
455
456static void serial_receive_byte(ChannelState *s, int ch)
457{
35db099d 458 SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
e80cfcfc
FB
459 s->rregs[0] |= 1;
460 s->rx = ch;
ba3c64fb 461 set_rxint(s);
e80cfcfc
FB
462}
463
464static void serial_receive_break(ChannelState *s)
465{
466 s->rregs[0] |= 0x80;
467 slavio_serial_update_irq(s);
468}
469
470static void serial_receive1(void *opaque, const uint8_t *buf, int size)
471{
472 ChannelState *s = opaque;
473 serial_receive_byte(s, buf[0]);
474}
475
476static void serial_event(void *opaque, int event)
477{
478 ChannelState *s = opaque;
479 if (event == CHR_EVENT_BREAK)
480 serial_receive_break(s);
481}
482
483static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
484 slavio_serial_mem_readb,
485 slavio_serial_mem_readb,
486 slavio_serial_mem_readb,
487};
488
489static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
490 slavio_serial_mem_writeb,
491 slavio_serial_mem_writeb,
492 slavio_serial_mem_writeb,
493};
494
495static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
496{
497 qemu_put_be32s(f, &s->irq);
498 qemu_put_be32s(f, &s->reg);
499 qemu_put_be32s(f, &s->rxint);
500 qemu_put_be32s(f, &s->txint);
e4a89056
FB
501 qemu_put_be32s(f, &s->rxint_under_svc);
502 qemu_put_be32s(f, &s->txint_under_svc);
e80cfcfc
FB
503 qemu_put_8s(f, &s->rx);
504 qemu_put_8s(f, &s->tx);
505 qemu_put_buffer(f, s->wregs, 16);
506 qemu_put_buffer(f, s->rregs, 16);
507}
508
509static void slavio_serial_save(QEMUFile *f, void *opaque)
510{
511 SerialState *s = opaque;
512
513 slavio_serial_save_chn(f, &s->chn[0]);
514 slavio_serial_save_chn(f, &s->chn[1]);
515}
516
517static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
518{
e4a89056 519 if (version_id > 2)
e80cfcfc
FB
520 return -EINVAL;
521
522 qemu_get_be32s(f, &s->irq);
523 qemu_get_be32s(f, &s->reg);
524 qemu_get_be32s(f, &s->rxint);
525 qemu_get_be32s(f, &s->txint);
e4a89056
FB
526 if (version_id >= 2) {
527 qemu_get_be32s(f, &s->rxint_under_svc);
528 qemu_get_be32s(f, &s->txint_under_svc);
529 }
e80cfcfc
FB
530 qemu_get_8s(f, &s->rx);
531 qemu_get_8s(f, &s->tx);
532 qemu_get_buffer(f, s->wregs, 16);
533 qemu_get_buffer(f, s->rregs, 16);
534 return 0;
535}
536
537static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
538{
539 SerialState *s = opaque;
540 int ret;
541
542 ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
543 if (ret != 0)
544 return ret;
545 ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
546 return ret;
547
548}
549
52cc07d0
BS
550SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1,
551 CharDriverState *chr2, void *intctl)
e80cfcfc 552{
8be1f5c8 553 int slavio_serial_io_memory, i;
e80cfcfc
FB
554 SerialState *s;
555
556 s = qemu_mallocz(sizeof(SerialState));
557 if (!s)
558 return NULL;
e80cfcfc
FB
559
560 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
561 cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
562
8be1f5c8
FB
563 s->chn[0].chr = chr1;
564 s->chn[1].chr = chr2;
565
566 for (i = 0; i < 2; i++) {
567 s->chn[i].irq = irq;
568 s->chn[i].chn = 1 - i;
569 s->chn[i].type = ser;
52cc07d0 570 s->chn[i].intctl = intctl;
8be1f5c8 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
52cc07d0 668void slavio_serial_ms_kbd_init(int base, int irq, void *intctl)
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;
52cc07d0 680 s->chn[i].intctl = intctl;
8be1f5c8
FB
681 }
682 s->chn[0].otherchn = &s->chn[1];
683 s->chn[1].otherchn = &s->chn[0];
684 s->chn[0].type = mouse;
685 s->chn[1].type = kbd;
e80cfcfc
FB
686
687 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
688 cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
689
455204eb 690 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
8be1f5c8 691 qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
e80cfcfc
FB
692 qemu_register_reset(slavio_serial_reset, s);
693 slavio_serial_reset(s);
694}