]> git.proxmox.com Git - qemu.git/blame - hw/escc.c
mips_fulong: remove bogus HAS_AUDIO
[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) {
9fc391f8 372 s->rregs[R_INTR] |= INTR_TXINTA;
80637a6a
BS
373 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
374 s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
375 else
376 s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
377 } else {
378 s->rregs[R_IVEC] = IVEC_TXINTB;
9fc391f8 379 s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
80637a6a 380 }
b4ed08e0 381 escc_update_irq(s);
9fc391f8 382 }
80637a6a
BS
383}
384
385static inline void clr_rxint(ChannelState *s)
386{
387 s->rxint = 0;
388 s->rxint_under_svc = 0;
389 if (s->chn == chn_a) {
390 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
391 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
392 else
393 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
394 s->rregs[R_INTR] &= ~INTR_RXINTA;
395 } else {
396 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
397 s->rregs[R_IVEC] = IVEC_HINOINT;
398 else
399 s->rregs[R_IVEC] = IVEC_LONOINT;
400 s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
401 }
402 if (s->txint)
403 set_txint(s);
b4ed08e0 404 escc_update_irq(s);
80637a6a
BS
405}
406
ba3c64fb
FB
407static inline void clr_txint(ChannelState *s)
408{
409 s->txint = 0;
e4a89056 410 s->txint_under_svc = 0;
b9652ca3 411 if (s->chn == chn_a) {
12abac85
BS
412 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
413 s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
b9652ca3 414 else
12abac85
BS
415 s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
416 s->rregs[R_INTR] &= ~INTR_TXINTA;
b9652ca3 417 } else {
9fc391f8 418 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
12abac85
BS
419 if (s->wregs[W_MINTR] & MINTR_STATUSHI)
420 s->rregs[R_IVEC] = IVEC_HINOINT;
b9652ca3 421 else
12abac85
BS
422 s->rregs[R_IVEC] = IVEC_LONOINT;
423 s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
b9652ca3 424 }
e4a89056
FB
425 if (s->rxint)
426 set_rxint(s);
b4ed08e0 427 escc_update_irq(s);
ba3c64fb
FB
428}
429
b4ed08e0 430static void escc_update_parameters(ChannelState *s)
35db099d
FB
431{
432 int speed, parity, data_bits, stop_bits;
433 QEMUSerialSetParams ssp;
434
435 if (!s->chr || s->type != ser)
436 return;
437
12abac85
BS
438 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
439 if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
35db099d
FB
440 parity = 'E';
441 else
442 parity = 'O';
443 } else {
444 parity = 'N';
445 }
12abac85 446 if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
35db099d
FB
447 stop_bits = 2;
448 else
449 stop_bits = 1;
12abac85
BS
450 switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
451 case TXCTRL2_5BITS:
35db099d
FB
452 data_bits = 5;
453 break;
12abac85 454 case TXCTRL2_7BITS:
35db099d
FB
455 data_bits = 7;
456 break;
12abac85 457 case TXCTRL2_6BITS:
35db099d
FB
458 data_bits = 6;
459 break;
460 default:
12abac85 461 case TXCTRL2_8BITS:
35db099d
FB
462 data_bits = 8;
463 break;
464 }
b4ed08e0 465 speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
12abac85
BS
466 switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
467 case TXCTRL1_CLK1X:
35db099d 468 break;
12abac85 469 case TXCTRL1_CLK16X:
35db099d
FB
470 speed /= 16;
471 break;
12abac85 472 case TXCTRL1_CLK32X:
35db099d
FB
473 speed /= 32;
474 break;
475 default:
12abac85 476 case TXCTRL1_CLK64X:
35db099d
FB
477 speed /= 64;
478 break;
479 }
480 ssp.speed = speed;
481 ssp.parity = parity;
482 ssp.data_bits = data_bits;
483 ssp.stop_bits = stop_bits;
484 SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
485 speed, parity, data_bits, stop_bits);
486 qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
487}
488
c227f099 489static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
e80cfcfc 490{
b3ceef24 491 SerialState *serial = opaque;
e80cfcfc
FB
492 ChannelState *s;
493 uint32_t saddr;
494 int newreg, channel;
495
496 val &= 0xff;
b4ed08e0
BS
497 saddr = (addr >> serial->it_shift) & 1;
498 channel = (addr >> (serial->it_shift + 1)) & 1;
b3ceef24 499 s = &serial->chn[channel];
e80cfcfc 500 switch (saddr) {
12abac85
BS
501 case SERIAL_CTRL:
502 SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
503 val & 0xff);
f930d07e
BS
504 newreg = 0;
505 switch (s->reg) {
12abac85
BS
506 case W_CMD:
507 newreg = val & CMD_PTR_MASK;
508 val &= CMD_CMD_MASK;
f930d07e 509 switch (val) {
12abac85
BS
510 case CMD_HI:
511 newreg |= CMD_HI;
f930d07e 512 break;
12abac85 513 case CMD_CLR_TXINT:
ba3c64fb 514 clr_txint(s);
f930d07e 515 break;
12abac85 516 case CMD_CLR_IUS:
9fc391f8
AT
517 if (s->rxint_under_svc) {
518 s->rxint_under_svc = 0;
519 if (s->txint) {
520 set_txint(s);
521 }
522 } else if (s->txint_under_svc) {
523 s->txint_under_svc = 0;
524 }
525 escc_update_irq(s);
f930d07e
BS
526 break;
527 default:
528 break;
529 }
530 break;
12abac85
BS
531 case W_INTR ... W_RXCTRL:
532 case W_SYNC1 ... W_TXBUF:
533 case W_MISC1 ... W_CLOCK:
534 case W_MISC2 ... W_EXTINT:
f930d07e
BS
535 s->wregs[s->reg] = val;
536 break;
12abac85
BS
537 case W_TXCTRL1:
538 case W_TXCTRL2:
796d8286 539 s->wregs[s->reg] = val;
b4ed08e0 540 escc_update_parameters(s);
796d8286 541 break;
12abac85
BS
542 case W_BRGLO:
543 case W_BRGHI:
f930d07e 544 s->wregs[s->reg] = val;
796d8286 545 s->rregs[s->reg] = val;
b4ed08e0 546 escc_update_parameters(s);
f930d07e 547 break;
12abac85
BS
548 case W_MINTR:
549 switch (val & MINTR_RST_MASK) {
f930d07e
BS
550 case 0:
551 default:
552 break;
12abac85 553 case MINTR_RST_B:
b4ed08e0 554 escc_reset_chn(&serial->chn[0]);
f930d07e 555 return;
12abac85 556 case MINTR_RST_A:
b4ed08e0 557 escc_reset_chn(&serial->chn[1]);
f930d07e 558 return;
12abac85 559 case MINTR_RST_ALL:
bdb78cae 560 escc_reset(&serial->busdev.qdev);
f930d07e
BS
561 return;
562 }
563 break;
564 default:
565 break;
566 }
567 if (s->reg == 0)
568 s->reg = newreg;
569 else
570 s->reg = 0;
571 break;
12abac85 572 case SERIAL_DATA:
f930d07e 573 SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
96c4f569 574 s->tx = val;
12abac85 575 if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
f930d07e
BS
576 if (s->chr)
577 qemu_chr_write(s->chr, &s->tx, 1);
577390ff 578 else if (s->type == kbd && !s->disabled) {
f930d07e
BS
579 handle_kbd_command(s, val);
580 }
581 }
12abac85
BS
582 s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
583 s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
96c4f569 584 set_txint(s);
f930d07e 585 break;
e80cfcfc 586 default:
f930d07e 587 break;
e80cfcfc
FB
588 }
589}
590
c227f099 591static uint32_t escc_mem_readb(void *opaque, target_phys_addr_t addr)
e80cfcfc 592{
b3ceef24 593 SerialState *serial = opaque;
e80cfcfc
FB
594 ChannelState *s;
595 uint32_t saddr;
596 uint32_t ret;
597 int channel;
598
b4ed08e0
BS
599 saddr = (addr >> serial->it_shift) & 1;
600 channel = (addr >> (serial->it_shift + 1)) & 1;
b3ceef24 601 s = &serial->chn[channel];
e80cfcfc 602 switch (saddr) {
12abac85
BS
603 case SERIAL_CTRL:
604 SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
605 s->rregs[s->reg]);
f930d07e
BS
606 ret = s->rregs[s->reg];
607 s->reg = 0;
608 return ret;
12abac85
BS
609 case SERIAL_DATA:
610 s->rregs[R_STATUS] &= ~STATUS_RXAV;
ba3c64fb 611 clr_rxint(s);
f930d07e
BS
612 if (s->type == kbd || s->type == mouse)
613 ret = get_queue(s);
614 else
615 ret = s->rx;
616 SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
b76482e7
BS
617 if (s->chr)
618 qemu_chr_accept_input(s->chr);
f930d07e 619 return ret;
e80cfcfc 620 default:
f930d07e 621 break;
e80cfcfc
FB
622 }
623 return 0;
624}
625
626static int serial_can_receive(void *opaque)
627{
628 ChannelState *s = opaque;
e4a89056
FB
629 int ret;
630
12abac85
BS
631 if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
632 || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
633 // char already available
f930d07e 634 ret = 0;
e80cfcfc 635 else
f930d07e 636 ret = 1;
e4a89056 637 return ret;
e80cfcfc
FB
638}
639
640static void serial_receive_byte(ChannelState *s, int ch)
641{
35db099d 642 SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
12abac85 643 s->rregs[R_STATUS] |= STATUS_RXAV;
e80cfcfc 644 s->rx = ch;
ba3c64fb 645 set_rxint(s);
e80cfcfc
FB
646}
647
648static void serial_receive_break(ChannelState *s)
649{
12abac85 650 s->rregs[R_STATUS] |= STATUS_BRK;
b4ed08e0 651 escc_update_irq(s);
e80cfcfc
FB
652}
653
654static void serial_receive1(void *opaque, const uint8_t *buf, int size)
655{
656 ChannelState *s = opaque;
657 serial_receive_byte(s, buf[0]);
658}
659
660static void serial_event(void *opaque, int event)
661{
662 ChannelState *s = opaque;
663 if (event == CHR_EVENT_BREAK)
664 serial_receive_break(s);
665}
666
d60efc6b 667static CPUReadMemoryFunc * const escc_mem_read[3] = {
b4ed08e0 668 escc_mem_readb,
7c560456
BS
669 NULL,
670 NULL,
e80cfcfc
FB
671};
672
d60efc6b 673static CPUWriteMemoryFunc * const escc_mem_write[3] = {
b4ed08e0 674 escc_mem_writeb,
7c560456
BS
675 NULL,
676 NULL,
e80cfcfc
FB
677};
678
bdb78cae
BS
679static const VMStateDescription vmstate_escc_chn = {
680 .name ="escc_chn",
681 .version_id = 2,
682 .minimum_version_id = 1,
683 .minimum_version_id_old = 1,
684 .fields = (VMStateField []) {
685 VMSTATE_UINT32(vmstate_dummy, ChannelState),
686 VMSTATE_UINT32(reg, ChannelState),
687 VMSTATE_UINT32(rxint, ChannelState),
688 VMSTATE_UINT32(txint, ChannelState),
689 VMSTATE_UINT32(rxint_under_svc, ChannelState),
690 VMSTATE_UINT32(txint_under_svc, ChannelState),
691 VMSTATE_UINT8(rx, ChannelState),
692 VMSTATE_UINT8(tx, ChannelState),
693 VMSTATE_BUFFER(wregs, ChannelState),
694 VMSTATE_BUFFER(rregs, ChannelState),
695 VMSTATE_END_OF_LIST()
e4a89056 696 }
bdb78cae 697};
e80cfcfc 698
bdb78cae
BS
699static const VMStateDescription vmstate_escc = {
700 .name ="escc",
701 .version_id = 2,
702 .minimum_version_id = 1,
703 .minimum_version_id_old = 1,
704 .fields = (VMStateField []) {
705 VMSTATE_STRUCT_ARRAY(chn, SerialState, 2, 2, vmstate_escc_chn,
706 ChannelState),
707 VMSTATE_END_OF_LIST()
708 }
709};
e80cfcfc 710
c227f099 711int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
aeeb69c7
AJ
712 CharDriverState *chrA, CharDriverState *chrB,
713 int clock, int it_shift)
e80cfcfc 714{
6c319c82
BS
715 DeviceState *dev;
716 SysBusDevice *s;
717 SerialState *d;
718
719 dev = qdev_create(NULL, "escc");
ee6847d1
GH
720 qdev_prop_set_uint32(dev, "disabled", 0);
721 qdev_prop_set_uint32(dev, "frequency", clock);
722 qdev_prop_set_uint32(dev, "it_shift", it_shift);
bc19fcaa
BS
723 qdev_prop_set_chr(dev, "chrB", chrB);
724 qdev_prop_set_chr(dev, "chrA", chrA);
ee6847d1
GH
725 qdev_prop_set_uint32(dev, "chnBtype", ser);
726 qdev_prop_set_uint32(dev, "chnAtype", ser);
e23a1b33 727 qdev_init_nofail(dev);
6c319c82 728 s = sysbus_from_qdev(dev);
e1a0e47f
AJ
729 sysbus_connect_irq(s, 0, irqB);
730 sysbus_connect_irq(s, 1, irqA);
6c319c82
BS
731 if (base) {
732 sysbus_mmio_map(s, 0, base);
e80cfcfc 733 }
6c319c82
BS
734
735 d = FROM_SYSBUS(SerialState, s);
736 return d->mmio_index;
e80cfcfc
FB
737}
738
8be1f5c8
FB
739static const uint8_t keycodes[128] = {
740 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
741 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
742 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
743 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
744 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
745 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
746 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
747 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
748};
749
43febf49
BS
750static const uint8_t e0_keycodes[128] = {
751 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
752 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
753 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
754 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
755 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
756 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
757 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
c0b5b109 758 1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
43febf49
BS
759};
760
e80cfcfc
FB
761static void sunkbd_event(void *opaque, int ch)
762{
763 ChannelState *s = opaque;
8be1f5c8
FB
764 int release = ch & 0x80;
765
12abac85
BS
766 KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" :
767 "press");
bbbb2f0a
BS
768 switch (ch) {
769 case 58: // Caps lock press
770 s->caps_lock_mode ^= 1;
771 if (s->caps_lock_mode == 2)
772 return; // Drop second press
773 break;
774 case 69: // Num lock press
775 s->num_lock_mode ^= 1;
776 if (s->num_lock_mode == 2)
777 return; // Drop second press
778 break;
779 case 186: // Caps lock release
780 s->caps_lock_mode ^= 2;
781 if (s->caps_lock_mode == 3)
782 return; // Drop first release
783 break;
784 case 197: // Num lock release
785 s->num_lock_mode ^= 2;
786 if (s->num_lock_mode == 3)
787 return; // Drop first release
788 break;
789 case 0xe0:
43febf49
BS
790 s->e0_mode = 1;
791 return;
bbbb2f0a
BS
792 default:
793 break;
43febf49
BS
794 }
795 if (s->e0_mode) {
796 s->e0_mode = 0;
797 ch = e0_keycodes[ch & 0x7f];
798 } else {
799 ch = keycodes[ch & 0x7f];
800 }
801 KBD_DPRINTF("Translated keycode %2.2x\n", ch);
8be1f5c8
FB
802 put_queue(s, ch | release);
803}
804
805static void handle_kbd_command(ChannelState *s, int val)
806{
807 KBD_DPRINTF("Command %d\n", val);
43febf49
BS
808 if (s->led_mode) { // Ignore led byte
809 s->led_mode = 0;
810 return;
811 }
8be1f5c8
FB
812 switch (val) {
813 case 1: // Reset, return type code
67deb562 814 clear_queue(s);
f930d07e
BS
815 put_queue(s, 0xff);
816 put_queue(s, 4); // Type 4
817 put_queue(s, 0x7f);
818 break;
43febf49
BS
819 case 0xe: // Set leds
820 s->led_mode = 1;
821 break;
8be1f5c8 822 case 7: // Query layout
67deb562
BS
823 case 0xf:
824 clear_queue(s);
f930d07e
BS
825 put_queue(s, 0xfe);
826 put_queue(s, 0); // XXX, layout?
827 break;
8be1f5c8 828 default:
f930d07e 829 break;
8be1f5c8 830 }
e80cfcfc
FB
831}
832
5fafdf24 833static void sunmouse_event(void *opaque,
e80cfcfc
FB
834 int dx, int dy, int dz, int buttons_state)
835{
836 ChannelState *s = opaque;
837 int ch;
838
715748fa
FB
839 MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
840
841 ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
842
843 if (buttons_state & MOUSE_EVENT_LBUTTON)
844 ch ^= 0x4;
845 if (buttons_state & MOUSE_EVENT_MBUTTON)
846 ch ^= 0x2;
847 if (buttons_state & MOUSE_EVENT_RBUTTON)
848 ch ^= 0x1;
849
850 put_queue(s, ch);
851
852 ch = dx;
853
854 if (ch > 127)
a0d98a71 855 ch = 127;
715748fa 856 else if (ch < -127)
a0d98a71 857 ch = -127;
715748fa
FB
858
859 put_queue(s, ch & 0xff);
860
861 ch = -dy;
862
863 if (ch > 127)
084bd071 864 ch = 127;
715748fa 865 else if (ch < -127)
084bd071 866 ch = -127;
715748fa
FB
867
868 put_queue(s, ch & 0xff);
869
870 // MSC protocol specify two extra motion bytes
871
872 put_queue(s, 0);
873 put_queue(s, 0);
e80cfcfc
FB
874}
875
c227f099 876void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
b4ed08e0 877 int disabled, int clock, int it_shift)
e80cfcfc 878{
6c319c82
BS
879 DeviceState *dev;
880 SysBusDevice *s;
881
882 dev = qdev_create(NULL, "escc");
ee6847d1
GH
883 qdev_prop_set_uint32(dev, "disabled", disabled);
884 qdev_prop_set_uint32(dev, "frequency", clock);
885 qdev_prop_set_uint32(dev, "it_shift", it_shift);
bc19fcaa
BS
886 qdev_prop_set_chr(dev, "chrB", NULL);
887 qdev_prop_set_chr(dev, "chrA", NULL);
ee6847d1
GH
888 qdev_prop_set_uint32(dev, "chnBtype", mouse);
889 qdev_prop_set_uint32(dev, "chnAtype", kbd);
e23a1b33 890 qdev_init_nofail(dev);
6c319c82
BS
891 s = sysbus_from_qdev(dev);
892 sysbus_connect_irq(s, 0, irq);
893 sysbus_connect_irq(s, 1, irq);
894 sysbus_mmio_map(s, 0, base);
895}
b4ed08e0 896
81a322d4 897static int escc_init1(SysBusDevice *dev)
6c319c82
BS
898{
899 SerialState *s = FROM_SYSBUS(SerialState, dev);
900 int io;
901 unsigned int i;
ee6847d1
GH
902
903 s->chn[0].disabled = s->disabled;
904 s->chn[1].disabled = s->disabled;
8be1f5c8 905 for (i = 0; i < 2; i++) {
6c319c82 906 sysbus_init_irq(dev, &s->chn[i].irq);
f930d07e 907 s->chn[i].chn = 1 - i;
ee6847d1 908 s->chn[i].clock = s->frequency / 2;
6c319c82
BS
909 if (s->chn[i].chr) {
910 qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
911 serial_receive1, serial_event, &s->chn[i]);
912 }
8be1f5c8
FB
913 }
914 s->chn[0].otherchn = &s->chn[1];
915 s->chn[1].otherchn = &s->chn[0];
e80cfcfc 916
2507c12a
AG
917 io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s,
918 DEVICE_NATIVE_ENDIAN);
6c319c82
BS
919 sysbus_init_mmio(dev, ESCC_SIZE << s->it_shift, io);
920 s->mmio_index = io;
e80cfcfc 921
6c319c82
BS
922 if (s->chn[0].type == mouse) {
923 qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
924 "QEMU Sun Mouse");
925 }
926 if (s->chn[1].type == kbd) {
927 qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
928 }
bdb78cae 929
81a322d4 930 return 0;
e80cfcfc 931}
6c319c82
BS
932
933static SysBusDeviceInfo escc_info = {
934 .init = escc_init1,
935 .qdev.name = "escc",
936 .qdev.size = sizeof(SerialState),
bdb78cae
BS
937 .qdev.vmsd = &vmstate_escc,
938 .qdev.reset = escc_reset,
ee6847d1 939 .qdev.props = (Property[]) {
ec02f7de
GH
940 DEFINE_PROP_UINT32("frequency", SerialState, frequency, 0),
941 DEFINE_PROP_UINT32("it_shift", SerialState, it_shift, 0),
942 DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0),
943 DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0),
944 DEFINE_PROP_UINT32("chnBtype", SerialState, chn[0].type, 0),
945 DEFINE_PROP_UINT32("chnAtype", SerialState, chn[1].type, 0),
946 DEFINE_PROP_CHR("chrB", SerialState, chn[0].chr),
947 DEFINE_PROP_CHR("chrA", SerialState, chn[1].chr),
948 DEFINE_PROP_END_OF_LIST(),
6c319c82
BS
949 }
950};
951
952static void escc_register_devices(void)
953{
954 sysbus_register_withprop(&escc_info);
955}
956
957device_init(escc_register_devices)