Skip site navigation (1)Skip section navigation (2)
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>