feature (PS/2): finished up initialization process

This commit is contained in:
antifallobst 2023-05-03 22:01:08 +02:00
parent c5cbf51e75
commit fb66944b0e
5 changed files with 87 additions and 15 deletions

View File

@ -9,13 +9,15 @@
#define PS2_CONTROLLER_STATUS_PORT 0x64
#define PS2_CONTROLLER_COMMAND_PORT 0x64
#define PS2_CONTROLLER_TIMEOUT 0xFFFFFF
#define PS2_CONTROLLER_TIMEOUT 0xFFFFF
void ps2_controller_init ();
uint8_t ps2_controller_command (uint8_t command);
uint8_t ps2_controller_command_with_data (uint8_t command, uint8_t data);
bool ps2_controller_command_has_response (uint8_t command);
bool ps2_controller_wait_until_ready_for_input ();
bool ps2_controller_wait_until_ready_for_output ();
uint8_t ps2_controller_read_data ();
void ps2_controller_write_data (uint8_t data);
#endif //NOX_CONTROLLER_H

View File

@ -31,7 +31,7 @@ typedef enum {
PS2_KEYBOARD_RESPONSE_KEY_DETECTION_ERROR_2 = 0xFF
} ps2_keyboard_response_E;
uint8_t ps2_keyboard_command (ps2_keyboard_command_E command, uint8_t data);
uint8_t ps2_keyboard_command (ps2_keyboard_command_E command);
void ps2_keyboard_init ();
void ps2_keyboard_read ();
string_t ps2_keyboard_command_to_string (ps2_keyboard_command_E command);

View File

