Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Oct 2014 11:27:03 +0000 (UTC)
From:      Tijl Coosemans <tijl@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r273856 - head/sys/dev/agp
Message-ID:  <201410301127.s9UBR3Rn069564@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tijl
Date: Thu Oct 30 11:27:03 2014
New Revision: 273856
URL: https://svnweb.freebsd.org/changeset/base/273856

Log:
  Add two new functions to the AGP driver KPI to bind/unbind arbitrary sets
  of pages into the GTT.
  
  Reviewed by:	kib
  MFC after:	1 month

Modified:
  head/sys/dev/agp/agp.c
  head/sys/dev/agp/agpvar.h

Modified: head/sys/dev/agp/agp.c
==============================================================================
--- head/sys/dev/agp/agp.c	Thu Oct 30 10:59:57 2014	(r273855)
+++ head/sys/dev/agp/agp.c	Thu Oct 30 11:27:03 2014	(r273856)
@@ -996,3 +996,76 @@ void agp_memory_info(device_t dev, void 
 	mi->ami_offset = mem->am_offset;
 	mi->ami_is_bound = mem->am_is_bound;
 }
+
+int
+agp_bind_pages(device_t dev, vm_page_t *pages, vm_size_t size,
+    vm_offset_t offset)
+{
+	struct agp_softc *sc;
+	vm_offset_t i, j, k, pa;
+	vm_page_t m;
+	int error;
+
+	if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
+	    (offset & (AGP_PAGE_SIZE - 1)) != 0)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->as_lock);
+	for (i = 0; i < size; i += PAGE_SIZE) {
+		m = pages[OFF_TO_IDX(i)];
+
+		/*
+		 * Install entries in the GATT, making sure that if
+		 * AGP_PAGE_SIZE < PAGE_SIZE and size is not
+		 * aligned to PAGE_SIZE, we don't modify too many GATT 
+		 * entries.
+		 */
+		for (j = 0; j < PAGE_SIZE && i + j < size; j += AGP_PAGE_SIZE) {
+			pa = VM_PAGE_TO_PHYS(m) + j;
+			AGP_DPF("binding offset %#jx to pa %#jx\n",
+				(uintmax_t)offset + i + j, (uintmax_t)pa);
+			error = AGP_BIND_PAGE(dev, offset + i + j, pa);
+			if (error) {
+				/*
+				 * Bail out. Reverse all the mappings.
+				 */
+				for (k = 0; k < i + j; k += AGP_PAGE_SIZE)
+					AGP_UNBIND_PAGE(dev, offset + k);
+
+				mtx_unlock(&sc->as_lock);
+				return (error);
+			}
+		}
+	}
+
+	agp_flush_cache();
+	AGP_FLUSH_TLB(dev);
+
+	mtx_unlock(&sc->as_lock);
+	return (0);
+}
+
+int
+agp_unbind_pages(device_t dev, vm_size_t size, vm_offset_t offset)
+{
+	struct agp_softc *sc;
+	vm_offset_t i;
+
+	if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
+	    (offset & (AGP_PAGE_SIZE - 1)) != 0)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->as_lock);
+	for (i = 0; i < size; i += AGP_PAGE_SIZE)
+		AGP_UNBIND_PAGE(dev, offset + i);
+
+	agp_flush_cache();
+	AGP_FLUSH_TLB(dev);
+
+	mtx_unlock(&sc->as_lock);
+	return (0);
+}

Modified: head/sys/dev/agp/agpvar.h
==============================================================================
--- head/sys/dev/agp/agpvar.h	Thu Oct 30 10:59:57 2014	(r273855)
+++ head/sys/dev/agp/agpvar.h	Thu Oct 30 11:27:03 2014	(r273856)
@@ -122,6 +122,19 @@ int agp_unbind_memory(device_t dev, void
  */
 void agp_memory_info(device_t dev, void *handle, struct agp_memory_info *mi);
 
+/*
+ * Bind a set of pages at a given offset within the AGP aperture.
+ * Returns EINVAL if the given size or offset is not at an AGP page boundary.
+ */
+int agp_bind_pages(device_t dev, vm_page_t *pages, vm_size_t size,
+		   vm_offset_t offset);
+
+/*
+ * Unbind a set of pages from the AGP aperture.
+ * Returns EINVAL if the given size or offset is not at an AGP page boundary.
+ */
+int agp_unbind_pages(device_t dev, vm_size_t size, vm_offset_t offset);
+
 #define AGP_NORMAL_MEMORY 0
 
 #define AGP_USER_TYPES (1 << 16)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410301127.s9UBR3Rn069564>