/* DKM PS/2 Keyboard Driver — IRQ1 scan code → ASCII * Stage 3, optional, depends on "irq", provides "keyboard". * Registers IRQ1 handler, translates scan codes via lookup table. */ #include #include "../dkm_shared.h" #include "../dkm_instr.h" DKM_STAT_DECL(ps2kbd_irq_count); /* Driver descriptor */ static const char *const g_depends[] = {"irq"}; static const char *const g_provides[] = {"keyboard"}; __attribute__((visibility("default"), used)) const struct dkm_driver_desc driver_desc = { .magic=DKM_DRIVER_MAGIC, .abi_version=DKM_ABI_VERSION, .desc_size=sizeof(struct dkm_driver_desc), .name="ps2kbd", .version="0.1.0", .vendor="Deshab", .driver_class=10, .stage=3, .flags=0, .priority=0, .depends=g_depends, .depends_count=1, .provides=g_provides, .provides_count=1, .min_kernel_abi=1, }; /* Scan code set 1 → ASCII (lowercase) */ static const char sc_ascii[] = { 0,0,'1','2','3','4','5','6','7','8','9','0','-','=',0, 0,'q','w','e','r','t','y','u','i','o','p','[',']',0, 0,'a','s','d','f','g','h','j','k','l',';','\'','`',0, '\\','z','x','c','v','b','n','m',',','.','/',0, '*',0,' ',0 }; static const struct dkm_log_api *g_log; static volatile int g_has_key; static volatile u8 g_last_sc; /* inline I/O */ static u8 inb(u16 p) { u8 v; __asm__("inb %1,%0":"=a"(v):"Nd"(p)); return v; } static void outb(u16 p, u8 v) { __asm__("outb %0,%1"::"a"(v),"Nd"(p)); } static void log_hex(const char *prefix, u64 v) { static const char h[]="0123456789abcdef"; char b[19]; u32 i=0; b[i++]='0'; b[i++]='x'; for (int j=15;j>=0;j--) b[i++]=h[(v>>(j*4))&0xf]; b[i]=0; g_log->info(prefix); g_log->info(b); } static int kbd_handler(u8 irq) { (void)irq; g_last_sc = inb(0x60); g_has_key = 1; DKM_STAT_INC(ps2kbd_irq_count); return 0; /* let kernel send EOI */ } __attribute__((visibility("default"))) int driver_init(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle) { (void)handle; if (!api||!api->log) return -1; g_log=api->log; dkm_instr_init(api); if (!api->irq_register) { g_log->warn("[kbd] irq_register not available"); return 0; } if (api->irq_register(1, (void*)(uintptr_t)kbd_handler) != 0) { g_log->error("[kbd] failed to register IRQ1"); return -1; } g_log->info("[kbd] IRQ1 registered, waiting for keypress"); g_log->info("[kbd] (boot will continue, key echo in ISR)"); /* spin briefly to show a key echo demo */ int ticks = 0; while (ticks < 200000) { if (g_has_key) { u8 sc = g_last_sc; g_has_key = 0; if (sc < 0x80) { /* make code */ log_hex("[kbd] sc=", sc); if (sc < sizeof(sc_ascii) && sc_ascii[sc]) { char buf[2] = {sc_ascii[sc], 0}; g_log->info("[kbd] key"); g_log->info(buf); } } } for (volatile int z=0;z<100;z++) {} ticks++; } g_log->info("[kbd] driver ready"); return 0; } __attribute__((visibility("default"))) int driver_exit(struct dkm_driver_handle *handle) { (void)handle; return 0; }