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