@ -44,15 +44,15 @@ void kernel_init(boot_info_T* boot_info) {
sysconfig_default_init();
scheduler_init(boot_info);
acpi_init(boot_info);
pci_init();
ps2_controller_init();
scheduler_init(boot_info);
tty_init();
ps2_controller_init();
}
void kmain(boot_info_T boot_info) {

View File

@ -8,6 +8,7 @@
#include "boot/config.h"
void ps2_controller_init() {
// check if the ps/2 controller exists
if (g_sysconfig->ps2_acpi_validation) {
if (!(g_acpi_table_fadt->ia_boot_architecture_flags & (1 << 1))) {
log(LOG_ERROR, "<PS2> ps2 controller initialization failed (ps2 controller not set in fadt boot flags)");
@ -17,12 +18,48 @@ void ps2_controller_init() {
log(LOG_WARNING, "<PS2> skipping ps2 controller existence acpi check (disabled by sysconfig)");
}
// disable ps/2 devices
ps2_controller_command(0xAD); // keyboard
ps2_controller_command(0xA7); // mouse
// clear buffer
while (io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000001) {
io_in_byte(PS2_CONTROLLER_DATA_PORT);
}
// set the configuration byte
uint8_t config_byte = ps2_controller_command(0x20);
bool dual_channel = (config_byte & 0b00100000);
config_byte &= 0b10111100;
ps2_controller_command_with_data(0x60, config_byte);
// performing self test
if (ps2_controller_command(0xAA) != 0x55) {
log(LOG_ERROR, "<PS2> controller driver init failed (controller self test failed)");
return;
}
// restore the config byte, due to a possible reset by the self test
ps2_controller_command_with_data(0x60, config_byte);
// check if the controller supports 2 channels
if (dual_channel) {
ps2_controller_command(0xA8);
dual_channel = !(ps2_controller_command(0x20) & 0b00100000);
ps2_controller_command(0xA7);
}
// perform interface tests
if (ps2_controller_command(0xAB) > 0 && (!dual_channel || ps2_controller_command(0xA9) > 0)) {
log(LOG_ERROR, "<PS2> controller driver init failed (interface tests failed)");
}
// init devices
ps2_keyboard_init();
}
uint8_t ps2_controller_command(uint8_t command) {
io_out_byte(PS2_CONTROLLER_COMMAND_PORT, command);
if (!ps2_controller_wait_until_ready_for_output()) {
if (ps2_controller_command_has_response(command) && !ps2_controller_wait_until_ready_for_output()) {
return 0;
}
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
@ -34,12 +71,21 @@ uint8_t ps2_controller_command_with_data(uint8_t command, uint8_t data) {
return 0;
}
io_out_byte(PS2_CONTROLLER_DATA_PORT, data);
if (!ps2_controller_wait_until_ready_for_output()) {
if (ps2_controller_command_has_response(command) && !ps2_controller_wait_until_ready_for_output()) {
return 0;
}
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
}
bool ps2_controller_command_has_response(uint8_t command) {
if (command >= 0x20 && command <= 0x3F) return true;
if (command >= 0xA9 && command <= 0xAC) return true;
if (command == 0xC0) return true;
if (command == 0xD0) return true;
return false;
}
bool ps2_controller_wait_until_ready_for_input() {
uint32_t timeout = 0;
while (io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000010) {
@ -54,7 +100,6 @@ bool ps2_controller_wait_until_ready_for_input() {
bool ps2_controller_wait_until_ready_for_output() {
uint32_t timeout = 0;
log(LOG_DEBUG, "status register: 0b%.8b", io_in_byte(PS2_CONTROLLER_STATUS_PORT));
while (!(io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000001)) {
if (timeout > PS2_CONTROLLER_TIMEOUT) {
log(LOG_WARNING, "<PS2 Controller> Controller not ready for output (timeout)");
@ -68,3 +113,7 @@ bool ps2_controller_wait_until_ready_for_output() {
uint8_t ps2_controller_read_data() {
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
}
void ps2_controller_write_data(uint8_t data) {
io_out_byte(PS2_CONTROLLER_DATA_PORT, data);
}

View File

@ -12,13 +12,24 @@ char scancode_set_1[] = " 1234567890-= qwertyuiop[] asdfghjkl;'` \\zxcvbnm,./
bool shift_enabled = false;
bool extended_key = false;
uint8_t ps2_keyboard_command(ps2_keyboard_command_E command, uint8_t data) {
uint8_t ps2_keyboard_command(ps2_keyboard_command_E command) {
uint8_t response = PS2_KEYBOARD_RESPONSE_RESEND;
uint8_t tries = 0;
while (response == PS2_KEYBOARD_RESPONSE_RESEND) {
response = ps2_controller_command(command);
log(LOG_DEBUG, "<PS2> '%s' + 0x%xb -> 0x%xb", ps2_keyboard_command_to_string(command), data, response);
if (!ps2_controller_wait_until_ready_for_input()) {
return 0;
}
ps2_controller_write_data(command);
if (!ps2_controller_wait_until_ready_for_output()) {
return 0;
}
while (io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000001) {
response = ps2_controller_read_data();
}
log(LOG_DEBUG, "<PS2> '%s' -> 0x%xb", ps2_keyboard_command_to_string(command), response);
tries++;
if (tries >= 3) {
@ -32,10 +43,20 @@ uint8_t ps2_keyboard_command(ps2_keyboard_command_E command, uint8_t data) {
void ps2_keyboard_init() {
// uint8_t data = ps2_keyboard_command(PS2_KEYBOARD_COMMAND_ECHO, 0);
// log(LOG_DEBUG, "response: 0x%xb", data);
// re-enable the ps/2 keyboard
ps2_controller_command(0xAE);
io_in_byte(PS2_CONTROLLER_DATA_PORT);
// reset the keyboard
ps2_keyboard_command(PS2_KEYBOARD_COMMAND_SELF_TEST);
// set scancode set to 1
ps2_keyboard_command(PS2_KEYBOARD_COMMAND_SET_SCANCODE_SET);
ps2_keyboard_command(1);
// enable keyboard interrupt on ps/2 controller
uint8_t config_byte = ps2_controller_command(0x20);
config_byte |= 0b00000001;
ps2_controller_command_with_data(0x60, config_byte);
pic_unmask_irq(IRQ_KEYBOARD);
}