xserver-multidpi/hw/xfree86/os-support/bsd/i386_video.c
Keith Packard 9838b7032e Introduce a consistent coding style
This is strictly the application of the script 'x-indent-all.sh'
from util/modular. Compared to the patch that Daniel posted in
January, I've added a few indent flags:

	-bap
	-psl
	-T PrivatePtr
	-T pmWait
	-T _XFUNCPROTOBEGIN
	-T _XFUNCPROTOEND
	-T _X_EXPORT

The typedefs were needed to make the output of sdksyms.sh match the
previous output, otherwise, the code is formatted badly enough that
sdksyms.sh generates incorrect output.

The generated code was compared with the previous version and found to
be essentially identical -- "assert" line numbers and BUILD_TIME were
the only differences found.

The comparison was done with this script:

dir1=$1
dir2=$2

for dir in $dir1 $dir2; do
	(cd $dir && find . -name '*.o' | while read file; do
		dir=`dirname $file`
		base=`basename $file .o`
		dump=$dir/$base.dump
		objdump -d $file > $dump
	done)
done

find $dir1 -name '*.dump' | while read dump; do
	otherdump=`echo $dump | sed "s;$dir1;$dir2;"`
	diff -u $dump $otherdump
done

Signed-off-by: Keith Packard <keithp@keithp.com>
Acked-by: Daniel Stone <daniel@fooishbar.org>
Acked-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2012-03-21 13:54:42 -07:00

887 lines
23 KiB
C

