xserver-multidpi/hw/xfree86/int10/helper_exec.c
Adam Jackson cc7c045bae Fix PCI config space cycles from int10 emulator.
The top bit of 0xCF8 is an enable bit, not part of the domain.  Sending
cycles to domain 128 instead of domain 0 is rarely the right thing to do.
2008-04-04 12:58:12 -04:00

741 lines
18 KiB
C

/*
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
*
* Part of this code was inspired by the VBIOS POSTing code in DOSEMU
* developed by the "DOSEMU-Development-Team"
*/
/*
* To debug port accesses define PRINT_PORT to 1.
* Note! You also have to comment out ioperm()
* in xf86EnableIO(). Otherwise we won't trap
* on PIO.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#define PRINT_PORT 0
#include <unistd.h>
#include <X11/Xos.h>
#include "xf86.h"
#include "xf86_OSproc.h"
#include "compiler.h"
#define _INT10_PRIVATE
#include "int10Defines.h"
#include "xf86int10.h"
#include "Pci.h"
#ifdef _X86EMU
#include "x86emu/x86emui.h"
#endif
#include <pciaccess.h>
static int pciCfg1in(CARD16 addr, CARD32 *val);
static int pciCfg1out(CARD16 addr, CARD32 val);
static int pciCfg1inw(CARD16 addr, CARD16 *val);
static int pciCfg1outw(CARD16 addr, CARD16 val);
static int pciCfg1inb(CARD16 addr, CARD8 *val);
static int pciCfg1outb(CARD16 addr, CARD8 val);
#if defined (_PC)
static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set);
#endif
#define REG pInt
int
setup_int(xf86Int10InfoPtr pInt)
{
if (pInt != Int10Current) {
if (!MapCurrentInt10(pInt))
return -1;
Int10Current = pInt;
}
X86_EAX = (CARD32) pInt->ax;
X86_EBX = (CARD32) pInt->bx;
X86_ECX = (CARD32) pInt->cx;
X86_EDX = (CARD32) pInt->dx;
X86_ESI = (CARD32) pInt->si;
X86_EDI = (CARD32) pInt->di;
X86_EBP = (CARD32) pInt->bp;
X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4;
X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */
X86_DS = 0x40; /* standard pc ds */
X86_ES = pInt->es;
X86_FS = 0;
X86_GS = 0;
X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
#if defined (_PC)
if (pInt->Flags & SET_BIOS_SCRATCH)
SetResetBIOSVars(pInt, TRUE);
#endif
return xf86BlockSIGIO();
}
void
finish_int(xf86Int10InfoPtr pInt, int sig)
{
xf86UnblockSIGIO(sig);
pInt->ax = (CARD32) X86_EAX;
pInt->bx = (CARD32) X86_EBX;
pInt->cx = (CARD32) X86_ECX;
pInt->dx = (CARD32) X86_EDX;
pInt->si = (CARD32) X86_ESI;
pInt->di = (CARD32) X86_EDI;
pInt->es = (CARD16) X86_ES;
pInt->bp = (CARD32) X86_EBP;
pInt->flags = (CARD32) X86_FLAGS;
#if defined (_PC)
if (pInt->Flags & RESTORE_BIOS_SCRATCH)
SetResetBIOSVars(pInt, FALSE);
#endif
}
/* general software interrupt handler */
CARD32
getIntVect(xf86Int10InfoPtr pInt,int num)
{
return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4);
}
void
pushw(xf86Int10InfoPtr pInt, CARD16 val)
{
X86_ESP -= 2;
MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val);
}
int
run_bios_int(int num, xf86Int10InfoPtr pInt)
{
CARD32 eflags;
#ifndef _PC
/* check if bios vector is initialized */
if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/
if (num == 21 && X86_AH == 0x4e) {
xf86DrvMsg(pInt->scrnIndex, X_NOTICE,
"Failing Find-Matching-File on non-PC"
" (int 21, func 4e)\n");
X86_AX = 2;
SET_FLAG(F_CF);
return 1;
} else {
xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2,
"Ignoring int 0x%02x call\n", num);
if (xf86GetVerbosity() > 3) {
dump_registers(pInt);
stack_trace(pInt);
}
return 1;
}
}
#endif
#ifdef PRINT_INT
ErrorF("calling card BIOS at: ");
#endif
eflags = X86_EFLAGS;
#if 0
eflags = eflags | IF_MASK;
X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK);
#endif
pushw(pInt, eflags);
pushw(pInt, X86_CS);
pushw(pInt, X86_IP);
X86_CS = MEM_RW(pInt, (num << 2) + 2);
X86_IP = MEM_RW(pInt, num << 2);
#ifdef PRINT_INT
ErrorF("0x%x:%lx\n", X86_CS, X86_EIP);
#endif
return 1;
}
/* Debugging stuff */
void
dump_code(xf86Int10InfoPtr pInt)
{
int i;
unsigned long lina = SEG_ADR((CARD32), X86_CS, IP);
xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina);
for (i=0; i<0x10; i++)
xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
xf86ErrorFVerb(3, "\n");
for (; i<0x20; i++)
xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
xf86ErrorFVerb(3, "\n");
}
void
dump_registers(xf86Int10InfoPtr pInt)
{
xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
"EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n",
(unsigned long)X86_EAX, (unsigned long)X86_EBX,
(unsigned long)X86_ECX, (unsigned long)X86_EDX);
xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
"ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n",
(unsigned long)X86_ESP, (unsigned long)X86_EBP,
(unsigned long)X86_ESI, (unsigned long)X86_EDI);
xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
"CS=0x%4.4x, SS=0x%4.4x,"
" DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n",
X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS);
xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
"EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n",
(unsigned long)X86_EIP, (unsigned long)X86_EFLAGS);
}
void
stack_trace(xf86Int10InfoPtr pInt)
{
int i = 0;
unsigned long stack = SEG_ADR((CARD32), X86_SS, SP);
unsigned long tail = (CARD32)((X86_SS << 4) + 0x1000);
if (stack >= tail) return;
xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack);
for (; stack < tail; stack++) {
xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack));
i = (i + 1) % 0x10;
if (!i)
xf86ErrorFVerb(3, "\n");
}
if (i)
xf86ErrorFVerb(3, "\n");
}
int
port_rep_inb(xf86Int10InfoPtr pInt,
CARD16 port, CARD32 base, int d_f, CARD32 count)
{
register int inc = d_f ? -1 : 1;
CARD32 dst = base;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" rep_insb(%#x) %d bytes at %8.8x %s\n",
port, count, base, d_f ? "up" : "down");
while (count--) {
MEM_WB(pInt, dst, x_inb(port));
dst += inc;
}
return dst - base;
}
int
port_rep_inw(xf86Int10InfoPtr pInt,
CARD16 port, CARD32 base, int d_f, CARD32 count)
{
register int inc = d_f ? -2 : 2;
CARD32 dst = base;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" rep_insw(%#x) %d bytes at %8.8x %s\n",
port, count, base, d_f ? "up" : "down");
while (count--) {
MEM_WW(pInt, dst, x_inw(port));
dst += inc;
}
return dst - base;
}
int
port_rep_inl(xf86Int10InfoPtr pInt,
CARD16 port, CARD32 base, int d_f, CARD32 count)
{
register int inc = d_f ? -4 : 4;
CARD32 dst = base;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" rep_insl(%#x) %d bytes at %8.8x %s\n",
port, count, base, d_f ? "up" : "down");
while (count--) {
MEM_WL(pInt, dst, x_inl(port));
dst += inc;
}
return dst - base;
}
int
port_rep_outb(xf86Int10InfoPtr pInt,
CARD16 port, CARD32 base, int d_f, CARD32 count)
{
register int inc = d_f ? -1 : 1;
CARD32 dst = base;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" rep_outb(%#x) %d bytes at %8.8x %s\n",
port, count, base, d_f ? "up" : "down");
while (count--) {
x_outb(port, MEM_RB(pInt, dst));
dst += inc;
}
return dst - base;
}
int
port_rep_outw(xf86Int10InfoPtr pInt,
CARD16 port, CARD32 base, int d_f, CARD32 count)
{
register int inc = d_f ? -2 : 2;
CARD32 dst = base;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" rep_outw(%#x) %d bytes at %8.8x %s\n",
port, count, base, d_f ? "up" : "down");
while (count--) {
x_outw(port, MEM_RW(pInt, dst));
dst += inc;
}
return dst - base;
}
int
port_rep_outl(xf86Int10InfoPtr pInt,
CARD16 port, CARD32 base, int d_f, CARD32 count)
{
register int inc = d_f ? -4 : 4;
CARD32 dst = base;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" rep_outl(%#x) %d bytes at %8.8x %s\n",
port, count, base, d_f ? "up" : "down");
while (count--) {
x_outl(port, MEM_RL(pInt, dst));
dst += inc;
}
return dst - base;
}
CARD8
x_inb(CARD16 port)
{
CARD8 val;
if (port == 0x40) {
Int10Current->inb40time++;
val = (CARD8)(Int10Current->inb40time >>
((Int10Current->inb40time & 1) << 3));
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" inb(%#x) = %2.2x\n", port, val);
#ifdef __NOT_YET__
} else if (port < 0x0100) { /* Don't interfere with mainboard */
val = 0;
xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
"inb 0x%4.4x\n", port);
if (xf86GetVerbosity() > 3) {
dump_registers(Int10Current);
stack_trace(Int10Current);
}
#endif /* __NOT_YET__ */
} else if (!pciCfg1inb(port, &val)) {
val = inb(Int10Current->ioBase + port);
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" inb(%#x) = %2.2x\n", port, val);
}
return val;
}
CARD16
x_inw(CARD16 port)
{
CARD16 val;
if (port == 0x5c) {
struct timeval tv;
/*
* Emulate a PC98's timer. Typical resolution is 3.26 usec.
* Approximate this by dividing by 3.
*/
X_GETTIMEOFDAY(&tv);
val = (CARD16)(tv.tv_usec / 3);
} else if (!pciCfg1inw(port, &val)) {
val = inw(Int10Current->ioBase + port);
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" inw(%#x) = %4.4x\n", port, val);
}
return val;
}
void
x_outb(CARD16 port, CARD8 val)
{
if ((port == 0x43) && (val == 0)) {
struct timeval tv;
/*
* Emulate a PC's timer 0. Such timers typically have a resolution of
* some .838 usec per tick, but this can only provide 1 usec per tick.
* (Not that this matters much, given inherent emulation delays.) Use
* the bottom bit as a byte select. See inb(0x40) above.
*/
X_GETTIMEOFDAY(&tv);
Int10Current->inb40time = (CARD16)(tv.tv_usec | 1);
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" outb(%#x, %2.2x)\n", port, val);
#ifdef __NOT_YET__
} else if (port < 0x0100) { /* Don't interfere with mainboard */
xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
"outb 0x%4.4x,0x%2.2x\n", port, val);
if (xf86GetVerbosity() > 3) {
dump_registers(Int10Current);
stack_trace(Int10Current);
}
#endif /* __NOT_YET__ */
} else if (!pciCfg1outb(port, val)) {
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" outb(%#x, %2.2x)\n", port, val);
outb(Int10Current->ioBase + port, val);
}
}
void
x_outw(CARD16 port, CARD16 val)
{
if (!pciCfg1outw(port, val)) {
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" outw(%#x, %4.4x)\n", port, val);
outw(Int10Current->ioBase + port, val);
}
}
CARD32
x_inl(CARD16 port)
{
CARD32 val;
if (!pciCfg1in(port, &val)) {
val = inl(Int10Current->ioBase + port);
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" inl(%#x) = %8.8x\n", port, val);
}
return val;
}
void
x_outl(CARD16 port, CARD32 val)
{
if (!pciCfg1out(port, val)) {
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" outl(%#x, %8.8x)\n", port, val);
outl(Int10Current->ioBase + port, val);
}
}
CARD8
Mem_rb(CARD32 addr)
{
return (*Int10Current->mem->rb)(Int10Current, addr);
}
CARD16
Mem_rw(CARD32 addr)
{
return (*Int10Current->mem->rw)(Int10Current, addr);
}
CARD32
Mem_rl(CARD32 addr)
{
return (*Int10Current->mem->rl)(Int10Current, addr);
}
void
Mem_wb(CARD32 addr, CARD8 val)
{
(*Int10Current->mem->wb)(Int10Current, addr, val);
}
void
Mem_ww(CARD32 addr, CARD16 val)
{
(*Int10Current->mem->ww)(Int10Current, addr, val);
}
void
Mem_wl(CARD32 addr, CARD32 val)
{
(*Int10Current->mem->wl)(Int10Current, addr, val);
}
static CARD32 PciCfg1Addr = 0;
#define PCI_OFFSET(x) ((x) & 0x000000ff)
#define PCI_TAG(x) ((x) & 0x7fffff00)
static struct pci_device*
pci_device_for_cfg_address (CARD32 addr)
{
struct pci_device *dev = NULL;
PCITAG tag = PCI_TAG(addr);
struct pci_slot_match slot_match = {
.domain = PCI_DOM_FROM_TAG(tag),
.bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)),
.dev = PCI_DEV_FROM_TAG(tag),
.func = PCI_FUNC_FROM_TAG(tag),
.match_data = 0
};
struct pci_device_iterator *iter =
pci_slot_match_iterator_create (&slot_match);
if (iter)
dev = pci_device_next(iter);
if (!dev) {
char buf[128]; /* enough to store "%u@%u" */
xf86FormatPciBusNumber(tag >> 16, buf);
ErrorF("Failed to find device matching %s:%u:%u\n",
buf, slot_match.dev, slot_match.func);
return NULL;
}
if (pci_device_next(iter)) {
char buf[128]; /* enough to store "%u@%u" */
xf86FormatPciBusNumber(tag >> 16, buf);
ErrorF("Multiple devices matching %s:%u:%u\n",
buf, slot_match.dev, slot_match.func);
}
return dev;
}
static int
pciCfg1in(CARD16 addr, CARD32 *val)
{
if (addr == 0xCF8) {
*val = PciCfg1Addr;
return 1;
}
if (addr == 0xCFC) {
pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr),
val, PCI_OFFSET(PciCfg1Addr));
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" cfg_inl(%#x) = %8.8x\n", PciCfg1Addr, *val);
return 1;
}
return 0;
}
static int
pciCfg1out(CARD16 addr, CARD32 val)
{
if (addr == 0xCF8) {
PciCfg1Addr = val;
return 1;
}
if (addr == 0xCFC) {
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" cfg_outl(%#x, %8.8x)\n", PciCfg1Addr, val);
pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr),
val, PCI_OFFSET(PciCfg1Addr));
return 1;
}
return 0;
}
static int
pciCfg1inw(CARD16 addr, CARD16 *val)
{
int shift;
if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
shift = (addr - 0xCF8) * 8;
*val = (PciCfg1Addr >> shift) & 0xffff;
return 1;
}
if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
const unsigned offset = addr - 0xCFC;
pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr),
val, PCI_OFFSET(PciCfg1Addr) + offset);
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" cfg_inw(%#x) = %4.4x\n", PciCfg1Addr + offset, *val);
return 1;
}
return 0;
}
static int
pciCfg1outw(CARD16 addr, CARD16 val)
{
int shift;
if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
shift = (addr - 0xCF8) * 8;
PciCfg1Addr &= ~(0xffff << shift);
PciCfg1Addr |= ((CARD32) val) << shift;
return 1;
}
if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
const unsigned offset = addr - 0xCFC;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" cfg_outw(%#x, %4.4x)\n", PciCfg1Addr + offset, val);
pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr),
val, PCI_OFFSET(PciCfg1Addr) + offset);
return 1;
}
return 0;
}
static int
pciCfg1inb(CARD16 addr, CARD8 *val)
{
int shift;
if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
shift = (addr - 0xCF8) * 8;
*val = (PciCfg1Addr >> shift) & 0xff;
return 1;
}
if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
const unsigned offset = addr - 0xCFC;
pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr),
val, PCI_OFFSET(PciCfg1Addr) + offset);
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" cfg_inb(%#x) = %2.2x\n", PciCfg1Addr + offset, *val);
return 1;
}
return 0;
}
static int
pciCfg1outb(CARD16 addr, CARD8 val)
{
int shift;
if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
shift = (addr - 0xCF8) * 8;
PciCfg1Addr &= ~(0xff << shift);
PciCfg1Addr |= ((CARD32) val) << shift;
return 1;
}
if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
const unsigned offset = addr - 0xCFC;
if (PRINT_PORT && DEBUG_IO_TRACE())
ErrorF(" cfg_outb(%#x, %2.2x)\n", PciCfg1Addr + offset, val);
pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr),
val, PCI_OFFSET(PciCfg1Addr) + offset);
return 1;
}
return 0;
}
CARD8
bios_checksum(const CARD8 *start, int size)
{
CARD8 sum = 0;
while (size-- > 0)
sum += *start++;
return sum;
}
/*
* Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
* an attempt to detect a legacy ISA card. If they find one they might
* act very strange: for example they might configure the card as a
* monochrome card. This might cause some drivers to choke.
* To avoid this we attempt legacy VGA by writing to all know VGA
* disable registers before we call the BIOS initialization and
* restore the original values afterwards. In beween we hold our
* breath. To get to a (possibly exising) ISA card need to disable
* our current PCI card.
*/
/*
* This is just for booting: we just want to catch pure
* legacy vga therefore we don't worry about mmio etc.
* This stuff should really go into vgaHW.c. However then
* the driver would have to load the vga-module prior to
* doing int10.
*/
void
LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
{
xf86SetCurrentAccess(FALSE, xf86Screens[pInt->scrnIndex]);
vga->save_msr = inb(pInt->ioBase + 0x03CC);
vga->save_vse = inb(pInt->ioBase + 0x03C3);
#ifndef __ia64__
vga->save_46e8 = inb(pInt->ioBase + 0x46E8);
#endif
vga->save_pos102 = inb(pInt->ioBase + 0x0102);
outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr);
outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse);
#ifndef __ia64__
outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8);
#endif
outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102);
xf86SetCurrentAccess(TRUE, xf86Screens[pInt->scrnIndex]);
}
void
UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
{
xf86SetCurrentAccess(FALSE, xf86Screens[pInt->scrnIndex]);
outb(pInt->ioBase + 0x0102, vga->save_pos102);
#ifndef __ia64__
outb(pInt->ioBase + 0x46E8, vga->save_46e8);
#endif
outb(pInt->ioBase + 0x03C3, vga->save_vse);
outb(pInt->ioBase + 0x03C2, vga->save_msr);
xf86SetCurrentAccess(TRUE, xf86Screens[pInt->scrnIndex]);
}
#if defined (_PC)
static void
SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set)
{
int pagesize = getpagesize();
unsigned char* base = xf86MapVidMem(pInt->scrnIndex,
VIDMEM_MMIO, 0, pagesize);
int i;
if (set) {
for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
MEM_WW(pInt, i, *(base + i));
} else {
for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
*(base + i) = MEM_RW(pInt, i);
}
xf86UnMapVidMem(pInt->scrnIndex,base,pagesize);
}
void
xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save)
{
int pagesize = getpagesize();
unsigned char* base;
int i;
if (!xf86IsEntityPrimary(pInt->entityIndex)
|| (!save && !pInt->BIOSScratch))
return;
base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize);
base += BIOS_SCRATCH_OFF;
if (save) {
if ((pInt->BIOSScratch
= xnfalloc(BIOS_SCRATCH_LEN)))
for (i = 0; i < BIOS_SCRATCH_LEN; i++)
*(((char*)pInt->BIOSScratch + i)) = *(base + i);
} else {
if (pInt->BIOSScratch) {
for (i = 0; i < BIOS_SCRATCH_LEN; i++)
*(base + i) = *(pInt->BIOSScratch + i);
xfree(pInt->BIOSScratch);
pInt->BIOSScratch = NULL;
}
}
xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize);
}
#endif
xf86Int10InfoPtr
xf86InitInt10(int entityIndex)
{
return xf86ExtendedInitInt10(entityIndex, 0);
}