svn commit: r273856 - head/sys/dev/agp
Tijl Coosemans
tijl at FreeBSD.org
Thu Oct 30 11:27:04 UTC 2014
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)
More information about the svn-src-all
mailing list