Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
drm_agpsupport.c
Go to the documentation of this file.
1 
9 /*
10  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12  * All Rights Reserved.
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice (including the next
22  * paragraph) shall be included in all copies or substantial portions of the
23  * Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31  * OTHER DEALINGS IN THE SOFTWARE.
32  */
33 
34 #include <drm/drmP.h>
35 #include <linux/module.h>
36 #include <linux/slab.h>
37 
38 #if __OS_HAS_AGP
39 
40 #include <asm/agp.h>
41 
54 int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
55 {
56  DRM_AGP_KERN *kern;
57 
58  if (!dev->agp || !dev->agp->acquired)
59  return -EINVAL;
60 
61  kern = &dev->agp->agp_info;
62  info->agp_version_major = kern->version.major;
63  info->agp_version_minor = kern->version.minor;
64  info->mode = kern->mode;
65  info->aperture_base = kern->aper_base;
66  info->aperture_size = kern->aper_size * 1024 * 1024;
67  info->memory_allowed = kern->max_memory << PAGE_SHIFT;
68  info->memory_used = kern->current_memory << PAGE_SHIFT;
69  info->id_vendor = kern->device->vendor;
70  info->id_device = kern->device->device;
71 
72  return 0;
73 }
74 
76 
77 int drm_agp_info_ioctl(struct drm_device *dev, void *data,
78  struct drm_file *file_priv)
79 {
80  struct drm_agp_info *info = data;
81  int err;
82 
83  err = drm_agp_info(dev, info);
84  if (err)
85  return err;
86 
87  return 0;
88 }
89 
99 int drm_agp_acquire(struct drm_device * dev)
100 {
101  if (!dev->agp)
102  return -ENODEV;
103  if (dev->agp->acquired)
104  return -EBUSY;
105  if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
106  return -ENODEV;
107  dev->agp->acquired = 1;
108  return 0;
109 }
110 
111 EXPORT_SYMBOL(drm_agp_acquire);
112 
125 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
126  struct drm_file *file_priv)
127 {
128  return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
129 }
130 
139 int drm_agp_release(struct drm_device * dev)
140 {
141  if (!dev->agp || !dev->agp->acquired)
142  return -EINVAL;
143  agp_backend_release(dev->agp->bridge);
144  dev->agp->acquired = 0;
145  return 0;
146 }
147 EXPORT_SYMBOL(drm_agp_release);
148 
149 int drm_agp_release_ioctl(struct drm_device *dev, void *data,
150  struct drm_file *file_priv)
151 {
152  return drm_agp_release(dev);
153 }
154 
165 int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
166 {
167  if (!dev->agp || !dev->agp->acquired)
168  return -EINVAL;
169 
170  dev->agp->mode = mode.mode;
171  agp_enable(dev->agp->bridge, mode.mode);
172  dev->agp->enabled = 1;
173  return 0;
174 }
175 
176 EXPORT_SYMBOL(drm_agp_enable);
177 
178 int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
179  struct drm_file *file_priv)
180 {
181  struct drm_agp_mode *mode = data;
182 
183  return drm_agp_enable(dev, *mode);
184 }
185 
198 int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
199 {
200  struct drm_agp_mem *entry;
202  unsigned long pages;
203  u32 type;
204 
205  if (!dev->agp || !dev->agp->acquired)
206  return -EINVAL;
207  if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
208  return -ENOMEM;
209 
210  memset(entry, 0, sizeof(*entry));
211 
212  pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
213  type = (u32) request->type;
214  if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) {
215  kfree(entry);
216  return -ENOMEM;
217  }
218 
219  entry->handle = (unsigned long)memory->key + 1;
220  entry->memory = memory;
221  entry->bound = 0;
222  entry->pages = pages;
223  list_add(&entry->head, &dev->agp->memory);
224 
225  request->handle = entry->handle;
226  request->physical = memory->physical;
227 
228  return 0;
229 }
230 EXPORT_SYMBOL(drm_agp_alloc);
231 
232 
233 int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
234  struct drm_file *file_priv)
235 {
236  struct drm_agp_buffer *request = data;
237 
238  return drm_agp_alloc(dev, request);
239 }
240 
250 static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
251  unsigned long handle)
252 {
253  struct drm_agp_mem *entry;
254 
255  list_for_each_entry(entry, &dev->agp->memory, head) {
256  if (entry->handle == handle)
257  return entry;
258  }
259  return NULL;
260 }
261 
274 int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
275 {
276  struct drm_agp_mem *entry;
277  int ret;
278 
279  if (!dev->agp || !dev->agp->acquired)
280  return -EINVAL;
281  if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
282  return -EINVAL;
283  if (!entry->bound)
284  return -EINVAL;
285  ret = drm_unbind_agp(entry->memory);
286  if (ret == 0)
287  entry->bound = 0;
288  return ret;
289 }
290 EXPORT_SYMBOL(drm_agp_unbind);
291 
292 
293 int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
294  struct drm_file *file_priv)
295 {
296  struct drm_agp_binding *request = data;
297 
298  return drm_agp_unbind(dev, request);
299 }
300 
314 int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
315 {
316  struct drm_agp_mem *entry;
317  int retcode;
318  int page;
319 
320  if (!dev->agp || !dev->agp->acquired)
321  return -EINVAL;
322  if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
323  return -EINVAL;
324  if (entry->bound)
325  return -EINVAL;
326  page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
327  if ((retcode = drm_bind_agp(entry->memory, page)))
328  return retcode;
329  entry->bound = dev->agp->base + (page << PAGE_SHIFT);
330  DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
331  dev->agp->base, entry->bound);
332  return 0;
333 }
334 EXPORT_SYMBOL(drm_agp_bind);
335 
336 
337 int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
338  struct drm_file *file_priv)
339 {
340  struct drm_agp_binding *request = data;
341 
342  return drm_agp_bind(dev, request);
343 }
344 
359 int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
360 {
361  struct drm_agp_mem *entry;
362 
363  if (!dev->agp || !dev->agp->acquired)
364  return -EINVAL;
365  if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
366  return -EINVAL;
367  if (entry->bound)
368  drm_unbind_agp(entry->memory);
369 
370  list_del(&entry->head);
371 
372  drm_free_agp(entry->memory, entry->pages);
373  kfree(entry);
374  return 0;
375 }
376 EXPORT_SYMBOL(drm_agp_free);
377 
378 
379 
380 int drm_agp_free_ioctl(struct drm_device *dev, void *data,
381  struct drm_file *file_priv)
382 {
383  struct drm_agp_buffer *request = data;
384 
385  return drm_agp_free(dev, request);
386 }
387 
397 struct drm_agp_head *drm_agp_init(struct drm_device *dev)
398 {
399  struct drm_agp_head *head = NULL;
400 
401  if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
402  return NULL;
403  memset((void *)head, 0, sizeof(*head));
404  head->bridge = agp_find_bridge(dev->pdev);
405  if (!head->bridge) {
406  if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
407  kfree(head);
408  return NULL;
409  }
410  agp_copy_info(head->bridge, &head->agp_info);
411  agp_backend_release(head->bridge);
412  } else {
413  agp_copy_info(head->bridge, &head->agp_info);
414  }
415  if (head->agp_info.chipset == NOT_SUPPORTED) {
416  kfree(head);
417  return NULL;
418  }
419  INIT_LIST_HEAD(&head->memory);
420  head->cant_use_aperture = head->agp_info.cant_use_aperture;
421  head->page_mask = head->agp_info.page_mask;
422  head->base = head->agp_info.aper_base;
423  return head;
424 }
425 
433 DRM_AGP_MEM *
434 drm_agp_bind_pages(struct drm_device *dev,
435  struct page **pages,
436  unsigned long num_pages,
437  uint32_t gtt_offset,
438  u32 type)
439 {
440  DRM_AGP_MEM *mem;
441  int ret, i;
442 
443  DRM_DEBUG("\n");
444 
445  mem = agp_allocate_memory(dev->agp->bridge, num_pages,
446  type);
447  if (mem == NULL) {
448  DRM_ERROR("Failed to allocate memory for %ld pages\n",
449  num_pages);
450  return NULL;
451  }
452 
453  for (i = 0; i < num_pages; i++)
454  mem->pages[i] = pages[i];
455  mem->page_count = num_pages;
456 
457  mem->is_flushed = true;
458  ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
459  if (ret != 0) {
460  DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
461  agp_free_memory(mem);
462  return NULL;
463  }
464 
465  return mem;
466 }
467 EXPORT_SYMBOL(drm_agp_bind_pages);
468 
469 #endif /* __OS_HAS_AGP */