summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2009-10-19 20:58:10 +0000
committerjkim <jkim@FreeBSD.org>2009-10-19 20:58:10 +0000
commit99279734b833c18edb9cfc47db1c920327e97fde (patch)
treed4a62e4e5d88debc2e3a4761c8ceea077f9a2ac1 /sys
parent8f9031d9fe5f0fb11cd72dd010fbdac9560df819 (diff)
downloadFreeBSD-src-99279734b833c18edb9cfc47db1c920327e97fde.zip
FreeBSD-src-99279734b833c18edb9cfc47db1c920327e97fde.tar.gz
Rewrite x86bios and update its dependent drivers.
- Do not map entire real mode memory (1MB). Instead, we map IVT/BDA and ROM area separately. Most notably, ROM area is mapped as device memory (uncacheable) as it should be. User memory is dynamically allocated and free'ed with contigmalloc(9) and contigfree(9). Remove now redundant and potentially dangerous x86bios_alloc.c. If this emulator ever grows to support non-PC hardware, we may implement it with rman(9) later. - Move all host-specific initializations from x86emu_util.c to x86bios.c and remove now unnecessary x86emu_util.c. Currently, non-PC hardware is not supported. We may use bus_space(9) later when the KPI is fixed. - Replace all bzero() calls for emulated registers with more obviously named x86bios_init_regs(). This function also initializes DS and SS properly. - Add x86bios_get_intr(). This function checks if the interrupt vector is available for the platform. It is not necessary for PC-compatible hardware but it may be needed later. ;-) - Do not try turning off monitor if DPMS does not support the state. - Allocate stable memory for VESA OEM strings instead of just holding pointers to them. They may or may not be accessible always. Fix a memory leak of video mode table while I am here. - Add (experimental) BIOS POST call for vesa(4). This function calls VGA BIOS POST code from the current VGA option ROM. Some video controllers cannot save and restore the state properly even if it is claimed to be supported. Usually the symptom is blank display after resuming from suspend state. If the video mode does not match the previous mode after restoring, we try BIOS POST and force the known good initial state. Some magic was taken from NetBSD (and it was taken from vbetool, I believe.) - Add a loader tunable for vgapci(4) to give a hint to dpms(4) and vesa(4) to identify who owns the VESA BIOS. This is very useful for multi-display adapter setup. By default, the POST video controller is automatically probed and the tunable "hw.pci.default_vgapci_unit" is set to corresponding vgapci unit number. You may override it from loader but it is very unlikely to be necessary. Unfortunately only AGP/PCI/PCI-E controllers can be matched because ISA controller does not have necessary device IDs. - Fix a long standing bug in state save/restore function. The state buffer pointer should be ES:BX, not ES:DI according to VBE 3.0. If it ever worked, that's because BX was always zero. :-) - Clean up register initializations more clearer per VBE 3.0. - Fix a lot of style issues with vesa(4).
Diffstat (limited to 'sys')
-rw-r--r--sys/compat/x86bios/x86bios.c379
-rw-r--r--sys/compat/x86bios/x86bios.h113
-rw-r--r--sys/compat/x86bios/x86bios_alloc.c81
-rw-r--r--sys/conf/files.amd642
-rw-r--r--sys/conf/files.i3862
-rw-r--r--sys/contrib/x86emu/x86emu_util.c211
-rw-r--r--sys/dev/atkbdc/atkbd.c15
-rw-r--r--sys/dev/dpms/dpms.c28
-rw-r--r--sys/dev/fb/vesa.c794
-rw-r--r--sys/dev/pci/vga_pci.c21
-rw-r--r--sys/modules/dpms/Makefile2
-rw-r--r--sys/modules/vesa/Makefile1
-rw-r--r--sys/modules/x86bios/Makefile3
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(&regs, sizeof(regs));
+ x86bios_init_regs(&regs);
regs.R_AH = 0xc0;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
+ /* Is int 0x16, function 0x0306 supported? */
+ x86bios_init_regs(&regs);
regs.R_AH = 0x09;
x86bios_intr(&regs, 0x16);
if ((regs.R_AL & 0x08) == 0)
return (ENODEV);
- bzero(&regs, sizeof(regs));
+ x86bios_init_regs(&regs);
regs.R_AX = 0x0306;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
+ if (x86bios_get_intr(0x10) == 0)
+ return (ENXIO);
+
+ x86bios_init_regs(&regs);
regs.R_AX = VBE_DPMS_FUNCTION;
regs.R_BL = subfunction;
regs.R_BH = *bh;
- regs.R_ES = 0;
- regs.R_DI = 0;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x0000 | mode;
+ x86bios_init_regs(&regs);
+ regs.R_AL = mode;
x86bios_intr(&regs, 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(&regs);
+ 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(&regs, 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(&regs, 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(&regs);
+ 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(&regs, 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(&regs);
+ regs.R_AX = 0x4f03;
+
+ x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f02;
- regs.R_EBX = mode;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f02;
+ regs.R_BX = mode;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f08;
- regs.R_EBX = 1;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f08;
+ regs.R_BL = 1;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f08;
- regs.R_EBX = (bits << 8);
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f08;
+ /* regs.R_BL = 0; */
+ regs.R_BH = bits;
x86bios_intr(&regs, 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(&regs, 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(&regs);
+ 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(&regs, 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(&regs, 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(&regs);
+ 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(&regs, 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(&regs);
+ 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(&regs, 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(&regs, 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(&regs);
+ 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(&regs, 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(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f04;
- regs.R_ECX = STATE_ALL;
- regs.R_EDX = STATE_SIZE;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f04;
+ /* regs.R_DL = STATE_SIZE; */
+ regs.R_CX = STATE_ALL;
x86bios_intr(&regs, 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(&regs, 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(&regs, 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(&regs);
+ 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(&regs, 0x10);
+ bcopy(buf, p, size);
+ break;
+ case STATE_LOAD:
+ bcopy(p, buf, size);
+ x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f06;
- regs.R_EBX = 1;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f06;
+ regs.R_BL = 1;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f06;
- regs.R_EBX = 0;
- regs.R_ECX = pixel;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f06;
+ /* regs.R_BL = 0; */
+ regs.R_CX = pixel;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f07;
- regs.R_EBX = 1;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f07;
+ regs.R_BL = 1;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f07;
- regs.R_EBX = 0x80;
- regs.R_EDX = y;
- regs.R_ECX = x;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f07;
+ regs.R_BL = 0x80;
+ regs.R_CX = x;
+ regs.R_DX = y;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f00;
- regs.R_ES = SEG_ADDR(offs);
- regs.R_DI = SEG_OFF(offs);
+ x86bios_init_regs(&regs);
+ 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(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f05;
- regs.R_EBX = 0x10;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f05;
+ regs.R_BL = 0x10;
x86bios_intr(&regs, 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(&regs, sizeof(regs));
- regs.R_EAX = 0x4f05;
- regs.R_EBX = 0;
- regs.R_EDX = offset / adp->va_window_gran;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f05;
+ regs.R_DX = offset / adp->va_window_gran;
+
x86bios_intr(&regs, 0x10);
- if ((regs.R_AX & 0xff) != 0x4f)
- return 1;
+ if (regs.R_AX != 0x004f)
+ return (1);
- bzero(&regs, sizeof(regs));
- regs.R_EAX = 0x4f05;
- regs.R_EBX = 1;
- regs.R_EDX = offset / adp->va_window_gran;
+ x86bios_init_regs(&regs);
+ regs.R_AX = 0x4f05;
+ regs.R_BL = 1;
+ regs.R_DX = offset / adp->va_window_gran;
x86bios_intr(&regs, 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>
OpenPOWER on IntegriCloud