| 1 |
/* ============================================================================ |
| 2 |
* Pactor64 — PS/2 Keyboard Driver (x86-64) |
| 3 |
* IRQ1 (INT 0x21), scancode set 1, circular buffer |
| 4 |
* ============================================================================ */ |
| 5 |
#include "../include/pactor64.h" |
| 6 |
|
| 7 |
/* === Scancode → ASCII lookup (scancode set 1) === */ |
| 8 |
static const char sc1_to_ascii[128] = { |
| 9 |
0, 0, '1', '2', '3', '4', '5', '6', /* 0x00-0x07 */ |
| 10 |
'7', '8', '9', '0', '-', '=', '\b', '\t', /* 0x08-0x0F */ |
| 11 |
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10-0x17 */ |
| 12 |
'o', 'p', '[', ']', '\n', 0, 'a', 's', /* 0x18-0x1F */ |
| 13 |
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 0x20-0x27 */ |
| 14 |
'\'', '`', 0, '\\', 'z', 'x', 'c', 'v', /* 0x28-0x2F */ |
| 15 |
'b', 'n', 'm', ',', '.', '/', 0, '*', /* 0x30-0x37 */ |
| 16 |
0, ' ', 0, 0, 0, 0, 0, 0, /* 0x38-0x3F */ |
| 17 |
0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47 */ |
| 18 |
0, 0, '-', 0, 0, 0, '+', 0, /* 0x48-0x4F */ |
| 19 |
0, 0, 0, 0, 0, 0, 0, 0, /* 0x50-0x57 */ |
| 20 |
0, 0, 0, 0, 0, 0, 0, 0, /* 0x58-0x5F */ |
| 21 |
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ |
| 22 |
0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6F */ |
| 23 |
0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ |
| 24 |
0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7F */ |
| 25 |
}; |
| 26 |
|
| 27 |
/* === Circular scancode buffer === */ |
| 28 |
#define KBD_BUF_SIZE 256 |
| 29 |
static volatile char kbd_buf[KBD_BUF_SIZE]; |
| 30 |
static volatile int kbd_buf_head = 0; |
| 31 |
static volatile int kbd_buf_tail = 0; |
| 32 |
|
| 33 |
/* Forward declaration */ |
| 34 |
extern void irq_install(int irq, void (*handler)(registers_t *regs)); |
| 35 |
|
| 36 |
/* === Keyboard ISR (IRQ1) === */ |
| 37 |
static void keyboard_isr(registers_t *regs) { |
| 38 |
(void)regs; |
| 39 |
uint8_t scancode = inb(KBD_DATA_PORT); |
| 40 |
|
| 41 |
/* Ignore key releases (bit 7 set) */ |
| 42 |
if (scancode & 0x80) return; |
| 43 |
|
| 44 |
char c = sc1_to_ascii[scancode]; |
| 45 |
if (c == 0) return; |
| 46 |
|
| 47 |
/* Insert into circular buffer */ |
| 48 |
int next = (kbd_buf_head + 1) % KBD_BUF_SIZE; |
| 49 |
if (next != kbd_buf_tail) { |
| 50 |
kbd_buf[kbd_buf_head] = c; |
| 51 |
kbd_buf_head = next; |
| 52 |
} |
| 53 |
} |
| 54 |
|
| 55 |
/* === Initialize keyboard === */ |
| 56 |
void keyboard_init(void) { |
| 57 |
kbd_buf_head = 0; |
| 58 |
kbd_buf_tail = 0; |
| 59 |
|
| 60 |
/* Drain any pending data */ |
| 61 |
while (inb(KBD_STATUS_PORT) & 0x01) { |
| 62 |
inb(KBD_DATA_PORT); |
| 63 |
} |
| 64 |
|
| 65 |
irq_install(0x21, keyboard_isr); |
| 66 |
pic_unmask_irq(1); |
| 67 |
} |
| 68 |
|
| 69 |
/* === Read a character from keyboard buffer (non-blocking, returns -1 if empty) === */ |
| 70 |
int keyboard_getchar(void) { |
| 71 |
if (kbd_buf_head == kbd_buf_tail) return -1; |
| 72 |
char c = kbd_buf[kbd_buf_tail]; |
| 73 |
kbd_buf_tail = (kbd_buf_tail + 1) % KBD_BUF_SIZE; |
| 74 |
return c; |
| 75 |
} |
| 76 |
|