/*- * Written by paradox * Public domain. */ #include __FBSDID("$FreeBSD: head/sys/compat/x86bios/x86bios.c 197475 2009-09-24 22:42:35Z jkim $"); #include "opt_x86bios.h" #include #include #include #include #include #include #include #include #include #include #include u_char *pbiosMem = NULL; static u_char *pbiosStack = NULL; int busySegMap[5]; static struct x86emu x86bios_emu; static struct mtx x86bios_lock; static uint8_t x86bios_emu_inb(struct x86emu *emu, uint16_t port) { if (port == 0xb2) /* APM scratch register */ return (0); if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); return (inb(port)); } static uint16_t x86bios_emu_inw(struct x86emu *emu, uint16_t port) { if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); return (inw(port)); } static uint32_t x86bios_emu_inl(struct x86emu *emu, uint16_t port) { if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); return (inl(port)); } static void x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) { if (port == 0xb2) /* APM scratch register */ return; if (port >= 0x80 && port < 0x88) /* POST status register */ return; outb(port, val); } static void x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) { if (port >= 0x80 && port < 0x88) /* POST status register */ return; outw(port, val); } static void x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) { if (port >= 0x80 && port < 0x88) /* POST status register */ return; outl(port, val); } void x86bios_intr(struct x86regs *regs, int intno) { if (intno < 0 || intno > 255) return; if (bootverbose) printf("Calling real mode int 0x%x " "(ax=0x%04x bx=0x%04x cx=0x%04x dx=0x%04x)\n", intno, regs->R_AX, regs->R_BX, regs->R_CX, regs->R_DX); mtx_lock_spin(&x86bios_lock); memcpy(&x86bios_emu.x86, regs, sizeof(*regs)); x86emu_exec_intr(&x86bios_emu, intno); memcpy(regs, &x86bios_emu.x86, sizeof(*regs)); mtx_unlock_spin(&x86bios_lock); if (bootverbose) printf("Exiting real mode int 0x%x " "(ax=0x%04x bx=0x%04x cx=0x%04x dx=0x%04x)\n", intno, regs->R_AX, regs->R_BX, regs->R_CX, regs->R_DX); } void * x86bios_offset(uint32_t offs) { return (pbiosMem + offs); } static void x86bios_init(void *arg __unused) { int offs; mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN); /* Can pbiosMem be NULL here? */ pbiosMem = pmap_mapbios(0x0, MAPPED_MEMORY_SIZE); memset(&x86bios_emu, 0, sizeof(x86bios_emu)); x86emu_init_default(&x86bios_emu); x86bios_emu.emu_inb = x86bios_emu_inb; x86bios_emu.emu_inw = x86bios_emu_inw; x86bios_emu.emu_inl = x86bios_emu_inl; x86bios_emu.emu_outb = x86bios_emu_outb; x86bios_emu.emu_outw = x86bios_emu_outw; x86bios_emu.emu_outl = x86bios_emu_outl; x86bios_emu.mem_base = (char *)pbiosMem; x86bios_emu.mem_size = 1024 * 1024; memset(busySegMap, 0, sizeof(busySegMap)); pbiosStack = x86bios_alloc(1, &offs); } static void x86bios_uninit(void *arg __unused) { x86bios_free(pbiosStack, 1); if (pbiosMem) pmap_unmapdev((vm_offset_t)pbiosMem, MAPPED_MEMORY_SIZE); mtx_destroy(&x86bios_lock); } static int x86bios_modevent(module_t mod __unused, int type, void *data __unused) { int err = 0; switch (type) { case MOD_LOAD: x86bios_init(NULL); break; case MOD_UNLOAD: x86bios_uninit(NULL); break; default: err = ENOTSUP; break; } return (err); } static moduledata_t x86bios_mod = { "x86bios", x86bios_modevent, NULL, }; DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_CPU, SI_ORDER_ANY); MODULE_VERSION(x86bios, 1);