x86bios.c revision 197388
1/*- 2 * Written by paradox <ddkprog@yahoo.com> 3 * Public domain. 4 */ 5 6#include <sys/cdefs.h> 7__FBSDID("$FreeBSD: head/sys/dev/x86bios/x86bios.c 197388 2009-09-21 09:09:55Z delphij $"); 8 9#include "opt_x86bios.h" 10 11#include <sys/param.h> 12#include <sys/systm.h> 13#include <sys/kernel.h> 14#include <sys/module.h> 15#include <sys/lock.h> 16#include <sys/mutex.h> 17 18#include <vm/vm.h> 19#include <vm/vm_extern.h> 20#include <vm/vm_kern.h> 21#include <vm/vm_param.h> 22#include <vm/pmap.h> 23 24#include <machine/cpufunc.h> 25 26#include <contrib/x86emu/x86emu.h> 27#include <contrib/x86emu/x86emu_regs.h> 28#include <dev/x86bios/x86bios.h> 29 30u_char *pbiosMem = NULL; 31static u_char *pbiosStack = NULL; 32 33int busySegMap[5]; 34 35static struct x86emu xbios86emu; 36 37static struct mtx x86bios_lock; 38 39static uint8_t 40vm86_emu_inb(struct x86emu *emu, uint16_t port) 41{ 42 if (port == 0xb2) /* APM scratch register */ 43 return 0; 44 if (port >= 0x80 && port < 0x88) /* POST status register */ 45 return 0; 46 return inb(port); 47} 48 49static uint16_t 50vm86_emu_inw(struct x86emu *emu, uint16_t port) 51{ 52 if (port >= 0x80 && port < 0x88) /* POST status register */ 53 return 0; 54 return inw(port); 55} 56 57static uint32_t 58vm86_emu_inl(struct x86emu *emu, uint16_t port) 59{ 60 if (port >= 0x80 && port < 0x88) /* POST status register */ 61 return 0; 62 return inl(port); 63} 64 65static void 66vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) 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 76vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) 77{ 78 if (port >= 0x80 && port < 0x88) /* POST status register */ 79 return; 80 outw(port, val); 81} 82 83static void 84vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) 85{ 86 if (port >= 0x80 && port < 0x88) /* POST status register */ 87 return; 88 outl(port, val); 89} 90 91void 92x86biosCall(struct x86regs *regs, int intno) 93{ 94 if (intno < 0 || intno > 255) 95 return; 96 97 mtx_lock(&x86bios_lock); 98 critical_enter(); 99 100 xbios86emu.x86.R_EAX = regs->R_EAX; 101 xbios86emu.x86.R_EBX = regs->R_EBX; 102 xbios86emu.x86.R_ECX = regs->R_ECX; 103 xbios86emu.x86.R_EDX = regs->R_EDX; 104 105 xbios86emu.x86.R_ESP = regs->R_ESP; 106 xbios86emu.x86.R_EBP = regs->R_EBP; 107 xbios86emu.x86.R_ESI = regs->R_ESI; 108 xbios86emu.x86.R_EDI = regs->R_EDI; 109 xbios86emu.x86.R_EIP = regs->R_EIP; 110 xbios86emu.x86.R_EFLG = regs->R_EFLG; 111 112 xbios86emu.x86.R_CS = regs->R_CS; 113 xbios86emu.x86.R_DS = regs->R_DS; 114 xbios86emu.x86.R_SS = regs->R_SS; 115 xbios86emu.x86.R_ES = regs->R_ES; 116 xbios86emu.x86.R_FS = regs->R_FS; 117 xbios86emu.x86.R_GS = regs->R_GS; 118 119 x86emu_exec_intr(&xbios86emu, intno); 120 121 regs->R_EAX = xbios86emu.x86.R_EAX; 122 regs->R_EBX = xbios86emu.x86.R_EBX; 123 regs->R_ECX = xbios86emu.x86.R_ECX; 124 regs->R_EDX = xbios86emu.x86.R_EDX; 125 126 regs->R_ESP = xbios86emu.x86.R_ESP; 127 regs->R_EBP = xbios86emu.x86.R_EBP; 128 regs->R_ESI = xbios86emu.x86.R_ESI; 129 regs->R_EDI = xbios86emu.x86.R_EDI; 130 regs->R_EIP = xbios86emu.x86.R_EIP; 131 regs->R_EFLG = xbios86emu.x86.R_EFLG; 132 133 regs->R_CS = xbios86emu.x86.R_CS; 134 regs->R_DS = xbios86emu.x86.R_DS; 135 regs->R_SS = xbios86emu.x86.R_SS; 136 regs->R_ES = xbios86emu.x86.R_ES; 137 regs->R_FS = xbios86emu.x86.R_FS; 138 regs->R_GS = xbios86emu.x86.R_GS; 139 140 critical_exit(); 141 mtx_unlock(&x86bios_lock); 142} 143 144void * 145x86biosOffs(uint32_t offs) 146{ 147 return (pbiosMem + offs); 148} 149 150static void 151x86bios_init(void *arg __unused) 152{ 153 int offs; 154 155 mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_DEF); 156 157 /* Can pbiosMem be NULL here? */ 158 pbiosMem = pmap_mapbios(0x0, MAPPED_MEMORY_SIZE); 159 160 memset(&xbios86emu, 0, sizeof(xbios86emu)); 161 x86emu_init_default(&xbios86emu); 162 163 xbios86emu.emu_inb = vm86_emu_inb; 164 xbios86emu.emu_inw = vm86_emu_inw; 165 xbios86emu.emu_inl = vm86_emu_inl; 166 xbios86emu.emu_outb = vm86_emu_outb; 167 xbios86emu.emu_outw = vm86_emu_outw; 168 xbios86emu.emu_outl = vm86_emu_outl; 169 170 xbios86emu.mem_base = (char *)pbiosMem; 171 xbios86emu.mem_size = 1024 * 1024; 172 173 memset(busySegMap, 0, sizeof(busySegMap)); 174 175 pbiosStack = x86biosAlloc(1, &offs); 176} 177 178static void 179x86bios_uninit(void *arg __unused) 180{ 181 x86biosFree(pbiosStack, 1); 182 183 if (pbiosMem) 184 pmap_unmapdev((vm_offset_t)pbiosMem, 185 MAPPED_MEMORY_SIZE); 186 187 mtx_destroy(&x86bios_lock); 188} 189 190static int 191x86bios_modevent(module_t mod __unused, int type, void *data __unused) 192{ 193 int err = 0; 194 195 switch (type) { 196 case MOD_LOAD: 197 x86bios_init(NULL); 198 break; 199 case MOD_UNLOAD: 200 x86bios_uninit(NULL); 201 break; 202 default: 203 err = ENOTSUP; 204 break; 205 } 206 207 return (err); 208} 209 210static moduledata_t x86bios_mod = { 211 "x86bios", 212 x86bios_modevent, 213 NULL, 214}; 215 216DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_CPU, SI_ORDER_ANY); 217MODULE_VERSION(x86bios, 1); 218 219