/*
* Copyright 1992 by Rich Murphey <Rich@Rice.edu>
* Copyright 1993 by David Wexelblat <dwex@goblin.org>
*
* 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 names of Rich Murphey and David Wexelblat
* not be used in advertising or publicity pertaining to distribution of
* the software without specific, written prior permission. Rich Murphey and
* David Wexelblat make no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT 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.
*
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <X11/X.h>
#include "xf86.h"
#include "xf86Priv.h"
#include <errno.h>
#include <sys/mman.h>
#ifdef HAS_MTRR_SUPPORT
#ifndef __NetBSD__
#include <sys/types.h>
#include <sys/memrange.h>
#else
#include "memrange.h"
#endif
#define X_MTRR_ID "XFree86"
#endif
#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__)
#include <machine/mtrr.h>
#include <machine/sysarch.h>
#include <sys/queue.h>
#ifdef __x86_64__
#define i386_set_mtrr x86_64_set_mtrr
#define i386_get_mtrr x86_64_get_mtrr
#define i386_iopl x86_64_iopl
#endif
#endif
#include "xf86_OSlib.h"
#include "xf86OSpriv.h"
#if defined(__NetBSD__) && !defined(MAP_FILE)
#define MAP_FLAGS MAP_SHARED
#else
#define MAP_FLAGS (MAP_FILE | MAP_SHARED)
#endif
#ifdef __OpenBSD__
#define SYSCTL_MSG "\tCheck that you have set 'machdep.allowaperture=1'\n"\
"\tin /etc/sysctl.conf and reboot your machine\n" \
"\trefer to xf86(4) for details"
#define SYSCTL_MSG2 \
"Check that you have set 'machdep.allowaperture=2'\n" \
"\tin /etc/sysctl.conf and reboot your machine\n" \
"\trefer to xf86(4) for details"
#endif
/***************************************************************************/
/* Video Memory Mapping section */
/***************************************************************************/
static Bool useDevMem = FALSE;
static int devMemFd = -1;
#ifdef HAS_APERTURE_DRV
#define DEV_APERTURE "/dev/xf86"
#endif
static pointer mapVidMem(int, unsigned long, unsigned long, int);
static void unmapVidMem(int, pointer, unsigned long);
#ifdef HAS_MTRR_SUPPORT
static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType);
static void undoWC(int, pointer);
static Bool cleanMTRR(void);
#endif
#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__)
static pointer NetBSDsetWC(int, unsigned long, unsigned long, Bool,
MessageType);
static void NetBSDundoWC(int, pointer);
#endif
/*
* Check if /dev/mem can be mmap'd. If it can't print a warning when
* "warn" is TRUE.
*/
static void
checkDevMem(Bool warn)
{
static Bool devMemChecked = FALSE;
int fd;
pointer base;
if (devMemChecked)
return;
devMemChecked = TRUE;
if ((fd = open(DEV_MEM, O_RDWR)) >= 0) {
/* Try to map a page at the VGA address */
base = mmap((caddr_t) 0, 4096, PROT_READ | PROT_WRITE,
MAP_FLAGS, fd, (off_t) 0xA0000);
if (base != MAP_FAILED) {
munmap((caddr_t) base, 4096);
devMemFd = fd;
useDevMem = TRUE;
return;
}
else {
/* This should not happen */
if (warn) {
xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n",
DEV_MEM, strerror(errno));
}
useDevMem = FALSE;
return;
}
}
#ifndef HAS_APERTURE_DRV
if (warn) {
xf86Msg(X_WARNING, "checkDevMem: failed to open %s (%s)\n",
DEV_MEM, strerror(errno));
}
useDevMem = FALSE;
return;
#else
/* Failed to open /dev/mem, try the aperture driver */
if ((fd = open(DEV_APERTURE, O_RDWR)) >= 0) {
/* Try to map a page at the VGA address */
base = mmap((caddr_t) 0, 4096, PROT_READ | PROT_WRITE,
MAP_FLAGS, fd, (off_t) 0xA0000);
if (base != MAP_FAILED) {
munmap((caddr_t) base, 4096);
devMemFd = fd;
useDevMem = TRUE;
xf86Msg(X_INFO, "checkDevMem: using aperture driver %s\n",
DEV_APERTURE);
return;
}
else {
if (warn) {
xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n",
DEV_APERTURE, strerror(errno));
}
}
}
else {
if (warn) {
#ifndef __OpenBSD__
xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n"
"\t(%s)\n", DEV_MEM, DEV_APERTURE, strerror(errno));
#else /* __OpenBSD__ */
xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n"
"\t(%s)\n%s", DEV_MEM, DEV_APERTURE, strerror(errno),
SYSCTL_MSG);
#endif /* __OpenBSD__ */
}
}
useDevMem = FALSE;
return;
#endif
}
void
xf86OSInitVidMem(VidMemInfoPtr pVidMem)
{
checkDevMem(TRUE);
pVidMem->linearSupported = useDevMem;
pVidMem->mapMem = mapVidMem;
pVidMem->unmapMem = unmapVidMem;
if (useDevMem)
pci_system_init_dev_mem(devMemFd);
#ifdef HAS_MTRR_SUPPORT
if (useDevMem) {
if (cleanMTRR()) {
pVidMem->setWC = setWC;
pVidMem->undoWC = undoWC;
}
}
#endif
#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__)
pVidMem->setWC = NetBSDsetWC;
pVidMem->undoWC = NetBSDundoWC;
#endif
pVidMem->initialised = TRUE;
}
static pointer
mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
{
pointer base;
checkDevMem(FALSE);
if (useDevMem) {
if (devMemFd < 0) {
FatalError("xf86MapVidMem: failed to open %s (%s)",
DEV_MEM, strerror(errno));
}
base = mmap((caddr_t) 0, Size,
(flags & VIDMEM_READONLY) ?
PROT_READ : (PROT_READ | PROT_WRITE),
MAP_FLAGS, devMemFd, (off_t) Base);
if (base == MAP_FAILED) {
FatalError("%s: could not mmap %s [s=%lx,a=%lx] (%s)",
"xf86MapVidMem", DEV_MEM, Size, Base, strerror(errno));
}
return base;
}
/* else, mmap /dev/vga */
if ((unsigned long) Base < 0xA0000 || (unsigned long) Base >= 0xC0000) {
FatalError("%s: Address 0x%lx outside allowable range",
"xf86MapVidMem", Base);
}
base = mmap(0, Size,
(flags & VIDMEM_READONLY) ?
PROT_READ : (PROT_READ | PROT_WRITE),
MAP_FLAGS, xf86Info.consoleFd, (unsigned long) Base - 0xA0000);
if (base == MAP_FAILED) {
FatalError("xf86MapVidMem: Could not mmap /dev/vga (%s)",
strerror(errno));
}
return base;
}
static void
unmapVidMem(int ScreenNum, pointer Base, unsigned long Size)
{
munmap((caddr_t) Base, Size);
}
/*
* Read BIOS via mmap()ing DEV_MEM
*/
int
xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf,
int Len)
{
unsigned char *ptr;
int psize;
int mlen;
checkDevMem(TRUE);
if (devMemFd == -1) {
return -1;
}
psize = getpagesize();
Offset += Base & (psize - 1);
Base &= ~(psize - 1);
mlen = (Offset + Len + psize - 1) & ~(psize - 1);
ptr = (unsigned char *) mmap((caddr_t) 0, mlen, PROT_READ,
MAP_SHARED, devMemFd, (off_t) Base);
if ((long) ptr == -1) {
xf86Msg(X_WARNING,
"xf86ReadBIOS: %s mmap[s=%x,a=%lx,o=%lx] failed (%s)\n",
DEV_MEM, Len, Base, Offset, strerror(errno));
#ifdef __OpenBSD__
if (Base < 0xa0000) {
xf86Msg(X_WARNING, SYSCTL_MSG2);
}
#endif
return -1;
}
#ifdef DEBUG
ErrorF("xf86ReadBIOS: BIOS at 0x%08x has signature 0x%04x\n",
Base, ptr[0] | (ptr[1] << 8));
#endif
(void) memcpy(Buf, (void *) (ptr + Offset), Len);
(void) munmap((caddr_t) ptr, mlen);
#ifdef DEBUG
xf86MsgVerb(X_INFO, 3, "xf86ReadBIOS(%x, %x, Buf, %x)"
"-> %02x %02x %02x %02x...\n",
Base, Offset, Len, Buf[0], Buf[1], Buf[2], Buf[3]);
#endif
return Len;
}
#ifdef USE_I386_IOPL
/***************************************************************************/
/* I/O Permissions section */
/***************************************************************************/
static Bool ExtendedEnabled = FALSE;
Bool
xf86EnableIO()
{
if (ExtendedEnabled)
return TRUE;
if (i386_iopl(TRUE) < 0) {
#ifndef __OpenBSD__
xf86Msg(X_WARNING, "%s: Failed to set IOPL for extended I/O",
"xf86EnableIO");
#else
xf86Msg(X_WARNING, "%s: Failed to set IOPL for extended I/O\n%s",
"xf86EnableIO", SYSCTL_MSG);
#endif
return FALSE;
}
ExtendedEnabled = TRUE;
return TRUE;
}
void
xf86DisableIO()
{
if (!ExtendedEnabled)
return;
i386_iopl(FALSE);
ExtendedEnabled = FALSE;
return;
}
#endif /* USE_I386_IOPL */
#ifdef USE_AMD64_IOPL
/***************************************************************************/
/* I/O Permissions section */
/***************************************************************************/
static Bool ExtendedEnabled = FALSE;
Bool
xf86EnableIO()
{
if (ExtendedEnabled)
return TRUE;
if (amd64_iopl(TRUE) < 0) {
#ifndef __OpenBSD__
xf86Msg(X_WARNING, "%s: Failed to set IOPL for extended I/O",
"xf86EnableIO");
#else
xf86Msg(X_WARNING, "%s: Failed to set IOPL for extended I/O\n%s",
"xf86EnableIO", SYSCTL_MSG);
#endif
return FALSE;
}
ExtendedEnabled = TRUE;
return TRUE;
}
void
xf86DisableIO()
{
if (!ExtendedEnabled)
return;
if (amd64_iopl(FALSE) == 0) {
ExtendedEnabled = FALSE;
}
/* Otherwise, the X server has revoqued its root uid,
and thus cannot give up IO privileges any more */
return;
}
#endif /* USE_AMD64_IOPL */
#ifdef USE_DEV_IO
static int IoFd = -1;
Bool
xf86EnableIO()
{
if (IoFd >= 0)
return TRUE;
if ((IoFd = open("/dev/io", O_RDWR)) == -1) {
xf86Msg(X_WARNING, "xf86EnableIO: "
"Failed to open /dev/io for extended I/O");
return FALSE;
}
return TRUE;
}
void
xf86DisableIO()
{
if (IoFd < 0)
return;
close(IoFd);
IoFd = -1;
return;
}
#endif
#ifdef __NetBSD__
/***************************************************************************/
/* Set TV output mode */
/***************************************************************************/
void
xf86SetTVOut(int mode)
{
switch (xf86Info.consType) {
#ifdef PCCONS_SUPPORT
case PCCONS:{
if (ioctl(xf86Info.consoleFd, CONSOLE_X_TV_ON, &mode) < 0) {
xf86Msg(X_WARNING,
"xf86SetTVOut: Could not set console to TV output, %s\n",
strerror(errno));
}
}
break;
#endif /* PCCONS_SUPPORT */
default:
FatalError("Xf86SetTVOut: Unsupported console");
break;
}
return;
}
void
xf86SetRGBOut()
{
switch (xf86Info.consType) {
#ifdef PCCONS_SUPPORT
case PCCONS:{
if (ioctl(xf86Info.consoleFd, CONSOLE_X_TV_OFF, 0) < 0) {
xf86Msg(X_WARNING,
"xf86SetTVOut: Could not set console to RGB output, %s\n",
strerror(errno));
}
}
break;
#endif /* PCCONS_SUPPORT */
default:
FatalError("Xf86SetTVOut: Unsupported console");
break;
}
return;
}
#endif
#ifdef HAS_MTRR_SUPPORT
/* memory range (MTRR) support for FreeBSD */
/*
* This code is experimental. Some parts may be overkill, and other parts
* may be incomplete.
*/
/*
* getAllRanges returns the full list of memory ranges with attributes set.
*/
static struct mem_range_desc *
getAllRanges(int *nmr)
{
struct mem_range_desc *mrd;
struct mem_range_op mro;
/*
* Find how many ranges there are. If this fails, then the kernel
* probably doesn't have MTRR support.
*/
mro.mo_arg[0] = 0;
if (ioctl(devMemFd, MEMRANGE_GET, &mro))
return NULL;
*nmr = mro.mo_arg[0];
mrd = xnfalloc(*nmr * sizeof(struct mem_range_desc));
mro.mo_arg[0] = *nmr;
mro.mo_desc = mrd;
if (ioctl(devMemFd, MEMRANGE_GET, &mro)) {
free(mrd);
return NULL;
}
return mrd;
}
/*
* cleanMTRR removes any memory attribute that may be left by a previous
* X server. Normally there won't be any, but this takes care of the
* case where a server crashed without being able finish cleaning up.
*/
static Bool
cleanMTRR()
{
struct mem_range_desc *mrd;
struct mem_range_op mro;
int nmr, i;
/* This shouldn't happen */
if (devMemFd < 0)
return FALSE;
if (!(mrd = getAllRanges(&nmr)))
return FALSE;
for (i = 0; i < nmr; i++) {
if (strcmp(mrd[i].mr_owner, X_MTRR_ID) == 0 &&
(mrd[i].mr_flags & MDF_ACTIVE)) {
#ifdef DEBUG
ErrorF("Clean for (0x%lx,0x%lx)\n",
(unsigned long) mrd[i].mr_base,
(unsigned long) mrd[i].mr_len);
#endif
if (mrd[i].mr_flags & MDF_FIXACTIVE) {
mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
mrd[i].mr_flags = MDF_UNCACHEABLE;
}
else {
mro.mo_arg[0] = MEMRANGE_SET_REMOVE;
}
mro.mo_desc = mrd + i;
ioctl(devMemFd, MEMRANGE_SET, &mro);
}
}
#ifdef DEBUG
sleep(10);
#endif
free(mrd);
return TRUE;
}
typedef struct x_RangeRec {
struct mem_range_desc mrd;
Bool wasWC;
struct x_RangeRec *next;
} RangeRec, *RangePtr;
static void
freeRangeList(RangePtr range)
{
RangePtr rp;
while (range) {
rp = range;
range = rp->next;
free(rp);
}
}
static RangePtr
dupRangeList(RangePtr list)
{
RangePtr new = NULL, rp, p;
rp = list;
while (rp) {
p = xnfalloc(sizeof(RangeRec));
*p = *rp;
p->next = new;
new = p;
rp = rp->next;
}
return new;
}
static RangePtr
sortRangeList(RangePtr list)
{
RangePtr rp1, rp2, copy, sorted = NULL, minp, prev, minprev;
unsigned long minBase;
/* Sort by base address */
rp1 = copy = dupRangeList(list);
while (rp1) {
minBase = rp1->mrd.mr_base;
minp = rp1;
minprev = NULL;
prev = rp1;
rp2 = rp1->next;
while (rp2) {
if (rp2->mrd.mr_base < minBase) {
minBase = rp2->mrd.mr_base;
minp = rp2;
minprev = prev;
}
prev = rp2;
rp2 = rp2->next;
}
if (minprev) {
minprev->next = minp->next;
rp1 = copy;
}
else {
rp1 = minp->next;
}
minp->next = sorted;
sorted = minp;
}
return sorted;
}
/*
* findRanges returns a list of ranges that overlap the specified range.
*/
static void
findRanges(unsigned long base, unsigned long size, RangePtr * ucp,
RangePtr * wcp)
{
struct mem_range_desc *mrd;
int nmr, i;
RangePtr rp, *p;
if (!(mrd = getAllRanges(&nmr)))
return;
for (i = 0; i < nmr; i++) {
if ((mrd[i].mr_flags & MDF_ACTIVE) &&
mrd[i].mr_base < base + size &&
mrd[i].mr_base + mrd[i].mr_len > base) {
if (mrd[i].mr_flags & MDF_WRITECOMBINE)
p = wcp;
else if (mrd[i].mr_flags & MDF_UNCACHEABLE)
p = ucp;
else
continue;
rp = xnfalloc(sizeof(RangeRec));
rp->mrd = mrd[i];
rp->next = *p;
*p = rp;
}
}
free(mrd);
}
/*
* This checks if the existing overlapping ranges fully cover the requested
* range. Is this overkill?
*/
static Bool
fullCoverage(unsigned long base, unsigned long size, RangePtr overlap)
{
RangePtr rp1, sorted = NULL;
unsigned long end;
sorted = sortRangeList(overlap);
/* Look for gaps */
rp1 = sorted;
end = base + size;
while (rp1) {
if (rp1->mrd.mr_base > base) {
freeRangeList(sorted);
return FALSE;
}
else {
base = rp1->mrd.mr_base + rp1->mrd.mr_len;
}
if (base >= end) {
freeRangeList(sorted);
return TRUE;
}
rp1 = rp1->next;
}
freeRangeList(sorted);
return FALSE;
}
static pointer
addWC(int screenNum, unsigned long base, unsigned long size, MessageType from)
{
RangePtr uc = NULL, wc = NULL, retlist = NULL;
struct mem_range_desc mrd;
struct mem_range_op mro;
findRanges(base, size, &uc, &wc);
/* See of the full range is already WC */
if (!uc && fullCoverage(base, size, wc)) {
xf86DrvMsg(screenNum, from,
"Write-combining range (0x%lx,0x%lx) was already set\n",
base, size);
return NULL;
}
/* Otherwise, try to add the new range */
mrd.mr_base = base;
mrd.mr_len = size;
strcpy(mrd.mr_owner, X_MTRR_ID);
mrd.mr_flags = MDF_WRITECOMBINE;
mro.mo_desc = &mrd;
mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
if (ioctl(devMemFd, MEMRANGE_SET, &mro)) {
xf86DrvMsg(screenNum, X_WARNING,
"Failed to set write-combining range "
"(0x%lx,0x%lx)\n", base, size);
return NULL;
}
else {
xf86DrvMsg(screenNum, from,
"Write-combining range (0x%lx,0x%lx)\n", base, size);
retlist = xnfalloc(sizeof(RangeRec));
retlist->mrd = mrd;
retlist->wasWC = FALSE;
retlist->next = NULL;
return retlist;
}
}
static pointer
delWC(int screenNum, unsigned long base, unsigned long size, MessageType from)
{
RangePtr uc = NULL, wc = NULL, retlist = NULL;
struct mem_range_desc mrd;
struct mem_range_op mro;
findRanges(base, size, &uc, &wc);
/*
* See of the full range is already not WC, or if there is full
* coverage from UC ranges.
*/
if (!wc || fullCoverage(base, size, uc)) {
xf86DrvMsg(screenNum, from,
"Write-combining range (0x%lx,0x%lx) was already clear\n",
base, size);
return NULL;
}
/* Otherwise, try to add the new range */
mrd.mr_base = base;
mrd.mr_len = size;
strcpy(mrd.mr_owner, X_MTRR_ID);
mrd.mr_flags = MDF_UNCACHEABLE;
mro.mo_desc = &mrd;
mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
if (ioctl(devMemFd, MEMRANGE_SET, &mro)) {
xf86DrvMsg(screenNum, X_WARNING,
"Failed to remove write-combining range "
"(0x%lx,0x%lx)\n", base, size);
/* XXX Should then remove all of the overlapping WC ranges */
return NULL;
}
else {
xf86DrvMsg(screenNum, from,
"Removed Write-combining range (0x%lx,0x%lx)\n", base, size);
retlist = xnfalloc(sizeof(RangeRec));
retlist->mrd = mrd;
retlist->wasWC = TRUE;
retlist->next = NULL;
return retlist;
}
}
static pointer
setWC(int screenNum, unsigned long base, unsigned long size, Bool enable,
MessageType from)
{
if (enable)
return addWC(screenNum, base, size, from);
else
return delWC(screenNum, base, size, from);
}
static void
undoWC(int screenNum, pointer list)
{
RangePtr rp;
struct mem_range_op mro;
Bool failed;
rp = list;
while (rp) {
#ifdef DEBUG
ErrorF("Undo for (0x%lx,0x%lx), %d\n",
(unsigned long) rp->mrd.mr_base,
(unsigned long) rp->mrd.mr_len, rp->wasWC);
#endif
failed = FALSE;
if (rp->wasWC) {
mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
rp->mrd.mr_flags = MDF_WRITECOMBINE;
strcpy(rp->mrd.mr_owner, "unknown");
}
else {
mro.mo_arg[0] = MEMRANGE_SET_REMOVE;
}
mro.mo_desc = &rp->mrd;
if (ioctl(devMemFd, MEMRANGE_SET, &mro)) {
if (!rp->wasWC) {
mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
rp->mrd.mr_flags = MDF_UNCACHEABLE;
strcpy(rp->mrd.mr_owner, "unknown");
if (ioctl(devMemFd, MEMRANGE_SET, &mro))
failed = TRUE;
}
else
failed = TRUE;
}
if (failed) {
xf86DrvMsg(screenNum, X_WARNING,
"Failed to restore MTRR range (0x%lx,0x%lx)\n",
(unsigned long) rp->mrd.mr_base,
(unsigned long) rp->mrd.mr_len);
}
rp = rp->next;
}
}
#endif /* HAS_MTRR_SUPPORT */
#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__)
static pointer
NetBSDsetWC(int screenNum, unsigned long base, unsigned long size, Bool enable,
MessageType from)
{
struct mtrr *mtrrp;
int n;
xf86DrvMsg(screenNum, X_WARNING,
"%s MTRR %lx - %lx\n", enable ? "set" : "remove",
base, (base + size));
mtrrp = xnfalloc(sizeof(struct mtrr));
mtrrp->base = base;
mtrrp->len = size;
mtrrp->type = MTRR_TYPE_WC;
/*
* MTRR_PRIVATE will make this MTRR get reset automatically
* if this process exits, so we have no need for an explicit
* cleanup operation when starting a new server.
*/
if (enable)
mtrrp->flags = MTRR_VALID | MTRR_PRIVATE;
else
mtrrp->flags = 0;
n = 1;
if (i386_set_mtrr(mtrrp, &n) < 0) {
free(mtrrp);
return NULL;
}
return mtrrp;
}
static void
NetBSDundoWC(int screenNum, pointer list)
{
struct mtrr *mtrrp = (struct mtrr *) list;
int n;
if (mtrrp == NULL)
return;
n = 1;
mtrrp->flags &= ~MTRR_VALID;
i386_set_mtrr(mtrrp, &n);
free(mtrrp);
}
#endif