1 /* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
2 * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
6 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
29 * Rickard E. (Rik) Faith <faith@valinux.com>
30 * Gareth Hughes <gareth@valinux.com>
35 #include "dev/drm/drmP.h"
38 #include <pci/agpreg.h>
39 #include <dev/pci/pcireg.h>
43 drm_device_find_capability(drm_device_t *dev, int cap)
46 /* Code taken from agp.c. IWBNI that was a public interface. */
51 * Check the CAP_LIST bit of the PCI status register first.
53 status = pci_read_config(dev->device, PCIR_STATUS, 2);
58 * Traverse the capabilities list.
60 for (ptr = pci_read_config(dev->device, AGP_CAPPTR, 1);
63 u_int32_t capid = pci_read_config(dev->device, ptr, 4);
64 next = AGP_CAPID_GET_NEXT_PTR(capid);
67 * If this capability entry ID is cap, then we are done.
69 if (AGP_CAPID_GET_CAP_ID(capid) == cap)
75 /* XXX: fill me in for non-FreeBSD */
81 drm_device_is_agp(drm_device_t *dev)
83 return (drm_device_find_capability(dev, PCIY_AGP));
87 drm_device_is_pcie(drm_device_t *dev)
89 return (drm_device_find_capability(dev, PCIY_EXPRESS));
92 int drm_agp_info(DRM_IOCTL_ARGS)
95 struct agp_info *kern;
98 if (!dev->agp || !dev->agp->acquired)
101 kern = &dev->agp->info;
102 agp_get_info(dev->agp->agpdev, kern);
103 info.agp_version_major = 1;
104 info.agp_version_minor = 0;
105 info.mode = kern->ai_mode;
106 info.aperture_base = kern->ai_aperture_base;
107 info.aperture_size = kern->ai_aperture_size;
108 info.memory_allowed = kern->ai_memory_allowed;
109 info.memory_used = kern->ai_memory_used;
110 info.id_vendor = kern->ai_devid & 0xffff;
111 info.id_device = kern->ai_devid >> 16;
113 *(drm_agp_info_t *) data = info;
117 int drm_agp_acquire(DRM_IOCTL_ARGS)
122 if (!dev->agp || dev->agp->acquired)
124 retcode = agp_acquire(dev->agp->agpdev);
127 dev->agp->acquired = 1;
131 int drm_agp_release(DRM_IOCTL_ARGS)
135 if (!dev->agp || !dev->agp->acquired)
137 agp_release(dev->agp->agpdev);
138 dev->agp->acquired = 0;
143 void drm_agp_do_release(void)
147 agpdev = DRM_AGP_FIND_DEVICE();
152 int drm_agp_enable(DRM_IOCTL_ARGS)
157 if (!dev->agp || !dev->agp->acquired)
160 mode = *(drm_agp_mode_t *) data;
162 dev->agp->mode = mode.mode;
163 agp_enable(dev->agp->agpdev, mode.mode);
164 dev->agp->base = dev->agp->info.ai_aperture_base;
165 dev->agp->enabled = 1;
169 int drm_agp_alloc(DRM_IOCTL_ARGS)
172 drm_agp_buffer_t request;
173 drm_agp_mem_t *entry;
177 struct agp_memory_info info;
179 if (!dev->agp || !dev->agp->acquired)
182 request = *(drm_agp_buffer_t *) data;
184 entry = malloc(sizeof(*entry), M_DRM, M_NOWAIT | M_ZERO);
188 pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
189 type = (u_int32_t) request.type;
191 if (!(handle = drm_agp_allocate_memory(pages, type))) {
196 entry->handle = handle;
198 entry->pages = pages;
200 entry->next = dev->agp->memory;
201 if (dev->agp->memory)
202 dev->agp->memory->prev = entry;
203 dev->agp->memory = entry;
205 agp_memory_info(dev->agp->agpdev, entry->handle, &info);
207 request.handle = (unsigned long) entry->handle;
208 request.physical = info.ami_physical;
210 *(drm_agp_buffer_t *) data = request;
215 static drm_agp_mem_t * drm_agp_lookup_entry(drm_device_t *dev, void *handle)
217 drm_agp_mem_t *entry;
219 for (entry = dev->agp->memory; entry; entry = entry->next) {
220 if (entry->handle == handle) return entry;
225 int drm_agp_unbind(DRM_IOCTL_ARGS)
228 drm_agp_binding_t request;
229 drm_agp_mem_t *entry;
232 if (!dev->agp || !dev->agp->acquired)
234 request = *(drm_agp_binding_t *) data;
235 if (!(entry = drm_agp_lookup_entry(dev, (void *)request.handle)))
237 if (!entry->bound) return EINVAL;
238 retcode = drm_agp_unbind_memory(entry->handle);
248 int drm_agp_bind(DRM_IOCTL_ARGS)
251 drm_agp_binding_t request;
252 drm_agp_mem_t *entry;
256 DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE);
257 if (!dev->agp || !dev->agp->acquired)
259 request = *(drm_agp_binding_t *) data;
260 if (!(entry = drm_agp_lookup_entry(dev, (void *)request.handle)))
262 if (entry->bound) return EINVAL;
263 page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
264 if ((retcode = drm_agp_bind_memory(entry->handle, page)))
266 entry->bound = dev->agp->base + (page << PAGE_SHIFT);
270 int drm_agp_free(DRM_IOCTL_ARGS)
273 drm_agp_buffer_t request;
274 drm_agp_mem_t *entry;
276 if (!dev->agp || !dev->agp->acquired)
278 request = *(drm_agp_buffer_t *) data;
279 if (!(entry = drm_agp_lookup_entry(dev, (void*)request.handle)))
282 drm_agp_unbind_memory(entry->handle);
285 entry->prev->next = entry->next;
287 dev->agp->memory = entry->next;
289 entry->next->prev = entry->prev;
290 drm_agp_free_memory(entry->handle);
295 drm_agp_head_t *drm_agp_init(void)
298 drm_agp_head_t *head = NULL;
299 int agp_available = 1;
301 agpdev = DRM_AGP_FIND_DEVICE();
305 DRM_DEBUG("agp_available = %d\n", agp_available);
308 head = malloc(sizeof(*head), M_DRM, M_NOWAIT | M_ZERO);
311 head->agpdev = agpdev;
312 agp_get_info(agpdev, &head->info);
314 DRM_INFO("AGP at 0x%08lx %dMB\n",
315 (long)head->info.ai_aperture_base,
316 (int)(head->info.ai_aperture_size >> 20));
321 void drm_agp_uninit(void)
323 /* FIXME: What goes here */
327 void *drm_agp_allocate_memory(size_t pages, u32 type)
331 agpdev = DRM_AGP_FIND_DEVICE();
335 return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT);
338 int drm_agp_free_memory(void *handle)
342 agpdev = DRM_AGP_FIND_DEVICE();
343 if (!agpdev || !handle)
346 agp_free_memory(agpdev, handle);
350 int drm_agp_bind_memory(void *handle, off_t start)
354 agpdev = DRM_AGP_FIND_DEVICE();
355 if (!agpdev || !handle)
358 return agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
361 int drm_agp_unbind_memory(void *handle)
365 agpdev = DRM_AGP_FIND_DEVICE();
366 if (!agpdev || !handle)
369 return agp_unbind_memory(agpdev, handle);