Files
86Box/src/device/keyboard_at.c
2023-04-05 22:14:48 +02:00

2795 lines
142 KiB
C

/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Intel 8042 (AT keyboard controller) emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* EngiNerd, <webmaster.crrc@yahoo.it>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2020 EngiNerd.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define HAVE_STDARG_H
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/ppi.h>
#include <86box/mem.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/m_xt_xi8088.h>
#include <86box/m_at_t3100e.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/sound.h>
#include <86box/snd_speaker.h>
#include <86box/video.h>
#include <86box/keyboard.h>
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
#define STAT_TTIMEOUT 0x20
#define STAT_MFULL 0x20
#define STAT_UNLOCKED 0x10
#define STAT_CD 0x08
#define STAT_SYSFLAG 0x04
#define STAT_IFULL 0x02
#define STAT_OFULL 0x01
#define RESET_DELAY_TIME (100 * 10) /* 600ms */
#define CCB_UNUSED 0x80
#define CCB_TRANSLATE 0x40
#define CCB_PCMODE 0x20
#define CCB_ENABLEKBD 0x10
#define CCB_IGNORELOCK 0x08
#define CCB_SYSTEM 0x04
#define CCB_ENABLEMINT 0x02
#define CCB_ENABLEKINT 0x01
#define CCB_MASK 0x68
#define MODE_MASK 0x6c
#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */
#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */
#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */
#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */
#define KBC_TYPE_MASK 0x03
#define KBC_VEN_GENERIC 0x00
#define KBC_VEN_AMI 0x04
#define KBC_VEN_IBM_MCA 0x08
#define KBC_VEN_QUADTEL 0x0c
#define KBC_VEN_TOSHIBA 0x10
#define KBC_VEN_XI8088 0x14
#define KBC_VEN_IBM_PS1 0x18
#define KBC_VEN_ACER 0x1c
#define KBC_VEN_INTEL_AMI 0x20
#define KBC_VEN_OLIVETTI 0x24
#define KBC_VEN_NCR 0x28
#define KBC_VEN_SAMSUNG 0x2c
#define KBC_VEN_ALI 0x30
#define KBC_VEN_PHOENIX 0x3c
#define KBC_VEN_MASK 0x3c
typedef struct {
uint8_t command, status, ib, 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,
key_wantcmd, key_dat, mouse_wantcmd, mouse_dat;
uint8_t mem[0x100];
int out_new, out_new_mouse,
reset_delay, mouse_reset_delay;
uint32_t flags;
pc_timer_t pulse_cb;
uint8_t (*write60_ven)(void *p, uint8_t val);
uint8_t (*write64_ven)(void *p, uint8_t val);
pc_timer_t send_delay_timer;
} atkbd_t;
/* bit 0 = repeat, bit 1 = makes break code? */
uint8_t keyboard_set3_flags[512];
uint8_t keyboard_set3_all_repeat;
uint8_t keyboard_set3_all_break;
/* Bits 0 - 1 = scan code set, bit 6 = translate or not. */
uint8_t keyboard_mode = 0x42;
static uint8_t key_ctrl_queue[64];
static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0;
static uint8_t key_queue[16];
static int key_queue_start = 0, key_queue_end = 0;
static uint8_t key_cmd_queue[16];
static int key_cmd_queue_start = 0, key_cmd_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;
static uint8_t sc_or = 0;
static atkbd_t *SavedKbd = NULL; // FIXME: remove!!! --FvK
/* Non-translated to translated scan codes. */
static const uint8_t nont_to_t[256] = {
0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#ifdef USE_SET1
static const scancode scancode_set1[512] = {
// clang-format off
{ { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/
{ { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/
{ { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/
{ { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/
{ { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/
{ { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/
{ { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/
{ { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/
{ { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/
{ { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/
{ { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/
{ { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/
{ { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/
{ { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/
{ { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/
{ { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/
{ { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/
{ { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/
{ { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/
{ { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/
{ { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/
{ { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/
{ { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/
{ { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/
{ { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/
{ { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/
{ { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/
{ { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/
{ { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/
{ { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/
{ { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/
{ { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/
{ { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/
{ { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/
{ { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/
{ { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/
{ { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/
{ { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/
{ { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/
{ { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/
{ { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/
{ { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/
{ { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/
{ { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/
{ { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/
{ { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/
{ { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/
{ { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/
{ { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/
{ { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/
{ { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/
{ { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/
{ { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/
{ { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/
{ { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/
{ { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/
{ { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/
{ { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/
{ { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/
{ { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/
{ { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/
{ { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/
{ { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/
{ { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/
{ {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/
{ {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/
{ {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/
{ {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/
{ {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/
{ {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/
{ {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/
{ {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/
{ {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/
{ {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/
{ {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/
{ {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/
{ {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/
{ {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/
{ {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/
{ {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/
{ {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/
{ {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/
{ {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/
{ {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/
{ { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/
{ {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/
{ {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/
{ { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/
{ {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/
{ {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/
{ {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/
{ {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/
{ {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/
{ {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/
{ {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/
{ { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/
{ { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/
// clang-format on
};
#endif
static const scancode scancode_set2[512] = {
// clang-format off
{ { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/
{ { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/
{ { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/
{ { 0x4E,0},{ 0xF0,0x4E,0} }, { { 0x55,0},{ 0xF0,0x55,0} }, { { 0x66,0},{ 0xF0,0x66,0} }, { { 0x0D,0},{ 0xF0,0x0D,0} }, /*00c*/
{ { 0x15,0},{ 0xF0,0x15,0} }, { { 0x1D,0},{ 0xF0,0x1D,0} }, { { 0x24,0},{ 0xF0,0x24,0} }, { { 0x2D,0},{ 0xF0,0x2D,0} }, /*010*/
{ { 0x2C,0},{ 0xF0,0x2C,0} }, { { 0x35,0},{ 0xF0,0x35,0} }, { { 0x3C,0},{ 0xF0,0x3C,0} }, { { 0x43,0},{ 0xF0,0x43,0} }, /*014*/
{ { 0x44,0},{ 0xF0,0x44,0} }, { { 0x4D,0},{ 0xF0,0x4D,0} }, { { 0x54,0},{ 0xF0,0x54,0} }, { { 0x5B,0},{ 0xF0,0x5B,0} }, /*018*/
{ { 0x5A,0},{ 0xF0,0x5A,0} }, { { 0x14,0},{ 0xF0,0x14,0} }, { { 0x1C,0},{ 0xF0,0x1C,0} }, { { 0x1B,0},{ 0xF0,0x1B,0} }, /*01c*/
{ { 0x23,0},{ 0xF0,0x23,0} }, { { 0x2B,0},{ 0xF0,0x2B,0} }, { { 0x34,0},{ 0xF0,0x34,0} }, { { 0x33,0},{ 0xF0,0x33,0} }, /*020*/
{ { 0x3B,0},{ 0xF0,0x3B,0} }, { { 0x42,0},{ 0xF0,0x42,0} }, { { 0x4B,0},{ 0xF0,0x4B,0} }, { { 0x4C,0},{ 0xF0,0x4C,0} }, /*024*/
{ { 0x52,0},{ 0xF0,0x52,0} }, { { 0x0E,0},{ 0xF0,0x0E,0} }, { { 0x12,0},{ 0xF0,0x12,0} }, { { 0x5D,0},{ 0xF0,0x5D,0} }, /*028*/
{ { 0x1A,0},{ 0xF0,0x1A,0} }, { { 0x22,0},{ 0xF0,0x22,0} }, { { 0x21,0},{ 0xF0,0x21,0} }, { { 0x2A,0},{ 0xF0,0x2A,0} }, /*02c*/
{ { 0x32,0},{ 0xF0,0x32,0} }, { { 0x31,0},{ 0xF0,0x31,0} }, { { 0x3A,0},{ 0xF0,0x3A,0} }, { { 0x41,0},{ 0xF0,0x41,0} }, /*030*/
{ { 0x49,0},{ 0xF0,0x49,0} }, { { 0x4A,0},{ 0xF0,0x4A,0} }, { { 0x59,0},{ 0xF0,0x59,0} }, { { 0x7C,0},{ 0xF0,0x7C,0} }, /*034*/
{ { 0x11,0},{ 0xF0,0x11,0} }, { { 0x29,0},{ 0xF0,0x29,0} }, { { 0x58,0},{ 0xF0,0x58,0} }, { { 0x05,0},{ 0xF0,0x05,0} }, /*038*/
{ { 0x06,0},{ 0xF0,0x06,0} }, { { 0x04,0},{ 0xF0,0x04,0} }, { { 0x0C,0},{ 0xF0,0x0C,0} }, { { 0x03,0},{ 0xF0,0x03,0} }, /*03c*/
{ { 0x0B,0},{ 0xF0,0x0B,0} }, { { 0x83,0},{ 0xF0,0x83,0} }, { { 0x0A,0},{ 0xF0,0x0A,0} }, { { 0x01,0},{ 0xF0,0x01,0} }, /*040*/
{ { 0x09,0},{ 0xF0,0x09,0} }, { { 0x77,0},{ 0xF0,0x77,0} }, { { 0x7E,0},{ 0xF0,0x7E,0} }, { { 0x6C,0},{ 0xF0,0x6C,0} }, /*044*/
{ { 0x75,0},{ 0xF0,0x75,0} }, { { 0x7D,0},{ 0xF0,0x7D,0} }, { { 0x7B,0},{ 0xF0,0x7B,0} }, { { 0x6B,0},{ 0xF0,0x6B,0} }, /*048*/
{ { 0x73,0},{ 0xF0,0x73,0} }, { { 0x74,0},{ 0xF0,0x74,0} }, { { 0x79,0},{ 0xF0,0x79,0} }, { { 0x69,0},{ 0xF0,0x69,0} }, /*04c*/
{ { 0x72,0},{ 0xF0,0x72,0} }, { { 0x7A,0},{ 0xF0,0x7A,0} }, { { 0x70,0},{ 0xF0,0x70,0} }, { { 0x71,0},{ 0xF0,0x71,0} }, /*050*/
{ { 0x84,0},{ 0xF0,0x84,0} }, { { 0x60,0},{ 0xF0,0x60,0} }, { { 0x61,0},{ 0xF0,0x61,0} }, { { 0x78,0},{ 0xF0,0x78,0} }, /*054*/
{ { 0x07,0},{ 0xF0,0x07,0} }, { { 0x0F,0},{ 0xF0,0x0F,0} }, { { 0x17,0},{ 0xF0,0x17,0} }, { { 0x1F,0},{ 0xF0,0x1F,0} }, /*058*/
{ { 0x27,0},{ 0xF0,0x27,0} }, { { 0x2F,0},{ 0xF0,0x2F,0} }, { { 0x37,0},{ 0xF0,0x37,0} }, { { 0x3F,0},{ 0xF0,0x3F,0} }, /*05c*/
{ { 0x47,0},{ 0xF0,0x47,0} }, { { 0x4F,0},{ 0xF0,0x4F,0} }, { { 0x56,0},{ 0xF0,0x56,0} }, { { 0x5E,0},{ 0xF0,0x5E,0} }, /*060*/
{ { 0x08,0},{ 0xF0,0x08,0} }, { { 0x10,0},{ 0xF0,0x10,0} }, { { 0x18,0},{ 0xF0,0x18,0} }, { { 0x20,0},{ 0xF0,0x20,0} }, /*064*/
{ { 0x28,0},{ 0xF0,0x28,0} }, { { 0x30,0},{ 0xF0,0x30,0} }, { { 0x38,0},{ 0xF0,0x38,0} }, { { 0x40,0},{ 0xF0,0x40,0} }, /*068*/
{ { 0x48,0},{ 0xF0,0x48,0} }, { { 0x50,0},{ 0xF0,0x50,0} }, { { 0x57,0},{ 0xF0,0x57,0} }, { { 0x6F,0},{ 0xF0,0x6F,0} }, /*06c*/
{ { 0x13,0},{ 0xF0,0x13,0} }, { { 0x19,0},{ 0xF0,0x19,0} }, { { 0x39,0},{ 0xF0,0x39,0} }, { { 0x51,0},{ 0xF0,0x51,0} }, /*070*/
{ { 0x53,0},{ 0xF0,0x53,0} }, { { 0x5C,0},{ 0xF0,0x5C,0} }, { { 0x5F,0},{ 0xF0,0x5F,0} }, { { 0x62,0},{ 0xF0,0x62,0} }, /*074*/
{ { 0x63,0},{ 0xF0,0x63,0} }, { { 0x64,0},{ 0xF0,0x64,0} }, { { 0x65,0},{ 0xF0,0x65,0} }, { { 0x67,0},{ 0xF0,0x67,0} }, /*078*/
{ { 0x68,0},{ 0xF0,0x68,0} }, { { 0x6A,0},{ 0xF0,0x6A,0} }, { { 0x6D,0},{ 0xF0,0x6D,0} }, { { 0x6E,0},{ 0xF0,0x6E,0} }, /*07c*/
{ { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/
{ { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/
{ { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/
{ { 0x8c,0},{ 0xf0,0x8c,0} }, { { 0x8d,0},{ 0xf0,0x8d,0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/
{ { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/
{ { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/
{ { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/
{ { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/
{ { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/
{ { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/
{ { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/
{ { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/
{ { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/
{ { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/
{ { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/
{ { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/
{ { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/
{ { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/
{ { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/
{ { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/
{ { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/
{ { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/
{ { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/
{ { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/
{ { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/
{ { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/
{ { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/
{ { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/
{ { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/
{ { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/
{ { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/
{ { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/
{ {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/
{ {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/
{ {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/
{ {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/
{ {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/
{ {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/
{ {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/
{ {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/
{ {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/
{ {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/
{ {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/
{ {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/
{ {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { { 0},{ 0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} }, /*134*/
{ {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/
{ {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/
{ {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/
{ {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} }, /*144*/
{ {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { { 0},{ 0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} }, /*148*/
{ {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} }, /*14c*/
{ {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} }, /*150*/
{ { 0},{ 0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/
{ {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} }, /*158*/
{ {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} }, /*15c*/
{ { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} }, /*160*/
{ {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/
{ {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/
{ {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/
{ {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/
{ {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/
{ {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/
{ {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/
{ { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/
{ { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/
// clang-format on
};
static const scancode scancode_set3[512] = {
// clang-format off
{ { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/
{ { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/
{ { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/
{ { 0x4E,0},{ 0xf0,0x4E,0} }, { { 0x55,0},{ 0xf0,0x55,0} }, { { 0x66,0},{ 0xf0,0x66,0} }, { { 0x0D,0},{ 0xf0,0x0D,0} }, /*00c*/
{ { 0x15,0},{ 0xf0,0x15,0} }, { { 0x1D,0},{ 0xf0,0x1D,0} }, { { 0x24,0},{ 0xf0,0x24,0} }, { { 0x2D,0},{ 0xf0,0x2D,0} }, /*010*/
{ { 0x2C,0},{ 0xf0,0x2C,0} }, { { 0x35,0},{ 0xf0,0x35,0} }, { { 0x3C,0},{ 0xf0,0x3C,0} }, { { 0x43,0},{ 0xf0,0x43,0} }, /*014*/
{ { 0x44,0},{ 0xf0,0x44,0} }, { { 0x4D,0},{ 0xf0,0x4D,0} }, { { 0x54,0},{ 0xf0,0x54,0} }, { { 0x5B,0},{ 0xf0,0x5B,0} }, /*018*/
{ { 0x5A,0},{ 0xf0,0x5A,0} }, { { 0x11,0},{ 0xf0,0x11,0} }, { { 0x1C,0},{ 0xf0,0x1C,0} }, { { 0x1B,0},{ 0xf0,0x1B,0} }, /*01c*/
{ { 0x23,0},{ 0xf0,0x23,0} }, { { 0x2B,0},{ 0xf0,0x2B,0} }, { { 0x34,0},{ 0xf0,0x34,0} }, { { 0x33,0},{ 0xf0,0x33,0} }, /*020*/
{ { 0x3B,0},{ 0xf0,0x3B,0} }, { { 0x42,0},{ 0xf0,0x42,0} }, { { 0x4B,0},{ 0xf0,0x4B,0} }, { { 0x4C,0},{ 0xf0,0x4C,0} }, /*024*/
{ { 0x52,0},{ 0xf0,0x52,0} }, { { 0x0E,0},{ 0xf0,0x0E,0} }, { { 0x12,0},{ 0xf0,0x12,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, /*028*/
{ { 0x1A,0},{ 0xf0,0x1A,0} }, { { 0x22,0},{ 0xf0,0x22,0} }, { { 0x21,0},{ 0xf0,0x21,0} }, { { 0x2A,0},{ 0xf0,0x2A,0} }, /*02c*/
{ { 0x32,0},{ 0xf0,0x32,0} }, { { 0x31,0},{ 0xf0,0x31,0} }, { { 0x3A,0},{ 0xf0,0x3A,0} }, { { 0x41,0},{ 0xf0,0x41,0} }, /*030*/
{ { 0x49,0},{ 0xf0,0x49,0} }, { { 0x4A,0},{ 0xf0,0x4A,0} }, { { 0x59,0},{ 0xf0,0x59,0} }, { { 0x7E,0},{ 0xf0,0x7E,0} }, /*034*/
{ { 0x19,0},{ 0xf0,0x19,0} }, { { 0x29,0},{ 0xf0,0x29,0} }, { { 0x14,0},{ 0xf0,0x14,0} }, { { 0x07,0},{ 0xf0,0x07,0} }, /*038*/
{ { 0x0F,0},{ 0xf0,0x0F,0} }, { { 0x17,0},{ 0xf0,0x17,0} }, { { 0x1F,0},{ 0xf0,0x1F,0} }, { { 0x27,0},{ 0xf0,0x27,0} }, /*03c*/
{ { 0x2F,0},{ 0xf0,0x2F,0} }, { { 0x37,0},{ 0xf0,0x37,0} }, { { 0x3F,0},{ 0xf0,0x3F,0} }, { { 0x47,0},{ 0xf0,0x47,0} }, /*040*/
{ { 0x4F,0},{ 0xf0,0x4F,0} }, { { 0x76,0},{ 0xf0,0x76,0} }, { { 0x5F,0},{ 0xf0,0x5F,0} }, { { 0x6C,0},{ 0xf0,0x6C,0} }, /*044*/
{ { 0x75,0},{ 0xf0,0x75,0} }, { { 0x7D,0},{ 0xf0,0x7D,0} }, { { 0x84,0},{ 0xf0,0x84,0} }, { { 0x6B,0},{ 0xf0,0x6B,0} }, /*048*/
{ { 0x73,0},{ 0xf0,0x73,0} }, { { 0x74,0},{ 0xf0,0x74,0} }, { { 0x7C,0},{ 0xf0,0x7C,0} }, { { 0x69,0},{ 0xf0,0x69,0} }, /*04c*/
{ { 0x72,0},{ 0xf0,0x72,0} }, { { 0x7A,0},{ 0xf0,0x7A,0} }, { { 0x70,0},{ 0xf0,0x70,0} }, { { 0x71,0},{ 0xf0,0x71,0} }, /*050*/
{ { 0x57,0},{ 0xf0,0x57,0} }, { { 0x60,0},{ 0xf0,0x60,0} }, { { 0},{ 0} }, { { 0x56,0},{ 0xf0,0x56,0} }, /*054*/
{ { 0x5E,0},{ 0xf0,0x5E,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*058*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*05c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*060*/
{ { 0},{ 0} }, { { 0x10,0},{ 0xf0,0x10,0} }, { { 0x18,0},{ 0xf0,0x18,0} }, { { 0x20,0},{ 0xf0,0x20,0} }, /*064*/
{ { 0x28,0},{ 0xf0,0x28,0} }, { { 0x30,0},{ 0xf0,0x30,0} }, { { 0x38,0},{ 0xf0,0x38,0} }, { { 0x40,0},{ 0xf0,0x40,0} }, /*068*/
{ { 0x48,0},{ 0xf0,0x48,0} }, { { 0x50,0},{ 0xf0,0x50,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*06c*/
{ { 0x87,0},{ 0xf0,0x87,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0x51,0},{ 0xf0,0x51,0} }, /*070*/
{ { 0x53,0},{ 0xf0,0x53,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, { { 0},{ 0} }, { { 0x62,0},{ 0xf0,0x62,0} }, /*074*/
{ { 0x63,0},{ 0xf0,0x63,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x85,0} }, /*078*/
{ { 0x68,0},{ 0xf0,0x68,0} }, { { 0x13,0},{ 0xf0,0x13,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*07c*/
{ { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/
{ { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/
{ { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/
{ { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/
{ { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/
{ { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/
{ { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/
{ { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/
{ { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/
{ { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/
{ { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/
{ { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/
{ { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/
{ { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/
{ { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/
{ { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/
{ { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/
{ { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/
{ { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/
{ { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/
{ { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/
{ { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/
{ { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/
{ { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/
{ { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/
{ { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/
{ { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/
{ { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/
{ { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/
{ { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/
{ { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/
{ { 0x62,0},{ 0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/
{ {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/
{ {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/
{ {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/
{ {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/
{ {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/
{ {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/
{ { 0x79,0},{ 0xf0,0x79,0} }, { { 0x58,0},{ 0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/
{ {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/
{ {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/
{ {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/
{ {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/
{ {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { { 0x77,0},{ 0xf0,0x77,0} }, { { 0},{ 0} }, { { 0x57,0},{ 0xf0,0x57,0} }, /*134*/
{ { 0x39,0},{ 0xf0,0x39,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/
{ {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/
{ {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/
{ {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { { 0x6E,0},{ 0xf0,0x6E,0} }, /*144*/
{ { 0x63,0},{ 0xf0,0x63,0} }, { { 0x6F,0},{ 0xf0,0x6F,0} }, { { 0},{ 0} }, { { 0x61,0},{ 0xf0,0x61,0} }, /*148*/
{ {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { { 0x6A,0},{ 0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { { 0x65,0},{ 0xf0,0x65,0} }, /*14c*/
{ { 0x60,0},{ 0xf0,0x60,0} }, { { 0x6D,0},{ 0xf0,0x6D,0} }, { { 0x67,0},{ 0xf0,0x67,0} }, { { 0x64,0},{ 0xf0,0x64,0} }, /*150*/
{ { 0xd4,0},{ 0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/
{ {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { { 0x8B,0},{ 0xf0,0x8B,0} }, /*158*/
{ { 0x8C,0},{ 0xf0,0x8C,0} }, { { 0x8D,0},{ 0xf0,0x8D,0} }, { { 0},{ 0} }, { { 0x7F,0},{ 0xf0,0x7F,0} }, /*15c*/
{ { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { { 0},{ 0} }, /*160*/
{ {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/
{ {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/
{ {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/
{ {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/
{ {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/
{ {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/
{ {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/
{ { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/
{ { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/
{ { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/
{ { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/
// clang-format on
};
static void add_data_kbd(uint16_t val);
#ifdef ENABLE_KEYBOARD_AT_LOG
int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG;
static void
kbd_log(const char *fmt, ...)
{
va_list ap;
if (keyboard_at_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define kbd_log(fmt, ...)
#endif
static void
set_scancode_map(atkbd_t *dev)
{
switch (keyboard_mode & 3) {
#ifdef USE_SET1
case 1:
default:
keyboard_set_table(scancode_set1);
break;
#else
default:
#endif
case 2:
keyboard_set_table(scancode_set2);
break;
case 3:
keyboard_set_table(scancode_set3);
break;
}
if (keyboard_mode & 0x20)
#ifdef USE_SET1
keyboard_set_table(scancode_set1);
#else
keyboard_set_table(scancode_set2);
#endif
}
static void
kbc_queue_reset(uint8_t channel)
{
switch (channel) {
case 1:
key_queue_start = key_queue_end = 0;
memset(key_queue, 0x00, sizeof(key_queue));
/* FALLTHROUGH */
case 4:
key_cmd_queue_start = key_cmd_queue_end = 0;
memset(key_cmd_queue, 0x00, sizeof(key_cmd_queue));
break;
case 2:
mouse_queue_start = mouse_queue_end = 0;
memset(mouse_queue, 0x00, sizeof(mouse_queue));
/* FALLTHROUGH */
case 3:
mouse_cmd_queue_start = mouse_cmd_queue_end = 0;
memset(mouse_cmd_queue, 0x00, sizeof(mouse_cmd_queue));
break;
case 0:
default:
key_ctrl_queue_start = key_ctrl_queue_end = 0;
memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue));
}
}
static void
kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel)
{
switch (channel) {
case 4:
kbd_log("ATkbc: key_cmd_queue[%02X] = %02X;\n", key_cmd_queue_end, val);
key_cmd_queue[key_cmd_queue_end] = val;
key_cmd_queue_end = (key_cmd_queue_end + 1) & 0xf;
break;
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;
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;
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;
}
}
static void
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;
if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF))
stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00);
else
stat_hi |= 0x10;
kbd_log("ATkbc: Adding %02X to front...\n", val);
dev->wantirq = 0;
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
written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if (channel >= 2) {
dev->status |= STAT_MFULL;
if (dev->mem[0x20] & 0x02)
picint(1 << 12);
picintc(1 << 1);
} else {
if (dev->mem[0x20] & 0x01)
picint(1 << 1);
picintc(1 << 12);
}
} else if (dev->mem[0x20] & 0x01)
picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
dev->out = val;
}
static void
add_data_kbd_cmd_queue(atkbd_t *dev, uint8_t val)
{
if ((dev->reset_delay > 0) || (key_cmd_queue_end >= 16)) {
kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", (dev->reset_delay > 0), (key_cmd_queue_end >= 16));
return;
}
kbd_log("ATkbc: key_cmd_queue[%02X] = %02X;\n", key_cmd_queue_end, val);
kbc_queue_add(dev, val, 4);
kbd_last_scan_code = val;
}
static void
add_data_kbd_queue(atkbd_t *dev, uint8_t val)
{
if (!keyboard_scan || (dev->reset_delay > 0) || (key_queue_end >= 16)) {
kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16));
return;
}
kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val);
kbc_queue_add(dev, val, 1);
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);
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)
{
add_data_kbd_cmd_queue(dev, val);
}
static void kbd_process_cmd(void *priv);
static void kbc_process_cmd(void *priv);
static void
set_enable_kbd(atkbd_t *dev, uint8_t enable)
{
dev->mem[0x20] &= 0xef;
dev->mem[0x20] |= (enable ? 0x00 : 0x10);
}
static void
set_enable_mouse(atkbd_t *dev, uint8_t enable)
{
dev->mem[0x20] &= 0xdf;
dev->mem[0x20] |= (enable ? 0x00 : 0x20);
}
static void
kbd_poll(void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
const uint8_t channels[4] = { 1, 2, 0, 0 };
int mouse_enabled;
timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC));
if (dev->status & STAT_IFULL) {
dev->status &= ~STAT_IFULL;
if ((dev->status & STAT_CD) || dev->want60)
kbc_process_cmd(dev);
else if (!(dev->status & STAT_CD) && !dev->want60) {
dev->status &= ~STAT_IFULL;
set_enable_kbd(dev, 1);
kbc_queue_reset(4);
dev->key_wantcmd = 1;
dev->key_dat = dev->ib;
}
} else {
/* TODO: Move keyboard controller queue processing here (it's just our way to do commands
with multi-byte output) and split out_new into two separate variables, one for
the keyboard and one for the mouse.
We also need a way to make sure that in case of us sending data to the keyboard
or the mouse, we do ignore output from the other channel until we have received
the one byte from the channel we are talking to. */
if ((dev->out_new != -1) && !(dev->status & STAT_OFULL)) {
dev->wantirq = 0;
if (dev->out_new & 0x100) {
kbd_log("ATkbc: %02X coming from channel 2\n", dev->out_new & 0xff);
add_to_kbc_queue_front(dev, dev->out_new & 0xff, 2, 0x00);
} else {
kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff,
channels[(dev->out_new >> 8) & 0x03]);
add_to_kbc_queue_front(dev, dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03], 0x00);
}
dev->out_new = -1;
}
mouse_enabled = !(dev->mem[0x20] & 0x20) && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF);
/* It would be better to separate the operation in two: keyboard/mouse processing fetches data from the FIFO
and passes it to the controller, the controller then passes it on to the guest. */
if (!(dev->status & STAT_OFULL) && (dev->out_new == -1)) {
if (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;
} else if (!(dev->mem[0x20] & 0x10) && (key_cmd_queue_start != key_cmd_queue_end)) {
kbd_log("ATkbc: %02X on channel 1\n", key_cmd_queue[key_cmd_queue_start]);
dev->out_new = key_cmd_queue[key_cmd_queue_start];
key_cmd_queue_start = (key_cmd_queue_start + 1) & 0xf;
} else if (!(dev->mem[0x20] & 0x10) && key_queue_start != key_queue_end) {
kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]);
dev->out_new = key_queue[key_queue_start];
key_queue_start = (key_queue_start + 1) & 0xf;
} else if (mouse_enabled && (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 (mouse_enabled && (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;
mouse_queue_start = (mouse_queue_start + 1) & 0xf;
}
}
}
if (dev->reset_delay) {
dev->reset_delay--;
if (!dev->reset_delay) {
kbd_log("ATkbc: Sending AA on keyboard reset...\n");
add_data_kbd_front(dev, 0xaa);
}
} else if (dev->key_wantcmd) {
if ((key_cmd_queue_start == key_cmd_queue_end) && (dev->out_new == -1) && (dev->reset_delay == 0)) {
kbd_process_cmd(dev);
dev->key_wantcmd = 0;
}
}
if (dev->mouse_reset_delay) {
dev->mouse_reset_delay--;
if (!dev->mouse_reset_delay) {
kbd_log("ATkbc: Sending AA 00 on mouse reset...\n");
keyboard_at_adddata_mouse_cmd(0xaa);
keyboard_at_adddata_mouse_cmd(0x00);
}
} else if (dev->mouse_wantcmd) {
if ((mouse_cmd_queue_start == mouse_cmd_queue_end) && (dev->out_new == -1) && (dev->mouse_reset_delay == 0)) {
mouse_write(dev->mouse_dat, mouse_p);
// if (dev->mouse_dat == 0xff)
// dev->mouse_reset_delay = RESET_DELAY_TIME;
dev->mouse_wantcmd = 0;
}
}
}
static void
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;
uint8_t or = 0;
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);
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
add_data_kbd(uint16_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 fake_shift[4];
uint8_t num_lock = 0, shift_states = 0;
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
if (dev->reset_delay)
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);
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) && (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) {
case FAKE_LSHIFT_ON:
kbd_log("fake left shift on, scan code: ");
if (num_lock) {
if (shift_states) {
kbd_log("N/A (one or both shifts on)\n");
break;
} else {
/* Num lock on and no shifts are pressed, send non-inverted fake shift. */
switch (keyboard_mode & 0x02) {
case 1:
fake_shift[0] = 0xe0;
fake_shift[1] = 0x2a;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
fake_shift[0] = 0xe0;
fake_shift[1] = 0x12;
add_data_vals(dev, fake_shift, 2);
break;
default:
kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
break;
}
}
} else {
if (shift_states & STATE_LSHIFT) {
/* Num lock off and left shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
fake_shift[0] = 0xe0;
fake_shift[1] = 0xaa;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
fake_shift[0] = 0xe0;
fake_shift[1] = 0xf0;
fake_shift[2] = 0x12;
add_data_vals(dev, fake_shift, 3);
break;
default:
kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
break;
}
}
if (shift_states & STATE_RSHIFT) {
/* Num lock off and right shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
fake_shift[0] = 0xe0;
fake_shift[1] = 0xb6;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
fake_shift[0] = 0xe0;
fake_shift[1] = 0xf0;
fake_shift[2] = 0x59;
add_data_vals(dev, fake_shift, 3);
break;
default:
kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
break;
}
}
kbd_log(shift_states ? "" : "N/A (both shifts off)\n");
}
break;
case FAKE_LSHIFT_OFF:
kbd_log("fake left shift on, scan code: ");
if (num_lock) {
if (shift_states) {
kbd_log("N/A (one or both shifts on)\n");
break;
} else {
/* Num lock on and no shifts are pressed, send non-inverted fake shift. */
switch (keyboard_mode & 0x02) {
case 1:
fake_shift[0] = 0xe0;
fake_shift[1] = 0xaa;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
fake_shift[0] = 0xe0;
fake_shift[1] = 0xf0;
fake_shift[2] = 0x12;
add_data_vals(dev, fake_shift, 3);
break;
default:
kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
break;
}
}
} else {
if (shift_states & STATE_LSHIFT) {
/* Num lock off and left shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
fake_shift[0] = 0xe0;
fake_shift[1] = 0x2a;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
fake_shift[0] = 0xe0;
fake_shift[1] = 0x12;
add_data_vals(dev, fake_shift, 2);
break;
default:
kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
break;
}
}
if (shift_states & STATE_RSHIFT) {
/* Num lock off and right shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
fake_shift[0] = 0xe0;
fake_shift[1] = 0x36;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
fake_shift[0] = 0xe0;
fake_shift[1] = 0x59;
add_data_vals(dev, fake_shift, 2);
break;
default:
kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
break;
}
}
kbd_log(shift_states ? "" : "N/A (both shifts off)\n");
}
break;
default:
#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
add_data_kbd_queue(dev, translate ? (nont_to_t[val] | sc_or) : val);
break;
}
if (sc_or == 0x80)
sc_or = 0;
}
static void
write_output(atkbd_t *dev, uint8_t val)
{
uint8_t old = dev->output_port;
kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port);
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
if ((kbc_ven != KBC_VEN_OLIVETTI) && ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)))
val |= ((dev->mem[0x20] << 4) & 0x10);
/*IRQ 12*/
if ((old ^ val) & 0x20) {
if (val & 0x20)
picint(1 << 12);
else
picintc(1 << 12);
}
/*IRQ 1*/
if ((old ^ val) & 0x10) {
if (val & 0x10)
picint(1 << 1);
else
picintc(1 << 1);
}
if ((old ^ val) & 0x02) { /*A20 enable change*/
mem_a20_key = val & 0x02;
mem_a20_recalc();
flushmmucache();
}
/* 0 holds the CPU in the RESET state, 1 releases it. To simplify this,
we just do everything on release. */
if ((old ^ val) & 0x01) { /*Reset*/
if (!(val & 0x01)) { /* Pin 0 selected. */
/* Pin 0 selected. */
kbd_log("write_output(): Pulse reset!\n");
if (machines[machine].flags & MACHINE_COREBOOT) {
/* The SeaBIOS hard reset code attempts a KBC reset if ACPI RESET_REG
is not available. However, the KBC reset is normally a soft reset, so
SeaBIOS gets caught in a soft reset loop as it tries to hard reset the
machine. Hack around this by making the KBC reset a hard reset only on
coreboot machines. */
pc_reset_hard();
} else {
softresetx86(); /*Pulse reset!*/
cpu_set_edx();
flushmmucache();
if (kbc_ven == KBC_VEN_ALI)
smbase = 0x00030000;
}
}
}
/* Do this here to avoid an infinite reset loop. */
dev->output_port = val;
}
static void
write_cmd(atkbd_t *dev, uint8_t val)
{
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]);
if ((val & 1) && (dev->status & STAT_OFULL))
dev->wantirq = 1;
if (!(val & 1) && dev->wantirq)
dev->wantirq = 0;
/* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */
if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) {
val &= ~CCB_TRANSLATE;
dev->mem[0x20] &= ~CCB_TRANSLATE;
}
/* Scan code translate ON/OFF. */
keyboard_mode &= 0x93;
keyboard_mode |= (val & MODE_MASK);
kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled");
/* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT);
PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch.
The AMIKEY firmware apparently uses this bit for something else. */
if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) {
keyboard_mode &= ~CCB_PCMODE;
kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled");
}
if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) {
/* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */
write_output(dev, dev->output_port);
}
kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val);
dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG);
}
static void
pulse_output(atkbd_t *dev, uint8_t mask)
{
if (mask != 0x0f) {
dev->old_output_port = dev->output_port & ~(0xf0 | mask);
kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask));
write_output(dev, dev->output_port & (0xf0 | mask));
timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC);
}
}
static void
pulse_poll(void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port);
write_output(dev, dev->output_port | dev->old_output_port);
}
static uint8_t
write64_generic(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
uint8_t current_drive, fixed_bits;
uint8_t kbc_ven = 0x0;
kbc_ven = dev->flags & KBC_VEN_MASK;
switch (val) {
case 0xa4: /* check if password installed */
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: check if password installed\n");
add_to_kbc_queue_front(dev, 0xf1, 0, 0x00);
return 0;
}
break;
case 0xa7: /* disable mouse port */
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: disable mouse port\n");
set_enable_mouse(dev, 0);
return 0;
}
break;
case 0xa8: /*Enable mouse port*/
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: enable mouse port\n");
set_enable_mouse(dev, 1);
return 0;
}
break;
case 0xa9: /*Test mouse port*/
kbd_log("ATkbc: test mouse port\n");
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
add_to_kbc_queue_front(dev, 0x00, 0, 0x00); /* no error, this is testing the channel 2 interface */
return 0;
}
break;
case 0xaf: /* read keyboard version */
kbd_log("ATkbc: read keyboard version\n");
add_to_kbc_queue_front(dev, 0x42, 0, 0x00);
return 0;
case 0xc0: /* read input port */
kbd_log("ATkbc: read input port\n");
fixed_bits = 4;
/* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */
if (kbc_ven == KBC_VEN_INTEL_AMI)
fixed_bits |= 0x40;
if (kbc_ven == KBC_VEN_IBM_PS1) {
current_drive = fdc_get_current_drive();
add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00),
0, 0x00);
dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00);
} else if (kbc_ven == KBC_VEN_NCR) {
/* switch settings
* bit 7: keyboard disable
* bit 6: display type (0 color, 1 mono)
* bit 5: power-on default speed (0 high, 1 low)
* bit 4: sense RAM size (0 unsupported, 1 512k on system board)
* bit 3: coprocessor detect
* bit 2: unused
* bit 1: high/auto speed
* bit 0: dma mode
*/
add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf,
0, 0x00);
dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc);
} else {
if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI))
#if 0
add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) &
(((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00);
#else
add_to_kbc_queue_front(dev, ((dev->input_port | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00);
#endif
else
add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00);
dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc);
}
return 0;
case 0xd3: /* write mouse output buffer */
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: write mouse output buffer\n");
dev->want60 = 1;
return 0;
}
break;
case 0xd4: /* write to mouse */
kbd_log("ATkbc: write to mouse\n");
set_enable_mouse(dev, 1);
kbc_queue_reset(3);
dev->want60 = 1;
return 0;
case 0xf0 ... 0xff:
kbd_log("ATkbc: pulse %01X\n", val & 0x0f);
pulse_output(dev, val & 0x0f);
return 0;
}
kbd_log("ATkbc: bad command %02X\n", val);
return 1;
}
static uint8_t
write60_ami(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (dev->command) {
/* 0x40 - 0x5F are aliases for 0x60-0x7F */
case 0x40 ... 0x5f:
kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command);
dev->mem[(dev->command & 0x1f) + 0x20] = val;
if (dev->command == 0x60)
write_cmd(dev, val);
return 0;
case 0xa5: /* get extended controller RAM */
kbd_log("ATkbc: AMI - get extended controller RAM\n");
add_to_kbc_queue_front(dev, dev->mem[val], 0, 0x00);
return 0;
case 0xaf: /* set extended controller RAM */
kbd_log("ATkbc: AMI - set extended controller RAM\n");
if (dev->secr_phase == 1) {
dev->mem_addr = val;
dev->want60 = 1;
dev->secr_phase = 2;
} else if (dev->secr_phase == 2) {
dev->mem[dev->mem_addr] = val;
dev->secr_phase = 0;
}
return 0;
case 0xc1:
kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val);
dev->input_port = val;
return 0;
case 0xcb: /* set keyboard mode */
kbd_log("ATkbc: AMI - set keyboard mode\n");
dev->ami_flags = val;
return 0;
}
return 1;
}
static uint8_t
write64_ami(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
switch (val) {
case 0x00 ... 0x1f:
kbd_log("ATkbc: AMI - alias read from %08X\n", val);
add_to_kbc_queue_front(dev, dev->mem[val + 0x20], 0, 0x00);
return 0;
case 0x40 ... 0x5f:
kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command);
dev->want60 = 1;
return 0;
case 0xa0: /* copyright message */
kbc_queue_add(dev, 0x28, 0);
kbc_queue_add(dev, 0x00, 0);
break;
case 0xa1: /* get controller version */
kbd_log("ATkbc: AMI - get controller version\n");
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if (kbc_ven == KBC_VEN_ALI)
add_to_kbc_queue_front(dev, 'F', 0, 0x00);
else if ((dev->flags & KBC_VEN_MASK) == KBC_VEN_INTEL_AMI)
add_to_kbc_queue_front(dev, '5', 0, 0x00);
else if (is_pentium)
add_to_kbc_queue_front(dev, 'R', 0, 0x00);
else
add_to_kbc_queue_front(dev, 'H', 0, 0x00);
} else if (is386 && !is486)
add_to_kbc_queue_front(dev, 'B', 0, 0x00);
else if (!is386)
add_to_kbc_queue_front(dev, '8', 0, 0x00);
else
add_to_kbc_queue_front(dev, 'F', 0, 0x00);
return 0;
case 0xa2: /* clear keyboard controller lines P22/P23 */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n");
write_output(dev, dev->output_port & 0xf3);
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
}
break;
case 0xa3: /* set keyboard controller lines P22/P23 */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n");
write_output(dev, dev->output_port | 0x0c);
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
}
break;
case 0xa4: /* write clock = low */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - write clock = low\n");
dev->ami_stat &= 0xfe;
return 0;
}
break;
case 0xa5: /* write clock = high */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - write clock = high\n");
dev->ami_stat |= 0x01;
} else {
kbd_log("ATkbc: get extended controller RAM\n");
dev->want60 = 1;
}
return 0;
case 0xa6: /* read clock */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - read clock\n");
add_to_kbc_queue_front(dev, (dev->ami_stat & 1) ? 0xff : 0x00, 0, 0x00);
return 0;
}
break;
case 0xa7: /* write cache bad */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - write cache bad\n");
dev->ami_stat &= 0xfd;
return 0;
}
break;
case 0xa8: /* write cache good */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - write cache good\n");
dev->ami_stat |= 0x02;
return 0;
}
break;
case 0xa9: /* read cache */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: AMI - read cache\n");
add_to_kbc_queue_front(dev, (dev->ami_stat & 2) ? 0xff : 0x00, 0, 0x00);
return 0;
}
break;
case 0xaf: /* set extended controller RAM */
if (kbc_ven == KBC_VEN_ALI) {
kbd_log("ATkbc: Award/ALi/VIA keyboard controller revision\n");
add_to_kbc_queue_front(dev, 0x43, 0, 0x00);
} else {
kbd_log("ATkbc: set extended controller RAM\n");
dev->want60 = 1;
dev->secr_phase = 1;
}
return 0;
case 0xb0 ... 0xb3:
/* set KBC lines P10-P13 (input port bits 0-3) low */
kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n");
if (!(dev->flags & DEVICE_PCI) || (val > 0xb1))
dev->input_port &= ~(1 << (val & 0x03));
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xb4: case 0xb5:
/* set KBC lines P22-P23 (output port bits 2-3) low */
kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n");
if (!(dev->flags & DEVICE_PCI))
write_output(dev, dev->output_port & ~(4 << (val & 0x01)));
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xb8 ... 0xbb:
/* set KBC lines P10-P13 (input port bits 0-3) high */
kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n");
if (!(dev->flags & DEVICE_PCI) || (val > 0xb9)) {
dev->input_port |= (1 << (val & 0x03));
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
}
return 0;
case 0xbc: case 0xbd:
/* set KBC lines P22-P23 (output port bits 2-3) high */
kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n");
if (!(dev->flags & DEVICE_PCI))
write_output(dev, dev->output_port | (4 << (val & 0x01)));
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xc1: /* write input port */
kbd_log("ATkbc: AMI MegaKey - write input port\n");
dev->want60 = 1;
return 0;
case 0xc4:
/* set KBC line P14 low */
kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n");
dev->input_port &= 0xef;
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xc5:
/* set KBC line P15 low */
kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n");
dev->input_port &= 0xdf;
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xc8:
/*
* unblock KBC lines P22/P23
* (allow command D1 to change bits 2/3 of the output port)
*/
kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n");
dev->ami_flags &= 0xfb;
return 0;
case 0xc9:
/*
* block KBC lines P22/P23
* (disallow command D1 from changing bits 2/3 of the port)
*/
kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n");
dev->ami_flags |= 0x04;
return 0;
case 0xcc:
/* set KBC line P14 high */
kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n");
dev->input_port |= 0x10;
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xcd:
/* set KBC line P15 high */
kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n");
dev->input_port |= 0x20;
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xef: /* ??? - sent by AMI486 */
kbd_log("ATkbc: ??? - sent by AMI486\n");
return 0;
}
return write64_generic(dev, val);
}
static uint8_t
write64_ibm_mca(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (val) {
case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/
kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n");
dev->status &= 0x0f;
dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4);
return 0;
case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/
kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n");
dev->status &= 0x0f;
dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0);
return 0;
case 0xaf:
kbd_log("ATkbc: bad KBC command AF\n");
return 1;
case 0xf0 ... 0xff:
kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c);
pulse_output(dev, (val & 0x03) | 0x0c);
return 0;
}
return write64_generic(dev, val);
}
static uint8_t
write60_quadtel(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (dev->command) {
case 0xcf: /*??? - sent by MegaPC BIOS*/
kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n");
return 0;
}
return 1;
}
static uint8_t
write64_olivetti(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (val) {
case 0x80: /* Olivetti-specific command */
/*
* bit 7: bus expansion board present (M300) / keyboard unlocked (M290)
* bits 4-6: ???
* bit 3: fast ram check (if inactive keyboard works erratically)
* bit 2: keyboard fuse present
* bits 0-1: ???
*/
add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00);
dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc);
return 0;
}
return write64_generic(dev, val);
}
static uint8_t
write64_quadtel(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (val) {
case 0xaf:
kbd_log("ATkbc: bad KBC command AF\n");
return 1;
case 0xcf: /*??? - sent by MegaPC BIOS*/
kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n");
dev->want60 = 1;
return 0;
}
return write64_generic(dev, val);
}
static uint8_t
write60_toshiba(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (dev->command) {
case 0xb6: /* T3100e - set color/mono switch */
kbd_log("ATkbc: T3100e - set color/mono switch\n");
t3100e_mono_set(val);
return 0;
}
return 1;
}
static uint8_t
write64_toshiba(void *priv, uint8_t val)
{
atkbd_t *dev = (atkbd_t *) priv;
switch (val) {
case 0xaf:
kbd_log("ATkbc: bad KBC command AF\n");
return 1;
case 0xb0: /* T3100e: Turbo on */
kbd_log("ATkbc: T3100e: Turbo on\n");
t3100e_turbo_set(1);
return 0;
case 0xb1: /* T3100e: Turbo off */
kbd_log("ATkbc: T3100e: Turbo off\n");
t3100e_turbo_set(0);
return 0;
case 0xb2: /* T3100e: Select external display */
kbd_log("ATkbc: T3100e: Select external display\n");
t3100e_display_set(0x00);
return 0;
case 0xb3: /* T3100e: Select internal display */
kbd_log("ATkbc: T3100e: Select internal display\n");
t3100e_display_set(0x01);
return 0;
case 0xb4: /* T3100e: Get configuration / status */
kbd_log("ATkbc: T3100e: Get configuration / status\n");
add_to_kbc_queue_front(dev, t3100e_config_get(), 0, 0x00);
return 0;
case 0xb5: /* T3100e: Get colour / mono byte */
kbd_log("ATkbc: T3100e: Get colour / mono byte\n");
add_to_kbc_queue_front(dev, t3100e_mono_get(), 0, 0x00);
return 0;
case 0xb6: /* T3100e: Set colour / mono byte */
kbd_log("ATkbc: T3100e: Set colour / mono byte\n");
dev->want60 = 1;
return 0;
case 0xb7: /* T3100e: Emulate PS/2 keyboard */
case 0xb8: /* T3100e: Emulate AT keyboard */
dev->flags &= ~KBC_TYPE_MASK;
if (val == 0xb7) {
kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n");
dev->flags |= KBC_TYPE_PS2_NOREF;
} else {
kbd_log("ATkbc: T3100e: Emulate AT keyboard\n");
dev->flags |= KBC_TYPE_ISA;
}
return 0;
case 0xbb: /* T3100e: Read 'Fn' key.
Return it for right Ctrl and right Alt; on the real
T3100e, these keystrokes could only be generated
using 'Fn'. */
kbd_log("ATkbc: T3100e: Read 'Fn' key\n");
if (keyboard_recv(0xb8) || /* Right Alt */
keyboard_recv(0x9d)) /* Right Ctrl */
add_to_kbc_queue_front(dev, 0x04, 0, 0x00);
else
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
return 0;
case 0xbc: /* T3100e: Reset Fn+Key notification */
kbd_log("ATkbc: T3100e: Reset Fn+Key notification\n");
t3100e_notify_set(0x00);
return 0;
case 0xc0: /*Read input port*/
kbd_log("ATkbc: read input port\n");
/* The T3100e returns all bits set except bit 6 which
* is set by t3100e_mono_set() */
dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf;
add_to_kbc_queue_front(dev, dev->input_port, 0, 0x00);
return 0;
}
return write64_generic(dev, val);
}
static void
kbd_process_cmd(void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
/* 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->key_dat == 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->key_dat);
break;
case 0xf0: /* get/set scancode set */
add_data_kbd_front(dev, 0xfa);
if (dev->key_dat == 0) {
kbd_log("Get scan code set: %02X\n", keyboard_mode & 3);
add_data_kbd_front(dev, keyboard_mode & 3);
} else {
if ((dev->key_dat <= 3) && (dev->key_dat != 1)) {
keyboard_mode &= 0xfc;
keyboard_mode |= (dev->key_dat & 3);
kbd_log("Scan code set now: %02X\n", dev->key_dat);
}
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->key_dat, dev->key_command);
add_data_kbd_front(dev, 0xfe);
break;
}
/* Keyboard command is now done. */
dev->key_command = 0x00;
/* Do not process command if the existing command is outputting bytes. */
} else {
/* No keyboard command in progress. */
dev->key_command = 0x00;
switch (dev->key_dat) {
case 0x00 ... 0x7f:
kbd_log("ATkbd: invalid command %02X\n", dev->key_dat);
add_data_kbd_front(dev, 0xfe);
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, 0xfa);
add_data_kbd_front(dev, 0xab);
add_data_kbd_front(dev, 0x83);
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->key_dat == 0xf6) ? "" : " and disable keyboard");
keyboard_scan = (dev->key_dat == 0xf6);
kbd_log("dev->key_dat = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n",
dev->key_dat, 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);
keyboard_scan = 1;
dev->reset_delay = RESET_DELAY_TIME;
break;
default:
kbd_log("ATkbd: bad keyboard command %02X\n", dev->key_dat);
add_data_kbd_front(dev, 0xfe);
}
/* If command needs data, remember command. */
if (dev->key_wantdata == 1)
dev->key_command = dev->key_dat;
}
}
static void
kbc_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 };
if (dev->status & STAT_CD) {
/* Controller command. */
dev->want60 = 0;
switch (dev->ib) {
/* Read data from KBC memory. */
case 0x20 ... 0x3f:
add_to_kbc_queue_front(dev, dev->mem[dev->ib], 0, 0x00);
break;
/* Write data to KBC memory. */
case 0x60 ... 0x7f:
dev->want60 = 1;
break;
case 0xaa: /* self-test */
kbd_log("ATkbc: self-test\n");
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
clocks high, which stops keyboard scanning. */
kbd_log("ATkbc: self-test reinitialization\n");
dev->out_new = -1;
for (i = 0; i < 3; i++)
kbc_queue_reset(i);
kbd_last_scan_code = 0x00;
dev->status &= ~STAT_OFULL;
dev->key_wantcmd = 0;
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)
write_cmd(dev, 0x30 | STAT_SYSFLAG);
else
write_cmd(dev, 0x10 | STAT_SYSFLAG);
add_to_kbc_queue_front(dev, 0x55, 0, 0x00);
break;
case 0xab: /* interface test */
kbd_log("ATkbc: interface test\n");
add_to_kbc_queue_front(dev, 0x00, 0, 0x00); /*no error*/
break;
case 0xac: /* diagnostic dump */
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: diagnostic dump\n");
dev->mem[0x30] = (dev->input_port & 0xf0) | 0x80;
dev->mem[0x31] = dev->output_port;
dev->mem[0x32] = 0x00; /* T0 and T1. */
dev->mem[0x33] = 0x00; /* PSW - Program Status Word - always return 0x00 because we do not emulate this byte. */
/* 20 bytes in high nibble in set 1, low nibble in set 1, set 1 space format = 60 bytes. */
for (i = 0; i < 20; i++) {
kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] >> 4], 0);
kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] & 0x0f], 0);
kbc_queue_add(dev, 0x39, 0);
}
}
break;
case 0xad: /* disable keyboard */
kbd_log("ATkbc: disable keyboard\n");
set_enable_kbd(dev, 0);
break;
case 0xae: /* enable keyboard */
kbd_log("ATkbc: enable keyboard\n");
set_enable_kbd(dev, 1);
break;
case 0xc7: /* set port1 bits */
kbd_log("ATkbc: Phoenix - set port1 bits\n");
dev->want60 = 1;
break;
case 0xca: /* read keyboard mode */
kbd_log("ATkbc: AMI - read keyboard mode\n");
add_to_kbc_queue_front(dev, dev->ami_flags, 0, 0x00);
break;
case 0xcb: /* set keyboard mode */
kbd_log("ATkbc: AMI - set keyboard mode\n");
dev->want60 = 1;
break;
case 0xd0: /* read output port */
kbd_log("ATkbc: read output port\n");
mask = 0xff;
if ((kbc_ven != KBC_VEN_OLIVETTI) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0x20] & 0x10))
mask &= 0xbf;
add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00);
break;
case 0xd1: /* write output port */
kbd_log("ATkbc: write output port\n");
dev->want60 = 1;
break;
case 0xd2: /* write keyboard output buffer */
kbd_log("ATkbc: write keyboard output buffer\n");
dev->want60 = 1;
break;
case 0xdd: /* disable A20 address line */
case 0xdf: /* enable A20 address line */
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 */
kbd_log("ATkbc: read test inputs\n");
add_to_kbc_queue_front(dev, 0x00, 0, 0x00);
break;
default:
/*
* Unrecognized controller command.
*
* If we have a vendor-specific handler, run
* that. Otherwise, or if that handler fails,
* log a bad command.
*/
if (dev->write64_ven)
bad = dev->write64_ven(dev, dev->ib);
kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib);
}
/* If the command needs data, remember the command. */
if (dev->want60)
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 0xc7: /* set port1 bits */
kbd_log("ATkbc: Phoenix - set port1 bits\n");
dev->input_port |= 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) {
kbc_queue_reset(3);
dev->mouse_wantcmd = 1;
dev->mouse_dat = dev->ib;
} 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);
}
}
}
}
static void
kbd_write(uint16_t port, uint8_t val, void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
kbd_log((port == 0x61) ? "" : "[%04X:%08X] ATkbc: write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
switch (port) {
case 0x60:
dev->status &= ~STAT_CD;
if (dev->want60 && (dev->command == 0xd1)) {
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);
dev->want60 = 0;
return;
}
break;
case 0x64:
dev->status |= STAT_CD;
if (val == 0xd1) {
kbd_log("ATkbc: write output port\n");
dev->want60 = 1;
dev->command = 0xd1;
return;
}
break;
}
dev->ib = val;
dev->status |= STAT_IFULL;
}
static uint8_t
kbd_read(uint16_t port, void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
uint8_t ret = 0xff;
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)
cycles -= ISA_CYCLES(8);
switch (port) {
case 0x60:
ret = dev->out;
dev->status &= ~STAT_OFULL;
/* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a bit the
output port (P2).
This also means that in AT mode, the IRQ is level-triggered. */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)
picintc(1 << 1);
break;
case 0x64:
ret = dev->status;
break;
default:
kbd_log("ATkbc: read(%04x) invalid!\n",port);
break;
}
kbd_log((port == 0x61) ? "" : "[%04X:%08X] ATkbc: read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
return (ret);
}
static void
kbd_reset(void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
int i;
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
dev->first_write = 1;
dev->status = STAT_UNLOCKED;
dev->mem[0x20] = 0x01;
dev->mem[0x20] |= CCB_TRANSLATE;
dev->wantirq = 0;
write_output(dev, 0xcf);
dev->secr_phase = 0;
dev->key_wantdata = 0;
/* Set up the correct Video Type bits. */
if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER))
dev->input_port = video_is_mda() ? 0xb0 : 0xf0;
else
dev->input_port = video_is_mda() ? 0xf0 : 0xb0;
kbd_log("ATkbc: input port = %02x\n", dev->input_port);
keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE);
/* Enable keyboard, disable mouse. */
set_enable_kbd(dev, 1);
keyboard_scan = 1;
set_enable_mouse(dev, 0);
mouse_scan = 0;
dev->out_new = -1;
for (i = 0; i < 3; i++)
kbc_queue_reset(i);
kbd_last_scan_code = 0;
sc_or = 0;
memset(keyboard_set3_flags, 0, 512);
set_scancode_map(dev);
dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00;
dev->ami_stat |= 0x02;
}
/* Reset the AT keyboard - this is needed for the PCI TRC and is done
until a better solution is found. */
void
keyboard_at_reset(void)
{
kbd_reset(SavedKbd);
}
static void
kbd_close(void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
kbd_reset(dev);
/* Stop timers. */
timer_disable(&dev->send_delay_timer);
keyboard_scan = 0;
keyboard_send = NULL;
/* Disable the scancode maps. */
keyboard_set_table(NULL);
SavedKbd = NULL;
free(dev);
}
static void *
kbd_init(const device_t *info)
{
atkbd_t *dev;
dev = (atkbd_t *) malloc(sizeof(atkbd_t));
memset(dev, 0x00, sizeof(atkbd_t));
dev->flags = info->local;
video_reset(gfxcard[0]);
kbd_reset(dev);
io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev);
io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev);
keyboard_send = add_data_kbd;
timer_add(&dev->send_delay_timer, kbd_poll, dev, 1);
timer_add(&dev->pulse_cb, pulse_poll, dev, 0);
dev->write60_ven = NULL;
dev->write64_ven = NULL;
switch (dev->flags & KBC_VEN_MASK) {
case KBC_VEN_ACER:
case KBC_VEN_GENERIC:
case KBC_VEN_NCR:
case KBC_VEN_IBM_PS1:
case KBC_VEN_XI8088:
dev->write64_ven = write64_generic;
break;
case KBC_VEN_OLIVETTI:
dev->write64_ven = write64_olivetti;
break;
case KBC_VEN_AMI:
case KBC_VEN_INTEL_AMI:
case KBC_VEN_SAMSUNG:
case KBC_VEN_ALI:
dev->write60_ven = write60_ami;
dev->write64_ven = write64_ami;
break;
case KBC_VEN_IBM_MCA:
dev->write64_ven = write64_ibm_mca;
break;
case KBC_VEN_QUADTEL:
dev->write60_ven = write60_quadtel;
dev->write64_ven = write64_quadtel;
break;
case KBC_VEN_TOSHIBA:
dev->write60_ven = write60_toshiba;
dev->write64_ven = write64_toshiba;
break;
}
/* We need this, sadly. */
SavedKbd = dev;
return (dev);
}
const device_t keyboard_at_device = {
.name = "PC/AT Keyboard",
.internal_name = "keyboard_at",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_GENERIC,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_at_ami_device = {
.name = "PC/AT Keyboard (AMI)",
.internal_name = "keyboard_at_ami",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_AMI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_at_samsung_device = {
.name = "PC/AT Keyboard (Samsung)",
.internal_name = "keyboard_at_samsung",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_SAMSUNG,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_at_toshiba_device = {
.name = "PC/AT Keyboard (Toshiba)",
.internal_name = "keyboard_at_toshiba",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_TOSHIBA,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_at_olivetti_device = {
.name = "PC/AT Keyboard (Olivetti)",
.internal_name = "keyboard_at_olivetti",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_OLIVETTI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_at_ncr_device = {
.name = "PC/AT Keyboard (NCR)",
.internal_name = "keyboard_at_ncr",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_NCR,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2",
.flags = 0,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_ps1_device = {
.name = "PS/2 Keyboard (IBM PS/1)",
.internal_name = "keyboard_ps2_ps1",
.flags = 0,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_ps1_pci_device = {
.name = "PS/2 Keyboard (IBM PS/1)",
.internal_name = "keyboard_ps2_ps1_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_xi8088_device = {
.name = "PS/2 Keyboard (Xi8088)",
.internal_name = "keyboard_ps2_xi8088",
.flags = 0,
.local = KBC_TYPE_PS2_1 | KBC_VEN_XI8088,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_ami_device = {
.name = "PS/2 Keyboard (AMI)",
.internal_name = "keyboard_ps2_ami",
.flags = 0,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_mca_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_mca",
.flags = 0,
.local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_mca_2_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_mca_2",
.flags = 0,
.local = KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_quadtel_device = {
.name = "PS/2 Keyboard (Quadtel/MegaPC)",
.internal_name = "keyboard_ps2_quadtel",
.flags = 0,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_pci_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_ami_pci_device = {
.name = "PS/2 Keyboard (AMI)",
.internal_name = "keyboard_ps2_ami_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_ali_pci_device = {
.name = "PS/2 Keyboard (ALi M5123/M1543C)",
.internal_name = "keyboard_ps2_ali_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_ALI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_intel_ami_pci_device = {
.name = "PS/2 Keyboard (AMI)",
.internal_name = "keyboard_ps2_intel_ami_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_acer_pci_device = {
.name = "PS/2 Keyboard (Acer 90M002A)",
.internal_name = "keyboard_ps2_acer_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_ACER,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
void
keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv)
{
mouse_write = func;
mouse_p = priv;
}
void
keyboard_at_adddata_keyboard_raw(uint8_t val)
{
atkbd_t *dev = SavedKbd;
add_data_kbd_queue(dev, val);
}
void
keyboard_at_adddata_mouse(uint8_t val)
{
atkbd_t *dev = SavedKbd;
if (!mouse_scan || (dev->mouse_reset_delay > 0) || (mouse_queue_end >= 16)) {
kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !mouse_scan, (dev->mouse_reset_delay > 0), (mouse_queue_end >= 16));
return;
}
kbc_queue_add(dev, val, 2);
}
void
keyboard_at_adddata_mouse_cmd(uint8_t val)
{
atkbd_t *dev = SavedKbd;
if ((dev->mouse_reset_delay > 0) || (mouse_cmd_queue_end >= 16)) {
kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", (dev->mouse_reset_delay > 0), (mouse_cmd_queue_end >= 16));
return;
}
kbc_queue_add(dev, val, 3);
}
void
keyboard_at_mouse_reset(void)
{
kbc_queue_reset(2);
}
uint8_t
keyboard_at_mouse_pos(void)
{
return ((mouse_queue_end - mouse_queue_start) & 0xf);
}
void
keyboard_at_set_mouse_scan(uint8_t val)
{
atkbd_t *dev = SavedKbd;
uint8_t temp_mouse_scan = val ? 1 : 0;
if (temp_mouse_scan == !(dev->mem[0x20] & 0x20))
return;
set_enable_mouse(dev, val ? 1 : 0);
kbd_log("ATkbc: mouse scan %sabled via PCI\n", mouse_scan ? "en" : "dis");
}
uint8_t
keyboard_at_get_mouse_scan(void)
{
atkbd_t *dev = SavedKbd;
return ((dev->mem[0x20] & 0x20) ? 0x00 : 0x10);
}
void
keyboard_at_set_a20_key(int state)
{
atkbd_t *dev = SavedKbd;
write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1));
}