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)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to