summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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