57 #define MAX_8042_QUEUELEN 256 70 #define PCKBC_TICKSHIFT 15 100 #define STATE_NORMAL 0 101 #define STATE_LDCMDBYTE 1 102 #define STATE_RDCMDBYTE 2 103 #define STATE_WAITING_FOR_TRANSLTABLE 3 104 #define STATE_WAITING_FOR_RATE 4 105 #define STATE_WAITING_FOR_ONEKEY_MB 5 106 #define STATE_WAITING_FOR_AUX 6 107 #define STATE_WAITING_FOR_AUX_OUT 7 108 #define STATE_LDOUTPUT 8 109 #define STATE_RDOUTPUT 9 122 fatal(
"[ pckbc: queue overrun, port %i! ]\n", port);
136 fatal(
"[ pckbc: queue empty, port %i! ]\n", port);
149 static void ascii_to_pc_scancodes_type3(
int a,
struct pckbc_data *d)
153 int shift = 0, ctrl = 0;
155 if (a >=
'A' && a <=
'Z') { a += 32; shift = 1; }
156 if ((a >= 1 && a <= 26) && (a!=
'\n' && a!=
'\t' && a!=
'\b' && a!=
'\r'))
157 { a += 96; ctrl = 1; }
158 if (a==
'!') { a =
'1'; shift = 1; }
159 if (a==
'@') { a =
'2'; shift = 1; }
160 if (a==
'#') { a =
'3'; shift = 1; }
161 if (a==
'$') { a =
'4'; shift = 1; }
162 if (a==
'%') { a =
'5'; shift = 1; }
163 if (a==
'^') { a =
'6'; shift = 1; }
164 if (a==
'&') { a =
'7'; shift = 1; }
165 if (a==
'*') { a =
'8'; shift = 1; }
166 if (a==
'(') { a =
'9'; shift = 1; }
167 if (a==
')') { a =
'0'; shift = 1; }
168 if (a==
'_') { a =
'-'; shift = 1; }
169 if (a==
'+') { a =
'='; shift = 1; }
170 if (a==
'{') { a =
'['; shift = 1; }
171 if (a==
'}') { a =
']'; shift = 1; }
172 if (a==
':') { a =
';'; shift = 1; }
173 if (a==
'"') { a =
'\''; shift = 1; }
174 if (a==
'|') { a =
'\\'; shift = 1; }
175 if (a==
'<') { a =
','; shift = 1; }
176 if (a==
'>') { a =
'.'; shift = 1; }
177 if (a==
'?') { a =
'/'; shift = 1; }
192 old_head = d->
head[p];
258 if (d->
head[p] != old_head) {
284 static void ascii_to_pc_scancodes_type2(
int a,
struct pckbc_data *d)
288 int shift = 0, ctrl = 0;
291 ascii_to_pc_scancodes_type3(a, d);
296 fatal(
"[ ascii_to_pc_scancodes: unimplemented type! ]\n");
300 if (a >=
'A' && a <=
'Z') { a += 32; shift = 1; }
301 if ((a >= 1 && a <= 26) && (a!=
'\n' && a!=
'\t' && a!=
'\b' && a!=
'\r'))
302 { a += 96; ctrl = 1; }
304 if (a==
'!') { a =
'1'; shift = 1; }
305 if (a==
'@') { a =
'2'; shift = 1; }
306 if (a==
'#') { a =
'3'; shift = 1; }
307 if (a==
'$') { a =
'4'; shift = 1; }
308 if (a==
'%') { a =
'5'; shift = 1; }
309 if (a==
'^') { a =
'6'; shift = 1; }
310 if (a==
'&') { a =
'7'; shift = 1; }
311 if (a==
'*') { a =
'8'; shift = 1; }
312 if (a==
'(') { a =
'9'; shift = 1; }
313 if (a==
')') { a =
'0'; shift = 1; }
314 if (a==
'_') { a =
'-'; shift = 1; }
315 if (a==
'+') { a =
'='; shift = 1; }
316 if (a==
'{') { a =
'['; shift = 1; }
317 if (a==
'}') { a =
']'; shift = 1; }
318 if (a==
':') { a =
';'; shift = 1; }
319 if (a==
'"') { a =
'\''; shift = 1; }
320 if (a==
'|') { a =
'\\'; shift = 1; }
321 if (a==
'<') { a =
','; shift = 1; }
322 if (a==
'>') { a =
'.'; shift = 1; }
323 if (a==
'?') { a =
'/'; shift = 1; }
324 if (a==
'~') { a =
'`'; shift = 1; }
343 old_head = d->
head[p];
428 if (d->
head[p] != old_head) {
442 int port_nr, ch, ints_enabled;
447 ascii_to_pc_scancodes_type2(ch, d);
457 for (port_nr=0; port_nr<2; port_nr++) {
461 if (d->
head[port_nr] != d->
tail[port_nr] && ints_enabled) {
462 debug(
"[ pckbc: interrupt port %i ]\n", port_nr);
486 static void dev_pckbc_command(
struct pckbc_data *d,
int port_nr)
494 debug(
"[ pckbc: (port %i) switching to translation table " 495 "0x%02x ]\n", port_nr, cmd);
500 default:
fatal(
"[ pckbc: (port %i) translation table " 501 "0x%02x is NOT YET IMPLEMENTED ]\n",
510 debug(
"[ pckbc: (port %i) received Typematic Rate data: " 511 "0x%02x ]\n", port_nr, cmd);
518 debug(
"[ pckbc: (port %i) received One-key make/break data: " 519 "0x%02x ]\n", port_nr, cmd);
526 debug(
"[ pckbc: (port %i) received aux data: " 527 "0x%02x ]\n", port_nr, cmd);
535 debug(
"[ pckbc: (port %i) received aux out data: " 536 "0x%02x ]\n", port_nr, cmd);
612 fatal(
"[ pckbc: (port %i) UNIMPLEMENTED 8048 command" 613 " 0x%02x ]\n", port_nr, cmd);
622 uint64_t idata = 0, odata = 0;
631 fatal(
"[ pckbc: write to addr 0x%x: 0x%x ]\n",
632 (
int)relative_addr, (
int)idata);
634 fatal(
"[ pckbc: read from addr 0x%x ]\n",
639 if (relative_addr >= 0x60) {
640 relative_addr -= 0x60;
641 if (relative_addr != 0)
646 relative_addr /=
sizeof(uint64_t);
648 port_nr = (relative_addr >> 2);
650 relative_addr +=
PS2;
653 if (relative_addr != 0 && relative_addr != 4) {
666 if (relative_addr != 0)
670 if (relative_addr != 0)
674 switch (relative_addr) {
691 default:
if (d->
head[0] != d->
tail[0]) {
702 debug(
"[ pckbc: write to DATA:");
703 for (i=0; i<len; i++)
718 default:d->
reg[relative_addr] = idata;
719 dev_pckbc_command(d, port_nr);
725 dev_pckbc_tick(
cpu, d);
742 debug(
"[ pckbc: write to CTL:");
743 for (i=0; i<len; i++)
746 d->
reg[relative_addr] = idata;
767 debug(
"[ pckbc: CONTROL 0xa9, TODO ]\n");
789 debug(
"[ pckbc: CONTROL 0xd3, TODO ]\n");
793 debug(
"[ pckbc: CONTROL 0xd4, TODO ]\n");
797 fatal(
"[ pckbc: unknown CONTROL 0x%x ]\n",
810 odata = random() & 0xff;
811 debug(
"[ pckbc: read from port %i, PS2_TXBUF: " 812 "0x%x ]\n", port_nr, (
int)odata);
814 debug(
"[ pckbc: write to port %i, PS2_TXBUF: " 815 "0x%llx ]\n", port_nr, (
long long)idata);
819 dev_pckbc_command(d, port_nr);
827 odata = random() & 0xff;
828 if (d->
head[port_nr] != d->
tail[port_nr])
830 debug(
"[ pckbc: read from port %i, PS2_RXBUF: " 831 "0x%02x ]\n", port_nr, (
int)odata);
833 debug(
"[ pckbc: write to port %i, PS2_RXBUF: " 834 "0x%llx ]\n", port_nr, (
long long)idata);
840 debug(
"[ pckbc: read from port %i, PS2_CONTROL" 843 debug(
"[ pckbc: write to port %i, PS2_CONTROL:" 844 " 0x%llx ]\n", port_nr, (
long long)idata);
856 if (d->
head[port_nr] != d->
tail[port_nr]) {
861 debug(
"[ pckbc: read from port %i, PS2_STATUS: " 862 "0x%llx ]\n", port_nr, (
long long)odata);
864 debug(
"[ pckbc: write to port %i, PS2_STATUS: " 865 "0x%llx ]\n", port_nr, (
long long)idata);
871 debug(
"[ pckbc: read from unimplemented reg %i ]\n",
875 debug(
"[ pckbc: write to unimplemented reg %i:",
877 for (i=0; i<len; i++)
886 odata |= (odata << 8) | (odata << 16) | (odata << 24) |
887 (odata << 32) | (odata << 40) | (odata << 48) |
893 dev_pckbc_tick(
cpu, d);
905 uint64_t baseaddr,
int type,
char *keyboard_irqpath,
933 machine,
"pckbc", d->
in_use);
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
void fatal(const char *fmt,...)
int console_start_slave_inputonly(struct machine *machine, const char *consolename, int use_for_input)
unsigned key_queue[2][MAX_8042_QUEUELEN]
struct interrupt irq_mouse
struct interrupt irq_keyboard
#define STATE_WAITING_FOR_AUX
int console_readchar(int handle)
#define STATE_WAITING_FOR_RATE
#define CHECK_ALLOCATION(ptr)
int console_charavail(int handle)
#define STATE_WAITING_FOR_ONEKEY_MB
#define STATE_WAITING_FOR_AUX_OUT
#define STATE_WAITING_FOR_TRANSLTABLE
#define INTERRUPT_ASSERT(istruct)
#define INTERRUPT_CONNECT(name, istruct)
int reg[DEV_PCKBC_LENGTH]
#define MAX_8042_QUEUELEN
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
void pckbc_add_code(struct pckbc_data *d, int code, int port)
int dev_pckbc_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
int currently_asserted[2]
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
int dev_pckbc_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int type, char *keyboard_irqpath, char *mouse_irqpath, int in_use, int pc_style_flag)
int pckbc_get_code(struct pckbc_data *d, int port)
#define INTERRUPT_DEASSERT(istruct)