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