]> git.proxmox.com Git - qemu.git/blame - hw/char/escc.c
acpi-build: fix build on glib < 2.14
[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
83c9f4ca
PB
25#include "hw/hw.h"
26#include "hw/sysbus.h"
0d09e41a 27#include "hw/char/escc.h"
dccfcd0e 28#include "sysemu/char.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
8be1f5c8
FB
64typedef enum {
65 chn_a, chn_b,
8e39a033 66} ChnID;
8be1f5c8 67
35db099d
FB
68#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
69
8be1f5c8
FB
70typedef enum {
71 ser, kbd, mouse,
8e39a033 72} ChnType;
8be1f5c8 73
715748fa 74#define SERIO_QUEUE_SIZE 256
8be1f5c8
FB
75
76typedef struct {
715748fa 77 uint8_t data[SERIO_QUEUE_SIZE];
8be1f5c8 78 int rptr, wptr, count;
715748fa 79} SERIOQueue;
8be1f5c8 80
12abac85 81#define SERIAL_REGS 16
e80cfcfc 82typedef struct ChannelState {
d537cf6c 83 qemu_irq irq;
22548760 84 uint32_t rxint, txint, rxint_under_svc, txint_under_svc;
8be1f5c8 85 struct ChannelState *otherchn;
d7b95534
BS
86 uint32_t reg;
87 uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
715748fa 88 SERIOQueue queue;
e80cfcfc 89 CharDriverState *chr;
bbbb2f0a 90 int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
577390ff 91 int disabled;
b4ed08e0 92 int clock;
bdb78cae 93 uint32_t vmstate_dummy;
d7b95534
BS
94 ChnID chn; // this channel, A (base+4) or B (base+0)
95 ChnType type;
96 uint8_t rx, tx;
e80cfcfc
FB
97} ChannelState;
98
81069b20
AF
99#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
100
3cf63ff2 101typedef struct ESCCState {
81069b20
AF
102 SysBusDevice parent_obj;
103
e80cfcfc 104 struct ChannelState chn[2];
ec02f7de 105 uint32_t it_shift;
23c5e4ca 106 MemoryRegion mmio;
ee6847d1
GH
107 uint32_t disabled;
108 uint32_t frequency;
3cf63ff2 109} ESCCState;
e80cfcfc 110
12abac85
BS
111#define SERIAL_CTRL 0
112#define SERIAL_DATA 1
113
114#define W_CMD 0
115#define CMD_PTR_MASK 0x07
116#define CMD_CMD_MASK 0x38
117#define CMD_HI 0x08
118#define CMD_CLR_TXINT 0x28
119#define CMD_CLR_IUS 0x38
120#define W_INTR 1
121#define INTR_INTALL 0x01
122#define INTR_TXINT 0x02
123#define INTR_RXMODEMSK 0x18
124#define INTR_RXINT1ST 0x08
125#define INTR_RXINTALL 0x10
126#define W_IVEC 2
127#define W_RXCTRL 3
128#define RXCTRL_RXEN 0x01
129#define W_TXCTRL1 4
130#define TXCTRL1_PAREN 0x01
131#define TXCTRL1_PAREV 0x02
132#define TXCTRL1_1STOP 0x04
133#define TXCTRL1_1HSTOP 0x08
134#define TXCTRL1_2STOP 0x0c
135#define TXCTRL1_STPMSK 0x0c
136#define TXCTRL1_CLK1X 0x00
137#define TXCTRL1_CLK16X 0x40
138#define TXCTRL1_CLK32X 0x80
139#define TXCTRL1_CLK64X 0xc0
140#define TXCTRL1_CLKMSK 0xc0
141#define W_TXCTRL2 5
142#define TXCTRL2_TXEN 0x08
143#define TXCTRL2_BITMSK 0x60
144#define TXCTRL2_5BITS 0x00
145#define TXCTRL2_7BITS 0x20
146#define TXCTRL2_6BITS 0x40
147#define TXCTRL2_8BITS 0x60
148#define W_SYNC1 6
149#define W_SYNC2 7
150#define W_TXBUF 8
151#define W_MINTR 9
152#define MINTR_STATUSHI 0x10
153#define MINTR_RST_MASK 0xc0
154#define MINTR_RST_B 0x40
155#define MINTR_RST_A 0x80
156#define MINTR_RST_ALL 0xc0
157#define W_MISC1 10
158#define W_CLOCK 11
159#define CLOCK_TRXC 0x08
160#define W_BRGLO 12
161#define W_BRGHI 13
162#define W_MISC2 14
163#define MISC2_PLLDIS 0x30
164#define W_EXTINT 15
165#define EXTINT_DCD 0x08
166#define EXTINT_SYNCINT 0x10
167#define EXTINT_CTSINT 0x20
168#define EXTINT_TXUNDRN 0x40
169#define EXTINT_BRKINT 0x80
170
171#define R_STATUS 0
172#define STATUS_RXAV 0x01
173#define STATUS_ZERO 0x02
174#define STATUS_TXEMPTY 0x04
175#define STATUS_DCD 0x08
176#define STATUS_SYNC 0x10
177#define STATUS_CTS 0x20
178#define STATUS_TXUNDRN 0x40
179#define STATUS_BRK 0x80
180#define R_SPEC 1
181#define SPEC_ALLSENT 0x01
182#define SPEC_BITS8 0x06
183#define R_IVEC 2
184#define IVEC_TXINTB 0x00
185#define IVEC_LONOINT 0x06
186#define IVEC_LORXINTA 0x0c
187#define IVEC_LORXINTB 0x04
188#define IVEC_LOTXINTA 0x08
189#define IVEC_HINOINT 0x60
190#define IVEC_HIRXINTA 0x30
191#define IVEC_HIRXINTB 0x20
192#define IVEC_HITXINTA 0x10
193#define R_INTR 3
194#define INTR_EXTINTB 0x01
195#define INTR_TXINTB 0x02
196#define INTR_RXINTB 0x04
197#define INTR_EXTINTA 0x08
198#define INTR_TXINTA 0x10
199#define INTR_RXINTA 0x20
200#define R_IPEN 4
201#define R_TXCTRL1 5
202#define R_TXCTRL2 6
203#define R_BC 7
204#define R_RXBUF 8
205#define R_RXCTRL 9
206#define R_MISC 10
207#define R_MISC1 11
208#define R_BRGLO 12
209#define R_BRGHI 13
210#define R_MISC1I 14
211#define R_EXTINT 15
e80cfcfc 212
8be1f5c8
FB
213static void handle_kbd_command(ChannelState *s, int val);
214static int serial_can_receive(void *opaque);
215static void serial_receive_byte(ChannelState *s, int ch);
216
67deb562
BS
217static void clear_queue(void *opaque)
218{
219 ChannelState *s = opaque;
220 SERIOQueue *q = &s->queue;
221 q->rptr = q->wptr = q->count = 0;
222}
223
8be1f5c8
FB
224static void put_queue(void *opaque, int b)
225{
226 ChannelState *s = opaque;
715748fa 227 SERIOQueue *q = &s->queue;
8be1f5c8 228
30c2f238 229 trace_escc_put_queue(CHN_C(s), b);
715748fa 230 if (q->count >= SERIO_QUEUE_SIZE)
8be1f5c8
FB
231 return;
232 q->data[q->wptr] = b;
715748fa 233 if (++q->wptr == SERIO_QUEUE_SIZE)
8be1f5c8
FB
234 q->wptr = 0;
235 q->count++;
236 serial_receive_byte(s, 0);
237}
238
239static uint32_t get_queue(void *opaque)
240{
241 ChannelState *s = opaque;
715748fa 242 SERIOQueue *q = &s->queue;
8be1f5c8 243 int val;
3b46e624 244
8be1f5c8 245 if (q->count == 0) {
f930d07e 246 return 0;
8be1f5c8
FB
247 } else {
248 val = q->data[q->rptr];
715748fa 249 if (++q->rptr == SERIO_QUEUE_SIZE)
8be1f5c8
FB
250 q->rptr = 0;
251 q->count--;
252 }
30c2f238 253 trace_escc_get_queue(CHN_C(s), val);
8be1f5c8 254 if (q->count > 0)
f930d07e 255 serial_receive_byte(s, 0);
8be1f5c8
FB
256 return val;
257}
258
b4ed08e0 259static int escc_update_irq_chn(ChannelState *s)
e80cfcfc 260{
9fc391f8 261 if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
12abac85
BS
262 // tx ints enabled, pending
263 ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
264 ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
f930d07e 265 s->rxint == 1) || // rx ints enabled, pending
12abac85
BS
266 ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
267 (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
e4a89056 268 return 1;
e80cfcfc 269 }
e4a89056
FB
270 return 0;
271}
272
b4ed08e0 273static void escc_update_irq(ChannelState *s)
e4a89056
FB
274{
275 int irq;
276
b4ed08e0
BS
277 irq = escc_update_irq_chn(s);
278 irq |= escc_update_irq_chn(s->otherchn);
e4a89056 279
30c2f238 280 trace_escc_update_irq(irq);
d537cf6c 281 qemu_set_irq(s->irq, irq);
e80cfcfc
FB
282}
283
b4ed08e0 284static void escc_reset_chn(ChannelState *s)
e80cfcfc
FB
285{
286 int i;
287
288 s->reg = 0;
8f180a43 289 for (i = 0; i < SERIAL_REGS; i++) {
f930d07e
BS
290 s->rregs[i] = 0;
291 s->wregs[i] = 0;
e80cfcfc 292 }
12abac85
BS
293 s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
294 s->wregs[W_MINTR] = MINTR_RST_ALL;
295 s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
296 s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
297 s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
298 EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
577390ff 299 if (s->disabled)
12abac85
BS
300 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
301 STATUS_CTS | STATUS_TXUNDRN;
577390ff 302 else
12abac85 303 s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
f48c537d 304 s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
e80cfcfc
FB
305
306 s->rx = s->tx = 0;
307 s->rxint = s->txint = 0;
e4a89056 308 s->rxint_under_svc = s->txint_under_svc = 0;
bbbb2f0a 309 s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
67deb562 310 clear_queue(s);
e80cfcfc
FB
311}
312
bdb78cae 313static void escc_reset(DeviceState *d)
e80cfcfc 314{
81069b20 315 ESCCState *s = ESCC(d);
bdb78cae 316
b4ed08e0
BS
317 escc_reset_chn(&s->chn[0]);
318 escc_reset_chn(&s->chn[1]);
e80cfcfc
FB
319}
320
ba3c64fb
FB
321static inline void set_rxint(ChannelState *s)
322{
323 s->rxint = 1;
9fc391f8
AT
324 /* XXX: missing daisy chainnig: chn_b rx should have a lower priority
325 than chn_a rx/tx/special_condition service*/
326 s->rxint_under_svc = 1;
327 if (s->chn == chn_a) {
12abac85 328 s->rregs[R_INTR] |= INTR_RXINTA;
9fc391f8
AT
329 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
330 s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
331 else
332 s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
333 } else {
12abac85 334 s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
9fc391f8
AT
335 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
336 s->rregs[R_IVEC] = IVEC_HIRXINTB;
337 else
338 s->rregs[R_IVEC] = IVEC_LORXINTB;
339 }
b4ed08e0 340 escc_update_irq(s);
ba3c64fb
FB
341}
342
80637a6a
BS
343static inline void set_txint(ChannelState *s)
344{
345 s->txint = 1;
346 if (!s->rxint_under_svc) {
347 s->txint_under_svc = 1;
348 if (s->chn == chn_a) {
f53671c0
AJ
349 if (s->wregs[W_INTR] & INTR_TXINT) {
350 s->rregs[R_INTR] |= INTR_TXINTA;
351 }
80637a6a
BS
352 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
353 s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
354 else
355 s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
356 } else {
357 s->rregs[R_IVEC] = IVEC_TXINTB;
f53671c0
AJ
358 if (s->wregs[W_INTR] & INTR_TXINT) {
359 s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
360 }
80637a6a 361 }
b4ed08e0 362 escc_update_irq(s);
9fc391f8 363 }
80637a6a
BS
364}
365
366static inline void clr_rxint(ChannelState *s)
367{
368 s->rxint = 0;
369 s->rxint_under_svc = 0;
370 if (s->chn == chn_a) {
371 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
372 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
373 else
374 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
375 s->rregs[R_INTR] &= ~INTR_RXINTA;
376 } else {
377 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
378 s->rregs[R_IVEC] = IVEC_HINOINT;
379 else
380 s->rregs[R_IVEC] = IVEC_LONOINT;
381 s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
382 }
383 if (s->txint)
384 set_txint(s);
b4ed08e0 385 escc_update_irq(s);
80637a6a
BS
386}
387
ba3c64fb
FB
388static inline void clr_txint(ChannelState *s)
389{
390 s->txint = 0;
e4a89056 391 s->txint_under_svc = 0;
b9652ca3 392 if (s->chn == chn_a) {
12abac85
BS
393 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
394 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
b9652ca3 395 else
12abac85
BS
396 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
397 s->rregs[R_INTR] &= ~INTR_TXINTA;
b9652ca3 398 } else {
9fc391f8 399 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
12abac85
BS
400 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
401 s->rregs[R_IVEC] = IVEC_HINOINT;
b9652ca3 402 else
12abac85
BS
403 s->rregs[R_IVEC] = IVEC_LONOINT;
404 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
b9652ca3 405 }
e4a89056
FB
406 if (s->rxint)
407 set_rxint(s);
b4ed08e0 408 escc_update_irq(s);
ba3c64fb
FB
409}
410
b4ed08e0 411static void escc_update_parameters(ChannelState *s)
35db099d
FB
412{
413 int speed, parity, data_bits, stop_bits;
414 QEMUSerialSetParams ssp;
415
416 if (!s->chr || s->type != ser)
417 return;
418
12abac85
BS
419 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
420 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
35db099d
FB
421 parity = 'E';
422 else
423 parity = 'O';
424 } else {
425 parity = 'N';
426 }
12abac85 427 if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
35db099d
FB
428 stop_bits = 2;
429 else
430 stop_bits = 1;
12abac85
BS
431 switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
432 case TXCTRL2_5BITS:
35db099d
FB
433 data_bits = 5;
434 break;
12abac85 435 case TXCTRL2_7BITS:
35db099d
FB
436 data_bits = 7;
437 break;
12abac85 438 case TXCTRL2_6BITS:
35db099d
FB
439 data_bits = 6;
440 break;
441 default:
12abac85 442 case TXCTRL2_8BITS:
35db099d
FB
443 data_bits = 8;
444 break;
445 }
b4ed08e0 446 speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
12abac85
BS
447 switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
448 case TXCTRL1_CLK1X:
35db099d 449 break;
12abac85 450 case TXCTRL1_CLK16X:
35db099d
FB
451 speed /= 16;
452 break;
12abac85 453 case TXCTRL1_CLK32X:
35db099d
FB
454 speed /= 32;
455 break;
456 default:
12abac85 457 case TXCTRL1_CLK64X:
35db099d
FB
458 speed /= 64;
459 break;
460 }
461 ssp.speed = speed;
462 ssp.parity = parity;
463 ssp.data_bits = data_bits;
464 ssp.stop_bits = stop_bits;
30c2f238 465 trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits);
41084f1b 466 qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
35db099d
FB
467}
468
a8170e5e 469static void escc_mem_write(void *opaque, hwaddr addr,
23c5e4ca 470 uint64_t val, unsigned size)
e80cfcfc 471{
3cf63ff2 472 ESCCState *serial = opaque;
e80cfcfc
FB
473 ChannelState *s;
474 uint32_t saddr;
475 int newreg, channel;
476
477 val &= 0xff;
b4ed08e0
BS
478 saddr = (addr >> serial->it_shift) & 1;
479 channel = (addr >> (serial->it_shift + 1)) & 1;
b3ceef24 480 s = &serial->chn[channel];
e80cfcfc 481 switch (saddr) {
12abac85 482 case SERIAL_CTRL:
30c2f238 483 trace_escc_mem_writeb_ctrl(CHN_C(s), s->reg, val & 0xff);
f930d07e
BS
484 newreg = 0;
485 switch (s->reg) {
12abac85
BS
486 case W_CMD:
487 newreg = val & CMD_PTR_MASK;
488 val &= CMD_CMD_MASK;
f930d07e 489 switch (val) {
12abac85
BS
490 case CMD_HI:
491 newreg |= CMD_HI;
f930d07e 492 break;
12abac85 493 case CMD_CLR_TXINT:
ba3c64fb 494 clr_txint(s);
f930d07e 495 break;
12abac85 496 case CMD_CLR_IUS:
9fc391f8
AT
497 if (s->rxint_under_svc) {
498 s->rxint_under_svc = 0;
499 if (s->txint) {
500 set_txint(s);
501 }
502 } else if (s->txint_under_svc) {
503 s->txint_under_svc = 0;
504 }
505 escc_update_irq(s);
f930d07e
BS
506 break;
507 default:
508 break;
509 }
510 break;
12abac85
BS
511 case W_INTR ... W_RXCTRL:
512 case W_SYNC1 ... W_TXBUF:
513 case W_MISC1 ... W_CLOCK:
514 case W_MISC2 ... W_EXTINT:
f930d07e
BS
515 s->wregs[s->reg] = val;
516 break;
12abac85
BS
517 case W_TXCTRL1:
518 case W_TXCTRL2:
796d8286 519 s->wregs[s->reg] = val;
b4ed08e0 520 escc_update_parameters(s);
796d8286 521 break;
12abac85
BS
522 case W_BRGLO:
523 case W_BRGHI:
f930d07e 524 s->wregs[s->reg] = val;
796d8286 525 s->rregs[s->reg] = val;
b4ed08e0 526 escc_update_parameters(s);
f930d07e 527 break;
12abac85
BS
528 case W_MINTR:
529 switch (val & MINTR_RST_MASK) {
f930d07e
BS
530 case 0:
531 default:
532 break;
12abac85 533 case MINTR_RST_B:
b4ed08e0 534 escc_reset_chn(&serial->chn[0]);
f930d07e 535 return;
12abac85 536 case MINTR_RST_A:
b4ed08e0 537 escc_reset_chn(&serial->chn[1]);
f930d07e 538 return;
12abac85 539 case MINTR_RST_ALL:
81069b20 540 escc_reset(DEVICE(serial));
f930d07e
BS
541 return;
542 }
543 break;
544 default:
545 break;
546 }
547 if (s->reg == 0)
548 s->reg = newreg;
549 else
550 s->reg = 0;
551 break;
12abac85 552 case SERIAL_DATA:
30c2f238 553 trace_escc_mem_writeb_data(CHN_C(s), val);
96c4f569 554 s->tx = val;
12abac85 555 if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
f930d07e 556 if (s->chr)
2cc6e0a1 557 qemu_chr_fe_write(s->chr, &s->tx, 1);
577390ff 558 else if (s->type == kbd && !s->disabled) {
f930d07e
BS
559 handle_kbd_command(s, val);
560 }
561 }
12abac85
BS
562 s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
563 s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
96c4f569 564 set_txint(s);
f930d07e 565 break;
e80cfcfc 566 default:
f930d07e 567 break;
e80cfcfc
FB
568 }
569}
570
a8170e5e 571static uint64_t escc_mem_read(void *opaque, hwaddr addr,
23c5e4ca 572 unsigned size)
e80cfcfc 573{
3cf63ff2 574 ESCCState *serial = opaque;
e80cfcfc
FB
575 ChannelState *s;
576 uint32_t saddr;
577 uint32_t ret;
578 int channel;
579
b4ed08e0
BS
580 saddr = (addr >> serial->it_shift) & 1;
581 channel = (addr >> (serial->it_shift + 1)) & 1;
b3ceef24 582 s = &serial->chn[channel];
e80cfcfc 583 switch (saddr) {
12abac85 584 case SERIAL_CTRL:
30c2f238 585 trace_escc_mem_readb_ctrl(CHN_C(s), s->reg, s->rregs[s->reg]);
f930d07e
BS
586 ret = s->rregs[s->reg];
587 s->reg = 0;
588 return ret;
12abac85
BS
589 case SERIAL_DATA:
590 s->rregs[R_STATUS] &= ~STATUS_RXAV;
ba3c64fb 591 clr_rxint(s);
f930d07e
BS
592 if (s->type == kbd || s->type == mouse)
593 ret = get_queue(s);
594 else
595 ret = s->rx;
30c2f238 596 trace_escc_mem_readb_data(CHN_C(s), ret);
b76482e7
BS
597 if (s->chr)
598 qemu_chr_accept_input(s->chr);
f930d07e 599 return ret;
e80cfcfc 600 default:
f930d07e 601 break;
e80cfcfc
FB
602 }
603 return 0;
604}
605
23c5e4ca
AK
606static const MemoryRegionOps escc_mem_ops = {
607 .read = escc_mem_read,
608 .write = escc_mem_write,
609 .endianness = DEVICE_NATIVE_ENDIAN,
610 .valid = {
611 .min_access_size = 1,
612 .max_access_size = 1,
613 },
614};
615
e80cfcfc
FB
616static int serial_can_receive(void *opaque)
617{
618 ChannelState *s = opaque;
e4a89056
FB
619 int ret;
620
12abac85
BS
621 if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
622 || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
623 // char already available
f930d07e 624 ret = 0;
e80cfcfc 625 else
f930d07e 626 ret = 1;
e4a89056 627 return ret;
e80cfcfc
FB
628}
629
630static void serial_receive_byte(ChannelState *s, int ch)
631{
30c2f238 632 trace_escc_serial_receive_byte(CHN_C(s), ch);
12abac85 633 s->rregs[R_STATUS] |= STATUS_RXAV;
e80cfcfc 634 s->rx = ch;
ba3c64fb 635 set_rxint(s);
e80cfcfc
FB
636}
637
638static void serial_receive_break(ChannelState *s)
639{
12abac85 640 s->rregs[R_STATUS] |= STATUS_BRK;
b4ed08e0 641 escc_update_irq(s);
e80cfcfc
FB
642}
643
644static void serial_receive1(void *opaque, const uint8_t *buf, int size)
645{
646 ChannelState *s = opaque;
647 serial_receive_byte(s, buf[0]);
648}
649
650static void serial_event(void *opaque, int event)
651{
652 ChannelState *s = opaque;
653 if (event == CHR_EVENT_BREAK)
654 serial_receive_break(s);
655}
656
bdb78cae
BS
657static const VMStateDescription vmstate_escc_chn = {
658 .name ="escc_chn",
659 .version_id = 2,
660 .minimum_version_id = 1,
661 .minimum_version_id_old = 1,
662 .fields = (VMStateField []) {
663 VMSTATE_UINT32(vmstate_dummy, ChannelState),
664 VMSTATE_UINT32(reg, ChannelState),
665 VMSTATE_UINT32(rxint, ChannelState),
666 VMSTATE_UINT32(txint, ChannelState),
667 VMSTATE_UINT32(rxint_under_svc, ChannelState),
668 VMSTATE_UINT32(txint_under_svc, ChannelState),
669 VMSTATE_UINT8(rx, ChannelState),
670 VMSTATE_UINT8(tx, ChannelState),
671 VMSTATE_BUFFER(wregs, ChannelState),
672 VMSTATE_BUFFER(rregs, ChannelState),
673 VMSTATE_END_OF_LIST()
e4a89056 674 }
bdb78cae 675};
e80cfcfc 676
bdb78cae
BS
677static const VMStateDescription vmstate_escc = {
678 .name ="escc",
679 .version_id = 2,
680 .minimum_version_id = 1,
681 .minimum_version_id_old = 1,
682 .fields = (VMStateField []) {
3cf63ff2 683 VMSTATE_STRUCT_ARRAY(chn, ESCCState, 2, 2, vmstate_escc_chn,
bdb78cae
BS
684 ChannelState),
685 VMSTATE_END_OF_LIST()
686 }
687};
e80cfcfc 688
a8170e5e 689MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
aeeb69c7
AJ
690 CharDriverState *chrA, CharDriverState *chrB,
691 int clock, int it_shift)
e80cfcfc 692{
6c319c82
BS
693 DeviceState *dev;
694 SysBusDevice *s;
3cf63ff2 695 ESCCState *d;
6c319c82 696
81069b20 697 dev = qdev_create(NULL, TYPE_ESCC);
ee6847d1
GH
698 qdev_prop_set_uint32(dev, "disabled", 0);
699 qdev_prop_set_uint32(dev, "frequency", clock);
700 qdev_prop_set_uint32(dev, "it_shift", it_shift);
bc19fcaa
BS
701 qdev_prop_set_chr(dev, "chrB", chrB);
702 qdev_prop_set_chr(dev, "chrA", chrA);
ee6847d1
GH
703 qdev_prop_set_uint32(dev, "chnBtype", ser);
704 qdev_prop_set_uint32(dev, "chnAtype", ser);
e23a1b33 705 qdev_init_nofail(dev);
1356b98d 706 s = SYS_BUS_DEVICE(dev);
e1a0e47f
AJ
707 sysbus_connect_irq(s, 0, irqB);
708 sysbus_connect_irq(s, 1, irqA);
6c319c82
BS
709 if (base) {
710 sysbus_mmio_map(s, 0, base);
e80cfcfc 711 }
6c319c82 712
81069b20 713 d = ESCC(s);
23c5e4ca 714 return &d->mmio;
e80cfcfc
FB
715}
716
8be1f5c8
FB
717static const uint8_t keycodes[128] = {
718 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
719 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
720 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
721 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
722 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
723 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
724 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
725 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
726};
727
43febf49
BS
728static const uint8_t e0_keycodes[128] = {
729 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
730 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
731 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
732 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
733 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
734 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
735 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
c0b5b109 736 1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
43febf49
BS
737};
738
e80cfcfc
FB
739static void sunkbd_event(void *opaque, int ch)
740{
741 ChannelState *s = opaque;
8be1f5c8
FB
742 int release = ch & 0x80;
743
30c2f238 744 trace_escc_sunkbd_event_in(ch);
bbbb2f0a
BS
745 switch (ch) {
746 case 58: // Caps lock press
747 s->caps_lock_mode ^= 1;
748 if (s->caps_lock_mode == 2)
749 return; // Drop second press
750 break;
751 case 69: // Num lock press
752 s->num_lock_mode ^= 1;
753 if (s->num_lock_mode == 2)
754 return; // Drop second press
755 break;
756 case 186: // Caps lock release
757 s->caps_lock_mode ^= 2;
758 if (s->caps_lock_mode == 3)
759 return; // Drop first release
760 break;
761 case 197: // Num lock release
762 s->num_lock_mode ^= 2;
763 if (s->num_lock_mode == 3)
764 return; // Drop first release
765 break;
766 case 0xe0:
43febf49
BS
767 s->e0_mode = 1;
768 return;
bbbb2f0a
BS
769 default:
770 break;
43febf49
BS
771 }
772 if (s->e0_mode) {
773 s->e0_mode = 0;
774 ch = e0_keycodes[ch & 0x7f];
775 } else {
776 ch = keycodes[ch & 0x7f];
777 }
30c2f238 778 trace_escc_sunkbd_event_out(ch);
8be1f5c8
FB
779 put_queue(s, ch | release);
780}
781
782static void handle_kbd_command(ChannelState *s, int val)
783{
30c2f238 784 trace_escc_kbd_command(val);
43febf49
BS
785 if (s->led_mode) { // Ignore led byte
786 s->led_mode = 0;
787 return;
788 }
8be1f5c8
FB
789 switch (val) {
790 case 1: // Reset, return type code
67deb562 791 clear_queue(s);
f930d07e
BS
792 put_queue(s, 0xff);
793 put_queue(s, 4); // Type 4
794 put_queue(s, 0x7f);
795 break;
43febf49
BS
796 case 0xe: // Set leds
797 s->led_mode = 1;
798 break;
8be1f5c8 799 case 7: // Query layout
67deb562
BS
800 case 0xf:
801 clear_queue(s);
f930d07e
BS
802 put_queue(s, 0xfe);
803 put_queue(s, 0); // XXX, layout?
804 break;
8be1f5c8 805 default:
f930d07e 806 break;
8be1f5c8 807 }
e80cfcfc
FB
808}
809
5fafdf24 810static void sunmouse_event(void *opaque,
e80cfcfc
FB
811 int dx, int dy, int dz, int buttons_state)
812{
813 ChannelState *s = opaque;
814 int ch;
815
30c2f238 816 trace_escc_sunmouse_event(dx, dy, buttons_state);
715748fa
FB
817 ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
818
819 if (buttons_state & MOUSE_EVENT_LBUTTON)
820 ch ^= 0x4;
821 if (buttons_state & MOUSE_EVENT_MBUTTON)
822 ch ^= 0x2;
823 if (buttons_state & MOUSE_EVENT_RBUTTON)
824 ch ^= 0x1;
825
826 put_queue(s, ch);
827
828 ch = dx;
829
830 if (ch > 127)
a0d98a71 831 ch = 127;
715748fa 832 else if (ch < -127)
a0d98a71 833 ch = -127;
715748fa
FB
834
835 put_queue(s, ch & 0xff);
836
837 ch = -dy;
838
839 if (ch > 127)
084bd071 840 ch = 127;
715748fa 841 else if (ch < -127)
084bd071 842 ch = -127;
715748fa
FB
843
844 put_queue(s, ch & 0xff);
845
846 // MSC protocol specify two extra motion bytes
847
848 put_queue(s, 0);
849 put_queue(s, 0);
e80cfcfc
FB
850}
851
a8170e5e 852void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
b4ed08e0 853 int disabled, int clock, int it_shift)
e80cfcfc 854{
6c319c82
BS
855 DeviceState *dev;
856 SysBusDevice *s;
857
81069b20 858 dev = qdev_create(NULL, TYPE_ESCC);
ee6847d1
GH
859 qdev_prop_set_uint32(dev, "disabled", disabled);
860 qdev_prop_set_uint32(dev, "frequency", clock);
861 qdev_prop_set_uint32(dev, "it_shift", it_shift);
bc19fcaa
BS
862 qdev_prop_set_chr(dev, "chrB", NULL);
863 qdev_prop_set_chr(dev, "chrA", NULL);
ee6847d1
GH
864 qdev_prop_set_uint32(dev, "chnBtype", mouse);
865 qdev_prop_set_uint32(dev, "chnAtype", kbd);
e23a1b33 866 qdev_init_nofail(dev);
1356b98d 867 s = SYS_BUS_DEVICE(dev);
6c319c82
BS
868 sysbus_connect_irq(s, 0, irq);
869 sysbus_connect_irq(s, 1, irq);
870 sysbus_mmio_map(s, 0, base);
871}
b4ed08e0 872
81a322d4 873static int escc_init1(SysBusDevice *dev)
6c319c82 874{
81069b20 875 ESCCState *s = ESCC(dev);
6c319c82 876 unsigned int i;
ee6847d1
GH
877
878 s->chn[0].disabled = s->disabled;
879 s->chn[1].disabled = s->disabled;
8be1f5c8 880 for (i = 0; i < 2; i++) {
6c319c82 881 sysbus_init_irq(dev, &s->chn[i].irq);
f930d07e 882 s->chn[i].chn = 1 - i;
ee6847d1 883 s->chn[i].clock = s->frequency / 2;
6c319c82
BS
884 if (s->chn[i].chr) {
885 qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
886 serial_receive1, serial_event, &s->chn[i]);
887 }
8be1f5c8
FB
888 }
889 s->chn[0].otherchn = &s->chn[1];
890 s->chn[1].otherchn = &s->chn[0];
e80cfcfc 891
300b1fc6 892 memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc",
23c5e4ca 893 ESCC_SIZE << s->it_shift);
750ecd44 894 sysbus_init_mmio(dev, &s->mmio);
e80cfcfc 895
6c319c82
BS
896 if (s->chn[0].type == mouse) {
897 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
898 "QEMU Sun Mouse");
899 }
900 if (s->chn[1].type == kbd) {
901 qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
902 }
bdb78cae 903
81a322d4 904 return 0;
e80cfcfc 905}
6c319c82 906
999e12bb 907static Property escc_properties[] = {
3cf63ff2
PB
908 DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0),
909 DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0),
910 DEFINE_PROP_UINT32("disabled", ESCCState, disabled, 0),
911 DEFINE_PROP_UINT32("chnBtype", ESCCState, chn[0].type, 0),
912 DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0),
913 DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr),
914 DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr),
999e12bb
AL
915 DEFINE_PROP_END_OF_LIST(),
916};
917
918static void escc_class_init(ObjectClass *klass, void *data)
919{
39bffca2 920 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
921 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
922
923 k->init = escc_init1;
39bffca2
AL
924 dc->reset = escc_reset;
925 dc->vmsd = &vmstate_escc;
926 dc->props = escc_properties;
999e12bb
AL
927}
928
8c43a6f0 929static const TypeInfo escc_info = {
81069b20 930 .name = TYPE_ESCC,
39bffca2 931 .parent = TYPE_SYS_BUS_DEVICE,
3cf63ff2 932 .instance_size = sizeof(ESCCState),
39bffca2 933 .class_init = escc_class_init,
6c319c82
BS
934};
935
83f7d43a 936static void escc_register_types(void)
6c319c82 937{
39bffca2 938 type_register_static(&escc_info);
6c319c82
BS
939}
940
83f7d43a 941type_init(escc_register_types)