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