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

Cache object: 2f07e5f5e5d399ae9302e6f648a2f2e4


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