MFC x86emu/x86bios emulator and make previously i386 only dpms and vesa

framebuffer driver, etc. work on FreeBSD/amd64.

A significant amount of improvements were done by jkim@ during the recent
months to make vesa(4) work better, over the initial code import.  This
work is based on OpenBSD's x86emu implementation and contributed by
paradox <ddkprog yahoo com> and swell.k at gmail com.

Hopefully I have stolen all their work to 8-STABLE :)

All bugs in this commit are mine, as usual.
This commit is contained in:
delphij 2010-03-02 01:56:55 +00:00
parent 3af89d2d21
commit 05b666175c
41 changed files with 10992 additions and 761 deletions

View File

@ -14,6 +14,9 @@
# The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
#
# 20100301: vesa and dpms promoted to be i386/amd64 common
OLD_FILES+=usr/include/machine/pc/vesa.h
OLD_FILES+=usr/share/man/man4/i386/dpms.4.gz
# 20091218: removal of rc.early(8) link
OLD_FILES+=usr/share/man/man8/rc.early.8.gz
# 20091027: pselect.3 implemented as syscall

View File

@ -112,6 +112,7 @@ _libsmb= libsmb
_libncp= libncp
.endif
_libsmb= libsmb
_libvgl= libvgl
.endif
.if ${MACHINE_ARCH} == "powerpc"

View File

@ -86,6 +86,7 @@ MAN= aac.4 \
digi.4 \
disc.4 \
divert.4 \
${_dpms.4} \
dpt.4 \
dummynet.4 \
ed.4 \
@ -622,6 +623,7 @@ _amdtemp.4= amdtemp.4
_asmc.4= asmc.4
_coretemp.4= coretemp.4
_cpuctl.4= cpuctl.4
_dpms.4= dpms.4
_hptiop.4= hptiop.4
_hptmv.4= hptmv.4
_hptrr.4= hptrr.4

View File

@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 22, 2006
.Dd September 10, 2009
.Dt SYSCONS 4
.Os
.Sh NAME
@ -325,7 +325,7 @@ This mode is useful on some laptop computers, but less so on
most other systems, and it adds substantial amount of code to syscons.
If this option is NOT defined, you can reduce the kernel size a lot.
See the
.Dv VESA800X600
.Dv VESAMODE
flag below.
.It Dv SC_TWOBUTTON_MOUSE
If you have a two button mouse, you may want to add this option
@ -426,15 +426,15 @@ or else at the loader prompt (see
.\".It bit 6 (QUIET_BELL)
.\"This option suppresses the bell, whether audible or visual,
.\"if it is rung in a background virtual terminal.
.It 0x0080 (VESA800X600)
This option puts the video card in the VESA 800x600 pixel, 16 color
mode.
It may be useful for laptop computers for which the 800x600 mode
is otherwise unsupported by the X server.
.It 0x0080 (VESAMODE)
This option puts the video card in the VESA mode specified by higher
16 bits of the flags during kernel initialization.
Note that in order for this flag to work, the kernel must be
compiled with the
.Dv SC_PIXEL_MODE
option explained above.
A list of the available mode can be obtained via
.Xr vidcontrol 1 .
.\"Note also that the ``copy-and-paste'' function is not currently supported
.\"in this mode and the mouse pointer will not be displayed.
.It 0x0100 (AUTODETECT_KBD)

View File

@ -154,6 +154,17 @@ options AGP_DEBUG
#####################################################################
# HARDWARE DEVICE CONFIGURATION
# To include support for VGA VESA video modes
options VESA
# Turn on extra debugging checks and output for VESA support.
options VESA_DEBUG
device dpms # DPMS suspend & resume via VESA BIOS
# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa
options X86BIOS
#
# Optional devices:
#
@ -213,6 +224,9 @@ options VGA_WIDTH90 # support 90 column modes
# Debugging.
options VGA_DEBUG
# Linear framebuffer driver for S3 VESA 1.2 cards. Works on top of VESA.
device s3pci
# 3Dfx Voodoo Graphics, Voodoo II /dev/3dfx CDEV support. This will create
# the /dev/3dfx0 device to work with glide implementations. This should get
# linked to /dev/3dfx and /dev/voodoo. Note that this is not the same as

View File

@ -0,0 +1,546 @@
/*-
* 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
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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>
__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 <sys/sysctl.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>
#define X86BIOS_PAGE_SIZE 0x00001000 /* 4K */
#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)
#define X86BIOS_PAGES (X86BIOS_MEM_SIZE / X86BIOS_PAGE_SIZE)
#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;
SYSCTL_NODE(_debug, OID_AUTO, x86bios, CTLFLAG_RD, NULL, "x86bios debugging");
static int x86bios_trace_call;
TUNABLE_INT("debug.x86bios.call", &x86bios_trace_call);
SYSCTL_INT(_debug_x86bios, OID_AUTO, call, CTLFLAG_RW, &x86bios_trace_call, 0,
"Trace far function calls");
static int x86bios_trace_int;
TUNABLE_INT("debug.x86bios.int", &x86bios_trace_int);
SYSCTL_INT(_debug_x86bios, OID_AUTO, int, CTLFLAG_RW, &x86bios_trace_int, 0,
"Trace software interrupt handlers");
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)
{
if (port == 0xb2) /* APM scratch register */
return (0);
if (port >= 0x80 && port < 0x88) /* POST status register */
return (0);
return (inb(port));
}
static uint16_t
x86bios_emu_inw(struct x86emu *emu, uint16_t port)
{
if (port >= 0x80 && port < 0x88) /* POST status register */
return (0);
return (inw(port));
}
static uint32_t
x86bios_emu_inl(struct x86emu *emu, uint16_t port)
{
if (port >= 0x80 && port < 0x88) /* POST status register */
return (0);
return (inl(port));
}
static void
x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
{
if (port == 0xb2) /* APM scratch register */
return;
if (port >= 0x80 && port < 0x88) /* POST status register */
return;
outb(port, val);
}
static void
x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
{
if (port >= 0x80 && port < 0x88) /* POST status register */
return;
outw(port, val);
}
static void
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 (x86bios_trace_call)
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 (x86bios_trace_call)
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)
{
if (intno < 0 || intno > 255)
return;
if (x86bios_map == NULL)
return;
if (x86bios_trace_int)
printf("Calling int 0x%x (ax=0x%04x bx=0x%04x "
"cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n",
intno, 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_intr(&x86bios_emu, intno);
memcpy(regs, &x86bios_emu.x86, sizeof(*regs));
mtx_unlock_spin(&x86bios_lock);
if (x86bios_trace_int)
printf("Exiting int 0x%x (ax=0x%04x bx=0x%04x "
"cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n",
intno, regs->R_AX, regs->R_BX, regs->R_CX,
regs->R_DX, regs->R_ES, regs->R_DI);
}
void *
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_mapbios(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)
{
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 i;
mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN);
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);
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;
x86bios_emu.emu_inl = x86bios_emu_inl;
x86bios_emu.emu_outb = x86bios_emu_outb;
x86bios_emu.emu_outw = x86bios_emu_outw;
x86bios_emu.emu_outl = x86bios_emu_outl;
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;
mtx_lock_spin(&x86bios_lock);
if (x86bios_map != NULL) {
free(x86bios_map, M_DEVBUF);
x86bios_map = NULL;
}
mtx_unlock_spin(&x86bios_lock);
if (map != NULL)
x86bios_unmap_mem();
mtx_destroy(&x86bios_lock);
}
static int
x86bios_modevent(module_t mod __unused, int type, void *data __unused)
{
switch (type) {
case MOD_LOAD:
x86bios_init(NULL);
break;
case MOD_UNLOAD:
x86bios_uninit(NULL);
break;
default:
return (ENOTSUP);
}
return (0);
}
static moduledata_t x86bios_mod = {
"x86bios",
x86bios_modevent,
NULL,
};
DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_CPU, SI_ORDER_ANY);
MODULE_VERSION(x86bios, 1);

