31 {
"PNP0300",
"IBM PC/XT keyboard controller (83-key)"},
32 {
"PNP0301",
"IBM PC/AT keyboard controller (86-key)"},
33 {
"PNP0302",
"IBM PC/XT keyboard controller (84-key)"},
34 {
"PNP0303",
"IBM Enhanced (101/102-key, PS/2 mouse support)"},
35 {
"PNP0304",
"Olivetti Keyboard (83-key)"},
36 {
"PNP0305",
"Olivetti Keyboard (102-key)"},
37 {
"PNP0306",
"Olivetti Keyboard (86-key)"},
38 {
"PNP0307",
"Microsoft Windows(R) Keyboard"},
39 {
"PNP0308",
"General Input Device Emulation Interface (GIDEI) legacy"},
40 {
"PNP0309",
"Olivetti Keyboard (A101/102 key)"},
41 {
"PNP030A",
"AT&T 302 keyboard"},
42 {
"PNP030B",
"Reserved by Microsoft"},
43 {
"PNP0320",
"Japanese 101-key keyboard"},
44 {
"PNP0321",
"Japanese AX keyboard"},
45 {
"PNP0322",
"Japanese 106-key keyboard A01"},
46 {
"PNP0323",
"Japanese 106-key keyboard 002/003"},
47 {
"PNP0324",
"Japanese 106-key keyboard 001"},
48 {
"PNP0325",
"Japanese Toshiba Desktop keyboard"},
49 {
"PNP0326",
"Japanese Toshiba Laptop keyboard"},
50 {
"PNP0327",
"Japanese Toshiba Notebook keyboard"},
51 {
"PNP0340",
"Korean 84-key keyboard"},
52 {
"PNP0341",
"Korean 86-key keyboard"},
53 {
"PNP0342",
"Korean Enhanced keyboard"},
54 {
"PNP0343",
"Korean Enhanced keyboard 101(b/c)"},
55 {
"PNP0344",
"Korean Enhanced keyboard 103"},
59 {
"PNP0F00",
"Microsoft Bus Mouse"},
60 {
"PNP0F01",
"Microsoft Serial Mouse"},
61 {
"PNP0F02",
"Microsoft InPort Mouse"},
62 {
"PNP0F03",
"Microsoft PS/2-style Mouse"},
63 {
"PNP0F04",
"Mouse Systems Mouse"},
64 {
"PNP0F05",
"Mouse Systems 3-Button Mouse (COM2)"},
65 {
"PNP0F06",
"Genius Mouse (COM1)"},
66 {
"PNP0F07",
"Genius Mouse (COM2)"},
67 {
"PNP0F08",
"Logitech Serial Mouse"},
68 {
"PNP0F09",
"Microsoft BallPoint Serial Mouse"},
69 {
"PNP0F0A",
"Microsoft Plug and Play Mouse"},
70 {
"PNP0F0B",
"Microsoft Plug and Play BallPoint Mouse"},
71 {
"PNP0F0C",
"Microsoft-compatible Serial Mouse"},
72 {
"PNP0F0D",
"Microsoft-compatible InPort-compatible Mouse"},
73 {
"PNP0F0E",
"Microsoft-compatible PS/2-style Mouse"},
74 {
"PNP0F0F",
"Microsoft-compatible Serial BallPoint-compatible Mouse"},
75 {
"PNP0F10",
"Texas Instruments QuickPort Mouse"},
76 {
"PNP0F11",
"Microsoft-compatible Bus Mouse"},
77 {
"PNP0F12",
"Logitech PS/2-style Mouse"},
78 {
"PNP0F13",
"PS/2 Port for PS/2-style Mice"},
79 {
"PNP0F14",
"Microsoft Kids Mouse"},
80 {
"PNP0F15",
"Logitech bus mouse"},
81 {
"PNP0F16",
"Logitech SWIFT device"},
82 {
"PNP0F17",
"Logitech-compatible serial mouse"},
83 {
"PNP0F18",
"Logitech-compatible bus mouse"},
84 {
"PNP0F19",
"Logitech-compatible PS/2-style Mouse"},
85 {
"PNP0F1A",
"Logitech-compatible SWIFT Device"},
86 {
"PNP0F1B",
"HP Omnibook Mouse"},
87 {
"PNP0F1C",
"Compaq LTE Trackball PS/2-style Mouse"},
88 {
"PNP0F1D",
"Compaq LTE Trackball Serial Mouse"},
89 {
"PNP0F1E",
"Microsoft Kids Trackball Mouse"},
90 {
"PNP0F1F",
"Reserved by Microsoft Input Device Group"},
91 {
"PNP0F20",
"Reserved by Microsoft Input Device Group"},
92 {
"PNP0F21",
"Reserved by Microsoft Input Device Group"},
93 {
"PNP0F22",
"Reserved by Microsoft Input Device Group"},
94 {
"PNP0F23",
"Reserved by Microsoft Input Device Group"},
95 {
"PNP0FFC",
"Reserved (temporarily) by Microsoft Kernel team"},
96 {
"PNP0FFF",
"Reserved by Microsoft Systems (SDA Standard Compliant SD Host Controller Vendor)"},
114 return "invalid response";
125 return "clock stuck low";
127 return "clock stuck high";
129 return "data stuck low";
131 return "data stuck high";
133 return "invalid response";
146 return "invalid device";
160 LOG_ERR(
"ps2 first device disable failed during controller init\n");
165 LOG_ERR(
"ps2 second device disable failed during controller init\n");
173 LOG_ERR(
"ps2 failed to read initial config\n");
184 LOG_ERR(
"ps2 failed to write initial config\n");
211 LOG_WARN(
"ps2 first device disable failed during deinit\n");
216 LOG_WARN(
"ps2 second device disable failed during deinit\n");
225 LOG_ERR(
"ps2 failed to read config byte.\n");
232 LOG_ERR(
"ps2 failed to send self test command\n");
244 LOG_ERR(
"ps2 failed to write config byte.\n");
256 LOG_ERR(
"ps2 failed to read config for dual channel check\n");
264 LOG_ERR(
"ps2 failed to send second port enable command\n");
271 LOG_ERR(
"ps2 failed to read config after second port enable\n");
278 LOG_INFO(
"dual channel PS/2 controller detected\n");
282 LOG_ERR(
"ps2 failed to disable second port after detection\n");
289 LOG_INFO(
"single channel PS/2 controller detected\n");
295 LOG_INFO(
"single channel PS/2 controller detected (second port clock not disabled)\n");
345 asm volatile(
"pause");
360 asm volatile(
"pause");
461 LOG_INFO(
"found PS/2 keyboard '%s' on IRQ %u\n", info->
name, info->
irq);
555 LOG_ERR(
"ps2 failed to get ACPI device config for '%s'\n", name);
565 LOG_ERR(
"ps2 device '%s' cannot initialize controller (already initialized)\n", name);
573 LOG_ERR(
"ps2 device '%s' has invalid status port resource\n", name);
580 LOG_ERR(
"ps2 controller initialization failed\n");
585 LOG_ERR(
"ps2 controller self test failed\n");
590 LOG_ERR(
"ps2 controller dual channel check failed\n");
595 LOG_ERR(
"ps2 controller devices test failed\n");
602 LOG_ERR(
"ps2 device '%s' has invalid IRQ resource count %d\n", name,
acpiCfg->irqCount);
617 LOG_ERR(
"ps2 device '%s' has unknown type '%s'\n", name, type);
623 LOG_ERR(
"ps2 device '%s' cannot be attached to %s port (port already attached)\n", name,
630 LOG_ERR(
"ps2 device '%s' cannot be attached to %s port (port already in use by %s)\n", name,
664 LOG_WARN(
"ps2 device '%s' has unknown PNP ID '%s'\n", name, type);
672 LOG_INFO(
"delaying ps2 device '%s' initialization (controller not initialized)\n", name);
679 LOG_INFO(
"delaying ps2 device '%s' initialization (waiting for other device)\n", name);
702 LOG_ERR(
"ps2 failed to register IRQ for keyboard device\n");
717 LOG_ERR(
"ps2 failed to register IRQ for mouse device\n");
729 LOG_ERR(
"ps2 failed to write final config byte\n");
737 LOG_ERR(
"ps2 failed to enable first port\n");
746 LOG_ERR(
"ps2 failed to enable second port\n");
static void io_out8(port_t port, uint8_t val)
Write an 8-bit value to an I/O port.
static uint8_t io_in8(port_t port)
Read an 8-bit value from an I/O port.
uint16_t port_t
I/O port type.
#define LOG_ERR(format,...)
#define LOG_WARN(format,...)
#define LOG_INFO(format,...)
#define LOG_DEBUG(format,...)
bool module_device_types_contains(const char *deviceTypes, const char *type)
Check if a list of device types contains a specific device type.
#define MODULE_INFO(_name, _author, _description, _version, _licence, _deviceTypes)
Macro to define module information.
@ MODULE_EVENT_DEVICE_ATTACH
void clock_wait(clock_t nanoseconds)
Wait for a specified number of nanoseconds.
clock_t clock_uptime(void)
Retrieve the time in nanoseconds since boot.
#define LOCK_CREATE()
Create a lock initializer.
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
#define ETIMEDOUT
Connection timed out.
#define errno
Error number variable.
#define ARRAY_SIZE(x)
Get the number of elements in a static array.
#define NULL
Pointer error value.
#define ERR
Integer error value.
uint64_t ps2_kbd_init(ps2_device_info_t *info)
Initialize a PS/2 keyboard device.
void ps2_kbd_deinit(ps2_device_info_t *info)
Deinitialize a PS/2 keyboard device.
uint64_t ps2_kbd_irq_register(ps2_device_info_t *info)
Register the IRQ handler for a PS/2 keyboard device.
void ps2_mouse_deinit(ps2_device_info_t *info)
Deinitialize a PS/2 mouse device.
uint64_t ps2_mouse_irq_register(ps2_device_info_t *info)
Register the IRQ handler for a PS/2 mouse device.
uint64_t ps2_mouse_init(ps2_device_info_t *info)
Initialize a PS/2 mouse device.
acpi_device_cfg_t * acpi_device_cfg_lookup(const char *name)
Retrieves the ACPI device configuration for a device by its name.
uint64_t acpi_device_cfg_get_port(acpi_device_cfg_t *cfg, uint64_t index, port_t *out)
Retrieves an the nth IO port assigned to an ACPI device.
uint64_t ps2_cmd(ps2_cmd_t command)
Send a command to the PS/2 controller without reading response.
ps2_device_t
PS/2 device identifiers.
uint64_t ps2_read(void)
Read from the PS/2 controllers data port.
ps2_status_bits_t
PS/2 controller status register bits.
#define PS2_COMMAND_RETRIES
Number of retries for commands.
ps2_device_test_response_t
PS/2 device test responses.
ps2_cmd_t
PS/2 controller commands.
#define PS2_WAIT_TIMEOUT
Wait timeout for PS/2 controller.
uint64_t ps2_wait_until_set(ps2_status_bits_t status)
Wait until status bit(s) are set.
uint64_t ps2_write(uint8_t data)
Write to the PS/2 controllers data port.
#define PS2_LARGE_DELAY
Large delay for various operations.
uint64_t ps2_device_cmd_and_read(ps2_device_t device, ps2_device_cmd_t command)
Send a command to a PS/2 device and read response.
ps2_self_test_response_t
PS/2 controller self-test responses.
uint64_t ps2_cmd_and_read(ps2_cmd_t command)
Send a command to the PS/2 controller and read response.
void ps2_drain(void)
Drain the PS/2 output buffer.
uint64_t ps2_read_no_wait(void)
Read from the PS/2 controllers data port without waiting.
#define PS2_MOUSE_PNP_IDS
All known PS/2 mouse PNP IDs.
#define PS2_SMALL_DELAY
Small delay for various operations.
uint64_t ps2_wait_until_clear(ps2_status_bits_t status)
Wait until status bit(s) are clear.
ps2_device_cmd_t
PS/2 device commands.
#define PS2_KEYBOARD_PNP_IDS
All known PS/2 keyboard PNP IDs.
uint64_t ps2_device_cmd(ps2_device_t device, ps2_device_cmd_t command)
Send a command to a PS/2 device without reading response.
uint64_t ps2_cmd_and_write(ps2_cmd_t command, uint8_t data)
Send a command to the PS/2 controller and write data.
uint64_t ps2_device_sub_cmd(ps2_device_t device, ps2_device_cmd_t command, uint8_t subCommand)
Send a command and a subcommand to a PS/2 device.
@ PS2_STATUS_IN_FULL
Input buffer status (0 = empty, 1 = full)
@ PS2_STATUS_OUT_FULL
Output buffer status (0 = empty, 1 = full)
@ PS2_DEV_TEST_DATA_STUCK_LOW
@ PS2_DEV_TEST_DATA_STUCK_HIGH
@ PS2_DEV_TEST_CLOCK_STUCK_HIGH
@ PS2_DEV_TEST_CLOCK_STUCK_LOW
@ PS2_CFG_SECOND_IRQ
Second PS/2 port interrupt enable.
@ PS2_CFG_FIRST_IRQ
First PS/2 port interrupt enable.
@ PS2_CFG_SECOND_CLOCK_DISABLE
Second PS/2 port clock disable.
@ PS2_CFG_FIRST_CLOCK_DISABLE
First PS/2 port clock disable.
@ PS2_CFG_FIRST_TRANSLATION
First PS/2 port translation enable.
@ PS2_DEV_CMD_DISABLE_SCANNING
@ PS2_DEV_CMD_ENABLE_SCANNING
@ PS2_DEV_RESPONSE_RESEND
@ PS2_DEV_RESPONSE_BAT_OK
static void ps2_controller_deinit(void)
static bool isDualChannel
static ps2_known_device_t knownKeyboards[]
static bool controllerInitialized
static uint64_t ps2_device_init(ps2_device_t device)
static ps2_known_device_t knownMice[]
uint64_t _module_procedure(const module_event_t *event)
static port_t commandPort
static uint64_t ps2_controller_init(void)
static uint64_t currentConfig
static uint64_t ps2_self_test(void)
static const char * ps2_self_test_response_to_string(ps2_self_test_response_t response)
static uint64_t ps2_check_if_dual_channel(void)
static uint64_t ps2_devices_test(void)
static const char * ps2_device_test_response_to_string(ps2_device_test_response_t response)
static uint64_t ps2_attach_device(const char *type, const char *name)
static const char * ps2_device_to_string(ps2_device_t device)
static ps2_device_info_t devices[PS2_DEV_COUNT]
_PUBLIC int strcmp(const char *s1, const char *s2)
ACPI device configuration structure.
A simple ticket lock implementation.
struct module_event_t::@4::@6 deviceAttach
PS/2 device information structure.
bool attached
The device has been attached from ACPI.
irq_virt_t irq
IRQ assigned to the device by ACPI.
ps2_device_t device
Device port.
bool initialized
The device has been initialized.
const char * name
Human-readable name of the device.
const char * pnpId
PNP ID of the device.
Known PS/2 device structure.