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