25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_pckbc.c,v 1.53 2005/10/26 14:37:04 debug Exp $ |
* $Id: dev_pckbc.c,v 1.60 2005/11/25 04:25:26 debug Exp $ |
29 |
* |
* |
30 |
* Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse |
* Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse |
31 |
* controller), including the 8048 keyboard chip. |
* controller), including the 8048 keyboard chip. |
100 |
#define STATE_WAITING_FOR_TRANSLTABLE 3 |
#define STATE_WAITING_FOR_TRANSLTABLE 3 |
101 |
#define STATE_WAITING_FOR_F3 4 |
#define STATE_WAITING_FOR_F3 4 |
102 |
#define STATE_WAITING_FOR_FC 5 |
#define STATE_WAITING_FOR_FC 5 |
103 |
#define STATE_LDOUTPUT 6 |
#define STATE_WAITING_FOR_AUX 6 |
104 |
#define STATE_RDOUTPUT 7 |
#define STATE_WAITING_FOR_AUX_OUT 7 |
105 |
|
#define STATE_LDOUTPUT 8 |
106 |
|
#define STATE_RDOUTPUT 9 |
107 |
|
|
108 |
|
|
109 |
/* |
/* |
271 |
|
|
272 |
|
|
273 |
/* |
/* |
274 |
* ascii_to_scancodes(): |
* ascii_to_scancodes_type2(): |
275 |
* |
* |
276 |
* Conversion from ASCII codes to default (US) keyboard scancodes. |
* Conversion from ASCII codes to default (US) keyboard scancodes. |
277 |
* (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html) |
* (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html) |
278 |
|
* |
279 |
|
* NOTE/TODO: This seems to be type 2, not type 1. |
280 |
*/ |
*/ |
281 |
static void ascii_to_pc_scancodes(int a, struct pckbc_data *d) |
static void ascii_to_pc_scancodes_type2(int a, struct pckbc_data *d) |
282 |
{ |
{ |
283 |
int old_head; |
int old_head; |
284 |
int p = 0; /* port */ |
int p = 0; /* port */ |
289 |
return; |
return; |
290 |
} |
} |
291 |
|
|
292 |
if (d->translation_table != 1) { |
if (d->translation_table != 2) { |
293 |
fatal("[ ascii_to_pc_scancodes: unimplemented type! ]\n"); |
fatal("[ ascii_to_pc_scancodes: unimplemented type! ]\n"); |
294 |
return; |
return; |
295 |
} |
} |
444 |
if (d->in_use && console_charavail(d->console_handle)) { |
if (d->in_use && console_charavail(d->console_handle)) { |
445 |
ch = console_readchar(d->console_handle); |
ch = console_readchar(d->console_handle); |
446 |
if (ch >= 0) |
if (ch >= 0) |
447 |
ascii_to_pc_scancodes(ch, d); |
ascii_to_pc_scancodes_type2(ch, d); |
448 |
} |
} |
449 |
|
|
450 |
ints_enabled = d->rx_int_enable; |
ints_enabled = d->rx_int_enable; |
488 |
debug("[ pckbc: (port %i) switching to translation table " |
debug("[ pckbc: (port %i) switching to translation table " |
489 |
"0x%02x ]\n", port_nr, cmd); |
"0x%02x ]\n", port_nr, cmd); |
490 |
switch (cmd) { |
switch (cmd) { |
491 |
case 1: |
case 2: |
492 |
case 3: d->translation_table = cmd; |
case 3: d->translation_table = cmd; |
493 |
break; |
break; |
494 |
default:fatal("[ pckbc: (port %i) translation table " |
default:fatal("[ pckbc: (port %i) translation table " |
495 |
"0x%02x is NOT YET IMPLEMENTED ]\n", port_nr, cmd); |
"0x%02x is NOT YET IMPLEMENTED ]\n", |
496 |
|
port_nr, cmd); |
497 |
} |
} |
498 |
pckbc_add_code(d, KBR_ACK, port_nr); |
pckbc_add_code(d, KBR_ACK, port_nr); |
499 |
d->state = STATE_NORMAL; |
d->state = STATE_NORMAL; |
516 |
return; |
return; |
517 |
} |
} |
518 |
|
|
519 |
|
if (d->state == STATE_WAITING_FOR_AUX) { |
520 |
|
debug("[ pckbc: (port %i) received aux data: " |
521 |
|
"0x%02x ]\n", port_nr, cmd); |
522 |
|
/* Echo back. */ |
523 |
|
pckbc_add_code(d, cmd, port_nr); |
524 |
|
d->state = STATE_NORMAL; |
525 |
|
return; |
526 |
|
} |
527 |
|
|
528 |
|
if (d->state == STATE_WAITING_FOR_AUX_OUT) { |
529 |
|
debug("[ pckbc: (port %i) received aux out data: " |
530 |
|
"0x%02x ]\n", port_nr, cmd); |
531 |
|
/* Echo back. */ |
532 |
|
pckbc_add_code(d, cmd, port_nr); |
533 |
|
d->state = STATE_NORMAL; |
534 |
|
return; |
535 |
|
} |
536 |
|
|
537 |
switch (cmd) { |
switch (cmd) { |
538 |
case 0x00: |
case 0x00: |
539 |
pckbc_add_code(d, KBR_ACK, port_nr); |
pckbc_add_code(d, KBR_ACK, port_nr); |
664 |
} |
} |
665 |
} |
} |
666 |
/* debug("[ pckbc: read from DATA: 0x%02x ]\n", |
/* debug("[ pckbc: read from DATA: 0x%02x ]\n", |
667 |
odata); */ |
(int)odata); */ |
668 |
} else { |
} else { |
669 |
debug("[ pckbc: write to DATA:"); |
debug("[ pckbc: write to DATA:"); |
670 |
for (i=0; i<len; i++) |
for (i=0; i<len; i++) |
713 |
d->reg[relative_addr] = idata; |
d->reg[relative_addr] = idata; |
714 |
|
|
715 |
switch (idata) { |
switch (idata) { |
716 |
|
case 0x10: |
717 |
|
case 0x11: |
718 |
|
/* TODO: For now, don't print warnings about |
719 |
|
these. NetBSD sends these. */ |
720 |
|
break; |
721 |
case K_RDCMDBYTE: |
case K_RDCMDBYTE: |
722 |
d->state = STATE_RDCMDBYTE; |
d->state = STATE_RDCMDBYTE; |
723 |
break; |
break; |
736 |
case 0xaa: /* keyboard self-test */ |
case 0xaa: /* keyboard self-test */ |
737 |
pckbc_add_code(d, 0x55, port_nr); |
pckbc_add_code(d, 0x55, port_nr); |
738 |
break; |
break; |
739 |
|
case 0xab: /* keyboard interface self-test */ |
740 |
|
pckbc_add_code(d, 0x00, port_nr); |
741 |
|
break; |
742 |
case 0xad: |
case 0xad: |
743 |
d->cmdbyte |= KC8_KDISABLE; |
d->cmdbyte |= KC8_KDISABLE; |
744 |
break; |
break; |
751 |
case 0xd1: |
case 0xd1: |
752 |
d->state = STATE_LDOUTPUT; |
d->state = STATE_LDOUTPUT; |
753 |
break; |
break; |
754 |
|
case 0xd3: /* write to auxiliary device |
755 |
|
output buffer */ |
756 |
|
debug("[ pckbc: CONTROL 0xd3, TODO ]\n"); |
757 |
|
d->state = STATE_WAITING_FOR_AUX_OUT; |
758 |
|
break; |
759 |
case 0xd4: /* write to auxiliary port */ |
case 0xd4: /* write to auxiliary port */ |
760 |
debug("[ pckbc: CONTROL 0xd4, TODO ]\n"); |
debug("[ pckbc: CONTROL 0xd4, TODO ]\n"); |
761 |
|
d->state = STATE_WAITING_FOR_AUX; |
762 |
break; |
break; |
763 |
default: |
default: |
764 |
fatal("[ pckbc: unknown CONTROL 0x%x ]\n", |
fatal("[ pckbc: unknown CONTROL 0x%x ]\n", |
765 |
idata); |
(int)idata); |
766 |
d->state = STATE_NORMAL; |
d->state = STATE_NORMAL; |
767 |
} |
} |
768 |
} |
} |
848 |
} |
} |
849 |
} |
} |
850 |
|
|
851 |
/* SGI? */ |
/* SGI? TODO: fix */ |
852 |
if (len == 8) |
if (len == 8) |
853 |
odata |= (odata << 8) | (odata << 16) | (odata << 24) | |
odata |= (odata << 8) | (odata << 16) | (odata << 24) | |
854 |
(odata << 32) | (odata << 40) | (odata << 48) | |
(odata << 32) | (odata << 40) | (odata << 48) | |
895 |
d->mouse_irqnr = mouse_irqnr; |
d->mouse_irqnr = mouse_irqnr; |
896 |
d->in_use = in_use; |
d->in_use = in_use; |
897 |
d->pc_style_flag = pc_style_flag; |
d->pc_style_flag = pc_style_flag; |
898 |
d->console_handle = console_start_slave_inputonly(machine, "pckbc"); |
if (d->in_use) |
899 |
d->translation_table = 1; |
d->console_handle = |
900 |
|
console_start_slave_inputonly(machine, "pckbc"); |
901 |
|
d->translation_table = 2; |
902 |
d->rx_int_enable = 1; |
d->rx_int_enable = 1; |
903 |
d->output_byte = 0x02; /* A20 enable on PCs */ |
d->output_byte = 0x02; /* A20 enable on PCs */ |
904 |
|
|
905 |
memory_device_register(mem, "pckbc", baseaddr, |
memory_device_register(mem, "pckbc", baseaddr, |
906 |
len, dev_pckbc_access, d, MEM_DEFAULT, NULL); |
len, dev_pckbc_access, d, DM_DEFAULT, NULL); |
907 |
machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT); |
machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT); |
908 |
|
|
909 |
return d->console_handle; |
return d->console_handle; |