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)
|
void terminal_putchar(char c)
|
||||||
{
|
{
|
||||||
|
if (c == '\n') {
|
||||||
|
terminal_row++;
|
||||||
|
terminal_column = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
|
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
|
||||||
if (++terminal_column == VGA_WIDTH) {
|
if (++terminal_column == VGA_WIDTH) {
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
|
@ -106,11 +112,133 @@ void terminal_writestring(const char* data)
|
||||||
terminal_write(data, strlen(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)
|
void kernel_main(void)
|
||||||
{
|
{
|
||||||
/* Initialize terminal interface */
|
/* Initialize terminal interface */
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
|
|
||||||
/* Newline support is left as an exercise. */
|
init_8042();
|
||||||
terminal_writestring("Hello, kernel World!\n");
|
if (single_channel)
|
||||||
|
|
||||||
|
terminal_writestring("\nHanging\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue