1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <drm/drmP.h>
35#include <linux/module.h>
36#include <linux/slab.h>
37#include "drm_legacy.h"
38
39#if __OS_HAS_AGP
40
41#include <asm/agp.h>
42
43
44
45
46
47
48
49
50
51
52
53
54
55int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
56{
57 struct agp_kern_info *kern;
58
59 if (!dev->agp || !dev->agp->acquired)
60 return -EINVAL;
61
62 kern = &dev->agp->agp_info;
63 info->agp_version_major = kern->version.major;
64 info->agp_version_minor = kern->version.minor;
65 info->mode = kern->mode;
66 info->aperture_base = kern->aper_base;
67 info->aperture_size = kern->aper_size * 1024 * 1024;
68 info->memory_allowed = kern->max_memory << PAGE_SHIFT;
69 info->memory_used = kern->current_memory << PAGE_SHIFT;
70 info->id_vendor = kern->device->vendor;
71 info->id_device = kern->device->device;
72
73 return 0;
74}
75
76EXPORT_SYMBOL(drm_agp_info);
77
78int drm_agp_info_ioctl(struct drm_device *dev, void *data,
79 struct drm_file *file_priv)
80{
81 struct drm_agp_info *info = data;
82 int err;
83
84 err = drm_agp_info(dev, info);
85 if (err)
86 return err;
87
88 return 0;
89}
90
91
92
93
94
95
96
97
98
99
100int drm_agp_acquire(struct drm_device * dev)
101{
102 if (!dev->agp)
103 return -ENODEV;
104 if (dev->agp->acquired)
105 return -EBUSY;
106 if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
107 return -ENODEV;
108 dev->agp->acquired = 1;
109 return 0;
110}
111
112EXPORT_SYMBOL(drm_agp_acquire);
113
114
115
116
117
118
119
120
121
122
123
124
125
126int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
127 struct drm_file *file_priv)
128{
129 return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
130}
131
132
133
134
135
136
137
138
139
140int drm_agp_release(struct drm_device * dev)
141{
142 if (!dev->agp || !dev->agp->acquired)
143 return -EINVAL;
144 agp_backend_release(dev->agp->bridge);
145 dev->agp->acquired = 0;
146 return 0;
147}
148EXPORT_SYMBOL(drm_agp_release);
149
150int drm_agp_release_ioctl(struct drm_device *dev, void *data,
151 struct drm_file *file_priv)
152{
153 return drm_agp_release(dev);
154}
155
156
157
158
159
160
161
162
163
164
165
166int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
167{
168 if (!dev->agp || !dev->agp->acquired)
169 return -EINVAL;
170
171 dev->agp->mode = mode.mode;
172 agp_enable(dev->agp->bridge, mode.mode);
173 dev->agp->enabled = 1;
174 return 0;
175}
176
177EXPORT_SYMBOL(drm_agp_enable);
178
179int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
180 struct drm_file *file_priv)
181{
182 struct drm_agp_mode *mode = data;
183
184 return drm_agp_enable(dev, *mode);
185}
186
187
188
189
190
191
192
193
194
195
196
197
198
199int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
200{
201 struct drm_agp_mem *entry;
202 struct agp_memory *memory;
203 unsigned long pages;
204 u32 type;
205
206 if (!dev->agp || !dev->agp->acquired)
207 return -EINVAL;
208 if (!(entry = kzalloc(sizeof(*entry), GFP_KERNEL)))
209 return -ENOMEM;
210
211 pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
212 type = (u32) request->type;
213 if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) {
214 kfree(entry);
215 return -ENOMEM;
216 }
217
218 entry->handle = (unsigned long)memory->key + 1;
219 entry->memory = memory;
220 entry->bound = 0;
221 entry->pages = pages;
222 list_add(&entry->head, &dev->agp->memory);
223
224 request->handle = entry->handle;
225 request->physical = memory->physical;
226
227 return 0;
228}
229EXPORT_SYMBOL(drm_agp_alloc);
230
231
232int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
233 struct drm_file *file_priv)
234{
235 struct drm_agp_buffer *request = data;
236
237 return drm_agp_alloc(dev, request);
238}
239
240
241
242
243
244
245
246
247
248
249static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
250 unsigned long handle)
251{
252 struct drm_agp_mem *entry;
253
254 list_for_each_entry(entry, &dev->agp->memory, head) {
255 if (entry->handle == handle)
256 return entry;
257 }
258 return NULL;
259}
260
261
262
263
264
265
266
267
268
269
270
271
272
273int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
274{
275 struct drm_agp_mem *entry;
276 int ret;
277
278 if (!dev->agp || !dev->agp->acquired)
279 return -EINVAL;
280 if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
281 return -EINVAL;
282 if (!entry->bound)
283 return -EINVAL;
284 ret = drm_unbind_agp(entry->memory);
285 if (ret == 0)
286 entry->bound = 0;
287 return ret;
288}
289EXPORT_SYMBOL(drm_agp_unbind);
290
291
292int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
293 struct drm_file *file_priv)
294{
295 struct drm_agp_binding *request = data;
296
297 return drm_agp_unbind(dev, request);
298}
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
314{
315 struct drm_agp_mem *entry;
316 int retcode;
317 int page;
318
319 if (!dev->agp || !dev->agp->acquired)
320 return -EINVAL;
321 if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
322 return -EINVAL;
323 if (entry->bound)
324 return -EINVAL;
325 page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
326 if ((retcode = drm_bind_agp(entry->memory, page)))
327 return retcode;
328 entry->bound = dev->agp->base + (page << PAGE_SHIFT);
329 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
330 dev->agp->base, entry->bound);
331 return 0;
332}
333EXPORT_SYMBOL(drm_agp_bind);
334
335
336int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
337 struct drm_file *file_priv)
338{
339 struct drm_agp_binding *request = data;
340
341 return drm_agp_bind(dev, request);
342}
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
359{
360 struct drm_agp_mem *entry;
361
362 if (!dev->agp || !dev->agp->acquired)
363 return -EINVAL;
364 if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
365 return -EINVAL;
366 if (entry->bound)
367 drm_unbind_agp(entry->memory);
368
369 list_del(&entry->head);
370
371 drm_free_agp(entry->memory, entry->pages);
372 kfree(entry);
373 return 0;
374}
375EXPORT_SYMBOL(drm_agp_free);
376
377
378
379int drm_agp_free_ioctl(struct drm_device *dev, void *data,
380 struct drm_file *file_priv)
381{
382 struct drm_agp_buffer *request = data;
383
384 return drm_agp_free(dev, request);
385}
386
387
388
389
390
391
392
393
394
395
396
397
398
399struct drm_agp_head *drm_agp_init(struct drm_device *dev)
400{
401 struct drm_agp_head *head = NULL;
402
403 if (!(head = kzalloc(sizeof(*head), GFP_KERNEL)))
404 return NULL;
405 head->bridge = agp_find_bridge(dev->pdev);
406 if (!head->bridge) {
407 if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
408 kfree(head);
409 return NULL;
410 }
411 agp_copy_info(head->bridge, &head->agp_info);
412 agp_backend_release(head->bridge);
413 } else {
414 agp_copy_info(head->bridge, &head->agp_info);
415 }
416 if (head->agp_info.chipset == NOT_SUPPORTED) {
417 kfree(head);
418 return NULL;
419 }
420 INIT_LIST_HEAD(&head->memory);
421 head->cant_use_aperture = head->agp_info.cant_use_aperture;
422 head->page_mask = head->agp_info.page_mask;
423 head->base = head->agp_info.aper_base;
424 return head;
425}
426
427
428
429
430
431
432
433
434
435
436
437
438
439void drm_agp_clear(struct drm_device *dev)
440{
441 struct drm_agp_mem *entry, *tempe;
442
443 if (!dev->agp)
444 return;
445 if (drm_core_check_feature(dev, DRIVER_MODESET))
446 return;
447
448 list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
449 if (entry->bound)
450 drm_unbind_agp(entry->memory);
451 drm_free_agp(entry->memory, entry->pages);
452 kfree(entry);
453 }
454 INIT_LIST_HEAD(&dev->agp->memory);
455
456 if (dev->agp->acquired)
457 drm_agp_release(dev);
458
459 dev->agp->acquired = 0;
460 dev->agp->enabled = 0;
461}
462
463
464
465
466
467
468
469
470struct agp_memory *
471drm_agp_bind_pages(struct drm_device *dev,
472 struct page **pages,
473 unsigned long num_pages,
474 uint32_t gtt_offset,
475 u32 type)
476{
477 struct agp_memory *mem;
478 int ret, i;
479
480 DRM_DEBUG("\n");
481
482 mem = agp_allocate_memory(dev->agp->bridge, num_pages,
483 type);
484 if (mem == NULL) {
485 DRM_ERROR("Failed to allocate memory for %ld pages\n",
486 num_pages);
487 return NULL;
488 }
489
490 for (i = 0; i < num_pages; i++)
491 mem->pages[i] = pages[i];
492 mem->page_count = num_pages;
493
494 mem->is_flushed = true;
495 ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
496 if (ret != 0) {
497 DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
498 agp_free_memory(mem);
499 return NULL;
500 }
501
502 return mem;
503}
504EXPORT_SYMBOL(drm_agp_bind_pages);
505
506#endif
507