bool ps2_probe() { uint8_t status; int buffer_size = 16; int bytes_read; status = ps2_read_status(); if(!PS2_STATUS_GET_SYSTEM_FLAG(status)) { kprintf("ps2 POST flag is false: 0x%hhx\n", status); return false; } for(bytes_read = 0; bytes_read < buffer_size && PS2_STATUS_GET_OUTPUT_BUFFER_STATUS(status); bytes_read++) { ps2_read_data(); status = ps2_read_status(); } if(bytes_read == buffer_size) { kprintf("read %d bytes from ps2 controller and couldn't empty output buffer. status=0x%hhx\n", bytes_read, status); return false; } ps2_write_command(test_ps2_controller); ps2_wait_output_buffer_sync(); uint8_t response = ps2_read_data(); if(!response == 0x55) { kprintf("ps2 self test failed. response: 0x%hhx\n", response); } return true; }
static uint32_t kbd_read_data(void *opaque, uint32_t addr) { KBDState *s = opaque; if (s->pending == KBD_PENDING_AUX) return ps2_read_data(s->mouse); return ps2_read_data(s->kbd); }
static uint64_t kbd_read_data(void *opaque, hwaddr addr, unsigned size) { KBDState *s = opaque; uint32_t val; if (s->pending == KBD_PENDING_AUX) val = ps2_read_data(s->mouse); else val = ps2_read_data(s->kbd); DPRINTF("kbd: read data=0x%02x\n", val); return val; }
static uint32_t kbd_read_data(void *opaque, uint32_t addr) { KBDState *s = opaque; uint32_t val; if (s->pending == KBD_PENDING_AUX) val = ps2_read_data(s->mouse); else val = ps2_read_data(s->kbd); #if defined(DEBUG_KBD) printf("kbd: read data=0x%02x\n", val); #endif return val; }
//TODO this is horrible void ps2_init() { if(acpi_tables_loaded()) { kprintf("checking acpi for ps2 controller\n"); _ps2_available = acpi_fadt_has_8042(); } else { kprintf("no acpi. assuming ps2 controller\n"); _ps2_available = true; } if(ps2_probe()) { kprintf("ps2 controller responding\n"); _ps2_available = true; } if(!_ps2_available) { kprintf("ps2 controller absent\n"); return; } kprintf("ps2 controller present\n"); ps2_write_command(disable_first_ps2_port); ps2_write_command(disable_second_ps2_port); ps2_flush_output_buffer(); ps2_ctrl_cfg_t config = ps2_read_config(); bool is_dual_channel = PS2_CTRL_CFG_GET_2ND_PS2_CLOCK_DISABLE(config) != 0 ? true : false; kprintf("ps2 config: 0x%hhx dual_channel=%s\n", config, BOOL_TO_STR(is_dual_channel)); config = PS2_CTRL_CFG_SET_1ST_PS2_INT_ENABLE(config, 0); config = PS2_CTRL_CFG_SET_2ND_PS2_INT_ENABLE(config, 0); config = PS2_CTRL_CFG_SET_1ST_PS2_TRANSLATION_ENABLE(config, 0); ps2_write_config(config); ps2_write_command(test_first_ps2_port); ps2_wait_output_buffer_sync(); // should be 0 uint8_t first_port_response; uint8_t second_port_response; first_port_response = ps2_read_data(); kprintf("ps2 port 0 test result: 0x%hhx\n", first_port_response); if(is_dual_channel) { ps2_write_command(test_second_ps2_port); ps2_wait_output_buffer_sync(); second_port_response = ps2_read_data(); kprintf("ps2 port 1 test result: 0x%hhx\n", second_port_response); } if(first_port_response == 0) { ps2_write_command(enable_first_ps2_port); config = ps2_read_config(); config = PS2_CTRL_CFG_SET_1ST_PS2_INT_ENABLE(config, 1); ps2_write_config(config); } if(is_dual_channel && second_port_response == 0) { ps2_write_command(enable_second_ps2_port); config = ps2_read_config(); config = PS2_CTRL_CFG_SET_2ND_PS2_INT_ENABLE(config, 1); ps2_write_config(config); } kprintf("installing ps2 keyboard irq handler\n"); hal_install_irq_handler(_kbd_irq, ps2_kbd_interrupt_handler, ps2_kbd_thread, "ps2_kbd", NULL); }
uint8_t ps2_read_config(void) { ps2_write_command(read_byte_0); return ps2_read_data(); }
void ps2_flush_output_buffer(void) { while(ps2_can_read_data()) { ps2_read_data(); } }