feature (PS/2): finished up initialization process
This commit is contained in:
parent
c5cbf51e75
commit
fb66944b0e
|
@ -9,13 +9,15 @@
|
||||||
#define PS2_CONTROLLER_STATUS_PORT 0x64
|
#define PS2_CONTROLLER_STATUS_PORT 0x64
|
||||||
#define PS2_CONTROLLER_COMMAND_PORT 0x64
|
#define PS2_CONTROLLER_COMMAND_PORT 0x64
|
||||||
|
|
||||||
#define PS2_CONTROLLER_TIMEOUT 0xFFFFFF
|
#define PS2_CONTROLLER_TIMEOUT 0xFFFFF
|
||||||
|
|
||||||
void ps2_controller_init ();
|
void ps2_controller_init ();
|
||||||
uint8_t ps2_controller_command (uint8_t command);
|
uint8_t ps2_controller_command (uint8_t command);
|
||||||
uint8_t ps2_controller_command_with_data (uint8_t command, uint8_t data);
|
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_input ();
|
||||||
bool ps2_controller_wait_until_ready_for_output ();
|
bool ps2_controller_wait_until_ready_for_output ();
|
||||||
uint8_t ps2_controller_read_data ();
|
uint8_t ps2_controller_read_data ();
|
||||||
|
void ps2_controller_write_data (uint8_t data);
|
||||||
|
|
||||||
#endif //NOX_CONTROLLER_H
|
#endif //NOX_CONTROLLER_H
|
||||||
|
|
|
@ -31,7 +31,7 @@ typedef enum {
|
||||||
PS2_KEYBOARD_RESPONSE_KEY_DETECTION_ERROR_2 = 0xFF
|
PS2_KEYBOARD_RESPONSE_KEY_DETECTION_ERROR_2 = 0xFF
|
||||||
} ps2_keyboard_response_E;
|
} 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_init ();
|
||||||
void ps2_keyboard_read ();
|
void ps2_keyboard_read ();
|
||||||
string_t ps2_keyboard_command_to_string (ps2_keyboard_command_E command);
|
string_t ps2_keyboard_command_to_string (ps2_keyboard_command_E command);
|
||||||
|
|
|
@ -44,15 +44,15 @@ void kernel_init(boot_info_T* boot_info) {
|
||||||
|
|
||||||
sysconfig_default_init();
|
sysconfig_default_init();
|
||||||
|
|
||||||
|
scheduler_init(boot_info);
|
||||||
|
|
||||||
acpi_init(boot_info);
|
acpi_init(boot_info);
|
||||||
|
|
||||||
pci_init();
|
pci_init();
|
||||||
|
|
||||||
ps2_controller_init();
|
|
||||||
|
|
||||||
scheduler_init(boot_info);
|
|
||||||
|
|
||||||
tty_init();
|
tty_init();
|
||||||
|
|
||||||
|
ps2_controller_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kmain(boot_info_T boot_info) {
|
void kmain(boot_info_T boot_info) {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "boot/config.h"
|
#include "boot/config.h"
|
||||||
|
|
||||||
void ps2_controller_init() {
|
void ps2_controller_init() {
|
||||||
|
// check if the ps/2 controller exists
|
||||||
if (g_sysconfig->ps2_acpi_validation) {
|
if (g_sysconfig->ps2_acpi_validation) {
|
||||||
if (!(g_acpi_table_fadt->ia_boot_architecture_flags & (1 << 1))) {
|
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)");
|
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)");
|
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();
|
ps2_keyboard_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ps2_controller_command(uint8_t command) {
|
uint8_t ps2_controller_command(uint8_t command) {
|
||||||
io_out_byte(PS2_CONTROLLER_COMMAND_PORT, 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 0;
|
||||||
}
|
}
|
||||||
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
io_out_byte(PS2_CONTROLLER_DATA_PORT, data);
|
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 0;
|
||||||
}
|
}
|
||||||
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
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() {
|
bool ps2_controller_wait_until_ready_for_input() {
|
||||||
uint32_t timeout = 0;
|
uint32_t timeout = 0;
|
||||||
while (io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000010) {
|
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() {
|
bool ps2_controller_wait_until_ready_for_output() {
|
||||||
uint32_t timeout = 0;
|
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)) {
|
while (!(io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000001)) {
|
||||||
if (timeout > PS2_CONTROLLER_TIMEOUT) {
|
if (timeout > PS2_CONTROLLER_TIMEOUT) {
|
||||||
log(LOG_WARNING, "<PS2 Controller> Controller not ready for output (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() {
|
uint8_t ps2_controller_read_data() {
|
||||||
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ps2_controller_write_data(uint8_t data) {
|
||||||
|
io_out_byte(PS2_CONTROLLER_DATA_PORT, data);
|
||||||
|
}
|
||||||
|
|
|
@ -12,13 +12,24 @@ char scancode_set_1[] = " 1234567890-= qwertyuiop[] asdfghjkl;'` \\zxcvbnm,./
|
||||||
bool shift_enabled = false;
|
bool shift_enabled = false;
|
||||||
bool extended_key = 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 response = PS2_KEYBOARD_RESPONSE_RESEND;
|
||||||
uint8_t tries = 0;
|
uint8_t tries = 0;
|
||||||
|
|
||||||
while (response == PS2_KEYBOARD_RESPONSE_RESEND) {
|
while (response == PS2_KEYBOARD_RESPONSE_RESEND) {
|
||||||
response = ps2_controller_command(command);
|
if (!ps2_controller_wait_until_ready_for_input()) {
|
||||||
log(LOG_DEBUG, "<PS2> '%s' + 0x%xb -> 0x%xb", ps2_keyboard_command_to_string(command), data, response);
|
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++;
|
tries++;
|
||||||
|
|
||||||
if (tries >= 3) {
|
if (tries >= 3) {
|
||||||
|
@ -32,10 +43,20 @@ uint8_t ps2_keyboard_command(ps2_keyboard_command_E command, uint8_t data) {
|
||||||
|
|
||||||
void ps2_keyboard_init() {
|
void ps2_keyboard_init() {
|
||||||
|
|
||||||
// uint8_t data = ps2_keyboard_command(PS2_KEYBOARD_COMMAND_ECHO, 0);
|
// re-enable the ps/2 keyboard
|
||||||
// log(LOG_DEBUG, "response: 0x%xb", data);
|
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);
|
pic_unmask_irq(IRQ_KEYBOARD);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue