Moved scan code translation to the keyboard controller's side where it should be and removed an excessive keyboard command queue add function.

This commit is contained in:
OBattler
2023-04-10 14:08:36 +02:00
parent c614efa075
commit d3bd8fb1ae

View File

@@ -724,10 +724,110 @@ kbc_irq(atkbd_t *dev, uint16_t irq, int raise)
dev->irq_levels &= ~irq; dev->irq_levels &= ~irq;
} }
static int
kbc_translate(uint8_t val)
{
atkbd_t *dev = SavedKbd;
int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF);
int translate = (keyboard_mode & 0x40);
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
int ret = - 1;
translate = translate || (keyboard_mode & 0x40) || xt_mode;
translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2);
/* Allow for scan code translation. */
if (translate && (val == 0xf0)) {
kbd_log("ATkbd: translate is on, F0 prefix detected\n");
sc_or = 0x80;
return ret;
}
/* Skip break code if translated make code has bit 7 set. */
if (translate && (sc_or == 0x80) && (nont_to_t[val] & 0x80)) {
kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val);
sc_or = 0;
return ret;
}
/* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */
if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) &&
(keyboard_recv(0x138) || keyboard_recv(0x11d))) switch (val) {
case 0x4f:
t3100e_notify_set(0x01);
break; /* End */
case 0x50:
t3100e_notify_set(0x02);
break; /* Down */
case 0x51:
t3100e_notify_set(0x03);
break; /* PgDn */
case 0x52:
t3100e_notify_set(0x04);
break; /* Ins */
case 0x53:
t3100e_notify_set(0x05);
break; /* Del */
case 0x54:
t3100e_notify_set(0x06);
break; /* SysRQ */
case 0x45:
t3100e_notify_set(0x07);
break; /* NumLock */
case 0x46:
t3100e_notify_set(0x08);
break; /* ScrLock */
case 0x47:
t3100e_notify_set(0x09);
break; /* Home */
case 0x48:
t3100e_notify_set(0x0a);
break; /* Up */
case 0x49:
t3100e_notify_set(0x0b);
break; /* PgUp */
case 0x4a:
t3100e_notify_set(0x0c);
break; /* Keypad - */
case 0x4b:
t3100e_notify_set(0x0d);
break; /* Left */
case 0x4c:
t3100e_notify_set(0x0e);
break; /* KP 5 */
case 0x4d:
t3100e_notify_set(0x0f);
break; /* Right */
}
kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off");
#ifdef ENABLE_KEYBOARD_AT_LOG
kbd_log("scan code: ");
if (translate) {
kbd_log("%02X (original: ", (nont_to_t[val] | sc_or));
if (sc_or == 0x80)
kbd_log("F0 ");
kbd_log("%02X)\n", val);
} else
kbd_log("%02X\n", val);
#endif
ret = translate ? (nont_to_t[val] | sc_or) : val;
if (sc_or == 0x80)
sc_or = 0;
return ret;
}
static void static void
add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi)
{ {
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
int temp = (channel == 1) ? kbc_translate(val) : val;
if (temp == -1)
return;
if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) || if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) ||
(kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) (kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF))
@@ -735,7 +835,7 @@ add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_
else else
stat_hi |= 0x10; stat_hi |= 0x10;
kbd_log("ATkbc: Adding %02X to front on channel %i...\n", val, channel); kbd_log("ATkbc: Adding %02X to front on channel %i...\n", temp, channel);
dev->status = (dev->status & ~0xf0) | STAT_OFULL | stat_hi; dev->status = (dev->status & ~0xf0) | STAT_OFULL | stat_hi;
/* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly /* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly
@@ -755,7 +855,7 @@ add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_
} else if (dev->mem[0x20] & 0x01) } else if (dev->mem[0x20] & 0x01)
picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
dev->out = val; dev->out = temp;
} }
static void static void
@@ -784,27 +884,6 @@ add_data_kbd_queue(atkbd_t *dev, uint8_t val)
static void static void
add_data_kbd_front(atkbd_t *dev, uint8_t val) 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);
uint8_t send;
if (dev->reset_delay)
return;
translate = translate || (keyboard_mode & 0x40) || xt_mode;
translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2);
if (translate)
send = nont_to_t[val];
else
send = val;
add_data_kbd_cmd_queue(dev, send);
}
static void
add_data_kbd_raw(atkbd_t *dev, uint8_t val)
{ {
if (dev->reset_delay) if (dev->reset_delay)
return; return;
@@ -1290,118 +1369,28 @@ kbd_poll(void *priv)
static void static void
add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len)
{ {
int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF);
int translate = (keyboard_mode & 0x40);
int i; int i;
uint8_t or = 0;
uint8_t send;
if (dev->reset_delay) if (dev->reset_delay)
return; return;
translate = translate || (keyboard_mode & 0x40) || xt_mode; for (i = 0; i < len; i++)
translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); add_data_kbd_queue(dev, val[i]);
for (i = 0; i < len; i++) {
if (translate) {
if (val[i] == 0xf0) {
or = 0x80;
continue;
}
send = nont_to_t[val[i]] | or ;
if (or == 0x80)
or = 0;
} else
send = val[i];
add_data_kbd_queue(dev, send);
}
} }
static void static void
add_data_kbd(uint16_t val) add_data_kbd(uint16_t val)
{ {
atkbd_t *dev = SavedKbd; atkbd_t *dev = SavedKbd;
int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF);
int translate = (keyboard_mode & 0x40);
uint8_t fake_shift[4]; uint8_t fake_shift[4];
uint8_t num_lock = 0, shift_states = 0; uint8_t num_lock = 0, shift_states = 0;
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
if (dev->reset_delay) if (dev->reset_delay)
return; return;
translate = translate || (keyboard_mode & 0x40) || xt_mode;
translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2);
keyboard_get_states(NULL, &num_lock, NULL); keyboard_get_states(NULL, &num_lock, NULL);
shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; shift_states = keyboard_get_shift() & STATE_SHIFT_MASK;
/* Allow for scan code translation. */
if (translate && (val == 0xf0)) {
kbd_log("ATkbd: translate is on, F0 prefix detected\n");
sc_or = 0x80;
return;
}
/* Skip break code if translated make code has bit 7 set. */
if (translate && (sc_or == 0x80) && (nont_to_t[val] & 0x80)) {
kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val);
sc_or = 0;
return;
}
/* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */
if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0x138) || keyboard_recv(0x11d)))
switch (val) {
case 0x4f:
t3100e_notify_set(0x01);
break; /* End */
case 0x50:
t3100e_notify_set(0x02);
break; /* Down */
case 0x51:
t3100e_notify_set(0x03);
break; /* PgDn */
case 0x52:
t3100e_notify_set(0x04);
break; /* Ins */
case 0x53:
t3100e_notify_set(0x05);
break; /* Del */
case 0x54:
t3100e_notify_set(0x06);
break; /* SysRQ */
case 0x45:
t3100e_notify_set(0x07);
break; /* NumLock */
case 0x46:
t3100e_notify_set(0x08);
break; /* ScrLock */
case 0x47:
t3100e_notify_set(0x09);
break; /* Home */
case 0x48:
t3100e_notify_set(0x0a);
break; /* Up */
case 0x49:
t3100e_notify_set(0x0b);
break; /* PgUp */
case 0x4A:
t3100e_notify_set(0x0c);
break; /* Keypad -*/
case 0x4B:
t3100e_notify_set(0x0d);
break; /* Left */
case 0x4C:
t3100e_notify_set(0x0e);
break; /* KP 5 */
case 0x4D:
t3100e_notify_set(0x0f);
break; /* Right */
}
kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off");
switch (val) { switch (val) {
case FAKE_LSHIFT_ON: case FAKE_LSHIFT_ON:
kbd_log("fake left shift on, scan code: "); kbd_log("fake left shift on, scan code: ");
@@ -1549,23 +1538,9 @@ add_data_kbd(uint16_t val)
break; break;
default: default:
#ifdef ENABLE_KEYBOARD_AT_LOG add_data_kbd_queue(dev, val);
kbd_log("scan code: ");
if (translate) {
kbd_log("%02X (original: ", (nont_to_t[val] | sc_or));
if (sc_or == 0x80)
kbd_log("F0 ");
kbd_log("%02X)\n", val);
} else
kbd_log("%02X\n", val);
#endif
add_data_kbd_queue(dev, translate ? (nont_to_t[val] | sc_or) : val);
break; break;
} }
if (sc_or == 0x80)
sc_or = 0;
} }
static void static void
@@ -2273,7 +2248,7 @@ kbd_key_reset(atkbd_t *dev, int do_fa)
keyboard_scan = 1; keyboard_scan = 1;
if (do_fa) if (do_fa)
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
dev->reset_delay = RESET_DELAY_TIME; dev->reset_delay = RESET_DELAY_TIME;
@@ -2320,19 +2295,19 @@ kbd_process_cmd(void *priv)
*/ */
if (dev->key_dat == dev->key_command) { if (dev->key_dat == dev->key_command) {
/* Respond NAK and ignore it. */ /* Respond NAK and ignore it. */
add_data_kbd_raw(dev, 0xfe); add_data_kbd_front(dev, 0xfe);
dev->key_command = 0x00; dev->key_command = 0x00;
return; return;
} }
switch (dev->key_command) { switch (dev->key_command) {
case 0xed: /* set/reset LEDs */ case 0xed: /* set/reset LEDs */
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
kbd_log("ATkbd: set LEDs [%02x]\n", dev->key_dat); kbd_log("ATkbd: set LEDs [%02x]\n", dev->key_dat);
break; break;
case 0xf0: /* get/set scancode set */ case 0xf0: /* get/set scancode set */
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
if (dev->key_dat == 0) { if (dev->key_dat == 0) {
kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); kbd_log("Get scan code set: %02X\n", keyboard_mode & 3);
add_data_kbd_front(dev, keyboard_mode & 3); add_data_kbd_front(dev, keyboard_mode & 3);
@@ -2347,12 +2322,12 @@ kbd_process_cmd(void *priv)
break; break;
case 0xf3: /* set typematic rate/delay */ case 0xf3: /* set typematic rate/delay */
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
break; break;
default: default:
kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", dev->key_dat, dev->key_command); kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", dev->key_dat, dev->key_command);
add_data_kbd_raw(dev, 0xfe); add_data_kbd_front(dev, 0xfe);
break; break;
} }
@@ -2366,12 +2341,12 @@ kbd_process_cmd(void *priv)
switch (dev->key_dat) { switch (dev->key_dat) {
case 0x00 ... 0x7f: case 0x00 ... 0x7f:
kbd_log("ATkbd: invalid command %02X\n", dev->key_dat); kbd_log("ATkbd: invalid command %02X\n", dev->key_dat);
add_data_kbd_raw(dev, 0xfe); add_data_kbd_front(dev, 0xfe);
break; break;
case 0xed: /* set/reset LEDs */ case 0xed: /* set/reset LEDs */
kbd_log("ATkbd: set/reset leds\n"); kbd_log("ATkbd: set/reset leds\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
dev->key_wantdata = 1; dev->key_wantdata = 1;
dev->kbd_state = DEV_STATE_MAIN_WANT_IN; dev->kbd_state = DEV_STATE_MAIN_WANT_IN;
@@ -2379,7 +2354,7 @@ kbd_process_cmd(void *priv)
case 0xee: /* diagnostic echo */ case 0xee: /* diagnostic echo */
kbd_log("ATkbd: ECHO\n"); kbd_log("ATkbd: ECHO\n");
add_data_kbd_raw(dev, 0xee); add_data_kbd_front(dev, 0xee);
break; break;
case 0xef: /* NOP (reserved for future use) */ case 0xef: /* NOP (reserved for future use) */
@@ -2388,7 +2363,7 @@ kbd_process_cmd(void *priv)
case 0xf0: /* get/set scan code set */ case 0xf0: /* get/set scan code set */
kbd_log("ATkbd: scan code set\n"); kbd_log("ATkbd: scan code set\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
dev->key_wantdata = 1; dev->key_wantdata = 1;
dev->kbd_state = DEV_STATE_MAIN_WANT_IN; dev->kbd_state = DEV_STATE_MAIN_WANT_IN;
break; break;
@@ -2398,21 +2373,21 @@ kbd_process_cmd(void *priv)
kbd_log("ATkbd: read keyboard id\n"); kbd_log("ATkbd: read keyboard id\n");
/* TODO: After keyboard type selection is implemented, make this /* TODO: After keyboard type selection is implemented, make this
return the correct keyboard ID for the selected type. */ return the correct keyboard ID for the selected type. */
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
add_data_kbd_front(dev, 0xab); add_data_kbd_front(dev, 0xab);
add_data_kbd_front(dev, 0x83); add_data_kbd_front(dev, 0x83);
break; break;
case 0xf3: /* set typematic rate/delay */ case 0xf3: /* set typematic rate/delay */
kbd_log("ATkbd: set typematic rate/delay\n"); kbd_log("ATkbd: set typematic rate/delay\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
dev->key_wantdata = 1; dev->key_wantdata = 1;
dev->kbd_state = DEV_STATE_MAIN_WANT_IN; dev->kbd_state = DEV_STATE_MAIN_WANT_IN;
break; break;
case 0xf4: /* enable keyboard */ case 0xf4: /* enable keyboard */
kbd_log("ATkbd: enable keyboard\n"); kbd_log("ATkbd: enable keyboard\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
keyboard_scan = 1; keyboard_scan = 1;
break; break;
@@ -2422,7 +2397,7 @@ kbd_process_cmd(void *priv)
keyboard_scan = (dev->key_dat == 0xf6); keyboard_scan = (dev->key_dat == 0xf6);
kbd_log("dev->key_dat = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", kbd_log("dev->key_dat = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n",
dev->key_dat, keyboard_scan, dev->mem[0]); dev->key_dat, keyboard_scan, dev->mem[0]);
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
keyboard_set3_all_break = 0; keyboard_set3_all_break = 0;
keyboard_set3_all_repeat = 0; keyboard_set3_all_repeat = 0;
@@ -2433,32 +2408,32 @@ kbd_process_cmd(void *priv)
case 0xf7: /* set all keys to repeat */ case 0xf7: /* set all keys to repeat */
kbd_log("ATkbd: set all keys to repeat\n"); kbd_log("ATkbd: set all keys to repeat\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
keyboard_set3_all_break = 1; keyboard_set3_all_break = 1;
break; break;
case 0xf8: /* set all keys to give make/break codes */ case 0xf8: /* set all keys to give make/break codes */
kbd_log("ATkbd: set all keys to give make/break codes\n"); kbd_log("ATkbd: set all keys to give make/break codes\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
keyboard_set3_all_break = 1; keyboard_set3_all_break = 1;
break; break;
case 0xf9: /* set all keys to give make codes only */ case 0xf9: /* set all keys to give make codes only */
kbd_log("ATkbd: set all keys to give make codes only\n"); kbd_log("ATkbd: set all keys to give make codes only\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
keyboard_set3_all_break = 0; keyboard_set3_all_break = 0;
break; break;
case 0xfa: /* set all keys to repeat and give make/break codes */ 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"); kbd_log("ATkbd: set all keys to repeat and give make/break codes\n");
add_data_kbd_raw(dev, 0xfa); add_data_kbd_front(dev, 0xfa);
keyboard_set3_all_repeat = 1; keyboard_set3_all_repeat = 1;
keyboard_set3_all_break = 1; keyboard_set3_all_break = 1;
break; break;
case 0xfe: /* resend last scan code */ case 0xfe: /* resend last scan code */
kbd_log("ATkbd: reset last scan code\n"); kbd_log("ATkbd: reset last scan code\n");
add_data_kbd_raw(dev, kbd_last_scan_code); add_data_kbd_front(dev, kbd_last_scan_code);
break; break;
case 0xff: /* reset */ case 0xff: /* reset */