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