1*7113f419Smiod /* $OpenBSD: vga_post.c,v 1.4 2009/06/14 20:27:24 miod Exp $ */ 2e208dfa2Spirofti /* $NetBSD: vga_post.c,v 1.12 2009/03/15 21:32:36 cegger Exp $ */ 3e208dfa2Spirofti 4e208dfa2Spirofti /*- 5e208dfa2Spirofti * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. 6e208dfa2Spirofti * All rights reserved. 7e208dfa2Spirofti * 8e208dfa2Spirofti * Redistribution and use in source and binary forms, with or without 9e208dfa2Spirofti * modification, are permitted provided that the following conditions 10e208dfa2Spirofti * are met: 11e208dfa2Spirofti * 12e208dfa2Spirofti * 1. Redistributions of source code must retain the above copyright 13e208dfa2Spirofti * notice, this list of conditions and the following disclaimer. 14e208dfa2Spirofti * 2. Redistributions in binary form must reproduce the above copyright 15e208dfa2Spirofti * notice, this list of conditions and the following disclaimer in 16e208dfa2Spirofti * the documentation and/or other materials provided with the 17e208dfa2Spirofti * distribution. 18e208dfa2Spirofti * 19e208dfa2Spirofti * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20e208dfa2Spirofti * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21e208dfa2Spirofti * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22e208dfa2Spirofti * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23e208dfa2Spirofti * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24e208dfa2Spirofti * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 25e208dfa2Spirofti * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26e208dfa2Spirofti * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27e208dfa2Spirofti * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28e208dfa2Spirofti * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29e208dfa2Spirofti * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30e208dfa2Spirofti * SUCH DAMAGE. 31e208dfa2Spirofti */ 32e208dfa2Spirofti 33e208dfa2Spirofti #include <sys/cdefs.h> 34e208dfa2Spirofti 35e208dfa2Spirofti #include <sys/param.h> 36e208dfa2Spirofti #include <sys/device.h> 37e208dfa2Spirofti #include <sys/malloc.h> 38e208dfa2Spirofti #include <uvm/uvm_extern.h> 39e208dfa2Spirofti #include <uvm/uvm_page.h> 40e208dfa2Spirofti 41e208dfa2Spirofti #include <machine/pio.h> 42e208dfa2Spirofti 43e208dfa2Spirofti #include <machine/vga_post.h> 44e208dfa2Spirofti 454b013528Sderaadt #include <dev/x86emu/x86emu.h> 464b013528Sderaadt #include <dev/x86emu/x86emu_regs.h> 47e208dfa2Spirofti 48e208dfa2Spirofti #define BASE_MEMORY 65536 /* How much memory to allocate in Real Mode */ 49e208dfa2Spirofti 50e208dfa2Spirofti struct vga_post { 516bf2980cSderaadt struct x86emu emu; 52e208dfa2Spirofti vaddr_t sys_image; 53e208dfa2Spirofti uint32_t initial_eax; 54e208dfa2Spirofti uint8_t bios_data[PAGE_SIZE]; 55e208dfa2Spirofti struct pglist ram_backing; 56e208dfa2Spirofti }; 57e208dfa2Spirofti 58e208dfa2Spirofti #ifdef DDB 59e208dfa2Spirofti static struct vga_post *ddb_vgapostp; 60e208dfa2Spirofti void ddb_vgapost(void); 61e208dfa2Spirofti #endif 62e208dfa2Spirofti 63e208dfa2Spirofti static uint8_t 646bf2980cSderaadt vm86_emu_inb(struct x86emu *emu, uint16_t port) 65e208dfa2Spirofti { 66e208dfa2Spirofti if (port == 0xb2) /* APM scratch register */ 67e208dfa2Spirofti return 0; 68e208dfa2Spirofti 69e208dfa2Spirofti if (port >= 0x80 && port < 0x88) /* POST status register */ 70e208dfa2Spirofti return 0; 71e208dfa2Spirofti 72e208dfa2Spirofti return inb(port); 73e208dfa2Spirofti } 74e208dfa2Spirofti 75e208dfa2Spirofti static uint16_t 766bf2980cSderaadt vm86_emu_inw(struct x86emu *emu, uint16_t port) 77e208dfa2Spirofti { 78e208dfa2Spirofti if (port >= 0x80 && port < 0x88) /* POST status register */ 79e208dfa2Spirofti return 0; 80e208dfa2Spirofti 81e208dfa2Spirofti return inw(port); 82e208dfa2Spirofti } 83e208dfa2Spirofti 84e208dfa2Spirofti static uint32_t 856bf2980cSderaadt vm86_emu_inl(struct x86emu *emu, uint16_t port) 86e208dfa2Spirofti { 87e208dfa2Spirofti if (port >= 0x80 && port < 0x88) /* POST status register */ 88e208dfa2Spirofti return 0; 89e208dfa2Spirofti 90e208dfa2Spirofti return inl(port); 91e208dfa2Spirofti } 92e208dfa2Spirofti 93e208dfa2Spirofti static void 946bf2980cSderaadt vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) 95e208dfa2Spirofti { 96e208dfa2Spirofti if (port == 0xb2) /* APM scratch register */ 97e208dfa2Spirofti return; 98e208dfa2Spirofti 99e208dfa2Spirofti if (port >= 0x80 && port < 0x88) /* POST status register */ 100e208dfa2Spirofti return; 101e208dfa2Spirofti 102e208dfa2Spirofti outb(port, val); 103e208dfa2Spirofti } 104e208dfa2Spirofti 105e208dfa2Spirofti static void 1066bf2980cSderaadt vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) 107e208dfa2Spirofti { 108e208dfa2Spirofti if (port >= 0x80 && port < 0x88) /* POST status register */ 109e208dfa2Spirofti return; 110e208dfa2Spirofti 111e208dfa2Spirofti outw(port, val); 112e208dfa2Spirofti } 113e208dfa2Spirofti 114e208dfa2Spirofti static void 1156bf2980cSderaadt vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) 116e208dfa2Spirofti { 117e208dfa2Spirofti if (port >= 0x80 && port < 0x88) /* POST status register */ 118e208dfa2Spirofti return; 119e208dfa2Spirofti 120e208dfa2Spirofti outl(port, val); 121e208dfa2Spirofti } 122e208dfa2Spirofti 123e208dfa2Spirofti struct vga_post * 124e208dfa2Spirofti vga_post_init(int bus, int device, int function) 125e208dfa2Spirofti { 126e208dfa2Spirofti struct vga_post *sc; 127e208dfa2Spirofti vaddr_t iter; 128e208dfa2Spirofti struct vm_page *pg; 129e208dfa2Spirofti vaddr_t sys_image, sys_bios_data; 130e208dfa2Spirofti int err; 131e208dfa2Spirofti 132e208dfa2Spirofti sys_bios_data = uvm_km_valloc(kernel_map, PAGE_SIZE); 133e208dfa2Spirofti if (sys_bios_data == 0) 134e208dfa2Spirofti return NULL; 135e208dfa2Spirofti 136e208dfa2Spirofti sys_image = uvm_km_valloc(kernel_map, 1024 * 1024); 137e208dfa2Spirofti if (sys_image == 0) { 138e208dfa2Spirofti uvm_km_free(kernel_map, sys_bios_data, PAGE_SIZE); 139e208dfa2Spirofti return NULL; 140e208dfa2Spirofti } 141e208dfa2Spirofti sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 142e208dfa2Spirofti 143*7113f419Smiod TAILQ_INIT(&sc->ram_backing); 144e208dfa2Spirofti err = uvm_pglistalloc(BASE_MEMORY, 0, (paddr_t)-1, 0, 0, 145e208dfa2Spirofti &sc->ram_backing, BASE_MEMORY/PAGE_SIZE, UVM_PLA_WAITOK); 146e208dfa2Spirofti if (err) { 147e208dfa2Spirofti uvm_km_free(kernel_map, sc->sys_image, 1024 * 1024); 148e208dfa2Spirofti free(sc, M_DEVBUF); 149e208dfa2Spirofti return NULL; 150e208dfa2Spirofti } 151e208dfa2Spirofti 152e208dfa2Spirofti sc->sys_image = sys_image; 153e208dfa2Spirofti sc->emu.sys_private = sc; 154e208dfa2Spirofti 155e208dfa2Spirofti pmap_kenter_pa(sys_bios_data, 0, VM_PROT_READ); 156e208dfa2Spirofti pmap_update(pmap_kernel()); 157e208dfa2Spirofti memcpy((void *)sc->bios_data, (void *)sys_bios_data, PAGE_SIZE); 158e208dfa2Spirofti pmap_kremove(sys_bios_data, PAGE_SIZE); 159e208dfa2Spirofti uvm_km_free(kernel_map, sys_bios_data, PAGE_SIZE); 160e208dfa2Spirofti 161e208dfa2Spirofti iter = 0; 162e208dfa2Spirofti TAILQ_FOREACH(pg, &sc->ram_backing, pageq) { 163e208dfa2Spirofti pmap_kenter_pa(sc->sys_image + iter, VM_PAGE_TO_PHYS(pg), 164e208dfa2Spirofti VM_PROT_READ | VM_PROT_WRITE); 165e208dfa2Spirofti iter += PAGE_SIZE; 166e208dfa2Spirofti } 167*7113f419Smiod KASSERT(iter == BASE_MEMORY); 168e208dfa2Spirofti 169e208dfa2Spirofti for (iter = 640 * 1024; iter < 1024 * 1024; iter += PAGE_SIZE) 170e208dfa2Spirofti pmap_kenter_pa(sc->sys_image + iter, iter, 171e208dfa2Spirofti VM_PROT_READ | VM_PROT_WRITE); 172e208dfa2Spirofti pmap_update(pmap_kernel()); 173e208dfa2Spirofti 174e208dfa2Spirofti memset(&sc->emu, 0, sizeof(sc->emu)); 1756bf2980cSderaadt x86emu_init_default(&sc->emu); 176e208dfa2Spirofti sc->emu.emu_inb = vm86_emu_inb; 177e208dfa2Spirofti sc->emu.emu_inw = vm86_emu_inw; 178e208dfa2Spirofti sc->emu.emu_inl = vm86_emu_inl; 179e208dfa2Spirofti sc->emu.emu_outb = vm86_emu_outb; 180e208dfa2Spirofti sc->emu.emu_outw = vm86_emu_outw; 181e208dfa2Spirofti sc->emu.emu_outl = vm86_emu_outl; 182e208dfa2Spirofti 183e208dfa2Spirofti sc->emu.mem_base = (char *)sc->sys_image; 184e208dfa2Spirofti sc->emu.mem_size = 1024 * 1024; 185e208dfa2Spirofti 186e208dfa2Spirofti sc->initial_eax = bus * 256 + device * 8 + function; 187e208dfa2Spirofti #ifdef DDB 188e208dfa2Spirofti ddb_vgapostp = sc; 189e208dfa2Spirofti #endif 190e208dfa2Spirofti return sc; 191e208dfa2Spirofti } 192e208dfa2Spirofti 193e208dfa2Spirofti void 194e208dfa2Spirofti vga_post_call(struct vga_post *sc) 195e208dfa2Spirofti { 196e208dfa2Spirofti sc->emu.x86.R_EAX = sc->initial_eax; 197e208dfa2Spirofti sc->emu.x86.R_EDX = 0x00000080; 198e208dfa2Spirofti sc->emu.x86.R_DS = 0x0040; 199e208dfa2Spirofti sc->emu.x86.register_flags = 0x3200; 200e208dfa2Spirofti 201e208dfa2Spirofti memcpy((void *)sc->sys_image, sc->bios_data, PAGE_SIZE); 202e208dfa2Spirofti 203e208dfa2Spirofti /* stack is at the end of the first 64KB */ 204e208dfa2Spirofti sc->emu.x86.R_SS = 0; 205e208dfa2Spirofti sc->emu.x86.R_ESP = 0; 206e208dfa2Spirofti 207e208dfa2Spirofti /* Jump straight into the VGA BIOS POST code */ 2086bf2980cSderaadt x86emu_exec_call(&sc->emu, 0xc000, 0x0003); 209e208dfa2Spirofti } 210e208dfa2Spirofti 211e208dfa2Spirofti void 212e208dfa2Spirofti vga_post_free(struct vga_post *sc) 213e208dfa2Spirofti { 214e208dfa2Spirofti uvm_pglistfree(&sc->ram_backing); 215e208dfa2Spirofti pmap_kremove(sc->sys_image, 1024 * 1024); 216e208dfa2Spirofti uvm_km_free(kernel_map, sc->sys_image, 1024 * 1024); 217e208dfa2Spirofti pmap_update(pmap_kernel()); 218e208dfa2Spirofti free(sc, M_DEVBUF); 219e208dfa2Spirofti } 220e208dfa2Spirofti 221e208dfa2Spirofti #ifdef DDB 222e208dfa2Spirofti void 223e208dfa2Spirofti ddb_vgapost(void) 224e208dfa2Spirofti { 225e208dfa2Spirofti 226e208dfa2Spirofti if (ddb_vgapostp) 227e208dfa2Spirofti vga_post_call(ddb_vgapostp); 228e208dfa2Spirofti else 229e208dfa2Spirofti printf("ddb_vgapost: vga_post not initialized\n"); 230e208dfa2Spirofti } 231e208dfa2Spirofti #endif 232