Add MTRR support.
PR: 21901 Submitted by: Alexander N. Kabaev <ak03@gte.com>
This commit is contained in:
parent
da6242698d
commit
1c63df741c
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=34912
4 changed files with 412 additions and 2 deletions
|
@ -7,6 +7,7 @@
|
|||
|
||||
PORTNAME= utah-glx
|
||||
PORTVERSION= 0.9.20000824
|
||||
PORTREVISION= 1
|
||||
CATEGORIES= graphics
|
||||
MASTER_SITES= ${MASTER_SITE_LOCAL}
|
||||
MASTER_SITE_SUBDIR= sobomax
|
||||
|
|
|
@ -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 @@
|
||||
])
|
||||
|
||||
|
|
364
graphics/utah-glx/files/patch-ag
Normal file
364
graphics/utah-glx/files/patch-ag
Normal file
|
@ -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
|
20
graphics/utah-glx/files/patch-ah
Normal file
20
graphics/utah-glx/files/patch-ah
Normal file
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in a new issue