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#include "drmP.h"
33#include <linux/module.h>
34
35#if __REALLY_HAVE_AGP
36
37#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
38#define DRM_AGP_PUT inter_module_put("drm_agp")
39
40static const drm_agp_t *drm_agp = NULL;
41
42int DRM(agp_info)(struct inode *inode, struct file *filp,
43 unsigned int cmd, unsigned long arg)
44{
45 drm_file_t *priv = filp->private_data;
46 drm_device_t *dev = priv->dev;
47 agp_kern_info *kern;
48 drm_agp_info_t info;
49
50 if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
51 return -EINVAL;
52
53 kern = &dev->agp->agp_info;
54 info.agp_version_major = kern->version.major;
55 info.agp_version_minor = kern->version.minor;
56 info.mode = kern->mode;
57 info.aperture_base = kern->aper_base;
58 info.aperture_size = kern->aper_size * 1024 * 1024;
59 info.memory_allowed = kern->max_memory << PAGE_SHIFT;
60 info.memory_used = kern->current_memory << PAGE_SHIFT;
61 info.id_vendor = kern->device->vendor;
62 info.id_device = kern->device->device;
63
64 if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info)))
65 return -EFAULT;
66 return 0;
67}
68
69int DRM(agp_acquire)(struct inode *inode, struct file *filp,
70 unsigned int cmd, unsigned long arg)
71{
72 drm_file_t *priv = filp->private_data;
73 drm_device_t *dev = priv->dev;
74 int retcode;
75
76 if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
77 return -EINVAL;
78 if ((retcode = drm_agp->acquire())) return retcode;
79 dev->agp->acquired = 1;
80 return 0;
81}
82
83int DRM(agp_release)(struct inode *inode, struct file *filp,
84 unsigned int cmd, unsigned long arg)
85{
86 drm_file_t *priv = filp->private_data;
87 drm_device_t *dev = priv->dev;
88
89 if (!dev->agp || !dev->agp->acquired || !drm_agp->release)
90 return -EINVAL;
91 drm_agp->release();
92 dev->agp->acquired = 0;
93 return 0;
94
95}
96
97void DRM(agp_do_release)(void)
98{
99 if (drm_agp->release) drm_agp->release();
100}
101
102int DRM(agp_enable)(struct inode *inode, struct file *filp,
103 unsigned int cmd, unsigned long arg)
104{
105 drm_file_t *priv = filp->private_data;
106 drm_device_t *dev = priv->dev;
107 drm_agp_mode_t mode;
108
109 if (!dev->agp || !dev->agp->acquired || !drm_agp->enable)
110 return -EINVAL;
111
112 if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
113 return -EFAULT;
114
115 dev->agp->mode = mode.mode;
116 drm_agp->enable(mode.mode);
117 dev->agp->base = dev->agp->agp_info.aper_base;
118 dev->agp->enabled = 1;
119 return 0;
120}
121
122int DRM(agp_alloc)(struct inode *inode, struct file *filp,
123 unsigned int cmd, unsigned long arg)
124{
125 drm_file_t *priv = filp->private_data;
126 drm_device_t *dev = priv->dev;
127 drm_agp_buffer_t request;
128 drm_agp_mem_t *entry;
129 agp_memory *memory;
130 unsigned long pages;
131 u32 type;
132
133 if (!dev->agp || !dev->agp->acquired) return -EINVAL;
134 if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
135 return -EFAULT;
136 if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
137 return -ENOMEM;
138
139 memset(entry, 0, sizeof(*entry));
140
141 pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
142 type = (u32) request.type;
143
144 if (!(memory = DRM(alloc_agp)(pages, type))) {
145 DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
146 return -ENOMEM;
147 }
148
149 entry->handle = (unsigned long)memory->memory;
150 entry->memory = memory;
151 entry->bound = 0;
152 entry->pages = pages;
153 entry->prev = NULL;
154 entry->next = dev->agp->memory;
155 if (dev->agp->memory) dev->agp->memory->prev = entry;
156 dev->agp->memory = entry;
157
158 request.handle = entry->handle;
159 request.physical = memory->physical;
160
161 if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) {
162 dev->agp->memory = entry->next;
163 dev->agp->memory->prev = NULL;
164 DRM(free_agp)(memory, pages);
165 DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
166 return -EFAULT;
167 }
168 return 0;
169}
170
171static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev,
172 unsigned long handle)
173{
174 drm_agp_mem_t *entry;
175
176 for (entry = dev->agp->memory; entry; entry = entry->next) {
177 if (entry->handle == handle) return entry;
178 }
179 return NULL;
180}
181
182int DRM(agp_unbind)(struct inode *inode, struct file *filp,
183 unsigned int cmd, unsigned long arg)
184{
185 drm_file_t *priv = filp->private_data;
186 drm_device_t *dev = priv->dev;
187 drm_agp_binding_t request;
188 drm_agp_mem_t *entry;
189
190 if (!dev->agp || !dev->agp->acquired) return -EINVAL;
191 if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
192 return -EFAULT;
193 if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
194 return -EINVAL;
195 if (!entry->bound) return -EINVAL;
196 return DRM(unbind_agp)(entry->memory);
197}
198
199int DRM(agp_bind)(struct inode *inode, struct file *filp,
200 unsigned int cmd, unsigned long arg)
201{
202 drm_file_t *priv = filp->private_data;
203 drm_device_t *dev = priv->dev;
204 drm_agp_binding_t request;
205 drm_agp_mem_t *entry;
206 int retcode;
207 int page;
208
209 if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory)
210 return -EINVAL;
211 if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
212 return -EFAULT;
213 if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
214 return -EINVAL;
215 if (entry->bound) return -EINVAL;
216 page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
217 if ((retcode = DRM(bind_agp)(entry->memory, page))) return retcode;
218 entry->bound = dev->agp->base + (page << PAGE_SHIFT);
219 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
220 dev->agp->base, entry->bound);
221 return 0;
222}
223
224int DRM(agp_free)(struct inode *inode, struct file *filp,
225 unsigned int cmd, unsigned long arg)
226{
227 drm_file_t *priv = filp->private_data;
228 drm_device_t *dev = priv->dev;
229 drm_agp_buffer_t request;
230 drm_agp_mem_t *entry;
231
232 if (!dev->agp || !dev->agp->acquired) return -EINVAL;
233 if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
234 return -EFAULT;
235 if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
236 return -EINVAL;
237 if (entry->bound) DRM(unbind_agp)(entry->memory);
238
239 if (entry->prev) entry->prev->next = entry->next;
240 else dev->agp->memory = entry->next;
241 if (entry->next) entry->next->prev = entry->prev;
242 DRM(free_agp)(entry->memory, entry->pages);
243 DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
244 return 0;
245}
246
247drm_agp_head_t *DRM(agp_init)(void)
248{
249 drm_agp_head_t *head = NULL;
250
251 drm_agp = DRM_AGP_GET;
252 if (drm_agp) {
253 if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS)))
254 return NULL;
255 memset((void *)head, 0, sizeof(*head));
256 drm_agp->copy_info(&head->agp_info);
257 if (head->agp_info.chipset == NOT_SUPPORTED) {
258 DRM(free)(head, sizeof(*head), DRM_MEM_AGPLISTS);
259 return NULL;
260 }
261 head->memory = NULL;
262 switch (head->agp_info.chipset) {
263 case INTEL_GENERIC: head->chipset = "Intel"; break;
264 case INTEL_LX: head->chipset = "Intel 440LX"; break;
265 case INTEL_BX: head->chipset = "Intel 440BX"; break;
266 case INTEL_GX: head->chipset = "Intel 440GX"; break;
267 case INTEL_I810: head->chipset = "Intel i810"; break;
268 case INTEL_I815: head->chipset = "Intel i815"; break;
269 case INTEL_I820: head->chipset = "Intel i820"; break;
270 case INTEL_I840: head->chipset = "Intel i840"; break;
271 case INTEL_I845: head->chipset = "Intel i845"; break;
272 case INTEL_I850: head->chipset = "Intel i850"; break;
273
274 case VIA_GENERIC: head->chipset = "VIA"; break;
275 case VIA_VP3: head->chipset = "VIA VP3"; break;
276 case VIA_MVP3: head->chipset = "VIA MVP3"; break;
277 case VIA_MVP4: head->chipset = "VIA MVP4"; break;
278 case VIA_APOLLO_KX133: head->chipset = "VIA Apollo KX133";
279 break;
280 case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133";
281 break;
282 case VIA_APOLLO_KT400: head->chipset = "VIA Apollo KT400";
283 break;
284 case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro";
285 break;
286 case VIA_APOLLO_P4X400: head->chipset = "VIA Apollo P4X400";
287 break;
288
289 case SIS_GENERIC: head->chipset = "SiS"; break;
290 case AMD_GENERIC: head->chipset = "AMD"; break;
291 case AMD_IRONGATE: head->chipset = "AMD Irongate"; break;
292 case AMD_8151: head->chipset = "AMD 8151"; break;
293 case ALI_GENERIC: head->chipset = "ALi"; break;
294 case ALI_M1541: head->chipset = "ALi M1541"; break;
295
296 case ALI_M1621: head->chipset = "ALi M1621"; break;
297 case ALI_M1631: head->chipset = "ALi M1631"; break;
298 case ALI_M1632: head->chipset = "ALi M1632"; break;
299 case ALI_M1641: head->chipset = "ALi M1641"; break;
300 case ALI_M1644: head->chipset = "ALi M1644"; break;
301 case ALI_M1647: head->chipset = "ALi M1647"; break;
302 case ALI_M1651: head->chipset = "ALi M1651"; break;
303
304 case SVWRKS_HE: head->chipset = "Serverworks HE";
305 break;
306 case SVWRKS_LE: head->chipset = "Serverworks LE";
307 break;
308 case SVWRKS_GENERIC: head->chipset = "Serverworks Generic";
309 break;
310
311 case HP_ZX1: head->chipset = "HP ZX1"; break;
312
313 default: head->chipset = "Unknown"; break;
314 }
315
316 head->cant_use_aperture = head->agp_info.cant_use_aperture;
317 head->page_mask = head->agp_info.page_mask;
318
319 DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n",
320 head->agp_info.version.major,
321 head->agp_info.version.minor,
322 head->chipset,
323 head->agp_info.aper_base,
324 head->agp_info.aper_size);
325 }
326 return head;
327}
328
329void DRM(agp_uninit)(void)
330{
331 DRM_AGP_PUT;
332 drm_agp = NULL;
333}
334
335agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type)
336{
337 if (!drm_agp->allocate_memory) return NULL;
338 return drm_agp->allocate_memory(pages, type);
339}
340
341int DRM(agp_free_memory)(agp_memory *handle)
342{
343 if (!handle || !drm_agp->free_memory) return 0;
344 drm_agp->free_memory(handle);
345 return 1;
346}
347
348int DRM(agp_bind_memory)(agp_memory *handle, off_t start)
349{
350 if (!handle || !drm_agp->bind_memory) return -EINVAL;
351 return drm_agp->bind_memory(handle, start);
352}
353
354int DRM(agp_unbind_memory)(agp_memory *handle)
355{
356 if (!handle || !drm_agp->unbind_memory) return -EINVAL;
357 return drm_agp->unbind_memory(handle);
358}
359
360#endif
361