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