/* * https://wiki.osdev.org/%228042%22_PS/2_Controller */ #include "keyboard.h" #include "ps2_controller.h" #include #include #include /* r status register */ /* w command register */ #define comm_port 0x64 #define comm_enable_first_ps2 0xae #define comm_enable_second_ps2 0xa8 #define comm_read_ctrl_config 0x20 #define comm_write_ctrl_config 0x60 #define data_port 0x60 #define data_enable_scanning 0xf4 /* TODO: All output to port 0x60 or 0x64 must be preceded by waiting for bit 1 (value=2) of port 0x64 to become clear. * TODO: Similarly, bytes cannot be read from port 0x60 until bit 0 (value=1) of port 0x64 is set. */ void ps2_ctrl_init() { int i; /* eat all previous keystrikes */ while (inb(comm_port) & 0x1) inb(data_port); uint8_t test; outb(0xaa, comm_port); test = inb(data_port); printf("i8042: self test 0xaa:%x %s\n", test, test == 0x55 ? "ok" : "failed"); outb(0xab, comm_port); test = inb(data_port); printf("i8042: port1 test 0xab:%x %s\n", test, test == 0x00 ? "ok" : "failed"); outb(0xa9, comm_port); test = inb(data_port); printf("i8042: port2 test 0xa9:%x %s\n", test, test == 0x00 ? "ok" : "failed"); /* printf("8042: init keyboard\n"); */ outb(comm_enable_first_ps2, comm_port); outb(comm_enable_second_ps2, comm_port); /* resets the cpu */ /* outb(0xfe, 0x64); */ outb(0xf2, 0x60); printf("i8042: id port1: "); while ((inb(0x64) & 0x01) == 0) {} for (i = 0; i < 3; ++i) printf("%x ", inb(0x60)); printf("\n"); outb(0xd4, 0x64); outb(0xf2, 0x60); printf("i8042: id port2: "); while ((inb(0x64) & 0x01) == 0) {} for (i = 0; i < 3; ++i) printf("%x ", inb(0x60)); printf("\n"); outb(comm_read_ctrl_config, comm_port); uint8_t conf = (inb(data_port) | 1) & ~0x10; conf |= 0x22; /* mouse */ outb(comm_write_ctrl_config, comm_port); outb(conf, data_port); outb(data_enable_scanning, data_port); outb(0xd4, 0x64); outb(0xf4, 0x60); } unsigned char ps2_read_port1() { return inb(data_port); } unsigned char ps2_read_port2() { outb(0xd4, 0x64); return inb(0x60); }