]> git.proxmox.com Git - mirror_qemu.git/blame - hw/char/escc.c
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[mirror_qemu.git] / hw / char / escc.c
CommitLineData
e80cfcfc 1/*
b4ed08e0 2 * QEMU ESCC (Z8030/Z8530/Z85C30/SCC/ESCC) 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 */
6c319c82 24
0430891c 25#include "qemu/osdep.h"
83c9f4ca
PB
26#include "hw/hw.h"
27#include "hw/sysbus.h"
0d09e41a 28#include "hw/char/escc.h"
28ecbaee 29#include "ui/console.h"
30c2f238 30#include "trace.h"
e80cfcfc
FB
31
32/*
09330e90
BS
33 * Chipset docs:
34 * "Z80C30/Z85C30/Z80230/Z85230/Z85233 SCC/ESCC User Manual",
35 * http://www.zilog.com/docs/serial/scc_escc_um.pdf
36 *
b4ed08e0 37 * On Sparc32 this is the serial port, mouse and keyboard part of chip STP2001
e80cfcfc
FB
38 * (Slave I/O), also produced as NCR89C105. See
39 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
5fafdf24 40 *
e80cfcfc
FB
41 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
42 * mouse and keyboard ports don't implement all functions and they are
43 * only asynchronous. There is no DMA.
44 *
b4ed08e0
BS
45 * Z85C30 is also used on PowerMacs. There are some small differences
46 * between Sparc version (sunzilog) and PowerMac (pmac):
47 * Offset between control and data registers
48 * There is some kind of lockup bug, but we can ignore it
49 * CTS is inverted
50 * DMA on pmac using DBDMA chip
51 * pmac can do IRDA and faster rates, sunzilog can only do 38400
52 * pmac baud rate generator clock is 3.6864 MHz, sunzilog 4.9152 MHz
e80cfcfc
FB
53 */
54
715748fa
FB
55/*
56 * Modifications:
57 * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented
58 * serial mouse queue.
59 * Implemented serial mouse protocol.
9fc391f8
AT
60 *
61 * 2010-May-23 Artyom Tarasenko: Reworked IUS logic
715748fa
FB
62 */
63
2cc75c32 64#define CHN_C(s) ((s)->chn == escc_chn_b ? 'b' : 'a')
e80cfcfc 65
12abac85
BS
66#define SERIAL_CTRL 0
67#define SERIAL_DATA 1
68
69#define W_CMD 0
70#define CMD_PTR_MASK 0x07
71#define CMD_CMD_MASK 0x38
72#define CMD_HI 0x08
73#define CMD_CLR_TXINT 0x28
74#define CMD_CLR_IUS 0x38
75#define W_INTR 1
76#define INTR_INTALL 0x01
77#define INTR_TXINT 0x02
78#define INTR_RXMODEMSK 0x18
79#define INTR_RXINT1ST 0x08
80#define INTR_RXINTALL 0x10
81#define W_IVEC 2
82#define W_RXCTRL 3
83#define RXCTRL_RXEN 0x01
84#define W_TXCTRL1 4
85#define TXCTRL1_PAREN 0x01
86#define TXCTRL1_PAREV 0x02
87#define TXCTRL1_1STOP 0x04
88#define TXCTRL1_1HSTOP 0x08
89#define TXCTRL1_2STOP 0x0c
90#define TXCTRL1_STPMSK 0x0c
91#define TXCTRL1_CLK1X 0x00
92#define TXCTRL1_CLK16X 0x40
93#define TXCTRL1_CLK32X 0x80
94#define TXCTRL1_CLK64X 0xc0
95#define TXCTRL1_CLKMSK 0xc0
96#define W_TXCTRL2 5
97#define TXCTRL2_TXEN 0x08
98#define TXCTRL2_BITMSK 0x60
99#define TXCTRL2_5BITS 0x00
100#define TXCTRL2_7BITS 0x20
101#define TXCTRL2_6BITS 0x40
102#define TXCTRL2_8BITS 0x60
103#define W_SYNC1 6
104#define W_SYNC2 7
105#define W_TXBUF 8
106#define W_MINTR 9
107#define MINTR_STATUSHI 0x10
108#define MINTR_RST_MASK 0xc0
109#define MINTR_RST_B 0x40
110#define MINTR_RST_A 0x80
111#define MINTR_RST_ALL 0xc0
112#define W_MISC1 10
113#define W_CLOCK 11
114#define CLOCK_TRXC 0x08
115#define W_BRGLO 12
116#define W_BRGHI 13
117#define W_MISC2 14
118#define MISC2_PLLDIS 0x30
119#define W_EXTINT 15
120#define EXTINT_DCD 0x08
121#define EXTINT_SYNCINT 0x10
122#define EXTINT_CTSINT 0x20
123#define EXTINT_TXUNDRN 0x40
124#define EXTINT_BRKINT 0x80
125
126#define R_STATUS 0
127#define STATUS_RXAV 0x01
128#define STATUS_ZERO 0x02
129#define STATUS_TXEMPTY 0x04
130#define STATUS_DCD 0x08
131#define STATUS_SYNC 0x10
132#define STATUS_CTS 0x20
133#define STATUS_TXUNDRN 0x40
134#define STATUS_BRK 0x80
135#define R_SPEC 1
136#define SPEC_ALLSENT 0x01
137#define SPEC_BITS8 0x06
138#define R_IVEC 2
139#define IVEC_TXINTB 0x00
140#define IVEC_LONOINT 0x06
141#define IVEC_LORXINTA 0x0c
142#define IVEC_LORXINTB 0x04
143#define IVEC_LOTXINTA 0x08
144#define IVEC_HINOINT 0x60
145#define IVEC_HIRXINTA 0x30
146#define IVEC_HIRXINTB 0x20
147#define IVEC_HITXINTA 0x10
148#define R_INTR 3
149#define INTR_EXTINTB 0x01
150#define INTR_TXINTB 0x02
151#define INTR_RXINTB 0x04
152#define INTR_EXTINTA 0x08
153#define INTR_TXINTA 0x10
154#define INTR_RXINTA 0x20
155#define R_IPEN 4
156#define R_TXCTRL1 5
157#define R_TXCTRL2 6
158#define R_BC 7
159#define R_RXBUF 8
160#define R_RXCTRL 9
161#define R_MISC 10
162#define R_MISC1 11
163#define R_BRGLO 12
164#define R_BRGHI 13
165#define R_MISC1I 14
166#define R_EXTINT 15
e80cfcfc 167
2cc75c32 168static void handle_kbd_command(ESCCChannelState *s, int val);
8be1f5c8 169static int serial_can_receive(void *opaque);
2cc75c32 170static void serial_receive_byte(ESCCChannelState *s, int ch);
8be1f5c8 171
67deb562
BS
172static void clear_queue(void *opaque)
173{
2cc75c32
LV
174 ESCCChannelState *s = opaque;
175 ESCCSERIOQueue *q = &s->queue;
67deb562
BS
176 q->rptr = q->wptr = q->count = 0;
177}
178
8be1f5c8
FB
179static void put_queue(void *opaque, int b)
180{
2cc75c32
LV
181 ESCCChannelState *s = opaque;
182 ESCCSERIOQueue *q = &s->queue;
8be1f5c8 183
30c2f238 184 trace_escc_put_queue(CHN_C(s), b);
2cc75c32 185 if (q->count >= ESCC_SERIO_QUEUE_SIZE) {
8be1f5c8 186 return;
2cc75c32 187 }
8be1f5c8 188 q->data[q->wptr] = b;
2cc75c32 189 if (++q->wptr == ESCC_SERIO_QUEUE_SIZE) {
8be1f5c8 190 q->wptr = 0;
2cc75c32 191 }
8be1f5c8
FB
192 q->count++;
193 serial_receive_byte(s, 0);
194}
195
196static uint32_t get_queue(void *opaque)
197{
2cc75c32
LV
198 ESCCChannelState *s = opaque;
199 ESCCSERIOQueue *q = &s->queue;
8be1f5c8 200 int val;
3b46e624 201
8be1f5c8 202 if (q->count == 0) {
f930d07e 203 return 0;
8be1f5c8
FB
204 } else {
205 val = q->data[q->rptr];
2cc75c32 206 if (++q->rptr == ESCC_SERIO_QUEUE_SIZE) {
8be1f5c8 207 q->rptr = 0;
2cc75c32 208 }
8be1f5c8
FB
209 q->count--;
210 }
30c2f238 211 trace_escc_get_queue(CHN_C(s), val);
8be1f5c8 212 if (q->count > 0)
f930d07e 213 serial_receive_byte(s, 0);
8be1f5c8
FB
214 return val;
215}
216
2cc75c32 217static int escc_update_irq_chn(ESCCChannelState *s)
e80cfcfc 218{
9fc391f8 219 if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
12abac85
BS
220 // tx ints enabled, pending
221 ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
222 ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
f930d07e 223 s->rxint == 1) || // rx ints enabled, pending
12abac85
BS
224 ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
225 (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
e4a89056 226 return 1;
e80cfcfc 227 }
e4a89056
FB
228 return 0;
229}
230
2cc75c32 231static void escc_update_irq(ESCCChannelState *s)
e4a89056
FB
232{
233 int irq;
234
b4ed08e0
BS
235 irq = escc_update_irq_chn(s);
236 irq |= escc_update_irq_chn(s->otherchn);
e4a89056 237
30c2f238 238 trace_escc_update_irq(irq);
d537cf6c 239 qemu_set_irq(s->irq, irq);
e80cfcfc
FB
240}
241
2cc75c32 242static void escc_reset_chn(ESCCChannelState *s)
e80cfcfc
FB
243{
244 int i;
245
246 s->reg = 0;
2cc75c32 247 for (i = 0; i < ESCC_SERIAL_REGS; i++) {
f930d07e
BS
248 s->rregs[i] = 0;
249 s->wregs[i] = 0;
e80cfcfc 250 }
12abac85
BS
251 s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
252 s->wregs[W_MINTR] = MINTR_RST_ALL;
253 s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
254 s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
255 s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
256 EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
577390ff 257 if (s->disabled)
12abac85
BS
258 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
259 STATUS_CTS | STATUS_TXUNDRN;
577390ff 260 else
12abac85 261 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
f48c537d 262 s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
e80cfcfc
FB
263
264 s->rx = s->tx = 0;
265 s->rxint = s->txint = 0;
e4a89056 266 s->rxint_under_svc = s->txint_under_svc = 0;
bbbb2f0a 267 s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
67deb562 268 clear_queue(s);
e80cfcfc
FB
269}
270
bdb78cae 271static void escc_reset(DeviceState *d)
e80cfcfc 272{
81069b20 273 ESCCState *s = ESCC(d);
bdb78cae 274
b4ed08e0
BS
275 escc_reset_chn(&s->chn[0]);
276 escc_reset_chn(&s->chn[1]);
e80cfcfc
FB
277}
278
2cc75c32 279static inline void set_rxint(ESCCChannelState *s)
ba3c64fb
FB
280{
281 s->rxint = 1;
2cc75c32 282 /* XXX: missing daisy chainnig: escc_chn_b rx should have a lower priority
9fc391f8
AT
283 than chn_a rx/tx/special_condition service*/
284 s->rxint_under_svc = 1;
2cc75c32 285 if (s->chn == escc_chn_a) {
12abac85 286 s->rregs[R_INTR] |= INTR_RXINTA;
9fc391f8
AT
287 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
288 s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
289 else
290 s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
291 } else {
12abac85 292 s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
9fc391f8
AT
293 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
294 s->rregs[R_IVEC] = IVEC_HIRXINTB;
295 else
296 s->rregs[R_IVEC] = IVEC_LORXINTB;
297 }
b4ed08e0 298 escc_update_irq(s);
ba3c64fb
FB
299}
300
2cc75c32 301static inline void set_txint(ESCCChannelState *s)
80637a6a
BS
302{
303 s->txint = 1;
304 if (!s->rxint_under_svc) {
305 s->txint_under_svc = 1;
2cc75c32 306 if (s->chn == escc_chn_a) {
f53671c0
AJ
307 if (s->wregs[W_INTR] & INTR_TXINT) {
308 s->rregs[R_INTR] |= INTR_TXINTA;
309 }
80637a6a
BS
310 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
311 s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
312 else
313 s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
314 } else {
315 s->rregs[R_IVEC] = IVEC_TXINTB;
f53671c0
AJ
316 if (s->wregs[W_INTR] & INTR_TXINT) {
317 s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
318 }
80637a6a 319 }
b4ed08e0 320 escc_update_irq(s);
9fc391f8 321 }
80637a6a
BS
322}
323
2cc75c32 324static inline void clr_rxint(ESCCChannelState *s)
80637a6a
BS
325{
326 s->rxint = 0;
327 s->rxint_under_svc = 0;
2cc75c32 328 if (s->chn == escc_chn_a) {
80637a6a
BS
329 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
330 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
331 else
332 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
333 s->rregs[R_INTR] &= ~INTR_RXINTA;
334 } else {
335 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
336 s->rregs[R_IVEC] = IVEC_HINOINT;
337 else
338 s->rregs[R_IVEC] = IVEC_LONOINT;
339 s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
340 }
341 if (s->txint)
342 set_txint(s);
b4ed08e0 343 escc_update_irq(s);
80637a6a
BS
344}
345
2cc75c32 346static inline void clr_txint(ESCCChannelState *s)
ba3c64fb
FB
347{
348 s->txint = 0;
e4a89056 349 s->txint_under_svc = 0;
2cc75c32 350 if (s->chn == escc_chn_a) {
12abac85
BS
351 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
352 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
b9652ca3 353 else
12abac85
BS
354 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
355 s->rregs[R_INTR] &= ~INTR_TXINTA;
b9652ca3 356 } else {
9fc391f8 357 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
12abac85
BS
358 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
359 s->rregs[R_IVEC] = IVEC_HINOINT;
b9652ca3 360 else
12abac85
BS
361 s->rregs[R_IVEC] = IVEC_LONOINT;
362 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
b9652ca3 363 }
e4a89056
FB
364 if (s->rxint)
365 set_rxint(s);
b4ed08e0 366 escc_update_irq(s);
ba3c64fb
FB
367}
368
2cc75c32 369static void escc_update_parameters(ESCCChannelState *s)
35db099d
FB
370{
371 int speed, parity, data_bits, stop_bits;
372 QEMUSerialSetParams ssp;
373
2cc75c32 374 if (!qemu_chr_fe_backend_connected(&s->chr) || s->type != escc_serial)
35db099d
FB
375 return;
376
12abac85
BS
377 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
378 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
35db099d
FB
379 parity = 'E';
380 else
381 parity = 'O';
382 } else {
383 parity = 'N';
384 }
12abac85 385 if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
35db099d
FB
386 stop_bits = 2;
387 else
388 stop_bits = 1;
12abac85
BS
389 switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
390 case TXCTRL2_5BITS:
35db099d
FB
391 data_bits = 5;
392 break;
12abac85 393 case TXCTRL2_7BITS:
35db099d
FB
394 data_bits = 7;
395 break;
12abac85 396 case TXCTRL2_6BITS:
35db099d
FB
397 data_bits = 6;
398 break;
399 default:
12abac85 400 case TXCTRL2_8BITS:
35db099d
FB
401 data_bits = 8;
402 break;
403 }
b4ed08e0 404 speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
12abac85
BS
405 switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
406 case TXCTRL1_CLK1X:
35db099d 407 break;
12abac85 408 case TXCTRL1_CLK16X:
35db099d
FB
409 speed /= 16;
410 break;
12abac85 411 case TXCTRL1_CLK32X:
35db099d
FB
412 speed /= 32;
413 break;
414 default:
12abac85 415 case TXCTRL1_CLK64X:
35db099d
FB
416 speed /= 64;
417 break;
418 }
419 ssp.speed = speed;
420 ssp.parity = parity;
421 ssp.data_bits = data_bits;
422 ssp.stop_bits = stop_bits;
30c2f238 423 trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits);
5345fdb4 424 qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
35db099d
FB
425}
426
a8170e5e 427static void escc_mem_write(void *opaque, hwaddr addr,
23c5e4ca 428 uint64_t val, unsigned size)
e80cfcfc 429{
3cf63ff2 430 ESCCState *serial = opaque;
2cc75c32 431 ESCCChannelState *s;
e80cfcfc
FB
432 uint32_t saddr;
433 int newreg, channel;
434
435 val &= 0xff;
b4ed08e0
BS
436 saddr = (addr >> serial->it_shift) & 1;
437 channel = (addr >> (serial->it_shift + 1)) & 1;
b3ceef24 438 s = &serial->chn[channel];
e80cfcfc 439 switch (saddr) {
12abac85 440 case SERIAL_CTRL:
30c2f238 441 trace_escc_mem_writeb_ctrl(CHN_C(s), s->reg, val & 0xff);
f930d07e
BS
442 newreg = 0;
443 switch (s->reg) {
12abac85
BS
444 case W_CMD:
445 newreg = val & CMD_PTR_MASK;
446 val &= CMD_CMD_MASK;
f930d07e 447 switch (val) {
12abac85
BS
448 case CMD_HI:
449 newreg |= CMD_HI;
f930d07e 450 break;
12abac85 451 case CMD_CLR_TXINT:
ba3c64fb 452 clr_txint(s);
f930d07e 453 break;
12abac85 454 case CMD_CLR_IUS:
9fc391f8
AT
455 if (s->rxint_under_svc) {
456 s->rxint_under_svc = 0;
457 if (s->txint) {
458 set_txint(s);
459 }
460 } else if (s->txint_under_svc) {
461 s->txint_under_svc = 0;
462 }
463 escc_update_irq(s);
f930d07e
BS
464 break;
465 default:
466 break;
467 }
468 break;
12abac85
BS
469 case W_INTR ... W_RXCTRL:
470 case W_SYNC1 ... W_TXBUF:
471 case W_MISC1 ... W_CLOCK:
472 case W_MISC2 ... W_EXTINT:
f930d07e
BS
473 s->wregs[s->reg] = val;
474 break;
12abac85
BS
475 case W_TXCTRL1:
476 case W_TXCTRL2:
796d8286 477 s->wregs[s->reg] = val;
b4ed08e0 478 escc_update_parameters(s);
796d8286 479 break;
12abac85
BS
480 case W_BRGLO:
481 case W_BRGHI:
f930d07e 482 s->wregs[s->reg] = val;
796d8286 483 s->rregs[s->reg] = val;
b4ed08e0 484 escc_update_parameters(s);
f930d07e 485 break;
12abac85
BS
486 case W_MINTR:
487 switch (val & MINTR_RST_MASK) {
f930d07e
BS
488 case 0:
489 default:
490 break;
12abac85 491 case MINTR_RST_B:
b4ed08e0 492 escc_reset_chn(&serial->chn[0]);
f930d07e 493 return;
12abac85 494 case MINTR_RST_A:
b4ed08e0 495 escc_reset_chn(&serial->chn[1]);
f930d07e 496 return;
12abac85 497 case MINTR_RST_ALL:
81069b20 498 escc_reset(DEVICE(serial));
f930d07e
BS
499 return;
500 }
501 break;
502 default:
503 break;
504 }
505 if (s->reg == 0)
506 s->reg = newreg;
507 else
508 s->reg = 0;
509 break;
12abac85 510 case SERIAL_DATA:
30c2f238 511 trace_escc_mem_writeb_data(CHN_C(s), val);
96c4f569 512 s->tx = val;
12abac85 513 if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
30650701 514 if (qemu_chr_fe_backend_connected(&s->chr)) {
6ab3fc32
DB
515 /* XXX this blocks entire thread. Rewrite to use
516 * qemu_chr_fe_write and background I/O callbacks */
5345fdb4 517 qemu_chr_fe_write_all(&s->chr, &s->tx, 1);
2cc75c32 518 } else if (s->type == escc_kbd && !s->disabled) {
f930d07e
BS
519 handle_kbd_command(s, val);
520 }
521 }
12abac85
BS
522 s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
523 s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
96c4f569 524 set_txint(s);
f930d07e 525 break;
e80cfcfc 526 default:
f930d07e 527 break;
e80cfcfc
FB
528 }
529}
530
a8170e5e 531static uint64_t escc_mem_read(void *opaque, hwaddr addr,
23c5e4ca 532 unsigned size)
e80cfcfc 533{
3cf63ff2 534 ESCCState *serial = opaque;
2cc75c32 535 ESCCChannelState *s;
e80cfcfc
FB
536 uint32_t saddr;
537 uint32_t ret;
538 int channel;
539
b4ed08e0
BS
540 saddr = (addr >> serial->it_shift) & 1;
541 channel = (addr >> (serial->it_shift + 1)) & 1;
b3ceef24 542 s = &serial->chn[channel];
e80cfcfc 543 switch (saddr) {
12abac85 544 case SERIAL_CTRL:
30c2f238 545 trace_escc_mem_readb_ctrl(CHN_C(s), s->reg, s->rregs[s->reg]);
f930d07e
BS
546 ret = s->rregs[s->reg];
547 s->reg = 0;
548 return ret;
12abac85
BS
549 case SERIAL_DATA:
550 s->rregs[R_STATUS] &= ~STATUS_RXAV;
ba3c64fb 551 clr_rxint(s);
2cc75c32 552 if (s->type == escc_kbd || s->type == escc_mouse) {
f930d07e 553 ret = get_queue(s);
2cc75c32 554 } else {
f930d07e 555 ret = s->rx;
2cc75c32 556 }
30c2f238 557 trace_escc_mem_readb_data(CHN_C(s), ret);
fa394ed6 558 qemu_chr_fe_accept_input(&s->chr);
f930d07e 559 return ret;
e80cfcfc 560 default:
f930d07e 561 break;
e80cfcfc
FB
562 }
563 return 0;
564}
565
23c5e4ca
AK
566static const MemoryRegionOps escc_mem_ops = {
567 .read = escc_mem_read,
568 .write = escc_mem_write,
569 .endianness = DEVICE_NATIVE_ENDIAN,
570 .valid = {
571 .min_access_size = 1,
572 .max_access_size = 1,
573 },
574};
575
e80cfcfc
FB
576static int serial_can_receive(void *opaque)
577{
2cc75c32 578 ESCCChannelState *s = opaque;
e4a89056
FB
579 int ret;
580
12abac85
BS
581 if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
582 || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
583 // char already available
f930d07e 584 ret = 0;
e80cfcfc 585 else
f930d07e 586 ret = 1;
e4a89056 587 return ret;
e80cfcfc
FB
588}
589
2cc75c32 590static void serial_receive_byte(ESCCChannelState *s, int ch)
e80cfcfc 591{
30c2f238 592 trace_escc_serial_receive_byte(CHN_C(s), ch);
12abac85 593 s->rregs[R_STATUS] |= STATUS_RXAV;
e80cfcfc 594 s->rx = ch;
ba3c64fb 595 set_rxint(s);
e80cfcfc
FB
596}
597
2cc75c32 598static void serial_receive_break(ESCCChannelState *s)
e80cfcfc 599{
12abac85 600 s->rregs[R_STATUS] |= STATUS_BRK;
b4ed08e0 601 escc_update_irq(s);
e80cfcfc
FB
602}
603
604static void serial_receive1(void *opaque, const uint8_t *buf, int size)
605{
2cc75c32 606 ESCCChannelState *s = opaque;
e80cfcfc
FB
607 serial_receive_byte(s, buf[0]);
608}
609
610static void serial_event(void *opaque, int event)
611{
2cc75c32 612 ESCCChannelState *s = opaque;
e80cfcfc
FB
613 if (event == CHR_EVENT_BREAK)
614 serial_receive_break(s);
615}
616
bdb78cae
BS
617static const VMStateDescription vmstate_escc_chn = {
618 .name ="escc_chn",
619 .version_id = 2,
620 .minimum_version_id = 1,
3aff6c2f 621 .fields = (VMStateField[]) {
2cc75c32
LV
622 VMSTATE_UINT32(vmstate_dummy, ESCCChannelState),
623 VMSTATE_UINT32(reg, ESCCChannelState),
624 VMSTATE_UINT32(rxint, ESCCChannelState),
625 VMSTATE_UINT32(txint, ESCCChannelState),
626 VMSTATE_UINT32(rxint_under_svc, ESCCChannelState),
627 VMSTATE_UINT32(txint_under_svc, ESCCChannelState),
628 VMSTATE_UINT8(rx, ESCCChannelState),
629 VMSTATE_UINT8(tx, ESCCChannelState),
630 VMSTATE_BUFFER(wregs, ESCCChannelState),
631 VMSTATE_BUFFER(rregs, ESCCChannelState),
bdb78cae 632 VMSTATE_END_OF_LIST()
e4a89056 633 }
bdb78cae 634};
e80cfcfc 635
bdb78cae
BS
636static const VMStateDescription vmstate_escc = {
637 .name ="escc",
638 .version_id = 2,
639 .minimum_version_id = 1,
3aff6c2f 640 .fields = (VMStateField[]) {
3cf63ff2 641 VMSTATE_STRUCT_ARRAY(chn, ESCCState, 2, 2, vmstate_escc_chn,
2cc75c32 642 ESCCChannelState),
bdb78cae
BS
643 VMSTATE_END_OF_LIST()
644 }
645};
e80cfcfc 646
65e7545e
GH
647static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
648 InputEvent *evt)
e80cfcfc 649{
2cc75c32 650 ESCCChannelState *s = (ESCCChannelState *)dev;
65e7545e 651 int qcode, keycode;
b5a1b443 652 InputKeyEvent *key;
65e7545e 653
568c73a4 654 assert(evt->type == INPUT_EVENT_KIND_KEY);
32bafa8f 655 key = evt->u.key.data;
b5a1b443 656 qcode = qemu_input_key_value_to_qcode(key->key);
977c736f 657 trace_escc_sunkbd_event_in(qcode, QKeyCode_str(qcode),
b5a1b443 658 key->down);
65e7545e
GH
659
660 if (qcode == Q_KEY_CODE_CAPS_LOCK) {
b5a1b443 661 if (key->down) {
65e7545e
GH
662 s->caps_lock_mode ^= 1;
663 if (s->caps_lock_mode == 2) {
664 return; /* Drop second press */
665 }
666 } else {
667 s->caps_lock_mode ^= 2;
668 if (s->caps_lock_mode == 3) {
669 return; /* Drop first release */
670 }
671 }
43febf49 672 }
65e7545e
GH
673
674 if (qcode == Q_KEY_CODE_NUM_LOCK) {
b5a1b443 675 if (key->down) {
65e7545e
GH
676 s->num_lock_mode ^= 1;
677 if (s->num_lock_mode == 2) {
678 return; /* Drop second press */
679 }
680 } else {
681 s->num_lock_mode ^= 2;
682 if (s->num_lock_mode == 3) {
683 return; /* Drop first release */
684 }
685 }
686 }
687
e709a61a
DB
688 if (qcode > qemu_input_map_qcode_to_sun_len) {
689 return;
690 }
691
692 keycode = qemu_input_map_qcode_to_sun[qcode];
b5a1b443 693 if (!key->down) {
65e7545e 694 keycode |= 0x80;
43febf49 695 }
65e7545e
GH
696 trace_escc_sunkbd_event_out(keycode);
697 put_queue(s, keycode);
8be1f5c8
FB
698}
699
65e7545e
GH
700static QemuInputHandler sunkbd_handler = {
701 .name = "sun keyboard",
702 .mask = INPUT_EVENT_MASK_KEY,
703 .event = sunkbd_handle_event,
704};
705
2cc75c32 706static void handle_kbd_command(ESCCChannelState *s, int val)
8be1f5c8 707{
30c2f238 708 trace_escc_kbd_command(val);
43febf49
BS
709 if (s->led_mode) { // Ignore led byte
710 s->led_mode = 0;
711 return;
712 }
8be1f5c8
FB
713 switch (val) {
714 case 1: // Reset, return type code
67deb562 715 clear_queue(s);
f930d07e
BS
716 put_queue(s, 0xff);
717 put_queue(s, 4); // Type 4
718 put_queue(s, 0x7f);
719 break;
43febf49
BS
720 case 0xe: // Set leds
721 s->led_mode = 1;
722 break;
8be1f5c8 723 case 7: // Query layout
67deb562
BS
724 case 0xf:
725 clear_queue(s);
f930d07e 726 put_queue(s, 0xfe);
59e7a130 727 put_queue(s, 0x21); /* en-us layout */
f930d07e 728 break;
8be1f5c8 729 default:
f930d07e 730 break;
8be1f5c8 731 }
e80cfcfc
FB
732}
733
5fafdf24 734static void sunmouse_event(void *opaque,
e80cfcfc
FB
735 int dx, int dy, int dz, int buttons_state)
736{
2cc75c32 737 ESCCChannelState *s = opaque;
e80cfcfc
FB
738 int ch;
739
30c2f238 740 trace_escc_sunmouse_event(dx, dy, buttons_state);
715748fa
FB
741 ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
742
743 if (buttons_state & MOUSE_EVENT_LBUTTON)
744 ch ^= 0x4;
745 if (buttons_state & MOUSE_EVENT_MBUTTON)
746 ch ^= 0x2;
747 if (buttons_state & MOUSE_EVENT_RBUTTON)
748 ch ^= 0x1;
749
750 put_queue(s, ch);
751
752 ch = dx;
753
754 if (ch > 127)
a0d98a71 755 ch = 127;
715748fa 756 else if (ch < -127)
a0d98a71 757 ch = -127;
715748fa
FB
758
759 put_queue(s, ch & 0xff);
760
761 ch = -dy;
762
763 if (ch > 127)
084bd071 764 ch = 127;
715748fa 765 else if (ch < -127)
084bd071 766 ch = -127;
715748fa
FB
767
768 put_queue(s, ch & 0xff);
769
770 // MSC protocol specify two extra motion bytes
771
772 put_queue(s, 0);
773 put_queue(s, 0);
e80cfcfc
FB
774}
775
e7c91369 776static void escc_init1(Object *obj)
6c319c82 777{
e7c91369
XZ
778 ESCCState *s = ESCC(obj);
779 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
6c319c82 780 unsigned int i;
ee6847d1 781
8be1f5c8 782 for (i = 0; i < 2; i++) {
6c319c82 783 sysbus_init_irq(dev, &s->chn[i].irq);
f930d07e 784 s->chn[i].chn = 1 - i;
8be1f5c8
FB
785 }
786 s->chn[0].otherchn = &s->chn[1];
787 s->chn[1].otherchn = &s->chn[0];
e80cfcfc 788
750ecd44 789 sysbus_init_mmio(dev, &s->mmio);
e7c91369
XZ
790}
791
792static void escc_realize(DeviceState *dev, Error **errp)
793{
794 ESCCState *s = ESCC(dev);
795 unsigned int i;
796
4b3eec91
XZ
797 s->chn[0].disabled = s->disabled;
798 s->chn[1].disabled = s->disabled;
799
800 memory_region_init_io(&s->mmio, OBJECT(dev), &escc_mem_ops, s, "escc",
801 ESCC_SIZE << s->it_shift);
802
e7c91369 803 for (i = 0; i < 2; i++) {
30650701 804 if (qemu_chr_fe_backend_connected(&s->chn[i].chr)) {
4b3eec91 805 s->chn[i].clock = s->frequency / 2;
5345fdb4 806 qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
81517ba3 807 serial_receive1, serial_event, NULL,
39ab61c6 808 &s->chn[i], NULL, true);
e7c91369
XZ
809 }
810 }
e80cfcfc 811
2cc75c32 812 if (s->chn[0].type == escc_mouse) {
6c319c82
BS
813 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
814 "QEMU Sun Mouse");
815 }
2cc75c32 816 if (s->chn[1].type == escc_kbd) {
65e7545e
GH
817 s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
818 &sunkbd_handler);
6c319c82 819 }
e80cfcfc 820}
6c319c82 821
999e12bb 822static Property escc_properties[] = {
3cf63ff2
PB
823 DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0),
824 DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0),
825 DEFINE_PROP_UINT32("disabled", ESCCState, disabled, 0),
826 DEFINE_PROP_UINT32("chnBtype", ESCCState, chn[0].type, 0),
827 DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0),
828 DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr),
829 DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr),
999e12bb
AL
830 DEFINE_PROP_END_OF_LIST(),
831};
832
833static void escc_class_init(ObjectClass *klass, void *data)
834{
39bffca2 835 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 836
39bffca2 837 dc->reset = escc_reset;
e7c91369 838 dc->realize = escc_realize;
39bffca2
AL
839 dc->vmsd = &vmstate_escc;
840 dc->props = escc_properties;
f8d4c07c 841 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
999e12bb
AL
842}
843
8c43a6f0 844static const TypeInfo escc_info = {
81069b20 845 .name = TYPE_ESCC,
39bffca2 846 .parent = TYPE_SYS_BUS_DEVICE,
3cf63ff2 847 .instance_size = sizeof(ESCCState),
e7c91369 848 .instance_init = escc_init1,
39bffca2 849 .class_init = escc_class_init,
6c319c82
BS
850};
851
83f7d43a 852static void escc_register_types(void)
6c319c82 853{
39bffca2 854 type_register_static(&escc_info);
6c319c82
BS
855}
856
83f7d43a 857type_init(escc_register_types)