]> git.proxmox.com Git - qemu.git/blob - hw/escc.c
93bc4bde39312107b488db6e930b54a34a55ef4f
[qemu.git] / hw / escc.c
1 /*
2 * QEMU ESCC (Z8030/Z8530/Z85C30/SCC/ESCC) serial port emulation
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
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
25 #include "hw.h"
26 #include "sysbus.h"
27 #include "escc.h"
28 #include "qemu-char.h"
29 #include "console.h"
30
31 /* debug serial */
32 //#define DEBUG_SERIAL
33
34 /* debug keyboard */
35 //#define DEBUG_KBD
36
37 /* debug mouse */
38 //#define DEBUG_MOUSE
39
40 /*
41 * On Sparc32 this is the serial port, mouse and keyboard part of chip STP2001
42 * (Slave I/O), also produced as NCR89C105. See
43 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
44 *
45 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
46 * mouse and keyboard ports don't implement all functions and they are
47 * only asynchronous. There is no DMA.
48 *
49 * Z85C30 is also used on PowerMacs. There are some small differences
50 * between Sparc version (sunzilog) and PowerMac (pmac):
51 * Offset between control and data registers
52 * There is some kind of lockup bug, but we can ignore it
53 * CTS is inverted
54 * DMA on pmac using DBDMA chip
55 * pmac can do IRDA and faster rates, sunzilog can only do 38400
56 * pmac baud rate generator clock is 3.6864 MHz, sunzilog 4.9152 MHz
57 */
58
59 /*
60 * Modifications:
61 * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented
62 * serial mouse queue.
63 * Implemented serial mouse protocol.
64 */
65
66 #ifdef DEBUG_SERIAL
67 #define SER_DPRINTF(fmt, ...) \
68 do { printf("SER: " fmt , ## __VA_ARGS__); } while (0)
69 #else
70 #define SER_DPRINTF(fmt, ...)
71 #endif
72 #ifdef DEBUG_KBD
73 #define KBD_DPRINTF(fmt, ...) \
74 do { printf("KBD: " fmt , ## __VA_ARGS__); } while (0)
75 #else
76 #define KBD_DPRINTF(fmt, ...)
77 #endif
78 #ifdef DEBUG_MOUSE
79 #define MS_DPRINTF(fmt, ...) \
80 do { printf("MSC: " fmt , ## __VA_ARGS__); } while (0)
81 #else
82 #define MS_DPRINTF(fmt, ...)
83 #endif
84
85 typedef enum {
86 chn_a, chn_b,
87 } chn_id_t;
88
89 #define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
90
91 typedef enum {
92 ser, kbd, mouse,
93 } chn_type_t;
94
95 #define SERIO_QUEUE_SIZE 256
96
97 typedef struct {
98 uint8_t data[SERIO_QUEUE_SIZE];
99 int rptr, wptr, count;
100 } SERIOQueue;
101
102 #define SERIAL_REGS 16
103 typedef struct ChannelState {
104 qemu_irq irq;
105 uint32_t reg;
106 uint32_t rxint, txint, rxint_under_svc, txint_under_svc;
107 chn_id_t chn; // this channel, A (base+4) or B (base+0)
108 chn_type_t type;
109 struct ChannelState *otherchn;
110 uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS];
111 SERIOQueue queue;
112 CharDriverState *chr;
113 int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
114 int disabled;
115 int clock;
116 } ChannelState;
117
118 struct SerialState {
119 SysBusDevice busdev;
120 struct ChannelState chn[2];
121 int it_shift;
122 int mmio_index;
123 };
124
125 #define SERIAL_CTRL 0
126 #define SERIAL_DATA 1
127
128 #define W_CMD 0
129 #define CMD_PTR_MASK 0x07
130 #define CMD_CMD_MASK 0x38
131 #define CMD_HI 0x08
132 #define CMD_CLR_TXINT 0x28
133 #define CMD_CLR_IUS 0x38
134 #define W_INTR 1
135 #define INTR_INTALL 0x01
136 #define INTR_TXINT 0x02
137 #define INTR_RXMODEMSK 0x18
138 #define INTR_RXINT1ST 0x08
139 #define INTR_RXINTALL 0x10
140 #define W_IVEC 2
141 #define W_RXCTRL 3
142 #define RXCTRL_RXEN 0x01
143 #define W_TXCTRL1 4
144 #define TXCTRL1_PAREN 0x01
145 #define TXCTRL1_PAREV 0x02
146 #define TXCTRL1_1STOP 0x04
147 #define TXCTRL1_1HSTOP 0x08
148 #define TXCTRL1_2STOP 0x0c
149 #define TXCTRL1_STPMSK 0x0c
150 #define TXCTRL1_CLK1X 0x00
151 #define TXCTRL1_CLK16X 0x40
152 #define TXCTRL1_CLK32X 0x80
153 #define TXCTRL1_CLK64X 0xc0
154 #define TXCTRL1_CLKMSK 0xc0
155 #define W_TXCTRL2 5
156 #define TXCTRL2_TXEN 0x08
157 #define TXCTRL2_BITMSK 0x60
158 #define TXCTRL2_5BITS 0x00
159 #define TXCTRL2_7BITS 0x20
160 #define TXCTRL2_6BITS 0x40
161 #define TXCTRL2_8BITS 0x60
162 #define W_SYNC1 6
163 #define W_SYNC2 7
164 #define W_TXBUF 8
165 #define W_MINTR 9
166 #define MINTR_STATUSHI 0x10
167 #define MINTR_RST_MASK 0xc0
168 #define MINTR_RST_B 0x40
169 #define MINTR_RST_A 0x80
170 #define MINTR_RST_ALL 0xc0
171 #define W_MISC1 10
172 #define W_CLOCK 11
173 #define CLOCK_TRXC 0x08
174 #define W_BRGLO 12
175 #define W_BRGHI 13
176 #define W_MISC2 14
177 #define MISC2_PLLDIS 0x30
178 #define W_EXTINT 15
179 #define EXTINT_DCD 0x08
180 #define EXTINT_SYNCINT 0x10
181 #define EXTINT_CTSINT 0x20
182 #define EXTINT_TXUNDRN 0x40
183 #define EXTINT_BRKINT 0x80
184
185 #define R_STATUS 0
186 #define STATUS_RXAV 0x01
187 #define STATUS_ZERO 0x02
188 #define STATUS_TXEMPTY 0x04
189 #define STATUS_DCD 0x08
190 #define STATUS_SYNC 0x10
191 #define STATUS_CTS 0x20
192 #define STATUS_TXUNDRN 0x40
193 #define STATUS_BRK 0x80
194 #define R_SPEC 1
195 #define SPEC_ALLSENT 0x01
196 #define SPEC_BITS8 0x06
197 #define R_IVEC 2
198 #define IVEC_TXINTB 0x00
199 #define IVEC_LONOINT 0x06
200 #define IVEC_LORXINTA 0x0c
201 #define IVEC_LORXINTB 0x04
202 #define IVEC_LOTXINTA 0x08
203 #define IVEC_HINOINT 0x60
204 #define IVEC_HIRXINTA 0x30
205 #define IVEC_HIRXINTB 0x20
206 #define IVEC_HITXINTA 0x10
207 #define R_INTR 3
208 #define INTR_EXTINTB 0x01
209 #define INTR_TXINTB 0x02
210 #define INTR_RXINTB 0x04
211 #define INTR_EXTINTA 0x08
212 #define INTR_TXINTA 0x10
213 #define INTR_RXINTA 0x20
214 #define R_IPEN 4
215 #define R_TXCTRL1 5
216 #define R_TXCTRL2 6
217 #define R_BC 7
218 #define R_RXBUF 8
219 #define R_RXCTRL 9
220 #define R_MISC 10
221 #define R_MISC1 11
222 #define R_BRGLO 12
223 #define R_BRGHI 13
224 #define R_MISC1I 14
225 #define R_EXTINT 15
226
227 static void handle_kbd_command(ChannelState *s, int val);
228 static int serial_can_receive(void *opaque);
229 static void serial_receive_byte(ChannelState *s, int ch);
230
231 static void clear_queue(void *opaque)
232 {
233 ChannelState *s = opaque;
234 SERIOQueue *q = &s->queue;
235 q->rptr = q->wptr = q->count = 0;
236 }
237
238 static void put_queue(void *opaque, int b)
239 {
240 ChannelState *s = opaque;
241 SERIOQueue *q = &s->queue;
242
243 SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
244 if (q->count >= SERIO_QUEUE_SIZE)
245 return;
246 q->data[q->wptr] = b;
247 if (++q->wptr == SERIO_QUEUE_SIZE)
248 q->wptr = 0;
249 q->count++;
250 serial_receive_byte(s, 0);
251 }
252
253 static uint32_t get_queue(void *opaque)
254 {
255 ChannelState *s = opaque;
256 SERIOQueue *q = &s->queue;
257 int val;
258
259 if (q->count == 0) {
260 return 0;
261 } else {
262 val = q->data[q->rptr];
263 if (++q->rptr == SERIO_QUEUE_SIZE)
264 q->rptr = 0;
265 q->count--;
266 }
267 SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
268 if (q->count > 0)
269 serial_receive_byte(s, 0);
270 return val;
271 }
272
273 static int escc_update_irq_chn(ChannelState *s)
274 {
275 if ((((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||
276 // tx ints enabled, pending
277 ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
278 ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
279 s->rxint == 1) || // rx ints enabled, pending
280 ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
281 (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
282 return 1;
283 }
284 return 0;
285 }
286
287 static void escc_update_irq(ChannelState *s)
288 {
289 int irq;
290
291 irq = escc_update_irq_chn(s);
292 irq |= escc_update_irq_chn(s->otherchn);
293
294 SER_DPRINTF("IRQ = %d\n", irq);
295 qemu_set_irq(s->irq, irq);
296 }
297
298 static void escc_reset_chn(ChannelState *s)
299 {
300 int i;
301
302 s->reg = 0;
303 for (i = 0; i < SERIAL_REGS; i++) {
304 s->rregs[i] = 0;
305 s->wregs[i] = 0;
306 }
307 s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
308 s->wregs[W_MINTR] = MINTR_RST_ALL;
309 s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
310 s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
311 s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
312 EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
313 if (s->disabled)
314 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
315 STATUS_CTS | STATUS_TXUNDRN;
316 else
317 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
318 s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
319
320 s->rx = s->tx = 0;
321 s->rxint = s->txint = 0;
322 s->rxint_under_svc = s->txint_under_svc = 0;
323 s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
324 clear_queue(s);
325 }
326
327 static void escc_reset(void *opaque)
328 {
329 SerialState *s = opaque;
330 escc_reset_chn(&s->chn[0]);
331 escc_reset_chn(&s->chn[1]);
332 }
333
334 static inline void set_rxint(ChannelState *s)
335 {
336 s->rxint = 1;
337 if (!s->txint_under_svc) {
338 s->rxint_under_svc = 1;
339 if (s->chn == chn_a) {
340 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
341 s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
342 else
343 s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
344 } else {
345 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
346 s->rregs[R_IVEC] = IVEC_HIRXINTB;
347 else
348 s->rregs[R_IVEC] = IVEC_LORXINTB;
349 }
350 }
351 if (s->chn == chn_a)
352 s->rregs[R_INTR] |= INTR_RXINTA;
353 else
354 s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
355 escc_update_irq(s);
356 }
357
358 static inline void set_txint(ChannelState *s)
359 {
360 s->txint = 1;
361 if (!s->rxint_under_svc) {
362 s->txint_under_svc = 1;
363 if (s->chn == chn_a) {
364 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
365 s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
366 else
367 s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
368 } else {
369 s->rregs[R_IVEC] = IVEC_TXINTB;
370 }
371 }
372 if (s->chn == chn_a)
373 s->rregs[R_INTR] |= INTR_TXINTA;
374 else
375 s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
376 escc_update_irq(s);
377 }
378
379 static inline void clr_rxint(ChannelState *s)
380 {
381 s->rxint = 0;
382 s->rxint_under_svc = 0;
383 if (s->chn == chn_a) {
384 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
385 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
386 else
387 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
388 s->rregs[R_INTR] &= ~INTR_RXINTA;
389 } else {
390 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
391 s->rregs[R_IVEC] = IVEC_HINOINT;
392 else
393 s->rregs[R_IVEC] = IVEC_LONOINT;
394 s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
395 }
396 if (s->txint)
397 set_txint(s);
398 escc_update_irq(s);
399 }
400
401 static inline void clr_txint(ChannelState *s)
402 {
403 s->txint = 0;
404 s->txint_under_svc = 0;
405 if (s->chn == chn_a) {
406 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
407 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
408 else
409 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
410 s->rregs[R_INTR] &= ~INTR_TXINTA;
411 } else {
412 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
413 s->rregs[R_IVEC] = IVEC_HINOINT;
414 else
415 s->rregs[R_IVEC] = IVEC_LONOINT;
416 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
417 }
418 if (s->rxint)
419 set_rxint(s);
420 escc_update_irq(s);
421 }
422
423 static void escc_update_parameters(ChannelState *s)
424 {
425 int speed, parity, data_bits, stop_bits;
426 QEMUSerialSetParams ssp;
427
428 if (!s->chr || s->type != ser)
429 return;
430
431 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
432 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
433 parity = 'E';
434 else
435 parity = 'O';
436 } else {
437 parity = 'N';
438 }
439 if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
440 stop_bits = 2;
441 else
442 stop_bits = 1;
443 switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
444 case TXCTRL2_5BITS:
445 data_bits = 5;
446 break;
447 case TXCTRL2_7BITS:
448 data_bits = 7;
449 break;
450 case TXCTRL2_6BITS:
451 data_bits = 6;
452 break;
453 default:
454 case TXCTRL2_8BITS:
455 data_bits = 8;
456 break;
457 }
458 speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
459 switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
460 case TXCTRL1_CLK1X:
461 break;
462 case TXCTRL1_CLK16X:
463 speed /= 16;
464 break;
465 case TXCTRL1_CLK32X:
466 speed /= 32;
467 break;
468 default:
469 case TXCTRL1_CLK64X:
470 speed /= 64;
471 break;
472 }
473 ssp.speed = speed;
474 ssp.parity = parity;
475 ssp.data_bits = data_bits;
476 ssp.stop_bits = stop_bits;
477 SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
478 speed, parity, data_bits, stop_bits);
479 qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
480 }
481
482 static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
483 {
484 SerialState *serial = opaque;
485 ChannelState *s;
486 uint32_t saddr;
487 int newreg, channel;
488
489 val &= 0xff;
490 saddr = (addr >> serial->it_shift) & 1;
491 channel = (addr >> (serial->it_shift + 1)) & 1;
492 s = &serial->chn[channel];
493 switch (saddr) {
494 case SERIAL_CTRL:
495 SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
496 val & 0xff);
497 newreg = 0;
498 switch (s->reg) {
499 case W_CMD:
500 newreg = val & CMD_PTR_MASK;
501 val &= CMD_CMD_MASK;
502 switch (val) {
503 case CMD_HI:
504 newreg |= CMD_HI;
505 break;
506 case CMD_CLR_TXINT:
507 clr_txint(s);
508 break;
509 case CMD_CLR_IUS:
510 if (s->rxint_under_svc)
511 clr_rxint(s);
512 else if (s->txint_under_svc)
513 clr_txint(s);
514 break;
515 default:
516 break;
517 }
518 break;
519 case W_INTR ... W_RXCTRL:
520 case W_SYNC1 ... W_TXBUF:
521 case W_MISC1 ... W_CLOCK:
522 case W_MISC2 ... W_EXTINT:
523 s->wregs[s->reg] = val;
524 break;
525 case W_TXCTRL1:
526 case W_TXCTRL2:
527 s->wregs[s->reg] = val;
528 escc_update_parameters(s);
529 break;
530 case W_BRGLO:
531 case W_BRGHI:
532 s->wregs[s->reg] = val;
533 s->rregs[s->reg] = val;
534 escc_update_parameters(s);
535 break;
536 case W_MINTR:
537 switch (val & MINTR_RST_MASK) {
538 case 0:
539 default:
540 break;
541 case MINTR_RST_B:
542 escc_reset_chn(&serial->chn[0]);
543 return;
544 case MINTR_RST_A:
545 escc_reset_chn(&serial->chn[1]);
546 return;
547 case MINTR_RST_ALL:
548 escc_reset(serial);
549 return;
550 }
551 break;
552 default:
553 break;
554 }
555 if (s->reg == 0)
556 s->reg = newreg;
557 else
558 s->reg = 0;
559 break;
560 case SERIAL_DATA:
561 SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
562 s->tx = val;
563 if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
564 if (s->chr)
565 qemu_chr_write(s->chr, &s->tx, 1);
566 else if (s->type == kbd && !s->disabled) {
567 handle_kbd_command(s, val);
568 }
569 }
570 s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
571 s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
572 set_txint(s);
573 break;
574 default:
575 break;
576 }
577 }
578
579 static uint32_t escc_mem_readb(void *opaque, target_phys_addr_t addr)
580 {
581 SerialState *serial = opaque;
582 ChannelState *s;
583 uint32_t saddr;
584 uint32_t ret;
585 int channel;
586
587 saddr = (addr >> serial->it_shift) & 1;
588 channel = (addr >> (serial->it_shift + 1)) & 1;
589 s = &serial->chn[channel];
590 switch (saddr) {
591 case SERIAL_CTRL:
592 SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
593 s->rregs[s->reg]);
594 ret = s->rregs[s->reg];
595 s->reg = 0;
596 return ret;
597 case SERIAL_DATA:
598 s->rregs[R_STATUS] &= ~STATUS_RXAV;
599 clr_rxint(s);
600 if (s->type == kbd || s->type == mouse)
601 ret = get_queue(s);
602 else
603 ret = s->rx;
604 SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
605 if (s->chr)
606 qemu_chr_accept_input(s->chr);
607 return ret;
608 default:
609 break;
610 }
611 return 0;
612 }
613
614 static int serial_can_receive(void *opaque)
615 {
616 ChannelState *s = opaque;
617 int ret;
618
619 if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
620 || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
621 // char already available
622 ret = 0;
623 else
624 ret = 1;
625 return ret;
626 }
627
628 static void serial_receive_byte(ChannelState *s, int ch)
629 {
630 SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
631 s->rregs[R_STATUS] |= STATUS_RXAV;
632 s->rx = ch;
633 set_rxint(s);
634 }
635
636 static void serial_receive_break(ChannelState *s)
637 {
638 s->rregs[R_STATUS] |= STATUS_BRK;
639 escc_update_irq(s);
640 }
641
642 static void serial_receive1(void *opaque, const uint8_t *buf, int size)
643 {
644 ChannelState *s = opaque;
645 serial_receive_byte(s, buf[0]);
646 }
647
648 static void serial_event(void *opaque, int event)
649 {
650 ChannelState *s = opaque;
651 if (event == CHR_EVENT_BREAK)
652 serial_receive_break(s);
653 }
654
655 static CPUReadMemoryFunc *escc_mem_read[3] = {
656 escc_mem_readb,
657 NULL,
658 NULL,
659 };
660
661 static CPUWriteMemoryFunc *escc_mem_write[3] = {
662 escc_mem_writeb,
663 NULL,
664 NULL,
665 };
666
667 static void escc_save_chn(QEMUFile *f, ChannelState *s)
668 {
669 uint32_t tmp = 0;
670
671 qemu_put_be32s(f, &tmp); /* unused, was IRQ. */
672 qemu_put_be32s(f, &s->reg);
673 qemu_put_be32s(f, &s->rxint);
674 qemu_put_be32s(f, &s->txint);
675 qemu_put_be32s(f, &s->rxint_under_svc);
676 qemu_put_be32s(f, &s->txint_under_svc);
677 qemu_put_8s(f, &s->rx);
678 qemu_put_8s(f, &s->tx);
679 qemu_put_buffer(f, s->wregs, SERIAL_REGS);
680 qemu_put_buffer(f, s->rregs, SERIAL_REGS);
681 }
682
683 static void escc_save(QEMUFile *f, void *opaque)
684 {
685 SerialState *s = opaque;
686
687 escc_save_chn(f, &s->chn[0]);
688 escc_save_chn(f, &s->chn[1]);
689 }
690
691 static int escc_load_chn(QEMUFile *f, ChannelState *s, int version_id)
692 {
693 uint32_t tmp;
694
695 if (version_id > 2)
696 return -EINVAL;
697
698 qemu_get_be32s(f, &tmp); /* unused */
699 qemu_get_be32s(f, &s->reg);
700 qemu_get_be32s(f, &s->rxint);
701 qemu_get_be32s(f, &s->txint);
702 if (version_id >= 2) {
703 qemu_get_be32s(f, &s->rxint_under_svc);
704 qemu_get_be32s(f, &s->txint_under_svc);
705 }
706 qemu_get_8s(f, &s->rx);
707 qemu_get_8s(f, &s->tx);
708 qemu_get_buffer(f, s->wregs, SERIAL_REGS);
709 qemu_get_buffer(f, s->rregs, SERIAL_REGS);
710 return 0;
711 }
712
713 static int escc_load(QEMUFile *f, void *opaque, int version_id)
714 {
715 SerialState *s = opaque;
716 int ret;
717
718 ret = escc_load_chn(f, &s->chn[0], version_id);
719 if (ret != 0)
720 return ret;
721 ret = escc_load_chn(f, &s->chn[1], version_id);
722 return ret;
723
724 }
725
726 int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
727 CharDriverState *chrA, CharDriverState *chrB,
728 int clock, int it_shift)
729 {
730 DeviceState *dev;
731 SysBusDevice *s;
732 SerialState *d;
733
734 dev = qdev_create(NULL, "escc");
735 qdev_set_prop_int(dev, "disabled", 0);
736 qdev_set_prop_int(dev, "frequency", clock);
737 qdev_set_prop_int(dev, "it_shift", it_shift);
738 qdev_set_prop_ptr(dev, "chrB", chrB);
739 qdev_set_prop_ptr(dev, "chrA", chrA);
740 qdev_set_prop_int(dev, "chnBtype", ser);
741 qdev_set_prop_int(dev, "chnAtype", ser);
742 qdev_init(dev);
743 s = sysbus_from_qdev(dev);
744 sysbus_connect_irq(s, 0, irqA);
745 sysbus_connect_irq(s, 1, irqB);
746 if (base) {
747 sysbus_mmio_map(s, 0, base);
748 }
749
750 d = FROM_SYSBUS(SerialState, s);
751 return d->mmio_index;
752 }
753
754 static const uint8_t keycodes[128] = {
755 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
756 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
757 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
758 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
759 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
760 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
761 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
762 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
763 };
764
765 static const uint8_t e0_keycodes[128] = {
766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
769 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
770 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
771 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773 1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
774 };
775
776 static void sunkbd_event(void *opaque, int ch)
777 {
778 ChannelState *s = opaque;
779 int release = ch & 0x80;
780
781 KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" :
782 "press");
783 switch (ch) {
784 case 58: // Caps lock press
785 s->caps_lock_mode ^= 1;
786 if (s->caps_lock_mode == 2)
787 return; // Drop second press
788 break;
789 case 69: // Num lock press
790 s->num_lock_mode ^= 1;
791 if (s->num_lock_mode == 2)
792 return; // Drop second press
793 break;
794 case 186: // Caps lock release
795 s->caps_lock_mode ^= 2;
796 if (s->caps_lock_mode == 3)
797 return; // Drop first release
798 break;
799 case 197: // Num lock release
800 s->num_lock_mode ^= 2;
801 if (s->num_lock_mode == 3)
802 return; // Drop first release
803 break;
804 case 0xe0:
805 s->e0_mode = 1;
806 return;
807 default:
808 break;
809 }
810 if (s->e0_mode) {
811 s->e0_mode = 0;
812 ch = e0_keycodes[ch & 0x7f];
813 } else {
814 ch = keycodes[ch & 0x7f];
815 }
816 KBD_DPRINTF("Translated keycode %2.2x\n", ch);
817 put_queue(s, ch | release);
818 }
819
820 static void handle_kbd_command(ChannelState *s, int val)
821 {
822 KBD_DPRINTF("Command %d\n", val);
823 if (s->led_mode) { // Ignore led byte
824 s->led_mode = 0;
825 return;
826 }
827 switch (val) {
828 case 1: // Reset, return type code
829 clear_queue(s);
830 put_queue(s, 0xff);
831 put_queue(s, 4); // Type 4
832 put_queue(s, 0x7f);
833 break;
834 case 0xe: // Set leds
835 s->led_mode = 1;
836 break;
837 case 7: // Query layout
838 case 0xf:
839 clear_queue(s);
840 put_queue(s, 0xfe);
841 put_queue(s, 0); // XXX, layout?
842 break;
843 default:
844 break;
845 }
846 }
847
848 static void sunmouse_event(void *opaque,
849 int dx, int dy, int dz, int buttons_state)
850 {
851 ChannelState *s = opaque;
852 int ch;
853
854 MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
855
856 ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
857
858 if (buttons_state & MOUSE_EVENT_LBUTTON)
859 ch ^= 0x4;
860 if (buttons_state & MOUSE_EVENT_MBUTTON)
861 ch ^= 0x2;
862 if (buttons_state & MOUSE_EVENT_RBUTTON)
863 ch ^= 0x1;
864
865 put_queue(s, ch);
866
867 ch = dx;
868
869 if (ch > 127)
870 ch=127;
871 else if (ch < -127)
872 ch=-127;
873
874 put_queue(s, ch & 0xff);
875
876 ch = -dy;
877
878 if (ch > 127)
879 ch=127;
880 else if (ch < -127)
881 ch=-127;
882
883 put_queue(s, ch & 0xff);
884
885 // MSC protocol specify two extra motion bytes
886
887 put_queue(s, 0);
888 put_queue(s, 0);
889 }
890
891 void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
892 int disabled, int clock, int it_shift)
893 {
894 DeviceState *dev;
895 SysBusDevice *s;
896
897 dev = qdev_create(NULL, "escc");
898 qdev_set_prop_int(dev, "disabled", disabled);
899 qdev_set_prop_int(dev, "frequency", clock);
900 qdev_set_prop_int(dev, "it_shift", it_shift);
901 qdev_set_prop_ptr(dev, "chrB", NULL);
902 qdev_set_prop_ptr(dev, "chrA", NULL);
903 qdev_set_prop_int(dev, "chnBtype", mouse);
904 qdev_set_prop_int(dev, "chnAtype", kbd);
905 qdev_init(dev);
906 s = sysbus_from_qdev(dev);
907 sysbus_connect_irq(s, 0, irq);
908 sysbus_connect_irq(s, 1, irq);
909 sysbus_mmio_map(s, 0, base);
910 }
911
912 static void escc_init1(SysBusDevice *dev)
913 {
914 SerialState *s = FROM_SYSBUS(SerialState, dev);
915 int io;
916 unsigned int i;
917 uint32_t clock, disabled;
918
919 s->it_shift = qdev_get_prop_int(&dev->qdev, "it_shift", 0);
920 clock = qdev_get_prop_int(&dev->qdev, "frequency", 0);
921 s->chn[0].chr = qdev_get_prop_ptr(&dev->qdev, "chrB");
922 s->chn[1].chr = qdev_get_prop_ptr(&dev->qdev, "chrA");
923 disabled = qdev_get_prop_int(&dev->qdev, "disabled", 0);
924 s->chn[0].disabled = disabled;
925 s->chn[1].disabled = disabled;
926 for (i = 0; i < 2; i++) {
927 sysbus_init_irq(dev, &s->chn[i].irq);
928 s->chn[i].chn = 1 - i;
929 s->chn[i].clock = clock / 2;
930 if (s->chn[i].chr) {
931 qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
932 serial_receive1, serial_event, &s->chn[i]);
933 }
934 }
935 s->chn[0].otherchn = &s->chn[1];
936 s->chn[1].otherchn = &s->chn[0];
937 s->chn[0].type = qdev_get_prop_int(&dev->qdev, "chnBtype", 0);
938 s->chn[1].type = qdev_get_prop_int(&dev->qdev, "chnAtype", 0);
939
940 io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s);
941 sysbus_init_mmio(dev, ESCC_SIZE << s->it_shift, io);
942 s->mmio_index = io;
943
944 if (s->chn[0].type == mouse) {
945 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
946 "QEMU Sun Mouse");
947 }
948 if (s->chn[1].type == kbd) {
949 qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
950 }
951 register_savevm("escc", -1, 2, escc_save, escc_load, s);
952 qemu_register_reset(escc_reset, s);
953 escc_reset(s);
954 }
955
956 static SysBusDeviceInfo escc_info = {
957 .init = escc_init1,
958 .qdev.name = "escc",
959 .qdev.size = sizeof(SerialState),
960 .qdev.props = (DevicePropList[]) {
961 {.name = "frequency", .type = PROP_TYPE_INT},
962 {.name = "it_shift", .type = PROP_TYPE_INT},
963 {.name = "disabled", .type = PROP_TYPE_INT},
964 {.name = "chrB", .type = PROP_TYPE_PTR},
965 {.name = "chrA", .type = PROP_TYPE_PTR},
966 {.name = "chnBtype", .type = PROP_TYPE_INT},
967 {.name = "chnAtype", .type = PROP_TYPE_INT},
968 {.name = NULL}
969 }
970 };
971
972 static void escc_register_devices(void)
973 {
974 sysbus_register_withprop(&escc_info);
975 }
976
977 device_init(escc_register_devices)