Set up ps/2 controller

This commit is contained in:
Juhani Krekelä 2022-01-19 21:22:12 +02:00
parent 58dfcec0cd
commit cb8a12eed0
1 changed files with 130 additions and 2 deletions

132
kernel.c
View File

@ -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");
}