|
|
1.1 root 1: /*
2: * QEMU Sparc SLAVIO serial port emulation
1.1.1.5 ! root 3: *
1.1 root 4: * Copyright (c) 2003-2005 Fabrice Bellard
1.1.1.5 ! root 5: *
1.1 root 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: */
1.1.1.5 ! root 24: #include "hw.h"
! 25: #include "sun4m.h"
! 26: #include "qemu-char.h"
! 27: #include "console.h"
! 28:
1.1 root 29: /* debug serial */
30: //#define DEBUG_SERIAL
31:
32: /* debug keyboard */
33: //#define DEBUG_KBD
34:
35: /* debug mouse */
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
1.1.1.5 ! root 42: *
1.1 root 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:
1.1.1.4 root 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:
1.1 root 56: #ifdef DEBUG_SERIAL
57: #define SER_DPRINTF(fmt, args...) \
58: do { 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...) \
64: do { 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...) \
1.1.1.4 root 70: do { printf("MSC: " fmt , ##args); } while (0)
1.1 root 71: #else
72: #define MS_DPRINTF(fmt, args...)
73: #endif
74:
75: typedef enum {
76: chn_a, chn_b,
77: } chn_id_t;
78:
1.1.1.4 root 79: #define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
80:
1.1 root 81: typedef enum {
82: ser, kbd, mouse,
83: } chn_type_t;
84:
1.1.1.4 root 85: #define SERIO_QUEUE_SIZE 256
1.1 root 86:
87: typedef struct {
1.1.1.4 root 88: uint8_t data[SERIO_QUEUE_SIZE];
1.1 root 89: int rptr, wptr, count;
1.1.1.4 root 90: } SERIOQueue;
1.1 root 91:
1.1.1.5 ! root 92: #define SERIAL_REGS 16
1.1 root 93: typedef struct ChannelState {
1.1.1.5 ! root 94: qemu_irq irq;
1.1 root 95: int reg;
1.1.1.4 root 96: int rxint, txint, rxint_under_svc, txint_under_svc;
1.1 root 97: chn_id_t chn; // this channel, A (base+4) or B (base+0)
98: chn_type_t type;
99: struct ChannelState *otherchn;
1.1.1.5 ! root 100: uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS];
1.1.1.4 root 101: SERIOQueue queue;
1.1 root 102: CharDriverState *chr;
1.1.1.5 ! root 103: int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
! 104: int disabled;
1.1 root 105: } ChannelState;
106:
107: struct SerialState {
108: struct ChannelState chn[2];
109: };
110:
111: #define SERIAL_MAXADDR 7
1.1.1.5 ! root 112: #define SERIAL_SIZE (SERIAL_MAXADDR + 1)
! 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
1.1 root 214:
215: static void handle_kbd_command(ChannelState *s, int val);
216: static int serial_can_receive(void *opaque);
217: static void serial_receive_byte(ChannelState *s, int ch);
1.1.1.4 root 218: static inline void set_txint(ChannelState *s);
1.1 root 219:
1.1.1.5 ! root 220: static 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:
1.1 root 227: static void put_queue(void *opaque, int b)
228: {
229: ChannelState *s = opaque;
1.1.1.4 root 230: SERIOQueue *q = &s->queue;
1.1 root 231:
1.1.1.4 root 232: SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
233: if (q->count >= SERIO_QUEUE_SIZE)
1.1 root 234: return;
235: q->data[q->wptr] = b;
1.1.1.4 root 236: if (++q->wptr == SERIO_QUEUE_SIZE)
1.1 root 237: q->wptr = 0;
238: q->count++;
239: serial_receive_byte(s, 0);
240: }
241:
242: static uint32_t get_queue(void *opaque)
243: {
244: ChannelState *s = opaque;
1.1.1.4 root 245: SERIOQueue *q = &s->queue;
1.1 root 246: int val;
1.1.1.5 ! root 247:
1.1 root 248: if (q->count == 0) {
1.1.1.5 ! root 249: return 0;
1.1 root 250: } else {
251: val = q->data[q->rptr];
1.1.1.4 root 252: if (++q->rptr == SERIO_QUEUE_SIZE)
1.1 root 253: q->rptr = 0;
254: q->count--;
255: }
1.1.1.5 ! root 256: SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
1.1 root 257: if (q->count > 0)
1.1.1.5 ! root 258: serial_receive_byte(s, 0);
1.1 root 259: return val;
260: }
261:
1.1.1.4 root 262: static int slavio_serial_update_irq_chn(ChannelState *s)
1.1 root 263: {
1.1.1.5 ! root 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)) &&
! 269: s->rxint == 1) || // rx ints enabled, pending
! 270: ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
! 271: (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
1.1.1.4 root 272: return 1;
1.1 root 273: }
1.1.1.4 root 274: return 0;
275: }
276:
277: static 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:
1.1.1.5 ! root 284: SER_DPRINTF("IRQ = %d\n", irq);
! 285: qemu_set_irq(s->irq, irq);
1.1 root 286: }
287:
288: static void slavio_serial_reset_chn(ChannelState *s)
289: {
290: int i;
291:
292: s->reg = 0;
1.1.1.5 ! root 293: for (i = 0; i < SERIAL_SIZE; i++) {
! 294: s->rregs[i] = 0;
! 295: s->wregs[i] = 0;
! 296: }
! 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
! 303: if (s->disabled)
! 304: s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
! 305: STATUS_CTS | STATUS_TXUNDRN;
! 306: else
! 307: s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
! 308: s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
1.1 root 309:
310: s->rx = s->tx = 0;
311: s->rxint = s->txint = 0;
1.1.1.4 root 312: s->rxint_under_svc = s->txint_under_svc = 0;
1.1.1.5 ! root 313: s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
! 314: clear_queue(s);
1.1 root 315: }
316:
317: static 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:
1.1.1.2 root 324: static inline void clr_rxint(ChannelState *s)
325: {
326: s->rxint = 0;
1.1.1.4 root 327: s->rxint_under_svc = 0;
1.1.1.5 ! root 328: if (s->chn == chn_a) {
! 329: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 330: s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
! 331: else
! 332: s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
! 333: s->rregs[R_INTR] &= ~INTR_RXINTA;
! 334: } else {
! 335: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 336: s->rregs[R_IVEC] = IVEC_HINOINT;
! 337: else
! 338: s->rregs[R_IVEC] = IVEC_LONOINT;
! 339: s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
! 340: }
1.1.1.4 root 341: if (s->txint)
342: set_txint(s);
1.1.1.2 root 343: slavio_serial_update_irq(s);
344: }
345:
346: static inline void set_rxint(ChannelState *s)
347: {
348: s->rxint = 1;
1.1.1.4 root 349: if (!s->txint_under_svc) {
350: s->rxint_under_svc = 1;
1.1.1.5 ! root 351: if (s->chn == chn_a) {
! 352: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 353: s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
! 354: else
! 355: s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
! 356: } else {
! 357: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 358: s->rregs[R_IVEC] = IVEC_HIRXINTB;
! 359: else
! 360: s->rregs[R_IVEC] = IVEC_LORXINTB;
! 361: }
1.1.1.2 root 362: }
1.1.1.5 ! root 363: if (s->chn == chn_a)
! 364: s->rregs[R_INTR] |= INTR_RXINTA;
! 365: else
! 366: s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
! 367: slavio_serial_update_irq(s);
1.1.1.2 root 368: }
369:
370: static inline void clr_txint(ChannelState *s)
371: {
372: s->txint = 0;
1.1.1.4 root 373: s->txint_under_svc = 0;
1.1.1.5 ! root 374: if (s->chn == chn_a) {
! 375: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 376: s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
! 377: else
! 378: s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
! 379: s->rregs[R_INTR] &= ~INTR_TXINTA;
! 380: } else {
! 381: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 382: s->rregs[R_IVEC] = IVEC_HINOINT;
! 383: else
! 384: s->rregs[R_IVEC] = IVEC_LONOINT;
! 385: s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
! 386: }
1.1.1.4 root 387: if (s->rxint)
388: set_rxint(s);
1.1.1.2 root 389: slavio_serial_update_irq(s);
390: }
391:
392: static inline void set_txint(ChannelState *s)
393: {
394: s->txint = 1;
1.1.1.4 root 395: if (!s->rxint_under_svc) {
396: s->txint_under_svc = 1;
1.1.1.5 ! root 397: if (s->chn == chn_a) {
! 398: if (s->wregs[W_MINTR] & MINTR_STATUSHI)
! 399: s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
! 400: else
! 401: s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
! 402: } else {
! 403: s->rregs[R_IVEC] = IVEC_TXINTB;
! 404: }
1.1.1.2 root 405: }
1.1.1.5 ! root 406: if (s->chn == chn_a)
! 407: s->rregs[R_INTR] |= INTR_TXINTA;
! 408: else
! 409: s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
! 410: slavio_serial_update_irq(s);
1.1.1.4 root 411: }
412:
413: static 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:
1.1.1.5 ! root 421: if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
! 422: if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
1.1.1.4 root 423: parity = 'E';
424: else
425: parity = 'O';
426: } else {
427: parity = 'N';
428: }
1.1.1.5 ! root 429: if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
1.1.1.4 root 430: stop_bits = 2;
431: else
432: stop_bits = 1;
1.1.1.5 ! root 433: switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
! 434: case TXCTRL2_5BITS:
1.1.1.4 root 435: data_bits = 5;
436: break;
1.1.1.5 ! root 437: case TXCTRL2_7BITS:
1.1.1.4 root 438: data_bits = 7;
439: break;
1.1.1.5 ! root 440: case TXCTRL2_6BITS:
1.1.1.4 root 441: data_bits = 6;
442: break;
443: default:
1.1.1.5 ! root 444: case TXCTRL2_8BITS:
1.1.1.4 root 445: data_bits = 8;
446: break;
447: }
1.1.1.5 ! root 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:
1.1.1.4 root 451: break;
1.1.1.5 ! root 452: case TXCTRL1_CLK16X:
1.1.1.4 root 453: speed /= 16;
454: break;
1.1.1.5 ! root 455: case TXCTRL1_CLK32X:
1.1.1.4 root 456: speed /= 32;
457: break;
458: default:
1.1.1.5 ! root 459: case TXCTRL1_CLK64X:
1.1.1.4 root 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);
1.1.1.2 root 470: }
471:
1.1.1.5 ! root 472: static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
! 473: uint32_t val)
1.1 root 474: {
1.1.1.5 ! root 475: SerialState *serial = opaque;
1.1 root 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;
1.1.1.5 ! root 483: s = &serial->chn[channel];
1.1 root 484: switch (saddr) {
1.1.1.5 ! root 485: case SERIAL_CTRL:
! 486: SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
! 487: val & 0xff);
! 488: newreg = 0;
! 489: switch (s->reg) {
! 490: case W_CMD:
! 491: newreg = val & CMD_PTR_MASK;
! 492: val &= CMD_CMD_MASK;
! 493: switch (val) {
! 494: case CMD_HI:
! 495: newreg |= CMD_HI;
! 496: break;
! 497: case CMD_CLR_TXINT:
1.1.1.2 root 498: clr_txint(s);
1.1.1.5 ! root 499: break;
! 500: case CMD_CLR_IUS:
1.1.1.4 root 501: if (s->rxint_under_svc)
502: clr_rxint(s);
503: else if (s->txint_under_svc)
504: clr_txint(s);
1.1.1.5 ! root 505: break;
! 506: default:
! 507: break;
! 508: }
! 509: break;
! 510: case W_INTR ... W_RXCTRL:
! 511: case W_SYNC1 ... W_TXBUF:
! 512: case W_MISC1 ... W_CLOCK:
! 513: case W_MISC2 ... W_EXTINT:
! 514: s->wregs[s->reg] = val;
! 515: break;
! 516: case W_TXCTRL1:
! 517: case W_TXCTRL2:
! 518: case W_BRGLO:
! 519: case W_BRGHI:
! 520: s->wregs[s->reg] = val;
1.1.1.4 root 521: slavio_serial_update_parameters(s);
1.1.1.5 ! root 522: break;
! 523: case W_MINTR:
! 524: switch (val & MINTR_RST_MASK) {
! 525: case 0:
! 526: default:
! 527: break;
! 528: case MINTR_RST_B:
! 529: slavio_serial_reset_chn(&serial->chn[1]);
! 530: return;
! 531: case MINTR_RST_A:
! 532: slavio_serial_reset_chn(&serial->chn[0]);
! 533: return;
! 534: case MINTR_RST_ALL:
! 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;
! 547: case SERIAL_DATA:
! 548: SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
! 549: s->tx = val;
! 550: if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
! 551: if (s->chr)
! 552: qemu_chr_write(s->chr, &s->tx, 1);
! 553: else if (s->type == kbd && !s->disabled) {
! 554: handle_kbd_command(s, val);
! 555: }
! 556: }
! 557: s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
! 558: s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
! 559: set_txint(s);
! 560: break;
1.1 root 561: default:
1.1.1.5 ! root 562: break;
1.1 root 563: }
564: }
565:
566: static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
567: {
1.1.1.5 ! root 568: SerialState *serial = opaque;
1.1 root 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;
1.1.1.5 ! root 576: s = &serial->chn[channel];
1.1 root 577: switch (saddr) {
1.1.1.5 ! root 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]);
! 581: ret = s->rregs[s->reg];
! 582: s->reg = 0;
! 583: return ret;
! 584: case SERIAL_DATA:
! 585: s->rregs[R_STATUS] &= ~STATUS_RXAV;
1.1.1.2 root 586: clr_rxint(s);
1.1.1.5 ! root 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);
! 592: if (s->chr)
! 593: qemu_chr_accept_input(s->chr);
! 594: return ret;
1.1 root 595: default:
1.1.1.5 ! root 596: break;
1.1 root 597: }
598: return 0;
599: }
600:
601: static int serial_can_receive(void *opaque)
602: {
603: ChannelState *s = opaque;
1.1.1.4 root 604: int ret;
605:
1.1.1.5 ! root 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
! 609: ret = 0;
1.1 root 610: else
1.1.1.5 ! root 611: ret = 1;
1.1.1.4 root 612: return ret;
1.1 root 613: }
614:
615: static void serial_receive_byte(ChannelState *s, int ch)
616: {
1.1.1.4 root 617: SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
1.1.1.5 ! root 618: s->rregs[R_STATUS] |= STATUS_RXAV;
1.1 root 619: s->rx = ch;
1.1.1.2 root 620: set_rxint(s);
1.1 root 621: }
622:
623: static void serial_receive_break(ChannelState *s)
624: {
1.1.1.5 ! root 625: s->rregs[R_STATUS] |= STATUS_BRK;
1.1 root 626: slavio_serial_update_irq(s);
627: }
628:
629: static 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:
635: static 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:
642: static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
643: slavio_serial_mem_readb,
1.1.1.5 ! root 644: NULL,
! 645: NULL,
1.1 root 646: };
647:
648: static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
649: slavio_serial_mem_writeb,
1.1.1.5 ! root 650: NULL,
! 651: NULL,
1.1 root 652: };
653:
654: static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
655: {
1.1.1.5 ! root 656: int tmp;
! 657: tmp = 0;
! 658: qemu_put_be32s(f, &tmp); /* unused, was IRQ. */
1.1 root 659: qemu_put_be32s(f, &s->reg);
660: qemu_put_be32s(f, &s->rxint);
661: qemu_put_be32s(f, &s->txint);
1.1.1.4 root 662: qemu_put_be32s(f, &s->rxint_under_svc);
663: qemu_put_be32s(f, &s->txint_under_svc);
1.1 root 664: qemu_put_8s(f, &s->rx);
665: qemu_put_8s(f, &s->tx);
1.1.1.5 ! root 666: qemu_put_buffer(f, s->wregs, SERIAL_REGS);
! 667: qemu_put_buffer(f, s->rregs, SERIAL_REGS);
1.1 root 668: }
669:
670: static 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:
678: static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
679: {
1.1.1.5 ! root 680: int tmp;
! 681:
1.1.1.4 root 682: if (version_id > 2)
1.1 root 683: return -EINVAL;
684:
1.1.1.5 ! root 685: qemu_get_be32s(f, &tmp); /* unused */
1.1 root 686: qemu_get_be32s(f, &s->reg);
687: qemu_get_be32s(f, &s->rxint);
688: qemu_get_be32s(f, &s->txint);
1.1.1.4 root 689: if (version_id >= 2) {
690: qemu_get_be32s(f, &s->rxint_under_svc);
691: qemu_get_be32s(f, &s->txint_under_svc);
692: }
1.1 root 693: qemu_get_8s(f, &s->rx);
694: qemu_get_8s(f, &s->tx);
1.1.1.5 ! root 695: qemu_get_buffer(f, s->wregs, SERIAL_REGS);
! 696: qemu_get_buffer(f, s->rregs, SERIAL_REGS);
1.1 root 697: return 0;
698: }
699:
700: static 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)
1.1.1.5 ! root 707: return ret;
1.1 root 708: ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
709: return ret;
710:
711: }
712:
1.1.1.5 ! root 713: SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
! 714: CharDriverState *chr1, CharDriverState *chr2)
1.1 root 715: {
716: int slavio_serial_io_memory, i;
717: SerialState *s;
718:
719: s = qemu_mallocz(sizeof(SerialState));
720: if (!s)
721: return NULL;
722:
1.1.1.5 ! root 723: slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
! 724: slavio_serial_mem_write,
! 725: s);
! 726: cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
1.1 root 727:
728: s->chn[0].chr = chr1;
729: s->chn[1].chr = chr2;
1.1.1.5 ! root 730: s->chn[0].disabled = 0;
! 731: s->chn[1].disabled = 0;
1.1 root 732:
733: for (i = 0; i < 2; i++) {
1.1.1.5 ! root 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,
1.1.1.4 root 739: serial_receive1, serial_event, &s->chn[i]);
1.1.1.5 ! root 740: }
1.1 root 741: }
742: s->chn[0].otherchn = &s->chn[1];
743: s->chn[1].otherchn = &s->chn[0];
1.1.1.5 ! root 744: register_savevm("slavio_serial", base, 2, slavio_serial_save,
! 745: slavio_serial_load, s);
1.1 root 746: qemu_register_reset(slavio_serial_reset, s);
747: slavio_serial_reset(s);
748: return s;
749: }
750:
751: static 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:
1.1.1.5 ! root 762: static 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:
1.1 root 773: static void sunkbd_event(void *opaque, int ch)
774: {
775: ChannelState *s = opaque;
776: int release = ch & 0x80;
777:
1.1.1.5 ! root 778: KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" :
! 779: "press");
! 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:
! 802: s->e0_mode = 1;
! 803: return;
! 804: default:
! 805: break;
! 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);
1.1 root 814: put_queue(s, ch | release);
815: }
816:
817: static void handle_kbd_command(ChannelState *s, int val)
818: {
819: KBD_DPRINTF("Command %d\n", val);
1.1.1.5 ! root 820: if (s->led_mode) { // Ignore led byte
! 821: s->led_mode = 0;
! 822: return;
! 823: }
1.1 root 824: switch (val) {
825: case 1: // Reset, return type code
1.1.1.5 ! root 826: clear_queue(s);
! 827: put_queue(s, 0xff);
! 828: put_queue(s, 4); // Type 4
! 829: put_queue(s, 0x7f);
! 830: break;
! 831: case 0xe: // Set leds
! 832: s->led_mode = 1;
! 833: break;
1.1 root 834: case 7: // Query layout
1.1.1.5 ! root 835: case 0xf:
! 836: clear_queue(s);
! 837: put_queue(s, 0xfe);
! 838: put_queue(s, 0); // XXX, layout?
! 839: break;
1.1 root 840: default:
1.1.1.5 ! root 841: break;
1.1 root 842: }
843: }
844:
1.1.1.5 ! root 845: static void sunmouse_event(void *opaque,
1.1 root 846: int dx, int dy, int dz, int buttons_state)
847: {
848: ChannelState *s = opaque;
849: int ch;
850:
1.1.1.4 root 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);
1.1 root 886: }
887:
1.1.1.5 ! root 888: void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
! 889: int disabled)
1.1 root 890: {
891: int slavio_serial_io_memory, i;
892: SerialState *s;
893:
894: s = qemu_mallocz(sizeof(SerialState));
895: if (!s)
896: return;
897: for (i = 0; i < 2; i++) {
1.1.1.5 ! root 898: s->chn[i].irq = irq;
! 899: s->chn[i].chn = 1 - i;
! 900: s->chn[i].chr = NULL;
1.1 root 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;
1.1.1.5 ! root 906: s->chn[0].disabled = disabled;
! 907: s->chn[1].disabled = disabled;
1.1 root 908:
1.1.1.5 ! root 909: slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
! 910: slavio_serial_mem_write,
! 911: s);
! 912: cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
1.1 root 913:
1.1.1.5 ! root 914: qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
! 915: "QEMU Sun Mouse");
1.1 root 916: qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
1.1.1.5 ! root 917: register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save,
! 918: slavio_serial_load, s);
1.1 root 919: qemu_register_reset(slavio_serial_reset, s);
920: slavio_serial_reset(s);
921: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.