mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +00:00
kernel: ps2 initialisation
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
#include <kernel/initrd.h>
|
#include <kernel/initrd.h>
|
||||||
#include <kernel/devfs.h>
|
#include <kernel/devfs.h>
|
||||||
#include <kernel/pseudodevices.h>
|
#include <kernel/pseudodevices.h>
|
||||||
|
#include <arch/ps2.h>
|
||||||
|
|
||||||
static cpu_t bsp_cpu;
|
static cpu_t bsp_cpu;
|
||||||
|
|
||||||
@@ -58,5 +59,7 @@ void kernel_entry() {
|
|||||||
|
|
||||||
pseudodevices_init();
|
pseudodevices_init();
|
||||||
|
|
||||||
|
arch_ps2_init();
|
||||||
|
|
||||||
__assert(!"kernel entry end");
|
__assert(!"kernel entry end");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#include <arch/ps2.h>
|
||||||
|
#include <printf.h>
|
||||||
|
|
||||||
|
static bool reset_selftest(int port) {
|
||||||
|
uint8_t r = RESEND;
|
||||||
|
bool timeout = false;
|
||||||
|
int attempts = 0;
|
||||||
|
|
||||||
|
while (r == RESEND && attempts < 10) {
|
||||||
|
device_command(port, DEVICE_CMD_RESETSELFTEST);
|
||||||
|
r = read_data_timeout(5, &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attempts == 10)
|
||||||
|
timeout = true;
|
||||||
|
|
||||||
|
if (!timeout) {
|
||||||
|
if (read_data() != DEVICE_SELFTEST_OK)
|
||||||
|
printf("ps2: %s port device self test failed!\n", port == 1 ? "First" : "Second");
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_ps2_init() {
|
||||||
|
// XXX actually check if the controller is there
|
||||||
|
write_command(CTLR_CMD_DISABLEP1);
|
||||||
|
write_command(CTLR_CMD_DISABLEP2);
|
||||||
|
|
||||||
|
inb(PS2_PORT_DATA); // flush output buffer
|
||||||
|
|
||||||
|
write_command(CTLR_CMD_READCFG);
|
||||||
|
uint8_t control = read_data();
|
||||||
|
|
||||||
|
bool dualport = control & CONFIG_CLOCKP2;
|
||||||
|
|
||||||
|
control &= ~(CONFIG_IRQP1 | CONFIG_IRQP2 | CONFIG_TRANSLATION);
|
||||||
|
|
||||||
|
write_command(CTLR_CMD_WRITECFG);
|
||||||
|
write_data(control);
|
||||||
|
|
||||||
|
write_command(CTLR_CMD_SELFTEST);
|
||||||
|
if (read_data() != CTLR_SELFTEST_OK)
|
||||||
|
printf("ps2: controller self test failed.\n");
|
||||||
|
|
||||||
|
write_command(CTLR_CMD_WRITECFG);
|
||||||
|
write_data(control); // restore config if it was reset
|
||||||
|
|
||||||
|
// confirm existance of second port
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
int workingflag = 0;
|
||||||
|
|
||||||
|
if (dualport) {
|
||||||
|
write_command(CTLR_CMD_P2SELFTEST);
|
||||||
|
if (read_data() == 0)
|
||||||
|
workingflag |= 2;
|
||||||
|
else
|
||||||
|
printf("ps2: econd port self test failed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workingflag == 0) {
|
||||||
|
printf("ps2: no working ports.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("ps2: controller with %d ports\n", dualport ? 2 : 1);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
int connectedflag = 0;
|
||||||
|
|
||||||
|
if (workingflag & 1 && reset_selftest(1))
|
||||||
|
connectedflag |= 1;
|
||||||
|
|
||||||
|
if (workingflag & 2 && reset_selftest(2))
|
||||||
|
connectedflag |= 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
#ifndef _PS2_H
|
||||||
|
#define _PS2_H
|
||||||
|
|
||||||
|
#include <kernel/timekeeper.h>
|
||||||
|
#include <arch/io.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#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 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 CTLR_SELFTEST_OK 0x55
|
||||||
|
|
||||||
|
#define CONFIG_IRQP1 1
|
||||||
|
#define CONFIG_IRQP2 2
|
||||||
|
#define CONFIG_TRANSLATION 0x40
|
||||||
|
#define CONFIG_CLOCKP2 0x20
|
||||||
|
|
||||||
|
#define DEVICE_CMD_RESETSELFTEST 0xff
|
||||||
|
#define DEVICE_CMD_IDENTIFY 0xf2
|
||||||
|
#define DEVICE_SELFTEST_OK 0xaa
|
||||||
|
|
||||||
|
static inline bool inbuffer_full() {
|
||||||
|
return (inb(PS2_PORT_STATUS) & 2) == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool outbuffer_full() {
|
||||||
|
return (inb(PS2_PORT_STATUS) & 1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write_command(uint8_t cmd) {
|
||||||
|
while (inbuffer_full());
|
||||||
|
outb(PS2_PORT_COMMAND, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void write_data(uint8_t cmd) {
|
||||||
|
while (inbuffer_full());
|
||||||
|
outb(PS2_PORT_DATA, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void device_command(int port, uint8_t command) {
|
||||||
|
if (port == 2)
|
||||||
|
write_command(CTLR_CMD_SECONDPORTSELECT);
|
||||||
|
|
||||||
|
write_data(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t read_data() {
|
||||||
|
while (!outbuffer_full());
|
||||||
|
return inb(PS2_PORT_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t read_data_timeout(int ms, bool *timeout) {
|
||||||
|
timespec_t initial = timekeeper_timefromboot();
|
||||||
|
|
||||||
|
while (outbuffer_full() == false) {
|
||||||
|
timespec_t current = timekeeper_timefromboot();
|
||||||
|
if (timespec_diffms(initial, current) >= ms) {
|
||||||
|
*timeout = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*timeout = false;
|
||||||
|
return read_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t device_write_response(int port, uint8_t command) {
|
||||||
|
uint8_t r = RESEND;
|
||||||
|
int tries = 0;
|
||||||
|
|
||||||
|
while (r == RESEND && tries-- < 5) {
|
||||||
|
device_command(port, command);
|
||||||
|
r = read_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_ps2_init();
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user