View File

@ -0,0 +1,156 @@
/*-
* Copyright (c) 2009 Alex Keda <admin@lissyara.su>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*
* $FreeBSD$
*/
/*
* x86 registers were borrowed from x86emu.h x86emu_regs.h
* for compatability.
*/
#ifndef _X86BIOS_H_
#define _X86BIOS_H_
#include <sys/endian.h>
#include <sys/systm.h>
#include <sys/types.h>
#ifdef __BIG_ENDIAN__
struct x86_register32 {
uint32_t e_reg;
};
struct x86_register16 {
uint16_t filler0;
uint16_t x_reg;
};
struct x86_register8 {
uint8_t filler0;
uint8_t filler1;
uint8_t h_reg;
uint8_t l_reg;
};
#else /* !__BIG_ENDIAN__ */
struct x86_register32 {
uint32_t e_reg;
};
struct x86_register16 {
uint16_t x_reg;
};
struct x86_register8 {
uint8_t l_reg;
uint8_t h_reg;
};
#endif /* __BIG_ENDIAN__ */
union x86_register {
struct x86_register32 I32_reg;
struct x86_register16 I16_reg;
struct x86_register8 I8_reg;
};
struct x86regs {
uint16_t _pad0; /* CS */
uint16_t _pad1; /* DS */
uint16_t register_es;
uint16_t register_fs;
uint16_t register_gs;
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 _pad3; /* SP */
union x86_register register_bp;
union x86_register register_si;
union x86_register register_di;
};
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
/* 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
/* 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
/* special registers */
#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_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_ES register_es
#define R_FS register_fs
#define R_GS register_gs
#define X86BIOS_PHYSTOSEG(x) (((x) >> 4) & 0xffff)
#define X86BIOS_PHYSTOOFF(x) ((x) & 0x000f)
__BEGIN_DECLS
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_ */

View File

