x86bios.c revision 197475
1/*- 2 * Written by paradox <ddkprog@yahoo.com> 3 * Public domain. 4 */ 5 6#include <sys/cdefs.h> 7__FBSDID("$FreeBSD: head/sys/compat/x86bios/x86bios.c 197475 2009-09-24 22:42:35Z jkim $"); 8 9#include "opt_x86bios.h" 10 11#include <sys/param.h> 12#include <sys/kernel.h> 13#include <sys/lock.h> 14#include <sys/module.h> 15#include <sys/mutex.h> 16 17#include <vm/vm.h> 18#include <vm/pmap.h> 19 20#include <machine/cpufunc.h> 21 22#include <contrib/x86emu/x86emu.h> 23#include <contrib/x86emu/x86emu_regs.h> 24#include <compat/x86bios/x86bios.h> 25 26u_char *pbiosMem = NULL; 27static u_char *pbiosStack = NULL; 28 29int busySegMap[5]; 30 31static struct x86emu x86bios_emu; 32 33static struct mtx x86bios_lock; 34 35static uint8_t 36x86bios_emu_inb(struct x86emu *emu, uint16_t port) 37{ 38 39 if (port == 0xb2) /* APM scratch register */ 40 return (0); 41 if (port >= 0x80 && port < 0x88) /* POST status register */ 42 return (0); 43 return (inb(port)); 44} 45 46static uint16_t 47x86bios_emu_inw(struct x86emu *emu, uint16_t port) 48{ 49 50 if (port >= 0x80 && port < 0x88) /* POST status register */ 51 return (0); 52 return (inw(port)); 53} 54 55static uint32_t 56x86bios_emu_inl(struct x86emu *emu, uint16_t port) 57{ 58 59 if (port >= 0x80 && port < 0x88) /* POST status register */ 60 return (0); 61 return (inl(port)); 62} 63 64static void 65x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) 66{ 67 68 if (port == 0xb2) /* APM scratch register */ 69 return; 70 if (port >= 0x80 && port < 0x88) /* POST status register */ 71 return; 72 outb(port, val); 73} 74 75static void 76x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) 77{ 78 79 if (port >= 0x80 && port < 0x88) /* POST status register */ 80 return; 81 outw(port, val); 82} 83 84static void 85x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) 86{ 87 88 if (port >= 0x80 && port < 0x88) /* POST status register */ 89 return; 90 outl(port, val); 91} 92 93void 94x86bios_intr(struct x86regs *regs, int intno) 95{ 96 97 if (intno < 0 || intno > 255) 98 return; 99 100 if (bootverbose) 101 printf("Calling real mode int 0x%x " 102 "(ax=0x%04x bx=0x%04x cx=0x%04x dx=0x%04x)\n", 103 intno, regs->R_AX, regs->R_BX, regs->R_CX, regs->R_DX); 104 105 mtx_lock_spin(&x86bios_lock); 106 107 memcpy(&x86bios_emu.x86, regs, sizeof(*regs)); 108 x86emu_exec_intr(&x86bios_emu, intno); 109 memcpy(regs, &x86bios_emu.x86, sizeof(*regs)); 110 111 mtx_unlock_spin(&x86bios_lock); 112 113 if (bootverbose) 114 printf("Exiting real mode int 0x%x " 115 "(ax=0x%04x bx=0x%04x cx=0x%04x dx=0x%04x)\n", 116 intno, regs->R_AX, regs->R_BX, regs->R_CX, regs->R_DX); 117} 118 119void * 120x86bios_offset(uint32_t offs) 121{ 122 123 return (pbiosMem + offs); 124} 125 126static void 127x86bios_init(void *arg __unused) 128{ 129 int offs; 130 131 mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN); 132 133 /* Can pbiosMem be NULL here? */ 134 pbiosMem = pmap_mapbios(0x0, MAPPED_MEMORY_SIZE); 135 136 memset(&x86bios_emu, 0, sizeof(x86bios_emu)); 137 x86emu_init_default(&x86bios_emu); 138 139 x86bios_emu.emu_inb = x86bios_emu_inb; 140 x86bios_emu.emu_inw = x86bios_emu_inw; 141 x86bios_emu.emu_inl = x86bios_emu_inl; 142 x86bios_emu.emu_outb = x86bios_emu_outb; 143 x86bios_emu.emu_outw = x86bios_emu_outw; 144 x86bios_emu.emu_outl = x86bios_emu_outl; 145 146 x86bios_emu.mem_base = (char *)pbiosMem; 147 x86bios_emu.mem_size = 1024 * 1024; 148 149 memset(busySegMap, 0, sizeof(busySegMap)); 150 151 pbiosStack = x86bios_alloc(1, &offs); 152} 153 154static void 155x86bios_uninit(void *arg __unused) 156{ 157 158 x86bios_free(pbiosStack, 1); 159 160 if (pbiosMem) 161 pmap_unmapdev((vm_offset_t)pbiosMem, 162 MAPPED_MEMORY_SIZE); 163 164 mtx_destroy(&x86bios_lock); 165} 166 167static int 168x86bios_modevent(module_t mod __unused, int type, void *data __unused) 169{ 170 int err = 0; 171 172 switch (type) { 173 case MOD_LOAD: 174 x86bios_init(NULL); 175 break; 176 case MOD_UNLOAD: 177 x86bios_uninit(NULL); 178 break; 179 default: 180 err = ENOTSUP; 181 break; 182 } 183 184 return (err); 185} 186 187static moduledata_t x86bios_mod = { 188 "x86bios", 189 x86bios_modevent, 190 NULL, 191}; 192 193DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_CPU, SI_ORDER_ANY); 194MODULE_VERSION(x86bios, 1); 195