From 1c63df741c56103647fd318578117b7ccbd73818 Mon Sep 17 00:00:00 2001 From: Maxim Sobolev Date: Wed, 8 Nov 2000 11:19:39 +0000 Subject: [PATCH] Add MTRR support. PR: 21901 Submitted by: Alexander N. Kabaev --- graphics/utah-glx/Makefile | 1 + graphics/utah-glx/files/patch-af | 29 ++- graphics/utah-glx/files/patch-ag | 364 +++++++++++++++++++++++++++++++ graphics/utah-glx/files/patch-ah | 20 ++ 4 files changed, 412 insertions(+), 2 deletions(-) create mode 100644 graphics/utah-glx/files/patch-ag create mode 100644 graphics/utah-glx/files/patch-ah diff --git a/graphics/utah-glx/Makefile b/graphics/utah-glx/Makefile index 3c6b0bcf211f..af82b044de02 100644 --- a/graphics/utah-glx/Makefile +++ b/graphics/utah-glx/Makefile @@ -7,6 +7,7 @@ PORTNAME= utah-glx PORTVERSION= 0.9.20000824 +PORTREVISION= 1 CATEGORIES= graphics MASTER_SITES= ${MASTER_SITE_LOCAL} MASTER_SITE_SUBDIR= sobomax diff --git a/graphics/utah-glx/files/patch-af b/graphics/utah-glx/files/patch-af index 39dde9437d15..05954672444e 100644 --- a/graphics/utah-glx/files/patch-af +++ b/graphics/utah-glx/files/patch-af @@ -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 files are incomplete ++ dnl For some reason, some 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 +-#ifdef MTRRIOC_ADD_ENTRY ++#include ++#ifdef MDF_WRITECOMBINE + GLX_maGiC_VALID + #endif + ], @@ -879,7 +879,7 @@ ]) diff --git a/graphics/utah-glx/files/patch-ag b/graphics/utah-glx/files/patch-ag new file mode 100644 index 000000000000..f73242728f07 --- /dev/null +++ b/graphics/utah-glx/files/patch-ag @@ -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 + #include + #include +@@ -7,13 +6,15 @@ + #include + #include + #include ++#include + + #include "glx_symbols.h" + #include "hwlog.h" + +- + #ifndef NO_MTRR + ++#ifdef linux ++ + #define MTRR_NEED_STRINGS + #include + #include +@@ -237,6 +238,339 @@ + sentry.base, sentry.size ); + } + } ++ ++#endif ++ ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++ ++#ifndef __NetBSD__ ++#include ++#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 diff --git a/graphics/utah-glx/files/patch-ah b/graphics/utah-glx/files/patch-ah new file mode 100644 index 000000000000..fff204b6df5b --- /dev/null +++ b/graphics/utah-glx/files/patch-ah @@ -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 +-#include +-#include +-#include +-#include +-int mtrr; +-void mgaCloseMTRR(); +-#endif +- + #include "xf86_OSproc.h" + +