static u_char spic_call2(struct spic_softc *sc, u_char dev, u_char fn) { busy_wait(sc); write_port2(sc, dev); busy_wait(sc); write_port1(sc, fn); return read_port1(sc); }
void KBM::init() { // disable ports ctl_send(CMD_DISABLE_PORT1); ctl_send(CMD_DISABLE_PORT2); ps2_flush(); // configure controller ctl_send(0x20); uint8_t config = read_data(); bool second_port = config & (1 << 5); (void) second_port; config |= 0x1 | 0x2; // enable interrupts config &= ~(1 << 6); // write config ctl_send(0x60); send_data(config); ps2_flush(); // enable port1 ctl_send(CMD_ENABLE_PORT1); ps2_flush(); // self-test (port1) write_port1(0xFF); uint8_t selftest = read_data(); assert(selftest == 0xAA); write_port1(DEV_IDENTIFY); uint8_t id1 = read_data(); if (id1 == 0xAA || id1 == 0xAB) { // port1 is the keyboard debug("keyboard on port1\n"); keyboard_write = write_port1; mouse_write = write_port2; } else { // port2 is the keyboard debug("keyboard on port2\n"); mouse_write = write_port1; keyboard_write = write_port2; } // enable keyboard keyboard_write(0xF4); // get and set scancode keyboard_write(0xF0); send_data(0x01); keyboard_write(0xF0); send_data(0x00); uint8_t scanset = 0xFA; while (scanset == 0xFA) scanset = read_data(); // route and enable interrupt handlers const uint8_t KEYB_IRQ = (keyboard_write == write_port1) ? PORT1_IRQ : PORT2_IRQ; const uint8_t MOUS_IRQ = (KEYB_IRQ == PORT1_IRQ) ? PORT2_IRQ : PORT1_IRQ; assert(KEYB_IRQ != MOUS_IRQ); // need to route IRQs from IO APIC to BSP LAPIC IRQ_manager::get().enable_irq(KEYB_IRQ); IRQ_manager::get().enable_irq(MOUS_IRQ); IRQ_manager::get().subscribe(KEYB_IRQ, [KEYB_IRQ] { //IRQ_manager::eoi(KEYB_IRQ); uint8_t byte = read_fast(); // transform to virtual key int key = get().transform_vk(byte); // call handler get().on_virtualkey(key); }); IRQ_manager::get().subscribe(MOUS_IRQ, [MOUS_IRQ] { //IRQ_manager::eoi(MOUS_IRQ); get().handle_mouse(read_fast()); }); /* // reset and enable keyboard send_data(0xF6); // enable keyboard scancodes send_data(0xF4); // enable interrupts //ctl_send(0x60, ctl_read(0x20) | 0x1 | 0x2); */ }