/**1* \file drm_memory.c2* Memory management wrappers for DRM3*4* \author Rickard E. (Rik) Faith <[email protected]>5* \author Gareth Hughes <[email protected]>6*/78/*9* Created: Thu Feb 4 14:00:34 1999 by [email protected]10*11* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.12* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.13* All Rights Reserved.14*15* Permission is hereby granted, free of charge, to any person obtaining a16* copy of this software and associated documentation files (the "Software"),17* to deal in the Software without restriction, including without limitation18* the rights to use, copy, modify, merge, publish, distribute, sublicense,19* and/or sell copies of the Software, and to permit persons to whom the20* Software is furnished to do so, subject to the following conditions:21*22* The above copyright notice and this permission notice (including the next23* paragraph) shall be included in all copies or substantial portions of the24* Software.25*26* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR27* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,28* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL29* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR30* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,31* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR32* OTHER DEALINGS IN THE SOFTWARE.33*/3435#include <linux/highmem.h>36#include "drmP.h"3738/**39* Called when "/proc/dri/%dev%/mem" is read.40*41* \param buf output buffer.42* \param start start of output data.43* \param offset requested start offset.44* \param len requested number of bytes.45* \param eof whether there is no more data to return.46* \param data private data.47* \return number of written bytes.48*49* No-op.50*/51int drm_mem_info(char *buf, char **start, off_t offset,52int len, int *eof, void *data)53{54return 0;55}5657#if __OS_HAS_AGP58static void *agp_remap(unsigned long offset, unsigned long size,59struct drm_device * dev)60{61unsigned long i, num_pages =62PAGE_ALIGN(size) / PAGE_SIZE;63struct drm_agp_mem *agpmem;64struct page **page_map;65struct page **phys_page_map;66void *addr;6768size = PAGE_ALIGN(size);6970#ifdef __alpha__71offset -= dev->hose->mem_space->start;72#endif7374list_for_each_entry(agpmem, &dev->agp->memory, head)75if (agpmem->bound <= offset76&& (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=77(offset + size))78break;79if (&agpmem->head == &dev->agp->memory)80return NULL;8182/*83* OK, we're mapping AGP space on a chipset/platform on which memory accesses by84* the CPU do not get remapped by the GART. We fix this by using the kernel's85* page-table instead (that's probably faster anyhow...).86*/87/* note: use vmalloc() because num_pages could be large... */88page_map = vmalloc(num_pages * sizeof(struct page *));89if (!page_map)90return NULL;9192phys_page_map = (agpmem->memory->pages + (offset - agpmem->bound) / PAGE_SIZE);93for (i = 0; i < num_pages; ++i)94page_map[i] = phys_page_map[i];95addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);96vfree(page_map);9798return addr;99}100101/** Wrapper around agp_free_memory() */102void drm_free_agp(DRM_AGP_MEM * handle, int pages)103{104agp_free_memory(handle);105}106EXPORT_SYMBOL(drm_free_agp);107108/** Wrapper around agp_bind_memory() */109int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)110{111return agp_bind_memory(handle, start);112}113114/** Wrapper around agp_unbind_memory() */115int drm_unbind_agp(DRM_AGP_MEM * handle)116{117return agp_unbind_memory(handle);118}119EXPORT_SYMBOL(drm_unbind_agp);120121#else /* __OS_HAS_AGP */122static inline void *agp_remap(unsigned long offset, unsigned long size,123struct drm_device * dev)124{125return NULL;126}127128#endif /* agp */129130void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)131{132if (drm_core_has_AGP(dev) &&133dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)134map->handle = agp_remap(map->offset, map->size, dev);135else136map->handle = ioremap(map->offset, map->size);137}138EXPORT_SYMBOL(drm_core_ioremap);139140void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)141{142if (drm_core_has_AGP(dev) &&143dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)144map->handle = agp_remap(map->offset, map->size, dev);145else146map->handle = ioremap_wc(map->offset, map->size);147}148EXPORT_SYMBOL(drm_core_ioremap_wc);149150void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)151{152if (!map->handle || !map->size)153return;154155if (drm_core_has_AGP(dev) &&156dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)157vunmap(map->handle);158else159iounmap(map->handle);160}161EXPORT_SYMBOL(drm_core_ioremapfree);162163164