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 "drmP.h"
35#include <linux/module.h>
36
37#if __OS_HAS_AGP
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 DRM_AGP_KERN *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 DRM_AGP_MEM *memory;
201 unsigned long pages;
202 u32 type;
203
204 if (!dev->agp || !dev->agp->acquired)
205 return -EINVAL;
206 if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
207 return -ENOMEM;
208
209 memset(entry, 0, sizeof(*entry));
210
211 pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
212 type = (u32) request->type;
213 if (!(memory = drm_alloc_agp(dev, 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
396struct drm_agp_head *drm_agp_init(struct drm_device *dev)
397{
398 struct drm_agp_head *head = NULL;
399
400 if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
401 return NULL;
402 memset((void *)head, 0, sizeof(*head));
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
426DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge,
427 size_t pages, u32 type)
428{
429 return agp_allocate_memory(bridge, pages, type);
430}
431
432
433int drm_agp_free_memory(DRM_AGP_MEM * handle)
434{
435 if (!handle)
436 return 0;
437 agp_free_memory(handle);
438 return 1;
439}
440
441
442int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
443{
444 if (!handle)
445 return -EINVAL;
446 return agp_bind_memory(handle, start);
447}
448
449
450int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
451{
452 if (!handle)
453 return -EINVAL;
454 return agp_unbind_memory(handle);
455}
456
457
458
459
460
461
462
463
464DRM_AGP_MEM *
465drm_agp_bind_pages(struct drm_device *dev,
466 struct page **pages,
467 unsigned long num_pages,
468 uint32_t gtt_offset,
469 u32 type)
470{
471 DRM_AGP_MEM *mem;
472 int ret, i;
473
474 DRM_DEBUG("\n");
475
476 mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages,
477 type);
478 if (mem == NULL) {
479 DRM_ERROR("Failed to allocate memory for %ld pages\n",
480 num_pages);
481 return NULL;
482 }
483
484 for (i = 0; i < num_pages; i++)
485 mem->pages[i] = pages[i];
486 mem->page_count = num_pages;
487
488 mem->is_flushed = true;
489 ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
490 if (ret != 0) {
491 DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
492 agp_free_memory(mem);
493 return NULL;
494 }
495
496 return mem;
497}
498EXPORT_SYMBOL(drm_agp_bind_pages);
499
500void drm_agp_chipset_flush(struct drm_device *dev)
501{
502 agp_flush_chipset(dev->agp->bridge);
503}
504EXPORT_SYMBOL(drm_agp_chipset_flush);
505
506#endif
507