310 lines
8.8 KiB
C
310 lines
8.8 KiB
C
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/kassert.h>
|
|
#include <sys/kdebug.h>
|
|
#include <sys/irq.h>
|
|
|
|
#include <machine/cpu.h>
|
|
#include <machine/cpuop.h>
|
|
|
|
#include "../console.h"
|
|
#include "ps2.h"
|
|
|
|
// Status/Command Port (Input/Output)
|
|
#define PS2_STATUS_PORT 0x64
|
|
#define PS2_COMMAND_PORT 0x64
|
|
#define PS2_DATA_PORT 0x60
|
|
|
|
// Controller Status
|
|
#define PS2_STATUS_OBS 0x01 /* Input Buffer Ready */
|
|
#define PS2_STATUS_IBS 0x02 /* Output Buffer Full */
|
|
|
|
// Controller Commands
|
|
#define PS2_COMMAND_AUXDISABLE 0xA7 /* Disable Auxiliary */
|
|
#define PS2_COMMAND_AUXENABLE 0xA8 /* Enable Auxiliary */
|
|
#define PS2_COMMAND_SELFTEST 0xAA /* Test Controller */
|
|
#define PS2_COMMAND_KBDDISABLE 0xAD /* Disable Keyboard */
|
|
#define PS2_COMMAND_KBDENABLE 0xAE /* Enable Keyboard */
|
|
|
|
// Keyboard Commands
|
|
#define PS2_KBD_RESET 0xFF /* Reset */
|
|
#define PS2_KBD_SETLED 0xED /* Set LED */
|
|
|
|
// Keyboard Response
|
|
#define PS2_KBD_RESETDONE 0xAA /* Reset Done */
|
|
|
|
static IRQHandler kbdHandler;
|
|
static IRQHandler psmHandler;
|
|
|
|
// Key state flags
|
|
#define KS_SHIFT 0x01
|
|
#define KS_ALT 0x02
|
|
#define KS_CONTROL 0x04
|
|
#define KS_CAPSLOCK 0x08
|
|
#define KS_NUMLOCK 0x10
|
|
#define KS_SCROLLLOCK 0x20
|
|
#define KS_E0ESCAPE 0x30
|
|
static uint32_t keyState;
|
|
|
|
static uint8_t keyMap[256] = {
|
|
0x00, 0x1B, '1', '2', '3', '4', '5', '6',
|
|
'7', '8', '9', '0', '-', '=', 0x08, 0x09,
|
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|
'o', 'p', '[', ']', 0x0A, 0x00, 'a', 's',
|
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
|
'\'', '`', 0x00, '\\', 'z', 'x', 'c', 'v',
|
|
'b', 'n', 'm', ',', '.', '/', 0x00, '*',
|
|
0x00, ' ', KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
|
|
|
|
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, 0x00, 0x00, '7',
|
|
'8', '9', '-', '4', '5', '6', '+', '1',
|
|
'2', '3', '0', '.', 0x00, 0x00, 0x00, KEY_F11,
|
|
KEY_F12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static uint8_t shiftKeyMap[256] = {
|
|
0x00, 0x1B, '!', '@', '#', '$', '%', '^',
|
|
'&', '*', '(', ')', '_', '+', 0x08, 0x09,
|
|
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
|
|
'O', 'P', '{', '}', 0x0A, 0x00, 'A', 'S',
|
|
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
|
|
'"', '~', 0x00, '|', 'Z', 'X', 'C', 'V',
|
|
'B', 'N', 'M', '<', '>', '?', 0x00, '*',
|
|
0x00, ' ', KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
|
|
|
|
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, 0x00, 0x00, '7',
|
|
'8', '9', '-', '4', '5', '6', '+', '1',
|
|
'2', '3', '0', '.', 0x00, 0x00, 0x00, KEY_F11,
|
|
KEY_F12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static uint8_t controlKeyMap[256] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static void
|
|
PS2_KeyboardIntr(void *arg)
|
|
{
|
|
uint8_t status;
|
|
uint8_t data;
|
|
uint8_t key;
|
|
|
|
while (1) {
|
|
status = inb(PS2_STATUS_PORT);
|
|
if ((status & PS2_STATUS_OBS) == 0)
|
|
return;
|
|
|
|
data = inb(PS2_DATA_PORT);
|
|
|
|
// E0 escape sequence
|
|
if (data == 0xE0) {
|
|
keyState |= KS_E0ESCAPE;
|
|
continue;
|
|
}
|
|
|
|
// Check for release of shift, alt, control
|
|
if (data & 0x80) {
|
|
if (data == 0xAA || data == 0xB6)
|
|
keyState &= ~KS_SHIFT;
|
|
if (data == 0x9D)
|
|
keyState &= ~KS_CONTROL;
|
|
if (data == 0x38)
|
|
keyState &= ~KS_ALT;
|
|
|
|
// Other key release
|
|
continue;
|
|
}
|
|
|
|
// Check for shift, alt, control
|
|
if (data == 0x2A || data == 0x36)
|
|
keyState |= KS_SHIFT;
|
|
if (data == 0x1D)
|
|
keyState |= KS_CONTROL;
|
|
if (data == 0x38)
|
|
keyState |= KS_ALT;
|
|
|
|
// Check for numlock, capslock, scrolllock
|
|
if (data == 0x3A)
|
|
keyState ^= KS_CAPSLOCK;
|
|
if (data == 0x45)
|
|
keyState ^= KS_NUMLOCK;
|
|
if (data == 0x46)
|
|
keyState ^= KS_SCROLLLOCK;
|
|
|
|
// Decode character
|
|
if (keyState & KS_E0ESCAPE) {
|
|
keyState &= ~KS_E0ESCAPE;
|
|
|
|
// Escape sequences
|
|
continue;
|
|
}
|
|
|
|
// Debugger sequences
|
|
if ((keyState & (KS_ALT | KS_CONTROL)) == (KS_ALT | KS_CONTROL)) {
|
|
// Debugger: Alt-Control-Backspace
|
|
if (data == 0x0E)
|
|
breakpoint();
|
|
|
|
// Reboot: Alt-Control-Delete
|
|
}
|
|
|
|
int isShift = 0;
|
|
if (keyState & KS_SHIFT)
|
|
isShift = 1;
|
|
if (keyState & KS_CAPSLOCK)
|
|
isShift ^= 1;
|
|
|
|
if (keyState & KS_CONTROL) {
|
|
key = controlKeyMap[data];
|
|
} else if (isShift) {
|
|
key = shiftKeyMap[data];
|
|
} else {
|
|
key = keyMap[data];
|
|
}
|
|
|
|
if (key == 0x00)
|
|
continue;
|
|
|
|
//kprintf("Key Press: %02X\n", key);
|
|
Console_EnqueueKey(key);
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
static void
|
|
PS2_MouseIntr(void *arg)
|
|
{
|
|
}
|
|
|
|
void
|
|
PS2Wait()
|
|
{
|
|
uint8_t status;
|
|
|
|
while (1) {
|
|
status = inb(PS2_STATUS_PORT);
|
|
if ((status & PS2_STATUS_OBS) != 0)
|
|
return;
|
|
}
|
|
}
|
|
|
|
void
|
|
PS2_Init()
|
|
{
|
|
uint8_t status, data;
|
|
|
|
keyState = 0;
|
|
|
|
outb(PS2_COMMAND_PORT, PS2_COMMAND_KBDDISABLE);
|
|
|
|
while (1) {
|
|
status = inb(PS2_STATUS_PORT);
|
|
if ((status & PS2_STATUS_OBS) == 0)
|
|
break;
|
|
|
|
data = inb(PS2_DATA_PORT);
|
|
}
|
|
|
|
// Self test
|
|
outb(PS2_COMMAND_PORT, PS2_COMMAND_SELFTEST);
|
|
PS2Wait();
|
|
data = inb(PS2_DATA_PORT);
|
|
if (data != 0x55)
|
|
kprintf("PS2: Controller test failed\n");
|
|
|
|
outb(PS2_COMMAND_PORT, PS2_COMMAND_KBDENABLE);
|
|
|
|
kbdHandler.irq = 1;
|
|
kbdHandler.cb = &PS2_KeyboardIntr;
|
|
kbdHandler.arg = NULL;
|
|
psmHandler.irq = 12;
|
|
psmHandler.cb = &PS2_MouseIntr;
|
|
psmHandler.arg = NULL;
|
|
|
|
IRQ_Register(1, &kbdHandler);
|
|
IRQ_Register(12, &psmHandler);
|
|
}
|
|
|