1*c0e09200SDave Airlie /** 2*c0e09200SDave Airlie * \file drm_agpsupport.c 3*c0e09200SDave Airlie * DRM support for AGP/GART backend 4*c0e09200SDave Airlie * 5*c0e09200SDave Airlie * \author Rickard E. (Rik) Faith <faith@valinux.com> 6*c0e09200SDave Airlie * \author Gareth Hughes <gareth@valinux.com> 7*c0e09200SDave Airlie */ 8*c0e09200SDave Airlie 9*c0e09200SDave Airlie /* 10*c0e09200SDave Airlie * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 11*c0e09200SDave Airlie * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12*c0e09200SDave Airlie * All Rights Reserved. 13*c0e09200SDave Airlie * 14*c0e09200SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 15*c0e09200SDave Airlie * copy of this software and associated documentation files (the "Software"), 16*c0e09200SDave Airlie * to deal in the Software without restriction, including without limitation 17*c0e09200SDave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18*c0e09200SDave Airlie * and/or sell copies of the Software, and to permit persons to whom the 19*c0e09200SDave Airlie * Software is furnished to do so, subject to the following conditions: 20*c0e09200SDave Airlie * 21*c0e09200SDave Airlie * The above copyright notice and this permission notice (including the next 22*c0e09200SDave Airlie * paragraph) shall be included in all copies or substantial portions of the 23*c0e09200SDave Airlie * Software. 24*c0e09200SDave Airlie * 25*c0e09200SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26*c0e09200SDave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27*c0e09200SDave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28*c0e09200SDave Airlie * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29*c0e09200SDave Airlie * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30*c0e09200SDave Airlie * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 31*c0e09200SDave Airlie * OTHER DEALINGS IN THE SOFTWARE. 32*c0e09200SDave Airlie */ 33*c0e09200SDave Airlie 34*c0e09200SDave Airlie #include "drmP.h" 35*c0e09200SDave Airlie #include <linux/module.h> 36*c0e09200SDave Airlie 37*c0e09200SDave Airlie #if __OS_HAS_AGP 38*c0e09200SDave Airlie 39*c0e09200SDave Airlie /** 40*c0e09200SDave Airlie * Get AGP information. 41*c0e09200SDave Airlie * 42*c0e09200SDave Airlie * \param inode device inode. 43*c0e09200SDave Airlie * \param file_priv DRM file private. 44*c0e09200SDave Airlie * \param cmd command. 45*c0e09200SDave Airlie * \param arg pointer to a (output) drm_agp_info structure. 46*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 47*c0e09200SDave Airlie * 48*c0e09200SDave Airlie * Verifies the AGP device has been initialized and acquired and fills in the 49*c0e09200SDave Airlie * drm_agp_info structure with the information in drm_agp_head::agp_info. 50*c0e09200SDave Airlie */ 51*c0e09200SDave Airlie int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info) 52*c0e09200SDave Airlie { 53*c0e09200SDave Airlie DRM_AGP_KERN *kern; 54*c0e09200SDave Airlie 55*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 56*c0e09200SDave Airlie return -EINVAL; 57*c0e09200SDave Airlie 58*c0e09200SDave Airlie kern = &dev->agp->agp_info; 59*c0e09200SDave Airlie info->agp_version_major = kern->version.major; 60*c0e09200SDave Airlie info->agp_version_minor = kern->version.minor; 61*c0e09200SDave Airlie info->mode = kern->mode; 62*c0e09200SDave Airlie info->aperture_base = kern->aper_base; 63*c0e09200SDave Airlie info->aperture_size = kern->aper_size * 1024 * 1024; 64*c0e09200SDave Airlie info->memory_allowed = kern->max_memory << PAGE_SHIFT; 65*c0e09200SDave Airlie info->memory_used = kern->current_memory << PAGE_SHIFT; 66*c0e09200SDave Airlie info->id_vendor = kern->device->vendor; 67*c0e09200SDave Airlie info->id_device = kern->device->device; 68*c0e09200SDave Airlie 69*c0e09200SDave Airlie return 0; 70*c0e09200SDave Airlie } 71*c0e09200SDave Airlie 72*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_info); 73*c0e09200SDave Airlie 74*c0e09200SDave Airlie int drm_agp_info_ioctl(struct drm_device *dev, void *data, 75*c0e09200SDave Airlie struct drm_file *file_priv) 76*c0e09200SDave Airlie { 77*c0e09200SDave Airlie struct drm_agp_info *info = data; 78*c0e09200SDave Airlie int err; 79*c0e09200SDave Airlie 80*c0e09200SDave Airlie err = drm_agp_info(dev, info); 81*c0e09200SDave Airlie if (err) 82*c0e09200SDave Airlie return err; 83*c0e09200SDave Airlie 84*c0e09200SDave Airlie return 0; 85*c0e09200SDave Airlie } 86*c0e09200SDave Airlie 87*c0e09200SDave Airlie /** 88*c0e09200SDave Airlie * Acquire the AGP device. 89*c0e09200SDave Airlie * 90*c0e09200SDave Airlie * \param dev DRM device that is to acquire AGP. 91*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 92*c0e09200SDave Airlie * 93*c0e09200SDave Airlie * Verifies the AGP device hasn't been acquired before and calls 94*c0e09200SDave Airlie * \c agp_backend_acquire. 95*c0e09200SDave Airlie */ 96*c0e09200SDave Airlie int drm_agp_acquire(struct drm_device * dev) 97*c0e09200SDave Airlie { 98*c0e09200SDave Airlie if (!dev->agp) 99*c0e09200SDave Airlie return -ENODEV; 100*c0e09200SDave Airlie if (dev->agp->acquired) 101*c0e09200SDave Airlie return -EBUSY; 102*c0e09200SDave Airlie if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev))) 103*c0e09200SDave Airlie return -ENODEV; 104*c0e09200SDave Airlie dev->agp->acquired = 1; 105*c0e09200SDave Airlie return 0; 106*c0e09200SDave Airlie } 107*c0e09200SDave Airlie 108*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_acquire); 109*c0e09200SDave Airlie 110*c0e09200SDave Airlie /** 111*c0e09200SDave Airlie * Acquire the AGP device (ioctl). 112*c0e09200SDave Airlie * 113*c0e09200SDave Airlie * \param inode device inode. 114*c0e09200SDave Airlie * \param file_priv DRM file private. 115*c0e09200SDave Airlie * \param cmd command. 116*c0e09200SDave Airlie * \param arg user argument. 117*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 118*c0e09200SDave Airlie * 119*c0e09200SDave Airlie * Verifies the AGP device hasn't been acquired before and calls 120*c0e09200SDave Airlie * \c agp_backend_acquire. 121*c0e09200SDave Airlie */ 122*c0e09200SDave Airlie int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, 123*c0e09200SDave Airlie struct drm_file *file_priv) 124*c0e09200SDave Airlie { 125*c0e09200SDave Airlie return drm_agp_acquire((struct drm_device *) file_priv->minor->dev); 126*c0e09200SDave Airlie } 127*c0e09200SDave Airlie 128*c0e09200SDave Airlie /** 129*c0e09200SDave Airlie * Release the AGP device. 130*c0e09200SDave Airlie * 131*c0e09200SDave Airlie * \param dev DRM device that is to release AGP. 132*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 133*c0e09200SDave Airlie * 134*c0e09200SDave Airlie * Verifies the AGP device has been acquired and calls \c agp_backend_release. 135*c0e09200SDave Airlie */ 136*c0e09200SDave Airlie int drm_agp_release(struct drm_device * dev) 137*c0e09200SDave Airlie { 138*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 139*c0e09200SDave Airlie return -EINVAL; 140*c0e09200SDave Airlie agp_backend_release(dev->agp->bridge); 141*c0e09200SDave Airlie dev->agp->acquired = 0; 142*c0e09200SDave Airlie return 0; 143*c0e09200SDave Airlie } 144*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_release); 145*c0e09200SDave Airlie 146*c0e09200SDave Airlie int drm_agp_release_ioctl(struct drm_device *dev, void *data, 147*c0e09200SDave Airlie struct drm_file *file_priv) 148*c0e09200SDave Airlie { 149*c0e09200SDave Airlie return drm_agp_release(dev); 150*c0e09200SDave Airlie } 151*c0e09200SDave Airlie 152*c0e09200SDave Airlie /** 153*c0e09200SDave Airlie * Enable the AGP bus. 154*c0e09200SDave Airlie * 155*c0e09200SDave Airlie * \param dev DRM device that has previously acquired AGP. 156*c0e09200SDave Airlie * \param mode Requested AGP mode. 157*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 158*c0e09200SDave Airlie * 159*c0e09200SDave Airlie * Verifies the AGP device has been acquired but not enabled, and calls 160*c0e09200SDave Airlie * \c agp_enable. 161*c0e09200SDave Airlie */ 162*c0e09200SDave Airlie int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode) 163*c0e09200SDave Airlie { 164*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 165*c0e09200SDave Airlie return -EINVAL; 166*c0e09200SDave Airlie 167*c0e09200SDave Airlie dev->agp->mode = mode.mode; 168*c0e09200SDave Airlie agp_enable(dev->agp->bridge, mode.mode); 169*c0e09200SDave Airlie dev->agp->enabled = 1; 170*c0e09200SDave Airlie return 0; 171*c0e09200SDave Airlie } 172*c0e09200SDave Airlie 173*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_enable); 174*c0e09200SDave Airlie 175*c0e09200SDave Airlie int drm_agp_enable_ioctl(struct drm_device *dev, void *data, 176*c0e09200SDave Airlie struct drm_file *file_priv) 177*c0e09200SDave Airlie { 178*c0e09200SDave Airlie struct drm_agp_mode *mode = data; 179*c0e09200SDave Airlie 180*c0e09200SDave Airlie return drm_agp_enable(dev, *mode); 181*c0e09200SDave Airlie } 182*c0e09200SDave Airlie 183*c0e09200SDave Airlie /** 184*c0e09200SDave Airlie * Allocate AGP memory. 185*c0e09200SDave Airlie * 186*c0e09200SDave Airlie * \param inode device inode. 187*c0e09200SDave Airlie * \param file_priv file private pointer. 188*c0e09200SDave Airlie * \param cmd command. 189*c0e09200SDave Airlie * \param arg pointer to a drm_agp_buffer structure. 190*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 191*c0e09200SDave Airlie * 192*c0e09200SDave Airlie * Verifies the AGP device is present and has been acquired, allocates the 193*c0e09200SDave Airlie * memory via alloc_agp() and creates a drm_agp_mem entry for it. 194*c0e09200SDave Airlie */ 195*c0e09200SDave Airlie int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) 196*c0e09200SDave Airlie { 197*c0e09200SDave Airlie struct drm_agp_mem *entry; 198*c0e09200SDave Airlie DRM_AGP_MEM *memory; 199*c0e09200SDave Airlie unsigned long pages; 200*c0e09200SDave Airlie u32 type; 201*c0e09200SDave Airlie 202*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 203*c0e09200SDave Airlie return -EINVAL; 204*c0e09200SDave Airlie if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS))) 205*c0e09200SDave Airlie return -ENOMEM; 206*c0e09200SDave Airlie 207*c0e09200SDave Airlie memset(entry, 0, sizeof(*entry)); 208*c0e09200SDave Airlie 209*c0e09200SDave Airlie pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; 210*c0e09200SDave Airlie type = (u32) request->type; 211*c0e09200SDave Airlie if (!(memory = drm_alloc_agp(dev, pages, type))) { 212*c0e09200SDave Airlie drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); 213*c0e09200SDave Airlie return -ENOMEM; 214*c0e09200SDave Airlie } 215*c0e09200SDave Airlie 216*c0e09200SDave Airlie entry->handle = (unsigned long)memory->key + 1; 217*c0e09200SDave Airlie entry->memory = memory; 218*c0e09200SDave Airlie entry->bound = 0; 219*c0e09200SDave Airlie entry->pages = pages; 220*c0e09200SDave Airlie list_add(&entry->head, &dev->agp->memory); 221*c0e09200SDave Airlie 222*c0e09200SDave Airlie request->handle = entry->handle; 223*c0e09200SDave Airlie request->physical = memory->physical; 224*c0e09200SDave Airlie 225*c0e09200SDave Airlie return 0; 226*c0e09200SDave Airlie } 227*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_alloc); 228*c0e09200SDave Airlie 229*c0e09200SDave Airlie 230*c0e09200SDave Airlie int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, 231*c0e09200SDave Airlie struct drm_file *file_priv) 232*c0e09200SDave Airlie { 233*c0e09200SDave Airlie struct drm_agp_buffer *request = data; 234*c0e09200SDave Airlie 235*c0e09200SDave Airlie return drm_agp_alloc(dev, request); 236*c0e09200SDave Airlie } 237*c0e09200SDave Airlie 238*c0e09200SDave Airlie /** 239*c0e09200SDave Airlie * Search for the AGP memory entry associated with a handle. 240*c0e09200SDave Airlie * 241*c0e09200SDave Airlie * \param dev DRM device structure. 242*c0e09200SDave Airlie * \param handle AGP memory handle. 243*c0e09200SDave Airlie * \return pointer to the drm_agp_mem structure associated with \p handle. 244*c0e09200SDave Airlie * 245*c0e09200SDave Airlie * Walks through drm_agp_head::memory until finding a matching handle. 246*c0e09200SDave Airlie */ 247*c0e09200SDave Airlie static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev, 248*c0e09200SDave Airlie unsigned long handle) 249*c0e09200SDave Airlie { 250*c0e09200SDave Airlie struct drm_agp_mem *entry; 251*c0e09200SDave Airlie 252*c0e09200SDave Airlie list_for_each_entry(entry, &dev->agp->memory, head) { 253*c0e09200SDave Airlie if (entry->handle == handle) 254*c0e09200SDave Airlie return entry; 255*c0e09200SDave Airlie } 256*c0e09200SDave Airlie return NULL; 257*c0e09200SDave Airlie } 258*c0e09200SDave Airlie 259*c0e09200SDave Airlie /** 260*c0e09200SDave Airlie * Unbind AGP memory from the GATT (ioctl). 261*c0e09200SDave Airlie * 262*c0e09200SDave Airlie * \param inode device inode. 263*c0e09200SDave Airlie * \param file_priv DRM file private. 264*c0e09200SDave Airlie * \param cmd command. 265*c0e09200SDave Airlie * \param arg pointer to a drm_agp_binding structure. 266*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 267*c0e09200SDave Airlie * 268*c0e09200SDave Airlie * Verifies the AGP device is present and acquired, looks-up the AGP memory 269*c0e09200SDave Airlie * entry and passes it to the unbind_agp() function. 270*c0e09200SDave Airlie */ 271*c0e09200SDave Airlie int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request) 272*c0e09200SDave Airlie { 273*c0e09200SDave Airlie struct drm_agp_mem *entry; 274*c0e09200SDave Airlie int ret; 275*c0e09200SDave Airlie 276*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 277*c0e09200SDave Airlie return -EINVAL; 278*c0e09200SDave Airlie if (!(entry = drm_agp_lookup_entry(dev, request->handle))) 279*c0e09200SDave Airlie return -EINVAL; 280*c0e09200SDave Airlie if (!entry->bound) 281*c0e09200SDave Airlie return -EINVAL; 282*c0e09200SDave Airlie ret = drm_unbind_agp(entry->memory); 283*c0e09200SDave Airlie if (ret == 0) 284*c0e09200SDave Airlie entry->bound = 0; 285*c0e09200SDave Airlie return ret; 286*c0e09200SDave Airlie } 287*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_unbind); 288*c0e09200SDave Airlie 289*c0e09200SDave Airlie 290*c0e09200SDave Airlie int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, 291*c0e09200SDave Airlie struct drm_file *file_priv) 292*c0e09200SDave Airlie { 293*c0e09200SDave Airlie struct drm_agp_binding *request = data; 294*c0e09200SDave Airlie 295*c0e09200SDave Airlie return drm_agp_unbind(dev, request); 296*c0e09200SDave Airlie } 297*c0e09200SDave Airlie 298*c0e09200SDave Airlie /** 299*c0e09200SDave Airlie * Bind AGP memory into the GATT (ioctl) 300*c0e09200SDave Airlie * 301*c0e09200SDave Airlie * \param inode device inode. 302*c0e09200SDave Airlie * \param file_priv DRM file private. 303*c0e09200SDave Airlie * \param cmd command. 304*c0e09200SDave Airlie * \param arg pointer to a drm_agp_binding structure. 305*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 306*c0e09200SDave Airlie * 307*c0e09200SDave Airlie * Verifies the AGP device is present and has been acquired and that no memory 308*c0e09200SDave Airlie * is currently bound into the GATT. Looks-up the AGP memory entry and passes 309*c0e09200SDave Airlie * it to bind_agp() function. 310*c0e09200SDave Airlie */ 311*c0e09200SDave Airlie int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request) 312*c0e09200SDave Airlie { 313*c0e09200SDave Airlie struct drm_agp_mem *entry; 314*c0e09200SDave Airlie int retcode; 315*c0e09200SDave Airlie int page; 316*c0e09200SDave Airlie 317*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 318*c0e09200SDave Airlie return -EINVAL; 319*c0e09200SDave Airlie if (!(entry = drm_agp_lookup_entry(dev, request->handle))) 320*c0e09200SDave Airlie return -EINVAL; 321*c0e09200SDave Airlie if (entry->bound) 322*c0e09200SDave Airlie return -EINVAL; 323*c0e09200SDave Airlie page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE; 324*c0e09200SDave Airlie if ((retcode = drm_bind_agp(entry->memory, page))) 325*c0e09200SDave Airlie return retcode; 326*c0e09200SDave Airlie entry->bound = dev->agp->base + (page << PAGE_SHIFT); 327*c0e09200SDave Airlie DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", 328*c0e09200SDave Airlie dev->agp->base, entry->bound); 329*c0e09200SDave Airlie return 0; 330*c0e09200SDave Airlie } 331*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_bind); 332*c0e09200SDave Airlie 333*c0e09200SDave Airlie 334*c0e09200SDave Airlie int drm_agp_bind_ioctl(struct drm_device *dev, void *data, 335*c0e09200SDave Airlie struct drm_file *file_priv) 336*c0e09200SDave Airlie { 337*c0e09200SDave Airlie struct drm_agp_binding *request = data; 338*c0e09200SDave Airlie 339*c0e09200SDave Airlie return drm_agp_bind(dev, request); 340*c0e09200SDave Airlie } 341*c0e09200SDave Airlie 342*c0e09200SDave Airlie /** 343*c0e09200SDave Airlie * Free AGP memory (ioctl). 344*c0e09200SDave Airlie * 345*c0e09200SDave Airlie * \param inode device inode. 346*c0e09200SDave Airlie * \param file_priv DRM file private. 347*c0e09200SDave Airlie * \param cmd command. 348*c0e09200SDave Airlie * \param arg pointer to a drm_agp_buffer structure. 349*c0e09200SDave Airlie * \return zero on success or a negative number on failure. 350*c0e09200SDave Airlie * 351*c0e09200SDave Airlie * Verifies the AGP device is present and has been acquired and looks up the 352*c0e09200SDave Airlie * AGP memory entry. If the memory it's currently bound, unbind it via 353*c0e09200SDave Airlie * unbind_agp(). Frees it via free_agp() as well as the entry itself 354*c0e09200SDave Airlie * and unlinks from the doubly linked list it's inserted in. 355*c0e09200SDave Airlie */ 356*c0e09200SDave Airlie int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request) 357*c0e09200SDave Airlie { 358*c0e09200SDave Airlie struct drm_agp_mem *entry; 359*c0e09200SDave Airlie 360*c0e09200SDave Airlie if (!dev->agp || !dev->agp->acquired) 361*c0e09200SDave Airlie return -EINVAL; 362*c0e09200SDave Airlie if (!(entry = drm_agp_lookup_entry(dev, request->handle))) 363*c0e09200SDave Airlie return -EINVAL; 364*c0e09200SDave Airlie if (entry->bound) 365*c0e09200SDave Airlie drm_unbind_agp(entry->memory); 366*c0e09200SDave Airlie 367*c0e09200SDave Airlie list_del(&entry->head); 368*c0e09200SDave Airlie 369*c0e09200SDave Airlie drm_free_agp(entry->memory, entry->pages); 370*c0e09200SDave Airlie drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); 371*c0e09200SDave Airlie return 0; 372*c0e09200SDave Airlie } 373*c0e09200SDave Airlie EXPORT_SYMBOL(drm_agp_free); 374*c0e09200SDave Airlie 375*c0e09200SDave Airlie 376*c0e09200SDave Airlie 377*c0e09200SDave Airlie int drm_agp_free_ioctl(struct drm_device *dev, void *data, 378*c0e09200SDave Airlie struct drm_file *file_priv) 379*c0e09200SDave Airlie { 380*c0e09200SDave Airlie struct drm_agp_buffer *request = data; 381*c0e09200SDave Airlie 382*c0e09200SDave Airlie return drm_agp_free(dev, request); 383*c0e09200SDave Airlie } 384*c0e09200SDave Airlie 385*c0e09200SDave Airlie /** 386*c0e09200SDave Airlie * Initialize the AGP resources. 387*c0e09200SDave Airlie * 388*c0e09200SDave Airlie * \return pointer to a drm_agp_head structure. 389*c0e09200SDave Airlie * 390*c0e09200SDave Airlie * Gets the drm_agp_t structure which is made available by the agpgart module 391*c0e09200SDave Airlie * via the inter_module_* functions. Creates and initializes a drm_agp_head 392*c0e09200SDave Airlie * structure. 393*c0e09200SDave Airlie */ 394*c0e09200SDave Airlie struct drm_agp_head *drm_agp_init(struct drm_device *dev) 395*c0e09200SDave Airlie { 396*c0e09200SDave Airlie struct drm_agp_head *head = NULL; 397*c0e09200SDave Airlie 398*c0e09200SDave Airlie if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) 399*c0e09200SDave Airlie return NULL; 400*c0e09200SDave Airlie memset((void *)head, 0, sizeof(*head)); 401*c0e09200SDave Airlie head->bridge = agp_find_bridge(dev->pdev); 402*c0e09200SDave Airlie if (!head->bridge) { 403*c0e09200SDave Airlie if (!(head->bridge = agp_backend_acquire(dev->pdev))) { 404*c0e09200SDave Airlie drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); 405*c0e09200SDave Airlie return NULL; 406*c0e09200SDave Airlie } 407*c0e09200SDave Airlie agp_copy_info(head->bridge, &head->agp_info); 408*c0e09200SDave Airlie agp_backend_release(head->bridge); 409*c0e09200SDave Airlie } else { 410*c0e09200SDave Airlie agp_copy_info(head->bridge, &head->agp_info); 411*c0e09200SDave Airlie } 412*c0e09200SDave Airlie if (head->agp_info.chipset == NOT_SUPPORTED) { 413*c0e09200SDave Airlie drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); 414*c0e09200SDave Airlie return NULL; 415*c0e09200SDave Airlie } 416*c0e09200SDave Airlie INIT_LIST_HEAD(&head->memory); 417*c0e09200SDave Airlie head->cant_use_aperture = head->agp_info.cant_use_aperture; 418*c0e09200SDave Airlie head->page_mask = head->agp_info.page_mask; 419*c0e09200SDave Airlie head->base = head->agp_info.aper_base; 420*c0e09200SDave Airlie return head; 421*c0e09200SDave Airlie } 422*c0e09200SDave Airlie 423*c0e09200SDave Airlie /** Calls agp_allocate_memory() */ 424*c0e09200SDave Airlie DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge, 425*c0e09200SDave Airlie size_t pages, u32 type) 426*c0e09200SDave Airlie { 427*c0e09200SDave Airlie return agp_allocate_memory(bridge, pages, type); 428*c0e09200SDave Airlie } 429*c0e09200SDave Airlie 430*c0e09200SDave Airlie /** Calls agp_free_memory() */ 431*c0e09200SDave Airlie int drm_agp_free_memory(DRM_AGP_MEM * handle) 432*c0e09200SDave Airlie { 433*c0e09200SDave Airlie if (!handle) 434*c0e09200SDave Airlie return 0; 435*c0e09200SDave Airlie agp_free_memory(handle); 436*c0e09200SDave Airlie return 1; 437*c0e09200SDave Airlie } 438*c0e09200SDave Airlie 439*c0e09200SDave Airlie /** Calls agp_bind_memory() */ 440*c0e09200SDave Airlie int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start) 441*c0e09200SDave Airlie { 442*c0e09200SDave Airlie if (!handle) 443*c0e09200SDave Airlie return -EINVAL; 444*c0e09200SDave Airlie return agp_bind_memory(handle, start); 445*c0e09200SDave Airlie } 446*c0e09200SDave Airlie 447*c0e09200SDave Airlie /** Calls agp_unbind_memory() */ 448*c0e09200SDave Airlie int drm_agp_unbind_memory(DRM_AGP_MEM * handle) 449*c0e09200SDave Airlie { 450*c0e09200SDave Airlie if (!handle) 451*c0e09200SDave Airlie return -EINVAL; 452*c0e09200SDave Airlie return agp_unbind_memory(handle); 453*c0e09200SDave Airlie } 454*c0e09200SDave Airlie 455*c0e09200SDave Airlie #endif /* __OS_HAS_AGP */ 456