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