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