72 lines
1.9 KiB
C
72 lines
1.9 KiB
C
// hal_keyboard.c - PS/2 keyboard, interrupt-driven, 256-entry ring buffer
|
|
#include "hal_api.h"
|
|
#include "hal_apic.h"
|
|
#include "hal_debug.h"
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <intrin.h>
|
|
|
|
#define PS2_DATA 0x60
|
|
#define PS2_STAT 0x64
|
|
#define PS2_CMD 0x64
|
|
|
|
#define KBD_BUF_SIZE 256
|
|
|
|
static uint8_t gBuf[KBD_BUF_SIZE];
|
|
static volatile int gHead = 0, gTail = 0;
|
|
static void (*gCallback)(uint8_t) = (void *)0;
|
|
|
|
// Minimal Set-2 to ASCII translation (unshifted only).
|
|
static const char gScanToAscii[128] = {
|
|
0,0,'1','2','3','4','5','6','7','8','9','0','-','=','\b',
|
|
'\t','q','w','e','r','t','y','u','i','o','p','[',']','\n',
|
|
0,'a','s','d','f','g','h','j','k','l',';','\'','`',
|
|
0,'\\','z','x','c','v','b','n','m',',','.','/',0,'*',
|
|
0,' ',0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
'7','8','9','-','4','5','6','+','1','2','3','0','.',0,0,0,
|
|
};
|
|
|
|
static void KbdIsr(void) {
|
|
uint8_t sc = __inbyte(PS2_DATA);
|
|
if (sc & 0x80) return; // key-up, ignore
|
|
int next = (gTail + 1) % KBD_BUF_SIZE;
|
|
if (next != gHead) {
|
|
gBuf[gTail] = sc;
|
|
gTail = next;
|
|
}
|
|
if (gCallback) gCallback(sc);
|
|
}
|
|
|
|
static bool KbdPoll(void) {
|
|
return gHead != gTail;
|
|
}
|
|
|
|
static uint8_t KbdReadScancode(void) {
|
|
while (gHead == gTail) { _mm_pause(); }
|
|
uint8_t sc = gBuf[gHead];
|
|
gHead = (gHead + 1) % KBD_BUF_SIZE;
|
|
return sc;
|
|
}
|
|
|
|
static char KbdReadChar(void) {
|
|
uint8_t sc = KbdReadScancode();
|
|
if (sc < 128) return gScanToAscii[sc];
|
|
return 0;
|
|
}
|
|
|
|
static void KbdSetCallback(void (*cb)(uint8_t sc)) {
|
|
gCallback = cb;
|
|
}
|
|
|
|
void HalKeyboardInitialize(HAL_KEYBOARD *out) {
|
|
// Flush PS/2 output buffer
|
|
while (__inbyte(PS2_STAT) & 1) __inbyte(PS2_DATA);
|
|
|
|
out->Poll = KbdPoll;
|
|
out->ReadScancode = KbdReadScancode;
|
|
out->ReadChar = KbdReadChar;
|
|
out->SetCallback = KbdSetCallback;
|
|
out->Isr = KbdIsr;
|
|
out->IrqNumber = 1;
|
|
}
|