More keyboard controller improvements - fixes IBM AT boot, CTRL and ALT getting stuck on pressing CTRL+ALT+ESC on Acer BIOS'es, Norton Commander behaving strangely after pressing ALT+Print Screen, and also moved PS/2 mouse command responses to their own queue to simulate the fact that on real hardware, PS/2 mouse commands, like keyboard commands, bypass the FIFO.
This commit is contained in:
@@ -95,7 +95,8 @@ typedef struct {
|
||||
uint8_t command, status, old_status, out, old_out, secr_phase,
|
||||
mem_addr, input_port, output_port, old_output_port,
|
||||
key_command, output_locked, ami_stat, want60,
|
||||
wantirq, key_wantdata, ami_flags, first_write;
|
||||
wantirq, key_wantdata, ami_flags, first_write,
|
||||
ib, pad, pad0, pad1;
|
||||
|
||||
uint8_t mem[0x100];
|
||||
|
||||
@@ -127,6 +128,8 @@ static uint8_t key_queue[16];
|
||||
static int key_queue_start = 0, key_queue_end = 0;
|
||||
uint8_t mouse_queue[16];
|
||||
int mouse_queue_start = 0, mouse_queue_end = 0;
|
||||
uint8_t mouse_cmd_queue[16];
|
||||
int mouse_cmd_queue_start = 0, mouse_cmd_queue_end = 0;
|
||||
static uint8_t kbd_last_scan_code;
|
||||
static void (*mouse_write)(uint8_t val, void *priv) = NULL;
|
||||
static void *mouse_p = NULL;
|
||||
@@ -622,6 +625,9 @@ kbc_queue_reset(uint8_t channel)
|
||||
if (channel == 2) {
|
||||
mouse_queue_start = mouse_queue_end = 0;
|
||||
memset(mouse_queue, 0x00, sizeof(mouse_queue));
|
||||
|
||||
mouse_cmd_queue_start = mouse_cmd_queue_end = 0;
|
||||
memset(mouse_cmd_queue, 0x00, sizeof(mouse_cmd_queue));
|
||||
} else if (channel == 1) {
|
||||
key_queue_start = key_queue_end = 0;
|
||||
memset(key_queue, 0x00, sizeof(key_queue));
|
||||
@@ -632,20 +638,30 @@ kbc_queue_reset(uint8_t channel)
|
||||
}
|
||||
|
||||
static void
|
||||
kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi)
|
||||
kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel)
|
||||
{
|
||||
if (channel == 2) {
|
||||
switch (channel) {
|
||||
case 3:
|
||||
kbd_log("ATkbc: mouse_cmd_queue[%02X] = %02X;\n", mouse_cmd_queue_end, val);
|
||||
mouse_cmd_queue[mouse_cmd_queue_end] = val;
|
||||
mouse_cmd_queue_end = (mouse_cmd_queue_end + 1) & 0xf;
|
||||
break;
|
||||
case 2:
|
||||
kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val);
|
||||
mouse_queue[mouse_queue_end] = val;
|
||||
mouse_queue_end = (mouse_queue_end + 1) & 0xf;
|
||||
} else if (channel == 1) {
|
||||
break;
|
||||
case 1:
|
||||
kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val);
|
||||
key_queue[key_queue_end] = val;
|
||||
key_queue_end = (key_queue_end + 1) & 0xf;
|
||||
} else {
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val);
|
||||
key_ctrl_queue[key_ctrl_queue_end] = val;
|
||||
key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0x3f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,7 +677,7 @@ add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_
|
||||
|
||||
kbd_log("ATkbc: Adding %02X to front...\n", val);
|
||||
dev->wantirq = 0;
|
||||
if (channel == 2) {
|
||||
if (channel >= 2) {
|
||||
if (dev->mem[0x20] & 0x02)
|
||||
picint(0x1000);
|
||||
if (kbc_ven != KBC_VEN_OLIVETTI)
|
||||
@@ -689,12 +705,24 @@ add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val)
|
||||
return;
|
||||
}
|
||||
kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val);
|
||||
kbc_queue_add(dev, val, 1, 0x00);
|
||||
kbc_queue_add(dev, val, 1);
|
||||
kbd_last_scan_code = val;
|
||||
}
|
||||
|
||||
static void
|
||||
add_data_kbd_direct(atkbd_t *dev, uint8_t val)
|
||||
add_data_kbc_queue(atkbd_t *dev, uint8_t val)
|
||||
{
|
||||
if ((dev->reset_delay > 0) || (key_ctrl_queue_end >= 64)) {
|
||||
kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", (dev->reset_delay > 0), (key_ctrl_queue_end >= 64));
|
||||
return;
|
||||
}
|
||||
kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val);
|
||||
kbc_queue_add(dev, val, 0);
|
||||
kbd_last_scan_code = val;
|
||||
}
|
||||
|
||||
static void
|
||||
add_data_kbd_front(atkbd_t *dev, uint8_t val)
|
||||
{
|
||||
int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF);
|
||||
int translate = (keyboard_mode & 0x40);
|
||||
@@ -711,15 +739,17 @@ add_data_kbd_direct(atkbd_t *dev, uint8_t val)
|
||||
else
|
||||
send = val;
|
||||
|
||||
add_data_kbd_queue(dev, 1, send);
|
||||
add_data_kbc_queue(dev, send);
|
||||
}
|
||||
|
||||
static void
|
||||
add_data_kbd_raw(atkbd_t *dev, uint8_t val)
|
||||
{
|
||||
add_data_kbd_queue(dev, 1, val);
|
||||
add_data_kbc_queue(dev, val);
|
||||
}
|
||||
|
||||
static void kbd_process_cmd(void *priv);
|
||||
|
||||
static void
|
||||
kbd_poll(void *priv)
|
||||
{
|
||||
@@ -730,6 +760,17 @@ kbd_poll(void *priv)
|
||||
|
||||
timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC));
|
||||
|
||||
if (dev->status & STAT_IFULL) {
|
||||
dev->status &= ~STAT_IFULL;
|
||||
kbd_process_cmd(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Scan should be disabled unless command is over, but for that, we need a better way
|
||||
to handle keyboard controller commands that return multiple bytes. */
|
||||
// if (dev->want60 != 0) || (dev->key_wantdata != 0)
|
||||
// return;
|
||||
|
||||
if (dev->out_new != -1 && !dev->last_irq) {
|
||||
dev->wantirq = 0;
|
||||
if (dev->out_new & 0x100) {
|
||||
@@ -751,7 +792,7 @@ kbd_poll(void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) {
|
||||
if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && key_ctrl_queue_start != key_ctrl_queue_end) {
|
||||
kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]);
|
||||
dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200;
|
||||
key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0x3f;
|
||||
@@ -759,6 +800,10 @@ kbd_poll(void *priv)
|
||||
kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]);
|
||||
dev->out_new = dev->out_delayed;
|
||||
dev->out_delayed = -1;
|
||||
} else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_cmd_queue_start != mouse_cmd_queue_end) {
|
||||
kbd_log("ATkbc: %02X on channel 2\n", mouse_cmd_queue[mouse_cmd_queue_start]);
|
||||
dev->out_new = mouse_cmd_queue[mouse_cmd_queue_start] | 0x100;
|
||||
mouse_cmd_queue_start = (mouse_cmd_queue_start + 1) & 0xf;
|
||||
} else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) {
|
||||
kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]);
|
||||
dev->out_new = mouse_queue[mouse_queue_start] | 0x100;
|
||||
@@ -773,7 +818,7 @@ kbd_poll(void *priv)
|
||||
dev->reset_delay--;
|
||||
if (!dev->reset_delay) {
|
||||
kbd_log("ATkbc: Sending AA on keyboard reset...\n");
|
||||
add_data_kbd_direct(dev, 0xaa);
|
||||
add_data_kbd_front(dev, 0xaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -784,7 +829,7 @@ add_data(atkbd_t *dev, uint8_t val)
|
||||
kbd_log("ATkbc: add to queue\n");
|
||||
|
||||
kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val);
|
||||
kbc_queue_add(dev, val, 0, 0x00);
|
||||
kbc_queue_add(dev, val, 0);
|
||||
|
||||
if (!(dev->out_new & 0x300)) {
|
||||
dev->out_delayed = dev->out_new;
|
||||
@@ -1890,385 +1935,30 @@ write64_toshiba(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static void
|
||||
kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
kbd_process_cmd(void *priv)
|
||||
{
|
||||
atkbd_t *dev = (atkbd_t *) priv;
|
||||
int i = 0, bad = 1;
|
||||
uint8_t mask, kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
uint8_t cmd_ac_conv[16] = { 0x0b, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21 };
|
||||
|
||||
kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X) = %02X\n", port, val);
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
dev->status &= ~STAT_CD;
|
||||
if (dev->want60) {
|
||||
/* Write data to controller. */
|
||||
dev->want60 = 0;
|
||||
|
||||
switch (dev->command) {
|
||||
case 0x60:
|
||||
case 0x61:
|
||||
case 0x62:
|
||||
case 0x63:
|
||||
case 0x64:
|
||||
case 0x65:
|
||||
case 0x66:
|
||||
case 0x67:
|
||||
case 0x68:
|
||||
case 0x69:
|
||||
case 0x6a:
|
||||
case 0x6b:
|
||||
case 0x6c:
|
||||
case 0x6d:
|
||||
case 0x6e:
|
||||
case 0x6f:
|
||||
case 0x70:
|
||||
case 0x71:
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
case 0x74:
|
||||
case 0x75:
|
||||
case 0x76:
|
||||
case 0x77:
|
||||
case 0x78:
|
||||
case 0x79:
|
||||
case 0x7a:
|
||||
case 0x7b:
|
||||
case 0x7c:
|
||||
case 0x7d:
|
||||
case 0x7e:
|
||||
case 0x7f:
|
||||
dev->mem[(dev->command & 0x1f) + 0x20] = val;
|
||||
if (dev->command == 0x60)
|
||||
write_cmd(dev, val);
|
||||
break;
|
||||
|
||||
case 0xd1: /* write output port */
|
||||
kbd_log("ATkbc: write output port\n");
|
||||
/* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no),
|
||||
discovered by reverse-engineering the AOpeN Vi15G BIOS. */
|
||||
if (dev->ami_flags & 0x04) {
|
||||
/*If keyboard controller lines P22-P23 are blocked,
|
||||
we force them to remain unchanged.*/
|
||||
val &= ~0x0c;
|
||||
val |= (dev->output_port & 0x0c);
|
||||
}
|
||||
write_output(dev, val | 0x01);
|
||||
break;
|
||||
|
||||
case 0xd2: /* write to keyboard output buffer */
|
||||
kbd_log("ATkbc: write to keyboard output buffer\n");
|
||||
add_to_kbc_queue_front(dev, val, 0, 0x00);
|
||||
break;
|
||||
|
||||
case 0xd3: /* write to mouse output buffer */
|
||||
kbd_log("ATkbc: write to mouse output buffer\n");
|
||||
if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF))
|
||||
keyboard_at_adddata_mouse(val);
|
||||
break;
|
||||
|
||||
case 0xd4: /* write to mouse */
|
||||
kbd_log("ATkbc: write to mouse (%02X)\n", val);
|
||||
|
||||
if (val == 0xbb)
|
||||
break;
|
||||
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
|
||||
set_enable_mouse(dev, 1);
|
||||
if (mouse_write)
|
||||
mouse_write(val, mouse_p);
|
||||
else
|
||||
add_to_kbc_queue_front(dev, 0xfe, 2, 0x40);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Run the vendor-specific handler
|
||||
* if we have one. Otherwise, or if
|
||||
* it returns an error, log a bad
|
||||
* controller command.
|
||||
*/
|
||||
if (dev->write60_ven)
|
||||
bad = dev->write60_ven(dev, val);
|
||||
|
||||
if (bad) {
|
||||
kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val);
|
||||
add_data_kbd(0xfe);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Write data to keyboard. */
|
||||
dev->mem[0x20] &= ~0x10;
|
||||
|
||||
if (dev->key_wantdata) {
|
||||
dev->key_wantdata = 0;
|
||||
|
||||
/*
|
||||
* Several system BIOSes and OS device drivers
|
||||
* mess up with this, and repeat the command
|
||||
* code many times. Fun!
|
||||
*/
|
||||
if (val == dev->key_command) {
|
||||
/* Respond NAK and ignore it. */
|
||||
add_data_kbd(0xfe);
|
||||
dev->key_command = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dev->key_command) {
|
||||
case 0xed: /* set/reset LEDs */
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
kbd_log("ATkbd: set LEDs [%02x]\n", val);
|
||||
break;
|
||||
|
||||
case 0xf0: /* get/set scancode set */
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
if (val == 0) {
|
||||
kbd_log("Get scan code set: %02X\n", keyboard_mode & 3);
|
||||
add_data_kbd_direct(dev, keyboard_mode & 3);
|
||||
} else {
|
||||
if ((val <= 3) && (val != 1)) {
|
||||
keyboard_mode &= 0xfc;
|
||||
keyboard_mode |= (val & 3);
|
||||
kbd_log("Scan code set now: %02X\n", val);
|
||||
}
|
||||
set_scancode_map(dev);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xf3: /* set typematic rate/delay */
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
break;
|
||||
|
||||
default:
|
||||
kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command);
|
||||
add_data_kbd_direct(dev, 0xfe);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Keyboard command is now done. */
|
||||
dev->key_command = 0x00;
|
||||
} else {
|
||||
/* No keyboard command in progress. */
|
||||
dev->key_command = 0x00;
|
||||
|
||||
set_enable_kbd(dev, 1);
|
||||
|
||||
switch (val) {
|
||||
case 0x00:
|
||||
kbd_log("ATkbd: command 00\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
break;
|
||||
|
||||
case 0x05: /*??? - sent by NT 4.0*/
|
||||
kbd_log("ATkbd: command 05 (NT 4.0)\n");
|
||||
add_data_kbd_direct(dev, 0xfe);
|
||||
break;
|
||||
|
||||
/* Sent by Pentium-era AMI BIOS'es.*/
|
||||
case 0x71:
|
||||
case 0x82:
|
||||
kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val);
|
||||
break;
|
||||
|
||||
case 0xed: /* set/reset LEDs */
|
||||
kbd_log("ATkbd: set/reset leds\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
|
||||
dev->key_wantdata = 1;
|
||||
break;
|
||||
|
||||
case 0xee: /* diagnostic echo */
|
||||
kbd_log("ATkbd: ECHO\n");
|
||||
add_data_kbd_direct(dev, 0xee);
|
||||
break;
|
||||
|
||||
case 0xef: /* NOP (reserved for future use) */
|
||||
kbd_log("ATkbd: NOP\n");
|
||||
break;
|
||||
|
||||
case 0xf0: /* get/set scan code set */
|
||||
kbd_log("ATkbd: scan code set\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
dev->key_wantdata = 1;
|
||||
break;
|
||||
|
||||
case 0xf2: /* read ID */
|
||||
/* Fixed as translation will be done in add_data_kbd(). */
|
||||
kbd_log("ATkbd: read keyboard id\n");
|
||||
/* TODO: After keyboard type selection is implemented, make this
|
||||
return the correct keyboard ID for the selected type. */
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
add_data_kbd_direct(dev, 0xab);
|
||||
add_data_kbd_direct(dev, 0x83);
|
||||
break;
|
||||
|
||||
case 0xf3: /* set typematic rate/delay */
|
||||
kbd_log("ATkbd: set typematic rate/delay\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
dev->key_wantdata = 1;
|
||||
break;
|
||||
|
||||
case 0xf4: /* enable keyboard */
|
||||
kbd_log("ATkbd: enable keyboard\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
keyboard_scan = 1;
|
||||
break;
|
||||
|
||||
case 0xf5: /* set defaults and disable keyboard */
|
||||
case 0xf6: /* set defaults */
|
||||
kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard");
|
||||
keyboard_scan = (val == 0xf6);
|
||||
kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n",
|
||||
val, keyboard_scan, dev->mem[0]);
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
|
||||
keyboard_set3_all_break = 0;
|
||||
keyboard_set3_all_repeat = 0;
|
||||
memset(keyboard_set3_flags, 0, 512);
|
||||
keyboard_mode = (keyboard_mode & 0xfc) | 0x02;
|
||||
set_scancode_map(dev);
|
||||
break;
|
||||
|
||||
case 0xf7: /* set all keys to repeat */
|
||||
kbd_log("ATkbd: set all keys to repeat\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
keyboard_set3_all_break = 1;
|
||||
break;
|
||||
|
||||
case 0xf8: /* set all keys to give make/break codes */
|
||||
kbd_log("ATkbd: set all keys to give make/break codes\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
keyboard_set3_all_break = 1;
|
||||
break;
|
||||
|
||||
case 0xf9: /* set all keys to give make codes only */
|
||||
kbd_log("ATkbd: set all keys to give make codes only\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
keyboard_set3_all_break = 0;
|
||||
break;
|
||||
|
||||
case 0xfa: /* set all keys to repeat and give make/break codes */
|
||||
kbd_log("ATkbd: set all keys to repeat and give make/break codes\n");
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
keyboard_set3_all_repeat = 1;
|
||||
keyboard_set3_all_break = 1;
|
||||
break;
|
||||
|
||||
case 0xfe: /* resend last scan code */
|
||||
kbd_log("ATkbd: reset last scan code\n");
|
||||
add_data_kbd_raw(dev, kbd_last_scan_code);
|
||||
break;
|
||||
|
||||
case 0xff: /* reset */
|
||||
kbd_log("ATkbd: kbd reset\n");
|
||||
kbc_queue_reset(1);
|
||||
kbd_last_scan_code = 0x00;
|
||||
add_data_kbd_direct(dev, 0xfa);
|
||||
|
||||
/* Set scan code set to 2. */
|
||||
keyboard_mode = (keyboard_mode & 0xfc) | 0x02;
|
||||
set_scancode_map(dev);
|
||||
|
||||
dev->reset_delay = RESET_DELAY_TIME;
|
||||
break;
|
||||
|
||||
default:
|
||||
kbd_log("ATkbd: bad keyboard command %02X\n", val);
|
||||
add_data_kbd_direct(dev, 0xfe);
|
||||
}
|
||||
|
||||
/* If command needs data, remember command. */
|
||||
if (dev->key_wantdata == 1)
|
||||
dev->key_command = val;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
if (dev->status & STAT_CD) {
|
||||
/* Controller command. */
|
||||
dev->want60 = 0;
|
||||
dev->status |= STAT_CD;
|
||||
|
||||
switch (val) {
|
||||
switch (dev->ib) {
|
||||
/* Read data from KBC memory. */
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
case 0x23:
|
||||
case 0x24:
|
||||
case 0x25:
|
||||
case 0x26:
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2a:
|
||||
case 0x2b:
|
||||
case 0x2c:
|
||||
case 0x2d:
|
||||
case 0x2e:
|
||||
case 0x2f:
|
||||
case 0x30:
|
||||
case 0x31:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
case 0x34:
|
||||
case 0x35:
|
||||
case 0x36:
|
||||
case 0x37:
|
||||
case 0x38:
|
||||
case 0x39:
|
||||
case 0x3a:
|
||||
case 0x3b:
|
||||
case 0x3c:
|
||||
case 0x3d:
|
||||
case 0x3e:
|
||||
case 0x3f:
|
||||
add_to_kbc_queue_front(dev, dev->mem[val], 0, 0x00);
|
||||
case 0x20 ... 0x3f:
|
||||
add_to_kbc_queue_front(dev, dev->mem[dev->ib], 0, 0x00);
|
||||
break;
|
||||
|
||||
/* Write data to KBC memory. */
|
||||
case 0x60:
|
||||
case 0x61:
|
||||
case 0x62:
|
||||
case 0x63:
|
||||
case 0x64:
|
||||
case 0x65:
|
||||
case 0x66:
|
||||
case 0x67:
|
||||
case 0x68:
|
||||
case 0x69:
|
||||
case 0x6a:
|
||||
case 0x6b:
|
||||
case 0x6c:
|
||||
case 0x6d:
|
||||
case 0x6e:
|
||||
case 0x6f:
|
||||
case 0x70:
|
||||
case 0x71:
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
case 0x74:
|
||||
case 0x75:
|
||||
case 0x76:
|
||||
case 0x77:
|
||||
case 0x78:
|
||||
case 0x79:
|
||||
case 0x7a:
|
||||
case 0x7b:
|
||||
case 0x7c:
|
||||
case 0x7d:
|
||||
case 0x7e:
|
||||
case 0x7f:
|
||||
case 0x60 ... 0x7f:
|
||||
dev->want60 = 1;
|
||||
break;
|
||||
|
||||
case 0xaa: /* self-test */
|
||||
kbd_log("ATkbc: self-test\n");
|
||||
if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG))
|
||||
dev->status |= STAT_IFULL;
|
||||
write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf);
|
||||
|
||||
/* Always reinitialize all queues - the real hardware pulls keyboard and mouse
|
||||
@@ -2285,7 +1975,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
write_cmd(dev, 0x30 | STAT_SYSFLAG);
|
||||
else
|
||||
write_cmd(dev, 0x10 | STAT_SYSFLAG);
|
||||
add_to_kbc_queue_front(dev, 0x55, 0, 0x00);
|
||||
// add_to_kbc_queue_front(dev, 0x55, 0, 0x00);
|
||||
add_data(dev, 0x55);
|
||||
break;
|
||||
|
||||
case 0xab: /* interface test */
|
||||
@@ -2349,8 +2040,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
case 0xdd: /* disable A20 address line */
|
||||
case 0xdf: /* enable A20 address line */
|
||||
kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis" : "en");
|
||||
write_output(dev, (dev->output_port & 0xfd) | (val & 0x02));
|
||||
kbd_log("ATkbc: %sable A20\n", (dev->ib == 0xdd) ? "dis" : "en");
|
||||
write_output(dev, (dev->output_port & 0xfd) | (dev->ib & 0x02));
|
||||
break;
|
||||
|
||||
case 0xe0: /* read test inputs */
|
||||
@@ -2367,16 +2058,289 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
* log a bad command.
|
||||
*/
|
||||
if (dev->write64_ven)
|
||||
bad = dev->write64_ven(dev, val);
|
||||
bad = dev->write64_ven(dev, dev->ib);
|
||||
|
||||
kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val);
|
||||
kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib);
|
||||
}
|
||||
|
||||
/* If the command needs data, remember the command. */
|
||||
if (dev->want60)
|
||||
dev->command = val;
|
||||
dev->command = dev->ib;
|
||||
} else {
|
||||
if (dev->want60) {
|
||||
/* Write data to controller. */
|
||||
dev->want60 = 0;
|
||||
|
||||
switch (dev->command) {
|
||||
case 0x60 ... 0x7f:
|
||||
dev->mem[(dev->command & 0x1f) + 0x20] = dev->ib;
|
||||
if (dev->command == 0x60)
|
||||
write_cmd(dev, dev->ib);
|
||||
break;
|
||||
|
||||
case 0xd1: /* write output port */
|
||||
kbd_log("ATkbc: write output port\n");
|
||||
/* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no),
|
||||
discovered by reverse-engineering the AOpeN Vi15G BIOS. */
|
||||
if (dev->ami_flags & 0x04) {
|
||||
/* If keyboard controller lines P22-P23 are blocked,
|
||||
we force them to remain unchanged. */
|
||||
dev->ib &= ~0x0c;
|
||||
dev->ib |= (dev->output_port & 0x0c);
|
||||
}
|
||||
write_output(dev, dev->ib | 0x01);
|
||||
break;
|
||||
|
||||
case 0xd2: /* write to keyboard output buffer */
|
||||
kbd_log("ATkbc: write to keyboard output buffer\n");
|
||||
add_to_kbc_queue_front(dev, dev->ib, 0, 0x00);
|
||||
break;
|
||||
|
||||
case 0xd3: /* write to mouse output buffer */
|
||||
kbd_log("ATkbc: write to mouse output buffer\n");
|
||||
if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF))
|
||||
keyboard_at_adddata_mouse(dev->ib);
|
||||
break;
|
||||
|
||||
case 0xd4: /* write to mouse */
|
||||
kbd_log("ATkbc: write to mouse (%02X)\n", dev->ib);
|
||||
|
||||
if (dev->ib == 0xbb)
|
||||
break;
|
||||
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
|
||||
set_enable_mouse(dev, 1);
|
||||
if (mouse_write)
|
||||
mouse_write(dev->ib, mouse_p);
|
||||
else
|
||||
add_to_kbc_queue_front(dev, 0xfe, 2, 0x40);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Run the vendor-specific handler
|
||||
* if we have one. Otherwise, or if
|
||||
* it returns an error, log a bad
|
||||
* controller command.
|
||||
*/
|
||||
if (dev->write60_ven)
|
||||
bad = dev->write60_ven(dev, dev->ib);
|
||||
|
||||
if (bad) {
|
||||
kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib);
|
||||
add_data_kbd(0xfe);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Write data to keyboard. */
|
||||
dev->mem[0x20] &= ~0x10;
|
||||
|
||||
if (dev->key_wantdata) {
|
||||
dev->key_wantdata = 0;
|
||||
|
||||
/*
|
||||
* Several system BIOSes and OS device drivers
|
||||
* mess up with this, and repeat the command
|
||||
* code many times. Fun!
|
||||
*/
|
||||
if (dev->ib == dev->key_command) {
|
||||
/* Respond NAK and ignore it. */
|
||||
add_data_kbd(0xfe);
|
||||
dev->key_command = 0x00;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->key_command) {
|
||||
case 0xed: /* set/reset LEDs */
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
kbd_log("ATkbd: set LEDs [%02x]\n", dev->ib);
|
||||
break;
|
||||
|
||||
case 0xf0: /* get/set scancode set */
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
if (dev->ib == 0) {
|
||||
kbd_log("Get scan code set: %02X\n", keyboard_mode & 3);
|
||||
add_data_kbd_front(dev, keyboard_mode & 3);
|
||||
} else {
|
||||
if ((dev->ib <= 3) && (dev->ib != 1)) {
|
||||
keyboard_mode &= 0xfc;
|
||||
keyboard_mode |= (dev->ib & 3);
|
||||
kbd_log("Scan code set now: %02X\n", dev->ib);
|
||||
}
|
||||
set_scancode_map(dev);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xf3: /* set typematic rate/delay */
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
break;
|
||||
|
||||
default:
|
||||
kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", dev->ib, dev->key_command);
|
||||
add_data_kbd_front(dev, 0xfe);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Keyboard command is now done. */
|
||||
dev->key_command = 0x00;
|
||||
} else {
|
||||
/* No keyboard command in progress. */
|
||||
dev->key_command = 0x00;
|
||||
|
||||
set_enable_kbd(dev, 1);
|
||||
|
||||
switch (dev->ib) {
|
||||
case 0x00:
|
||||
kbd_log("ATkbd: command 00\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
break;
|
||||
|
||||
case 0x05: /*??? - sent by NT 4.0*/
|
||||
kbd_log("ATkbd: command 05 (NT 4.0)\n");
|
||||
add_data_kbd_front(dev, 0xfe);
|
||||
break;
|
||||
|
||||
/* Sent by Pentium-era AMI BIOS'es.*/
|
||||
case 0x71:
|
||||
case 0x82:
|
||||
kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", dev->ib);
|
||||
break;
|
||||
|
||||
case 0xed: /* set/reset LEDs */
|
||||
kbd_log("ATkbd: set/reset leds\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
|
||||
dev->key_wantdata = 1;
|
||||
break;
|
||||
|
||||
case 0xee: /* diagnostic echo */
|
||||
kbd_log("ATkbd: ECHO\n");
|
||||
add_data_kbd_front(dev, 0xee);
|
||||
break;
|
||||
|
||||
case 0xef: /* NOP (reserved for future use) */
|
||||
kbd_log("ATkbd: NOP\n");
|
||||
break;
|
||||
|
||||
case 0xf0: /* get/set scan code set */
|
||||
kbd_log("ATkbd: scan code set\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
dev->key_wantdata = 1;
|
||||
break;
|
||||
|
||||
case 0xf2: /* read ID */
|
||||
/* Fixed as translation will be done in add_data_kbd(). */
|
||||
kbd_log("ATkbd: read keyboard id\n");
|
||||
/* TODO: After keyboard type selection is implemented, make this
|
||||
return the correct keyboard ID for the selected type. */
|
||||
add_data_kbd_front(dev, 0x83);
|
||||
add_data_kbd_front(dev, 0xab);
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
break;
|
||||
|
||||
case 0xf3: /* set typematic rate/delay */
|
||||
kbd_log("ATkbd: set typematic rate/delay\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
dev->key_wantdata = 1;
|
||||
break;
|
||||
|
||||
case 0xf4: /* enable keyboard */
|
||||
kbd_log("ATkbd: enable keyboard\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
keyboard_scan = 1;
|
||||
break;
|
||||
|
||||
case 0xf5: /* set defaults and disable keyboard */
|
||||
case 0xf6: /* set defaults */
|
||||
kbd_log("ATkbd: set defaults%s\n", (dev->ib == 0xf6) ? "" : " and disable keyboard");
|
||||
keyboard_scan = (dev->ib == 0xf6);
|
||||
kbd_log("dev->ib = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n",
|
||||
dev->ib, keyboard_scan, dev->mem[0]);
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
|
||||
keyboard_set3_all_break = 0;
|
||||
keyboard_set3_all_repeat = 0;
|
||||
memset(keyboard_set3_flags, 0, 512);
|
||||
keyboard_mode = (keyboard_mode & 0xfc) | 0x02;
|
||||
set_scancode_map(dev);
|
||||
break;
|
||||
|
||||
case 0xf7: /* set all keys to repeat */
|
||||
kbd_log("ATkbd: set all keys to repeat\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
keyboard_set3_all_break = 1;
|
||||
break;
|
||||
|
||||
case 0xf8: /* set all keys to give make/break codes */
|
||||
kbd_log("ATkbd: set all keys to give make/break codes\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
keyboard_set3_all_break = 1;
|
||||
break;
|
||||
|
||||
case 0xf9: /* set all keys to give make codes only */
|
||||
kbd_log("ATkbd: set all keys to give make codes only\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
keyboard_set3_all_break = 0;
|
||||
break;
|
||||
|
||||
case 0xfa: /* set all keys to repeat and give make/break codes */
|
||||
kbd_log("ATkbd: set all keys to repeat and give make/break codes\n");
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
keyboard_set3_all_repeat = 1;
|
||||
keyboard_set3_all_break = 1;
|
||||
break;
|
||||
|
||||
case 0xfe: /* resend last scan code */
|
||||
kbd_log("ATkbd: reset last scan code\n");
|
||||
add_data_kbd_raw(dev, kbd_last_scan_code);
|
||||
break;
|
||||
|
||||
case 0xff: /* reset */
|
||||
kbd_log("ATkbd: kbd reset\n");
|
||||
kbc_queue_reset(1);
|
||||
kbd_last_scan_code = 0x00;
|
||||
add_data_kbd_front(dev, 0xfa);
|
||||
|
||||
/* Set scan code set to 2. */
|
||||
keyboard_mode = (keyboard_mode & 0xfc) | 0x02;
|
||||
set_scancode_map(dev);
|
||||
|
||||
dev->reset_delay = RESET_DELAY_TIME;
|
||||
break;
|
||||
|
||||
default:
|
||||
kbd_log("ATkbd: bad keyboard command %02X\n", dev->ib);
|
||||
add_data_kbd_front(dev, 0xfe);
|
||||
}
|
||||
|
||||
/* If command needs data, remember command. */
|
||||
if (dev->key_wantdata == 1)
|
||||
dev->key_command = dev->ib;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
atkbd_t *dev = (atkbd_t *) priv;
|
||||
|
||||
kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X) = %02X\n", port, val);
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
dev->status &= ~STAT_CD;
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
dev->status |= STAT_CD;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->ib = val;
|
||||
dev->status |= STAT_IFULL;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
@@ -2877,7 +2841,15 @@ keyboard_at_adddata_mouse(uint8_t val)
|
||||
{
|
||||
atkbd_t *dev = SavedKbd;
|
||||
|
||||
kbc_queue_add(dev, val, 2, 0x00);
|
||||
kbc_queue_add(dev, val, 2);
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_at_adddata_mouse_cmd(uint8_t val)
|
||||
{
|
||||
atkbd_t *dev = SavedKbd;
|
||||
|
||||
kbc_queue_add(dev, val, 3);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -82,7 +82,7 @@ mouse_clear_data(void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
ps2_report_coordinates(mouse_t *dev)
|
||||
ps2_report_coordinates(mouse_t *dev, int cmd)
|
||||
{
|
||||
uint8_t buff[3] = { 0x08, 0x00, 0x00 };
|
||||
|
||||
@@ -114,9 +114,15 @@ ps2_report_coordinates(mouse_t *dev)
|
||||
buff[1] = (dev->x & 0xff);
|
||||
buff[2] = (dev->y & 0xff);
|
||||
|
||||
if (cmd) {
|
||||
keyboard_at_adddata_mouse_cmd(buff[0]);
|
||||
keyboard_at_adddata_mouse_cmd(buff[1]);
|
||||
keyboard_at_adddata_mouse_cmd(buff[2]);
|
||||
} else {
|
||||
keyboard_at_adddata_mouse(buff[0]);
|
||||
keyboard_at_adddata_mouse(buff[1]);
|
||||
keyboard_at_adddata_mouse(buff[2]);
|
||||
}
|
||||
if (dev->flags & FLAG_INTMODE) {
|
||||
int temp_z = dev->z;
|
||||
if ((dev->flags & FLAG_5BTN)) {
|
||||
@@ -126,6 +132,9 @@ ps2_report_coordinates(mouse_t *dev)
|
||||
if (mouse_buttons & 16)
|
||||
temp_z |= 0x20;
|
||||
}
|
||||
if (cmd)
|
||||
keyboard_at_adddata_mouse_cmd(temp_z);
|
||||
else
|
||||
keyboard_at_adddata_mouse(temp_z);
|
||||
}
|
||||
|
||||
@@ -147,16 +156,16 @@ ps2_write(uint8_t val, void *priv)
|
||||
switch (dev->command) {
|
||||
case 0xe8: /* set mouse resolution */
|
||||
dev->resolution = val;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
break;
|
||||
|
||||
case 0xf3: /* set sample rate */
|
||||
dev->sample_rate = val;
|
||||
keyboard_at_adddata_mouse(0xfa); /* Command response */
|
||||
keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */
|
||||
break;
|
||||
|
||||
default:
|
||||
keyboard_at_adddata_mouse(0xfc);
|
||||
keyboard_at_adddata_mouse_cmd(0xfc);
|
||||
}
|
||||
} else {
|
||||
dev->command = val;
|
||||
@@ -164,21 +173,21 @@ ps2_write(uint8_t val, void *priv)
|
||||
switch (dev->command) {
|
||||
case 0xe6: /* set scaling to 1:1 */
|
||||
dev->flags &= ~FLAG_SCALED;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
break;
|
||||
|
||||
case 0xe7: /* set scaling to 2:1 */
|
||||
dev->flags |= FLAG_SCALED;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
break;
|
||||
|
||||
case 0xe8: /* set mouse resolution */
|
||||
dev->flags |= FLAG_CTRLDAT;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
break;
|
||||
|
||||
case 0xe9: /* status request */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
temp = (dev->flags & 0x30);
|
||||
if (mouse_buttons & 1)
|
||||
temp |= 4;
|
||||
@@ -186,46 +195,46 @@ ps2_write(uint8_t val, void *priv)
|
||||
temp |= 1;
|
||||
if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI))
|
||||
temp |= 2;
|
||||
keyboard_at_adddata_mouse(temp);
|
||||
keyboard_at_adddata_mouse(dev->resolution);
|
||||
keyboard_at_adddata_mouse(dev->sample_rate);
|
||||
keyboard_at_adddata_mouse_cmd(temp);
|
||||
keyboard_at_adddata_mouse_cmd(dev->resolution);
|
||||
keyboard_at_adddata_mouse_cmd(dev->sample_rate);
|
||||
break;
|
||||
|
||||
case 0xea: /* set stream */
|
||||
dev->flags &= ~FLAG_CTRLDAT;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */
|
||||
keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */
|
||||
break;
|
||||
|
||||
case 0xeb: /* Get mouse data */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
|
||||
ps2_report_coordinates(dev);
|
||||
ps2_report_coordinates(dev, 1);
|
||||
break;
|
||||
|
||||
case 0xf2: /* read ID */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
if (dev->flags & FLAG_INTMODE)
|
||||
keyboard_at_adddata_mouse((dev->flags & FLAG_5BTN) ? 0x04 : 0x03);
|
||||
keyboard_at_adddata_mouse_cmd((dev->flags & FLAG_5BTN) ? 0x04 : 0x03);
|
||||
else
|
||||
keyboard_at_adddata_mouse(0x00);
|
||||
keyboard_at_adddata_mouse_cmd(0x00);
|
||||
break;
|
||||
|
||||
case 0xf3: /* set command mode */
|
||||
dev->flags |= FLAG_CTRLDAT;
|
||||
keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */
|
||||
keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */
|
||||
break;
|
||||
|
||||
case 0xf4: /* enable */
|
||||
dev->flags |= FLAG_ENABLED;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
break;
|
||||
|
||||
case 0xf5: /* disable */
|
||||
dev->flags &= ~FLAG_ENABLED;
|
||||
mouse_scan = 0;
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
break;
|
||||
|
||||
case 0xf6: /* set defaults */
|
||||
@@ -235,15 +244,15 @@ mouse_reset:
|
||||
dev->flags &= 0x88;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_mouse_reset();
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
keyboard_at_adddata_mouse_cmd(0xfa);
|
||||
if (dev->command == 0xff) {
|
||||
keyboard_at_adddata_mouse(0xaa);
|
||||
keyboard_at_adddata_mouse(0x00);
|
||||
keyboard_at_adddata_mouse_cmd(0xaa);
|
||||
keyboard_at_adddata_mouse_cmd(0x00);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
keyboard_at_adddata_mouse(0xfe);
|
||||
keyboard_at_adddata_mouse_cmd(0xfe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +297,7 @@ ps2_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv)
|
||||
if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) && (keyboard_at_mouse_pos() < 13)) {
|
||||
dev->b = b;
|
||||
|
||||
ps2_report_coordinates(dev);
|
||||
ps2_report_coordinates(dev, 0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
@@ -139,6 +139,7 @@ extern uint8_t keyboard_set3_flags[512];
|
||||
extern uint8_t keyboard_set3_all_repeat;
|
||||
extern uint8_t keyboard_set3_all_break;
|
||||
extern int mouse_queue_start, mouse_queue_end;
|
||||
extern int mouse_cmd_queue_start, mouse_cmd_queue_end;
|
||||
extern int mouse_scan;
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
|
||||
Reference in New Issue
Block a user