1 1.13 riastrad /* $NetBSD: drm_agpsupport.c,v 1.13 2022/07/19 22:24:33 riastradh Exp $ */ 2 1.7 riastrad 3 1.12 riastrad /* 4 1.1 riastrad * \file drm_agpsupport.c 5 1.1 riastrad * DRM support for AGP/GART backend 6 1.1 riastrad * 7 1.1 riastrad * \author Rickard E. (Rik) Faith <faith (at) valinux.com> 8 1.1 riastrad * \author Gareth Hughes <gareth (at) valinux.com> 9 1.1 riastrad */ 10 1.1 riastrad 11 1.1 riastrad /* 12 1.1 riastrad * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13 1.1 riastrad * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 1.1 riastrad * All Rights Reserved. 15 1.1 riastrad * 16 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 17 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 18 1.1 riastrad * to deal in the Software without restriction, including without limitation 19 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 21 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 22 1.1 riastrad * 23 1.1 riastrad * The above copyright notice and this permission notice (including the next 24 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 25 1.1 riastrad * Software. 26 1.1 riastrad * 27 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 1.1 riastrad * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 34 1.1 riastrad */ 35 1.1 riastrad 36 1.7 riastrad #include <sys/cdefs.h> 37 1.13 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_agpsupport.c,v 1.13 2022/07/19 22:24:33 riastradh Exp $"); 38 1.7 riastrad 39 1.1 riastrad #include <linux/module.h> 40 1.12 riastrad #include <linux/pci.h> 41 1.1 riastrad #include <linux/slab.h> 42 1.1 riastrad 43 1.1 riastrad #include <asm/agp.h> 44 1.1 riastrad 45 1.12 riastrad #include <drm/drm_agpsupport.h> 46 1.12 riastrad #include <drm/drm_device.h> 47 1.12 riastrad #include <drm/drm_drv.h> 48 1.12 riastrad #include <drm/drm_file.h> 49 1.12 riastrad #include <drm/drm_print.h> 50 1.12 riastrad 51 1.12 riastrad #include "drm_legacy.h" 52 1.12 riastrad 53 1.1 riastrad /** 54 1.1 riastrad * Get AGP information. 55 1.1 riastrad * 56 1.1 riastrad * \param inode device inode. 57 1.1 riastrad * \param file_priv DRM file private. 58 1.1 riastrad * \param cmd command. 59 1.1 riastrad * \param arg pointer to a (output) drm_agp_info structure. 60 1.1 riastrad * \return zero on success or a negative number on failure. 61 1.1 riastrad * 62 1.1 riastrad * Verifies the AGP device has been initialized and acquired and fills in the 63 1.1 riastrad * drm_agp_info structure with the information in drm_agp_head::agp_info. 64 1.1 riastrad */ 65 1.10 riastrad static int drm_agp_info_hook(struct drm_device *dev, struct drm_agp_info *info) 66 1.1 riastrad { 67 1.3 riastrad struct agp_kern_info *kern; 68 1.1 riastrad 69 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 70 1.1 riastrad return -EINVAL; 71 1.1 riastrad 72 1.1 riastrad kern = &dev->agp->agp_info; 73 1.2 riastrad #if __NetBSD__ 74 1.2 riastrad info->agp_version_major = 1; 75 1.2 riastrad info->agp_version_minor = 0; 76 1.4 riastrad info->mode = kern->aki_info.ai_mode; 77 1.4 riastrad info->aperture_base = kern->aki_info.ai_aperture_base; 78 1.4 riastrad info->aperture_size = kern->aki_info.ai_aperture_size; 79 1.4 riastrad info->memory_allowed = kern->aki_info.ai_memory_allowed; 80 1.4 riastrad info->memory_used = kern->aki_info.ai_memory_used; 81 1.4 riastrad info->id_vendor = PCI_VENDOR(kern->aki_info.ai_devid); 82 1.4 riastrad info->id_device = PCI_PRODUCT(kern->aki_info.ai_devid); 83 1.2 riastrad #else 84 1.1 riastrad info->agp_version_major = kern->version.major; 85 1.1 riastrad info->agp_version_minor = kern->version.minor; 86 1.1 riastrad info->mode = kern->mode; 87 1.1 riastrad info->aperture_base = kern->aper_base; 88 1.1 riastrad info->aperture_size = kern->aper_size * 1024 * 1024; 89 1.1 riastrad info->memory_allowed = kern->max_memory << PAGE_SHIFT; 90 1.1 riastrad info->memory_used = kern->current_memory << PAGE_SHIFT; 91 1.1 riastrad info->id_vendor = kern->device->vendor; 92 1.1 riastrad info->id_device = kern->device->device; 93 1.2 riastrad #endif 94 1.1 riastrad 95 1.1 riastrad return 0; 96 1.1 riastrad } 97 1.1 riastrad EXPORT_SYMBOL(drm_agp_info); 98 1.1 riastrad 99 1.10 riastrad static int drm_agp_info_ioctl_hook(struct drm_device *dev, void *data, 100 1.1 riastrad struct drm_file *file_priv) 101 1.1 riastrad { 102 1.1 riastrad struct drm_agp_info *info = data; 103 1.1 riastrad int err; 104 1.1 riastrad 105 1.1 riastrad err = drm_agp_info(dev, info); 106 1.1 riastrad if (err) 107 1.1 riastrad return err; 108 1.1 riastrad 109 1.1 riastrad return 0; 110 1.1 riastrad } 111 1.1 riastrad 112 1.1 riastrad /** 113 1.1 riastrad * Acquire the AGP device. 114 1.1 riastrad * 115 1.1 riastrad * \param dev DRM device that is to acquire AGP. 116 1.1 riastrad * \return zero on success or a negative number on failure. 117 1.1 riastrad * 118 1.1 riastrad * Verifies the AGP device hasn't been acquired before and calls 119 1.1 riastrad * \c agp_backend_acquire. 120 1.1 riastrad */ 121 1.10 riastrad static int drm_agp_acquire_hook(struct drm_device * dev) 122 1.1 riastrad { 123 1.1 riastrad if (!dev->agp) 124 1.1 riastrad return -ENODEV; 125 1.1 riastrad if (dev->agp->acquired) 126 1.1 riastrad return -EBUSY; 127 1.12 riastrad dev->agp->bridge = agp_backend_acquire(dev->pdev); 128 1.12 riastrad if (!dev->agp->bridge) 129 1.1 riastrad return -ENODEV; 130 1.1 riastrad dev->agp->acquired = 1; 131 1.1 riastrad return 0; 132 1.1 riastrad } 133 1.1 riastrad EXPORT_SYMBOL(drm_agp_acquire); 134 1.1 riastrad 135 1.1 riastrad /** 136 1.1 riastrad * Acquire the AGP device (ioctl). 137 1.1 riastrad * 138 1.1 riastrad * \param inode device inode. 139 1.1 riastrad * \param file_priv DRM file private. 140 1.1 riastrad * \param cmd command. 141 1.1 riastrad * \param arg user argument. 142 1.1 riastrad * \return zero on success or a negative number on failure. 143 1.1 riastrad * 144 1.1 riastrad * Verifies the AGP device hasn't been acquired before and calls 145 1.1 riastrad * \c agp_backend_acquire. 146 1.1 riastrad */ 147 1.10 riastrad static int drm_agp_acquire_ioctl_hook(struct drm_device *dev, void *data, 148 1.1 riastrad struct drm_file *file_priv) 149 1.1 riastrad { 150 1.1 riastrad return drm_agp_acquire((struct drm_device *) file_priv->minor->dev); 151 1.1 riastrad } 152 1.1 riastrad 153 1.1 riastrad /** 154 1.1 riastrad * Release the AGP device. 155 1.1 riastrad * 156 1.1 riastrad * \param dev DRM device that is to release AGP. 157 1.1 riastrad * \return zero on success or a negative number on failure. 158 1.1 riastrad * 159 1.1 riastrad * Verifies the AGP device has been acquired and calls \c agp_backend_release. 160 1.1 riastrad */ 161 1.10 riastrad static int drm_agp_release_hook(struct drm_device * dev) 162 1.1 riastrad { 163 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 164 1.1 riastrad return -EINVAL; 165 1.1 riastrad agp_backend_release(dev->agp->bridge); 166 1.1 riastrad dev->agp->acquired = 0; 167 1.1 riastrad return 0; 168 1.1 riastrad } 169 1.1 riastrad EXPORT_SYMBOL(drm_agp_release); 170 1.1 riastrad 171 1.10 riastrad static int drm_agp_release_ioctl_hook(struct drm_device *dev, void *data, 172 1.1 riastrad struct drm_file *file_priv) 173 1.1 riastrad { 174 1.1 riastrad return drm_agp_release(dev); 175 1.1 riastrad } 176 1.1 riastrad 177 1.1 riastrad /** 178 1.1 riastrad * Enable the AGP bus. 179 1.1 riastrad * 180 1.1 riastrad * \param dev DRM device that has previously acquired AGP. 181 1.1 riastrad * \param mode Requested AGP mode. 182 1.1 riastrad * \return zero on success or a negative number on failure. 183 1.1 riastrad * 184 1.1 riastrad * Verifies the AGP device has been acquired but not enabled, and calls 185 1.1 riastrad * \c agp_enable. 186 1.1 riastrad */ 187 1.10 riastrad static int drm_agp_enable_hook(struct drm_device * dev, struct drm_agp_mode mode) 188 1.1 riastrad { 189 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 190 1.1 riastrad return -EINVAL; 191 1.1 riastrad 192 1.1 riastrad dev->agp->mode = mode.mode; 193 1.1 riastrad agp_enable(dev->agp->bridge, mode.mode); 194 1.1 riastrad dev->agp->enabled = 1; 195 1.1 riastrad return 0; 196 1.1 riastrad } 197 1.1 riastrad EXPORT_SYMBOL(drm_agp_enable); 198 1.1 riastrad 199 1.10 riastrad static int drm_agp_enable_ioctl_hook(struct drm_device *dev, void *data, 200 1.1 riastrad struct drm_file *file_priv) 201 1.1 riastrad { 202 1.1 riastrad struct drm_agp_mode *mode = data; 203 1.1 riastrad 204 1.1 riastrad return drm_agp_enable(dev, *mode); 205 1.1 riastrad } 206 1.1 riastrad 207 1.1 riastrad /** 208 1.1 riastrad * Allocate AGP memory. 209 1.1 riastrad * 210 1.1 riastrad * \param inode device inode. 211 1.1 riastrad * \param file_priv file private pointer. 212 1.1 riastrad * \param cmd command. 213 1.1 riastrad * \param arg pointer to a drm_agp_buffer structure. 214 1.1 riastrad * \return zero on success or a negative number on failure. 215 1.1 riastrad * 216 1.1 riastrad * Verifies the AGP device is present and has been acquired, allocates the 217 1.1 riastrad * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it. 218 1.1 riastrad */ 219 1.10 riastrad static int drm_agp_alloc_hook(struct drm_device *dev, struct drm_agp_buffer *request) 220 1.1 riastrad { 221 1.1 riastrad struct drm_agp_mem *entry; 222 1.3 riastrad struct agp_memory *memory; 223 1.1 riastrad unsigned long pages; 224 1.1 riastrad u32 type; 225 1.1 riastrad 226 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 227 1.1 riastrad return -EINVAL; 228 1.12 riastrad entry = kzalloc(sizeof(*entry), GFP_KERNEL); 229 1.12 riastrad if (!entry) 230 1.1 riastrad return -ENOMEM; 231 1.1 riastrad 232 1.12 riastrad pages = DIV_ROUND_UP(request->size, AGP_PAGE_SIZE); 233 1.1 riastrad type = (u32) request->type; 234 1.12 riastrad memory = agp_allocate_memory(dev->agp->bridge, pages, type); 235 1.12 riastrad if (!memory) { 236 1.1 riastrad kfree(entry); 237 1.1 riastrad return -ENOMEM; 238 1.1 riastrad } 239 1.1 riastrad 240 1.2 riastrad #ifdef __NetBSD__ 241 1.2 riastrad /* I presume the `+ 1' is there to avoid an id of 0 or something. */ 242 1.2 riastrad entry->handle = (unsigned long)memory->am_id + 1; 243 1.2 riastrad #else 244 1.1 riastrad entry->handle = (unsigned long)memory->key + 1; 245 1.2 riastrad #endif 246 1.1 riastrad entry->memory = memory; 247 1.1 riastrad entry->bound = 0; 248 1.1 riastrad entry->pages = pages; 249 1.1 riastrad list_add(&entry->head, &dev->agp->memory); 250 1.1 riastrad 251 1.1 riastrad request->handle = entry->handle; 252 1.2 riastrad #ifdef __NetBSD__ 253 1.2 riastrad { 254 1.2 riastrad struct agp_memory_info info; 255 1.2 riastrad agp_memory_info(dev->agp->bridge, memory, &info); 256 1.2 riastrad request->physical = info.ami_physical; 257 1.2 riastrad } 258 1.2 riastrad #else 259 1.1 riastrad request->physical = memory->physical; 260 1.2 riastrad #endif 261 1.1 riastrad 262 1.1 riastrad return 0; 263 1.1 riastrad } 264 1.1 riastrad EXPORT_SYMBOL(drm_agp_alloc); 265 1.1 riastrad 266 1.1 riastrad 267 1.10 riastrad static int drm_agp_alloc_ioctl_hook(struct drm_device *dev, void *data, 268 1.1 riastrad struct drm_file *file_priv) 269 1.1 riastrad { 270 1.1 riastrad struct drm_agp_buffer *request = data; 271 1.1 riastrad 272 1.1 riastrad return drm_agp_alloc(dev, request); 273 1.1 riastrad } 274 1.1 riastrad 275 1.1 riastrad /** 276 1.1 riastrad * Search for the AGP memory entry associated with a handle. 277 1.1 riastrad * 278 1.1 riastrad * \param dev DRM device structure. 279 1.1 riastrad * \param handle AGP memory handle. 280 1.1 riastrad * \return pointer to the drm_agp_mem structure associated with \p handle. 281 1.1 riastrad * 282 1.1 riastrad * Walks through drm_agp_head::memory until finding a matching handle. 283 1.1 riastrad */ 284 1.12 riastrad static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device *dev, 285 1.12 riastrad unsigned long handle) 286 1.1 riastrad { 287 1.1 riastrad struct drm_agp_mem *entry; 288 1.1 riastrad 289 1.1 riastrad list_for_each_entry(entry, &dev->agp->memory, head) { 290 1.1 riastrad if (entry->handle == handle) 291 1.1 riastrad return entry; 292 1.1 riastrad } 293 1.1 riastrad return NULL; 294 1.1 riastrad } 295 1.1 riastrad 296 1.1 riastrad /** 297 1.1 riastrad * Unbind AGP memory from the GATT (ioctl). 298 1.1 riastrad * 299 1.1 riastrad * \param inode device inode. 300 1.1 riastrad * \param file_priv DRM file private. 301 1.1 riastrad * \param cmd command. 302 1.1 riastrad * \param arg pointer to a drm_agp_binding structure. 303 1.1 riastrad * \return zero on success or a negative number on failure. 304 1.1 riastrad * 305 1.1 riastrad * Verifies the AGP device is present and acquired, looks-up the AGP memory 306 1.1 riastrad * entry and passes it to the unbind_agp() function. 307 1.1 riastrad */ 308 1.10 riastrad static int drm_agp_unbind_hook(struct drm_device *dev, struct drm_agp_binding *request) 309 1.1 riastrad { 310 1.1 riastrad struct drm_agp_mem *entry; 311 1.1 riastrad int ret; 312 1.1 riastrad 313 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 314 1.1 riastrad return -EINVAL; 315 1.12 riastrad entry = drm_agp_lookup_entry(dev, request->handle); 316 1.12 riastrad if (!entry || !entry->bound) 317 1.1 riastrad return -EINVAL; 318 1.2 riastrad #ifdef __NetBSD__ 319 1.2 riastrad ret = drm_unbind_agp(dev->agp->bridge, entry->memory); 320 1.2 riastrad #else 321 1.1 riastrad ret = drm_unbind_agp(entry->memory); 322 1.2 riastrad #endif 323 1.1 riastrad if (ret == 0) 324 1.1 riastrad entry->bound = 0; 325 1.1 riastrad return ret; 326 1.1 riastrad } 327 1.1 riastrad EXPORT_SYMBOL(drm_agp_unbind); 328 1.1 riastrad 329 1.1 riastrad 330 1.10 riastrad static int drm_agp_unbind_ioctl_hook(struct drm_device *dev, void *data, 331 1.1 riastrad struct drm_file *file_priv) 332 1.1 riastrad { 333 1.1 riastrad struct drm_agp_binding *request = data; 334 1.1 riastrad 335 1.1 riastrad return drm_agp_unbind(dev, request); 336 1.1 riastrad } 337 1.1 riastrad 338 1.1 riastrad /** 339 1.1 riastrad * Bind AGP memory into the GATT (ioctl) 340 1.1 riastrad * 341 1.1 riastrad * \param inode device inode. 342 1.1 riastrad * \param file_priv DRM file private. 343 1.1 riastrad * \param cmd command. 344 1.1 riastrad * \param arg pointer to a drm_agp_binding structure. 345 1.1 riastrad * \return zero on success or a negative number on failure. 346 1.1 riastrad * 347 1.1 riastrad * Verifies the AGP device is present and has been acquired and that no memory 348 1.1 riastrad * is currently bound into the GATT. Looks-up the AGP memory entry and passes 349 1.1 riastrad * it to bind_agp() function. 350 1.1 riastrad */ 351 1.10 riastrad static int drm_agp_bind_hook(struct drm_device *dev, struct drm_agp_binding *request) 352 1.1 riastrad { 353 1.1 riastrad struct drm_agp_mem *entry; 354 1.1 riastrad int retcode; 355 1.1 riastrad int page; 356 1.1 riastrad 357 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 358 1.1 riastrad return -EINVAL; 359 1.12 riastrad entry = drm_agp_lookup_entry(dev, request->handle); 360 1.12 riastrad if (!entry || entry->bound) 361 1.1 riastrad return -EINVAL; 362 1.12 riastrad page = DIV_ROUND_UP(request->offset, AGP_PAGE_SIZE); 363 1.2 riastrad #ifdef __NetBSD__ 364 1.2 riastrad if ((retcode = drm_bind_agp(dev->agp->bridge, entry->memory, page))) 365 1.2 riastrad return retcode; 366 1.2 riastrad #else 367 1.12 riastrad retcode = drm_bind_agp(entry->memory, page); 368 1.12 riastrad if (retcode) 369 1.1 riastrad return retcode; 370 1.2 riastrad #endif 371 1.1 riastrad entry->bound = dev->agp->base + (page << PAGE_SHIFT); 372 1.1 riastrad DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", 373 1.1 riastrad dev->agp->base, entry->bound); 374 1.1 riastrad return 0; 375 1.1 riastrad } 376 1.1 riastrad EXPORT_SYMBOL(drm_agp_bind); 377 1.1 riastrad 378 1.1 riastrad 379 1.10 riastrad static int drm_agp_bind_ioctl_hook(struct drm_device *dev, void *data, 380 1.1 riastrad struct drm_file *file_priv) 381 1.1 riastrad { 382 1.1 riastrad struct drm_agp_binding *request = data; 383 1.1 riastrad 384 1.1 riastrad return drm_agp_bind(dev, request); 385 1.1 riastrad } 386 1.1 riastrad 387 1.1 riastrad /** 388 1.1 riastrad * Free AGP memory (ioctl). 389 1.1 riastrad * 390 1.1 riastrad * \param inode device inode. 391 1.1 riastrad * \param file_priv DRM file private. 392 1.1 riastrad * \param cmd command. 393 1.1 riastrad * \param arg pointer to a drm_agp_buffer structure. 394 1.1 riastrad * \return zero on success or a negative number on failure. 395 1.1 riastrad * 396 1.1 riastrad * Verifies the AGP device is present and has been acquired and looks up the 397 1.12 riastrad * AGP memory entry. If the memory is currently bound, unbind it via 398 1.1 riastrad * unbind_agp(). Frees it via free_agp() as well as the entry itself 399 1.1 riastrad * and unlinks from the doubly linked list it's inserted in. 400 1.1 riastrad */ 401 1.10 riastrad static int drm_agp_free_hook(struct drm_device *dev, struct drm_agp_buffer *request) 402 1.1 riastrad { 403 1.1 riastrad struct drm_agp_mem *entry; 404 1.1 riastrad 405 1.1 riastrad if (!dev->agp || !dev->agp->acquired) 406 1.1 riastrad return -EINVAL; 407 1.12 riastrad entry = drm_agp_lookup_entry(dev, request->handle); 408 1.12 riastrad if (!entry) 409 1.1 riastrad return -EINVAL; 410 1.1 riastrad if (entry->bound) 411 1.2 riastrad #ifdef __NetBSD__ 412 1.2 riastrad drm_unbind_agp(dev->agp->bridge, entry->memory); 413 1.2 riastrad #else 414 1.1 riastrad drm_unbind_agp(entry->memory); 415 1.2 riastrad #endif 416 1.1 riastrad 417 1.1 riastrad list_del(&entry->head); 418 1.1 riastrad 419 1.2 riastrad #ifdef __NetBSD__ 420 1.2 riastrad drm_free_agp(dev->agp->bridge, entry->memory, entry->pages); 421 1.2 riastrad #else 422 1.1 riastrad drm_free_agp(entry->memory, entry->pages); 423 1.2 riastrad #endif 424 1.1 riastrad kfree(entry); 425 1.1 riastrad return 0; 426 1.1 riastrad } 427 1.1 riastrad EXPORT_SYMBOL(drm_agp_free); 428 1.1 riastrad 429 1.1 riastrad 430 1.10 riastrad static int drm_agp_free_ioctl_hook(struct drm_device *dev, void *data, 431 1.1 riastrad struct drm_file *file_priv) 432 1.1 riastrad { 433 1.1 riastrad struct drm_agp_buffer *request = data; 434 1.1 riastrad 435 1.1 riastrad return drm_agp_free(dev, request); 436 1.1 riastrad } 437 1.1 riastrad 438 1.1 riastrad /** 439 1.1 riastrad * Initialize the AGP resources. 440 1.1 riastrad * 441 1.1 riastrad * \return pointer to a drm_agp_head structure. 442 1.1 riastrad * 443 1.1 riastrad * Gets the drm_agp_t structure which is made available by the agpgart module 444 1.1 riastrad * via the inter_module_* functions. Creates and initializes a drm_agp_head 445 1.1 riastrad * structure. 446 1.3 riastrad * 447 1.3 riastrad * Note that final cleanup of the kmalloced structure is directly done in 448 1.3 riastrad * drm_pci_agp_destroy. 449 1.1 riastrad */ 450 1.10 riastrad static struct drm_agp_head *drm_agp_init_hook(struct drm_device *dev) 451 1.1 riastrad { 452 1.1 riastrad struct drm_agp_head *head = NULL; 453 1.1 riastrad 454 1.12 riastrad head = kzalloc(sizeof(*head), GFP_KERNEL); 455 1.12 riastrad if (!head) 456 1.1 riastrad return NULL; 457 1.1 riastrad head->bridge = agp_find_bridge(dev->pdev); 458 1.1 riastrad if (!head->bridge) { 459 1.12 riastrad head->bridge = agp_backend_acquire(dev->pdev); 460 1.12 riastrad if (!head->bridge) { 461 1.1 riastrad kfree(head); 462 1.1 riastrad return NULL; 463 1.1 riastrad } 464 1.1 riastrad agp_copy_info(head->bridge, &head->agp_info); 465 1.1 riastrad agp_backend_release(head->bridge); 466 1.1 riastrad } else { 467 1.1 riastrad agp_copy_info(head->bridge, &head->agp_info); 468 1.1 riastrad } 469 1.2 riastrad #ifndef __NetBSD__ 470 1.2 riastrad /* Why would anything even attach in this case? */ 471 1.1 riastrad if (head->agp_info.chipset == NOT_SUPPORTED) { 472 1.1 riastrad kfree(head); 473 1.1 riastrad return NULL; 474 1.1 riastrad } 475 1.2 riastrad #endif 476 1.1 riastrad INIT_LIST_HEAD(&head->memory); 477 1.2 riastrad #ifdef __NetBSD__ 478 1.4 riastrad head->cant_use_aperture = false; /* XXX */ 479 1.4 riastrad head->page_mask = ~0UL; 480 1.4 riastrad head->base = head->agp_info.aki_info.ai_aperture_base; 481 1.2 riastrad #else 482 1.1 riastrad head->cant_use_aperture = head->agp_info.cant_use_aperture; 483 1.1 riastrad head->page_mask = head->agp_info.page_mask; 484 1.1 riastrad head->base = head->agp_info.aper_base; 485 1.2 riastrad #endif 486 1.1 riastrad return head; 487 1.1 riastrad } 488 1.12 riastrad /* Only exported for i810.ko */ 489 1.12 riastrad EXPORT_SYMBOL(drm_agp_init); 490 1.1 riastrad 491 1.1 riastrad /** 492 1.12 riastrad * drm_legacy_agp_clear - Clear AGP resource list 493 1.3 riastrad * @dev: DRM device 494 1.3 riastrad * 495 1.3 riastrad * Iterate over all AGP resources and remove them. But keep the AGP head 496 1.3 riastrad * intact so it can still be used. It is safe to call this if AGP is disabled or 497 1.3 riastrad * was already removed. 498 1.3 riastrad * 499 1.12 riastrad * Cleanup is only done for drivers who have DRIVER_LEGACY set. 500 1.3 riastrad */ 501 1.10 riastrad static void drm_agp_clear_hook(struct drm_device *dev) 502 1.3 riastrad { 503 1.3 riastrad struct drm_agp_mem *entry, *tempe; 504 1.3 riastrad 505 1.3 riastrad if (!dev->agp) 506 1.3 riastrad return; 507 1.12 riastrad if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 508 1.3 riastrad return; 509 1.3 riastrad 510 1.3 riastrad list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { 511 1.10 riastrad #ifdef __NetBSD__ 512 1.3 riastrad if (entry->bound) 513 1.4 riastrad drm_unbind_agp(dev->agp->bridge, entry->memory); 514 1.4 riastrad drm_free_agp(dev->agp->bridge, entry->memory, entry->pages); 515 1.4 riastrad #else 516 1.10 riastrad if (entry->bound) 517 1.10 riastrad drm_unbind_agp(entry->memory); 518 1.3 riastrad drm_free_agp(entry->memory, entry->pages); 519 1.4 riastrad #endif 520 1.3 riastrad kfree(entry); 521 1.3 riastrad } 522 1.3 riastrad INIT_LIST_HEAD(&dev->agp->memory); 523 1.3 riastrad 524 1.3 riastrad if (dev->agp->acquired) 525 1.3 riastrad drm_agp_release(dev); 526 1.3 riastrad 527 1.3 riastrad dev->agp->acquired = 0; 528 1.3 riastrad dev->agp->enabled = 0; 529 1.3 riastrad } 530 1.13 riastrad 531 1.10 riastrad #ifdef __NetBSD__ 532 1.10 riastrad 533 1.10 riastrad static void 534 1.10 riastrad drm_agp_flush_hook(void) 535 1.10 riastrad { 536 1.10 riastrad 537 1.10 riastrad agp_flush_cache(); 538 1.10 riastrad } 539 1.10 riastrad 540 1.10 riastrad static const struct drm_agp_hooks agp_hooks = { 541 1.10 riastrad .agph_info = drm_agp_info_hook, 542 1.10 riastrad .agph_info_ioctl = drm_agp_info_ioctl_hook, 543 1.10 riastrad .agph_acquire = drm_agp_acquire_hook, 544 1.10 riastrad .agph_acquire_ioctl = drm_agp_acquire_ioctl_hook, 545 1.10 riastrad .agph_release = drm_agp_release_hook, 546 1.10 riastrad .agph_release_ioctl = drm_agp_release_ioctl_hook, 547 1.10 riastrad .agph_enable = drm_agp_enable_hook, 548 1.10 riastrad .agph_enable_ioctl = drm_agp_enable_ioctl_hook, 549 1.10 riastrad .agph_alloc = drm_agp_alloc_hook, 550 1.10 riastrad .agph_alloc_ioctl = drm_agp_alloc_ioctl_hook, 551 1.10 riastrad .agph_unbind = drm_agp_unbind_hook, 552 1.10 riastrad .agph_unbind_ioctl = drm_agp_unbind_ioctl_hook, 553 1.10 riastrad .agph_bind = drm_agp_bind_hook, 554 1.10 riastrad .agph_bind_ioctl = drm_agp_bind_ioctl_hook, 555 1.10 riastrad .agph_free = drm_agp_free_hook, 556 1.10 riastrad .agph_free_ioctl = drm_agp_free_ioctl_hook, 557 1.10 riastrad .agph_init = drm_agp_init_hook, 558 1.10 riastrad .agph_clear = drm_agp_clear_hook, 559 1.10 riastrad .agph_flush = drm_agp_flush_hook, 560 1.10 riastrad }; 561 1.10 riastrad 562 1.10 riastrad #include <sys/module.h> 563 1.10 riastrad #include <sys/once.h> 564 1.10 riastrad 565 1.10 riastrad MODULE(MODULE_CLASS_MISC, drmkms_agp, "drmkms"); /* XXX agp */ 566 1.10 riastrad 567 1.10 riastrad static int 568 1.10 riastrad drmkms_agp_init(void) 569 1.10 riastrad { 570 1.10 riastrad 571 1.10 riastrad return drm_agp_register(&agp_hooks); 572 1.10 riastrad } 573 1.10 riastrad 574 1.10 riastrad int 575 1.10 riastrad drmkms_agp_guarantee_initialized(void) 576 1.10 riastrad { 577 1.10 riastrad #ifdef _MODULE 578 1.10 riastrad return 0; 579 1.10 riastrad #else 580 1.10 riastrad static ONCE_DECL(drmkms_agp_init_once); 581 1.10 riastrad 582 1.10 riastrad return RUN_ONCE(&drmkms_agp_init_once, &drmkms_agp_init); 583 1.10 riastrad #endif 584 1.10 riastrad } 585 1.10 riastrad 586 1.10 riastrad static int 587 1.10 riastrad drmkms_agp_fini(void) 588 1.10 riastrad { 589 1.10 riastrad 590 1.10 riastrad return drm_agp_deregister(&agp_hooks); 591 1.10 riastrad } 592 1.10 riastrad 593 1.10 riastrad static int 594 1.10 riastrad drmkms_agp_modcmd(modcmd_t cmd, void *arg __unused) 595 1.10 riastrad { 596 1.10 riastrad int error; 597 1.10 riastrad 598 1.10 riastrad switch (cmd) { 599 1.10 riastrad case MODULE_CMD_INIT: 600 1.10 riastrad #ifdef _MODULE 601 1.10 riastrad error = drmkms_agp_init(); 602 1.10 riastrad #else 603 1.10 riastrad error = drmkms_agp_guarantee_initialized(); 604 1.10 riastrad #endif 605 1.10 riastrad if (error) 606 1.10 riastrad return error; 607 1.10 riastrad return 0; 608 1.13 riastrad case MODULE_CMD_AUTOUNLOAD: 609 1.13 riastrad return EBUSY; 610 1.10 riastrad case MODULE_CMD_FINI: 611 1.10 riastrad error = drmkms_agp_fini(); 612 1.10 riastrad if (error) 613 1.10 riastrad return error; 614 1.10 riastrad return 0; 615 1.10 riastrad default: 616 1.10 riastrad return ENOTTY; 617 1.10 riastrad } 618 1.10 riastrad } 619 1.10 riastrad 620 1.10 riastrad #endif /* __NetBSD__ */ 621