@ -0,0 +1,81 @@
/*-
* 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 *
x86biosAlloc(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
x86biosFree(void *pbuf, int count)
{
int i;
int busySeg;
busySeg = ((u_char *)pbuf - pbiosMem) / 4096;
for (i = busySeg; i < (busySeg + count); i++)
busySegMap[i] = 0;
}

View File

@ -2821,3 +2821,4 @@ options AAC_DEBUG # Debugging levels:
##options BKTR_ALLOC_PAGES=(217*4+1)
options BROOKTREE_ALLOC_PAGES=(217*4+1)
options MAXFILES=999

View File

@ -2893,4 +2893,3 @@ dev/xen/netfront/netfront.c optional xen | xenhvm
dev/xen/xenpci/xenpci.c optional xenpci
dev/xen/xenpci/evtchn.c optional xenpci
dev/xen/xenpci/machine_reboot.c optional xenpci

View File

@ -163,6 +163,7 @@ dev/atkbdc/atkbdc_subr.c optional atkbdc
dev/atkbdc/psm.c optional psm atkbdc
dev/coretemp/coretemp.c optional coretemp
dev/cpuctl/cpuctl.c optional cpuctl
dev/dpms/dpms.c optional dpms
# There are no systems with isa slots, so all ed isa entries should go..
dev/ed/if_ed_3c503.c optional ed isa ed_3c503
dev/ed/if_ed_isa.c optional ed isa
@ -170,6 +171,8 @@ dev/ed/if_ed_wd80x3.c optional ed isa
dev/ed/if_ed_hpp.c optional ed isa ed_hpp
dev/ed/if_ed_sic.c optional ed isa ed_sic
dev/fb/fb.c optional fb | vga
dev/fb/s3_pci.c optional s3pci
dev/fb/vesa.c optional vga vesa
dev/fb/vga.c optional vga
dev/ichwd/ichwd.c optional ichwd
dev/if_ndis/if_ndis.c optional ndis
@ -220,6 +223,7 @@ dev/sio/sio_puc.c optional sio puc
dev/speaker/spkr.c optional speaker
dev/syscons/apm/apm_saver.c optional apm_saver apm
dev/syscons/scterm-teken.c optional sc
dev/syscons/scvesactl.c optional sc vga vesa
dev/syscons/scvgarndr.c optional sc vga
dev/syscons/scvtb.c optional sc
dev/syscons/teken/teken.c optional sc
@ -294,3 +298,8 @@ i386/cpufreq/p4tcc.c optional cpufreq
#
libkern/memmove.c standard
libkern/memset.c standard
#
# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa
#
compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa
contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa

View File

@ -151,12 +151,15 @@ dev/ctau/if_ct.c optional ctau
dev/cx/csigma.c optional cx
dev/cx/cxddk.c optional cx
dev/cx/if_cx.c optional cx
dev/dpms/dpms.c optional dpms
dev/ed/if_ed_3c503.c optional ed isa ed_3c503
dev/ed/if_ed_isa.c optional ed isa
dev/ed/if_ed_wd80x3.c optional ed isa
dev/ed/if_ed_hpp.c optional ed isa ed_hpp
dev/ed/if_ed_sic.c optional ed isa ed_sic
dev/fb/fb.c optional fb | vga
dev/fb/s3_pci.c optional s3pci
dev/fb/vesa.c optional vga vesa
dev/fb/vga.c optional vga
dev/fdc/fdc.c optional fdc
dev/fdc/fdc_acpi.c optional fdc
@ -333,7 +336,6 @@ i386/isa/clock.c optional native
i386/xen/clock.c optional xen
i386/xen/xen_clock_util.c optional xen
i386/xen/xen_rtc.c optional xen
i386/isa/dpms.c optional dpms
i386/isa/elcr.c standard
i386/isa/elink.c optional ep | ie
i386/isa/isa.c optional isa
@ -343,7 +345,6 @@ i386/isa/npx.c optional npx
i386/isa/pmtimer.c optional pmtimer
i386/isa/prof_machdep.c optional profiling-routine
i386/isa/spic.c optional spic
i386/isa/vesa.c optional vga vesa
i386/linux/imgact_linux.c optional compat_linux
i386/linux/linux_dummy.c optional compat_linux
i386/linux/linux_locore.s optional compat_linux \
@ -381,3 +382,8 @@ i386/xbox/xbox.c optional xbox
i386/xbox/xboxfb.c optional xboxfb
dev/fb/boot_font.c optional xboxfb
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
contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa

View File

@ -841,3 +841,5 @@ SND_FEEDER_FULL_MULTIFORMAT opt_snd.h
SND_FEEDER_RATE_HP opt_snd.h
SND_PCM_64 opt_snd.h
SND_OLDSTEREO opt_snd.h
X86BIOS

View File

@ -37,6 +37,9 @@ VGA_NO_MODE_CHANGE opt_vga.h
VGA_SLOW_IOACCESS opt_vga.h
VGA_WIDTH90 opt_vga.h
VESA
VESA_DEBUG opt_vesa.h
# AGP debugging support
AGP_DEBUG opt_agp.h

8335
sys/contrib/x86emu/x86emu.c Normal file

File diff suppressed because it is too large Load Diff

184
sys/contrib/x86emu/x86emu.h Normal file
View File

@ -0,0 +1,184 @@
/* $NetBSD: x86emu.h,v 1.1 2007/12/01 20:14:10 joerg Exp $ */
/* $OpenBSD: x86emu.h,v 1.3 2009/06/06 03:45:05 matthieu Exp $ */
/* $FreeBSD$ */
/****************************************************************************
*
* 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.
*
****************************************************************************/
#ifndef __X86EMU_X86EMU_H
#define __X86EMU_X86EMU_H
#include <sys/types.h>
#include <sys/endian.h>
#ifdef _KERNEL
#include <sys/systm.h>
#include <machine/setjmp.h>
#else
#include <setjmp.h>
#endif
/*
* General EAX, EBX, ECX, EDX type registers. Note that for
* portability, and speed, the issue of byte swapping is not addressed
* in the registers. All registers are stored in the default format
* available on the host machine. The only critical issue is that the
* registers should line up EXACTLY in the same manner as they do in
* the 386. That is:
*
* EAX & 0xff === AL
* EAX & 0xffff == AX
*
* etc. The result is that alot of the calculations can then be
* done using the native instruction set fully.
*/
#ifdef __BIG_ENDIAN__
struct x86emu_register32 {
uint32_t e_reg;
};
struct x86emu_register16 {
uint16_t filler0;
uint16_t x_reg;
};
struct x86emu_register8 {
uint8_t filler0, filler1;
uint8_t h_reg, l_reg;
};
#else /* !__BIG_ENDIAN__ */
struct x86emu_register32 {
uint32_t e_reg;
};
struct x86emu_register16 {
uint16_t x_reg;
};
struct x86emu_register8 {
uint8_t l_reg, h_reg;
};
#endif /* BIG_ENDIAN */
union x86emu_register {
struct x86emu_register32 I32_reg;
struct x86emu_register16 I16_reg;
struct x86emu_register8 I8_reg;
};
struct x86emu_regs {
uint16_t register_cs;
uint16_t register_ds;
uint16_t register_es;
uint16_t register_fs;
uint16_t register_gs;
uint16_t register_ss;
uint32_t register_flags;
union x86emu_register register_a;
union x86emu_register register_b;
union x86emu_register register_c;
union x86emu_register register_d;
union x86emu_register register_sp;
union x86emu_register register_bp;
union x86emu_register register_si;
union x86emu_register register_di;
union x86emu_register register_ip;
/*
* MODE contains information on:
* REPE prefix 2 bits repe,repne
* SEGMENT overrides 5 bits normal,DS,SS,CS,ES
* Delayed flag set 3 bits (zero, signed, parity)
* reserved 6 bits
* interrupt # 8 bits instruction raised interrupt
* BIOS video segregs 4 bits
* Interrupt Pending 1 bits
* Extern interrupt 1 bits
* Halted 1 bits
*/
uint32_t mode;
volatile int intr; /* mask of pending interrupts */
uint8_t intno;
uint8_t __pad[3];
};
struct x86emu {
char *mem_base;
size_t mem_size;
void *sys_private;
struct x86emu_regs x86;
jmp_buf exec_state;
uint64_t cur_cycles;
unsigned int cur_mod:2;
unsigned int cur_rl:3;
unsigned int cur_rh:3;
uint32_t cur_offset;
uint8_t (*emu_rdb)(struct x86emu *, uint32_t addr);
uint16_t (*emu_rdw)(struct x86emu *, uint32_t addr);
uint32_t (*emu_rdl)(struct x86emu *, uint32_t addr);
void (*emu_wrb)(struct x86emu *, uint32_t addr,uint8_t val);
void (*emu_wrw)(struct x86emu *, uint32_t addr, uint16_t val);
void (*emu_wrl)(struct x86emu *, uint32_t addr, uint32_t val);
uint8_t (*emu_inb)(struct x86emu *, uint16_t addr);
uint16_t (*emu_inw)(struct x86emu *, uint16_t addr);
uint32_t (*emu_inl)(struct x86emu *, uint16_t addr);
void (*emu_outb)(struct x86emu *, uint16_t addr, uint8_t val);
void (*emu_outw)(struct x86emu *, uint16_t addr, uint16_t val);
void (*emu_outl)(struct x86emu *, uint16_t addr, uint32_t val);
void (*_x86emu_intrTab[256])(struct x86emu *, int);
};
__BEGIN_DECLS
void x86emu_init_default(struct x86emu *);
/* decode.c */
void x86emu_exec(struct x86emu *);
void x86emu_exec_call(struct x86emu *, uint16_t, uint16_t);
void x86emu_exec_intr(struct x86emu *, uint8_t);
void x86emu_halt_sys(struct x86emu *) __dead2;
__END_DECLS
#endif /* __X86EMU_X86EMU_H */

View File

