diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:22 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:22 +0000 |
commit | d568221710959cf7d783e6ff0fb80fb43a231124 (patch) | |
tree | 8d6f039393294c6ffac8533639afdebe5d68bfc1 /hw/xfree86/os-support/lynxos | |
parent | 9508a382f8a9f241dab097d921b6d290c1c3a776 (diff) |
XFree86 4.3.0.1xf86-4_3_0_1PRE_xf86-4_3_0_1
Diffstat (limited to 'hw/xfree86/os-support/lynxos')
-rw-r--r-- | hw/xfree86/os-support/lynxos/lynx_init.c | 45 | ||||
-rw-r--r-- | hw/xfree86/os-support/lynxos/lynx_io.c | 78 | ||||
-rw-r--r-- | hw/xfree86/os-support/lynxos/lynx_mmap.c | 25 | ||||
-rw-r--r-- | hw/xfree86/os-support/lynxos/lynx_video.c | 597 |
4 files changed, 634 insertions, 111 deletions
diff --git a/hw/xfree86/os-support/lynxos/lynx_init.c b/hw/xfree86/os-support/lynxos/lynx_init.c index 6c0e00aa3..8565dcc5c 100644 --- a/hw/xfree86/os-support/lynxos/lynx_init.c +++ b/hw/xfree86/os-support/lynxos/lynx_init.c @@ -22,36 +22,33 @@ */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_init.c,v 3.1.6.1 1998/02/06 22:36:51 hohndel Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_init.c,v 3.3 1998/08/29 05:43:58 dawes Exp $ */ #include "X.h" #include "Xmd.h" -#include "input.h" -#include "scrnintstr.h" #include "compiler.h" #include "xf86.h" -#include "xf86Procs.h" +#include "xf86Priv.h" #include "xf86_OSlib.h" static int VTnum = -1; -void xf86OpenConsole() +void +xf86OpenConsole() { struct vt_mode VT; char vtname1[11]; - int i, fd, pgrp; + int fd, pgrp; + MessageType from = X_PROBED; if (serverGeneration == 1) { /* check if we're run with euid==0 */ if (geteuid() != 0) { - FatalError("xf86OpenConsole: Server must be running with root " - "permissions\n" - "You should be using Xwrapper to start the server or xdm.\n" - "We strongly advise against making the server SUID root!\n"); + FatalError("xf86OpenConsole: Server must be suid root\n"); } /* @@ -67,6 +64,7 @@ void xf86OpenConsole() if (VTnum != -1) { xf86Info.vtno = VTnum; + from = X_CMDLINE; } else { @@ -88,7 +86,7 @@ void xf86OpenConsole() } close(fd); } - ErrorF("(using VT number %d)\n\n", xf86Info.vtno); + xf86Msg(from, "using VT number %d\n", xf86Info.vtno); sprintf(vtname1,"/dev/atc%d",xf86Info.vtno); @@ -104,19 +102,12 @@ void xf86OpenConsole() /* change ownership of the vt */ chown(vtname1, getuid(), getgid()); - /* Reading Config after opening the VT get's rid of */ - /* problems with LynxOS VT handling (i.e. VT_OPENQUERY */ - /* without open() leaves the vtxx busy until next */ - /* open/close) */ - - xf86Config(FALSE); /* Read XF86Config */ - /* * now get the VT */ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) { - ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); } if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) { @@ -142,20 +133,21 @@ void xf86OpenConsole() */ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) { - ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); + xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); } /* * If the server doesn't have the VT when the reset occurs, * this is to make sure we don't continue until the activate * signal is received. */ - if (!xf86VTSema) + if (!xf86Screens[0]->vtSema) sleep(5); } return; } -void xf86CloseConsole() +void +xf86CloseConsole() { struct vt_mode VT; @@ -172,10 +164,8 @@ void xf86CloseConsole() return; } -int xf86ProcessArgument (argc, argv, i) -int argc; -char *argv[]; -int i; +int +xf86ProcessArgument(int argc, char *argv[], int i) { if ((argv[i][0] == 'v') && (argv[i][1] == 't')) { @@ -190,7 +180,8 @@ int i; return(0); } -void xf86UseMsg() +void +xf86UseMsg() { ErrorF("vtXX use the specified VT number\n"); return; diff --git a/hw/xfree86/os-support/lynxos/lynx_io.c b/hw/xfree86/os-support/lynxos/lynx_io.c index e0134609e..e61ce76b7 100644 --- a/hw/xfree86/os-support/lynxos/lynx_io.c +++ b/hw/xfree86/os-support/lynxos/lynx_io.c @@ -21,25 +21,20 @@ * */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_io.c,v 3.3 1996/08/10 13:07:36 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_io.c,v 3.10 2003/02/17 15:11:57 dawes Exp $ */ -#define NEED_EVENTS #include "X.h" -#include "Xproto.h" -#include "inputstr.h" -#include "scrnintstr.h" #include "compiler.h" -#include "xf86Procs.h" +#include "xf86.h" +#include "xf86Priv.h" #include "xf86_OSlib.h" #if defined(KDMKTONE) || defined(KIOCSOUND) /* Lynx 2.2.1 has sophisticated atc stuff.... */ -void xf86SoundKbdBell(loudness, pitch, duration) -int loudness; -int pitch; -int duration; +void +xf86SoundKbdBell(int loudness, int pitch, int duration) { if (loudness && pitch) { @@ -73,10 +68,8 @@ int duration; #define FREQ_LO(f) ((TIMER_CONSTANT / (f)) % 256) #define FREQ_HI(f) ((TIMER_CONSTANT / (f)) / 256) -void xf86SoundKbdBell(loudness, pitch, duration) -int loudness; -int pitch; -int duration; +void +xf86SoundKbdBell(int loudness, int pitch, int duration) { int flo = FREQ_LO(pitch); int fhi = FREQ_HI(pitch); @@ -93,28 +86,43 @@ int duration; } #endif -void xf86SetKbdLeds(leds) -int leds; +void +xf86SetKbdLeds(int leds) { +#ifdef KBD_SET_LEDS + ioctl(xf86Info.consoleFd, KBD_SET_LEDS, &leds); +#endif } -int xf86GetKbdLeds() +int +xf86GetKbdLeds() { +#ifdef KBD_SET_LEDS + int leds; + + if (ioctl(xf86Info.consoleFd, KBD_SET_LEDS, &leds) < 0) + return 0; + + return leds; +#endif return 0; } -void xf86SetKbdRepeat(char rad) +void +xf86SetKbdRepeat(char rad) { } static struct termio kbdtty; -void xf86KbdInit() +void +xf86KbdInit() { ioctl(xf86Info.consoleFd, TCGETA, &kbdtty); } -int xf86KbdOn() +int +xf86KbdOn() { struct termio nTty; @@ -136,7 +144,8 @@ int xf86KbdOn() return(xf86Info.consoleFd); } -int xf86KbdOff() +int +xf86KbdOff() { /* disable scan mode */ ioctl(xf86Info.consoleFd, TIO_DISSCANMODE, NULL); @@ -144,29 +153,10 @@ int xf86KbdOff() return(xf86Info.consoleFd); } -void xf86MouseInit(mouse) -MouseDevPtr mouse; -{ - return; -} +#include "xf86OSKbd.h" -int xf86MouseOn(mouse) -MouseDevPtr mouse; +Bool +xf86OSKbdPreInit(InputInfoPtr pInfo) { - if ((mouse->mseFd = open(mouse->mseDevice, O_RDWR | O_NDELAY)) < 0) - { - if (xf86AllowMouseOpenFail) { - ErrorF("Cannot open mouse (%s) - Continuing...\n", - strerror(errno)); - return(-2); - } - FatalError("Cannot open mouse (%s)\n", strerror(errno)); - } - - /* assert DTR */ - ioctl(mouse->mseFd, TIOCSDTR, NULL); - - xf86SetupMouse(mouse); - - return(mouse->mseFd); + return FALSE; } diff --git a/hw/xfree86/os-support/lynxos/lynx_mmap.c b/hw/xfree86/os-support/lynxos/lynx_mmap.c index 621f42c5d..dcf734965 100644 --- a/hw/xfree86/os-support/lynxos/lynx_mmap.c +++ b/hw/xfree86/os-support/lynxos/lynx_mmap.c @@ -21,11 +21,9 @@ * */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_mmap.c,v 3.2 1996/09/29 13:38:29 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_mmap.c,v 3.6 2000/02/11 22:36:02 dawes Exp $ */ #include "X.h" -#include "input.h" -#include "scrnintstr.h" #include "xf86.h" #include "xf86Priv.h" @@ -35,26 +33,30 @@ * Read BIOS using smem_create facility */ -int xf86ReadBIOS(Base, Offset, Buf, Len) -unsigned long Base; -unsigned long Offset; -unsigned char *Buf; -int Len; +int +xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf, + int Len) { +#if defined(__powerpc__) + xf86Msg(X_WARNING, "xf86ReadBios: no BIOS-probe on PowerPC\n"); + return(-1); +#else char *p; int mlen; - mlen = (Offset + Len + 4095) & ~4096; + mlen = (Offset + Len + 4095) & ~4095; p = smem_create("BIOS-probe", (char *)Base, mlen, SM_READ); if (p == NULL) { /* check if there is a stale segment around */ if (smem_remove("BIOS-probe") == 0) { - ErrorF("xf86ReadBios: removed stale smem_ segment\n"); + xf86Msg(X_INFO, + "xf86ReadBios: removed stale smem_ segment\n"); p = smem_create("BIOS-probe", (char *)Base, mlen, SM_READ); } if (p == NULL) { - ErrorF("xf86ReadBios: Failed to smem_create Base %x len %x %s \n", + xf86Msg(X_WARNING, "xf86ReadBios: Failed to smem_create " + "Base %x len %x %s \n", Base, mlen, strerror(errno)); return(-1); } @@ -63,4 +65,5 @@ int Len; smem_create(NULL, p, 0, SM_DETACH); smem_remove("BIOS-probe"); return(Len); +#endif } diff --git a/hw/xfree86/os-support/lynxos/lynx_video.c b/hw/xfree86/os-support/lynxos/lynx_video.c index 94b2f0ecd..c667994b3 100644 --- a/hw/xfree86/os-support/lynxos/lynx_video.c +++ b/hw/xfree86/os-support/lynxos/lynx_video.c @@ -21,7 +21,7 @@ * */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_video.c,v 3.2.4.1 1997/05/09 07:15:24 hohndel Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_video.c,v 3.18 2002/12/14 04:41:14 dawes Exp $ */ #include "X.h" #include "input.h" @@ -30,6 +30,81 @@ #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" +#include "xf86OSpriv.h" + +#if defined(__powerpc__) + +# if defined(USE_MACHINE_ABSOLUTE) +# include <machine/absolute.h> +# else +# define __USER_SPACE_INCLUDE +# include <hw_absolute.h> +# endif + +void ppcPciIoMap(int bus); +#endif + +#if 0 +#define DEBUG +#endif + +#ifdef HAS_MTRR_SUPPORT +#include <sys/memrange.h> +#define X_MTRR_ID "XFree86" + +static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); +static void undoWC(int, pointer); +static Bool cleanMTRR(void); +static int devMemFd = -1; +#define MTRR_DEVICE "/dev/mtrr" +#endif + + +#if !defined(NO_MMAP) +#include <sys/mman.h> + +int smem_remove(char *name) +{ + return(0); +} + +char *smem_create(char *name, char *arg_addr, long size, int mode) +{ + int fd; + void *addr = 0; + char *retval; + size_t len = size; + int prot = PROT_READ|PROT_WRITE|PROT_UNCACHE; + int flags = MAP_SHARED; + off_t off = (off_t)arg_addr; + + if ((fd = open("/dev/mem" , O_RDWR)) < 0) + { + retval = (char *)-1; + } + else + { + if (mode == SM_DETACH) + { + munmap(arg_addr, len); + retval = 0; + } + else + { + if ((retval = mmap (addr, len, prot, flags, fd, off) ) == MAP_FAILED) + { + retval = (char *)-1; + } + } + + close(fd); + } + + return(retval); +} + +#endif + /***************************************************************************/ /* Video Memory Mapping section */ @@ -38,19 +113,24 @@ typedef struct { char name[16]; - pointer Base; - long Size; + unsigned long Base; + unsigned long Size; char *ptr; int RefCnt; } _SMEMS; -#define MAX_SMEMS 8 +#define MAX_SMEMS 16 static _SMEMS smems[MAX_SMEMS]; + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + static void -smemCleanup() +smemCleanup(void) { int i; @@ -60,18 +140,15 @@ smemCleanup() (void)smem_remove(smems[i].name); *smems[i].name = '\0'; smems[i].ptr = NULL; - smems[i].Base = NULL; + smems[i].Base = 0; smems[i].Size = 0; smems[i].RefCnt = 0; } } } -pointer xf86MapVidMem(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; +static pointer +MapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) { static int once; int free_slot = -1; @@ -86,14 +163,15 @@ unsigned long Size; { if (!*smems[i].name && free_slot == -1) free_slot = i; - if (smems[i].Base == Base && smems[i].Size == Size && *smems[i].name) { + if (smems[i].Base == Base && smems[i].Size == Size + && *smems[i].name) { smems[i].RefCnt++; return smems[i].ptr; } } if (i == MAX_SMEMS && free_slot == -1) { - FatalError("xf86MapVidMem: failed to smem_create Base %x Size %x (out of SMEMS entries)\n", + FatalError("MapVidMem: failed to smem_create Base %x Size %x (out of SMEMS entries)\n", Base, Size); } @@ -101,53 +179,85 @@ unsigned long Size; sprintf(smems[i].name, "Video-%d", i); smems[i].Base = Base; smems[i].Size = Size; - smems[i].ptr = smem_create(smems[i].name, Base, Size, SM_READ|SM_WRITE); + + xf86MsgVerb(X_INFO, 3, "MapVidMem: Base=0x%x Size=0x%x\n", + Base, Size); + +#if defined(__powerpc__) + if (((unsigned long)Base & PHYS_IO_MEM_START) != PHYS_IO_MEM_START) { + Base = Base | PHYS_IO_MEM_START; + } +#endif + + smems[i].ptr = smem_create(smems[i].name, (char *)Base, Size, SM_READ|SM_WRITE); smems[i].RefCnt = 1; if (smems[i].ptr == NULL) { /* check if there is a stale segment around */ if (smem_remove(smems[i].name) == 0) { - ErrorF("xf86MapVidMem: removed stale smem_ segment %s\n", - smems[i].name); + xf86Msg(X_INFO, + "MapVidMem: removed stale smem_ segment %s\n", + smems[i].name); smems[i].ptr = smem_create(smems[i].name, - Base, Size, SM_READ|SM_WRITE); + (char *)Base, Size, SM_READ|SM_WRITE); } if (smems[i].ptr == NULL) { *smems[i].name = '\0'; - FatalError("xf86MapVidMem: failed to smem_create Base %x Size %x (%s)\n", + FatalError("MapVidMem: failed to smem_create Base %x Size %x (%s)\n", Base, Size, strerror(errno)); } } + xf86MsgVerb(X_INFO, 3, "MapVidMem: Base=0x%x Size=0x%x Ptr=0x%x\n", + Base, Size, smems[i].ptr); return smems[i].ptr; } -void xf86UnMapVidMem(ScreenNum, Region, Base, Size) -int ScreenNum; -int Region; -pointer Base; -unsigned long Size; +static void +UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size) { int i; + xf86MsgVerb(X_INFO, 3, "UnMapVidMem: Base/Ptr=0x%x Size=0x%x\n", + Base, Size); for (i = 0; i < MAX_SMEMS; i++) { - if (*smems[i].name && smems[i].ptr == Base && smems[i].Size == Size) + if (*smems[i].name && smems[i].ptr == Base + && smems[i].Size == Size) { if (--smems[i].RefCnt > 0) return; + (void)smem_create(NULL, smems[i].ptr, 0, SM_DETACH); + xf86MsgVerb(X_INFO, 3, + "UnMapVidMem: smem_create(%s, 0x%08x, ... " + "SM_DETACH)\n", smems[i].name, smems[i].ptr); (void)smem_remove(smems[i].name); *smems[i].name = '\0'; smems[i].RefCnt = 0; return; } } - ErrorF("xf86UnMapVidMem: no SMEM found for Base = %lx Size = %lx\n", Base, Size); + xf86MsgVerb(X_WARNING, 2, + "UnMapVidMem: no SMEM found for Base = %lx Size = %lx\n", + Base, Size); } -Bool xf86LinearVidMem() + +void +xf86OSInitVidMem(VidMemInfoPtr pVidMem) { - return(TRUE); + pVidMem->linearSupported = TRUE; + pVidMem->mapMem = MapVidMem; + pVidMem->unmapMem = UnMapVidMem; + pVidMem->setWC = 0; + pVidMem->undoWC = 0; +#ifdef HAS_MTRR_SUPPORT + if (cleanMTRR()) { + pVidMem->setWC = setWC; + pVidMem->undoWC = undoWC; + } +#endif + pVidMem->initialised = TRUE; } @@ -155,13 +265,442 @@ Bool xf86LinearVidMem() /* Interrupt Handling section */ /***************************************************************************/ -Bool xf86DisableInterrupts() +Bool +xf86DisableInterrupts() { return(TRUE); } -void xf86EnableInterrupts() +void +xf86EnableInterrupts() +{ + return; +} + +/***************************************************************************/ +/* I/O Permissions section for PowerPC */ +/***************************************************************************/ + +#if defined(__powerpc__) + +volatile unsigned char *ioBase = MAP_FAILED; +volatile unsigned char *pciConfBase = MAP_FAILED; + +static int IOEnabled; + + +static void +removeIOSmem(void) +{ + smem_create(NULL, (char *) ioBase, 0, SM_DETACH); + smem_remove("IOBASE"); + ioBase = MAP_FAILED; +} + +void +xf86EnableIO() { + if (IOEnabled++ == 0) { + ioBase = (unsigned char *) smem_create("IOBASE", + (char *)PHYS_ISA_IO_SPACE, 64*1024, SM_READ|SM_WRITE); + if (ioBase == MAP_FAILED) { + --IOEnabled; + FatalError("xf86EnableIO: Failed to map I/O\n"); + } else { +#ifdef DEBUG + ErrorF("xf86EnableIO: mapped I/O at vaddr 0x%08x\n", + ioBase); +#endif + atexit(removeIOSmem); + } + } return; } +void +xf86DisableIO() +{ + if (!IOEnabled) + return; + + if (--IOEnabled == 0) + removeIOSmem(); + return; +} + +#if 0 +void +xf86DisableIOPrivs(void) +{ + return; +} +#endif +void +ppcPciIoMap(int bus) +{ + xf86EnableIO(); +} + +#endif + + +#ifdef HAS_MTRR_SUPPORT +/* memory range (MTRR) support for LynxOS (taken from BSD MTRR support) */ + +/* + * 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)) { + xfree(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) { + if ((devMemFd = open(MTRR_DEVICE, O_RDONLY)) < 0) { +perror("open MTRR"); + 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 + xfree(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; + xfree(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; + } + } + xfree(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 */ + |