3 * Memory mapping for DRM
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
10 * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
12 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
13 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14 * All Rights Reserved.
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
40 * \c nopage method for AGP virtual memory.
42 * \param vma virtual memory area.
43 * \param address access address.
44 * \return pointer to the page structure.
46 * Find the right map and if it's AGP memory find the real physical page to
47 * map, get the page, increment the use count and return it.
50 static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
51 unsigned long address)
53 struct drm_file *priv = vma->vm_file->private_data;
54 struct drm_device *dev = priv->minor->dev;
55 struct drm_map *map = NULL;
56 struct drm_map_list *r_list;
57 struct drm_hash_item *hash;
62 if (!drm_core_has_AGP(dev))
65 if (!dev->agp || !dev->agp->cant_use_aperture)
68 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
71 r_list = drm_hash_entry(hash, struct drm_map_list, hash);
74 if (map && map->type == _DRM_AGP) {
75 unsigned long offset = address - vma->vm_start;
76 unsigned long baddr = map->offset + offset;
77 struct drm_agp_mem *agpmem;
82 * Adjust to a bus-relative address
84 baddr -= dev->hose->mem_space->start;
88 * It's AGP memory - find the real physical page to map
90 list_for_each_entry(agpmem, &dev->agp->memory, head) {
91 if (agpmem->bound <= baddr &&
92 agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
100 * Get the page, inc the use count, and return it
102 offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
103 page = virt_to_page(__va(agpmem->memory->memory[offset]));
107 /* page_count() not defined everywhere */
109 ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
110 baddr, __va(agpmem->memory->memory[offset]), offset,
117 return NOPAGE_SIGBUS; /* Disallow mremap */
119 #else /* __OS_HAS_AGP */
120 static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
121 unsigned long address)
123 return NOPAGE_SIGBUS;
125 #endif /* __OS_HAS_AGP */
128 * \c nopage method for shared virtual memory.
130 * \param vma virtual memory area.
131 * \param address access address.
132 * \return pointer to the page structure.
134 * Get the mapping, find the real physical page to map, get the page, and
137 static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
138 unsigned long address)
140 struct drm_map *map = (struct drm_map *) vma->vm_private_data;
141 unsigned long offset;
145 if (address > vma->vm_end)
146 return NOPAGE_SIGBUS; /* Disallow mremap */
148 return NOPAGE_SIGBUS; /* Nothing allocated */
150 offset = address - vma->vm_start;
151 i = (unsigned long)map->handle + offset;
152 page = vmalloc_to_page((void *)i);
154 return NOPAGE_SIGBUS;
157 DRM_DEBUG("0x%lx\n", address);
162 * \c nopage method for DMA virtual memory.
164 * \param vma virtual memory area.
165 * \param address access address.
166 * \return pointer to the page structure.
168 * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
170 static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
171 unsigned long address)
173 struct drm_file *priv = vma->vm_file->private_data;
174 struct drm_device *dev = priv->minor->dev;
175 struct drm_device_dma *dma = dev->dma;
176 unsigned long offset;
177 unsigned long page_nr;
181 return NOPAGE_SIGBUS; /* Error */
182 if (address > vma->vm_end)
183 return NOPAGE_SIGBUS; /* Disallow mremap */
185 return NOPAGE_SIGBUS; /* Nothing allocated */
187 offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
188 page_nr = offset >> PAGE_SHIFT;
189 page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
193 DRM_DEBUG("0x%lx (page %lu)\n", address, page_nr);
198 * \c nopage method for scatter-gather virtual memory.
200 * \param vma virtual memory area.
201 * \param address access address.
202 * \return pointer to the page structure.
204 * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
206 static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
207 unsigned long address)
209 struct drm_map *map = (struct drm_map *) vma->vm_private_data;
210 struct drm_file *priv = vma->vm_file->private_data;
211 struct drm_device *dev = priv->minor->dev;
212 struct drm_sg_mem *entry = dev->sg;
213 unsigned long offset;
214 unsigned long map_offset;
215 unsigned long page_offset;
220 return NOPAGE_SIGBUS; /* Error */
221 if (address > vma->vm_end)
222 return NOPAGE_SIGBUS; /* Disallow mremap */
223 if (!entry->pagelist)
224 return NOPAGE_SIGBUS; /* Nothing allocated */
226 offset = address - vma->vm_start;
227 map_offset = map->offset - (unsigned long)dev->sg->virtual;
228 page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
229 page = entry->pagelist[page_offset];
236 struct page *drm_vm_nopage(struct vm_area_struct *vma,
237 unsigned long address, int *type)
240 *type = VM_FAULT_MINOR;
241 return drm_do_vm_nopage(vma, address);
244 struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
245 unsigned long address, int *type)
248 *type = VM_FAULT_MINOR;
249 return drm_do_vm_shm_nopage(vma, address);
252 struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
253 unsigned long address, int *type)
256 *type = VM_FAULT_MINOR;
257 return drm_do_vm_dma_nopage(vma, address);
260 struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
261 unsigned long address, int *type)
264 *type = VM_FAULT_MINOR;
265 return drm_do_vm_sg_nopage(vma, address);