@ -0,0 +1,170 @@
/* $NetBSD: x86emu_regs.h,v 1.1 2007/12/01 20:14:10 joerg Exp $ */
/* $OpenBSD: x86emu_regs.h,v 1.2 2009/06/06 03:45:05 matthieu 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.
*
****************************************************************************/
#ifndef __X86EMU_REGS_H
#define __X86EMU_REGS_H
/*---------------------- Macros and type definitions ----------------------*/
/* 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
/* 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
/* 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
/* 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_IP register_ip.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_EIP register_ip.I32_reg.e_reg
#define R_EFLG register_flags
/* segment registers */
#define R_CS register_cs
#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
/* flag conditions */
#define FB_CF 0x0001 /* CARRY flag */
#define FB_PF 0x0004 /* PARITY flag */
#define FB_AF 0x0010 /* AUX flag */
#define FB_ZF 0x0040 /* ZERO flag */
#define FB_SF 0x0080 /* SIGN flag */
#define FB_TF 0x0100 /* TRAP flag */
#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */
#define FB_DF 0x0400 /* DIR flag */
#define FB_OF 0x0800 /* OVERFLOW flag */
/* 80286 and above always have bit#1 set */
#define F_ALWAYS_ON (0x0002) /* flag bits always on */
/*
* Define a mask for only those flag bits we will ever pass back
* (via PUSHF)
*/
#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
/* following bits masked in to a 16bit quantity */
#define F_CF 0x0001 /* CARRY flag */
#define F_PF 0x0004 /* PARITY flag */
#define F_AF 0x0010 /* AUX flag */
#define F_ZF 0x0040 /* ZERO flag */
#define F_SF 0x0080 /* SIGN flag */
#define F_TF 0x0100 /* TRAP flag */
#define F_IF 0x0200 /* INTERRUPT ENABLE flag */
#define F_DF 0x0400 /* DIR flag */
#define F_OF 0x0800 /* OVERFLOW flag */
#define SET_FLAG(flag) (emu->x86.R_FLG |= (flag))
#define CLEAR_FLAG(flag) (emu->x86.R_FLG &= ~(flag))
#define ACCESS_FLAG(flag) (emu->x86.R_FLG & (flag))
#define CLEARALL_FLAG(m) (emu->x86.R_FLG = 0)
#define CONDITIONAL_SET_FLAG(COND,FLAG) \
if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
#define F_PF_CALC 0x010000 /* PARITY flag has been calced */
#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */
#define F_SF_CALC 0x040000 /* SIGN flag has been calced */
#define F_ALL_CALC 0xff0000 /* All have been calced */
/*
* Emulator machine state.
* Segment usage control.
*/
#define SYSMODE_SEG_DS_SS 0x00000001
#define SYSMODE_SEGOVR_CS 0x00000002
#define SYSMODE_SEGOVR_DS 0x00000004
#define SYSMODE_SEGOVR_ES 0x00000008
#define SYSMODE_SEGOVR_FS 0x00000010
#define SYSMODE_SEGOVR_GS 0x00000020
#define SYSMODE_SEGOVR_SS 0x00000040
#define SYSMODE_PREFIX_REPE 0x00000080
#define SYSMODE_PREFIX_REPNE 0x00000100
#define SYSMODE_PREFIX_DATA 0x00000200
#define SYSMODE_PREFIX_ADDR 0x00000400
#define SYSMODE_INTR_PENDING 0x10000000
#define SYSMODE_EXTRN_INTR 0x20000000
#define SYSMODE_HALTED 0x40000000
#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \
SYSMODE_SEGOVR_CS | \
SYSMODE_SEGOVR_DS | \
SYSMODE_SEGOVR_ES | \
SYSMODE_SEGOVR_FS | \
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS)
#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \
SYSMODE_SEGOVR_CS | \
SYSMODE_SEGOVR_DS | \
SYSMODE_SEGOVR_ES | \
SYSMODE_SEGOVR_FS | \
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS | \
SYSMODE_PREFIX_DATA | \
SYSMODE_PREFIX_ADDR)
#define INTR_SYNCH 0x1
#endif /* __X86EMU_REGS_H */

View File

@ -0,0 +1,208 @@
/* $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/param.h>
#include <sys/endian.h>
#include <dev/x86emu/x86emu.h>
#include <dev/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 letoh32(*(u_int32_t *)(emu->mem_base + addr));
#else
return letoh16(*(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 letoh32(*(u_int32_t *)(emu->mem_base + addr));
#else
return letoh32(*(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;
}

View File

@ -44,10 +44,10 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
#ifdef __i386__
#if defined(__i386__) || defined(__amd64__)
#include <machine/md_var.h>
#include <machine/psl.h>
#include <machine/vm86.h>
#include <compat/x86bios/x86bios.h>
#include <machine/pc/bios.h>
#include <vm/vm.h>
@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_param.h>
#include <isa/isareg.h>
#endif /* __i386__ */
#endif /* __i386__ || __amd64__ */
#include <sys/kbio.h>
#include <dev/kbd/kbdreg.h>
@ -1089,34 +1089,45 @@ atkbd_shutdown_final(void *v)
static int
get_typematic(keyboard_t *kbd)
{
#ifdef __i386__
#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...
*/
struct vm86frame vmf;
u_int32_t p;
x86regs_t regs;
uint8_t *p;
bzero(&vmf, sizeof(vmf));
vmf.vmf_ax = 0xc000;
vm86_intcall(0x15, &vmf);
if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah)
return ENODEV;
p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx);
if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */
return ENODEV;
vmf.vmf_ax = 0x0900;
vm86_intcall(0x16, &vmf);
if ((vmf.vmf_al & 0x08) == 0) /* int 16, function 0x0306 supported? */
return ENODEV;
vmf.vmf_ax = 0x0306;
vm86_intcall(0x16, &vmf);
kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5);
kbd->kb_delay2 = typematic_rate(vmf.vmf_bl);
return 0;
if (x86bios_get_intr(0x15) == 0 || x86bios_get_intr(0x16) == 0)
return (ENODEV);
/* Is BIOS system configuration table supported? */
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 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 0x16, function 0x0306 supported? */
x86bios_init_regs(&regs);
regs.R_AH = 0x09;
x86bios_intr(&regs, 0x16);
if ((regs.R_AL & 0x08) == 0)
return (ENODEV);
x86bios_init_regs(&regs);
regs.R_AX = 0x0306;
x86bios_intr(&regs, 0x16);
kbd->kb_delay1 = typematic_delay(regs.R_BH << 5);
kbd->kb_delay2 = typematic_rate(regs.R_BL);
return (0);
#else
return ENODEV;
#endif /* __i386__ */
return (ENODEV);
#endif /* __i386__ || __amd64__ */
}
static int

View File

