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