The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm2/drm_agpsupport.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 64b6076a73845b1a51856a447c9673bf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.