@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$");
#include <sys/libkern.h>
#include <sys/module.h>
#include <machine/vm86.h>
#include <compat/x86bios/x86bios.h>
/*
* VESA DPMS States
@ -118,19 +118,14 @@ static driver_t dpms_driver = {
static devclass_t dpms_devclass;
DRIVER_MODULE(dpms, vgapci, dpms_driver, dpms_devclass, NULL, NULL);
DRIVER_MODULE(dpms, vgapm, dpms_driver, dpms_devclass, NULL, NULL);
MODULE_DEPEND(dpms, x86bios, 1, 1, 1);
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)
if (x86bios_match_device(0xc0000, device_get_parent(parent)))
device_add_child(parent, "dpms", 0);
}
@ -171,8 +166,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);
}
@ -189,21 +187,23 @@ dpms_resume(device_t dev)
static int
dpms_call_bios(int subfunction, int *bh)
{
struct vm86frame vmf;
int error;
x86regs_t regs;
bzero(&vmf, sizeof(vmf));
vmf.vmf_ax = VBE_DPMS_FUNCTION;
vmf.vmf_bl = subfunction;
vmf.vmf_bh = *bh;
vmf.vmf_es = 0;
vmf.vmf_di = 0;
error = vm86_intcall(0x10, &vmf);
if (error == 0 && (vmf.vmf_eax & 0xffff) != 0x004f)
error = ENXIO;
if (error == 0)
*bh = vmf.vmf_bh;
return (error);
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;
x86bios_intr(&regs, 0x10);
if (regs.R_AX != 0x004f)
return (ENXIO);
*bh = regs.R_BH;
return (0);
}
static int

View File

@ -54,9 +54,8 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <machine/md_var.h>
#include <machine/vm86.h>
#include <machine/pc/bios.h>
#include <machine/pc/vesa.h>
#include <dev/fb/vesa.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/vgareg.h>

File diff suppressed because it is too large Load Diff

View File

@ -26,8 +26,8 @@
* $FreeBSD$
*/
#ifndef _MACHINE_PC_VESA_H
#define _MACHINE_PC_VESA_H
#ifndef _DEV_FB_VESA_H_
#define _DEV_FB_VESA_H_
struct vesa_info
{
@ -46,6 +46,8 @@ struct vesa_info
u_int32_t v_venderstr; /* vender */
u_int32_t v_prodstr; /* product name */
u_int32_t v_revstr; /* product rev */
u_int8_t v_strach[222];
u_int8_t v_oemdata[256];
} __packed;
struct vesa_mode
@ -106,7 +108,21 @@ struct vesa_mode
u_int32_t v_lfb;
u_int32_t v_offscreen;
u_int16_t v_offscreensize;
};
/* 3.0 implementations */
u_int16_t v_linbpscanline;
u_int8_t v_bankipages;
u_int8_t v_linipages;
u_int8_t v_linredmasksize;
u_int8_t v_linredfieldpos;
u_int8_t v_lingreenmasksize;
u_int8_t v_lingreenfieldpos;
u_int8_t v_linbluemasksize;
u_int8_t v_linbluefieldpos;
u_int8_t v_linresmasksize;
u_int8_t v_linresfieldpos;
u_int32_t v_maxpixelclock;
u_int8_t v_reserved1[190];
} __packed;
#ifdef _KERNEL
@ -117,4 +133,4 @@ int vesa_unload_ioctl(void);
#endif
#endif /* !_MACHINE_PC_VESA_H */
#endif /* !_DEV_FB_VESA_H_ */

View File

@ -156,7 +156,7 @@ vga_mmap(struct cdev *dev, vga_softc_t *sc, vm_offset_t offset, vm_offset_t *pad
#include <isa/rtc.h>
#ifdef __i386__
#include <machine/pc/vesa.h>
#include <dev/fb/vesa.h>
#endif
#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)

View File

@ -70,6 +70,7 @@ struct video_adapter;
typedef struct vga_softc {
struct video_adapter *adp;
void *state_buf;
void *pal_buf;
#ifdef FB_INSTALL_CDEV
genfb_softc_t gensc;
#endif

View File

@ -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_RDTUN,
&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);
}

View File

@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/fbio.h>
#include <sys/consio.h>
#include <machine/pc/vesa.h>
#include <dev/fb/vesa.h>
#include <dev/fb/fbreg.h>
#include <dev/syscons/syscons.h>

View File

@ -193,6 +193,8 @@ static u_short mouse_or_mask[16] = {
case 15: \
writew(pos, vga_palette15[color]); \
break; \
case 8: \
writeb(pos, (uint8_t)color); \
}
static uint32_t vga_palette32[16] = {
@ -215,6 +217,7 @@ static uint16_t vga_palette15[16] = {
#ifndef SC_NO_CUTPASTE
static uint32_t mouse_buf32[256];
static uint16_t mouse_buf16[256];
static uint8_t mouse_buf8[256];
#endif
#endif
@ -498,7 +501,9 @@ vga_rndrinit(scr_stat *scp)
scp->rndr->draw_cursor = vga_pxlcursor_planar;
scp->rndr->blink_cursor = vga_pxlblink_planar;
scp->rndr->draw_mouse = vga_pxlmouse_planar;
} else if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT) {
} else
if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT ||
scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_PACKED) {
scp->rndr->clear = vga_pxlclear_direct;
scp->rndr->draw_border = vga_pxlborder_direct;
scp->rndr->draw = vga_vgadraw_direct;
@ -1148,6 +1153,7 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
int i, j;
uint32_t *u32;
uint16_t *u16;
uint8_t *u8;
int bpp;
if (!on)
@ -1179,6 +1185,10 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
u16 = (uint16_t*)(p + j * pixel_size);
writew(u16, mouse_buf16[i * 16 + j]);
break;
case 8:
u8 = (uint8_t*)(p + j * pixel_size);
writeb(u8, mouse_buf8[i * 16 + j]);
break;
}
}
@ -1214,6 +1224,14 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
else if (mouse_and_mask[i] & (1 << (15 - j)))
writew(u16, 0);
break;
case 8:
u8 = (uint8_t*)(p + j * pixel_size);
mouse_buf8[i * 16 + j] = *u8;
if (mouse_or_mask[i] & (1 << (15 - j)))
writeb(u8, 15);
else if (mouse_and_mask[i] & (1 << (15 - j)))
writeb(u8, 0);
break;
}
}

View File

@ -369,30 +369,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize))
return EINVAL;
/*
* We currently support the following graphic modes:
*
* - 4 bpp planar modes whose memory size does not exceed 64K
* - 15, 16, 24 and 32 bpp linear modes
*/
if (info.vi_mem_model == V_INFO_MM_PLANAR) {
if (info.vi_planes != 4)
return ENODEV;
/*
* A memory size >64K requires bank switching to access the entire
* screen. XXX
*/
if (info.vi_width * info.vi_height / 8 > info.vi_window_size)
return ENODEV;
} else if (info.vi_mem_model == V_INFO_MM_DIRECT) {
if (!(info.vi_flags & V_INFO_LINEAR) &&
(info.vi_depth != 15) && (info.vi_depth != 16) &&
(info.vi_depth != 24) && (info.vi_depth != 32))
return ENODEV;
} else
if (!sc_support_pixel_mode(&info))
return ENODEV;
/* stop screen saver, etc */
@ -468,6 +445,48 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
#endif /* SC_PIXEL_MODE */
}
int
sc_support_pixel_mode(void *arg)
{
#ifdef SC_PIXEL_MODE
video_info_t *info = arg;
if ((info->vi_flags & V_INFO_GRAPHICS) == 0)
return (0);
/*
* We currently support the following graphic modes:
*
* - 4 bpp planar modes whose memory size does not exceed 64K
* - 15, 16, 24 and 32 bpp linear modes
*/
switch (info->vi_mem_model) {
case V_INFO_MM_PLANAR:
if (info->vi_planes != 4)
break;
/*
* A memory size >64K requires bank switching to access
* the entire screen. XXX
*/
if (info->vi_width * info->vi_height / 8 > info->vi_window_size)
break;
return (1);
case V_INFO_MM_DIRECT:
if ((info->vi_flags & V_INFO_LINEAR) == 0 &&
info->vi_depth != 15 && info->vi_depth != 16 &&
info->vi_depth != 24 && info->vi_depth != 32)
break;
return (1);
case V_INFO_MM_PACKED:
if ((info->vi_flags & V_INFO_LINEAR) == 0 &&
info->vi_depth != 8)
break;
return (1);
}
#endif
return (0);
}
#define fb_ioctl(a, c, d) \
(((a) == NULL) ? ENODEV : \
vidd_ioctl((a), (c), (caddr_t)(d)))
@ -721,6 +740,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
#endif
#ifndef SC_NO_PALETTE_LOADING
#ifdef SC_PIXEL_MODE
if ((adp->va_flags & V_ADP_DAC8) != 0)
vidd_load_palette(adp, scp->sc->palette2);
else
#endif
vidd_load_palette(adp, scp->sc->palette);
#endif
@ -778,7 +802,10 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
if (scp == scp->sc->cur_scp) {
set_mode(scp);
#ifndef SC_NO_PALETTE_LOADING
vidd_load_palette(adp, scp->sc->palette);
if ((adp->va_flags & V_ADP_DAC8) != 0)
vidd_load_palette(adp, scp->sc->palette2);
else
vidd_load_palette(adp, scp->sc->palette);
#endif
}
sc_clear_screen(scp);

