diff options
Diffstat (limited to 'linux/drm_vm.h')
-rw-r--r-- | linux/drm_vm.h | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/linux/drm_vm.h b/linux/drm_vm.h index d8e77f79..2a5ee146 100644 --- a/linux/drm_vm.h +++ b/linux/drm_vm.h @@ -67,6 +67,64 @@ struct page *DRM(vm_nopage)(struct vm_area_struct *vma, int write_access) #endif { +#if defined(__alpha__) && __REALLY_HAVE_AGP + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map = NULL; + drm_map_list_t *r_list; + struct list_head *list; + + /* + * Find the right map + */ + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *)list; + map = r_list->map; + if (!map) continue; + if (map->offset == VM_OFFSET(vma)) break; + } + + if (map && map->type == _DRM_AGP) { + unsigned long offset = address - vma->vm_start; + unsigned long baddr = VM_OFFSET(vma) + offset; + struct drm_agp_mem *agpmem; + struct page *page; + + /* + * Make it a bus-relative address + */ + baddr -= dev->hose->mem_space->start; + + /* + * It's AGP memory - find the real physical page to map + */ + for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { + if (agpmem->bound <= baddr && + agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) + break; + } + + if (!agpmem) { + /* + * Oops - no memory found + */ + return NOPAGE_SIGBUS; /* couldn't find it */ + } + + /* + * Get the page, inc the use count, and return it + */ + offset = (baddr - agpmem->bound) >> PAGE_SHIFT; + agpmem->memory->memory[offset] &= ~1UL; /* HACK */ + page = virt_to_page(__va(agpmem->memory->memory[offset])); +#if 0 +DRM_ERROR("baddr = 0x%lx page = 0x%lx, offset = 0x%lx\n", + baddr, __va(agpmem->memory->memory[offset]), offset); +#endif + get_page(page); + return page; + } +#endif return NOPAGE_SIGBUS; /* Disallow mremap */ } @@ -434,9 +492,20 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) } switch (map->type) { + case _DRM_AGP: +#if defined(__alpha__) + /* + * On Alpha we can't talk to bus dma address from the + * CPU, so for memory of type DRM_AGP, we'll deal with + * sorting out the real physical pages and mappings + * in nopage() + */ + vma->vm_ops = &DRM(vm_ops); + break; +#endif + /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: - case _DRM_AGP: if (VM_OFFSET(vma) >= __pa(high_memory)) { #if defined(__i386__) if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { |