dev_pckbc.cc Source File
Back to the index.
Go to the documentation of this file.
62 #define MAX_8042_QUEUELEN 32768
71 #define PS2_CONTROL_TXINTEN (1 << 2)
72 #define PS2_CONTROL_RXINTEN (1 << 3)
74 #define PS2_STATUS_TXEMPTY (1 << 3)
75 #define PS2_STATUS_RXFULL (1 << 4)
77 #define PS2 100 // internal offset
79 #define PCKBC_TICKSHIFT 15
114 #define STATE_NORMAL 0
115 #define STATE_LDCMDBYTE 1
116 #define STATE_RDCMDBYTE 2
117 #define STATE_WAITING_FOR_TRANSLTABLE 3
118 #define STATE_WAITING_FOR_RATE 4
119 #define STATE_WAITING_FOR_ONEKEY_MB 5
120 #define STATE_WAITING_FOR_AUX 6
121 #define STATE_WAITING_FOR_AUX_OUT 7
122 #define STATE_LDOUTPUT 8
123 #define STATE_RDOUTPUT 9
136 fatal(
"[ pckbc: queue overrun, port %i! ]\n", port);
150 fatal(
"[ pckbc: queue empty, port %i! ]\n", port);
163 static void ascii_to_pc_scancodes_type1(
int a,
struct pckbc_data *d)
167 int shift = 0, ctrl = 0;
169 if (a >=
'A' && a <=
'Z') { a += 32; shift = 1; }
170 if ((a >= 1 && a <= 26) && (a!=
'\n' && a!=
'\t' && a!=
'\b' && a!=
'\r'))
171 { a += 96; ctrl = 1; }
173 if (a==
'!') { a =
'1'; shift = 1; }
174 if (a==
'@') { a =
'2'; shift = 1; }
175 if (a==
'#') { a =
'3'; shift = 1; }
176 if (a==
'$') { a =
'4'; shift = 1; }
177 if (a==
'%') { a =
'5'; shift = 1; }
178 if (a==
'^') { a =
'6'; shift = 1; }
179 if (a==
'&') { a =
'7'; shift = 1; }
180 if (a==
'*') { a =
'8'; shift = 1; }
181 if (a==
'(') { a =
'9'; shift = 1; }
182 if (a==
')') { a =
'0'; shift = 1; }
183 if (a==
'_') { a =
'-'; shift = 1; }
184 if (a==
'+') { a =
'='; shift = 1; }
185 if (a==
'{') { a =
'['; shift = 1; }
186 if (a==
'}') { a =
']'; shift = 1; }
187 if (a==
':') { a =
';'; shift = 1; }
188 if (a==
'"') { a =
'\''; shift = 1; }
189 if (a==
'|') { a =
'\\'; shift = 1; }
190 if (a==
'<') { a =
','; shift = 1; }
191 if (a==
'>') { a =
'.'; shift = 1; }
192 if (a==
'?') { a =
'/'; shift = 1; }
193 if (a==
'~') { a =
'`'; shift = 1; }
212 old_head = d->
head[p];
297 if (d->
head[p] != old_head) {
313 static void ascii_to_pc_scancodes_type2(
int a,
struct pckbc_data *d)
317 int shift = 0, ctrl = 0;
319 if (a >=
'A' && a <=
'Z') { a += 32; shift = 1; }
320 if ((a >= 1 && a <= 26) && (a!=
'\n' && a!=
'\t' && a!=
'\b' && a!=
'\r'))
321 { a += 96; ctrl = 1; }
322 if (a==
'!') { a =
'1'; shift = 1; }
323 if (a==
'@') { a =
'2'; shift = 1; }
324 if (a==
'#') { a =
'3'; shift = 1; }
325 if (a==
'$') { a =
'4'; shift = 1; }
326 if (a==
'%') { a =
'5'; shift = 1; }
327 if (a==
'^') { a =
'6'; shift = 1; }
328 if (a==
'&') { a =
'7'; shift = 1; }
329 if (a==
'*') { a =
'8'; shift = 1; }
330 if (a==
'(') { a =
'9'; shift = 1; }
331 if (a==
')') { a =
'0'; shift = 1; }
332 if (a==
'_') { a =
'-'; shift = 1; }
333 if (a==
'+') { a =
'='; shift = 1; }
334 if (a==
'{') { a =
'['; shift = 1; }
335 if (a==
'}') { a =
']'; shift = 1; }
336 if (a==
':') { a =
';'; shift = 1; }
337 if (a==
'"') { a =
'\''; shift = 1; }
338 if (a==
'|') { a =
'\\'; shift = 1; }
339 if (a==
'<') { a =
','; shift = 1; }
340 if (a==
'>') { a =
'.'; shift = 1; }
341 if (a==
'?') { a =
'/'; shift = 1; }
342 if (a==
'~') { a =
'`'; shift = 1; }
357 old_head = d->
head[p];
423 if (d->
head[p] != old_head) {
446 static void ascii_to_pc_scancodes_type3(
int a,
struct pckbc_data *d)
450 int shift = 0, ctrl = 0;
452 if (a >=
'A' && a <=
'Z') { a += 32; shift = 1; }
453 if ((a >= 1 && a <= 26) && (a!=
'\n' && a!=
'\t' && a!=
'\b' && a!=
'\r'))
454 { a += 96; ctrl = 1; }
455 if (a==
'!') { a =
'1'; shift = 1; }
456 if (a==
'@') { a =
'2'; shift = 1; }
457 if (a==
'#') { a =
'3'; shift = 1; }
458 if (a==
'$') { a =
'4'; shift = 1; }
459 if (a==
'%') { a =
'5'; shift = 1; }
460 if (a==
'^') { a =
'6'; shift = 1; }
461 if (a==
'&') { a =
'7'; shift = 1; }
462 if (a==
'*') { a =
'8'; shift = 1; }
463 if (a==
'(') { a =
'9'; shift = 1; }
464 if (a==
')') { a =
'0'; shift = 1; }
465 if (a==
'_') { a =
'-'; shift = 1; }
466 if (a==
'+') { a =
'='; shift = 1; }
467 if (a==
'{') { a =
'['; shift = 1; }
468 if (a==
'}') { a =
']'; shift = 1; }
469 if (a==
':') { a =
';'; shift = 1; }
470 if (a==
'"') { a =
'\''; shift = 1; }
471 if (a==
'|') { a =
'\\'; shift = 1; }
472 if (a==
'<') { a =
','; shift = 1; }
473 if (a==
'>') { a =
'.'; shift = 1; }
474 if (a==
'?') { a =
'/'; shift = 1; }
475 if (a==
'~') { a =
'`'; shift = 1; }
490 old_head = d->
head[p];
556 if (d->
head[p] != old_head) {
576 bool ints_enabled =
true;
581 for (
int port_nr = 0; port_nr < 2; port_nr++) {
622 case 1: ascii_to_pc_scancodes_type1(ch, d);
624 case 2: ascii_to_pc_scancodes_type2(ch, d);
626 case 3: ascii_to_pc_scancodes_type3(ch, d);
628 default:
fatal(
"[ pckbc: unimplemented translation table type %i ]\n",
670 b1 |= ((xdelta >> 8) & 1) << 4;
671 b1 |= ((ydelta >> 8) & 1) << 5;
690 static void dev_pckbc_command(
struct pckbc_data *d,
int port_nr)
697 fatal(
"[ pckbc: (port %i) command 0x%02x ]\n", port_nr,
cmd);
701 debug(
"[ pckbc: (port %i) switching to translation table "
702 "0x%02x ]\n", port_nr,
cmd);
709 fatal(
"[ pckbc: TODO: return current translation table ]\n");
715 default:
fatal(
"[ pckbc: (port %i) translation table "
716 "0x%02x is NOT YET IMPLEMENTED ]\n",
722 fatal(
"[ pckbc: TODO: hack for non-8242. figure out how to deal with this ]\n");
732 debug(
"[ pckbc: (port %i) received Typematic/Sample Rate data: "
733 "0x%02x ]\n", port_nr,
cmd);
740 debug(
"[ pckbc: (port %i) received One-key make/break data: "
741 "0x%02x ]\n", port_nr,
cmd);
748 debug(
"[ pckbc: (port %i) received aux data: "
749 "0x%02x ]\n", port_nr,
cmd);
757 debug(
"[ pckbc: (port %i) received aux out data: "
758 "0x%02x ]\n", port_nr,
cmd);
858 fatal(
"[ pckbc: UNIMPLEMENTED command"
859 " 0x%02x (port %i) ]\n",
cmd, port_nr);
867 uint64_t idata = 0, odata = 0;
876 fatal(
"[ pckbc: write to addr 0x%x: 0x%x ]\n",
877 (
int)relative_addr, (
int)idata);
879 fatal(
"[ pckbc: read from addr 0x%x ]\n",
884 if (relative_addr >= 0x60) {
885 relative_addr -= 0x60;
886 if (relative_addr != 0)
891 relative_addr /=
sizeof(uint64_t);
893 port_nr = (relative_addr >> 2);
895 relative_addr +=
PS2;
898 if (relative_addr != 0 && relative_addr != 4) {
911 if (relative_addr != 0)
915 if (relative_addr != 0)
919 switch (relative_addr) {
927 switch (d->
state[port_nr]) {
936 default:
if (d->
head[0] != d->
tail[0]) {
948 fatal(
"[ pckbc: write to DATA:");
949 for (i=0; i<len; i++)
954 switch (d->
state[port_nr]) {
965 default:d->
reg[relative_addr] = idata;
966 dev_pckbc_command(d, port_nr);
987 debug(
"[ pckbc: write to CTL:");
988 for (i=0; i<len; i++)
991 d->
reg[relative_addr] = idata;
1012 debug(
"[ pckbc: CONTROL 0xa9, TODO ]\n");
1034 debug(
"[ pckbc: CONTROL 0xd3, TODO ]\n");
1038 debug(
"[ pckbc: CONTROL 0xd4, TODO ]\n");
1042 fatal(
"[ pckbc: unknown CONTROL 0x%x ]\n",
1055 odata = random() & 0xff;
1056 debug(
"[ pckbc: read from port %i, PS2_TXBUF: "
1057 "0x%x ]\n", port_nr, (
int)odata);
1059 debug(
"[ pckbc: write to port %i, PS2_TXBUF: "
1060 "0x%llx ]\n", port_nr, (
long long)idata);
1064 dev_pckbc_command(d, port_nr);
1073 if (d->
head[port_nr] != d->
tail[port_nr])
1075 debug(
"[ pckbc: read from port %i, PS2_RXBUF: "
1076 "0x%02x ]\n", port_nr, (
int)odata);
1078 debug(
"[ pckbc: write to port %i, PS2_RXBUF: "
1079 "0x%llx ]\n", port_nr, (
long long)idata);
1085 debug(
"[ pckbc: read from port %i, PS2_CONTROL"
1088 debug(
"[ pckbc: write to port %i, PS2_CONTROL:"
1089 " 0x%llx ]\n", port_nr, (
long long)idata);
1108 if (d->
head[port_nr] != d->
tail[port_nr]) {
1116 debug(
"[ pckbc: write to port %i, PS2_STATUS: "
1117 "0x%llx ]\n", port_nr, (
long long)idata);
1123 debug(
"[ pckbc: read from unimplemented reg %i ]\n",
1124 (
int)relative_addr);
1127 debug(
"[ pckbc: write to unimplemented reg %i:",
1128 (
int)relative_addr);
1129 for (i=0; i<len; i++)
1139 odata |= (odata << 8) | (odata << 16) | (odata << 24) |
1140 (odata << 32) | (odata << 40) | (odata << 48) |
1158 uint64_t baseaddr,
int type,
char *keyboard_irqpath,
struct interrupt irq_mouse
#define INTERRUPT_CONNECT(name, istruct)
#define INTERRUPT_ASSERT(istruct)
#define PS2_CONTROL_TXINTEN
#define STATE_WAITING_FOR_RATE
void console_getmouse(int *x, int *y, int *buttons, int *fb_nr)
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)
#define STATE_WAITING_FOR_AUX
int console_start_slave_inputonly(struct machine *machine, const char *consolename, int use_for_input)
void pckbc_add_code(struct pckbc_data *d, int code, int port)
int console_charavail(int handle)
#define MAX_8042_QUEUELEN
#define PS2_STATUS_TXEMPTY
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
void pckbc_reassert_interrupts(struct pckbc_data *d)
#define STATE_WAITING_FOR_AUX_OUT
void fatal(const char *fmt,...)
struct interrupt irq_keyboard
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
int console_readchar(int handle)
#define STATE_WAITING_FOR_TRANSLTABLE
#define STATE_WAITING_FOR_ONEKEY_MB
int currently_asserted[2]
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)
#define PS2_STATUS_RXFULL
#define INTERRUPT_DEASSERT(istruct)
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
#define PS2_CONTROL_RXINTEN
int reg[DEV_PCKBC_LENGTH]
int pckbc_get_code(struct pckbc_data *d, 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 *)
unsigned key_queue[2][MAX_8042_QUEUELEN]
#define CHECK_ALLOCATION(ptr)
Generated on Tue Aug 25 2020 19:25:06 for GXemul by
1.8.18