View File

@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/consio.h>
@ -342,16 +343,105 @@ sc_alloc_tty(int index, int devnum)
return (tp);
}
#ifdef SC_PIXEL_MODE
static void
sc_set_vesa_mode(scr_stat *scp, sc_softc_t *sc, int unit)
{
video_info_t info;
int depth;
int i;
int vmode;
vmode = 0;
(void)resource_int_value("sc", unit, "vesa_mode", &vmode);
if (vmode < M_VESA_BASE || vmode > M_VESA_MODE_MAX ||
vidd_get_info(sc->adp, vmode, &info) != 0 ||
!sc_support_pixel_mode(&info))
vmode = 0;
/*
* If the mode is unset or unsupported, search for an available
* 800x600 graphics mode with the highest color depth.
*/
if (vmode == 0) {
for (depth = 0, i = M_VESA_BASE; i <= M_VESA_MODE_MAX; i++)
if (vidd_get_info(sc->adp, i, &info) == 0 &&
info.vi_width == 800 && info.vi_height == 600 &&
sc_support_pixel_mode(&info) &&
info.vi_depth > depth) {
vmode = i;
depth = info.vi_depth;
}
if (vmode == 0)
return;
vidd_get_info(sc->adp, vmode, &info);
}
#ifndef SC_NO_FONT_LOADING
if ((sc->fonts_loaded & FONT_16) == 0)
return;
#endif
#ifdef DEV_SPLASH
if ((sc->flags & SC_SPLASH_SCRN) != 0)
splash_term(sc->adp);
#endif
#ifndef SC_NO_HISTORY
if (scp->history != NULL) {
sc_vtb_append(&scp->vtb, 0, scp->history,
scp->ypos * scp->xsize + scp->xpos);
scp->history_pos = sc_vtb_tail(scp->history);
}
#endif
vidd_set_mode(sc->adp, vmode);
scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN);
scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE);
scp->xpixel = info.vi_width;
scp->ypixel = info.vi_height;
scp->xsize = scp->xpixel / 8;
scp->ysize = scp->ypixel / 16;
scp->xpos = 0;
scp->ypos = scp->ysize - 1;
scp->xoff = scp->yoff = 0;
#ifndef SC_NO_FONT_LOADING
scp->font = sc->font_16;
#else
scp->font = NULL;
#endif
scp->font_size = 16;
scp->font_width = 8;
scp->start = scp->xsize * scp->ysize - 1;
scp->end = 0;
scp->cursor_pos = scp->cursor_oldpos = scp->xsize * scp->xsize;
scp->mode = sc->initial_mode = vmode;
#ifndef __sparc64__
sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
(void *)sc->adp->va_window, FALSE);
#endif
sc_alloc_scr_buffer(scp, FALSE, FALSE);
sc_init_emulator(scp, NULL);
#ifndef SC_NO_CUTPASTE
sc_alloc_cut_buffer(scp, FALSE);
#endif
#ifndef SC_NO_HISTORY
sc_alloc_history_buffer(scp, 0, 0, FALSE);
#endif
sc_set_border(scp, scp->border);
sc_set_cursor_image(scp);
scp->status &= ~UNKNOWN_MODE;
#ifdef DEV_SPLASH
if ((sc->flags & SC_SPLASH_SCRN) != 0)
splash_init(sc->adp, scsplash_callback, sc);
#endif
}
#endif
int
sc_attach_unit(int unit, int flags)
{
sc_softc_t *sc;
scr_stat *scp;
#ifdef SC_PIXEL_MODE
video_info_t info;
#endif
int vc;
struct cdev *dev;
int vc;
flags &= ~SC_KERNEL_CONSOLE;
@ -373,21 +463,8 @@ sc_attach_unit(int unit, int flags)
sc_console = scp;
#ifdef SC_PIXEL_MODE
if ((sc->config & SC_VESA800X600)
&& (vidd_get_info(sc->adp, M_VESA_800x600, &info) == 0)) {
#ifdef DEV_SPLASH
if (sc->flags & SC_SPLASH_SCRN)
splash_term(sc->adp);
#endif
sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
sc_set_pixel_mode(scp, NULL, COL, ROW, 16, 8);
sc->initial_mode = M_VESA_800x600;
#ifdef DEV_SPLASH
/* put up the splash again! */
if (sc->flags & SC_SPLASH_SCRN)
splash_init(sc->adp, scsplash_callback, sc);
#endif
}
if ((sc->config & SC_VESAMODE) != 0)
sc_set_vesa_mode(scp, sc, unit);
#endif /* SC_PIXEL_MODE */
/* initialize cursor */
@ -517,7 +594,7 @@ sctty_open(struct tty *tp)
if (scp == NULL) {
scp = SC_STAT(tp) = alloc_scp(sc, SC_VTY(tp));
if (ISGRAPHSC(scp))
sc_set_pixel_mode(scp, NULL, COL, ROW, 16, 8);
sc_set_pixel_mode(scp, NULL, 0, 0, 16, 8);
}
if (!tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
tp->t_winsize.ws_col = scp->xsize;
@ -2049,6 +2126,11 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode)
}
if (set_mode(scp) == 0) {
#ifndef SC_NO_PALETTE_LOADING
#ifdef SC_PIXEL_MODE
if ((scp->sc->adp->va_flags & V_ADP_DAC8) != 0)
vidd_load_palette(scp->sc->adp, scp->sc->palette2);
else
#endif
vidd_load_palette(scp->sc->adp, scp->sc->palette);
#endif
--scrn_blanked;
@ -2452,8 +2534,14 @@ exchange_scr(sc_softc_t *sc)
if (!ISGRAPHSC(scp))
sc_set_cursor_image(scp);
#ifndef SC_NO_PALETTE_LOADING
if (ISGRAPHSC(sc->old_scp))
if (ISGRAPHSC(sc->old_scp)) {
#ifdef SC_PIXEL_MODE
if ((sc->adp->va_flags & V_ADP_DAC8) != 0)
vidd_load_palette(sc->adp, sc->palette2);
else
#endif
vidd_load_palette(sc->adp, sc->palette);
}
#endif
sc_set_border(scp, scp->border);
@ -2802,6 +2890,10 @@ scinit(int unit, int flags)
#ifndef SC_NO_PALETTE_LOADING
vidd_save_palette(sc->adp, sc->palette);
#ifdef SC_PIXEL_MODE
for (i = 0; i < sizeof(sc->palette2); i++)
sc->palette2[i] = i / 3;
#endif
#endif
#ifdef DEV_SPLASH
@ -2995,6 +3087,8 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
scp->ysize = info.vi_height;
scp->xpixel = scp->xsize*info.vi_cwidth;
scp->ypixel = scp->ysize*info.vi_cheight;
}
scp->font_size = info.vi_cheight;
scp->font_width = info.vi_cwidth;
if (info.vi_cheight < 14) {
@ -3016,7 +3110,7 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
scp->font = NULL;
#endif
}
}
sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
#ifndef __sparc64__
sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);

