xserver-multidpi/hw/xfree86/os-support/linux/lnx_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

870 lines
26 KiB
C

/*
* Copyright 1992 by Orest Zborowski <obz@Kodak.com>
* 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 Orest Zborowski and David Wexelblat
* not be used in advertising or publicity pertaining to distribution of
* the software without specific, written prior permission. Orest Zborowski
* 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.
*
* OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI 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 <errno.h>
#include <string.h>
#include <X11/X.h>
#include "input.h"
#include "scrnintstr.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "xf86OSpriv.h"
#ifdef __alpha__
#include "shared/xf86Axp.h"
#endif
#ifdef HAS_MTRR_SUPPORT
#include <asm/mtrr.h>
#endif
static Bool ExtendedEnabled = FALSE;
#ifdef __ia64__
#include "compiler.h"
#include <sys/io.h>
#elif !defined(__powerpc__) && \
!defined(__mc68000__) && \
!defined(__sparc__) && \
!defined(__mips__) && \
!defined(__nds32__) && \
!defined(__arm__)
/*
* Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare
* these.
*/
extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on);
extern int iopl(int __level);
#endif
#ifdef __alpha__
#define BUS_BASE bus_base
#else
#define BUS_BASE (0)
#endif /* __alpha__ */
/***************************************************************************/
/* Video Memory Mapping section */
/***************************************************************************/
static pointer mapVidMem(int, unsigned long, unsigned long, int);
static void unmapVidMem(int, pointer, unsigned long);
#if defined (__alpha__)
extern void sethae(unsigned long hae);
extern unsigned long _bus_base __P((void)) __attribute__ ((const));
extern unsigned long _bus_base_sparse __P((void)) __attribute__ ((const));
static pointer mapVidMemSparse(int, unsigned long, unsigned long, int);
extern axpDevice lnxGetAXP(void);
static void unmapVidMemSparse(int, pointer, unsigned long);
static axpDevice axpSystem = -1;
static Bool needSparse;
static unsigned long hae_thresh;
static unsigned long hae_mask;
static unsigned long bus_base;
#endif
#ifdef HAS_MTRR_SUPPORT
#define SPLIT_WC_REGIONS 1
static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType);
static void undoWC(int, pointer);
/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr
driver will clean up when we exit. */
#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */
#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had
a problem. */
static int mtrr_fd = MTRR_FD_UNOPENED;
/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0,
and will fail on Linux 2.2 with MTRR support configured out,
so verbosity should be chosen appropriately. */
static Bool
mtrr_open(int verbosity)
{
/* Only report absence of /proc/mtrr once. */
static Bool warned = FALSE;
if (mtrr_fd == MTRR_FD_UNOPENED) {
mtrr_fd = open("/proc/mtrr", O_WRONLY);
if (mtrr_fd < 0)
mtrr_fd = MTRR_FD_PROBLEM;
}
if (mtrr_fd == MTRR_FD_PROBLEM) {
/* To make sure we only ever warn once, need to check
verbosity outside xf86MsgVerb */
if (!warned && verbosity <= xf86GetVerbosity()) {
xf86MsgVerb(X_WARNING, verbosity,
"System lacks support for changing MTRRs\n");
warned = TRUE;
}
return FALSE;
}
else
return TRUE;
}
/*
* We maintain a list of WC regions for each physical mapping so they can
* be undone when unmapping.
*/
struct mtrr_wc_region {
struct mtrr_sentry sentry;
Bool added; /* added WC or removed it */
struct mtrr_wc_region *next;
};
static struct mtrr_wc_region *
mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size,
MessageType from)
{
/* Some BIOS writers thought that setting wc over the mmio
region of a graphics devices was a good idea. Try to fix
it. */
struct mtrr_gentry gent;
struct mtrr_wc_region *wcreturn = NULL, *wcr;
int count, ret = 0;
/* Linux 2.0 users should not get a warning without -verbose */
if (!mtrr_open(2))
return NULL;
for (gent.regnum = 0;
ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++) {
if (gent.type != MTRR_TYPE_WRCOMB
|| gent.base + gent.size <= base || base + size <= gent.base)
continue;
/* Found an overlapping region. Delete it. */
wcr = malloc(sizeof(*wcr));
if (!wcr)
return NULL;
wcr->sentry.base = gent.base;
wcr->sentry.size = gent.size;
wcr->sentry.type = MTRR_TYPE_WRCOMB;
wcr->added = FALSE;
count = 3;
while (count-- &&
(ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0);
if (ret >= 0) {
xf86DrvMsg(screenNum, from,
"Removed MMIO write-combining range "
"(0x%lx,0x%lx)\n",
(unsigned long) gent.base, (unsigned long) gent.size);
wcr->next = wcreturn;
wcreturn = wcr;
gent.regnum--;
}
else {
free(wcr);
xf86DrvMsgVerb(screenNum, X_WARNING, 0,
"Failed to remove MMIO "
"write-combining range (0x%lx,0x%lx)\n",
gent.base, (unsigned long) gent.size);
}
}
return wcreturn;
}
static struct mtrr_wc_region *
mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size,
MessageType from)
{
struct mtrr_gentry gent;
struct mtrr_wc_region *wcreturn = NULL, **wcr;
if (!mtrr_open(2))
return NULL;
wcr = &wcreturn;
for (gent.regnum = 0;
ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++) {
if (gent.type == MTRR_TYPE_WRCOMB
&& ((gent.base >= base && gent.base + gent.size < base + size) ||
(gent.base > base && gent.base + gent.size <= base + size))) {
*wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from);
if (*wcr)
gent.regnum--;
while (*wcr) {
wcr = &((*wcr)->next);
}
}
}
return wcreturn;
}
static struct mtrr_wc_region *
mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size,
MessageType from)
{
struct mtrr_wc_region **wcr, *wcreturn, *curwcr;
/*
* There can be only one....
*/
wcreturn = mtrr_remove_offending(screenNum, base, size, from);
wcr = &wcreturn;
while (*wcr) {
wcr = &((*wcr)->next);
}
/* Linux 2.0 should not warn, unless the user explicitly asks for
WC. */
if (!mtrr_open(from == X_CONFIG ? 0 : 2))
return wcreturn;
*wcr = curwcr = malloc(sizeof(**wcr));
if (!curwcr)
return wcreturn;
curwcr->sentry.base = base;
curwcr->sentry.size = size;
curwcr->sentry.type = MTRR_TYPE_WRCOMB;
curwcr->added = TRUE;
curwcr->next = NULL;
#if SPLIT_WC_REGIONS
/*
* Splits up the write-combining region if it is not aligned on a
* size boundary.
*/
{
unsigned long lbase, d_size = 1;
unsigned long n_size = size;
unsigned long n_base = base;
for (lbase = n_base, d_size = 1; !(lbase & 1);
lbase = lbase >> 1, d_size <<= 1);
while (d_size > n_size)
d_size = d_size >> 1;
DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n", base, base + d_size - 1);
n_base += d_size;
n_size -= d_size;
if (n_size) {
xf86DrvMsgVerb(screenNum, X_INFO, 3, "Splitting WC range: "
"base: 0x%lx, size: 0x%lx\n", base, size);
curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size, from);
}
curwcr->sentry.size = d_size;
}
/*****************************************************************/
#endif /* SPLIT_WC_REGIONS */
if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) {
/* Avoid printing on every VT switch */
if (xf86ServerIsInitialising()) {
xf86DrvMsg(screenNum, from,
"Write-combining range (0x%lx,0x%lx)\n", base, size);
}
return wcreturn;
}
else {
*wcr = curwcr->next;
free(curwcr);
/* Don't complain about the VGA region: MTRR fixed
regions aren't currently supported, but might be in
the future. */
if ((unsigned long) base >= 0x100000) {
xf86DrvMsgVerb(screenNum, X_WARNING, 0,
"Failed to set up write-combining range "
"(0x%lx,0x%lx)\n", base, size);
}
return wcreturn;
}
}
static void
mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr)
{
struct mtrr_wc_region *p, *prev;
if (mtrr_fd >= 0) {
p = wcr;
while (p) {
if (p->added)
ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry);
prev = p;
p = p->next;
free(prev);
}
}
}
static pointer
setWC(int screenNum, unsigned long base, unsigned long size, Bool enable,
MessageType from)
{
if (enable)
return mtrr_add_wc_region(screenNum, base, size, from);
else
return mtrr_cull_wc_region(screenNum, base, size, from);
}
static void
undoWC(int screenNum, pointer regioninfo)
{
mtrr_undo_wc_region(screenNum, regioninfo);
}
#endif /* HAS_MTRR_SUPPORT */
void
xf86OSInitVidMem(VidMemInfoPtr pVidMem)
{
pVidMem->linearSupported = TRUE;
#ifdef __alpha__
if (axpSystem == -1) {
axpSystem = lnxGetAXP();
if ((needSparse = (_bus_base_sparse() > 0))) {
hae_thresh = xf86AXPParams[axpSystem].hae_thresh;
hae_mask = xf86AXPParams[axpSystem].hae_mask;
}
bus_base = _bus_base();
}
if (needSparse) {
xf86Msg(X_INFO, "Machine needs sparse mapping\n");
pVidMem->mapMem = mapVidMemSparse;
pVidMem->unmapMem = unmapVidMemSparse;
}
else {
xf86Msg(X_INFO, "Machine type has 8/16 bit access\n");
pVidMem->mapMem = mapVidMem;
pVidMem->unmapMem = unmapVidMem;
}
#else
pVidMem->mapMem = mapVidMem;
pVidMem->unmapMem = unmapVidMem;
#endif /* __alpha__ */
#ifdef HAS_MTRR_SUPPORT
pVidMem->setWC = setWC;
pVidMem->undoWC = undoWC;
#endif
pVidMem->initialised = TRUE;
}
#ifdef __sparc__
/* Basically, you simply cannot do this on Sparc. You have to do something portable
* like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM
*/
static pointer
mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
{
return NULL;
}
#else
static pointer
mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
{
pointer base;
int fd;
int mapflags = MAP_SHARED;
int prot;
memType realBase, alignOff;
realBase = Base & ~(getpagesize() - 1);
alignOff = Base - realBase;
DebugF("base: %lx, realBase: %lx, alignOff: %lx \n",
Base, realBase, alignOff);
#if defined(__ia64__) || defined(__arm__) || defined(__s390__)
#ifndef MAP_WRITECOMBINED
#define MAP_WRITECOMBINED 0x00010000
#endif
#ifndef MAP_NONCACHED
#define MAP_NONCACHED 0x00020000
#endif
if (flags & VIDMEM_FRAMEBUFFER)
mapflags |= MAP_WRITECOMBINED;
else
mapflags |= MAP_NONCACHED;
#endif
#if 0
/* this will disappear when people upgrade their kernels */
fd = open(DEV_MEM,
((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC);
#else
fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
#endif
if (fd < 0) {
FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n",
strerror(errno));
}
if (flags & VIDMEM_READONLY)
prot = PROT_READ;
else
prot = PROT_READ | PROT_WRITE;
/* This requires linux-0.99.pl10 or above */
base = mmap((caddr_t) 0, Size + alignOff, prot, mapflags, fd,
(off_t) realBase + BUS_BASE);
close(fd);
if (base == MAP_FAILED) {
FatalError("xf86MapVidMem: Could not mmap framebuffer"
" (0x%08lx,0x%lx) (%s)\n", Base, Size, strerror(errno));
}
DebugF("base: %lx aligned base: %lx\n", base, (char *) base + alignOff);
return (char *) base + alignOff;
}
#endif /* !(__sparc__) */
static void
unmapVidMem(int ScreenNum, pointer Base, unsigned long Size)
{
uintptr_t alignOff = (uintptr_t) Base
- ((uintptr_t) Base & ~(getpagesize() - 1));
DebugF("alignment offset: %lx\n", (unsigned long) alignOff);
munmap((void *) ((uintptr_t) Base - alignOff), (Size + alignOff));
}
/***************************************************************************/
/* I/O Permissions section */
/***************************************************************************/
#if defined(__powerpc__)
volatile unsigned char *ioBase = NULL;
#ifndef __NR_pciconfig_iobase
#define __NR_pciconfig_iobase 200
#endif
#endif
Bool
xf86EnableIO(void)
{
#if defined(__powerpc__)
int fd;
unsigned int ioBase_phys;
#endif
if (ExtendedEnabled)
return TRUE;
#if defined(__powerpc__)
ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0);
fd = open("/dev/mem", O_RDWR);
if (ioBase == NULL) {
ioBase = (volatile unsigned char *) mmap(0, 0x20000,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, ioBase_phys);
/* Should this be fatal or just a warning? */
#if 0
if (ioBase == MAP_FAILED) {
xf86Msg(X_WARNING,
"xf86EnableIOPorts: Failed to map iobase (%s)\n",
strerror(errno));
return FALSE;
}
#endif
}
close(fd);
#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) && !defined(__nds32__)
if (ioperm(0, 1024, 1) || iopl(3)) {
if (errno == ENODEV)
ErrorF("xf86EnableIOPorts: no I/O ports found\n");
else
FatalError("xf86EnableIOPorts: failed to set IOPL"
" for I/O (%s)\n", strerror(errno));
return FALSE;
}
#if !defined(__alpha__)
/* XXX: this is actually not trapping anything because of iopl(3)
* above */
ioperm(0x40, 4, 0); /* trap access to the timer chip */
ioperm(0x60, 4, 0); /* trap access to the keyboard controller */
#endif
#endif
ExtendedEnabled = TRUE;
return TRUE;
}
void
xf86DisableIO(void)
{
if (!ExtendedEnabled)
return;
#if defined(__powerpc__)
munmap(ioBase, 0x20000);
ioBase = NULL;
#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) && !defined(__nds32__)
iopl(0);
ioperm(0, 1024, 0);
#endif
ExtendedEnabled = FALSE;
return;
}
#if defined (__alpha__)
#define vuip volatile unsigned int *
extern int readDense8(pointer Base, register unsigned long Offset);
extern int readDense16(pointer Base, register unsigned long Offset);
extern int readDense32(pointer Base, register unsigned long Offset);
extern void
writeDenseNB8(int Value, pointer Base, register unsigned long Offset);
extern void
writeDenseNB16(int Value, pointer Base, register unsigned long Offset);
extern void
writeDenseNB32(int Value, pointer Base, register unsigned long Offset);
extern void
writeDense8(int Value, pointer Base, register unsigned long Offset);
extern void
writeDense16(int Value, pointer Base, register unsigned long Offset);
extern void
writeDense32(int Value, pointer Base, register unsigned long Offset);
static int readSparse8(pointer Base, register unsigned long Offset);
static int readSparse16(pointer Base, register unsigned long Offset);
static int readSparse32(pointer Base, register unsigned long Offset);
static void
writeSparseNB8(int Value, pointer Base, register unsigned long Offset);
static void
writeSparseNB16(int Value, pointer Base, register unsigned long Offset);
static void
writeSparseNB32(int Value, pointer Base, register unsigned long Offset);
static void
writeSparse8(int Value, pointer Base, register unsigned long Offset);
static void
writeSparse16(int Value, pointer Base, register unsigned long Offset);
static void
writeSparse32(int Value, pointer Base, register unsigned long Offset);
#define DENSE_BASE 0x2ff00000000UL
#define SPARSE_BASE 0x30000000000UL
static unsigned long msb_set = 0;
static pointer
mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size,
int flags)
{
int fd, prot;
unsigned long ret, rets = 0;
static Bool was_here = FALSE;
if (!was_here) {
was_here = TRUE;
xf86WriteMmio8 = writeSparse8;
xf86WriteMmio16 = writeSparse16;
xf86WriteMmio32 = writeSparse32;
xf86WriteMmioNB8 = writeSparseNB8;
xf86WriteMmioNB16 = writeSparseNB16;
xf86WriteMmioNB32 = writeSparseNB32;
xf86ReadMmio8 = readSparse8;
xf86ReadMmio16 = readSparse16;
xf86ReadMmio32 = readSparse32;
}
fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR);
if (fd < 0) {
FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n",
strerror(errno));
}
#if 0
xf86Msg(X_INFO, "mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n",
Base, Size, flags);
#endif
if (flags & VIDMEM_READONLY)
prot = PROT_READ;
else
prot = PROT_READ | PROT_WRITE;
/* This requirers linux-0.99.pl10 or above */
/*
* Always do DENSE mmap, since read32/write32 currently require it.
*/
ret = (unsigned long) mmap((caddr_t) (DENSE_BASE + Base), Size,
prot, MAP_SHARED, fd, (off_t) (bus_base + Base));
/*
* Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER
* and SPARSE (which should require the use of read/write macros).
*
* By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K
* bytes worth of pagetable (32 pages).
*/
if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) ||
((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) {
rets = (unsigned long) mmap((caddr_t) (SPARSE_BASE + (Base << 5)),
Size << 5, prot, MAP_SHARED, fd,
(off_t) _bus_base_sparse() + (Base << 5));
}
close(fd);
if (ret == (unsigned long) MAP_FAILED) {
FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n",
strerror(errno));
}
if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) ||
((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) {
if (rets == (unsigned long) MAP_FAILED ||
rets != (SPARSE_BASE + (Base << 5))) {
FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n",
strerror(errno));
}
}
#if 1
if (rets)
xf86Msg(X_INFO, "mapVidMemSparse: mapped Base 0x%lx size 0x%lx"
" to DENSE at 0x%lx and SPARSE at 0x%lx\n",
Base, Size, ret, rets);
else
xf86Msg(X_INFO, "mapVidMemSparse: mapped Base 0x%lx size 0x%lx"
" to DENSE only at 0x%lx\n", Base, Size, ret);
#endif
return (pointer) ret;
}
static void
unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size)
{
unsigned long Offset = (unsigned long) Base - DENSE_BASE;
#if 1
xf86Msg(X_INFO, "unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n",
Base, Size);
#endif
/* Unmap DENSE always. */
munmap((caddr_t) Base, Size);
/* Unmap SPARSE always, and ignore error in case we did not map it. */
munmap((caddr_t) (SPARSE_BASE + (Offset << 5)), Size << 5);
}
static int
readSparse8(pointer Base, register unsigned long Offset)
{
register unsigned long result, shift;
register unsigned long msb;
mem_barrier();
Offset += (unsigned long) Base - DENSE_BASE;
shift = (Offset & 0x3) << 3;
if (Offset >= (hae_thresh)) {
msb = Offset & hae_mask;
Offset -= msb;
if (msb_set != msb) {
sethae(msb);
msb_set = msb;
}
}
mem_barrier();
result = *(vuip) (SPARSE_BASE + (Offset << 5));
result >>= shift;
return 0xffUL & result;
}
static int
readSparse16(pointer Base, register unsigned long Offset)
{
register unsigned long result, shift;
register unsigned long msb;
mem_barrier();
Offset += (unsigned long) Base - DENSE_BASE;
shift = (Offset & 0x2) << 3;
if (Offset >= hae_thresh) {
msb = Offset & hae_mask;
Offset -= msb;
if (msb_set != msb) {
sethae(msb);
msb_set = msb;
}
}
mem_barrier();
result = *(vuip) (SPARSE_BASE + (Offset << 5) + (1 << (5 - 2)));
result >>= shift;
return 0xffffUL & result;
}
static int
readSparse32(pointer Base, register unsigned long Offset)
{
/* NOTE: this is really using DENSE. */
mem_barrier();
return *(vuip) ((unsigned long) Base + (Offset));
}
static void
writeSparse8(int Value, pointer Base, register unsigned long Offset)
{
register unsigned long msb;
register unsigned int b = Value & 0xffU;
write_mem_barrier();
Offset += (unsigned long) Base - DENSE_BASE;
if (Offset >= hae_thresh) {
msb = Offset & hae_mask;
Offset -= msb;
if (msb_set != msb) {
sethae(msb);
msb_set = msb;
}
}
write_mem_barrier();
*(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101;
}
static void
writeSparse16(int Value, pointer Base, register unsigned long Offset)
{
register unsigned long msb;
register unsigned int w = Value & 0xffffU;
write_mem_barrier();
Offset += (unsigned long) Base - DENSE_BASE;
if (Offset >= hae_thresh) {
msb = Offset & hae_mask;
Offset -= msb;
if (msb_set != msb) {
sethae(msb);
msb_set = msb;
}
}
write_mem_barrier();
*(vuip) (SPARSE_BASE + (Offset << 5) + (1 << (5 - 2))) = w * 0x00010001;
}
static void
writeSparse32(int Value, pointer Base, register unsigned long Offset)
{
/* NOTE: this is really using DENSE. */
write_mem_barrier();
*(vuip) ((unsigned long) Base + (Offset)) = Value;
return;
}
static void
writeSparseNB8(int Value, pointer Base, register unsigned long Offset)
{
register unsigned long msb;
register unsigned int b = Value & 0xffU;
Offset += (unsigned long) Base - DENSE_BASE;
if (Offset >= hae_thresh) {
msb = Offset & hae_mask;
Offset -= msb;
if (msb_set != msb) {
sethae(msb);
msb_set = msb;
}
}
*(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101;
}
static void
writeSparseNB16(int Value, pointer Base, register unsigned long Offset)
{
register unsigned long msb;
register unsigned int w = Value & 0xffffU;
Offset += (unsigned long) Base - DENSE_BASE;
if (Offset >= hae_thresh) {
msb = Offset & hae_mask;
Offset -= msb;
if (msb_set != msb) {
sethae(msb);
msb_set = msb;
}
}
*(vuip) (SPARSE_BASE + (Offset << 5) + (1 << (5 - 2))) = w * 0x00010001;
}
static void
writeSparseNB32(int Value, pointer Base, register unsigned long Offset)
{
/* NOTE: this is really using DENSE. */
*(vuip) ((unsigned long) Base + (Offset)) = Value;
return;
}
void (*xf86WriteMmio8) (int Value, pointer Base, unsigned long Offset)
= writeDense8;
void (*xf86WriteMmio16) (int Value, pointer Base, unsigned long Offset)
= writeDense16;
void (*xf86WriteMmio32) (int Value, pointer Base, unsigned long Offset)
= writeDense32;
void (*xf86WriteMmioNB8) (int Value, pointer Base, unsigned long Offset)
= writeDenseNB8;
void (*xf86WriteMmioNB16) (int Value, pointer Base, unsigned long Offset)
= writeDenseNB16;
void (*xf86WriteMmioNB32) (int Value, pointer Base, unsigned long Offset)
= writeDenseNB32;
int (*xf86ReadMmio8) (pointer Base, unsigned long Offset)
= readDense8;
int (*xf86ReadMmio16) (pointer Base, unsigned long Offset)
= readDense16;
int (*xf86ReadMmio32) (pointer Base, unsigned long Offset)
= readDense32;
#endif /* __alpha__ */