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/drm/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  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
    3  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
    4  * All Rights Reserved.
    5  *
    6  * Permission is hereby granted, free of charge, to any person obtaining a
    7  * copy of this software and associated documentation files (the "Software"),
    8  * to deal in the Software without restriction, including without limitation
    9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   10  * and/or sell copies of the Software, and to permit persons to whom the
   11  * Software is furnished to do so, subject to the following conditions:
   12  *
   13  * The above copyright notice and this permission notice (including the next
   14  * paragraph) shall be included in all copies or substantial portions of the
   15  * Software.
   16  *
   17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   23  * OTHER DEALINGS IN THE SOFTWARE.
   24  *
   25  * Author:
   26  *    Rickard E. (Rik) Faith <faith@valinux.com>
   27  *    Gareth Hughes <gareth@valinux.com>
   28  *
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/9.0/sys/dev/drm/drm_agpsupport.c 219902 2011-03-23 13:10:15Z jhb $");
   33 
   34 /** @file drm_agpsupport.c
   35  * Support code for tying the kernel AGP support to DRM drivers and
   36  * the DRM's AGP ioctls.
   37  */
   38 
   39 #include "dev/drm/drmP.h"
   40 
   41 #if __FreeBSD_version >= 800004
   42 #include <dev/agp/agpreg.h>
   43 #else /* __FreeBSD_version >= 800004 */
   44 #include <pci/agpreg.h>
   45 #endif /* __FreeBSD_version >= 800004 */
   46 #include <dev/pci/pcireg.h>
   47 
   48 /* Returns 1 if AGP or 0 if not. */
   49 static int
   50 drm_device_find_capability(struct drm_device *dev, int cap)
   51 {
   52 #if __FreeBSD_version >= 602102
   53 
   54         return (pci_find_cap(dev->device, cap, NULL) == 0);
   55 #else
   56         /* Code taken from agp.c.  IWBNI that was a public interface. */
   57         u_int32_t status;
   58         u_int8_t ptr, next;
   59 
   60         /*
   61          * Check the CAP_LIST bit of the PCI status register first.
   62          */
   63         status = pci_read_config(dev->device, PCIR_STATUS, 2);
   64         if (!(status & 0x10))
   65                 return 0;
   66 
   67         /*
   68          * Traverse the capabilities list.
   69          */
   70         for (ptr = pci_read_config(dev->device, AGP_CAPPTR, 1);
   71              ptr != 0;
   72              ptr = next) {
   73                 u_int32_t capid = pci_read_config(dev->device, ptr, 4);
   74                 next = AGP_CAPID_GET_NEXT_PTR(capid);
   75 
   76                 /*
   77                  * If this capability entry ID is cap, then we are done.
   78                  */
   79                 if (AGP_CAPID_GET_CAP_ID(capid) == cap)
   80                         return 1;
   81         }
   82 
   83         return 0;
   84 #endif
   85 }
   86 
   87 int drm_device_is_agp(struct drm_device *dev)
   88 {
   89         if (dev->driver->device_is_agp != NULL) {
   90                 int ret;
   91 
   92                 /* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
   93                  * AGP, 2 = fall back to PCI capability
   94                  */
   95                 ret = (*dev->driver->device_is_agp)(dev);
   96                 if (ret != DRM_MIGHT_BE_AGP)
   97                         return ret;
   98         }
   99 
  100         return (drm_device_find_capability(dev, PCIY_AGP));
  101 }
  102 
  103 int drm_device_is_pcie(struct drm_device *dev)
  104 {
  105         return (drm_device_find_capability(dev, PCIY_EXPRESS));
  106 }
  107 
  108 int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
  109 {
  110         struct agp_info *kern;
  111 
  112         if (!dev->agp || !dev->agp->acquired)
  113                 return EINVAL;
  114 
  115         kern                   = &dev->agp->info;
  116         agp_get_info(dev->agp->agpdev, kern);
  117         info->agp_version_major = 1;
  118         info->agp_version_minor = 0;
  119         info->mode              = kern->ai_mode;
  120         info->aperture_base     = kern->ai_aperture_base;
  121         info->aperture_size     = kern->ai_aperture_size;
  122         info->memory_allowed    = kern->ai_memory_allowed;
  123         info->memory_used       = kern->ai_memory_used;
  124         info->id_vendor         = kern->ai_devid & 0xffff;
  125         info->id_device         = kern->ai_devid >> 16;
  126 
  127         return 0;
  128 }
  129 
  130 int drm_agp_info_ioctl(struct drm_device *dev, void *data,
  131                        struct drm_file *file_priv)
  132 {
  133         int err;
  134         struct drm_agp_info info;
  135 
  136         err = drm_agp_info(dev, &info);
  137         if (err != 0)
  138                 return err;
  139 
  140         *(struct drm_agp_info *) data = info;
  141         return 0;
  142 }
  143 
  144 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
  145                           struct drm_file *file_priv)
  146 {
  147 
  148         return drm_agp_acquire(dev);
  149 }
  150 
  151 int drm_agp_acquire(struct drm_device *dev)
  152 {
  153         int retcode;
  154 
  155         if (!dev->agp || dev->agp->acquired)
  156                 return EINVAL;
  157 
  158         retcode = agp_acquire(dev->agp->agpdev);
  159         if (retcode)
  160                 return retcode;
  161 
  162         dev->agp->acquired = 1;
  163         return 0;
  164 }
  165 
  166 int drm_agp_release_ioctl(struct drm_device *dev, void *data,
  167                           struct drm_file *file_priv)
  168 {
  169 
  170         return drm_agp_release(dev);
  171 }
  172 
  173 int drm_agp_release(struct drm_device * dev)
  174 {
  175         if (!dev->agp || !dev->agp->acquired)
  176                 return EINVAL;
  177         agp_release(dev->agp->agpdev);
  178         dev->agp->acquired = 0;
  179         return 0;
  180 }
  181 
  182 int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
  183 {
  184 
  185         if (!dev->agp || !dev->agp->acquired)
  186                 return EINVAL;
  187         
  188         dev->agp->mode    = mode.mode;
  189         agp_enable(dev->agp->agpdev, mode.mode);
  190         dev->agp->enabled = 1;
  191         return 0;
  192 }
  193 
  194 int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
  195                          struct drm_file *file_priv)
  196 {
  197         struct drm_agp_mode mode;
  198 
  199         mode = *(struct drm_agp_mode *) data;
  200 
  201         return drm_agp_enable(dev, mode);
  202 }
  203 
  204 int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
  205 {
  206         drm_agp_mem_t    *entry;
  207         void             *handle;
  208         unsigned long    pages;
  209         u_int32_t        type;
  210         struct agp_memory_info info;
  211 
  212         if (!dev->agp || !dev->agp->acquired)
  213                 return EINVAL;
  214 
  215         entry = malloc(sizeof(*entry), DRM_MEM_AGPLISTS, M_NOWAIT | M_ZERO);
  216         if (entry == NULL)
  217                 return ENOMEM;
  218 
  219         pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
  220         type = (u_int32_t) request->type;
  221 
  222         DRM_UNLOCK();
  223         handle = drm_agp_allocate_memory(pages, type);
  224         DRM_LOCK();
  225         if (handle == NULL) {
  226                 free(entry, DRM_MEM_AGPLISTS);
  227                 return ENOMEM;
  228         }
  229         
  230         entry->handle    = handle;
  231         entry->bound     = 0;
  232         entry->pages     = pages;
  233         entry->prev      = NULL;
  234         entry->next      = dev->agp->memory;
  235         if (dev->agp->memory)
  236                 dev->agp->memory->prev = entry;
  237         dev->agp->memory = entry;
  238 
  239         agp_memory_info(dev->agp->agpdev, entry->handle, &info);
  240 
  241         request->handle   = (unsigned long) entry->handle;
  242         request->physical = info.ami_physical;
  243 
  244         return 0;
  245 }
  246 
  247 int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
  248                         struct drm_file *file_priv)
  249 {
  250         struct drm_agp_buffer request;
  251         int retcode;
  252 
  253         request = *(struct drm_agp_buffer *) data;
  254 
  255         DRM_LOCK();
  256         retcode = drm_agp_alloc(dev, &request);
  257         DRM_UNLOCK();
  258 
  259         *(struct drm_agp_buffer *) data = request;
  260 
  261         return retcode;
  262 }
  263 
  264 static drm_agp_mem_t * drm_agp_lookup_entry(struct drm_device *dev,
  265                                             void *handle)
  266 {
  267         drm_agp_mem_t *entry;
  268 
  269         for (entry = dev->agp->memory; entry; entry = entry->next) {
  270                 if (entry->handle == handle) return entry;
  271         }
  272         return NULL;
  273 }
  274 
  275 int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
  276 {
  277         drm_agp_mem_t     *entry;
  278         int retcode;
  279 
  280         if (!dev->agp || !dev->agp->acquired)
  281                 return EINVAL;
  282 
  283         entry = drm_agp_lookup_entry(dev, (void *)request->handle);
  284         if (entry == NULL || !entry->bound)
  285                 return EINVAL;
  286 
  287         DRM_UNLOCK();
  288         retcode = drm_agp_unbind_memory(entry->handle);
  289         DRM_LOCK();
  290 
  291         if (retcode == 0)
  292                 entry->bound = 0;
  293 
  294         return retcode;
  295 }
  296 
  297 int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
  298                          struct drm_file *file_priv)
  299 {
  300         struct drm_agp_binding request;
  301         int retcode;
  302 
  303         request = *(struct drm_agp_binding *) data;
  304 
  305         DRM_LOCK();
  306         retcode = drm_agp_unbind(dev, &request);
  307         DRM_UNLOCK();
  308 
  309         return retcode;
  310 }
  311 
  312 int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
  313 {
  314         drm_agp_mem_t     *entry;
  315         int               retcode;
  316         int               page;
  317         
  318         if (!dev->agp || !dev->agp->acquired)
  319                 return EINVAL;
  320 
  321         DRM_DEBUG("agp_bind, page_size=%x\n", (int)PAGE_SIZE);
  322 
  323         entry = drm_agp_lookup_entry(dev, (void *)request->handle);
  324         if (entry == NULL || entry->bound)
  325                 return EINVAL;
  326 
  327         page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
  328 
  329         DRM_UNLOCK();
  330         retcode = drm_agp_bind_memory(entry->handle, page);
  331         DRM_LOCK();
  332         if (retcode == 0)
  333                 entry->bound = dev->agp->base + (page << PAGE_SHIFT);
  334 
  335         return retcode;
  336 }
  337 
  338 int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
  339                        struct drm_file *file_priv)
  340 {
  341         struct drm_agp_binding request;
  342         int retcode;
  343 
  344         request = *(struct drm_agp_binding *) data;
  345 
  346         DRM_LOCK();
  347         retcode = drm_agp_bind(dev, &request);
  348         DRM_UNLOCK();
  349 
  350         return retcode;
  351 }
  352 
  353 int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
  354 {
  355         drm_agp_mem_t    *entry;
  356         
  357         if (!dev->agp || !dev->agp->acquired)
  358                 return EINVAL;
  359 
  360         entry = drm_agp_lookup_entry(dev, (void*)request->handle);
  361         if (entry == NULL)
  362                 return EINVAL;
  363    
  364         if (entry->prev)
  365                 entry->prev->next = entry->next;
  366         else
  367                 dev->agp->memory  = entry->next;
  368         if (entry->next)
  369                 entry->next->prev = entry->prev;
  370 
  371         DRM_UNLOCK();
  372         if (entry->bound)
  373                 drm_agp_unbind_memory(entry->handle);
  374         drm_agp_free_memory(entry->handle);
  375         DRM_LOCK();
  376 
  377         free(entry, DRM_MEM_AGPLISTS);
  378 
  379         return 0;
  380 
  381 }
  382 
  383 int drm_agp_free_ioctl(struct drm_device *dev, void *data,
  384                        struct drm_file *file_priv)
  385 {
  386         struct drm_agp_buffer request;
  387         int retcode;
  388 
  389         request = *(struct drm_agp_buffer *) data;
  390 
  391         DRM_LOCK();
  392         retcode = drm_agp_free(dev, &request);
  393         DRM_UNLOCK();
  394 
  395         return retcode;
  396 }
  397 
  398 drm_agp_head_t *drm_agp_init(void)
  399 {
  400         device_t agpdev;
  401         drm_agp_head_t *head   = NULL;
  402         int      agp_available = 1;
  403    
  404         agpdev = DRM_AGP_FIND_DEVICE();
  405         if (!agpdev)
  406                 agp_available = 0;
  407 
  408         DRM_DEBUG("agp_available = %d\n", agp_available);
  409 
  410         if (agp_available) {
  411                 head = malloc(sizeof(*head), DRM_MEM_AGPLISTS,
  412                     M_NOWAIT | M_ZERO);
  413                 if (head == NULL)
  414                         return NULL;
  415                 head->agpdev = agpdev;
  416                 agp_get_info(agpdev, &head->info);
  417                 head->base = head->info.ai_aperture_base;
  418                 head->memory = NULL;
  419                 DRM_INFO("AGP at 0x%08lx %dMB\n",
  420                          (long)head->info.ai_aperture_base,
  421                          (int)(head->info.ai_aperture_size >> 20));
  422         }
  423         return head;
  424 }
  425 
  426 void *drm_agp_allocate_memory(size_t pages, u32 type)
  427 {
  428         device_t agpdev;
  429 
  430         agpdev = DRM_AGP_FIND_DEVICE();
  431         if (!agpdev)
  432                 return NULL;
  433 
  434         return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT);
  435 }
  436 
  437 int drm_agp_free_memory(void *handle)
  438 {
  439         device_t agpdev;
  440 
  441         agpdev = DRM_AGP_FIND_DEVICE();
  442         if (!agpdev || !handle)
  443                 return 0;
  444 
  445         agp_free_memory(agpdev, handle);
  446         return 1;
  447 }
  448 
  449 int drm_agp_bind_memory(void *handle, off_t start)
  450 {
  451         device_t agpdev;
  452 
  453         agpdev = DRM_AGP_FIND_DEVICE();
  454         if (!agpdev || !handle)
  455                 return EINVAL;
  456 
  457         return agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
  458 }
  459 
  460 int drm_agp_unbind_memory(void *handle)
  461 {
  462         device_t agpdev;
  463 
  464         agpdev = DRM_AGP_FIND_DEVICE();
  465         if (!agpdev || !handle)
  466                 return EINVAL;
  467 
  468         return agp_unbind_memory(agpdev, handle);
  469 }

Cache object: a439dfc9736892d462995207e3998374


[ 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.