Commit 8be1f5c889fa39571f9dad766497b7bdd56e9d6d

Authored by bellard
1 parent d827220b

keyboard support (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1346 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 166 additions and 25 deletions
hw/slavio_serial.c
1 /* 1 /*
2 * QEMU Sparc SLAVIO serial port emulation 2 * QEMU Sparc SLAVIO serial port emulation
3 * 3 *
4 - * Copyright (c) 2003-2004 Fabrice Bellard 4 + * Copyright (c) 2003-2005 Fabrice Bellard
5 * 5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 7 * of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +22,13 @@ @@ -22,13 +22,13 @@
22 * THE SOFTWARE. 22 * THE SOFTWARE.
23 */ 23 */
24 #include "vl.h" 24 #include "vl.h"
25 - 25 +/* debug serial */
26 //#define DEBUG_SERIAL 26 //#define DEBUG_SERIAL
27 27
28 /* debug keyboard */ 28 /* debug keyboard */
29 //#define DEBUG_KBD 29 //#define DEBUG_KBD
30 30
31 -/* debug keyboard : only mouse */ 31 +/* debug mouse */
32 //#define DEBUG_MOUSE 32 //#define DEBUG_MOUSE
33 33
34 /* 34 /*
@@ -42,11 +42,49 @@ @@ -42,11 +42,49 @@
42 * 42 *
43 */ 43 */
44 44
  45 +#ifdef DEBUG_SERIAL
  46 +#define SER_DPRINTF(fmt, args...) \
  47 +do { printf("SER: " fmt , ##args); } while (0)
  48 +#else
  49 +#define SER_DPRINTF(fmt, args...)
  50 +#endif
  51 +#ifdef DEBUG_KBD
  52 +#define KBD_DPRINTF(fmt, args...) \
  53 +do { printf("KBD: " fmt , ##args); } while (0)
  54 +#else
  55 +#define KBD_DPRINTF(fmt, args...)
  56 +#endif
  57 +#ifdef DEBUG_MOUSE
  58 +#define MS_DPRINTF(fmt, args...) \
  59 +do { printf("SER: " fmt , ##args); } while (0)
  60 +#else
  61 +#define MS_DPRINTF(fmt, args...)
  62 +#endif
  63 +
  64 +typedef enum {
  65 + chn_a, chn_b,
  66 +} chn_id_t;
  67 +
  68 +typedef enum {
  69 + ser, kbd, mouse,
  70 +} chn_type_t;
  71 +
  72 +#define KBD_QUEUE_SIZE 256
  73 +
  74 +typedef struct {
  75 + uint8_t data[KBD_QUEUE_SIZE];
  76 + int rptr, wptr, count;
  77 +} KBDQueue;
  78 +
45 typedef struct ChannelState { 79 typedef struct ChannelState {
46 int irq; 80 int irq;
47 int reg; 81 int reg;
48 int rxint, txint; 82 int rxint, txint;
  83 + chn_id_t chn; // this channel, A (base+4) or B (base+0)
  84 + chn_type_t type;
  85 + struct ChannelState *otherchn;
49 uint8_t rx, tx, wregs[16], rregs[16]; 86 uint8_t rx, tx, wregs[16], rregs[16];
  87 + KBDQueue queue;
50 CharDriverState *chr; 88 CharDriverState *chr;
51 } ChannelState; 89 } ChannelState;
52 90
@@ -56,6 +94,45 @@ struct SerialState { @@ -56,6 +94,45 @@ struct SerialState {
56 94
57 #define SERIAL_MAXADDR 7 95 #define SERIAL_MAXADDR 7
58 96
  97 +static void handle_kbd_command(ChannelState *s, int val);
  98 +static int serial_can_receive(void *opaque);
  99 +static void serial_receive_byte(ChannelState *s, int ch);
  100 +
  101 +static void put_queue(void *opaque, int b)
  102 +{
  103 + ChannelState *s = opaque;
  104 + KBDQueue *q = &s->queue;
  105 +
  106 + KBD_DPRINTF("put: 0x%02x\n", b);
  107 + if (q->count >= KBD_QUEUE_SIZE)
  108 + return;
  109 + q->data[q->wptr] = b;
  110 + if (++q->wptr == KBD_QUEUE_SIZE)
  111 + q->wptr = 0;
  112 + q->count++;
  113 + serial_receive_byte(s, 0);
  114 +}
  115 +
  116 +static uint32_t get_queue(void *opaque)
  117 +{
  118 + ChannelState *s = opaque;
  119 + KBDQueue *q = &s->queue;
  120 + int val;
  121 +
  122 + if (q->count == 0) {
  123 + return 0;
  124 + } else {
  125 + val = q->data[q->rptr];
  126 + if (++q->rptr == KBD_QUEUE_SIZE)
  127 + q->rptr = 0;
  128 + q->count--;
  129 + }
  130 + KBD_DPRINTF("get 0x%02x\n", val);
  131 + if (q->count > 0)
  132 + serial_receive_byte(s, 0);
  133 + return val;
  134 +}
  135 +
59 static void slavio_serial_update_irq(ChannelState *s) 136 static void slavio_serial_update_irq(ChannelState *s)
60 { 137 {
61 if ((s->wregs[1] & 1) && // interrupts enabled 138 if ((s->wregs[1] & 1) && // interrupts enabled
@@ -110,6 +187,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint @@ -110,6 +187,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
110 s = &ser->chn[channel]; 187 s = &ser->chn[channel];
111 switch (saddr) { 188 switch (saddr) {
112 case 0: 189 case 0:
  190 + SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, val & 0xff);
113 newreg = 0; 191 newreg = 0;
114 switch (s->reg) { 192 switch (s->reg) {
115 case 0: 193 case 0:
@@ -158,11 +236,23 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint @@ -158,11 +236,23 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
158 s->reg = 0; 236 s->reg = 0;
159 break; 237 break;
160 case 1: 238 case 1:
  239 + SER_DPRINTF("Write channel %c, ch %d\n", channel? 'b' : 'a', val);
161 if (s->wregs[5] & 8) { // tx enabled 240 if (s->wregs[5] & 8) { // tx enabled
162 s->tx = val; 241 s->tx = val;
163 if (s->chr) 242 if (s->chr)
164 qemu_chr_write(s->chr, &s->tx, 1); 243 qemu_chr_write(s->chr, &s->tx, 1);
  244 + else if (s->type == kbd) {
  245 + handle_kbd_command(s, val);
  246 + }
165 s->txint = 1; 247 s->txint = 1;
  248 + s->rregs[0] |= 4;
  249 + // Interrupts reported only on channel A
  250 + if (s->chn == 0)
  251 + s->rregs[3] |= 0x10;
  252 + else {
  253 + s->otherchn->rregs[3] |= 2;
  254 + }
  255 + slavio_serial_update_irq(s);
166 } 256 }
167 break; 257 break;
168 default: 258 default:
@@ -183,12 +273,18 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) @@ -183,12 +273,18 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
183 s = &ser->chn[channel]; 273 s = &ser->chn[channel];
184 switch (saddr) { 274 switch (saddr) {
185 case 0: 275 case 0:
  276 + SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, s->rregs[s->reg]);
186 ret = s->rregs[s->reg]; 277 ret = s->rregs[s->reg];
187 s->reg = 0; 278 s->reg = 0;
188 return ret; 279 return ret;
189 case 1: 280 case 1:
  281 + SER_DPRINTF("Read channel %c, ch %d\n", channel? 'b' : 'a', s->rx);
190 s->rregs[0] &= ~1; 282 s->rregs[0] &= ~1;
191 - return s->rx; 283 + if (s->type == kbd)
  284 + ret = get_queue(s);
  285 + else
  286 + ret = s->rx;
  287 + return ret;
192 default: 288 default:
193 break; 289 break;
194 } 290 }
@@ -208,6 +304,12 @@ static int serial_can_receive(void *opaque) @@ -208,6 +304,12 @@ static int serial_can_receive(void *opaque)
208 static void serial_receive_byte(ChannelState *s, int ch) 304 static void serial_receive_byte(ChannelState *s, int ch)
209 { 305 {
210 s->rregs[0] |= 1; 306 s->rregs[0] |= 1;
  307 + // Interrupts reported only on channel A
  308 + if (s->chn == 0)
  309 + s->rregs[3] |= 0x20;
  310 + else {
  311 + s->otherchn->rregs[3] |= 4;
  312 + }
211 s->rx = ch; 313 s->rx = ch;
212 s->rxint = 1; 314 s->rxint = 1;
213 slavio_serial_update_irq(s); 315 slavio_serial_update_irq(s);
@@ -295,39 +397,73 @@ static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id) @@ -295,39 +397,73 @@ static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
295 397
296 SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2) 398 SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
297 { 399 {
298 - int slavio_serial_io_memory; 400 + int slavio_serial_io_memory, i;
299 SerialState *s; 401 SerialState *s;
300 402
301 s = qemu_mallocz(sizeof(SerialState)); 403 s = qemu_mallocz(sizeof(SerialState));
302 if (!s) 404 if (!s)
303 return NULL; 405 return NULL;
304 - s->chn[0].irq = irq;  
305 - s->chn[1].irq = irq;  
306 - s->chn[0].chr = chr1;  
307 - s->chn[1].chr = chr2;  
308 406
309 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s); 407 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
310 cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory); 408 cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
311 409
312 - if (chr1) {  
313 - qemu_chr_add_read_handler(chr1, serial_can_receive, serial_receive1, &s->chn[0]);  
314 - qemu_chr_add_event_handler(chr1, serial_event);  
315 - }  
316 - if (chr2) {  
317 - qemu_chr_add_read_handler(chr2, serial_can_receive, serial_receive1, &s->chn[1]);  
318 - qemu_chr_add_event_handler(chr2, serial_event); 410 + s->chn[0].chr = chr1;
  411 + s->chn[1].chr = chr2;
  412 +
  413 + for (i = 0; i < 2; i++) {
  414 + s->chn[i].irq = irq;
  415 + s->chn[i].chn = 1 - i;
  416 + s->chn[i].type = ser;
  417 + if (s->chn[i].chr) {
  418 + qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
  419 + qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
  420 + }
319 } 421 }
  422 + s->chn[0].otherchn = &s->chn[1];
  423 + s->chn[1].otherchn = &s->chn[0];
320 register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s); 424 register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
321 qemu_register_reset(slavio_serial_reset, s); 425 qemu_register_reset(slavio_serial_reset, s);
322 slavio_serial_reset(s); 426 slavio_serial_reset(s);
323 return s; 427 return s;
324 } 428 }
325 429
  430 +static const uint8_t keycodes[128] = {
  431 + 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
  432 + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
  433 + 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
  434 + 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
  435 + 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
  436 + 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
  437 + 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
  438 + 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
  439 +};
  440 +
326 static void sunkbd_event(void *opaque, int ch) 441 static void sunkbd_event(void *opaque, int ch)
327 { 442 {
328 ChannelState *s = opaque; 443 ChannelState *s = opaque;
329 - // XXX: PC -> Sun Type 5 translation?  
330 - serial_receive_byte(s, ch); 444 + int release = ch & 0x80;
  445 +
  446 + ch = keycodes[ch & 0x7f];
  447 + KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
  448 + put_queue(s, ch | release);
  449 +}
  450 +
  451 +static void handle_kbd_command(ChannelState *s, int val)
  452 +{
  453 + KBD_DPRINTF("Command %d\n", val);
  454 + switch (val) {
  455 + case 1: // Reset, return type code
  456 + put_queue(s, 0xff);
  457 + put_queue(s, 0xff);
  458 + put_queue(s, 5); // Type 5
  459 + break;
  460 + case 7: // Query layout
  461 + put_queue(s, 0xfe);
  462 + put_queue(s, 0x20); // XXX, layout?
  463 + break;
  464 + default:
  465 + break;
  466 + }
331 } 467 }
332 468
333 static void sunmouse_event(void *opaque, 469 static void sunmouse_event(void *opaque,
@@ -343,22 +479,27 @@ static void sunmouse_event(void *opaque, @@ -343,22 +479,27 @@ static void sunmouse_event(void *opaque,
343 479
344 void slavio_serial_ms_kbd_init(int base, int irq) 480 void slavio_serial_ms_kbd_init(int base, int irq)
345 { 481 {
346 - int slavio_serial_io_memory; 482 + int slavio_serial_io_memory, i;
347 SerialState *s; 483 SerialState *s;
348 484
349 s = qemu_mallocz(sizeof(SerialState)); 485 s = qemu_mallocz(sizeof(SerialState));
350 if (!s) 486 if (!s)
351 return; 487 return;
352 - s->chn[0].irq = irq;  
353 - s->chn[1].irq = irq;  
354 - s->chn[0].chr = NULL;  
355 - s->chn[1].chr = NULL; 488 + for (i = 0; i < 2; i++) {
  489 + s->chn[i].irq = irq;
  490 + s->chn[i].chn = 1 - i;
  491 + s->chn[i].chr = NULL;
  492 + }
  493 + s->chn[0].otherchn = &s->chn[1];
  494 + s->chn[1].otherchn = &s->chn[0];
  495 + s->chn[0].type = mouse;
  496 + s->chn[1].type = kbd;
356 497
357 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s); 498 slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
358 cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory); 499 cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
359 500
360 - qemu_add_kbd_event_handler(sunkbd_event, &s->chn[0]);  
361 - qemu_add_mouse_event_handler(sunmouse_event, &s->chn[1]); 501 + qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0]);
  502 + qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
362 qemu_register_reset(slavio_serial_reset, s); 503 qemu_register_reset(slavio_serial_reset, s);
363 slavio_serial_reset(s); 504 slavio_serial_reset(s);
364 } 505 }