AGP backends for TTM.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Tue, 22 Aug 2006 08:09:57 +0000 (10:09 +0200)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Tue, 22 Aug 2006 08:09:57 +0000 (10:09 +0200)
linux-core/drmP.h
linux-core/drm_agpsupport.c

index 33d8ecc..8f8f324 100644 (file)
@@ -850,6 +850,16 @@ typedef struct drm_device {
 
 } drm_device_t;
 
+#if __OS_HAS_AGP
+typedef struct drm_agp_ttm_priv {
+       DRM_AGP_MEM *mem;
+       struct agp_bridge_data *bridge;
+       unsigned mem_type;
+       int populated;
+} drm_agp_ttm_priv;
+#endif
+
+
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
                                             int feature)
 {
@@ -1162,6 +1172,8 @@ extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size
 extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
 extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
 extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+extern drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev);
+extern drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev);
 
                                /* Stub support (drm_stub.h) */
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
index dce27cd..9286800 100644 (file)
@@ -552,4 +552,169 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
        return agp_unbind_memory(handle);
 }
 
+/*
+ * AGP ttm backend interface.
+ */
+
+static int drm_agp_needs_cache_adjust_true(drm_ttm_backend_t *backend) {
+       return TRUE;
+}
+
+static int drm_agp_needs_cache_adjust_false(drm_ttm_backend_t *backend) {
+       return FALSE;
+}
+
+#define AGP_MEM_USER (1 << 16)
+#define AGP_MEM_UCACHED (2 << 16)
+
+static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, 
+                           struct page **pages) {
+
+       drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+       struct page **cur_page, **last_page = pages + num_pages;
+       DRM_AGP_MEM *mem;
+
+       DRM_DEBUG("drm_agp_populate_ttm\n");
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)
+       mem = drm_agp_allocate_memory(num_pages, agp_priv->mem_type);
+#else
+       mem = drm_agp_allocate_memory(agp_priv->bridge, num_pages, agp_priv->mem_type);
+#endif
+       if (!mem) 
+               return -1;
+
+       DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count);
+       mem->page_count = 0;
+       for (cur_page = pages; cur_page < last_page; ++cur_page) {
+               mem->memory[mem->page_count++] = page_to_phys(*cur_page);
+       }
+       agp_priv->mem = mem;
+       return 0;
+}
+
+static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, unsigned long offset) {
+
+       drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+       DRM_AGP_MEM *mem = agp_priv->mem;
+       int ret;
+
+       DRM_DEBUG("drm_agp_bind_ttm\n");
+       mem->is_flushed = FALSE;
+       ret = drm_agp_bind_memory(mem, offset);
+       if (ret) {
+               DRM_ERROR("AGP Bind memory failed\n");
+       }
+       return ret;
+}
+
+static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) {
+
+       drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+
+       DRM_DEBUG("drm_agp_unbind_ttm\n");
+       if (agp_priv->mem->is_bound)
+               return drm_agp_unbind_memory(agp_priv->mem);
+       else
+               return 0;
+}
+
+static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) {
+
+       drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+       DRM_AGP_MEM *mem = agp_priv->mem;
+
+       DRM_DEBUG("drm_agp_clear_ttm\n");
+       if (mem) {
+               if (mem->is_bound) {
+                       drm_agp_unbind_memory(mem);
+               }
+               agp_free_memory(mem);
+       }
+       agp_priv->mem = NULL;
+}
+
+static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) {
+
+       drm_agp_ttm_priv *agp_priv; 
+       
+       if (backend) {
+         DRM_DEBUG("drm_agp_destroy_ttm\n");
+         agp_priv = (drm_agp_ttm_priv *) backend->private;
+               if (agp_priv) {
+                       if (agp_priv->mem) {
+                               drm_agp_clear_ttm(backend);
+                       }
+                       drm_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS);
+               }
+               drm_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS);
+       }
+}
+       
+
+drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev) {
+
+        drm_ttm_backend_t *agp_be;
+       drm_agp_ttm_priv *agp_priv;
+
+       agp_be = drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS);
+
+       if (!agp_be)
+               return NULL;
+       
+       agp_priv = drm_calloc(1, sizeof(agp_priv), DRM_MEM_MAPPINGS);
+       
+       if (!agp_priv) {
+               drm_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS);
+               return NULL;
+       }
+       
+       agp_priv->mem = NULL;
+       agp_priv->mem_type = AGP_MEM_USER;
+       agp_priv->bridge = dev->agp->bridge;
+       agp_priv->populated = FALSE;
+       agp_be->aperture_base = dev->agp->agp_info.aper_base;
+       agp_be->private = (void *) agp_priv;
+       agp_be->needs_cache_adjust = drm_agp_needs_cache_adjust_true;
+       agp_be->populate = drm_agp_populate;
+       agp_be->clear = drm_agp_clear_ttm;
+       agp_be->bind = drm_agp_bind_ttm;
+       agp_be->unbind = drm_agp_unbind_ttm;
+       agp_be->destroy = drm_agp_destroy_ttm;
+       return agp_be;
+}
+
+
+drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev) {
+
+        drm_ttm_backend_t *agp_be;
+       drm_agp_ttm_priv *agp_priv;
+
+       agp_be = drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS);
+
+       if (!agp_be)
+               return NULL;
+       
+       agp_priv = drm_calloc(1, sizeof(agp_priv), DRM_MEM_MAPPINGS);
+       
+       if (!agp_priv) {
+               drm_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS);
+               return NULL;
+       }
+       
+       agp_priv->mem = NULL;
+       agp_priv->mem_type = AGP_MEM_UCACHED;
+       agp_priv->bridge = dev->agp->bridge;
+       agp_priv->populated = FALSE;
+       agp_be->aperture_base = dev->agp->agp_info.aper_base;
+       agp_be->private = (void *) agp_priv;
+       agp_be->needs_cache_adjust = drm_agp_needs_cache_adjust_false;
+       agp_be->populate = drm_agp_populate;
+       agp_be->clear = drm_agp_clear_ttm;
+       agp_be->bind = drm_agp_bind_ttm;
+       agp_be->unbind = drm_agp_unbind_ttm;
+       agp_be->destroy = drm_agp_destroy_ttm;
+       return agp_be;
+}
+
+
 #endif                         /* __OS_HAS_AGP */