summaryrefslogtreecommitdiff
path: root/linux-core/ati_pcigart.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/ati_pcigart.c')
-rw-r--r--linux-core/ati_pcigart.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
index 524618a8..66742bbc 100644
--- a/linux-core/ati_pcigart.c
+++ b/linux-core/ati_pcigart.c
@@ -238,3 +238,148 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
return ret;
}
EXPORT_SYMBOL(drm_ati_pcigart_init);
+
+static int ati_pcigart_needs_unbind_cache_adjust(drm_ttm_backend_t *backend)
+{
+ return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
+}
+
+void ati_pcigart_alloc_page_array(size_t size, struct ati_pcigart_memory *mem)
+{
+ mem->memory = NULL;
+ mem->flags = 0;
+
+ if (size <= 2*PAGE_SIZE)
+ mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+ if (mem->memory == NULL) {
+ mem->memory = vmalloc(size);
+ mem->flags |= ATI_PCIGART_FLAG_VMALLOC;
+ }
+}
+
+static int ati_pcigart_populate(drm_ttm_backend_t *backend,
+ unsigned long num_pages,
+ struct page **pages)
+{
+ ati_pcigart_ttm_priv *atipci_priv = (ati_pcigart_ttm_priv *)backend->private;
+ struct page **cur_page, **last_page = pages + num_pages;
+ struct ati_pcigart_memory *mem;
+ unsigned long alloc_size = num_pages * sizeof(struct page *);
+
+ DRM_DEBUG("%d\n", num_pages);
+ if (drm_alloc_memctl(num_pages * sizeof(void *)))
+ return -1;
+
+ mem = drm_alloc(sizeof(struct ati_pcigart_memory), DRM_MEM_MAPPINGS);
+ if (!mem) {
+ drm_free_memctl(num_pages * sizeof(void *));
+ return -1;
+ }
+
+ ati_pcigart_alloc_page_array(alloc_size, mem);
+ mem->page_count = 0;
+ for (cur_page = pages; cur_page < last_page; ++cur_page) {
+ mem->memory[mem->page_count++] = page_to_phys(*cur_page);
+ }
+ atipci_priv->mem = mem;
+ return 0;
+}
+
+static int ati_pcigart_bind_ttm(drm_ttm_backend_t *backend,
+ unsigned long offset,
+ int cached)
+{
+ ati_pcigart_ttm_priv *atipci_priv = (ati_pcigart_ttm_priv *)backend->private;
+ struct ati_pcigart_memory *mem = atipci_priv->mem;
+ off_t j;
+
+ j = offset;
+ while (j < (pg_start + mem->page_count)) {
+ j++;
+ }
+
+ for (i = 0, j = offset; i < mem->page_count; i++, j++) {
+ /* write value */
+ }
+
+ /* need to traverse table and add entries */
+ DRM_DEBUG("\n");
+ return -1;
+}
+
+static int ati_pcigart_unbind_ttm(drm_ttm_backend_t *backend)
+{
+ ati_pcigart_ttm_priv *atipci_priv = (ati_pcigart_ttm_priv *)backend->private;
+
+ DRM_DEBUG("\n");
+ return -1;
+}
+
+static void ati_pcigart_clear_ttm(drm_ttm_backend_t *backend)
+{
+ ati_pcigart_ttm_priv *atipci_priv = (ati_pcigart_ttm_priv *)backend->private;
+ struct ati_pcigart_memory *mem = atipci_priv->mem;
+
+ DRM_DEBUG("\n");
+ if (mem) {
+ unsigned long num_pages = mem->page_count;
+ backend->unbind(backend);
+ /* free test */
+ drm_free(mem, sizeof(struct ati_pcigart_memory), DRM_MEM_MAPPINGS);
+ drm_free_memctl(num_pages * sizeof(void *));
+ }
+ atipci_priv->mem = NULL;
+}
+
+static void ati_pcigart_destroy_ttm(drm_ttm_backend_t *backend)
+{
+ ati_pcigart_ttm_priv *atipci_priv;
+
+ if (backend) {
+ DRM_DEBUG("\n");
+ atipci_priv = (ati_pcigart_ttm_priv *)backend->private;
+ if (atipci_priv) {
+ if (atipci_priv->mem) {
+ backend->clear(backend);
+ }
+ drm_ctl_free(atipci_priv, sizeof(*atipci_priv), DRM_MEM_MAPPINGS);
+ backend->private = NULL;
+ }
+ if (backend->flags & DRM_BE_FLAG_NEEDS_FREE) {
+ drm_ctl_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS);
+ }
+ }
+}
+
+
+drm_ttm_backend_t *ati_pcigart_init_ttm(struct drm_device *dev,
+ drm_ttm_backend_t *backend)
+{
+ drm_ttm_backend_t *atipci_be;
+ ati_pcigart_ttm_priv *atipci_priv;
+
+ atipci_be = (backend != NULL) ? backend :
+ drm_ctl_calloc(1, sizeof (*atipci_be), DRM_MEM_MAPPINGS);
+
+ if (!atipci_be)
+ return NULL;
+
+ atipci_priv = drm_ctl_calloc(1, sizeof(*atipci_priv), DRM_MEM_MAPPINGS);
+ if (!atipci_priv) {
+ drm_ctl_free(atipci_be, sizeof(*atipci_be), DRM_MEM_MAPPINGS);
+ return NULL;
+ }
+
+ atipci_priv->populated = FALSE;
+ atipci_be->needs_ub_cache_adjust = ati_pcigart_needs_unbind_cache_adjust;
+ atipci_be->populate = ati_pcigart_populate;
+ atipci_be->clear = ati_pcigart_clear_ttm;
+ atipci_be->bind = ati_pcigart_bind_ttm;
+ atipci_be->unbind = ati_pcigart_unbind_ttm;
+ atipci_be->destroy = ati_pcigart_destroy_ttm;
+
+ DRM_FLAG_MASKED(atipci_be->flags, (backend == NULL) ? DRM_BE_FLAG_NEEDS_FREE : 0, DRM_BE_FLAG_NEEDS_FREE);
+ atipci_be->drm_map_type = _DRM_SCATTER_GATHER;
+ return atipci_be;
+}
+EXPORT_SYMBOL(ati_pcigart_init_ttm);