Date: Tue, 10 Oct 2000 21:47:29 -0400 (EDT) From: kabaev@mail.ru To: FreeBSD-gnats-submit@freebsd.org Subject: ports/21901: Add support for MTRRs into utah-glx port Message-ID: <200010110147.e9B1lTS43280@kan.dnsalias.net>
next in thread | raw e-mail | index | archive | help
>Number: 21901 >Category: ports >Synopsis: Port MTRR support from XFree86-4 to utah-glx >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Oct 10 18:50:01 PDT 2000 >Closed-Date: >Last-Modified: >Originator: Alexander N. Kabaev >Release: FreeBSD 5.0-CURRENT i386 >Organization: Verizon Laboratories Inc. >Environment: 5.0-CURRENT, should not on 4.x-STABLE as well >Description: MTRR setting code has been lifted from XFree86-4 bsd_video.c and added to the utah-glx hw_mtrr.c file Changed configure.in slightly to allow detection of MTRR interface on FreeBSD >How-To-Repeat: N/A >Fix: Index: files/patch-af =================================================================== RCS file: /home/ncvs/ports/graphics/utah-glx/files/patch-af,v retrieving revision 1.1 diff -u -r1.1 patch-af --- files/patch-af 2000/06/26 13:45:28 1.1 +++ files/patch-af 2000/10/10 05:08:04 @@ -1,5 +1,30 @@ ---- configure.in.orig Fri Jun 23 12:23:13 2000 -+++ configure.in Fri Jun 23 12:30:06 2000 +--- configure.in.orig Thu Aug 24 09:53:45 2000 ++++ configure.in Mon Oct 9 21:39:56 2000 +@@ -846,19 +846,19 @@ + AC_HEADER_STDC + AC_CHECK_HEADERS(fcntl.h limits.h sys/ioctl.h unistd.h floatingpoint.h \ + sys/types.h sys/mman.h sys/perm.h asm/sigcontext.h) +-AC_CHECK_HEADER(asm/mtrr.h, ++AC_CHECK_HEADER(sys/memrange.h, + [ + if test "$enable_mtrr" = "no" + then + echo "disabling mtrr (manual override)" + cflags="$cflags -DNO_MTRR" + else +- dnl For some reason, some <asm/mtrr.h> files are incomplete ++ dnl For some reason, some <sys/memrange.h> files are incomplete + dnl Verify the validity of the file here +- AC_MSG_CHECKING(validity of asm/mtrr.h) ++ AC_MSG_CHECKING(validity of sys/memrange.h) + AC_EGREP_CPP([GLX_maGiC_VALID],[ +-#include <asm/mtrr.h> +-#ifdef MTRRIOC_ADD_ENTRY ++#include <sys/memrange.h> ++#ifdef MDF_WRITECOMBINE + GLX_maGiC_VALID + #endif + ], @@ -879,7 +879,7 @@ ]) Index: files/patch-ag =================================================================== RCS file: patch-ag diff -N patch-ag --- /dev/null Tue Oct 10 14:53:47 2000 +++ patch-ag Mon Oct 9 21:44:15 2000 @@ -0,0 +1,364 @@ +--- servGL/hwglx/common/hw_mtrr.c.orig Mon Oct 9 21:42:30 2000 ++++ servGL/hwglx/common/hw_mtrr.c Mon Oct 9 21:42:55 2000 +@@ -1,4 +1,3 @@ +- + #include <stdlib.h> + #include <errno.h> + #include <unistd.h> +@@ -7,13 +6,15 @@ + #include <sys/stat.h> + #include <fcntl.h> + #include <signal.h> ++#include <sys/ioctl.h> + + #include "glx_symbols.h" + #include "hwlog.h" + +- + #ifndef NO_MTRR + ++#ifdef linux ++ + #define MTRR_NEED_STRINGS + #include <errno.h> + #include <asm/mtrr.h> +@@ -237,6 +238,339 @@ + sentry.base, sentry.size ); + } + } ++ ++#endif ++ ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++ ++#ifndef __NetBSD__ ++#include <sys/memrange.h> ++#else ++#include "memrange.h" ++#endif ++#define X_MTRR_ID "XFree86" ++ ++typedef struct x_RangeRec { ++ struct mem_range_desc mrd; ++ int wasWC; ++ struct x_RangeRec * next; ++} RangeRec, *RangePtr; ++ ++static RangePtr savedRangeList = NULL; ++static int devMemFd = -1; ++ ++/* ++ * 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 = (struct mem_range_desc *)xalloc(*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; ++} ++ ++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 = (RangePtr)xalloc(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 = (RangePtr)xalloc(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 int ++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 1; ++ } ++ rp1 = rp1->next; ++ } ++ freeRangeList(sorted); ++ return 0; ++} ++ ++static RangePtr ++addWC(unsigned long base, unsigned long size) ++{ ++ 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)) { ++ hwMsg(1, "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)) { ++ hwError("Failed to set write-combining range " ++ "(0x%lx,0x%lx)\n", base, size); ++ return NULL; ++ } else { ++ hwMsg(1, "Write-combining range (0x%lx,0x%lx)\n", base, size); ++ retlist = (RangePtr)xalloc(sizeof(RangeRec)); ++ retlist->mrd = mrd; ++ retlist->wasWC = FALSE; ++ retlist->next = NULL; ++ return retlist; ++ } ++} ++ ++static void ++undoWC(RangePtr rp) ++{ ++ struct mem_range_op mro; ++ int failed; ++ ++ while (rp) { ++ hwMsg(1,"Undo for (0x%lx,0x%lx), %d\n", ++ (unsigned long)rp->mrd.mr_base, ++ (unsigned long)rp->mrd.mr_len, rp->wasWC); ++ 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) { ++ hwError("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; ++ } ++} ++ ++static int ++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)) { ++ hwMsg( 1,"Clean for (0x%lx,0x%lx)\n", ++ (unsigned long)mrd[i].mr_base, ++ (unsigned long)mrd[i].mr_len); ++ 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); ++ } ++ } ++ xfree(mrd); ++ return TRUE; ++} ++ ++static void CloseMTRR( void ) ++{ ++ undoWC(savedRangeList); ++ close(devMemFd); ++} ++ ++static void OpenMTRR( void ) ++{ ++ if ( ( devMemFd = open( "/dev/mem", O_RDWR, 0 ) ) == -1 ) ++ { ++ hwError( "Error opening /dev/mem: %s\n", strerror( errno ) ); ++ hwError( "MTRR not enabled\n" ); ++ return; ++ } ++ ++ if ( !cleanMTRR() ) { ++ close(devMemFd); ++ devMemFd = -1; ++ return; ++ } ++ ++ atexit( CloseMTRR ); ++} ++ ++void SetWriteCombining( long physical, int bytes ) ++{ ++ RangePtr rp; ++ ++ if ( devMemFd < 0 ) { ++ OpenMTRR(); ++ } ++ ++ if ( devMemFd < 0 ) { ++ return; ++ } ++ ++ rp = addWC(physical, bytes); ++ ++ if ( NULL != rp ) { ++ rp->next = savedRangeList; ++ savedRangeList = rp; ++ } ++} ++ ++ ++#endif /* end of BSD MTRR support */ + + /* + * FlushWriteCombining Index: files/patch-ah =================================================================== RCS file: patch-ah diff -N patch-ah --- /dev/null Tue Oct 10 14:53:47 2000 +++ patch-ah Mon Oct 9 21:49:06 2000 @@ -0,0 +1,20 @@ +--- servGL/hwglx/mga/mgadirect.c.orig Mon Oct 9 21:47:35 2000 ++++ servGL/hwglx/mga/mgadirect.c Mon Oct 9 21:48:18 2000 +@@ -62,17 +62,6 @@ + #include "glx_clients.h" + #include "glx_init.h" + +-#ifndef NO_MTRR +-#define MTRR_NEED_STRINGS +-#include <errno.h> +-#include <asm/mtrr.h> +-#include <fcntl.h> +-#include <sys/ioctl.h> +-#include <unistd.h> +-int mtrr; +-void mgaCloseMTRR(); +-#endif +- + #include "xf86_OSproc.h" + + >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010110147.e9B1lTS43280>