diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/x86bios/x86bios.c | 379 | ||||
-rw-r--r-- | sys/compat/x86bios/x86bios.h | 113 | ||||
-rw-r--r-- | sys/compat/x86bios/x86bios_alloc.c | 81 | ||||
-rw-r--r-- | sys/conf/files.amd64 | 2 | ||||
-rw-r--r-- | sys/conf/files.i386 | 2 | ||||
-rw-r--r-- | sys/contrib/x86emu/x86emu_util.c | 211 | ||||
-rw-r--r-- | sys/dev/atkbdc/atkbd.c | 15 | ||||
-rw-r--r-- | sys/dev/dpms/dpms.c | 28 | ||||
-rw-r--r-- | sys/dev/fb/vesa.c | 794 | ||||
-rw-r--r-- | sys/dev/pci/vga_pci.c | 21 | ||||
-rw-r--r-- | sys/modules/dpms/Makefile | 2 | ||||
-rw-r--r-- | sys/modules/vesa/Makefile | 1 | ||||
-rw-r--r-- | sys/modules/x86bios/Makefile | 3 |
13 files changed, 944 insertions, 708 deletions
diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c index 1d1c48a..74c32a7 100644 --- a/sys/compat/x86bios/x86bios.c +++ b/sys/compat/x86bios/x86bios.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2009 Alex Keda <admin@lissyara.su> + * Copyright (c) 2009 Jung-uk Kim <jkim@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,7 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ #include <sys/cdefs.h> @@ -31,29 +31,153 @@ __FBSDID("$FreeBSD$"); #include "opt_x86bios.h" #include <sys/param.h> +#include <sys/bus.h> #include <sys/kernel.h> #include <sys/lock.h> +#include <sys/malloc.h> #include <sys/module.h> #include <sys/mutex.h> +#include <sys/proc.h> + +#include <contrib/x86emu/x86emu.h> +#include <contrib/x86emu/x86emu_regs.h> +#include <compat/x86bios/x86bios.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <machine/cpufunc.h> #include <vm/vm.h> #include <vm/pmap.h> -#include <machine/cpufunc.h> +#define X86BIOS_PAGE_SIZE 0x00001000 /* 4K */ -#include <contrib/x86emu/x86emu.h> -#include <contrib/x86emu/x86emu_regs.h> -#include <compat/x86bios/x86bios.h> +#define X86BIOS_IVT_SIZE 0x00000500 /* 1K + 256 (BDA) */ +#define X86BIOS_SEG_SIZE 0x00010000 /* 64K */ +#define X86BIOS_MEM_SIZE 0x00100000 /* 1M */ + +#define X86BIOS_IVT_BASE 0x00000000 +#define X86BIOS_RAM_BASE 0x00001000 +#define X86BIOS_ROM_BASE 0x000a0000 /* XXX EBDA? */ + +#define X86BIOS_ROM_SIZE (X86BIOS_MEM_SIZE - X86BIOS_ROM_BASE) -u_char *pbiosMem = NULL; -static u_char *pbiosStack = NULL; +#define X86BIOS_PAGES (X86BIOS_MEM_SIZE / X86BIOS_PAGE_SIZE) -int busySegMap[5]; +#define X86BIOS_R_DS _pad1 +#define X86BIOS_R_SS _pad2 static struct x86emu x86bios_emu; static struct mtx x86bios_lock; +static void *x86bios_ivt; +static void *x86bios_rom; +static void *x86bios_seg; + +static vm_offset_t *x86bios_map; + +static vm_paddr_t x86bios_seg_phys; + +static void * +x86bios_get_pages(uint32_t offset, size_t size) +{ + int i; + + if (offset + size > X86BIOS_MEM_SIZE) + return (NULL); + + i = offset / X86BIOS_PAGE_SIZE; + if (x86bios_map[i] != 0) + return ((void *)(x86bios_map[i] + offset - + i * X86BIOS_PAGE_SIZE)); + + return (NULL); +} + +static void +x86bios_set_pages(vm_offset_t va, vm_paddr_t pa, size_t size) +{ + int i, j; + + for (i = pa / X86BIOS_PAGE_SIZE, j = 0; + j < howmany(size, X86BIOS_PAGE_SIZE); i++, j++) + x86bios_map[i] = va + j * X86BIOS_PAGE_SIZE; +} + +static uint8_t +x86bios_emu_rdb(struct x86emu *emu, uint32_t addr) +{ + uint8_t *va; + + va = x86bios_get_pages(addr, sizeof(*va)); + if (va == NULL) + x86emu_halt_sys(emu); + + return (*va); +} + +static uint16_t +x86bios_emu_rdw(struct x86emu *emu, uint32_t addr) +{ + uint16_t *va; + + va = x86bios_get_pages(addr, sizeof(*va)); + if (va == NULL) + x86emu_halt_sys(emu); + + return (le16toh(*va)); +} + +static uint32_t +x86bios_emu_rdl(struct x86emu *emu, uint32_t addr) +{ + uint32_t *va; + + va = x86bios_get_pages(addr, sizeof(*va)); + if (va == NULL) + x86emu_halt_sys(emu); + + return (le32toh(*va)); +} + +static void +x86bios_emu_wrb(struct x86emu *emu, uint32_t addr, uint8_t val) +{ + uint8_t *va; + + va = x86bios_get_pages(addr, sizeof(*va)); + if (va == NULL) + x86emu_halt_sys(emu); + + *va = val; +} + +static void +x86bios_emu_wrw(struct x86emu *emu, uint32_t addr, uint16_t val) +{ + uint16_t *va; + + va = x86bios_get_pages(addr, sizeof(*va)); + if (va == NULL) + x86emu_halt_sys(emu); + + *va = htole16(val); +} + +static void +x86bios_emu_wrl(struct x86emu *emu, uint32_t addr, uint32_t val) +{ + uint32_t *va; + + va = x86bios_get_pages(addr, sizeof(*va)); + if (va == NULL) + x86emu_halt_sys(emu); + + *va = htole32(val); +} + static uint8_t x86bios_emu_inb(struct x86emu *emu, uint16_t port) { @@ -62,6 +186,7 @@ x86bios_emu_inb(struct x86emu *emu, uint16_t port) return (0); if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); + return (inb(port)); } @@ -71,6 +196,7 @@ x86bios_emu_inw(struct x86emu *emu, uint16_t port) if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); + return (inw(port)); } @@ -80,6 +206,7 @@ x86bios_emu_inl(struct x86emu *emu, uint16_t port) if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); + return (inl(port)); } @@ -91,6 +218,7 @@ x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) return; if (port >= 0x80 && port < 0x88) /* POST status register */ return; + outb(port, val); } @@ -100,6 +228,7 @@ x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) if (port >= 0x80 && port < 0x88) /* POST status register */ return; + outw(port, val); } @@ -109,9 +238,109 @@ x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) if (port >= 0x80 && port < 0x88) /* POST status register */ return; + outl(port, val); } +static void +x86bios_emu_get_intr(struct x86emu *emu, int intno) +{ + uint16_t *sp; + uint32_t iv; + + emu->x86.R_SP -= 6; + + sp = (uint16_t *)((vm_offset_t)x86bios_seg + emu->x86.R_SP); + sp[0] = htole16(emu->x86.R_IP); + sp[1] = htole16(emu->x86.R_CS); + sp[2] = htole16(emu->x86.R_FLG); + + iv = x86bios_get_intr(intno); + emu->x86.R_IP = iv & 0x000f; + emu->x86.R_CS = (iv >> 12) & 0xffff; + emu->x86.R_FLG &= ~(F_IF | F_TF); +} + +void * +x86bios_alloc(uint32_t *offset, size_t size) +{ + void *vaddr; + + if (offset == NULL || size == 0) + return (NULL); + + vaddr = contigmalloc(size, M_DEVBUF, M_NOWAIT, X86BIOS_RAM_BASE, + X86BIOS_ROM_BASE, X86BIOS_PAGE_SIZE, 0); + if (vaddr != NULL) { + *offset = vtophys(vaddr); + x86bios_set_pages((vm_offset_t)vaddr, *offset, size); + } + + return (vaddr); +} + +void +x86bios_free(void *addr, size_t size) +{ + vm_paddr_t paddr; + + if (addr == NULL || size == 0) + return; + + paddr = vtophys(addr); + if (paddr < X86BIOS_RAM_BASE || paddr >= X86BIOS_ROM_BASE || + paddr % X86BIOS_PAGE_SIZE != 0) + return; + + bzero(x86bios_map + paddr / X86BIOS_PAGE_SIZE, + sizeof(*x86bios_map) * howmany(size, X86BIOS_PAGE_SIZE)); + contigfree(addr, size, M_DEVBUF); +} + +void +x86bios_init_regs(struct x86regs *regs) +{ + + bzero(regs, sizeof(*regs)); + regs->X86BIOS_R_DS = regs->X86BIOS_R_SS = x86bios_seg_phys >> 4; +} + +void +x86bios_call(struct x86regs *regs, uint16_t seg, uint16_t off) +{ + + if (x86bios_map == NULL) + return; + + if (bootverbose) + printf("Calling 0x%05x (ax=0x%04x bx=0x%04x " + "cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n", + (seg << 4) + off, regs->R_AX, regs->R_BX, regs->R_CX, + regs->R_DX, regs->R_ES, regs->R_DI); + + mtx_lock_spin(&x86bios_lock); + memcpy(&x86bios_emu.x86, regs, sizeof(*regs)); + x86emu_exec_call(&x86bios_emu, seg, off); + memcpy(regs, &x86bios_emu.x86, sizeof(*regs)); + mtx_unlock_spin(&x86bios_lock); + + if (bootverbose) + printf("Exiting 0x%05x (ax=0x%04x bx=0x%04x " + "cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n", + (seg << 4) + off, regs->R_AX, regs->R_BX, regs->R_CX, + regs->R_DX, regs->R_ES, regs->R_DI); +} + +uint32_t +x86bios_get_intr(int intno) +{ + uint32_t *iv; + + iv = (uint32_t *)((vm_offset_t)x86bios_ivt + intno * 4); + + return (le32toh(*iv)); +} + void x86bios_intr(struct x86regs *regs, int intno) { @@ -119,6 +348,9 @@ x86bios_intr(struct x86regs *regs, int intno) if (intno < 0 || intno > 255) return; + if (x86bios_map == NULL) + return; + if (bootverbose) printf("Calling int 0x%x (ax=0x%04x bx=0x%04x " "cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n", @@ -126,11 +358,9 @@ x86bios_intr(struct x86regs *regs, int intno) regs->R_DX, regs->R_ES, regs->R_DI); 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) @@ -141,24 +371,112 @@ x86bios_intr(struct x86regs *regs, int intno) } void * -x86bios_offset(uint32_t offs) +x86bios_offset(uint32_t offset) +{ + + return (x86bios_get_pages(offset, 1)); +} + +void * +x86bios_get_orm(uint32_t offset) +{ + uint8_t *p; + + /* Does the shadow ROM contain BIOS POST code for x86? */ + p = x86bios_offset(offset); + if (p == NULL || p[0] != 0x55 || p[1] != 0xaa || p[3] != 0xe9) + return (NULL); + + return (p); +} + +int +x86bios_match_device(uint32_t offset, device_t dev) +{ + uint8_t *p; + uint16_t device, vendor; + uint8_t class, progif, subclass; + + /* Does the shadow ROM contain BIOS POST code for x86? */ + p = x86bios_get_orm(offset); + if (p == NULL) + return (0); + + /* Does it contain PCI data structure? */ + p += le16toh(*(uint16_t *)(p + 0x18)); + if (bcmp(p, "PCIR", 4) != 0 || + le16toh(*(uint16_t *)(p + 0x0a)) < 0x18 || *(p + 0x14) != 0) + return (0); + + /* Does it match the vendor, device, and classcode? */ + vendor = le16toh(*(uint16_t *)(p + 0x04)); + device = le16toh(*(uint16_t *)(p + 0x06)); + progif = *(p + 0x0d); + subclass = *(p + 0x0e); + class = *(p + 0x0f); + if (vendor != pci_get_vendor(dev) || device != pci_get_device(dev) || + class != pci_get_class(dev) || subclass != pci_get_subclass(dev) || + progif != pci_get_progif(dev)) + return (0); + + return (1); +} + +static __inline int +x86bios_map_mem(void) +{ + + x86bios_ivt = pmap_mapdev(X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE); + if (x86bios_ivt == NULL) + return (1); + x86bios_rom = pmap_mapdev(X86BIOS_ROM_BASE, X86BIOS_ROM_SIZE); + if (x86bios_rom == NULL) { + pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); + return (1); + } + x86bios_seg = contigmalloc(X86BIOS_SEG_SIZE, M_DEVBUF, M_WAITOK, + X86BIOS_RAM_BASE, X86BIOS_ROM_BASE, X86BIOS_PAGE_SIZE, 0); + x86bios_seg_phys = vtophys(x86bios_seg); + + return (0); +} + +static __inline void +x86bios_unmap_mem(void) { - return (pbiosMem + offs); + pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); + pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); + contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF); } static void x86bios_init(void *arg __unused) { - int offs; + int i; mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN); - /* Can pbiosMem be NULL here? */ - pbiosMem = pmap_mapbios(0x0, MAPPED_MEMORY_SIZE); + if (x86bios_map_mem() != 0) + return; + + x86bios_map = malloc(sizeof(*x86bios_map) * X86BIOS_PAGES, M_DEVBUF, + M_WAITOK | M_ZERO); + x86bios_set_pages((vm_offset_t)x86bios_ivt, X86BIOS_IVT_BASE, + X86BIOS_IVT_SIZE); + x86bios_set_pages((vm_offset_t)x86bios_rom, X86BIOS_ROM_BASE, + X86BIOS_ROM_SIZE); + x86bios_set_pages((vm_offset_t)x86bios_seg, x86bios_seg_phys, + X86BIOS_SEG_SIZE); - memset(&x86bios_emu, 0, sizeof(x86bios_emu)); - x86emu_init_default(&x86bios_emu); + bzero(&x86bios_emu, sizeof(x86bios_emu)); + + x86bios_emu.emu_rdb = x86bios_emu_rdb; + x86bios_emu.emu_rdw = x86bios_emu_rdw; + x86bios_emu.emu_rdl = x86bios_emu_rdl; + x86bios_emu.emu_wrb = x86bios_emu_wrb; + x86bios_emu.emu_wrw = x86bios_emu_wrw; + x86bios_emu.emu_wrl = x86bios_emu_wrl; x86bios_emu.emu_inb = x86bios_emu_inb; x86bios_emu.emu_inw = x86bios_emu_inw; @@ -167,23 +485,24 @@ x86bios_init(void *arg __unused) x86bios_emu.emu_outw = x86bios_emu_outw; x86bios_emu.emu_outl = x86bios_emu_outl; - x86bios_emu.mem_base = (char *)pbiosMem; - x86bios_emu.mem_size = MAPPED_MEMORY_SIZE; - - memset(busySegMap, 0, sizeof(busySegMap)); - - pbiosStack = x86bios_alloc(1, &offs); + for (i = 0; i < 256; i++) + x86bios_emu._x86emu_intrTab[i] = x86bios_emu_get_intr; } static void x86bios_uninit(void *arg __unused) { + vm_offset_t *map = x86bios_map; - x86bios_free(pbiosStack, 1); + mtx_lock_spin(&x86bios_lock); + if (x86bios_map != NULL) { + free(x86bios_map, M_DEVBUF); + x86bios_map = NULL; + } + mtx_unlock_spin(&x86bios_lock); - if (pbiosMem) - pmap_unmapdev((vm_offset_t)pbiosMem, - MAPPED_MEMORY_SIZE); + if (map != NULL) + x86bios_unmap_mem(); mtx_destroy(&x86bios_lock); } @@ -191,7 +510,6 @@ x86bios_uninit(void *arg __unused) static int x86bios_modevent(module_t mod __unused, int type, void *data __unused) { - int err = 0; switch (type) { case MOD_LOAD: @@ -201,11 +519,10 @@ x86bios_modevent(module_t mod __unused, int type, void *data __unused) x86bios_uninit(NULL); break; default: - err = ENOTSUP; - break; + return (ENOTSUP); } - return (err); + return (0); } static moduledata_t x86bios_mod = { diff --git a/sys/compat/x86bios/x86bios.h b/sys/compat/x86bios/x86bios.h index 8d46d5b..4ed15e0 100644 --- a/sys/compat/x86bios/x86bios.h +++ b/sys/compat/x86bios/x86bios.h @@ -23,49 +23,51 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD$ */ /* * x86 registers were borrowed from x86emu.h x86emu_regs.h * for compatability. - * - * $FreeBSD$ */ #ifndef _X86BIOS_H_ -#define _X86BIOS_H_ +#define _X86BIOS_H_ -#include <sys/types.h> #include <sys/endian.h> #include <sys/systm.h> +#include <sys/types.h> #ifdef __BIG_ENDIAN__ struct x86_register32 { - uint32_t e_reg; + uint32_t e_reg; }; struct x86_register16 { - uint16_t filler0; - uint16_t x_reg; + uint16_t filler0; + uint16_t x_reg; }; struct x86_register8 { - uint8_t filler0, filler1; - uint8_t h_reg, l_reg; + uint8_t filler0; + uint8_t filler1; + uint8_t h_reg; + uint8_t l_reg; }; #else /* !__BIG_ENDIAN__ */ struct x86_register32 { - uint32_t e_reg; + uint32_t e_reg; }; struct x86_register16 { - uint16_t x_reg; + uint16_t x_reg; }; struct x86_register8 { - uint8_t l_reg, h_reg; + uint8_t l_reg; + uint8_t h_reg; }; #endif /* __BIG_ENDIAN__ */ @@ -77,19 +79,19 @@ union x86_register { }; struct x86regs { - uint16_t padding; /* CS is unused. */ - uint16_t register_ds; + uint16_t _pad0; /* CS */ + uint16_t _pad1; /* DS */ uint16_t register_es; uint16_t register_fs; uint16_t register_gs; - uint16_t register_ss; + uint16_t _pad2; /* SS */ uint32_t register_flags; union x86_register register_a; union x86_register register_b; union x86_register register_c; union x86_register register_d; - union x86_register register_sp; + union x86_register _pad3; /* SP */ union x86_register register_bp; union x86_register register_si; union x86_register register_di; @@ -98,60 +100,57 @@ struct x86regs { typedef struct x86regs x86regs_t; /* 8 bit registers */ -#define R_AH register_a.I8_reg.h_reg -#define R_AL register_a.I8_reg.l_reg -#define R_BH register_b.I8_reg.h_reg -#define R_BL register_b.I8_reg.l_reg -#define R_CH register_c.I8_reg.h_reg -#define R_CL register_c.I8_reg.l_reg -#define R_DH register_d.I8_reg.h_reg -#define R_DL register_d.I8_reg.l_reg +#define R_AH register_a.I8_reg.h_reg +#define R_AL register_a.I8_reg.l_reg +#define R_BH register_b.I8_reg.h_reg +#define R_BL register_b.I8_reg.l_reg +#define R_CH register_c.I8_reg.h_reg +#define R_CL register_c.I8_reg.l_reg +#define R_DH register_d.I8_reg.h_reg +#define R_DL register_d.I8_reg.l_reg /* 16 bit registers */ -#define R_AX register_a.I16_reg.x_reg -#define R_BX register_b.I16_reg.x_reg -#define R_CX register_c.I16_reg.x_reg -#define R_DX register_d.I16_reg.x_reg +#define R_AX register_a.I16_reg.x_reg +#define R_BX register_b.I16_reg.x_reg +#define R_CX register_c.I16_reg.x_reg +#define R_DX register_d.I16_reg.x_reg /* 32 bit extended registers */ -#define R_EAX register_a.I32_reg.e_reg -#define R_EBX register_b.I32_reg.e_reg -#define R_ECX register_c.I32_reg.e_reg -#define R_EDX register_d.I32_reg.e_reg +#define R_EAX register_a.I32_reg.e_reg +#define R_EBX register_b.I32_reg.e_reg +#define R_ECX register_c.I32_reg.e_reg +#define R_EDX register_d.I32_reg.e_reg /* special registers */ -#define R_SP register_sp.I16_reg.x_reg -#define R_BP register_bp.I16_reg.x_reg -#define R_SI register_si.I16_reg.x_reg -#define R_DI register_di.I16_reg.x_reg -#define R_FLG register_flags +#define R_BP register_bp.I16_reg.x_reg +#define R_SI register_si.I16_reg.x_reg +#define R_DI register_di.I16_reg.x_reg +#define R_FLG register_flags /* special registers */ -#define R_ESP register_sp.I32_reg.e_reg -#define R_EBP register_bp.I32_reg.e_reg -#define R_ESI register_si.I32_reg.e_reg -#define R_EDI register_di.I32_reg.e_reg -#define R_EFLG register_flags +#define R_EBP register_bp.I32_reg.e_reg +#define R_ESI register_si.I32_reg.e_reg +#define R_EDI register_di.I32_reg.e_reg +#define R_EFLG register_flags /* segment registers */ -#define R_DS register_ds -#define R_SS register_ss -#define R_ES register_es -#define R_FS register_fs -#define R_GS register_gs - -#define SEG_ADDR(x) (((x) >> 4) & 0x00F000) -#define SEG_OFF(x) ((x) & 0x0FFFF) -#define FARP(x) ((le32toh(x) & 0xffff) + ((le32toh(x) >> 12) & 0xffff00)) +#define R_ES register_es +#define R_FS register_fs +#define R_GS register_gs -#define MAPPED_MEMORY_SIZE (1024 * 1024) -#define PAGE_RESERV (4096 * 5) +#define X86BIOS_PHYSTOSEG(x) (((x) >> 4) & 0xffff) +#define X86BIOS_PHYSTOOFF(x) ((x) & 0x000f) __BEGIN_DECLS -void *x86bios_alloc(int count, int *segs); -void x86bios_free(void *pbuf, int count); -void x86bios_intr(struct x86regs *regs, int intno); -void *x86bios_offset(uint32_t offs); +void *x86bios_alloc(uint32_t *offset, size_t size); +void x86bios_call(struct x86regs *regs, uint16_t seg, uint16_t off); +void x86bios_free(void *addr, size_t size); +uint32_t x86bios_get_intr(int intno); +void *x86bios_get_orm(uint32_t offset); +void x86bios_init_regs(struct x86regs *regs); +void x86bios_intr(struct x86regs *regs, int intno); +int x86bios_match_device(uint32_t offset, device_t dev); +void *x86bios_offset(uint32_t offset); __END_DECLS #endif /* !_X86BIOS_H_ */ diff --git a/sys/compat/x86bios/x86bios_alloc.c b/sys/compat/x86bios/x86bios_alloc.c deleted file mode 100644 index 0a364e7..0000000 --- a/sys/compat/x86bios/x86bios_alloc.c +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * Copyright (C) 1999 Egbert Eich - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of the authors not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The authors makes no - * representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * xserver/hw/xfree86/int10/generic.c - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> - -#include <compat/x86bios/x86bios.h> - -extern u_char *pbiosMem; -extern int busySegMap[5]; - -void * -x86bios_alloc(int count, int *segs) -{ - int i; - int j; - - /* find the free segblock of page */ - for (i = 0; i < (PAGE_RESERV - count); i++) - { - if (busySegMap[i] == 0) - { - /* find the capacity of segblock */ - for (j = i; j < (i + count); j++) - { - if (busySegMap[j] == 1) - break; - } - - if (j == (i + count)) - break; - i += count; - } - } - - if (i == (PAGE_RESERV - count)) - return NULL; - - /* make the segblock is used */ - for (j = i; j < (i + count); j++) - busySegMap[i] = 1; - - *segs = i * 4096; - - return (pbiosMem + *segs); -} - -void -x86bios_free(void *pbuf, int count) -{ - int i; - int busySeg; - - busySeg = ((u_char *)pbuf - pbiosMem) / 4096; - - for (i = busySeg; i < (busySeg + count); i++) - busySegMap[i] = 0; -} diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 6fda086..fbf4d28 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -301,6 +301,4 @@ libkern/memset.c standard # x86 real mode BIOS emulator, required by atkbdc/dpms/vesa # compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa -compat/x86bios/x86bios_alloc.c optional x86bios | atkbd | dpms | vesa contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa -contrib/x86emu/x86emu_util.c optional x86bios | atkbd | dpms | vesa diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 34d190a..839955b 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -385,6 +385,4 @@ i386/xbox/pic16l.s optional xbox # x86 real mode BIOS emulator, required by atkbdc/dpms/vesa # compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa -compat/x86bios/x86bios_alloc.c optional x86bios | atkbd | dpms | vesa contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa -contrib/x86emu/x86emu_util.c optional x86bios | atkbd | dpms | vesa diff --git a/sys/contrib/x86emu/x86emu_util.c b/sys/contrib/x86emu/x86emu_util.c deleted file mode 100644 index 4172f94..0000000 --- a/sys/contrib/x86emu/x86emu_util.c +++ /dev/null @@ -1,211 +0,0 @@ -/* $OpenBSD: x86emu_util.c,v 1.5 2009/06/18 14:19:21 pirofti Exp $ */ -/* $NetBSD: x86emu_util.c,v 1.2 2007/12/04 17:32:22 joerg Exp $ */ - -/* - * - * Realmode X86 Emulator Library - * - * Copyright (C) 1996-1999 SciTech Software, Inc. - * Copyright (C) David Mosberger-Tang - * Copyright (C) 1999 Egbert Eich - * Copyright (C) 2007 Joerg Sonnenberger - * - * ======================================================================== - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of the authors not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The authors makes no - * representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/endian.h> - -#include <contrib/x86emu/x86emu.h> -#include <contrib/x86emu/x86emu_regs.h> - - - -/* - * PARAMETERS: - * addr - Emulator memory address to read - * - * RETURNS: - * Byte value read from emulator memory. - * - * REMARKS: - * Reads a byte value from the emulator memory. - */ -static uint8_t -rdb(struct x86emu *emu, uint32_t addr) -{ - if (addr > emu->mem_size - 1) - x86emu_halt_sys(emu); - return emu->mem_base[addr]; -} - -/* - * PARAMETERS: - * addr - Emulator memory address to read - * - * RETURNS: - * Word value read from emulator memory. - * - * REMARKS: - * Reads a word value from the emulator memory. - */ -static uint16_t -rdw(struct x86emu *emu, uint32_t addr) -{ - if (addr > emu->mem_size - 2) - x86emu_halt_sys(emu); -#ifdef __STRICT_ALIGNMENT - if (addr & 1) { - u_int8_t *a = emu->mem_base + addr; - u_int16_t r; - - r = ((*(a + 0) << 0) & 0x00ff) | - ((*(a + 1) << 8) & 0xff00); - return r; - } else - return le32toh(*(u_int32_t *)(emu->mem_base + addr)); -#else - return le16toh(*(u_int16_t *)(emu->mem_base + addr)); -#endif -} - -/* - * PARAMETERS: - * addr - Emulator memory address to read - * - * RETURNS: - * Long value read from emulator memory. - * REMARKS: - * Reads a long value from the emulator memory. - */ -static uint32_t -rdl(struct x86emu *emu, uint32_t addr) -{ - if (addr > emu->mem_size - 4) - x86emu_halt_sys(emu); -#ifdef __STRICT_ALIGNMENT - if (addr & 3) { - u_int8_t *a = emu->mem_base + addr; - u_int32_t r; - - r = ((*(a + 0) << 0) & 0x000000ff) | - ((*(a + 1) << 8) & 0x0000ff00) | - ((*(a + 2) << 16) & 0x00ff0000) | - ((*(a + 3) << 24) & 0xff000000); - return r; - } else - return le32toh(*(u_int32_t *)(emu->mem_base + addr)); -#else - return le32toh(*(u_int32_t *)(emu->mem_base + addr)); -#endif -} - -/* - * PARAMETERS: - * addr - Emulator memory address to read - * val - Value to store - * - * REMARKS: - * Writes a byte value to emulator memory. - */ -static void -wrb(struct x86emu *emu, uint32_t addr, uint8_t val) -{ - if (addr > emu->mem_size - 1) - x86emu_halt_sys(emu); - emu->mem_base[addr] = val; -} - -/* - * PARAMETERS: - * addr - Emulator memory address to read - * val - Value to store - * - * REMARKS: - * Writes a word value to emulator memory. - */ -static void -wrw(struct x86emu *emu, uint32_t addr, uint16_t val) -{ - if (addr > emu->mem_size - 2) - x86emu_halt_sys(emu); -#ifdef __STRICT_ALIGNMENT - if (addr & 1) { - u_int8_t *a = emu->mem_base + addr; - - *((a + 0)) = (val >> 0) & 0xff; - *((a + 1)) = (val >> 8) & 0xff; - } else - *((u_int16_t *)(emu->mem_base + addr)) = htole16(val); -#else - *((u_int16_t *)(emu->mem_base + addr)) = htole16(val); -#endif -} - -/* - * PARAMETERS: - * addr - Emulator memory address to read - * val - Value to store - * - * REMARKS: - * Writes a long value to emulator memory. - */ -static void -wrl(struct x86emu *emu, uint32_t addr, uint32_t val) -{ - if (addr > emu->mem_size - 4) - x86emu_halt_sys(emu); -#ifdef __STRICT_ALIGNMENT - if (addr & 3) { - u_int8_t *a = emu->mem_base + addr; - - *((a + 0) = (val >> 0) & 0xff; - *((a + 1) = (val >> 8) & 0xff; - *((a + 2) = (val >> 16) & 0xff; - *((a + 3) = (val >> 24) & 0xff; - } else - *((u_int32_t *)(emu->mem_base + addr)) = htole32(val); -#else - *((u_int32_t *)(emu->mem_base + addr)) = htole32(val); -#endif -} - -/* Setup */ - -void -x86emu_init_default(struct x86emu *emu) -{ - int i; - - emu->emu_rdb = rdb; - emu->emu_rdw = rdw; - emu->emu_rdl = rdl; - emu->emu_wrb = wrb; - emu->emu_wrw = wrw; - emu->emu_wrl = wrl; - - for (i = 0; i < 256; i++) - emu->_x86emu_intrTab[i] = NULL; -} diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c index 59d9632..600020f 100644 --- a/sys/dev/atkbdc/atkbd.c +++ b/sys/dev/atkbdc/atkbd.c @@ -1091,32 +1091,35 @@ get_typematic(keyboard_t *kbd) { #if defined(__i386__) || defined(__amd64__) /* - * Only some systems allow us to retrieve the keyboard repeat + * Only some systems allow us to retrieve the keyboard repeat * rate previously set via the BIOS... */ x86regs_t regs; uint8_t *p; + if (x86bios_get_intr(0x15) == 0 || x86bios_get_intr(0x16) == 0) + return (ENODEV); + /* Is BIOS system configuration table supported? */ - bzero(®s, sizeof(regs)); + x86bios_init_regs(®s); regs.R_AH = 0xc0; x86bios_intr(®s, 0x15); if ((regs.R_FLG & PSL_C) != 0 || regs.R_AH != 0) return (ENODEV); - /* Is int 16, function 0x09 supported? */ + /* Is int 0x16, function 0x09 supported? */ p = x86bios_offset((regs.R_ES << 4) + regs.R_BX); if (readw(p) < 5 || (readb(p + 6) & 0x40) == 0) return (ENODEV); - /* Is int 16, function 0x0306 supported? */ - bzero(®s, sizeof(regs)); + /* Is int 0x16, function 0x0306 supported? */ + x86bios_init_regs(®s); regs.R_AH = 0x09; x86bios_intr(®s, 0x16); if ((regs.R_AL & 0x08) == 0) return (ENODEV); - bzero(®s, sizeof(regs)); + x86bios_init_regs(®s); regs.R_AX = 0x0306; x86bios_intr(®s, 0x16); kbd->kb_delay1 = typematic_delay(regs.R_BH << 5); diff --git a/sys/dev/dpms/dpms.c b/sys/dev/dpms/dpms.c index c0476c5..58e2f37 100644 --- a/sys/dev/dpms/dpms.c +++ b/sys/dev/dpms/dpms.c @@ -125,13 +125,13 @@ static void dpms_identify(driver_t *driver, device_t parent) { - /* - * XXX: The DPMS VBE only allows for manipulating a single - * monitor, but we don't know which one. Just attach to the - * first vgapci(4) device we encounter and hope it is the - * right one. - */ - if (devclass_get_device(dpms_devclass, 0) == NULL) + /* The DPMS VBE only allows for manipulating a single monitor. */ + if (devclass_get_device(dpms_devclass, 0) != NULL) + return; + + if ((x86bios_match_device(0xc0000, parent) && + device_get_flags(parent) != 0) || + x86bios_get_orm(0xc0000) != NULL) device_add_child(parent, "dpms", 0); } @@ -172,8 +172,11 @@ dpms_detach(device_t dev) static int dpms_suspend(device_t dev) { + struct dpms_softc *sc; - dpms_set_state(DPMS_OFF); + sc = device_get_softc(dev); + if ((sc->dpms_supported_states & DPMS_OFF) != 0) + dpms_set_state(DPMS_OFF); return (0); } @@ -192,15 +195,16 @@ dpms_call_bios(int subfunction, int *bh) { x86regs_t regs; - bzero(®s, sizeof(regs)); + if (x86bios_get_intr(0x10) == 0) + return (ENXIO); + + x86bios_init_regs(®s); regs.R_AX = VBE_DPMS_FUNCTION; regs.R_BL = subfunction; regs.R_BH = *bh; - regs.R_ES = 0; - regs.R_DI = 0; x86bios_intr(®s, 0x10); - if ((regs.R_EAX & 0xffff) != 0x004f) + if (regs.R_AX != 0x004f) return (ENXIO); *bh = regs.R_BH; diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c index 8a61368..11b9598 100644 --- a/sys/dev/fb/vesa.c +++ b/sys/dev/fb/vesa.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #ifndef VGA_NO_MODE_CHANGE #include <sys/param.h> +#include <sys/bus.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/module.h> @@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$"); #include <dev/fb/fbreg.h> #include <dev/fb/vgareg.h> +#include <dev/pci/pcivar.h> + #include <isa/isareg.h> #include <compat/x86bios/x86bios.h> @@ -160,7 +163,9 @@ static char *vesa_revstr = NULL; #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) static int int10_set_mode(int mode); +static int vesa_bios_post(void); static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode); +static int vesa_bios_get_current_mode(void); static int vesa_bios_set_mode(int mode); static int vesa_bios_get_dac(void); static int vesa_bios_set_dac(int bits); @@ -222,12 +227,62 @@ int10_set_mode(int mode) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x0000 | mode; + x86bios_init_regs(®s); + regs.R_AL = mode; x86bios_intr(®s, 0x10); - return 0; + return (0); +} + +static int +vesa_bios_post(void) +{ + x86regs_t regs; + devclass_t dc; + device_t *devs; + device_t dev; + int count, i, is_pci; + + if (x86bios_get_orm(0xc0000) == NULL) + return (1); + + dev = NULL; + is_pci = 0; + + /* Find the matching PCI video controller. */ + dc = devclass_find("vgapci"); + if (dc != NULL && devclass_get_devices(dc, &devs, &count) == 0) { + for (dev = NULL, i = 0; dev == NULL && i < count; devs++, i++) + if (x86bios_match_device(0xc0000, *devs) && + device_get_flags(*devs) != 0) { + dev = *devs; + is_pci = 1; + break; + } + free(devs, M_TEMP); + } + + /* Try VGA if a PCI device is not found. */ + if (dev == NULL) { + dc = devclass_find(VGA_DRIVER_NAME); + if (dc != NULL) + dev = devclass_get_device(dc, 0); + } + + if (bootverbose) + printf("%s: calling BIOS POST\n", + dev == NULL ? "VESA" : device_get_nameunit(dev)); + + x86bios_init_regs(®s); + if (is_pci) { + regs.R_AH = pci_get_bus(dev); + regs.R_AL = (pci_get_slot(dev) << 3) | + (pci_get_function(dev) & 0x07); + } + regs.R_DL = 0x80; + x86bios_call(®s, 0xc000, 0x0003); + return (0); } /* VESA BIOS calls */ @@ -235,30 +290,47 @@ static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode) { x86regs_t regs; - int offs; - u_char *buf; + uint32_t offs; + void *buf; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f01; - regs.R_ECX = mode; + buf = x86bios_alloc(&offs, sizeof(*vmode)); + if (buf == NULL) + return (1); - buf = (u_char *)x86bios_alloc(1, &offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f01; + regs.R_CX = mode; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - { - x86bios_free(buf, 1); - return 1; + if (regs.R_AX != 0x004f) { + x86bios_free(buf, sizeof(*vmode)); + return (1); } bcopy(buf, vmode, sizeof(*vmode)); - x86bios_free(buf, 1); + x86bios_free(buf, sizeof(*vmode)); - return 0; + return (0); +} + +static int +vesa_bios_get_current_mode(void) +{ + x86regs_t regs; + + x86bios_init_regs(®s); + regs.R_AX = 0x4f03; + + x86bios_intr(®s, 0x10); + + if (regs.R_AX != 0x004f) + return (-1); + + return (regs.R_BX); } static int @@ -266,13 +338,13 @@ vesa_bios_set_mode(int mode) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f02; - regs.R_EBX = mode; + x86bios_init_regs(®s); + regs.R_AX = 0x4f02; + regs.R_BX = mode; x86bios_intr(®s, 0x10); - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } static int @@ -280,16 +352,16 @@ vesa_bios_get_dac(void) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f08; - regs.R_EBX = 1; + x86bios_init_regs(®s); + regs.R_AX = 0x4f08; + regs.R_BL = 1; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 6; + if (regs.R_AX != 0x004f) + return (6); - return ((regs.R_EBX >> 8) & 0x00ff); + return (regs.R_BH); } static int @@ -297,43 +369,45 @@ vesa_bios_set_dac(int bits) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f08; - regs.R_EBX = (bits << 8); + x86bios_init_regs(®s); + regs.R_AX = 0x4f08; + /* regs.R_BL = 0; */ + regs.R_BH = bits; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 6; + if (regs.R_AX != 0x004f) + return (6); - return ((regs.R_EBX >> 8) & 0x00ff); + return (regs.R_BH); } static int vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 1; - regs.R_ECX = colors; - regs.R_EDX = start; + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); - p = (u_char *)x86bios_alloc(1, &offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + regs.R_BL = 1; + regs.R_CX = colors; + regs.R_DX = start; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - { - x86bios_free(p, 1); - return 1; + if (regs.R_AX != 0x004f) { + x86bios_free(p, colors * 4); + return (1); } bits = 8 - bits; @@ -342,9 +416,9 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) palette[i*3 + 1] = p[i*4 + 1] << bits; palette[i*3 + 2] = p[i*4] << bits; } + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - return 0; + return (0); } static int @@ -352,27 +426,28 @@ vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 1; - regs.R_ECX = colors; - regs.R_EDX = start; + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); - p = (u_char *)x86bios_alloc(1, &offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + regs.R_BL = 1; + regs.R_CX = colors; + regs.R_DX = start; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - { - x86bios_free(p, 1); - return 1; + if (regs.R_AX != 0x004f) { + x86bios_free(p, colors * 4); + return (1); } bits = 8 - bits; @@ -381,20 +456,31 @@ vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, g[i] = p[i*4 + 1] << bits; b[i] = p[i*4] << bits; } + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - return 0; + return (0); } static int vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - p = (u_char *)x86bios_alloc(1, &offs); + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); + + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + /* regs.R_BL = 0; */ + regs.R_CX = colors; + regs.R_DX = start; + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -403,21 +489,10 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) p[i*4 + 2] = palette[i*3] >> bits; p[i*4 + 3] = 0; } - - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 0; - regs.R_ECX = colors; - regs.R_EDX = start; - - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); - x86bios_intr(®s, 0x10); + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } #ifdef notyet @@ -426,11 +501,22 @@ vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - p = (u_char *)x86bios_alloc(1, &offs); + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); + + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + /* regs.R_BL = 0; */ + regs.R_CX = colors; + regs.R_DX = start; + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -439,21 +525,10 @@ vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, p[i*4 + 2] = r[i] >> bits; p[i*4 + 3] = 0; } - - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 0; - regs.R_ECX = colors; - regs.R_EDX = start; - - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); - x86bios_intr(®s, 0x10); + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } #endif @@ -462,48 +537,55 @@ vesa_bios_state_buf_size(void) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f04; - regs.R_ECX = STATE_ALL; - regs.R_EDX = STATE_SIZE; + x86bios_init_regs(®s); + regs.R_AX = 0x4f04; + /* regs.R_DL = STATE_SIZE; */ + regs.R_CX = STATE_ALL; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 0; + if (regs.R_AX != 0x004f) + return (0); - return regs.R_BX * 64; + return (regs.R_BX * 64); } static int vesa_bios_save_restore(int code, void *p, size_t size) { x86regs_t regs; - int offs; - u_char *buf; + uint32_t offs; + void *buf; if (size > VESA_BIOS_BUFSIZE) return (1); - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f04; - regs.R_ECX = STATE_ALL; - regs.R_EDX = code; - - buf = (u_char *)x86bios_alloc(1, &offs); - - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); - - bcopy(p, buf, size); - - x86bios_intr(®s, 0x10); - - bcopy(buf, p, size); + if (code != STATE_SAVE && code != STATE_LOAD) + return (1); - x86bios_free(p, 1); + buf = x86bios_alloc(&offs, size); + + x86bios_init_regs(®s); + regs.R_AX = 0x4f04; + regs.R_DL = code; + regs.R_CX = STATE_ALL; + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_BX = X86BIOS_PHYSTOOFF(offs); + + switch (code) { + case STATE_SAVE: + x86bios_intr(®s, 0x10); + bcopy(buf, p, size); + break; + case STATE_LOAD: + bcopy(p, buf, size); + x86bios_intr(®s, 0x10); + break; + } + x86bios_free(buf, size); - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } static int @@ -511,16 +593,16 @@ vesa_bios_get_line_length(void) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f06; - regs.R_EBX = 1; + x86bios_init_regs(®s); + regs.R_AX = 0x4f06; + regs.R_BL = 1; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return -1; + if (regs.R_AX != 0x004f) + return (-1); - return regs.R_BX; + return (regs.R_BX); } static int @@ -528,25 +610,25 @@ vesa_bios_set_line_length(int pixel, int *bytes, int *lines) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f06; - regs.R_EBX = 0; - regs.R_ECX = pixel; + x86bios_init_regs(®s); + regs.R_AX = 0x4f06; + /* regs.R_BL = 0; */ + regs.R_CX = pixel; x86bios_intr(®s, 0x10); #if VESA_DEBUG > 1 printf("bx:%d, cx:%d, dx:%d\n", regs.R_BX, regs.R_CX, regs.R_DX); #endif - if ((regs.R_AX & 0xff) != 0x4f) - return -1; + if (regs.R_AX != 0x004f) + return (-1); - if (bytes) + if (bytes != NULL) *bytes = regs.R_BX; - if (lines) + if (lines != NULL) *lines = regs.R_DX; - return 0; + return (0); } #if 0 @@ -555,19 +637,19 @@ vesa_bios_get_start(int *x, int *y) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f07; - regs.R_EBX = 1; + x86bios_init_regs(®s); + regs.R_AX = 0x4f07; + regs.R_BL = 1; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return -1; + if (regs.R_AX != 0x004f) + return (-1); *x = regs.R_CX; *y = regs.R_DX; - return 0; + return (0); } #endif @@ -576,15 +658,15 @@ vesa_bios_set_start(int x, int y) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f07; - regs.R_EBX = 0x80; - regs.R_EDX = y; - regs.R_ECX = x; + x86bios_init_regs(®s); + regs.R_AX = 0x4f07; + regs.R_BL = 0x80; + regs.R_CX = x; + regs.R_DX = y; x86bios_intr(®s, 0x10); - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } /* map a generic video mode to a known mode */ @@ -604,9 +686,9 @@ vesa_map_gen_mode_num(int type, int color, int mode) for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { if (mode_map[i].from == mode) - return mode_map[i].to; + return (mode_map[i].to); } - return mode; + return (mode); } static int @@ -628,7 +710,7 @@ vesa_translate_flags(u_int16_t vflags) flags |= (vflags & ftable[i].mask) ? ftable[i].set : ftable[i].reset; } - return flags; + return (flags); } static int @@ -649,9 +731,9 @@ vesa_translate_mmodel(u_int8_t vmodel) for (i = 0; mtable[i].mmodel >= 0; ++i) { if (mtable[i].vmodel == vmodel) - return mtable[i].mmodel; + return (mtable[i].mmodel); } - return V_INFO_MM_OTHER; + return (V_INFO_MM_OTHER); } static int @@ -685,6 +767,18 @@ vesa_get_line_width(video_info_t *info) return (len > 0 ? len : width); } +#define VESA_MAXSTR 256 + +#define VESA_STRCPY(dst, src) do { \ + char *str; \ + int i; \ + dst = malloc(VESA_MAXSTR, M_DEVBUF, M_WAITOK); \ + str = x86bios_offset(BIOS_SADDRTOLADDR(src)); \ + for (i = 0; i < VESA_MAXSTR - 1 && str[i] != '\0'; i++) \ + dst[i] = str[i]; \ + dst[i] = '\0'; \ +} while (0) + static int vesa_bios_init(void) { @@ -693,32 +787,50 @@ vesa_bios_init(void) video_info_t *p; x86regs_t regs; size_t bsize; - int offs; - u_char *vmbuf; + void *vmbuf; + uint32_t offs; + uint16_t vers; int is_via_cle266; int modes; int i; if (vesa_init_done) - return 0; + return (0); has_vesa_bios = FALSE; vesa_adp_info = NULL; vesa_vmode_max = 0; vesa_vmode[0].vi_mode = EOT; - vmbuf = (u_char *)x86bios_alloc(1, &offs); - bcopy("VBE2", vmbuf, 4); /* try for VBE2 data */ + /* + * If the VBE real mode interrupt vector is not found, try BIOS POST. + */ + if (x86bios_get_intr(0x10) == 0) { + if (vesa_bios_post() != 0) + return (1); + offs = x86bios_get_intr(0x10); + if (offs == 0) + return (1); + if (bootverbose) + printf("VESA: interrupt vector installed (0x%x)\n", + BIOS_SADDRTOLADDR(offs)); + } - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f00; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f00; + vmbuf = x86bios_alloc(&offs, sizeof(buf)); + if (vmbuf == NULL) + return (1); + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); + + bcopy("VBE2", vmbuf, 4); /* try for VBE2 data */ x86bios_intr(®s, 0x10); - if (((regs.R_AX & 0xff) != 0x4f) || bcmp("VESA", vmbuf, 4)) - return 1; + if (regs.R_AX != 0x004f || bcmp("VESA", vmbuf, 4) != 0) + goto fail; bcopy(vmbuf, &buf, sizeof(buf)); @@ -727,34 +839,43 @@ vesa_bios_init(void) printf("VESA: information block\n"); dump_buffer((u_char *)&buf, sizeof(buf)); } - if (vesa_adp_info->v_version < 0x0102) { + + vers = buf.v_version = le16toh(buf.v_version); + buf.v_oemstr = le32toh(buf.v_oemstr); + buf.v_flags = le32toh(buf.v_flags); + buf.v_modetable = le32toh(buf.v_modetable); + buf.v_memsize = le16toh(buf.v_memsize); + buf.v_revision = le16toh(buf.v_revision); + buf.v_venderstr = le32toh(buf.v_venderstr); + buf.v_prodstr = le32toh(buf.v_prodstr); + buf.v_revstr = le32toh(buf.v_revstr); + + if (vers < 0x0102) { printf("VESA: VBE version %d.%d is not supported; " "version 1.2 or later is required.\n", - ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 - + ((vesa_adp_info->v_version & 0x0f00) >> 8), - ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 - + (vesa_adp_info->v_version & 0x000f)); - return 1; + ((vers & 0xf000) >> 12) * 10 + ((vers & 0x0f00) >> 8), + ((vers & 0x00f0) >> 4) * 10 + (vers & 0x000f)); + return (1); } - vesa_oemstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_oemstr)); - - is_via_cle266 = strcmp(vesa_oemstr, VESA_VIA_CLE266) == 0; - - if (vesa_adp_info->v_version >= 0x0200) { - vesa_venderstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_venderstr)); - vesa_prodstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_prodstr)); - vesa_revstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_revstr)); + VESA_STRCPY(vesa_oemstr, buf.v_oemstr); + if (vers >= 0x0200) { + VESA_STRCPY(vesa_venderstr, buf.v_venderstr); + VESA_STRCPY(vesa_prodstr, buf.v_prodstr); + VESA_STRCPY(vesa_revstr, buf.v_revstr); } + is_via_cle266 = strncmp(vesa_oemstr, VESA_VIA_CLE266, + sizeof(VESA_VIA_CLE266)) == 0; - vesa_vmodetab = (uint16_t *)x86bios_offset(FARP(vesa_adp_info->v_modetable)); + if (buf.v_modetable == 0) + goto fail; - if (vesa_vmodetab == NULL) - return 1; + vesa_vmodetab = x86bios_offset(BIOS_SADDRTOLADDR(buf.v_modetable)); for (i = 0, modes = 0; (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1)) && (vesa_vmodetab[i] != 0xffff); ++i) { + vesa_vmodetab[i] = le16toh(vesa_vmodetab[i]); if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode)) continue; @@ -888,16 +1009,36 @@ vesa_bios_init(void) } vesa_vmode[modes].vi_mode = EOT; - x86bios_free(vmbuf, 1); - if (bootverbose) printf("VESA: %d mode(s) found\n", modes); has_vesa_bios = (modes > 0); if (!has_vesa_bios) - return (1); + goto fail; + x86bios_free(vmbuf, sizeof(buf)); return (0); + +fail: + if (vmbuf != NULL) + x86bios_free(vmbuf, sizeof(buf)); + if (vesa_oemstr != NULL) { + free(vesa_oemstr, M_DEVBUF); + vesa_oemstr = NULL; + } + if (vesa_venderstr != NULL) { + free(vesa_venderstr, M_DEVBUF); + vesa_venderstr = NULL; + } + if (vesa_prodstr != NULL) { + free(vesa_prodstr, M_DEVBUF); + vesa_prodstr = NULL; + } + if (vesa_revstr != NULL) { + free(vesa_revstr, M_DEVBUF); + vesa_revstr = NULL; + } + return (1); } static void @@ -946,9 +1087,9 @@ vesa_configure(int flags) int i; if (vesa_init_done) - return 0; + return (0); if (flags & VIO_PROBE_ONLY) - return 0; /* XXX */ + return (0); /* * If the VESA module has already been loaded, abort loading @@ -956,10 +1097,11 @@ vesa_configure(int flags) */ for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) { if (adp->va_flags & V_ADP_VESA) - return ENXIO; + return (ENXIO); if (adp->va_type == KD_VGA) break; } + /* * The VGA adapter is not found. This is because either * 1) the VGA driver has not been initialized, or 2) the VGA card @@ -968,7 +1110,7 @@ vesa_configure(int flags) */ if (adp == NULL) { vga_sub_configure = vesa_configure; - return ENODEV; + return (ENODEV); } /* count number of registered adapters */ @@ -980,7 +1122,7 @@ vesa_configure(int flags) vesa_adp = adp; if (vesa_bios_init()) { vesa_adp = NULL; - return ENXIO; + return (ENXIO); } vesa_adp->va_flags |= V_ADP_VESA; @@ -997,36 +1139,40 @@ vesa_configure(int flags) vesa_init_done = TRUE; } else { vesa_adp = NULL; - return error; + return (error); } - return 0; + return (0); } #if 0 static int vesa_nop(void) { - return 0; + + return (0); } #endif static int vesa_error(void) { - return 1; + + return (1); } static int vesa_probe(int unit, video_adapter_t **adpp, void *arg, int flags) { - return (*prevvidsw->probe)(unit, adpp, arg, flags); + + return ((*prevvidsw->probe)(unit, adpp, arg, flags)); } static int vesa_init(int unit, video_adapter_t *adp, int flags) { - return (*prevvidsw->init)(unit, adp, flags); + + return ((*prevvidsw->init)(unit, adp, flags)); } static int @@ -1035,10 +1181,10 @@ vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info) int i; if ((*prevvidsw->get_info)(adp, mode, info) == 0) - return 0; + return (0); if (adp != vesa_adp) - return 1; + return (1); mode = vesa_map_gen_mode_num(vesa_adp->va_type, vesa_adp->va_flags & V_ADP_COLOR, mode); @@ -1047,10 +1193,10 @@ vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info) continue; if (vesa_vmode[i].vi_mode == mode) { *info = vesa_vmode[i]; - return 0; + return (0); } } - return 1; + return (1); } static int @@ -1059,9 +1205,9 @@ vesa_query_mode(video_adapter_t *adp, video_info_t *info) int i; if ((*prevvidsw->query_mode)(adp, info) == 0) - return 0; + return (0); if (adp != vesa_adp) - return ENODEV; + return (ENODEV); for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) { if ((info->vi_width != 0) @@ -1087,9 +1233,9 @@ vesa_query_mode(video_adapter_t *adp, video_info_t *info) && (info->vi_flags != vesa_vmode[i].vi_flags)) continue; *info = vesa_vmode[i]; - return 0; + return (0); } - return ENODEV; + return (ENODEV); } static int @@ -1098,7 +1244,7 @@ vesa_set_mode(video_adapter_t *adp, int mode) video_info_t info; if (adp != vesa_adp) - return (*prevvidsw->set_mode)(adp, mode); + return ((*prevvidsw->set_mode)(adp, mode)); mode = vesa_map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); @@ -1129,11 +1275,11 @@ vesa_set_mode(video_adapter_t *adp, int mode) /* we may not need to handle this mode after all... */ if ((*prevvidsw->set_mode)(adp, mode) == 0) - return 0; + return (0); /* is the new mode supported? */ if (vesa_get_info(adp, mode, &info)) - return 1; + return (1); /* assert(VESA_MODE(mode)); */ #if VESA_DEBUG > 0 @@ -1144,7 +1290,7 @@ vesa_set_mode(video_adapter_t *adp, int mode) info.vi_flags &= ~V_INFO_LINEAR; if (vesa_bios_set_mode(mode | ((info.vi_flags & V_INFO_LINEAR) ? 0x4000 : 0))) - return 1; + return (1); if (adp->va_info.vi_flags & V_INFO_LINEAR) vesa_unmap_buffer(adp->va_buffer, @@ -1190,29 +1336,32 @@ vesa_set_mode(video_adapter_t *adp, int mode) /* move hardware cursor out of the way */ (*vidsw[vesa_adp->va_index]->set_hw_cursor)(vesa_adp, -1, -1); - return 0; + return (0); } static int vesa_save_font(video_adapter_t *adp, int page, int fontsize, int fontwidth, u_char *data, int ch, int count) { - return (*prevvidsw->save_font)(adp, page, fontsize, fontwidth, data, - ch, count); + + return ((*prevvidsw->save_font)(adp, page, fontsize, fontwidth, data, + ch, count)); } static int vesa_load_font(video_adapter_t *adp, int page, int fontsize, int fontwidth, u_char *data, int ch, int count) { - return (*prevvidsw->load_font)(adp, page, fontsize, fontwidth, data, - ch, count); + + return ((*prevvidsw->load_font)(adp, page, fontsize, fontwidth, data, + ch, count)); } static int vesa_show_font(video_adapter_t *adp, int page) { - return (*prevvidsw->show_font)(adp, page); + + return ((*prevvidsw->show_font)(adp, page)); } static int @@ -1226,12 +1375,12 @@ vesa_save_palette(video_adapter_t *adp, u_char *palette) bits = vesa_bios_get_dac(); error = vesa_bios_save_palette(0, 256, palette, bits); if (error == 0) - return 0; + return (0); if (bits != 6) - return error; + return (error); } - return (*prevvidsw->save_palette)(adp, palette); + return ((*prevvidsw->save_palette)(adp, palette)); } static int @@ -1245,48 +1394,67 @@ vesa_load_palette(video_adapter_t *adp, u_char *palette) && VESA_MODE(adp->va_mode) && ((bits = vesa_bios_set_dac(8)) > 6)) { error = vesa_bios_load_palette(0, 256, palette, bits); if (error == 0) - return 0; + return (0); if (vesa_bios_set_dac(6) != 6) - return 1; + return (1); } #endif /* notyet */ - return (*prevvidsw->load_palette)(adp, palette); + return ((*prevvidsw->load_palette)(adp, palette)); } static int vesa_set_border(video_adapter_t *adp, int color) { - return (*prevvidsw->set_border)(adp, color); + + return ((*prevvidsw->set_border)(adp, color)); } static int vesa_save_state(video_adapter_t *adp, void *p, size_t size) { + if (adp != vesa_adp) - return (*prevvidsw->save_state)(adp, p, size); + return ((*prevvidsw->save_state)(adp, p, size)); if (vesa_state_buf_size == 0) vesa_state_buf_size = vesa_bios_state_buf_size(); if (size == 0) return (sizeof(int) + vesa_state_buf_size); else if (size < (sizeof(int) + vesa_state_buf_size)) - return 1; + return (1); ((adp_state_t *)p)->sig = V_STATE_SIG; bzero(((adp_state_t *)p)->regs, vesa_state_buf_size); - return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, - vesa_state_buf_size); + return (vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, + vesa_state_buf_size)); } static int vesa_load_state(video_adapter_t *adp, void *p) { + int flags, mode, ret; + if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG)) - return (*prevvidsw->load_state)(adp, p); + return ((*prevvidsw->load_state)(adp, p)); - return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, - vesa_state_buf_size); + ret = vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, + vesa_state_buf_size); + + /* + * If the current mode is not restored properly, try BIOS POST and + * force setting the mode. + */ + flags = adp->va_info.vi_flags; + if (!(flags & V_INFO_GRAPHICS)) + flags &= ~V_INFO_LINEAR; + mode = adp->va_mode | ((flags & V_INFO_LINEAR) ? 0x4000 : 0); + if (vesa_bios_get_current_mode() != mode && vesa_bios_post() == 0 && + x86bios_get_intr(0x10) != 0) { + int10_set_mode(adp->va_initial_bios_mode); + vesa_bios_set_mode(mode); + } + return (ret); } #if 0 @@ -1295,17 +1463,17 @@ vesa_get_origin(video_adapter_t *adp, off_t *offset) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f05; - regs.R_EBX = 0x10; + x86bios_init_regs(®s); + regs.R_AX = 0x4f05; + regs.R_BL = 0x10; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 1; + if (regs.R_AX != 0x004f) + return (1); *offset = regs.DX * adp->va_window_gran; - return 0; + return (0); } #endif @@ -1321,99 +1489,107 @@ vesa_set_origin(video_adapter_t *adp, off_t offset) * detect error. */ if (adp != vesa_adp) - return (*prevvidsw->set_win_org)(adp, offset); + return ((*prevvidsw->set_win_org)(adp, offset)); /* if this is a linear frame buffer, do nothing */ if (adp->va_info.vi_flags & V_INFO_LINEAR) - return 0; + return (0); /* XXX */ if (adp->va_window_gran == 0) - return 1; + return (1); - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f05; - regs.R_EBX = 0; - regs.R_EDX = offset / adp->va_window_gran; + x86bios_init_regs(®s); + regs.R_AX = 0x4f05; + regs.R_DX = offset / adp->va_window_gran; + x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 1; + if (regs.R_AX != 0x004f) + return (1); - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f05; - regs.R_EBX = 1; - regs.R_EDX = offset / adp->va_window_gran; + x86bios_init_regs(®s); + regs.R_AX = 0x4f05; + regs.R_BL = 1; + regs.R_DX = offset / adp->va_window_gran; x86bios_intr(®s, 0x10); adp->va_window_orig = (offset/adp->va_window_gran)*adp->va_window_gran; - return 0; /* XXX */ + return (0); /* XXX */ } static int vesa_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { - return (*prevvidsw->read_hw_cursor)(adp, col, row); + + return ((*prevvidsw->read_hw_cursor)(adp, col, row)); } static int vesa_set_hw_cursor(video_adapter_t *adp, int col, int row) { - return (*prevvidsw->set_hw_cursor)(adp, col, row); + + return ((*prevvidsw->set_hw_cursor)(adp, col, row)); } static int vesa_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { - return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize, - blink); + + return ((*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize, + blink)); } static int vesa_blank_display(video_adapter_t *adp, int mode) { + /* XXX: use VESA DPMS */ - return (*prevvidsw->blank_display)(adp, mode); + return ((*prevvidsw->blank_display)(adp, mode)); } static int vesa_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr, int prot) { + #if VESA_DEBUG > 0 printf("vesa_mmap(): window:0x%tx, buffer:0x%tx, offset:0x%tx\n", adp->va_info.vi_window, adp->va_info.vi_buffer, offset); #endif - if ((adp == vesa_adp) && (adp->va_info.vi_flags & V_INFO_LINEAR)) { + if ((adp == vesa_adp) && + (adp->va_info.vi_flags & V_INFO_LINEAR) != 0) { /* va_window_size == va_buffer_size/vi_planes */ /* XXX: is this correct? */ if (offset > adp->va_window_size - PAGE_SIZE) - return -1; + return (-1); *paddr = adp->va_info.vi_buffer + offset; - return 0; - } else { - return (*prevvidsw->mmap)(adp, offset, paddr, prot); + return (0); } + return ((*prevvidsw->mmap)(adp, offset, paddr, prot)); } static int vesa_clear(video_adapter_t *adp) { - return (*prevvidsw->clear)(adp); + + return ((*prevvidsw->clear)(adp)); } static int vesa_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { - return (*prevvidsw->fill_rect)(adp, val, x, y, cx, cy); + + return ((*prevvidsw->fill_rect)(adp, val, x, y, cx, cy)); } static int vesa_bitblt(video_adapter_t *adp,...) { + /* FIXME */ - return 1; + return (1); } static int @@ -1427,15 +1603,15 @@ get_palette(video_adapter_t *adp, int base, int count, int error; if ((base < 0) || (base >= 256) || (count < 0) || (count > 256)) - return 1; + return (1); if ((base + count) > 256) - return 1; + return (1); if (!(vesa_adp_info->v_flags & V_DAC8) || !VESA_MODE(adp->va_mode)) - return 1; + return (1); bits = vesa_bios_get_dac(); if (bits <= 6) - return 1; + return (1); r = malloc(count*3, M_DEVBUF, M_WAITOK); g = r + count; @@ -1453,14 +1629,14 @@ get_palette(video_adapter_t *adp, int base, int count, free(r, M_DEVBUF); /* if error && bits != 6 at this point, we are in trouble... XXX */ - return error; + return (error); } static int set_palette(video_adapter_t *adp, int base, int count, u_char *red, u_char *green, u_char *blue, u_char *trans) { - return 1; + return (1); #ifdef notyet u_char *r; u_char *g; @@ -1469,10 +1645,10 @@ set_palette(video_adapter_t *adp, int base, int count, int error; if ((base < 0) || (base >= 256) || (base + count > 256)) - return 1; + return (1); if (!(vesa_adp_info->v_flags & V_DAC8) || !VESA_MODE(adp->va_mode) || ((bits = vesa_bios_set_dac(8)) <= 6)) - return 1; + return (1); r = malloc(count*3, M_DEVBUF, M_WAITOK); g = r + count; @@ -1484,11 +1660,11 @@ set_palette(video_adapter_t *adp, int base, int count, error = vesa_bios_load_palette2(base, count, r, g, b, bits); free(r, M_DEVBUF); if (error == 0) - return 0; + return (0); /* if the following call fails, we are in trouble... XXX */ vesa_bios_set_dac(6); - return 1; + return (1); #endif /* notyet */ } @@ -1498,7 +1674,7 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) int bytes; if (adp != vesa_adp) - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); switch (cmd) { case FBIO_SETWINORG: /* set frame buffer window origin */ @@ -1508,24 +1684,24 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) case FBIO_SETDISPSTART: /* set display start address */ if (!VESA_MODE(adp->va_mode)) - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); if (vesa_bios_set_start(((video_display_start_t *)arg)->x, ((video_display_start_t *)arg)->y)) - return ENODEV; + return (ENODEV); adp->va_disp_start.x = ((video_display_start_t *)arg)->x; adp->va_disp_start.y = ((video_display_start_t *)arg)->y; - return 0; + return (0); case FBIO_SETLINEWIDTH: /* set line length in pixel */ if (!VESA_MODE(adp->va_mode)) - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); if (vesa_bios_set_line_length(*(u_int *)arg, &bytes, NULL)) - return ENODEV; + return (ENODEV); adp->va_line_width = bytes; #if VESA_DEBUG > 1 printf("new line width:%d\n", adp->va_line_width); #endif - return 0; + return (0); case FBIO_GETPALETTE: /* get color palette */ if (get_palette(adp, ((video_color_palette_t *)arg)->index, @@ -1534,8 +1710,8 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((video_color_palette_t *)arg)->green, ((video_color_palette_t *)arg)->blue, ((video_color_palette_t *)arg)->transparent)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); case FBIO_SETPALETTE: /* set color palette */ @@ -1545,8 +1721,8 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((video_color_palette_t *)arg)->green, ((video_color_palette_t *)arg)->blue, ((video_color_palette_t *)arg)->transparent)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); case FBIOGETCMAP: /* get color palette */ if (get_palette(adp, ((struct fbcmap *)arg)->index, @@ -1554,8 +1730,8 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((struct fbcmap *)arg)->red, ((struct fbcmap *)arg)->green, ((struct fbcmap *)arg)->blue, NULL)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); case FBIOPUTCMAP: /* set color palette */ if (set_palette(adp, ((struct fbcmap *)arg)->index, @@ -1563,11 +1739,11 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((struct fbcmap *)arg)->red, ((struct fbcmap *)arg)->green, ((struct fbcmap *)arg)->blue, NULL)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); default: - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); } } @@ -1579,15 +1755,15 @@ vesa_diag(video_adapter_t *adp, int level) /* call the previous handler first */ error = (*prevvidsw->diag)(adp, level); if (error) - return error; + return (error); if (adp != vesa_adp) - return 1; + return (1); if (level <= 0) - return 0; + return (0); - return 0; + return (0); } static int @@ -1597,15 +1773,16 @@ vesa_bios_info(int level) struct vesa_mode vmode; int i; #endif + uint16_t vers; + + vers = vesa_adp_info->v_version; if (bootverbose) { /* general adapter information */ printf( "VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n", - ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 + - ((vesa_adp_info->v_version & 0x0f00) >> 8), - ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 + - (vesa_adp_info->v_version & 0x000f), + (vers >> 12) * 10 + ((vers & 0x0f00) >> 8), + ((vers & 0x00f0) >> 4) * 10 + (vers & 0x000f), vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags, vesa_vmodetab, vesa_adp_info->v_modetable); @@ -1615,9 +1792,9 @@ vesa_bios_info(int level) } if (level <= 0) - return 0; + return (0); - if (vesa_adp_info->v_version >= 0x0200 && bootverbose) { + if (vers >= 0x0200 && bootverbose) { /* vender name, product name, product revision */ printf("VESA: %s %s %s\n", (vesa_venderstr != NULL) ? vesa_venderstr : "unknown", @@ -1664,7 +1841,7 @@ vesa_bios_info(int level) } #endif /* VESA_DEBUG > 1 */ - return 0; + return (0); } /* module loading */ @@ -1676,7 +1853,7 @@ vesa_load(void) int s; if (vesa_init_done) - return 0; + return (0); /* locate a VGA adapter */ s = spltty(); @@ -1687,7 +1864,7 @@ vesa_load(void) if (error == 0) vesa_bios_info(bootverbose); - return error; + return (error); } static int @@ -1700,7 +1877,7 @@ vesa_unload(void) /* if the adapter is currently in a VESA mode, don't unload */ if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode)) - return EBUSY; + return (EBUSY); /* * FIXME: if there is at least one vty which is in a VESA mode, * we shouldn't be unloading! XXX @@ -1725,21 +1902,30 @@ vesa_unload(void) } splx(s); - return error; + if (vesa_oemstr != NULL) + free(vesa_oemstr, M_DEVBUF); + if (vesa_venderstr != NULL) + free(vesa_venderstr, M_DEVBUF); + if (vesa_prodstr != NULL) + free(vesa_prodstr, M_DEVBUF); + if (vesa_revstr != NULL) + free(vesa_revstr, M_DEVBUF); + if (vesa_vmode != &vesa_vmode_empty) + free(vesa_vmode, M_DEVBUF); + return (error); } static int vesa_mod_event(module_t mod, int type, void *data) { + switch (type) { case MOD_LOAD: - return vesa_load(); + return (vesa_load()); case MOD_UNLOAD: - return vesa_unload(); - default: - return EOPNOTSUPP; + return (vesa_unload()); } - return 0; + return (EOPNOTSUPP); } static moduledata_t vesa_mod = { diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 3e5b1a6..1467bbd 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/rman.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <dev/pci/pcireg.h> @@ -58,9 +59,19 @@ struct vga_pci_softc { struct vga_resource vga_res[PCIR_MAX_BAR_0 + 1]; }; +SYSCTL_DECL(_hw_pci); + +int vga_pci_default_unit = -1; +TUNABLE_INT("hw.pci.default_vgapci_unit", &vga_pci_default_unit); +SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RD, + &vga_pci_default_unit, -1, "Default VGA-compatible display"); + static int vga_pci_probe(device_t dev) { + device_t bdev; + int unit; + uint16_t bctl; switch (pci_get_class(dev)) { case PCIC_DISPLAY: @@ -72,6 +83,16 @@ vga_pci_probe(device_t dev) default: return (ENXIO); } + + /* Probe default display. */ + unit = device_get_unit(dev); + bdev = device_get_parent(device_get_parent(dev)); + bctl = pci_read_config(bdev, PCIR_BRIDGECTL_1, 2); + if (vga_pci_default_unit < 0 && (bctl & PCIB_BCR_VGA_ENABLE) != 0) + vga_pci_default_unit = unit; + if (vga_pci_default_unit == unit) + device_set_flags(dev, 1); + device_set_desc(dev, "VGA-compatible display"); return (BUS_PROBE_GENERIC); } diff --git a/sys/modules/dpms/Makefile b/sys/modules/dpms/Makefile index d1d58ff..4eabf14 100644 --- a/sys/modules/dpms/Makefile +++ b/sys/modules/dpms/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ KMOD= dpms -SRCS= bus_if.h device_if.h +SRCS= bus_if.h device_if.h pci_if.h .PATH: ${.CURDIR}/../../dev/dpms SRCS+= dpms.c diff --git a/sys/modules/vesa/Makefile b/sys/modules/vesa/Makefile index 8b45915..69a0c33 100644 --- a/sys/modules/vesa/Makefile +++ b/sys/modules/vesa/Makefile @@ -2,6 +2,7 @@ KMOD= vesa SRCS= opt_vga.h opt_vesa.h +SRCS+= bus_if.h device_if.h pci_if.h .PATH: ${.CURDIR}/../../dev/fb SRCS+= vesa.c diff --git a/sys/modules/x86bios/Makefile b/sys/modules/x86bios/Makefile index 8b5fa30..3cab285 100644 --- a/sys/modules/x86bios/Makefile +++ b/sys/modules/x86bios/Makefile @@ -2,9 +2,10 @@ KMOD= x86bios SRCS= opt_x86bios.h +SRCS+= bus_if.h device_if.h pci_if.h .PATH: ${.CURDIR}/../../contrib/x86emu .PATH: ${.CURDIR}/../../compat/x86bios -SRCS+= x86bios.c x86bios_alloc.c x86emu.c x86emu_util.c +SRCS+= x86bios.c x86emu.c .include <bsd.kmod.mk> |