View File

@ -191,7 +191,7 @@ struct tty;
typedef struct sc_softc {
int unit; /* unit # */
int config; /* configuration flags */
#define SC_VESA800X600 (1 << 7)
#define SC_VESAMODE (1 << 7)
#define SC_AUTODETECT_KBD (1 << 8)
#define SC_KERNEL_CONSOLE (1 << 9)
@ -245,7 +245,10 @@ typedef struct sc_softc {
#endif
#ifndef SC_NO_PALETTE_LOADING
u_char palette[256*3];
u_char palette[256 * 3];
#ifdef SC_PIXEL_MODE
u_char palette2[256 * 3];
#endif
#endif
#ifndef SC_NO_FONT_LOADING
@ -616,6 +619,7 @@ int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode,
int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode);
int sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize,
int ysize, int fontsize, int font_width);
int sc_support_pixel_mode(void *arg);
int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data,
struct thread *td);

View File

@ -361,6 +361,9 @@ options VESA_DEBUG
device dpms # DPMS suspend & resume via VESA BIOS
# x86 real mode BIOS emulator, required by atkbdc/dpms/vesa
options X86BIOS
#
# The Numeric Processing eXtension driver. This is non-optional.
device npx
@ -444,6 +447,9 @@ options VGA_WIDTH90 # support 90 column modes
# Debugging.
options VGA_DEBUG
# Linear framebuffer driver for S3 VESA 1.2 cards. Works on top of VESA.
device s3pci
# 3Dfx Voodoo Graphics, Voodoo II /dev/3dfx CDEV support. This will create
# the /dev/3dfx0 device to work with glide implementations. This should get
# linked to /dev/3dfx and /dev/voodoo. Note that this is not the same as

View File

