Add the current OS source tree, build scripts, system image layout, and development notes covering DMA page allocation, e1000 bring-up, net API dispatch, and DHCP work in progress.
140 lines
4.2 KiB
C
140 lines
4.2 KiB
C
/* 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 <stdint.h>
|
|
|
|
/* DKM ABI types */
|
|
#define DKM_DRIVER_MAGIC 0x444B4D31u
|
|
#define DKM_ABI_VERSION 1u
|
|
|
|
typedef unsigned char u8;
|
|
typedef unsigned short u16;
|
|
typedef unsigned int u32;
|
|
typedef unsigned long long u64;
|
|
typedef long long i64;
|
|
#define NULL ((void *)0)
|
|
|
|
struct dkm_log_api {
|
|
void (*info)(const char *msg);
|
|
void (*warn)(const char *msg);
|
|
void (*error)(const char *msg);
|
|
void (*panic)(const char *msg);
|
|
};
|
|
|
|
struct dkm_kernel_api {
|
|
u32 version; u32 size; u64 feature_bits;
|
|
const struct dkm_log_api *log;
|
|
const void *mem,*utsm,*irq_api,*pci_api,*dma,*vfs_api,*net,*timer,*drr;
|
|
const void *rsdp_address,*fb_address;
|
|
u64 fb_width,fb_height,fb_pitch; u16 fb_bpp;
|
|
const void *boot_modules_response;
|
|
int (*irq_register)(u8 irq, void *handler);
|
|
};
|
|
|
|
struct dkm_driver_handle;
|
|
struct dkm_driver_desc {
|
|
u32 magic; u16 abi_version; u16 desc_size;
|
|
const char *name,*version,*vendor;
|
|
u32 driver_class,stage,flags,priority;
|
|
const char *const *depends; u32 depends_count;
|
|
const char *const *provides; u32 provides_count;
|
|
u64 min_kernel_abi,feature_bits,reserved0,reserved1;
|
|
};
|
|
|
|
/* 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;
|
|
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;
|
|
|
|
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;
|
|
}
|