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_drv.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_drv.h -- Generic driver template -*- linux-c -*-
    2  * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
    3  */
    4 /*-
    5  * Copyright 1999, 2000 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  * Authors:
   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_drv.c 176138 2008-02-10 11:15:27Z remko $");
   36 
   37 #include "dev/drm/drmP.h"
   38 #include "dev/drm/drm.h"
   39 #include "dev/drm/drm_sarea.h"
   40 
   41 #ifdef DRM_DEBUG_DEFAULT_ON
   42 int drm_debug_flag = 1;
   43 #else
   44 int drm_debug_flag = 0;
   45 #endif
   46 
   47 static int drm_load(drm_device_t *dev);
   48 static void drm_unload(drm_device_t *dev);
   49 static drm_pci_id_list_t *drm_find_description(int vendor, int device,
   50     drm_pci_id_list_t *idlist);
   51 
   52 #ifdef __FreeBSD__
   53 #define DRIVER_SOFTC(unit) \
   54         ((drm_device_t *)devclass_get_softc(drm_devclass, unit))
   55 
   56 MODULE_VERSION(drm, 1);
   57 MODULE_DEPEND(drm, agp, 1, 1, 1);
   58 MODULE_DEPEND(drm, pci, 1, 1, 1);
   59 #if __FreeBSD_version > 502127
   60 MODULE_DEPEND(drm, mem, 1, 1, 1);
   61 #endif
   62 #endif /* __FreeBSD__ */
   63 
   64 #if defined(__NetBSD__) || defined(__OpenBSD__)
   65 #define DRIVER_SOFTC(unit) \
   66         ((drm_device_t *)device_lookup(&drm_cd, unit))
   67 #endif /* __NetBSD__ || __OpenBSD__ */
   68 
   69 static drm_ioctl_desc_t           drm_ioctls[256] = {
   70         [DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { drm_version,     0 },
   71         [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { drm_getunique,   0 },
   72         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { drm_getmagic,    0 },
   73         [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
   74         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { drm_getmap,      0 },
   75         [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { drm_getclient,   0 },
   76         [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { drm_getstats,    0 },
   77         [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)]   = { drm_setversion,  DRM_MASTER|DRM_ROOT_ONLY },
   78 
   79         [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { drm_setunique,   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   80         [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { drm_noop,        DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   81         [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { drm_noop,        DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   82         [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { drm_authmagic,   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   83 
   84         [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   85         [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { drm_rmmap_ioctl, DRM_AUTH },
   86 
   87         [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   88         [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, DRM_AUTH },
   89 
   90         [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { drm_addctx,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   91         [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { drm_rmctx,       DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   92         [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { drm_modctx,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   93         [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { drm_getctx,      DRM_AUTH },
   94         [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { drm_switchctx,   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   95         [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { drm_newctx,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   96         [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { drm_resctx,      DRM_AUTH },
   97 
   98         [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { drm_adddraw,     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
   99         [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { drm_rmdraw,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  100 
  101         [DRM_IOCTL_NR(DRM_IOCTL_LOCK)]          = { drm_lock,        DRM_AUTH },
  102         [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { drm_unlock,      DRM_AUTH },
  103         [DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { drm_noop,        DRM_AUTH },
  104 
  105         [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  106         [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { drm_markbufs,    DRM_AUTH|DRM_MASTER },
  107         [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { drm_infobufs,    DRM_AUTH },
  108         [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { drm_mapbufs,     DRM_AUTH },
  109         [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { drm_freebufs,    DRM_AUTH },
  110         [DRM_IOCTL_NR(DRM_IOCTL_DMA)]           = { drm_dma,         DRM_AUTH },
  111 
  112         [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { drm_control,     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  113 
  114         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  115         [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  116         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  117         [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { drm_agp_info_ioctl, DRM_AUTH },
  118         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  119         [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  120         [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  121         [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  122 
  123         [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { drm_sg_alloc,    DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  124         [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { drm_sg_free,     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
  125 
  126         [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { drm_wait_vblank, 0 },
  127 };
  128 
  129 #ifdef __FreeBSD__
  130 static struct cdevsw drm_cdevsw = {
  131 #if __FreeBSD_version >= 502103
  132         .d_version =    D_VERSION,
  133 #endif
  134         .d_open =       drm_open,
  135         .d_close =      drm_close,
  136         .d_read =       drm_read,
  137         .d_ioctl =      drm_ioctl,
  138         .d_poll =       drm_poll,
  139         .d_mmap =       drm_mmap,
  140         .d_name =       "drm",
  141 #if __FreeBSD_version >= 502103
  142         .d_flags =      D_TRACKCLOSE | D_NEEDGIANT,
  143 #else
  144         .d_maj =        145,
  145         .d_flags =      D_TRACKCLOSE,
  146 #endif
  147 #if __FreeBSD_version < 500000
  148         .d_bmaj =       -1
  149 #endif
  150 };
  151 
  152 int drm_probe(device_t dev, drm_pci_id_list_t *idlist)
  153 {
  154         drm_pci_id_list_t *id_entry;
  155         int vendor, device;
  156 #if __FreeBSD_version < 700010
  157         device_t realdev;
  158 
  159         if (!strcmp(device_get_name(dev), "drmsub"))
  160                 realdev = device_get_parent(dev);
  161         else
  162                 realdev = dev;
  163         vendor = pci_get_vendor(realdev);
  164         device = pci_get_device(realdev);
  165 #else
  166         vendor = pci_get_vendor(dev);
  167         device = pci_get_device(dev);
  168 #endif
  169 
  170         id_entry = drm_find_description(vendor, device, idlist);
  171         if (id_entry != NULL) {
  172                 device_set_desc(dev, id_entry->name);
  173                 return 0;
  174         }
  175 
  176         return ENXIO;
  177 }
  178 
  179 int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)
  180 {
  181         drm_device_t *dev;
  182         drm_pci_id_list_t *id_entry;
  183         int unit;
  184 
  185         unit = device_get_unit(nbdev);
  186         dev = device_get_softc(nbdev);
  187 
  188 #if __FreeBSD_version < 700010
  189         if (!strcmp(device_get_name(nbdev), "drmsub"))
  190                 dev->device = device_get_parent(nbdev);
  191         else
  192                 dev->device = nbdev;
  193 #else
  194         dev->device = nbdev;
  195 #endif
  196         dev->devnode = make_dev(&drm_cdevsw,
  197                         unit,
  198                         DRM_DEV_UID,
  199                         DRM_DEV_GID,
  200                         DRM_DEV_MODE,
  201                         "dri/card%d", unit);
  202 #if __FreeBSD_version >= 500000
  203         mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
  204 #endif
  205 
  206         id_entry = drm_find_description(pci_get_vendor(dev->device),
  207             pci_get_device(dev->device), idlist);
  208         dev->id_entry = id_entry;
  209 
  210         return drm_load(dev);
  211 }
  212 
  213 int drm_detach(device_t dev)
  214 {
  215         drm_unload(device_get_softc(dev));
  216         return 0;
  217 }
  218 
  219 #ifndef DRM_DEV_NAME
  220 #define DRM_DEV_NAME "drm"
  221 #endif
  222 
  223 devclass_t drm_devclass;
  224 
  225 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  226 
  227 static struct cdevsw drm_cdevsw = {
  228         drm_open,
  229         drm_close,
  230         drm_read,
  231         nowrite,
  232         drm_ioctl,
  233         nostop,
  234         notty,
  235         drm_poll,
  236         drm_mmap,
  237         nokqfilter,
  238         D_TTY
  239 };
  240 
  241 int drm_refcnt = 0;
  242 
  243 #if defined(__NetBSD__) && __NetBSD_Version__ >= 106080000
  244 MOD_DEV("drm", DRIVER_NAME, NULL, -1, &drm_cdevsw, CDEV_MAJOR);
  245 #else
  246 MOD_DEV("drm", LM_DT_CHAR, CDEV_MAJOR, &drm_cdevsw);
  247 #endif
  248 
  249 int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver);
  250 static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd);
  251 
  252 int drm_modprobe(void);
  253 int drm_probe(struct pci_attach_args *pa);
  254 void drm_attach(struct pci_attach_args *pa, dev_t kdev);
  255 
  256 int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) {
  257         DISPATCH(lkmtp, cmd, ver, drm_lkmhandle, drm_lkmhandle, drm_lkmhandle);
  258 }
  259 
  260 static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd)
  261 {
  262         int error = 0;
  263 
  264         switch(cmd) {
  265         case LKM_E_LOAD:
  266                 if (lkmexists(lkmtp))
  267                         return EEXIST;
  268 
  269                 if(drm_modprobe())
  270                         return 0;
  271 
  272                 return 1;
  273 
  274         case LKM_E_UNLOAD:
  275                 if (drm_refcnt > 0)
  276                         return (EBUSY);
  277                 break;
  278         case LKM_E_STAT:
  279                 break;
  280 
  281         default:
  282                 error = EIO;
  283                 break;
  284         }
  285         
  286         return error;
  287 }
  288 
  289 int drm_modprobe(void)
  290 {
  291         struct pci_attach_args pa;
  292         int error;
  293 
  294         error = pci_find_device(&pa, drm_probe, idlist);
  295         if (error != 0)
  296                 drm_attach(&pa, 0);
  297 
  298         return error;
  299 }
  300 
  301 int drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t idlist)
  302 {
  303         const char *desc;
  304         drm_pci_id_list_t *id_entry;
  305 
  306         id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
  307             PCI_PRODUCT(pa->pa_id), idlist);
  308         if (id_entry != NULL) {
  309                 return 1;
  310         }
  311 
  312         return 0;
  313 }
  314 
  315 void drm_attach(struct pci_attach_args *pa, dev_t kdev, 
  316     drm_pci_id_list_t *idlist)
  317 {
  318         int i;
  319         drm_device_t *dev;
  320         drm_pci_id_list_t *id_entry;
  321 
  322         config_makeroom(kdev, &drm_cd);
  323         drm_cd.cd_devs[(kdev)] = malloc(sizeof(drm_device_t), M_DRM, M_WAITOK);
  324         dev = DRIVER_SOFTC(kdev);
  325 
  326         memset(dev, 0, sizeof(drm_device_t));
  327         memcpy(&dev->pa, pa, sizeof(dev->pa));
  328 
  329         dev->irq = pa->pa_intrline;
  330         dev->pci_domain = 0;
  331         dev->pci_bus = pa->pa_bus;
  332         dev->pci_slot = pa->pa_device;
  333         dev->pci_func = pa->pa_function;
  334         dev->dma_tag = pa->pa_dmat;
  335 
  336         id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
  337             PCI_PRODUCT(pa->pa_id), idlist);
  338         dev->driver.pci_id_entry = id_entry;
  339 
  340         DRM_INFO("%s", id_entry->name);
  341         drm_load(dev);
  342 }
  343 
  344 int drm_detach(struct device *self, int flags)
  345 {
  346         drm_unload((drm_device_t *)self);
  347         return 0;
  348 }
  349 
  350 int drm_activate(struct device *self, enum devact act)
  351 {
  352         switch (act) {
  353         case DVACT_ACTIVATE:
  354                 return (EOPNOTSUPP);
  355                 break;
  356 
  357         case DVACT_DEACTIVATE:
  358                 /* FIXME */
  359                 break;
  360         }
  361         return (0);
  362 }
  363 #endif /* __NetBSD__ || __OpenBSD__ */
  364 
  365 drm_pci_id_list_t *drm_find_description(int vendor, int device,
  366     drm_pci_id_list_t *idlist)
  367 {
  368         int i = 0;
  369         
  370         for (i = 0; idlist[i].vendor != 0; i++) {
  371                 if ((idlist[i].vendor == vendor) &&
  372                     (idlist[i].device == device)) {
  373                         return &idlist[i];
  374                 }
  375         }
  376         return NULL;
  377 }
  378 
  379 static int drm_firstopen(drm_device_t *dev)
  380 {
  381         drm_local_map_t *map;
  382         int i;
  383 
  384         DRM_SPINLOCK_ASSERT(&dev->dev_lock);
  385 
  386         /* prebuild the SAREA */
  387         i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
  388                        _DRM_CONTAINS_LOCK, &map);
  389         if (i != 0)
  390                 return i;
  391 
  392         if (dev->driver.firstopen)
  393                 dev->driver.firstopen(dev);
  394 
  395         dev->buf_use = 0;
  396 
  397         if (dev->driver.use_dma) {
  398                 i = drm_dma_setup(dev);
  399                 if (i != 0)
  400                         return i;
  401         }
  402 
  403         dev->counters  = 6;
  404         dev->types[0]  = _DRM_STAT_LOCK;
  405         dev->types[1]  = _DRM_STAT_OPENS;
  406         dev->types[2]  = _DRM_STAT_CLOSES;
  407         dev->types[3]  = _DRM_STAT_IOCTLS;
  408         dev->types[4]  = _DRM_STAT_LOCKS;
  409         dev->types[5]  = _DRM_STAT_UNLOCKS;
  410 
  411         for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
  412                 atomic_set( &dev->counts[i], 0 );
  413 
  414         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
  415                 dev->magiclist[i].head = NULL;
  416                 dev->magiclist[i].tail = NULL;
  417         }
  418 
  419         dev->lock.lock_queue = 0;
  420         dev->irq_enabled = 0;
  421         dev->context_flag = 0;
  422         dev->last_context = 0;
  423         dev->if_version = 0;
  424 
  425 #ifdef __FreeBSD__
  426         dev->buf_sigio = NULL;
  427 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  428         dev->buf_pgid = 0;
  429 #endif
  430 
  431         DRM_DEBUG( "\n" );
  432 
  433         return 0;
  434 }
  435 
  436 static int drm_lastclose(drm_device_t *dev)
  437 {
  438         drm_magic_entry_t *pt, *next;
  439         drm_local_map_t *map, *mapsave;
  440         int i;
  441 
  442         DRM_SPINLOCK_ASSERT(&dev->dev_lock);
  443 
  444         DRM_DEBUG( "\n" );
  445 
  446         if (dev->driver.lastclose != NULL)
  447                 dev->driver.lastclose(dev);
  448 
  449         if (dev->irq_enabled)
  450                 drm_irq_uninstall(dev);
  451 
  452         if ( dev->unique ) {
  453                 free(dev->unique, M_DRM);
  454                 dev->unique = NULL;
  455                 dev->unique_len = 0;
  456         }
  457                                 /* Clear pid list */
  458         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
  459                 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
  460                         next = pt->next;
  461                         free(pt, M_DRM);
  462                 }
  463                 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
  464         }
  465 
  466                                 /* Clear AGP information */
  467         if ( dev->agp ) {
  468                 drm_agp_mem_t *entry;
  469                 drm_agp_mem_t *nexte;
  470 
  471                 /* Remove AGP resources, but leave dev->agp intact until
  472                  * drm_unload is called.
  473                  */
  474                 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
  475                         nexte = entry->next;
  476                         if ( entry->bound )
  477                                 drm_agp_unbind_memory(entry->handle);
  478                         drm_agp_free_memory(entry->handle);
  479                         free(entry, M_DRM);
  480                 }
  481                 dev->agp->memory = NULL;
  482 
  483                 if (dev->agp->acquired)
  484                         drm_agp_release(dev);
  485 
  486                 dev->agp->acquired = 0;
  487                 dev->agp->enabled  = 0;
  488         }
  489         if (dev->sg != NULL) {
  490                 drm_sg_cleanup(dev->sg);
  491                 dev->sg = NULL;
  492         }
  493 
  494         TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
  495                 drm_rmmap(dev, map);
  496         }
  497 
  498 
  499         drm_dma_takedown(dev);
  500         if ( dev->lock.hw_lock ) {
  501                 dev->lock.hw_lock = NULL; /* SHM removed */
  502                 dev->lock.filp = NULL;
  503                 DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
  504         }
  505 
  506         return 0;
  507 }
  508 
  509 static int drm_load(drm_device_t *dev)
  510 {
  511         int retcode;
  512 
  513         DRM_DEBUG( "\n" );
  514 
  515         dev->irq = pci_get_irq(dev->device);
  516         /* XXX Fix domain number (alpha hoses) */
  517         dev->pci_domain = 0;
  518         dev->pci_bus = pci_get_bus(dev->device);
  519         dev->pci_slot = pci_get_slot(dev->device);
  520         dev->pci_func = pci_get_function(dev->device);
  521 
  522         dev->pci_vendor = pci_get_vendor(dev->device);
  523         dev->pci_device = pci_get_device(dev->device);
  524 
  525         TAILQ_INIT(&dev->maplist);
  526 
  527         drm_mem_init();
  528 #ifdef __FreeBSD__
  529         drm_sysctl_init(dev);
  530 #endif
  531         TAILQ_INIT(&dev->files);
  532 
  533         if (dev->driver.load != NULL) {
  534                 DRM_LOCK();
  535                 retcode = dev->driver.load(dev, dev->id_entry->driver_private);
  536                 DRM_UNLOCK();
  537                 if (retcode != 0)
  538                         goto error;
  539         }
  540 
  541         if (dev->driver.use_agp) {
  542                 if (drm_device_is_agp(dev))
  543                         dev->agp = drm_agp_init();
  544                 if (dev->driver.require_agp && dev->agp == NULL) {
  545                         DRM_ERROR("Card isn't AGP, or couldn't initialize "
  546                             "AGP.\n");
  547                         retcode = DRM_ERR(ENOMEM);
  548                         goto error;
  549                 }
  550                 if (dev->agp != NULL) {
  551                         if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
  552                             dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
  553                                 dev->agp->mtrr = 1;
  554                 }
  555         }
  556 
  557         retcode = drm_ctxbitmap_init(dev);
  558         if (retcode != 0) {
  559                 DRM_ERROR("Cannot allocate memory for context bitmap.\n");
  560                 goto error;
  561         }
  562         
  563         DRM_INFO("Initialized %s %d.%d.%d %s\n",
  564                 dev->driver.name,
  565                 dev->driver.major,
  566                 dev->driver.minor,
  567                 dev->driver.patchlevel,
  568                 dev->driver.date);
  569 
  570         return 0;
  571 
  572 error:
  573 #ifdef __FreeBSD__
  574         drm_sysctl_cleanup(dev);
  575 #endif
  576         DRM_LOCK();
  577         drm_lastclose(dev);
  578         DRM_UNLOCK();
  579 #ifdef __FreeBSD__
  580         destroy_dev(dev->devnode);
  581 #if __FreeBSD_version >= 500000
  582         mtx_destroy(&dev->dev_lock);
  583 #endif
  584 #endif
  585         return retcode;
  586 }
  587 
  588 static void drm_unload(drm_device_t *dev)
  589 {
  590         int i;
  591 
  592         DRM_DEBUG( "\n" );
  593 
  594 #ifdef __FreeBSD__
  595         drm_sysctl_cleanup(dev);
  596         destroy_dev(dev->devnode);
  597 #endif
  598 
  599         drm_ctxbitmap_cleanup(dev);
  600 
  601         if (dev->agp && dev->agp->mtrr) {
  602                 int __unused retcode;
  603 
  604                 retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base,
  605                     dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
  606                 DRM_DEBUG("mtrr_del = %d", retcode);
  607         }
  608 
  609         DRM_LOCK();
  610         drm_lastclose(dev);
  611         DRM_UNLOCK();
  612 
  613         /* Clean up PCI resources allocated by drm_bufs.c.  We're not really
  614          * worried about resource consumption while the DRM is inactive (between
  615          * lastclose and firstopen or unload) because these aren't actually
  616          * taking up KVA, just keeping the PCI resource allocated.
  617          */
  618         for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
  619                 if (dev->pcir[i] == NULL)
  620                         continue;
  621                 bus_release_resource(dev->device, SYS_RES_MEMORY,
  622                     dev->pcirid[i], dev->pcir[i]);
  623                 dev->pcir[i] = NULL;
  624         }
  625 
  626         if ( dev->agp ) {
  627                 free(dev->agp, M_DRM);
  628                 dev->agp = NULL;
  629         }
  630 
  631         if (dev->driver.unload != NULL)
  632                 dev->driver.unload(dev);
  633 
  634         drm_mem_uninit();
  635 #if defined(__FreeBSD__) &&  __FreeBSD_version >= 500000
  636         mtx_destroy(&dev->dev_lock);
  637 #endif
  638 }
  639 
  640 
  641 int drm_version(DRM_IOCTL_ARGS)
  642 {
  643         DRM_DEVICE;
  644         drm_version_t version;
  645         int len;
  646 
  647         DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) );
  648 
  649 #define DRM_COPY( name, value )                                         \
  650         len = strlen( value );                                          \
  651         if ( len > name##_len ) len = name##_len;                       \
  652         name##_len = strlen( value );                                   \
  653         if ( len && name ) {                                            \
  654                 if ( DRM_COPY_TO_USER( name, value, len ) )             \
  655                         return DRM_ERR(EFAULT);                         \
  656         }
  657 
  658         version.version_major           = dev->driver.major;
  659         version.version_minor           = dev->driver.minor;
  660         version.version_patchlevel      = dev->driver.patchlevel;
  661 
  662         DRM_COPY(version.name, dev->driver.name);
  663         DRM_COPY(version.date, dev->driver.date);
  664         DRM_COPY(version.desc, dev->driver.desc);
  665 
  666         DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) );
  667 
  668         return 0;
  669 }
  670 
  671 int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
  672 {
  673         drm_device_t *dev = NULL;
  674         int retcode = 0;
  675 
  676         dev = DRIVER_SOFTC(minor(kdev));
  677 
  678         DRM_DEBUG( "open_count = %d\n", dev->open_count );
  679 
  680         retcode = drm_open_helper(kdev, flags, fmt, p, dev);
  681 
  682         if ( !retcode ) {
  683                 atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
  684                 DRM_LOCK();
  685 #ifdef __FreeBSD__
  686                 device_busy(dev->device);
  687 #endif
  688                 if ( !dev->open_count++ )
  689                         retcode = drm_firstopen(dev);
  690                 DRM_UNLOCK();
  691         }
  692 
  693         return retcode;
  694 }
  695 
  696 int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
  697 {
  698         drm_file_t *priv;
  699         DRM_DEVICE;
  700         int retcode = 0;
  701         DRMFILE filp = (void *)(uintptr_t)(DRM_CURRENTPID);
  702         
  703         DRM_DEBUG( "open_count = %d\n", dev->open_count );
  704 
  705         DRM_LOCK();
  706 
  707         priv = drm_find_file_by_proc(dev, p);
  708         if (!priv) {
  709                 DRM_UNLOCK();
  710                 DRM_ERROR("can't find authenticator\n");
  711                 return EINVAL;
  712         }
  713 
  714         if (--priv->refs != 0)
  715                 goto done;
  716 
  717         if (dev->driver.preclose != NULL)
  718                 dev->driver.preclose(dev, filp);
  719 
  720         /* ========================================================
  721          * Begin inline drm_release
  722          */
  723 
  724 #ifdef __FreeBSD__
  725         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
  726                    DRM_CURRENTPID, (long)dev->device, dev->open_count );
  727 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  728         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
  729                    DRM_CURRENTPID, (long)&dev->device, dev->open_count);
  730 #endif
  731 
  732         if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
  733             && dev->lock.filp == filp) {
  734                 DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
  735                           DRM_CURRENTPID,
  736                           _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
  737                 if (dev->driver.reclaim_buffers_locked != NULL)
  738                         dev->driver.reclaim_buffers_locked(dev, filp);
  739 
  740                 drm_lock_free(dev, &dev->lock.hw_lock->lock,
  741                     _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
  742                 
  743                                 /* FIXME: may require heavy-handed reset of
  744                                    hardware at this point, possibly
  745                                    processed via a callback to the X
  746                                    server. */
  747         } else if (dev->driver.reclaim_buffers_locked != NULL &&
  748             dev->lock.hw_lock != NULL) {
  749                 /* The lock is required to reclaim buffers */
  750                 for (;;) {
  751                         if ( !dev->lock.hw_lock ) {
  752                                 /* Device has been unregistered */
  753                                 retcode = DRM_ERR(EINTR);
  754                                 break;
  755                         }
  756                         if (drm_lock_take(&dev->lock.hw_lock->lock,
  757                             DRM_KERNEL_CONTEXT)) {
  758                                 dev->lock.filp = filp;
  759                                 dev->lock.lock_time = jiffies;
  760                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
  761                                 break;  /* Got lock */
  762                         }
  763                                 /* Contention */
  764 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
  765                         retcode = msleep((void *)&dev->lock.lock_queue,
  766                             &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
  767 #else
  768                         retcode = tsleep((void *)&dev->lock.lock_queue,
  769                             PZERO | PCATCH, "drmlk2", 0);
  770 #endif
  771                         if (retcode)
  772                                 break;
  773                 }
  774                 if (retcode == 0) {
  775                         dev->driver.reclaim_buffers_locked(dev, filp);
  776                         drm_lock_free(dev, &dev->lock.hw_lock->lock,
  777                             DRM_KERNEL_CONTEXT);
  778                 }
  779         }
  780 
  781         if (dev->driver.use_dma && !dev->driver.reclaim_buffers_locked)
  782                 drm_reclaim_buffers(dev, filp);
  783 
  784 #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
  785         funsetown(&dev->buf_sigio);
  786 #elif defined(__FreeBSD__)
  787         funsetown(dev->buf_sigio);
  788 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  789         dev->buf_pgid = 0;
  790 #endif /* __NetBSD__  || __OpenBSD__ */
  791 
  792         if (dev->driver.postclose != NULL)
  793                 dev->driver.postclose(dev, priv);
  794 
  795         TAILQ_REMOVE(&dev->files, priv, link);
  796         free(priv, M_DRM);
  797 
  798         /* ========================================================
  799          * End inline drm_release
  800          */
  801 
  802         done:
  803         atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
  804 #ifdef __FreeBSD__
  805         device_unbusy(dev->device);
  806 #endif
  807         if (--dev->open_count == 0) {
  808                 retcode = drm_lastclose(dev);
  809         }
  810 
  811         DRM_UNLOCK();
  812         
  813         return retcode;
  814 }
  815 
  816 /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
  817  */
  818 int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, 
  819     DRM_STRUCTPROC *p)
  820 {
  821         DRM_DEVICE;
  822         int retcode = 0;
  823         drm_ioctl_desc_t *ioctl;
  824         int (*func)(DRM_IOCTL_ARGS);
  825         int nr = DRM_IOCTL_NR(cmd);
  826         int is_driver_ioctl = 0;
  827         drm_file_t *priv;
  828         DRMFILE filp = (DRMFILE)(uintptr_t)DRM_CURRENTPID;
  829 
  830         DRM_LOCK();
  831         priv = drm_find_file_by_proc(dev, p);
  832         DRM_UNLOCK();
  833         if (priv == NULL) {
  834                 DRM_ERROR("can't find authenticator\n");
  835                 return EINVAL;
  836         }
  837 
  838         atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
  839         ++priv->ioctl_count;
  840 
  841 #ifdef __FreeBSD__
  842         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
  843                  DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
  844 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  845         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
  846                  DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated );
  847 #endif
  848 
  849         switch (cmd) {
  850         case FIONBIO:
  851         case FIOASYNC:
  852                 return 0;
  853 
  854 #ifdef __FreeBSD__
  855         case FIOSETOWN:
  856                 return fsetown(*(int *)data, &dev->buf_sigio);
  857 
  858         case FIOGETOWN:
  859 #if (__FreeBSD_version >= 500000)
  860                 *(int *) data = fgetown(&dev->buf_sigio);
  861 #else
  862                 *(int *) data = fgetown(dev->buf_sigio);
  863 #endif
  864                 return 0;
  865 #endif /* __FreeBSD__ */
  866 #if defined(__NetBSD__) || defined(__OpenBSD__)
  867         case TIOCSPGRP:
  868                 dev->buf_pgid = *(int *)data;
  869                 return 0;
  870 
  871         case TIOCGPGRP:
  872                 *(int *)data = dev->buf_pgid;
  873                 return 0;
  874 #endif /* __NetBSD__ */
  875         }
  876 
  877         if (IOCGROUP(cmd) != DRM_IOCTL_BASE) {
  878                 DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd));
  879                 return EINVAL;
  880         }
  881 
  882         ioctl = &drm_ioctls[nr];
  883         /* It's not a core DRM ioctl, try driver-specific. */
  884         if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
  885                 /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
  886                 nr -= DRM_COMMAND_BASE;
  887                 if (nr > dev->driver.max_ioctl) {
  888                         DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n",
  889                             nr, dev->driver.max_ioctl);
  890                         return EINVAL;
  891                 }
  892                 ioctl = &dev->driver.ioctls[nr];
  893                 is_driver_ioctl = 1;
  894         }
  895         func = ioctl->func;
  896 
  897         if (func == NULL) {
  898                 DRM_DEBUG( "no function\n" );
  899                 return EINVAL;
  900         }
  901         /* ioctl->master check should be against something in the filp set up
  902          * for the first opener, but it doesn't matter yet.
  903          */
  904         if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
  905             ((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
  906             ((ioctl->flags & DRM_MASTER) && !priv->master))
  907                 return EACCES;
  908 
  909         if (is_driver_ioctl)
  910                 DRM_LOCK();
  911         retcode = func(kdev, cmd, data, flags, p, filp);
  912         if (is_driver_ioctl)
  913                 DRM_UNLOCK();
  914 
  915         if (retcode != 0)
  916                 DRM_DEBUG("    returning %d\n", retcode);
  917 
  918         return DRM_ERR(retcode);
  919 }
  920 
  921 
  922 #if DRM_LINUX
  923 
  924 #include <sys/sysproto.h>
  925 
  926 MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
  927 
  928 #define LINUX_IOCTL_DRM_MIN             0x6400
  929 #define LINUX_IOCTL_DRM_MAX             0x64ff
  930 
  931 static linux_ioctl_function_t drm_linux_ioctl;
  932 static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl, 
  933     LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
  934 
  935 SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE, 
  936     linux_ioctl_register_handler, &drm_handler);
  937 SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, 
  938     linux_ioctl_unregister_handler, &drm_handler);
  939 
  940 /* The bits for in/out are switched on Linux */
  941 #define LINUX_IOC_IN    IOC_OUT
  942 #define LINUX_IOC_OUT   IOC_IN
  943 
  944 static int
  945 drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
  946 {
  947         int error;
  948         int cmd = args->cmd;
  949 
  950         args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
  951         if (cmd & LINUX_IOC_IN)
  952                 args->cmd |= IOC_IN;
  953         if (cmd & LINUX_IOC_OUT)
  954                 args->cmd |= IOC_OUT;
  955         
  956         error = ioctl(p, (struct ioctl_args *)args);
  957 
  958         return error;
  959 }
  960 #endif /* DRM_LINUX */

Cache object: 64a24d05f63bf94e3348e86b3542dcb7


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