@ -59,6 +59,69 @@ __FBSDID("$FreeBSD$");
#include <isa/isareg.h>
#include <isa/isavar.h>
static void
vga_suspend(device_t dev)
{
vga_softc_t *sc;
int nbytes;
sc = device_get_softc(dev);
/* Save the video state across the suspend. */
if (sc->state_buf != NULL)
goto save_palette;
nbytes = vidd_save_state(sc->adp, NULL, 0);
if (nbytes <= 0)
goto save_palette;
sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT);
if (sc->state_buf == NULL)
goto save_palette;
if (bootverbose)
device_printf(dev, "saving %d bytes of video state\n", nbytes);
if (vidd_save_state(sc->adp, sc->state_buf, nbytes) != 0) {
device_printf(dev, "failed to save state (nbytes=%d)\n",
nbytes);
free(sc->state_buf, M_TEMP);
sc->state_buf = NULL;
}
save_palette:
/* Save the color palette across the suspend. */
if (sc->pal_buf != NULL)
return;
sc->pal_buf = malloc(256 * 3, M_TEMP, M_NOWAIT);
if (sc->pal_buf == NULL)
return;
if (bootverbose)
device_printf(dev, "saving color palette\n");
if (vidd_save_palette(sc->adp, sc->pal_buf) != 0) {
device_printf(dev, "failed to save palette\n");
free(sc->pal_buf, M_TEMP);
sc->pal_buf = NULL;
}
}
static void
vga_resume(device_t dev)
{
vga_softc_t *sc;
sc = device_get_softc(dev);
if (sc->state_buf != NULL) {
if (vidd_load_state(sc->adp, sc->state_buf) != 0)
device_printf(dev, "failed to reload state\n");
free(sc->state_buf, M_TEMP);
sc->state_buf = NULL;
}
if (sc->pal_buf != NULL) {
if (vidd_load_palette(sc->adp, sc->pal_buf) != 0)
device_printf(dev, "failed to reload palette\n");
free(sc->pal_buf, M_TEMP);
sc->pal_buf = NULL;
}
}
#define VGA_SOFTC(unit) \
((vga_softc_t *)devclass_get_softc(isavga_devclass, unit))
@ -103,9 +166,9 @@ isavga_probe(device_t dev)
if (isa_get_vendorid(dev))
return (ENXIO);
device_set_desc(dev, "Generic ISA VGA");
error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev));
if (error == 0) {
device_set_desc(dev, "Generic ISA VGA");
bus_set_resource(dev, SYS_RES_IOPORT, 0,
adp.va_io_base, adp.va_io_size);
bus_set_resource(dev, SYS_RES_MEMORY, 0,
@ -117,7 +180,7 @@ isavga_probe(device_t dev)
isa_set_msize(dev, adp.va_mem_size);
#endif
}
return error;
return (error);
}
static int
@ -140,13 +203,13 @@ isavga_attach(device_t dev)
error = vga_attach_unit(unit, sc, device_get_flags(dev));
if (error)
return error;
return (error);
#ifdef FB_INSTALL_CDEV
/* attach a virtual frame buffer device */
error = fb_attach(VGA_MKMINOR(unit), sc->adp, &isavga_cdevsw);
if (error)
return error;
return (error);
#endif /* FB_INSTALL_CDEV */
if (0 && bootverbose)
@ -157,57 +220,29 @@ isavga_attach(device_t dev)
bus_generic_attach(dev);
#endif
return 0;
return (0);
}
static int
isavga_suspend(device_t dev)
{
vga_softc_t *sc;
int err, nbytes;
int error;
sc = device_get_softc(dev);
err = bus_generic_suspend(dev);
if (err)
return (err);
error = bus_generic_suspend(dev);
if (error != 0)
return (error);
vga_suspend(dev);
/* Save the video state across the suspend. */
if (sc->state_buf != NULL) {
free(sc->state_buf, M_TEMP);
sc->state_buf = NULL;
}
nbytes = vidd_save_state(sc->adp, NULL, 0);
if (nbytes <= 0)
return (0);
sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT | M_ZERO);
if (sc->state_buf == NULL)
return (0);
if (bootverbose)
device_printf(dev, "saving %d bytes of video state\n", nbytes);
if (vidd_save_state(sc->adp, sc->state_buf, nbytes) != 0) {
device_printf(dev, "failed to save state (nbytes=%d)\n",
nbytes);
free(sc->state_buf, M_TEMP);
sc->state_buf = NULL;
}
return (0);
return (error);
}
static int
isavga_resume(device_t dev)
{
vga_softc_t *sc;
sc = device_get_softc(dev);
if (sc->state_buf != NULL) {
if (vidd_load_state(sc->adp, sc->state_buf) != 0)
device_printf(dev, "failed to reload state\n");
free(sc->state_buf, M_TEMP);
sc->state_buf = NULL;
}
vga_resume(dev);
bus_generic_resume(dev);
return 0;
return (bus_generic_resume(dev));
}
#ifdef FB_INSTALL_CDEV
@ -215,37 +250,37 @@ isavga_resume(device_t dev)
static int
isavga_open(struct cdev *dev, int flag, int mode, struct thread *td)
{
return vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td);
return (vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td));
}
static int
isavga_close(struct cdev *dev, int flag, int mode, struct thread *td)
{
return vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td);
return (vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td));
}
static int
isavga_read(struct cdev *dev, struct uio *uio, int flag)
{
return vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag);
return (vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag));
}
static int
isavga_write(struct cdev *dev, struct uio *uio, int flag)
{
return vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag);
return (vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag));
}
static int
isavga_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
{
return vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), cmd, arg, flag, td);
return (vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), cmd, arg, flag, td));
}
static int
isavga_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int prot)
{
return vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), offset, paddr, prot);
return (vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), offset, paddr, prot));
}
#endif /* FB_INSTALL_CDEV */
@ -268,3 +303,79 @@ static driver_t isavga_driver = {
};
DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0);
static devclass_t vgapm_devclass;
static void
vgapm_identify(driver_t *driver, device_t parent)
{
if (device_get_flags(parent) != 0)
device_add_child(parent, "vgapm", 0);
}
static int
vgapm_probe(device_t dev)
{
device_set_desc(dev, "VGA suspend/resume");
device_quiet(dev);
return (BUS_PROBE_DEFAULT);
}
static int
vgapm_attach(device_t dev)
{
bus_generic_probe(dev);
bus_generic_attach(dev);
return (0);
}
static int
vgapm_suspend(device_t dev)
{
device_t vga_dev;
int error;
error = bus_generic_suspend(dev);
if (error != 0)
return (error);
vga_dev = devclass_get_device(isavga_devclass, 0);
if (vga_dev == NULL)
return (0);
vga_suspend(vga_dev);
return (0);
}
static int
vgapm_resume(device_t dev)
{
device_t vga_dev;
vga_dev = devclass_get_device(isavga_devclass, 0);
if (vga_dev != NULL)
vga_resume(vga_dev);
return (bus_generic_resume(dev));
}
static device_method_t vgapm_methods[] = {
DEVMETHOD(device_identify, vgapm_identify),
DEVMETHOD(device_probe, vgapm_probe),
DEVMETHOD(device_attach, vgapm_attach),
DEVMETHOD(device_suspend, vgapm_suspend),
DEVMETHOD(device_resume, vgapm_resume),
{ 0, 0 }
};
static driver_t vgapm_driver = {
"vgapm",
vgapm_methods,
0
};
DRIVER_MODULE(vgapm, vgapci, vgapm_driver, vgapm_devclass, 0, 0);

View File

@ -300,6 +300,7 @@ SUBDIR= ${_3dfx} \
wlan_xauth \
${_wpi} \
${_wpifw} \
${_x86bios} \
${_xe} \
xfs \
xl \
@ -463,6 +464,7 @@ _padlock= padlock
_s3= s3
_twa= twa
_vesa= vesa
_x86bios= x86bios
.elif ${MACHINE} == "pc98"
_canbepm= canbepm
_canbus= canbus
@ -490,6 +492,7 @@ _cpufreq= cpufreq
.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
_cyclic= cyclic
.endif
_dpms= dpms
_drm= drm
.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
_dtrace= dtrace
@ -538,14 +541,18 @@ _padlock= padlock
.endif
_pccard= pccard
_rdma= rdma
_s3= s3
_safe= safe
_scsi_low= scsi_low
_smbfs= smbfs
_sound= sound
_speaker= speaker
_splash= splash
_sppp= sppp
_tmpfs= tmpfs
_twa= twa
_vesa= vesa
_x86bios= x86bios
_wi= wi
_wpi= wpi
_wpifw= wpifw

View File

@ -1,9 +1,9 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../i386/isa
KMOD= dpms
SRCS= dpms.c
SRCS+= bus_if.h device_if.h
SRCS= bus_if.h device_if.h pci_if.h
.PATH: ${.CURDIR}/../../dev/dpms
SRCS+= dpms.c
.include <bsd.kmod.mk>

View File

@ -1,8 +1,13 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/syscons ${.CURDIR}/../../i386/isa
KMOD= vesa
SRCS= vesa.c scvesactl.c opt_vga.h opt_vesa.h
SRCS= opt_vga.h opt_vesa.h
SRCS+= bus_if.h device_if.h pci_if.h
.PATH: ${.CURDIR}/../../dev/fb
SRCS+= vesa.c
.PATH: ${.CURDIR}/../../dev/syscons
SRCS+= scvesactl.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,11 @@
# $FreeBSD$
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 x86emu.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,8 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../contrib/x86emu
KMOD= x86emu
SRCS= x86emu.c x86emu_util.c
.include <bsd.kmod.mk>

View File

@ -269,6 +269,7 @@ struct video_info {
#define V_INFO_GRAPHICS (1 << 1)
#define V_INFO_LINEAR (1 << 2)
#define V_INFO_VESA (1 << 3)
#define V_INFO_NONVGA (1 << 4)
int vi_width;
int vi_height;
int vi_cwidth;
@ -331,6 +332,7 @@ struct video_adapter {
#define V_ADP_INITIALIZED (1 << 17)
#define V_ADP_REGISTERED (1 << 18)
#define V_ADP_ATTACHED (1 << 19)
#define V_ADP_DAC8 (1 << 20)
vm_offset_t va_io_base;
int va_io_size;
vm_offset_t va_crtc_addr;

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 800503 /* Master, propagated to newvers */
#define __FreeBSD_version 800504 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>