Set up ps/2 controller
This commit is contained in:
parent
58dfcec0cd
commit
cb8a12eed0
132
kernel.c
132
kernel.c
|
@ -87,6 +87,12 @@ void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
|
|||
|
||||
void terminal_putchar(char c)
|
||||
{
|
||||
if (c == '\n') {
|
||||
terminal_row++;
|
||||
terminal_column = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
|
||||
if (++terminal_column == VGA_WIDTH) {
|
||||
terminal_column = 0;
|
||||
|
@ -106,11 +112,133 @@ void terminal_writestring(const char* data)
|
|||
terminal_write(data, strlen(data));
|
||||
}
|
||||
|
||||
// (out|in)port from sortix, Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
void outport8(uint16_t port, uint8_t value)
|
||||
{
|
||||
asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));
|
||||
}
|
||||
|
||||
uint8_t inport8(uint16_t port)
|
||||
{
|
||||
uint8_t result;
|
||||
asm volatile("inb %1, %0" : "=a" (result) : "dN" (port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void command_8042(uint8_t command) {
|
||||
outport8(0x64, command);
|
||||
}
|
||||
|
||||
uint8_t status_8042(void) {
|
||||
return inport8(0x64);
|
||||
}
|
||||
|
||||
uint8_t read_8042(void) {
|
||||
return inport8(0x60);
|
||||
}
|
||||
|
||||
void write_8042(uint8_t data) {
|
||||
outport8(0x60, data);
|
||||
}
|
||||
|
||||
bool translation_initially;
|
||||
bool single_channel = false;
|
||||
|
||||
uint8_t read_config_8042(void) {
|
||||
command_8042(0x20);
|
||||
return read_8042();
|
||||
}
|
||||
|
||||
void write_config_8042(uint8_t config) {
|
||||
command_8042(0x60);
|
||||
write_8042(config);
|
||||
}
|
||||
|
||||
void init_8042(void) {
|
||||
// Disable devices
|
||||
command_8042(0xad);
|
||||
command_8042(0xa7);
|
||||
|
||||
// Flush output buffer
|
||||
while (status_8042() & (1<<0))
|
||||
(void) read_8042();
|
||||
|
||||
// Read configuration
|
||||
uint8_t config = read_config_8042();
|
||||
translation_initially = config & (1<<6);
|
||||
single_channel = !(config & (1<<5));
|
||||
|
||||
// Disable IRQ
|
||||
config &= ~(1<<0);
|
||||
config &= ~(1<<1);
|
||||
command_8042(0x60);
|
||||
write_8042(config);
|
||||
|
||||
// Self test
|
||||
terminal_writestring("8042 self-test... ");
|
||||
command_8042(0xaa);
|
||||
while (!(status_8042() & (1<<0)));
|
||||
if (read_8042() != 0x55)
|
||||
terminal_writestring("failed\n");
|
||||
else
|
||||
terminal_writestring("ok\n");
|
||||
// Some controllers need this
|
||||
command_8042(0x60);
|
||||
write_8042(config);
|
||||
|
||||
// Determine number of channels
|
||||
if (!single_channel) {
|
||||
command_8042(0xae);
|
||||
single_channel = read_config_8042() & (1<<5);
|
||||
if (!single_channel)
|
||||
command_8042(0xa7);
|
||||
}
|
||||
if (single_channel)
|
||||
terminal_writestring("Single-channel ps/2 controller\n");
|
||||
else
|
||||
terminal_writestring("Dual-channel ps/2 controller\n");
|
||||
|
||||
// Test channels
|
||||
terminal_writestring("Testing channel 1... ");
|
||||
command_8042(0xab);
|
||||
if (read_8042() != 0)
|
||||
terminal_writestring("failed\n");
|
||||
else
|
||||
terminal_writestring("ok\n");
|
||||
if (!single_channel) {
|
||||
terminal_writestring("Testing channel 2... ");
|
||||
command_8042(0xa9);
|
||||
if (read_8042() != 0)
|
||||
terminal_writestring("failed\n");
|
||||
else
|
||||
terminal_writestring("ok\n");
|
||||
}
|
||||
|
||||
// Enable devices
|
||||
command_8042(0xae);
|
||||
if (!single_channel)
|
||||
command_8042(0xa8);
|
||||
}
|
||||
|
||||
void enable_translation(void) {
|
||||
uint8_t config = read_config_8042();
|
||||
config |= 1<<6;
|
||||
write_config_8042(config);
|
||||
}
|
||||
|
||||
void disable_translation(void) {
|
||||
uint8_t config = read_config_8042();
|
||||
config &= ~(1<<6);
|
||||
write_config_8042(config);
|
||||
}
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
/* Initialize terminal interface */
|
||||
terminal_initialize();
|
||||
|
||||
/* Newline support is left as an exercise. */
|
||||
terminal_writestring("Hello, kernel World!\n");
|
||||
init_8042();
|
||||
if (single_channel)
|
||||
|
||||
terminal_writestring("\nHanging\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue