mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
ps2: improvements
This commit is contained in:
+226
-72
@@ -3,121 +3,275 @@
|
||||
#include <arch/ps2kbd.h>
|
||||
#include <arch/ps2mouse.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2,35 +2,23 @@
|
||||
#include <logging.h>
|
||||
#include <kernel/mouse.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
Reference in New Issue
Block a user