diff --git a/kernel-src/arch/x86-64/ps2.c b/kernel-src/arch/x86-64/ps2.c index 5a86f416..222f99e8 100644 --- a/kernel-src/arch/x86-64/ps2.c +++ b/kernel-src/arch/x86-64/ps2.c @@ -3,121 +3,275 @@ #include #include -static bool reset_selftest(int port) { - uint8_t r = RESEND; - bool timeout = false; - int attempts = 0; +static void ps2_disablescanning(int port) { + ps2_device_command(port, PS2_DEVICE_CMD_DISABLESCANNING); - while (r == RESEND && attempts < 5) { - device_command(port, DEVICE_CMD_RESETSELFTEST); - r = read_data_timeout(5, &timeout); - ++attempts; - } + int resendtries = 0; - if (attempts == 5) - timeout = true; + // loop until timeout, resend if we need to + // this is done to clear the buffer and make sure no more data will be read + for (;;) { + bool timeout; + uint8_t data = ps2_read_data_timeout(100, &timeout); + if (timeout) + break; - if (!timeout) { - if (read_data() != DEVICE_SELFTEST_OK) { - printf("ps2: %s port device self test failed!\n", port == 1 ? "First" : "Second"); - } else { - return true; + if (data == PS2_RESEND) { + if (resendtries++ > 5) { + printf("ps2: ps2_disablescanning: port %d: too many resends\n", port); + return; + } + + ps2_device_command(port, PS2_DEVICE_CMD_DISABLESCANNING); } } - return false; + // just to make sure + ps2_flush_outbuffer(); +} + +static bool ps2_enablescanning(int port) { + ps2_device_command(port, PS2_DEVICE_CMD_ENABLESCANNING); + int resendtries = 0; + + for (;;) { + bool timeout; + uint8_t data = ps2_read_data_timeout(100, &timeout); + if (timeout) { + printf("ps2: ps2_enablescanning: port %d: timeout\n", port); + return false; + } + + if (data == PS2_ACK) + break; + + if (data == PS2_RESEND) { + if (resendtries++ > 5) { + printf("ps2: ps2_enablescanning: port %d: too many resends\n", port); + return false; + } + } + } + + // just to make sure + ps2_flush_outbuffer(); + return true; +} + +static bool ps2_device_reset_selftest(int port) { + ps2_disablescanning(port); + + ps2_device_command(port, PS2_DEVICE_CMD_RESETSELFTEST); + int resendtries = 0; + // loop until ACK or timeout, RESEND if needed + // this will make sure the reset command is ACK'd by the device + for (;;) { + bool timeout; + uint8_t data = ps2_read_data_timeout(500, &timeout); + + if (timeout) { + printf("ps2: ps2_reset_selftest: port %d: timed out waiting for ACK\n", port); + return false; + } + + if (data == PS2_RESEND) { + if (resendtries > 5) { + printf("ps2: ps2_reset_selftest: port %d: too many resend tries for self test command\n", port); + return false; + } + + ps2_device_command(port, PS2_DEVICE_CMD_RESETSELFTEST); + ++resendtries; + continue; + } + + if (data == PS2_ACK) + break; + } + + // now wait for the reset to be done + for (;;) { + bool timeout; + uint8_t data = ps2_read_data_timeout(2000, &timeout); + if (timeout) { + printf("ps2: ps2_reset_selftest: port %d: timed out waiting for result\n", port); + return false; + } + + if (data == PS2_DEVICE_SELFTEST_OK) + break; + + if (data == PS2_DEVICE_SELFTEST_FAIL) { + printf("ps2: ps2_reset_selftest: port %d: self test failed\n"); + return false; + } + } + + // and clear whatever could come our way + for (;;) { + bool timeout; + ps2_read_data_timeout(100, &timeout); + if (timeout) + break; + } + + // just to make sure + ps2_flush_outbuffer(); + return true; +} + +bool ps2_init_device(int port, bool *mouse) { + if (ps2_device_reset_selftest(port) == false) + return false; + + // to make sure it is still disabled + ps2_disablescanning(port); + return true; } void arch_ps2_init() { // XXX actually check if the controller is there - write_command(CTLR_CMD_DISABLEP1); - write_command(CTLR_CMD_DISABLEP2); + ps2_write_command(PS2_CTLR_CMD_DISABLEP1); + ps2_write_command(PS2_CTLR_CMD_DISABLEP2); - inb(PS2_PORT_DATA); // flush output buffer + // just to make sure + ps2_flush_outbuffer(); - write_command(CTLR_CMD_READCFG); - uint8_t control = read_data(); + ps2_write_command(PS2_CTLR_CMD_READCFG); + uint8_t control = ps2_read_data(); - bool dualport = control & CONFIG_CLOCKP2; + bool dualport = control & PS2_CONFIG_CLOCKP2; - control &= ~(CONFIG_IRQP1 | CONFIG_IRQP2 | CONFIG_TRANSLATION); + control &= ~(PS2_CONFIG_IRQP1 | PS2_CONFIG_IRQP2 | PS2_CONFIG_TRANSLATION); - write_command(CTLR_CMD_WRITECFG); - write_data(control); + ps2_write_command(PS2_CTLR_CMD_WRITECFG); + ps2_write_data(control); - write_command(CTLR_CMD_SELFTEST); - if (read_data() != CTLR_SELFTEST_OK) { - printf("ps2: controller self test failed.\n"); + ps2_write_command(PS2_CTLR_CMD_SELFTEST); + uint8_t result = ps2_read_data(); + + if (result != PS2_CTLR_SELFTEST_OK) { + printf("ps2: controller self test failed (expected %x got %x)\n", PS2_CTLR_SELFTEST_OK, result); return; } - write_command(CTLR_CMD_WRITECFG); - write_data(control); // restore config if it was reset + ps2_write_command(PS2_CTLR_CMD_WRITECFG); + ps2_write_data(control); // restore config if it was reset // confirm existance of second port + if (dualport) { + ps2_write_command(PS2_CTLR_CMD_ENABLEP2); + ps2_write_command(PS2_CTLR_CMD_READCFG); + control = ps2_read_data(); - write_command(CTLR_CMD_ENABLEP2); - - write_command(CTLR_CMD_READCFG); - control = read_data(); - - if (dualport && (control & CONFIG_CLOCKP2)) // not enabled, not dual port. - dualport = false; - else - write_command(CTLR_CMD_DISABLEP2); // disable second port again + if (dualport && (control & PS2_CONFIG_CLOCKP2)) // not enabled, not dual port. + dualport = false; + else + ps2_write_command(PS2_CTLR_CMD_DISABLEP2); // disable second port again + } + // do port self tests int workingflag = 0; - write_command(CTLR_CMD_P1SELFTEST); - if (read_data() == 0) + ps2_write_command(PS2_CTLR_CMD_P1SELFTEST); + result = ps2_read_data(); + if (result == 0) workingflag |= 1; else - printf("First PS/2 port self test failed!\n"); + printf("ps2: first PS/2 port self test failed! Expected 0 got %x\n", result); if (dualport) { - write_command(CTLR_CMD_P2SELFTEST); - if (read_data() == 0) + ps2_write_command(PS2_CTLR_CMD_P2SELFTEST); + result = ps2_read_data(); + if (result == 0) workingflag |= 2; else - printf("ps2: second port self test failed!\n"); + printf("ps2: second port self test failed! Expected 0 got %x\n", result); } if (workingflag == 0) { - printf("ps2: no working ports.\n"); + printf("ps2: no working ports\n"); return; } printf("ps2: controller with %d ports\n", dualport ? 2 : 1); - // enable ports - - write_command(CTLR_CMD_ENABLEP1); - if (dualport) - write_command(CTLR_CMD_ENABLEP2); - - // enable irqs and translation in config - - write_command(CTLR_CMD_READCFG); - control = read_data(); - - control |= (dualport ? CONFIG_IRQP1 | CONFIG_IRQP2 : CONFIG_IRQP1) | CONFIG_TRANSLATION; - - write_command(CTLR_CMD_WRITECFG); - write_data(control); - // reset and self test devices + // the ports leave this with scanning disabled int connectedflag = 0; - if ((workingflag & 1) && reset_selftest(1)) - connectedflag |= 1; + if (workingflag & 1) { + if (ps2_device_reset_selftest(1) == false) { + printf("ps2: device self test for port 1 failed\n"); + } else { + connectedflag |= 1; + } + } - if ((workingflag & 2) && reset_selftest(2)) - connectedflag |= 2; + if (workingflag & 2) { + if (ps2_device_reset_selftest(2) == false) { + printf("ps2: device self test for port 2 failed\n"); + } else { + connectedflag |= 2; + } + } - // XXX should id each one for proper identification - if (connectedflag & 1) - ps2kbd_init(); - if (connectedflag & 2) - ps2mouse_init(); + if (connectedflag == 0) { + printf("ps2: no working devices\n"); + return; + } + + uint8_t okflag = 0; + // now initialize and enable the device stuff + if (connectedflag & 1) { + ps2_write_command(PS2_CTLR_CMD_ENABLEP1); + // figure out what the device is TODO and actually use the result for something + uint8_t identity[2]; + if (ps2_identify(1, identity) == false) { + printf("ps2: failed to identify first port\n"); + goto do_2; + } else { + ps2kbd_init(); + ps2_write_command(PS2_CTLR_CMD_DISABLEP2); + okflag |= 1; + } + } + + do_2: + if (connectedflag & 2) { + ps2_write_command(PS2_CTLR_CMD_ENABLEP2); + // figure out what the device is TODO and actually use the result for something + uint8_t identity[2]; + if (ps2_identify(1, identity) == false) { + printf("ps2: failed to identify second port\n"); + } else { + ps2mouse_init(); + ps2_write_command(PS2_CTLR_CMD_DISABLEP2); + okflag |= 2; + } + } + + if (okflag & 1) { + ps2_write_command(PS2_CTLR_CMD_ENABLEP1); + if (ps2_enablescanning(1) == false) { + printf("ps2: failed to enable scanning for port 1\n"); + } + } + + if (okflag & 2) { + ps2_write_command(PS2_CTLR_CMD_ENABLEP2); + if (ps2_enablescanning(2) == false) { + printf("ps2: failed to enable scanning for port 2\n"); + } + } + + // enable irqs and translation in config + ps2_write_command(PS2_CTLR_CMD_READCFG); + control = ps2_read_data(); + + control |= (dualport ? PS2_CONFIG_IRQP1 | PS2_CONFIG_IRQP2 : PS2_CONFIG_IRQP1) | PS2_CONFIG_TRANSLATION; + + ps2_write_command(PS2_CTLR_CMD_WRITECFG); + ps2_write_data(control); } diff --git a/kernel-src/arch/x86-64/ps2kbd.c b/kernel-src/arch/x86-64/ps2kbd.c index 5c24abc0..6b1e9c2b 100644 --- a/kernel-src/arch/x86-64/ps2kbd.c +++ b/kernel-src/arch/x86-64/ps2kbd.c @@ -116,7 +116,6 @@ static char extendedcodes[128] = { }; #define KEYBOARDIRQ 1 -#define KEYBOARD_CMD_REPORTDATA 0xf4 keyboard_t *kb; static bool extended = false; @@ -153,15 +152,6 @@ static void kbdisr(isr_t *isr, context_t *ctx) { } void ps2kbd_init() { - // clear PS/2 buffer to make sure its empty - inb(PS2_PORT_DATA); - - int response = device_write_response(1, KEYBOARD_CMD_REPORTDATA); - if (response != ACK) { - printf("ps2keyboard: expected ACK, got %x\n", response); - return; - } - isr_t *isr = interrupt_allocate(kbdisr, arch_apic_eoi, IPL_KEYBOARD); __assert(isr); arch_ioapic_setirq(KEYBOARDIRQ, isr->id & 0xff, _cpu()->id, false); diff --git a/kernel-src/arch/x86-64/ps2mouse.c b/kernel-src/arch/x86-64/ps2mouse.c index 029b00cd..b3affba7 100644 --- a/kernel-src/arch/x86-64/ps2mouse.c +++ b/kernel-src/arch/x86-64/ps2mouse.c @@ -2,35 +2,23 @@ #include #include -#define MOUSE_CMD_SAMPLERATE 0xF3 -#define MOUSE_CMD_REPORTDATA 0xF4 +#define PS2_MOUSE_CMD_SAMPLERATE 0xF3 -#define MOUSE 0 -#define MOUSE_Z 3 -#define MOUSE_5B 4 +#define PS2_MOUSE 0 +#define PS2_MOUSE_Z 3 +#define PS2_MOUSE_5B 4 static bool haswheel = false; static bool fivebuttons = false; -static void mouse_setrate(int port, uint8_t rate) { - device_write_response(port, MOUSE_CMD_SAMPLERATE); - device_write_response(port, rate); -} - -static uint8_t identify(int port) { - bool timeout; - - device_command(port, DEVICE_CMD_IDENTIFY); - uint8_t b = read_data_timeout(5, &timeout); - - if (b != ACK) { - printf("ps2mouse: identify failed: %x\n", b); - return RESEND; +static void ps2_mouse_setrate(int port, uint8_t rate) { + if (ps2_device_write_ok(port, PS2_MOUSE_CMD_SAMPLERATE) == false) { + printf("ps2mouse: setting rate at port %d failed\n", port); } - b = read_data_timeout(5, &timeout); - - return timeout ? RESEND : b; + if (ps2_device_write_ok(port, rate) == false) { + printf("ps2mouse: setting rate at port %d failed\n", port); + } } static int datac; @@ -81,42 +69,49 @@ static void mouseisr() { mouse_packet(mouse, &packet); } +#define DO_IDENTIFY_CHECK(step) \ + if (ps2_identify(2, identity) == false) { \ + printf("ps2: ps2mouse_init: failed to identify mouse at port %d (step \"%s\")\n", port, step); \ + return; \ + } void ps2mouse_init() { - inb(PS2_PORT_DATA); + int port = 2; + uint8_t identity[2]; - if (identify(2) != MOUSE) { + DO_IDENTIFY_CHECK("first"); + + if (identity[0] != PS2_MOUSE) { printf("Not a mouse!\n"); return; } // check if mouse has scroll wheel - mouse_setrate(2, 200); - mouse_setrate(2, 100); - mouse_setrate(2, 80); + ps2_mouse_setrate(2, 200); + ps2_mouse_setrate(2, 100); + ps2_mouse_setrate(2, 80); + + DO_IDENTIFY_CHECK("has scroll"); - if (identify(2) == MOUSE_Z) { + if (identity[0] == PS2_MOUSE_Z) { haswheel = true; // check if mouse has 5 buttons - mouse_setrate(2, 200); - mouse_setrate(2, 200); - mouse_setrate(2, 80); + ps2_mouse_setrate(2, 200); + ps2_mouse_setrate(2, 200); + ps2_mouse_setrate(2, 80); - if (identify(2) == MOUSE_5B) + DO_IDENTIFY_CHECK("5 buttons"); + + if (identity[0] == PS2_MOUSE_5B) fivebuttons = true; } - mouse_setrate(2, 60); - int response = device_write_response(2, MOUSE_CMD_REPORTDATA); - if (response != ACK) { - printf("ps2mouse: expected ACK, got %x\n", response); - return; - } + ps2_mouse_setrate(2, 60); isr_t *isr = interrupt_allocate(mouseisr, arch_apic_eoi, IPL_MOUSE); __assert(isr); - arch_ioapic_setirq(MOUSEIRQ, isr->id & 0xff, _cpu()->id, false); + arch_ioapic_setirq(PS2_MOUSEIRQ, isr->id & 0xff, _cpu()->id, false); mouse = mouse_new(); __assert(mouse); printf("ps2mouse: irq enabled with vector %u\n", isr->id & 0xff); diff --git a/kernel-src/include/x86-64/arch/ps2.h b/kernel-src/include/x86-64/arch/ps2.h index 4306248d..bcccf963 100644 --- a/kernel-src/include/x86-64/arch/ps2.h +++ b/kernel-src/include/x86-64/arch/ps2.h @@ -12,68 +12,79 @@ #define PS2_PORT_DATA 0x60 #define PS2_PORT_COMMAND 0x64 #define PS2_PORT_STATUS 0x64 -#define RESEND 0xfe -#define ACK 0xfa -#define ECHO 0xee -#define KEYBOARDIRQ 1 -#define MOUSEIRQ 12 +#define PS2_RESEND 0xfe +#define PS2_ACK 0xfa +#define PS2_ECHO 0xee +#define PS2_KEYBOARDIRQ 1 +#define PS2_MOUSEIRQ 12 -#define CTLR_CMD_SECONDPORTSELECT 0xd4 -#define CTLR_CMD_DISABLEP1 0xad -#define CTLR_CMD_DISABLEP2 0xa7 -#define CTLR_CMD_READCFG 0x20 -#define CTLR_CMD_WRITECFG 0x60 -#define CTLR_CMD_SELFTEST 0xaa -#define CTLR_CMD_ENABLEP1 0xae -#define CTLR_CMD_ENABLEP2 0xa8 -#define CTLR_CMD_P1SELFTEST 0xab -#define CTLR_CMD_P2SELFTEST 0xa9 +#define PS2_CTLR_CMD_SECONDPORTSELECT 0xd4 +#define PS2_CTLR_CMD_DISABLEP1 0xad +#define PS2_CTLR_CMD_DISABLEP2 0xa7 +#define PS2_CTLR_CMD_READCFG 0x20 +#define PS2_CTLR_CMD_WRITECFG 0x60 +#define PS2_CTLR_CMD_SELFTEST 0xaa +#define PS2_CTLR_CMD_ENABLEP1 0xae +#define PS2_CTLR_CMD_ENABLEP2 0xa8 +#define PS2_CTLR_CMD_P1SELFTEST 0xab +#define PS2_CTLR_CMD_P2SELFTEST 0xa9 -#define CTLR_SELFTEST_OK 0x55 +#define PS2_CTLR_SELFTEST_OK 0x55 -#define CONFIG_IRQP1 1 -#define CONFIG_IRQP2 2 -#define CONFIG_TRANSLATION 0x40 -#define CONFIG_CLOCKP2 0x20 +#define PS2_CONFIG_IRQP1 1 +#define PS2_CONFIG_IRQP2 2 +#define PS2_CONFIG_TRANSLATION 0x40 +#define PS2_CONFIG_CLOCKP2 0x20 -#define DEVICE_CMD_RESETSELFTEST 0xff -#define DEVICE_CMD_IDENTIFY 0xf2 -#define DEVICE_SELFTEST_OK 0xaa +#define PS2_DEVICE_CMD_RESETSELFTEST 0xff +#define PS2_DEVICE_CMD_DISABLESCANNING 0xf5 +#define PS2_DEVICE_CMD_ENABLESCANNING 0xf4 +#define PS2_DEVICE_CMD_IDENTIFY 0xf2 +#define PS2_DEVICE_SELFTEST_OK 0xaa +#define PS2_DEVICE_SELFTEST_FAIL 0xfc -static inline bool inbuffer_full() { +// needs to be waited to read +static inline bool ps2_outbuffer_empty() { + return (inb(PS2_PORT_STATUS) & 1) == 0; +} + +// needs to be waited to write +static inline bool ps2_inbuffer_full() { return (inb(PS2_PORT_STATUS) & 2) == 2; } -static inline bool outbuffer_full() { - return (inb(PS2_PORT_STATUS) & 1) == 1; +static inline void ps2_flush_outbuffer() { + while (ps2_outbuffer_empty() == false) + inb(PS2_PORT_DATA); } -static inline void write_command(uint8_t cmd) { - while (inbuffer_full()); +static inline void ps2_write_command(uint8_t cmd) { + while (ps2_inbuffer_full()); outb(PS2_PORT_COMMAND, cmd); } -static inline void write_data(uint8_t cmd) { - while (inbuffer_full()); +static inline void ps2_write_data(uint8_t cmd) { + while (ps2_inbuffer_full()); outb(PS2_PORT_DATA, cmd); } -static inline void device_command(int port, uint8_t command) { +static inline void ps2_device_command(int port, uint8_t command) { if (port == 2) - write_command(CTLR_CMD_SECONDPORTSELECT); + ps2_write_command(PS2_CTLR_CMD_SECONDPORTSELECT); - write_data(command); + ps2_write_data(command); } -static inline uint8_t read_data() { - while (!outbuffer_full()); +static inline uint8_t ps2_read_data() { + while (ps2_outbuffer_empty()); + return inb(PS2_PORT_DATA); } -static inline uint8_t read_data_timeout(int ms, bool *timeout) { +static inline uint8_t ps2_read_data_timeout(int ms, bool *timeout) { timespec_t initial = timekeeper_timefromboot(); - while (outbuffer_full() == false) { + while (ps2_outbuffer_empty()) { timespec_t current = timekeeper_timefromboot(); if (timespec_diffms(initial, current) >= ms) { *timeout = true; @@ -82,22 +93,77 @@ static inline uint8_t read_data_timeout(int ms, bool *timeout) { } *timeout = false; - return read_data(); + return ps2_read_data(); } -static inline uint8_t device_write_response(int port, uint8_t command) { - uint8_t r = RESEND; +static inline bool ps2_device_write_ok(int port, uint8_t command) { + ps2_device_command(port, command); + int resends = 0; + bool timeout; + + for (;;) { + uint8_t data = ps2_read_data_timeout(100, &timeout); + if (timeout) + return false; + + if (data == PS2_RESEND) { + if (resends++ > 5) + return false; + + ps2_device_command(port, command); + } + + if (data == PS2_ACK) + break; + } + + return true; +} + +static inline uint8_t ps2_device_write_response(int port, uint8_t command) { + uint8_t r = PS2_RESEND; int tries = 0; - while (r == RESEND && tries < 5) { - device_command(port, command); - r = read_data(); + while (r == PS2_RESEND && tries < 5) { + ps2_device_command(port, command); + r = ps2_read_data(); ++tries; } return r; } +static bool ps2_identify(int port, uint8_t results[2]) { + ps2_device_command(port, PS2_DEVICE_CMD_IDENTIFY); + int resends = 0; + bool timeout; + + for (;;) { + uint8_t data = ps2_read_data_timeout(100, &timeout); + if (timeout) + return false; + + if (data == PS2_RESEND) { + if (resends++ > 5) + return false; + + ps2_device_command(port, PS2_DEVICE_CMD_IDENTIFY); + } + + if (data == PS2_ACK) + break; + } + + // now read the actual data bytes + results[0] = ps2_read_data_timeout(100, &timeout); + if (timeout) + return false; + + // secon read can timeout just fine. + results[1] = ps2_read_data_timeout(100, &timeout); + return true; +} + void arch_ps2_init(); #endif diff --git a/recipes/xfontxfree86type1 b/recipes/xfontxfree86type1 deleted file mode 100644 index d867d008..00000000 --- a/recipes/xfontxfree86type1 +++ /dev/null @@ -1,15 +0,0 @@ -name=xfontmiscmisc -revision=1 -from_source=xfontmiscmisc -imagedeps="gcc xorg-mkfontscale" -hostdeps="xgcc xbinutils pkgconfig util-macros fontutil" -deps="mlibc" - -build() { - ${source_dir}/configure --prefix=${prefix} --host=x86_64-astral - make -j${parallelism} -} - -package() { - make install DESTDIR=${dest_dir} -}