AGP backends for TTM.

This commit is contained in:
Thomas Hellstrom 2006-08-22 10:09:57 +02:00
parent 700bf80ca9
commit b81ca5e031
2 changed files with 177 additions and 0 deletions

View 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,

View 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 */