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

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  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
    5  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
    6  * All Rights Reserved.
    7  *
    8  * Permission is hereby granted, free of charge, to any person obtaining a
    9  * copy of this software and associated documentation files (the "Software"),
   10  * to deal in the Software without restriction, including without limitation
   11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   12  * and/or sell copies of the Software, and to permit persons to whom the
   13  * Software is furnished to do so, subject to the following conditions:
   14  *
   15  * The above copyright notice and this permission notice (including the next
   16  * paragraph) shall be included in all copies or substantial portions of the
   17  * Software.
   18  *
   19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   22  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   25  * OTHER DEALINGS IN THE SOFTWARE.
   26  *
   27  * Authors:
   28  *    Rickard E. (Rik) Faith <faith@valinux.com>
   29  *    Gareth Hughes <gareth@valinux.com>
   30  *
   31  * $FreeBSD: releng/5.0/sys/dev/drm/drm_drv.h 104393 2002-10-03 02:13:00Z truckman $
   32  */
   33 
   34 /*
   35  * To use this template, you must at least define the following (samples
   36  * given for the MGA driver):
   37  *
   38  * #define DRIVER_AUTHOR        "VA Linux Systems, Inc."
   39  *
   40  * #define DRIVER_NAME          "mga"
   41  * #define DRIVER_DESC          "Matrox G200/G400"
   42  * #define DRIVER_DATE          "20001127"
   43  *
   44  * #define DRIVER_MAJOR         2
   45  * #define DRIVER_MINOR         0
   46  * #define DRIVER_PATCHLEVEL    2
   47  *
   48  * #define DRIVER_IOCTL_COUNT   DRM_ARRAY_SIZE( mga_ioctls )
   49  *
   50  * #define DRM(x)               mga_##x
   51  */
   52 
   53 #ifndef __MUST_HAVE_AGP
   54 #define __MUST_HAVE_AGP                 0
   55 #endif
   56 #ifndef __HAVE_CTX_BITMAP
   57 #define __HAVE_CTX_BITMAP               0
   58 #endif
   59 #ifndef __HAVE_DMA_IRQ
   60 #define __HAVE_DMA_IRQ                  0
   61 #endif
   62 #ifndef __HAVE_DMA_QUEUE
   63 #define __HAVE_DMA_QUEUE                0
   64 #endif
   65 #ifndef __HAVE_MULTIPLE_DMA_QUEUES
   66 #define __HAVE_MULTIPLE_DMA_QUEUES      0
   67 #endif
   68 #ifndef __HAVE_DMA_SCHEDULE
   69 #define __HAVE_DMA_SCHEDULE             0
   70 #endif
   71 #ifndef __HAVE_DMA_FLUSH
   72 #define __HAVE_DMA_FLUSH                0
   73 #endif
   74 #ifndef __HAVE_DMA_READY
   75 #define __HAVE_DMA_READY                0
   76 #endif
   77 #ifndef __HAVE_DMA_QUIESCENT
   78 #define __HAVE_DMA_QUIESCENT            0
   79 #endif
   80 #ifndef __HAVE_RELEASE
   81 #define __HAVE_RELEASE                  0
   82 #endif
   83 #ifndef __HAVE_COUNTERS
   84 #define __HAVE_COUNTERS                 0
   85 #endif
   86 #ifndef __HAVE_SG
   87 #define __HAVE_SG                       0
   88 #endif
   89 #ifndef __HAVE_KERNEL_CTX_SWITCH
   90 #define __HAVE_KERNEL_CTX_SWITCH        0
   91 #endif
   92 #ifndef PCI_ANY_ID
   93 #define PCI_ANY_ID      ~0
   94 #endif
   95 
   96 #ifndef DRIVER_PREINIT
   97 #define DRIVER_PREINIT()
   98 #endif
   99 #ifndef DRIVER_POSTINIT
  100 #define DRIVER_POSTINIT()
  101 #endif
  102 #ifndef DRIVER_PRERELEASE
  103 #define DRIVER_PRERELEASE()
  104 #endif
  105 #ifndef DRIVER_PRETAKEDOWN
  106 #define DRIVER_PRETAKEDOWN()
  107 #endif
  108 #ifndef DRIVER_POSTCLEANUP
  109 #define DRIVER_POSTCLEANUP()
  110 #endif
  111 #ifndef DRIVER_PRESETUP
  112 #define DRIVER_PRESETUP()
  113 #endif
  114 #ifndef DRIVER_POSTSETUP
  115 #define DRIVER_POSTSETUP()
  116 #endif
  117 #ifndef DRIVER_IOCTLS
  118 #define DRIVER_IOCTLS
  119 #endif
  120 #ifndef DRIVER_FOPS
  121 #ifdef __linux__
  122 #define DRIVER_FOPS                             \
  123 static struct file_operations   DRM(fops) = {   \
  124         owner:   THIS_MODULE,                   \
  125         open:    DRM(open),                     \
  126         flush:   DRM(flush),                    \
  127         release: DRM(release),                  \
  128         ioctl:   DRM(ioctl),                    \
  129         mmap:    DRM(mmap),                     \
  130         read:    DRM(read),                     \
  131         fasync:  DRM(fasync),                   \
  132         poll:    DRM(poll),                     \
  133 }
  134 #endif /* __linux__ */
  135 #ifdef __FreeBSD__
  136 #if DRM_LINUX
  137 #include <sys/file.h>
  138 #include <sys/proc.h>
  139 #include <machine/../linux/linux.h>
  140 #include <machine/../linux/linux_proto.h>
  141 #endif
  142 #endif /* __FreeBSD__ */
  143 #endif
  144 
  145 
  146 /*
  147  * The default number of instances (minor numbers) to initialize.
  148  */
  149 #ifndef DRIVER_NUM_CARDS
  150 #define DRIVER_NUM_CARDS 1
  151 #endif
  152 
  153 #ifdef __FreeBSD__
  154 static int DRM(init)(device_t nbdev);
  155 static void DRM(cleanup)(device_t nbdev);
  156 
  157 #define CDEV_MAJOR      145
  158 #define DRIVER_SOFTC(unit) \
  159         ((drm_device_t *) devclass_get_softc(DRM(devclass), unit))
  160 
  161 #if __REALLY_HAVE_AGP
  162 MODULE_DEPEND(DRIVER_NAME, agp, 1, 1, 1);
  163 #endif
  164 #if DRM_LINUX
  165 MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
  166 #endif
  167 #endif /* __FreeBSD__ */
  168 
  169 static drm_device_t     *DRM(device);
  170 static int              *DRM(minor);
  171 static int              DRM(numdevs) = 0;
  172 
  173 #ifdef __linux__
  174 DRIVER_FOPS;
  175 #endif /* __linux__ */
  176 
  177 static drm_ioctl_desc_t           DRM(ioctls)[] = {
  178         [DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
  179         [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
  180         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
  181         [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_busid),   0, 1 },
  182         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
  183         [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
  184         [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
  185 
  186         [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { DRM(setunique),   1, 1 },
  187         [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { DRM(block),       1, 1 },
  188         [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { DRM(unblock),     1, 1 },
  189         [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { DRM(authmagic),   1, 1 },
  190 
  191         [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap),      1, 1 },
  192         [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap),       1, 0 },
  193 
  194 #if __HAVE_CTX_BITMAP
  195         [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
  196         [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
  197 #endif
  198 
  199         [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { DRM(addctx),      1, 1 },
  200         [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { DRM(rmctx),       1, 1 },
  201         [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { DRM(modctx),      1, 1 },
  202         [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { DRM(getctx),      1, 0 },
  203         [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { DRM(switchctx),   1, 1 },
  204         [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { DRM(newctx),      1, 1 },
  205         [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { DRM(resctx),      1, 0 },
  206 
  207         [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { DRM(adddraw),     1, 1 },
  208         [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { DRM(rmdraw),      1, 1 },
  209 
  210         [DRM_IOCTL_NR(DRM_IOCTL_LOCK)]          = { DRM(lock),        1, 0 },
  211         [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { DRM(unlock),      1, 0 },
  212         [DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(finish),      1, 0 },
  213 
  214 #if __HAVE_DMA
  215         [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { DRM(addbufs),     1, 1 },
  216         [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { DRM(markbufs),    1, 1 },
  217         [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
  218         [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
  219         [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
  220 
  221         /* The DRM_IOCTL_DMA ioctl should be defined by the driver.
  222          */
  223 #if __HAVE_DMA_IRQ
  224         [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
  225 #endif
  226 #endif
  227 
  228 #if __REALLY_HAVE_AGP
  229         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
  230         [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { DRM(agp_release), 1, 1 },
  231         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { DRM(agp_enable),  1, 1 },
  232         [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { DRM(agp_info),    1, 0 },
  233         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { DRM(agp_alloc),   1, 1 },
  234         [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { DRM(agp_free),    1, 1 },
  235         [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { DRM(agp_bind),    1, 1 },
  236         [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  1, 1 },
  237 #endif
  238 
  239 #if __REALLY_HAVE_SG
  240         [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc),    1, 1 },
  241         [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
  242 #endif
  243 
  244         DRIVER_IOCTLS
  245 };
  246 
  247 #define DRIVER_IOCTL_COUNT      DRM_ARRAY_SIZE( DRM(ioctls) )
  248 
  249 #ifdef __linux__
  250 #ifdef MODULE
  251 static char *drm_opts = NULL;
  252 #endif
  253 
  254 MODULE_AUTHOR( DRIVER_AUTHOR );
  255 MODULE_DESCRIPTION( DRIVER_DESC );
  256 MODULE_PARM( drm_opts, "s" );
  257 MODULE_LICENSE("GPL and additional rights");
  258 #endif /* __linux__ */
  259 
  260 #ifdef __FreeBSD__
  261 static int DRM(probe)(device_t dev)
  262 {
  263         const char *s = 0;
  264 
  265         int pciid=pci_get_devid(dev);
  266         int vendor = (pciid & 0x0000ffff);
  267         int device = (pciid & 0xffff0000) >> 16;
  268         int i=0, done=0;
  269         /*DRM_INFO("Checking PCI vendor=%d, device=%d\n", vendor, device);*/
  270         while ( !done && (DRM(devicelist)[i].vendor != 0 ) ) {
  271                 if ( (DRM(devicelist)[i].vendor == vendor) &&
  272                      (DRM(devicelist)[i].device == device) ) {
  273                         done=1;
  274                         if ( DRM(devicelist)[i].supported )
  275                                 s = DRM(devicelist)[i].name;
  276                         else
  277                                 DRM_INFO("%s not supported\n", DRM(devicelist)[i].name);
  278                 }
  279                 i++;
  280         }
  281         
  282         if (s) {
  283                 device_set_desc(dev, s);
  284                 return 0;
  285         }
  286 
  287         return ENXIO;
  288 }
  289 
  290 static int DRM(attach)(device_t dev)
  291 {
  292         return DRM(init)(dev);
  293 }
  294 
  295 static int DRM(detach)(device_t dev)
  296 {
  297         DRM(cleanup)(dev);
  298         return 0;
  299 }
  300 
  301 static device_method_t DRM(methods)[] = {
  302         /* Device interface */
  303         DEVMETHOD(device_probe,         DRM( probe)),
  304         DEVMETHOD(device_attach,        DRM( attach)),
  305         DEVMETHOD(device_detach,        DRM( detach)),
  306 
  307         { 0, 0 }
  308 };
  309 
  310 static driver_t DRM(driver) = {
  311         "drm",
  312         DRM(methods),
  313         sizeof(drm_device_t),
  314 };
  315 
  316 static devclass_t DRM( devclass);
  317 
  318 static struct cdevsw DRM( cdevsw) = {
  319         /* open */      DRM( open ),
  320         /* close */     DRM( close ),
  321         /* read */      DRM( read ),
  322         /* write */     DRM( write ),
  323         /* ioctl */     DRM( ioctl ),
  324         /* poll */      DRM( poll ),
  325         /* mmap */      DRM( mmap ),
  326         /* strategy */  nostrategy,
  327         /* name */      DRIVER_NAME,
  328         /* maj */       CDEV_MAJOR,
  329         /* dump */      nodump,
  330         /* psize */     nopsize,
  331         /* flags */     D_TTY | D_TRACKCLOSE,
  332 #if __FreeBSD_version >= 500000
  333         /* kqfilter */  0
  334 #else
  335         /* bmaj */      -1
  336 #endif
  337 };
  338 #endif /* __FreeBSD__ */
  339 
  340 static int DRM(setup)( drm_device_t *dev )
  341 {
  342         int i;
  343 
  344         DRIVER_PRESETUP();
  345         atomic_set( &dev->ioctl_count, 0 );
  346         atomic_set( &dev->vma_count, 0 );
  347         dev->buf_use = 0;
  348         atomic_set( &dev->buf_alloc, 0 );
  349 
  350 #if __HAVE_DMA
  351         i = DRM(dma_setup)( dev );
  352         if ( i < 0 )
  353                 return i;
  354 #endif
  355 
  356         dev->counters  = 6 + __HAVE_COUNTERS;
  357         dev->types[0]  = _DRM_STAT_LOCK;
  358         dev->types[1]  = _DRM_STAT_OPENS;
  359         dev->types[2]  = _DRM_STAT_CLOSES;
  360         dev->types[3]  = _DRM_STAT_IOCTLS;
  361         dev->types[4]  = _DRM_STAT_LOCKS;
  362         dev->types[5]  = _DRM_STAT_UNLOCKS;
  363 #ifdef __HAVE_COUNTER6
  364         dev->types[6]  = __HAVE_COUNTER6;
  365 #endif
  366 #ifdef __HAVE_COUNTER7
  367         dev->types[7]  = __HAVE_COUNTER7;
  368 #endif
  369 #ifdef __HAVE_COUNTER8
  370         dev->types[8]  = __HAVE_COUNTER8;
  371 #endif
  372 #ifdef __HAVE_COUNTER9
  373         dev->types[9]  = __HAVE_COUNTER9;
  374 #endif
  375 #ifdef __HAVE_COUNTER10
  376         dev->types[10] = __HAVE_COUNTER10;
  377 #endif
  378 #ifdef __HAVE_COUNTER11
  379         dev->types[11] = __HAVE_COUNTER11;
  380 #endif
  381 #ifdef __HAVE_COUNTER12
  382         dev->types[12] = __HAVE_COUNTER12;
  383 #endif
  384 #ifdef __HAVE_COUNTER13
  385         dev->types[13] = __HAVE_COUNTER13;
  386 #endif
  387 #ifdef __HAVE_COUNTER14
  388         dev->types[14] = __HAVE_COUNTER14;
  389 #endif
  390 #ifdef __HAVE_COUNTER15
  391         dev->types[14] = __HAVE_COUNTER14;
  392 #endif
  393 
  394         for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
  395                 atomic_set( &dev->counts[i], 0 );
  396 
  397         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
  398                 dev->magiclist[i].head = NULL;
  399                 dev->magiclist[i].tail = NULL;
  400         }
  401 
  402         dev->maplist = DRM(alloc)(sizeof(*dev->maplist),
  403                                   DRM_MEM_MAPS);
  404         if(dev->maplist == NULL) return DRM_OS_ERR(ENOMEM);
  405         memset(dev->maplist, 0, sizeof(*dev->maplist));
  406 #ifdef __linux__
  407         INIT_LIST_HEAD(&dev->maplist->head);
  408 #endif /* __linux__ */
  409 #ifdef __FreeBSD__
  410         TAILQ_INIT(dev->maplist);
  411 #endif /* __FreeBSD__ */
  412         dev->map_count = 0;
  413 
  414         dev->vmalist = NULL;
  415         dev->lock.hw_lock = NULL;
  416 #ifdef __linux__
  417         init_waitqueue_head( &dev->lock.lock_queue );
  418 #endif /* __linux__ */
  419 #ifdef __FreeBSD__
  420         dev->lock.lock_queue = 0;
  421 #endif /* __FreeBSD__ */
  422         dev->queue_count = 0;
  423         dev->queue_reserved = 0;
  424         dev->queue_slots = 0;
  425         dev->queuelist = NULL;
  426         dev->irq = 0;
  427         dev->context_flag = 0;
  428         dev->interrupt_flag = 0;
  429         dev->dma_flag = 0;
  430         dev->last_context = 0;
  431         dev->last_switch = 0;
  432         dev->last_checked = 0;
  433 #ifdef __linux__
  434         init_timer( &dev->timer );
  435         init_waitqueue_head( &dev->context_wait );
  436 #endif /* __linux__ */
  437 #ifdef __FreeBSD__
  438 #if __FreeBSD_version >= 500000
  439         callout_init( &dev->timer, 1 );
  440 #else
  441         callout_init( &dev->timer );
  442 #endif
  443         dev->context_wait = 0;
  444 #endif /* __FreeBSD__ */
  445 
  446         dev->ctx_start = 0;
  447         dev->lck_start = 0;
  448 
  449         dev->buf_rp = dev->buf;
  450         dev->buf_wp = dev->buf;
  451         dev->buf_end = dev->buf + DRM_BSZ;
  452 #ifdef __linux__
  453         dev->buf_async = NULL;
  454         init_waitqueue_head( &dev->buf_readers );
  455         init_waitqueue_head( &dev->buf_writers );
  456 #endif /* __linux__ */
  457 #ifdef __FreeBSD__
  458         dev->buf_sigio = NULL;
  459         dev->buf_readers = 0;
  460         dev->buf_writers = 0;
  461         dev->buf_selecting = 0;
  462 #endif /* __FreeBSD__ */
  463 
  464         DRM_DEBUG( "\n" );
  465 
  466         /* The kernel's context could be created here, but is now created
  467          * in drm_dma_enqueue.  This is more resource-efficient for
  468          * hardware that does not do DMA, but may mean that
  469          * drm_select_queue fails between the time the interrupt is
  470          * initialized and the time the queues are initialized.
  471          */
  472         DRIVER_POSTSETUP();
  473         return 0;
  474 }
  475 
  476 
  477 static int DRM(takedown)( drm_device_t *dev )
  478 {
  479         drm_magic_entry_t *pt, *next;
  480         drm_map_t *map;
  481 #ifdef __linux__
  482         drm_map_list_t *r_list;
  483         struct list_head *list, *list_next;
  484 #endif /* __linux__ */
  485 #ifdef __FreeBSD__
  486         drm_map_list_entry_t *list;
  487 #endif /* __FreeBSD__ */
  488         drm_vma_entry_t *vma, *vma_next;
  489         int i;
  490 
  491         DRM_DEBUG( "\n" );
  492 
  493         DRIVER_PRETAKEDOWN();
  494 #if __HAVE_DMA_IRQ
  495         if ( dev->irq ) DRM(irq_uninstall)( dev );
  496 #endif
  497 
  498         DRM_OS_LOCK;
  499 #ifdef __linux__
  500         del_timer( &dev->timer );
  501 #endif /* __linux__ */
  502 #ifdef __FreeBSD__
  503         callout_stop( &dev->timer );
  504 #endif /* __FreeBSD__ */
  505 
  506         if ( dev->devname ) {
  507                 DRM(free)( dev->devname, strlen( dev->devname ) + 1,
  508                            DRM_MEM_DRIVER );
  509                 dev->devname = NULL;
  510         }
  511 
  512         if ( dev->unique ) {
  513                 DRM(free)( dev->unique, strlen( dev->unique ) + 1,
  514                            DRM_MEM_DRIVER );
  515                 dev->unique = NULL;
  516                 dev->unique_len = 0;
  517         }
  518                                 /* Clear pid list */
  519         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
  520                 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
  521                         next = pt->next;
  522                         DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
  523                 }
  524                 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
  525         }
  526 
  527 #if __REALLY_HAVE_AGP
  528                                 /* Clear AGP information */
  529         if ( dev->agp ) {
  530                 drm_agp_mem_t *entry;
  531                 drm_agp_mem_t *nexte;
  532 
  533                                 /* Remove AGP resources, but leave dev->agp
  534                                    intact until drv_cleanup is called. */
  535                 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
  536                         nexte = entry->next;
  537 #ifdef __linux__
  538                         if ( entry->bound ) DRM(unbind_agp)( entry->memory );
  539                         DRM(free_agp)( entry->memory, entry->pages );
  540 #endif /* __linux__ */
  541 #ifdef __FreeBSD__
  542                         if ( entry->bound ) DRM(unbind_agp)( entry->handle );
  543                         DRM(free_agp)( entry->handle, entry->pages );
  544 #endif /* __FreeBSD__ */
  545                         DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
  546                 }
  547                 dev->agp->memory = NULL;
  548 
  549                 if ( dev->agp->acquired ) DRM(agp_do_release)();
  550 
  551                 dev->agp->acquired = 0;
  552                 dev->agp->enabled  = 0;
  553         }
  554 #endif
  555 
  556                                 /* Clear vma list (only built for debugging) */
  557         if ( dev->vmalist ) {
  558                 for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
  559                         vma_next = vma->next;
  560                         DRM(free)( vma, sizeof(*vma), DRM_MEM_VMAS );
  561                 }
  562                 dev->vmalist = NULL;
  563         }
  564 
  565         if( dev->maplist ) {
  566 #ifdef __linux__
  567                 for(list = dev->maplist->head.next;
  568                     list != &dev->maplist->head;
  569                     list = list_next) {
  570                         list_next = list->next;
  571                         r_list = (drm_map_list_t *)list;
  572                         map = r_list->map;
  573                         DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
  574                         if(!map) continue;
  575 #endif /* __linux__ */
  576 #ifdef __FreeBSD__
  577                 while ((list=TAILQ_FIRST(dev->maplist))) {
  578                         map = list->map;
  579 #endif /* __FreeBSD__ */
  580                         switch ( map->type ) {
  581                         case _DRM_REGISTERS:
  582                         case _DRM_FRAME_BUFFER:
  583 #if __REALLY_HAVE_MTRR
  584                                 if ( map->mtrr >= 0 ) {
  585                                         int retcode;
  586                                         retcode = mtrr_del( map->mtrr,
  587                                                             map->offset,
  588                                                             map->size );
  589                                         DRM_DEBUG( "mtrr_del=%d\n", retcode );
  590                                 }
  591 #endif
  592                                 DRM(ioremapfree)( map->handle, map->size );
  593                                 break;
  594                         case _DRM_SHM:
  595 #ifdef __linux__
  596                                 vfree(map->handle);
  597 #endif /* __linux__ */
  598 #ifdef __FreeBSD__
  599                                 DRM(free_pages)((unsigned long)map->handle,
  600                                                DRM(order)(map->size)
  601                                                - PAGE_SHIFT,
  602                                                DRM_MEM_SAREA);
  603 #endif /* __FreeBSD__ */
  604                                 break;
  605 
  606                         case _DRM_AGP:
  607                                 /* Do nothing here, because this is all
  608                                  * handled in the AGP/GART driver.
  609                                  */
  610                                 break;
  611                        case _DRM_SCATTER_GATHER:
  612                                 /* Handle it, but do nothing, if REALLY_HAVE_SG
  613                                  * isn't defined.
  614                                  */
  615 #if __REALLY_HAVE_SG
  616                                 if(dev->sg) {
  617                                         DRM(sg_cleanup)(dev->sg);
  618                                         dev->sg = NULL;
  619                                 }
  620 #endif
  621                                 break;
  622                         }
  623 #ifdef __FreeBSD__
  624                         TAILQ_REMOVE(dev->maplist, list, link);
  625                         DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
  626 #endif /* __FreeBSD__ */
  627                         DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
  628                 }
  629                 DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
  630                 dev->maplist   = NULL;
  631         }
  632 
  633 #if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES
  634         if ( dev->queuelist ) {
  635                 for ( i = 0 ; i < dev->queue_count ; i++ ) {
  636                         DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist );
  637                         if ( dev->queuelist[i] ) {
  638                                 DRM(free)( dev->queuelist[i],
  639                                           sizeof(*dev->queuelist[0]),
  640                                           DRM_MEM_QUEUES );
  641                                 dev->queuelist[i] = NULL;
  642                         }
  643                 }
  644                 DRM(free)( dev->queuelist,
  645                           dev->queue_slots * sizeof(*dev->queuelist),
  646                           DRM_MEM_QUEUES );
  647                 dev->queuelist = NULL;
  648         }
  649         dev->queue_count = 0;
  650 #endif
  651 
  652 #if __HAVE_DMA
  653         DRM(dma_takedown)( dev );
  654 #endif
  655         if ( dev->lock.hw_lock ) {
  656                 dev->lock.hw_lock = NULL; /* SHM removed */
  657                 dev->lock.pid = 0;
  658                 DRM_OS_WAKEUP_INT(&dev->lock.lock_queue);
  659         }
  660         DRM_OS_UNLOCK;
  661 
  662         return 0;
  663 }
  664 
  665 /*
  666  * Figure out how many instances to initialize.
  667  */
  668 static int drm_count_cards(void)
  669 {
  670         int num = 0;
  671 #if defined(DRIVER_CARD_LIST)
  672         int i;
  673         drm_pci_list_t *l;
  674         u16 device, vendor;
  675         struct pci_dev *pdev = NULL;
  676 #endif
  677 
  678         DRM_DEBUG( "\n" );
  679 
  680 #if defined(DRIVER_COUNT_CARDS)
  681         num = DRIVER_COUNT_CARDS();
  682 #elif defined(DRIVER_CARD_LIST)
  683         for (i = 0, l = DRIVER_CARD_LIST; l[i].vendor != 0; i++) {
  684                 pdev = NULL;
  685                 vendor = l[i].vendor;
  686                 device = l[i].device;
  687                 if(device == 0xffff) device = PCI_ANY_ID;
  688                 if(vendor == 0xffff) vendor = PCI_ANY_ID;
  689                 while ((pdev = pci_find_device(vendor, device, pdev))) {
  690                         num++;  /* FIXME: What about two cards of the same device id? */
  691                 }
  692         }
  693 #else
  694         num = DRIVER_NUM_CARDS;
  695 #endif
  696         DRM_DEBUG("numdevs = %d\n", num);
  697         return num;
  698 }
  699 
  700 /* drm_init is called via init_module at module load time, or via
  701  * linux/init/main.c (this is not currently supported).
  702  */
  703 #ifdef __linux__
  704 static int __init drm_init( void )
  705 #endif /* __linux__ */
  706 #ifdef __FreeBSD__
  707 static int DRM(init)( device_t nbdev )
  708 #endif /* __FreeBSD__ */
  709 {
  710 
  711         drm_device_t *dev;
  712         int i;
  713 #if __HAVE_CTX_BITMAP
  714         int retcode;
  715 #endif
  716         DRM_DEBUG( "\n" );
  717 
  718 #ifdef MODULE
  719         DRM(parse_options)( drm_opts );
  720 #endif
  721 
  722         DRM(numdevs) = drm_count_cards();
  723         /* Force at least one instance. */
  724         if (DRM(numdevs) <= 0)
  725                 DRM(numdevs) = 1;
  726 
  727         DRM(device) = DRM_OS_MALLOC(sizeof(*DRM(device)) * DRM(numdevs));
  728         if (!DRM(device)) {
  729                 return DRM_OS_ERR(ENOMEM);
  730         }
  731         DRM(minor) = DRM_OS_MALLOC(sizeof(*(DRM(minor))) * DRM(numdevs));
  732         if (!DRM(minor)) {
  733                 DRM_OS_FREE(DRM(device));
  734                 return DRM_OS_ERR(ENOMEM);
  735         }
  736 
  737         DRIVER_PREINIT();
  738 
  739 #ifdef __linux__
  740         DRM(mem_init)();
  741 #endif /* __linux__ */
  742 
  743         for (i = 0; i < DRM(numdevs); i++) {
  744 #ifdef __linux__
  745                 dev = &(DRM(device)[i]);
  746 #endif /* __linux__ */
  747 #ifdef __FreeBSD__
  748                 int unit = device_get_unit(nbdev);
  749                 /* FIXME??? - multihead !!! */
  750                 dev = device_get_softc(nbdev);
  751 #endif /* __FreeBSD__ */
  752                 memset( (void *)dev, 0, sizeof(*dev) );
  753 #ifdef __linux__
  754                 dev->count_lock = SPIN_LOCK_UNLOCKED;
  755                 sema_init( &dev->struct_sem, 1 );
  756                 if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
  757                         return -EPERM;
  758                 dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
  759                 dev->name   = DRIVER_NAME;
  760 #endif /* __linux__ */
  761 #ifdef __FreeBSD__
  762                 DRM(minor)[i]=unit;
  763                 DRM_OS_SPININIT(dev->count_lock, "drm device");
  764                 lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0);
  765                 dev->device = nbdev;
  766                 dev->devnode = make_dev( &DRM(cdevsw),
  767                                 unit,
  768                                 DRM_DEV_UID,
  769                                 DRM_DEV_GID,
  770                                 DRM_DEV_MODE,
  771                                 "dri/card%d", unit );
  772                 dev->name   = DRIVER_NAME;
  773                 DRM(mem_init)();
  774                 DRM(sysctl_init)(dev);
  775                 TAILQ_INIT(&dev->files);
  776 #endif /* __FreeBSD__ */
  777 
  778 #if __REALLY_HAVE_AGP
  779                 dev->agp = DRM(agp_init)();
  780 #if __MUST_HAVE_AGP
  781                 if ( dev->agp == NULL ) {
  782                         DRM_ERROR( "Cannot initialize the agpgart module.\n" );
  783 #ifdef __linux__
  784                         DRM(stub_unregister)(DRM(minor)[i]);
  785 #endif /* __linux__ */
  786 #ifdef __FreeBSD__
  787                         DRM(sysctl_cleanup)( dev );
  788                         destroy_dev(dev->devnode);
  789 #endif /* __FreeBSD__ */
  790                         DRM(takedown)( dev );
  791                         return DRM_OS_ERR(ENOMEM);
  792                 }
  793 #endif
  794 #if __REALLY_HAVE_MTRR
  795                 if (dev->agp)
  796                         dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
  797                                        dev->agp->agp_info.aper_size*1024*1024,
  798                                        MTRR_TYPE_WRCOMB,
  799                                        1 );
  800 #endif
  801 #endif
  802 
  803 #if __HAVE_CTX_BITMAP
  804                 retcode = DRM(ctxbitmap_init)( dev );
  805                 if( retcode ) {
  806                         DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
  807 #ifdef __linux__
  808                         DRM(stub_unregister)(DRM(minor)[i]);
  809 #endif /* __linux__ */
  810 #ifdef __FreeBSD__
  811                         DRM(sysctl_cleanup)( dev );
  812                         destroy_dev(dev->devnode);
  813 #endif /* __FreeBSD__ */
  814                         DRM(takedown)( dev );
  815                         return retcode;
  816                 }
  817 #endif
  818                 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
  819                         DRIVER_NAME,
  820                         DRIVER_MAJOR,
  821                         DRIVER_MINOR,
  822                         DRIVER_PATCHLEVEL,
  823                         DRIVER_DATE,
  824                         DRM(minor)[i] );
  825         }
  826 
  827         DRIVER_POSTINIT();
  828 
  829         return 0;
  830 }
  831 
  832 /* drm_cleanup is called via cleanup_module at module unload time.
  833  */
  834 #ifdef __linux__
  835 static void __exit drm_cleanup( void )
  836 #endif /* __linux__ */
  837 #ifdef __FreeBSD__
  838 static void DRM(cleanup)(device_t nbdev)
  839 #endif /* __FreeBSD__ */
  840 {
  841         drm_device_t *dev;
  842         int i;
  843 
  844         DRM_DEBUG( "\n" );
  845 
  846         for (i = DRM(numdevs) - 1; i >= 0; i--) {
  847 #ifdef __linux__
  848                 dev = &(DRM(device)[i]);
  849                 if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
  850                         DRM_ERROR( "Cannot unload module\n" );
  851                 } else {
  852                         DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
  853                         if (i == 0) {
  854                                 DRM_INFO( "Module unloaded\n" );
  855                         }
  856                 }
  857 #endif /* __linux__ */
  858 #ifdef __FreeBSD__
  859                 /* FIXME??? - multihead */
  860                 dev = device_get_softc(nbdev);
  861                 DRM(sysctl_cleanup)( dev );
  862                 destroy_dev(dev->devnode);
  863 #endif /* __FreeBSD__ */
  864 #if __HAVE_CTX_BITMAP
  865                 DRM(ctxbitmap_cleanup)( dev );
  866 #endif
  867 
  868 #if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
  869                 if ( dev->agp && dev->agp->agp_mtrr >= 0) {
  870                         int retval;
  871                         retval = mtrr_del( dev->agp->agp_mtrr,
  872                                    dev->agp->agp_info.aper_base,
  873                                    dev->agp->agp_info.aper_size*1024*1024 );
  874                         DRM_DEBUG( "mtrr_del=%d\n", retval );
  875                 }
  876 #endif
  877 
  878                 DRM(takedown)( dev );
  879 
  880 #if __REALLY_HAVE_AGP
  881                 if ( dev->agp ) {
  882                         DRM(agp_uninit)();
  883                         DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
  884                         dev->agp = NULL;
  885                 }
  886 #endif
  887         }
  888         DRIVER_POSTCLEANUP();
  889         DRM_OS_FREE(DRM(minor));
  890         DRM_OS_FREE(DRM(device));
  891         DRM(numdevs) = 0;
  892 }
  893 
  894 #ifdef __linux__
  895 module_init( drm_init );
  896 module_exit( drm_cleanup );
  897 #endif /* __linux__ */
  898 
  899 int DRM(version)( DRM_OS_IOCTL )
  900 {
  901         drm_version_t version;
  902         int len;
  903 
  904         DRM_OS_KRNFROMUSR( version, (drm_version_t *)data, sizeof(version) );
  905 
  906 #define DRM_COPY( name, value )                                         \
  907         len = strlen( value );                                          \
  908         if ( len > name##_len ) len = name##_len;                       \
  909         name##_len = strlen( value );                                   \
  910         if ( len && name ) {                                            \
  911                 if ( DRM_OS_COPYTOUSR( name, value, len ) )             \
  912                         return DRM_OS_ERR(EFAULT);                              \
  913         }
  914 
  915         version.version_major = DRIVER_MAJOR;
  916         version.version_minor = DRIVER_MINOR;
  917         version.version_patchlevel = DRIVER_PATCHLEVEL;
  918 
  919         DRM_COPY( version.name, DRIVER_NAME );
  920         DRM_COPY( version.date, DRIVER_DATE );
  921         DRM_COPY( version.desc, DRIVER_DESC );
  922 
  923         DRM_OS_KRNTOUSR( (drm_version_t *)data, version, sizeof(version) );
  924 
  925         return 0;
  926 }
  927 
  928 #ifdef __linux__
  929 int DRM(open)( struct inode *inode, struct file *filp )
  930 #endif /* __linux__ */
  931 #ifdef __FreeBSD__
  932 int DRM( open)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p)
  933 #endif /* __FreeBSD__ */
  934 {
  935         drm_device_t *dev = NULL;
  936         int retcode = 0;
  937         int i;
  938 
  939         for (i = 0; i < DRM(numdevs); i++) {
  940 #ifdef __linux__
  941                 if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
  942                         dev = &(DRM(device)[i]);
  943                         break;
  944                 }
  945 #endif /* __linux__ */
  946 #ifdef __FreeBSD__
  947                 /* FIXME ??? - multihead */
  948                 dev    = DRIVER_SOFTC(minor(kdev));
  949 #endif /* __FreeBSD__ */
  950         }
  951         if (!dev) {
  952                 return DRM_OS_ERR(ENODEV);
  953         }
  954 
  955         DRM_DEBUG( "open_count = %d\n", dev->open_count );
  956 
  957 #ifdef __linux__
  958         retcode = DRM(open_helper)( inode, filp, dev );
  959 #endif /* __linux__ */
  960 #ifdef __FreeBSD__
  961         device_busy(dev->device);
  962         retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
  963 #endif /* __FreeBSD__ */
  964 
  965         if ( !retcode ) {
  966                 atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
  967                 DRM_OS_SPINLOCK( &dev->count_lock );
  968                 if ( !dev->open_count++ ) {
  969                         DRM_OS_SPINUNLOCK( &dev->count_lock );
  970                         return DRM(setup)( dev );
  971                 }
  972                 DRM_OS_SPINUNLOCK( &dev->count_lock );
  973         }
  974 #ifdef __FreeBSD__
  975         device_unbusy(dev->device);
  976 #endif /* __FreeBSD__ */
  977 
  978         return retcode;
  979 }
  980 
  981 #ifdef __linux__
  982 int DRM(release)( struct inode *inode, struct file *filp )
  983 {
  984         drm_file_t *priv = filp->private_data;
  985         drm_device_t *dev;
  986 #endif /* __linux__ */
  987 #ifdef __FreeBSD__
  988 int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p)
  989 {
  990         drm_file_t *priv;
  991         drm_device_t  *dev    = kdev->si_drv1;
  992 #endif /* __FreeBSD__ */
  993         int retcode = 0;
  994 
  995 #ifdef __linux__
  996         lock_kernel();
  997         dev = priv->dev;
  998 #endif /* __linux__ */
  999         DRM_DEBUG( "open_count = %d\n", dev->open_count );
 1000 #ifdef __FreeBSD__
 1001         priv = DRM(find_file_by_proc)(dev, p);
 1002         if (!priv) {
 1003                 DRM_DEBUG("can't find authenticator\n");
 1004                 return EINVAL;
 1005         }
 1006 #endif /* __FreeBSD__ */
 1007 
 1008         DRIVER_PRERELEASE();
 1009 
 1010         /* ========================================================
 1011          * Begin inline drm_release
 1012          */
 1013 
 1014         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
 1015                    DRM_OS_CURRENTPID, (long)dev->device, dev->open_count );
 1016 
 1017         if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
 1018             && dev->lock.pid == DRM_OS_CURRENTPID) {
 1019                 DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
 1020                           DRM_OS_CURRENTPID,
 1021                           _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 1022 #if HAVE_DRIVER_RELEASE
 1023                 DRIVER_RELEASE();
 1024 #endif
 1025                 DRM(lock_free)(dev,
 1026                               &dev->lock.hw_lock->lock,
 1027                               _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 1028                 
 1029                                 /* FIXME: may require heavy-handed reset of
 1030                                    hardware at this point, possibly
 1031                                    processed via a callback to the X
 1032                                    server. */
 1033         }
 1034 #if __HAVE_RELEASE
 1035         else if ( dev->lock.hw_lock ) {
 1036                 /* The lock is required to reclaim buffers */
 1037 #ifdef __linux__
 1038                 DECLARE_WAITQUEUE( entry, current );
 1039                 add_wait_queue( &dev->lock.lock_queue, &entry );
 1040 #endif /* __linux__ */
 1041                 for (;;) {
 1042 #ifdef __linux__
 1043                         current->state = TASK_INTERRUPTIBLE;
 1044 #endif /* __linux__ */
 1045                         if ( !dev->lock.hw_lock ) {
 1046                                 /* Device has been unregistered */
 1047                                 retcode = DRM_OS_ERR(EINTR);
 1048                                 break;
 1049                         }
 1050                         if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
 1051                                              DRM_KERNEL_CONTEXT ) ) {
 1052 #ifdef __linux__
 1053                                 dev->lock.pid       = priv->pid;
 1054 #endif /* __linux__ */
 1055 #ifdef __FreeBSD__
 1056                                 dev->lock.pid       = p->p_pid;
 1057 #endif /* __FreeBSD__ */
 1058                                 dev->lock.lock_time = jiffies;
 1059                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
 1060                                 break;  /* Got lock */
 1061                         }
 1062                                 /* Contention */
 1063 #if 0
 1064                         atomic_inc( &dev->total_sleeps );
 1065 #endif
 1066 #ifdef __linux__
 1067                         schedule();
 1068                         if ( signal_pending( current ) ) {
 1069                                 retcode = DRM_OS_ERR(ERESTARTSYS);
 1070                                 break;
 1071                         }
 1072 #endif /* __linux__ */
 1073 #ifdef __FreeBSD__
 1074                         retcode = tsleep(&dev->lock.lock_queue,
 1075                                         PZERO|PCATCH,
 1076                                         "drmlk2",
 1077                                         0);
 1078                         if (retcode)
 1079                                 break;
 1080 #endif /* __FreeBSD__ */
 1081                 }
 1082 #ifdef __linux__
 1083                 current->state = TASK_RUNNING;
 1084                 remove_wait_queue( &dev->lock.lock_queue, &entry );
 1085 #endif /* __linux__ */
 1086                 if( !retcode ) {
 1087                         DRIVER_RELEASE();
 1088                         DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 1089                                         DRM_KERNEL_CONTEXT );
 1090                 }
 1091         }
 1092 #elif __HAVE_DMA
 1093         DRM(reclaim_buffers)( dev, priv->pid );
 1094 #endif
 1095 
 1096 #ifdef __linux__
 1097         DRM(fasync)( -1, filp, 0 );
 1098 #endif /* __linux__ */
 1099 #ifdef __FreeBSD__
 1100         funsetown(&dev->buf_sigio);
 1101 #endif /* __FreeBSD__ */
 1102 
 1103         DRM_OS_LOCK;
 1104 #ifdef __linux__
 1105         if ( priv->remove_auth_on_close == 1 ) {
 1106                 drm_file_t *temp = dev->file_first;
 1107                 while ( temp ) {
 1108                         temp->authenticated = 0;
 1109                         temp = temp->next;
 1110                 }
 1111         }
 1112         if ( priv->prev ) {
 1113                 priv->prev->next = priv->next;
 1114         } else {
 1115                 dev->file_first  = priv->next;
 1116         }
 1117         if ( priv->next ) {
 1118                 priv->next->prev = priv->prev;
 1119         } else {
 1120                 dev->file_last   = priv->prev;
 1121         }
 1122 #endif /* __linux__ */
 1123 #ifdef __FreeBSD__
 1124         priv = DRM(find_file_by_proc)(dev, p);
 1125         if (priv) {
 1126                 priv->refs--;
 1127                 if (!priv->refs) {
 1128                         TAILQ_REMOVE(&dev->files, priv, link);
 1129                 }
 1130         }
 1131 #endif /* __FreeBSD__ */
 1132         DRM_OS_UNLOCK;
 1133 
 1134         DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
 1135 
 1136         /* ========================================================
 1137          * End inline drm_release
 1138          */
 1139 
 1140         atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
 1141         DRM_OS_SPINLOCK( &dev->count_lock );
 1142         if ( !--dev->open_count ) {
 1143                 if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
 1144                         DRM_ERROR( "Device busy: %ld %d\n",
 1145                                 (unsigned long)atomic_read( &dev->ioctl_count ),
 1146                                    dev->blocked );
 1147                         DRM_OS_SPINUNLOCK( &dev->count_lock );
 1148 #ifdef __linux__
 1149                         unlock_kernel();
 1150 #endif /* __linux__ */
 1151                         return DRM_OS_ERR(EBUSY);
 1152                 }
 1153                 DRM_OS_SPINUNLOCK( &dev->count_lock );
 1154 #ifdef __linux__
 1155                 unlock_kernel();
 1156 #endif /* __linux__ */
 1157 #ifdef __FreeBSD__
 1158                 device_unbusy(dev->device);
 1159 #endif /* __FreeBSD__ */
 1160                 return DRM(takedown)( dev );
 1161         }
 1162         DRM_OS_SPINUNLOCK( &dev->count_lock );
 1163 
 1164 #ifdef __linux__
 1165         unlock_kernel();
 1166 #endif /* __linux__ */
 1167         
 1168         return retcode;
 1169 }
 1170 
 1171 /* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
 1172  */
 1173 int DRM(ioctl)( DRM_OS_IOCTL )
 1174 {
 1175         DRM_OS_DEVICE;
 1176         int retcode = 0;
 1177         drm_ioctl_desc_t *ioctl;
 1178         drm_ioctl_t *func;
 1179         int nr = DRM_IOCTL_NR(cmd);
 1180         DRM_OS_PRIV;
 1181 
 1182         atomic_inc( &dev->ioctl_count );
 1183         atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
 1184         ++priv->ioctl_count;
 1185 
 1186         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
 1187                  DRM_OS_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
 1188 
 1189 #ifdef __FreeBSD__
 1190         switch (cmd) {
 1191         case FIONBIO:
 1192                 atomic_dec(&dev->ioctl_count);
 1193                 return 0;
 1194 
 1195         case FIOASYNC:
 1196                 atomic_dec(&dev->ioctl_count);
 1197                 dev->flags |= FASYNC;
 1198                 return 0;
 1199 
 1200         case FIOSETOWN:
 1201                 atomic_dec(&dev->ioctl_count);
 1202                 return fsetown(*(int *)data, &dev->buf_sigio);
 1203 
 1204         case FIOGETOWN:
 1205                 atomic_dec(&dev->ioctl_count);
 1206                 *(int *) data = fgetown(&dev->buf_sigio);
 1207                 return 0;
 1208         }
 1209 #endif /* __FreeBSD__ */
 1210 
 1211         if ( nr >= DRIVER_IOCTL_COUNT ) {
 1212                 retcode = DRM_OS_ERR(EINVAL);
 1213         } else {
 1214                 ioctl = &DRM(ioctls)[nr];
 1215                 func = ioctl->func;
 1216 
 1217                 if ( !func ) {
 1218                         DRM_DEBUG( "no function\n" );
 1219                         retcode = DRM_OS_ERR(EINVAL);
 1220                 } else if ( ( ioctl->root_only && DRM_OS_CHECKSUSER ) 
 1221                          || ( ioctl->auth_needed && !priv->authenticated ) ) {
 1222                         retcode = DRM_OS_ERR(EACCES);
 1223                 } else {
 1224                         retcode = func( IOCTL_ARGS_PASS );
 1225                 }
 1226         }
 1227 
 1228         atomic_dec( &dev->ioctl_count );
 1229         return retcode;
 1230 }
 1231 
 1232 int DRM(lock)( DRM_OS_IOCTL )
 1233 {
 1234         DRM_OS_DEVICE;
 1235 #ifdef __linux__
 1236         DECLARE_WAITQUEUE( entry, current );
 1237 #endif /* __linux__ */
 1238         drm_lock_t lock;
 1239         int ret = 0;
 1240 #if __HAVE_MULTIPLE_DMA_QUEUES
 1241         drm_queue_t *q;
 1242 #endif
 1243 #if __HAVE_DMA_HISTOGRAM
 1244         cycles_t start;
 1245 
 1246         dev->lck_start = start = get_cycles();
 1247 #endif
 1248 
 1249         DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) );
 1250 
 1251         if ( lock.context == DRM_KERNEL_CONTEXT ) {
 1252                 DRM_ERROR( "Process %d using kernel context %d\n",
 1253                            DRM_OS_CURRENTPID, lock.context );
 1254                 return DRM_OS_ERR(EINVAL);
 1255         }
 1256 
 1257         DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
 1258                    lock.context, DRM_OS_CURRENTPID,
 1259                    dev->lock.hw_lock->lock, lock.flags );
 1260 
 1261 #if __HAVE_DMA_QUEUE
 1262         if ( lock.context < 0 )
 1263                 return DRM_OS_ERR(EINVAL);
 1264 #elif __HAVE_MULTIPLE_DMA_QUEUES
 1265         if ( lock.context < 0 || lock.context >= dev->queue_count )
 1266                 return DRM_OS_ERR(EINVAL);
 1267         q = dev->queuelist[lock.context];
 1268 #endif
 1269 
 1270 #if __HAVE_DMA_FLUSH
 1271         ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags );
 1272 #endif
 1273         if ( !ret ) {
 1274 #ifdef __linux__
 1275                 add_wait_queue( &dev->lock.lock_queue, &entry );
 1276 #endif /* __linux__ */
 1277                 for (;;) {
 1278 #ifdef __linux__
 1279                         current->state = TASK_INTERRUPTIBLE;
 1280 #endif /* __linux__ */
 1281                         if ( !dev->lock.hw_lock ) {
 1282                                 /* Device has been unregistered */
 1283                                 ret = DRM_OS_ERR(EINTR);
 1284                                 break;
 1285                         }
 1286                         if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
 1287                                              lock.context ) ) {
 1288                                 dev->lock.pid       = DRM_OS_CURRENTPID;
 1289                                 dev->lock.lock_time = jiffies;
 1290                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
 1291                                 break;  /* Got lock */
 1292                         }
 1293 
 1294                                 /* Contention */
 1295 #ifdef __linux__
 1296                         schedule();
 1297                         if ( signal_pending( current ) ) {
 1298                                 ret = DRM_OS_ERR(ERESTARTSYS);
 1299                                 break;
 1300                         }
 1301 #endif /* __linux__ */
 1302 #ifdef __FreeBSD__
 1303                         ret = tsleep(&dev->lock.lock_queue,
 1304                                         PZERO|PCATCH,
 1305                                         "drmlk2",
 1306                                         0);
 1307                         if (ret)
 1308                                 break;
 1309 #endif /* __FreeBSD__ */
 1310                 }
 1311 #ifdef __linux__
 1312                 current->state = TASK_RUNNING;
 1313                 remove_wait_queue( &dev->lock.lock_queue, &entry );
 1314 #endif /* __linux__ */
 1315         }
 1316 
 1317 #if __HAVE_DMA_FLUSH
 1318         DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */
 1319 #endif
 1320 
 1321         if ( !ret ) {
 1322 #ifdef __linux__
 1323                 sigemptyset( &dev->sigmask );
 1324                 sigaddset( &dev->sigmask, SIGSTOP );
 1325                 sigaddset( &dev->sigmask, SIGTSTP );
 1326                 sigaddset( &dev->sigmask, SIGTTIN );
 1327                 sigaddset( &dev->sigmask, SIGTTOU );
 1328                 dev->sigdata.context = lock.context;
 1329                 dev->sigdata.lock    = dev->lock.hw_lock;
 1330                 block_all_signals( DRM(notifier),
 1331                                    &dev->sigdata, &dev->sigmask );
 1332 #endif /* __linux__ */
 1333 
 1334 #if __HAVE_DMA_READY
 1335                 if ( lock.flags & _DRM_LOCK_READY ) {
 1336                         DRIVER_DMA_READY();
 1337                 }
 1338 #endif
 1339 #if __HAVE_DMA_QUIESCENT
 1340                 if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
 1341                         DRIVER_DMA_QUIESCENT();
 1342                 }
 1343 #endif
 1344 #if __HAVE_KERNEL_CTX_SWITCH
 1345                 if ( dev->last_context != lock.context ) {
 1346                         DRM(context_switch)(dev, dev->last_context,
 1347                                             lock.context);
 1348                 }
 1349 #endif
 1350         }
 1351 
 1352         DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
 1353 
 1354 #if __HAVE_DMA_HISTOGRAM
 1355         atomic_inc(&dev->histo.lacq[DRM(histogram_slot)(get_cycles()-start)]);
 1356 #endif
 1357 
 1358         return ret;
 1359 }
 1360 
 1361 
 1362 int DRM(unlock)( DRM_OS_IOCTL )
 1363 {
 1364         DRM_OS_DEVICE;
 1365         drm_lock_t lock;
 1366 
 1367         DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) ) ;
 1368 
 1369         if ( lock.context == DRM_KERNEL_CONTEXT ) {
 1370                 DRM_ERROR( "Process %d using kernel context %d\n",
 1371                            DRM_OS_CURRENTPID, lock.context );
 1372                 return DRM_OS_ERR(EINVAL);
 1373         }
 1374 
 1375         atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
 1376 
 1377 #if __HAVE_KERNEL_CTX_SWITCH
 1378         /* We no longer really hold it, but if we are the next
 1379          * agent to request it then we should just be able to
 1380          * take it immediately and not eat the ioctl.
 1381          */
 1382         dev->lock.pid = 0;
 1383         {
 1384                 __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
 1385                 unsigned int old, new, prev, ctx;
 1386 
 1387                 ctx = lock.context;
 1388                 do {
 1389                         old  = *plock;
 1390                         new  = ctx;
 1391                         prev = cmpxchg(plock, old, new);
 1392                 } while (prev != old);
 1393         }
 1394         wake_up_interruptible(&dev->lock.lock_queue);
 1395 #else
 1396         DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
 1397                             DRM_KERNEL_CONTEXT );
 1398 #if __HAVE_DMA_SCHEDULE
 1399         DRM(dma_schedule)( dev, 1 );
 1400 #endif
 1401 
 1402         /* FIXME: Do we ever really need to check this???
 1403          */
 1404         if ( 1 /* !dev->context_flag */ ) {
 1405                 if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 1406                                      DRM_KERNEL_CONTEXT ) ) {
 1407                         DRM_ERROR( "\n" );
 1408                 }
 1409         }
 1410 #endif /* !__HAVE_KERNEL_CTX_SWITCH */
 1411 
 1412 #ifdef __linux__
 1413         unblock_all_signals();
 1414 #endif /* __linux__ */
 1415         return 0;
 1416 }
 1417 
 1418 #if DRM_LINUX
 1419 #define LINUX_IOCTL_DRM_MIN             0x6400
 1420 #define LINUX_IOCTL_DRM_MAX             0x64ff
 1421 
 1422 static linux_ioctl_function_t DRM( linux_ioctl);
 1423 static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
 1424 SYSINIT  (DRM( register),   SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
 1425 SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
 1426 
 1427 #define LINUX_IOC_VOID  IOC_VOID
 1428 #define LINUX_IOC_IN    IOC_OUT         /* Linux has the values the other way around */
 1429 #define LINUX_IOC_OUT   IOC_IN
 1430 
 1431 /*
 1432  * Linux emulation IOCTL
 1433  */
 1434 static int
 1435 DRM(linux_ioctl)(DRM_OS_STRUCTPROC *p, struct linux_ioctl_args* args)
 1436 {
 1437         u_long          cmd = args->cmd;
 1438 #define STK_PARAMS      128
 1439         union {
 1440             char stkbuf[STK_PARAMS];
 1441             long align;
 1442         } ubuf;
 1443         caddr_t         data=NULL, memp=NULL;
 1444         u_int           size = IOCPARM_LEN(cmd);
 1445         int             error;
 1446 #if (__FreeBSD_version >= 500000)
 1447         struct file     *fp;
 1448 #else
 1449         struct file     *fp = p->p_fd->fd_ofiles[args->fd];
 1450 #endif
 1451         if ( size > STK_PARAMS ) {
 1452                 if ( size > IOCPARM_MAX )
 1453                         return EINVAL;
 1454                 memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
 1455                 data = memp;
 1456         } else {
 1457                 data = ubuf.stkbuf;
 1458         }
 1459 
 1460         if ( cmd & LINUX_IOC_IN ) {
 1461                 if ( size ) {
 1462                         error = copyin( (caddr_t)args->arg, data, (u_int)size );
 1463                         if (error) {
 1464                                 if ( memp )
 1465                                         free( data, DRM(M_DRM) );
 1466                                 return error;
 1467                         }
 1468                 } else {
 1469                         data = (caddr_t)args->arg;
 1470                 }
 1471         } else if ( (cmd & LINUX_IOC_OUT) && size ) {
 1472                 /*
 1473                  * Zero the buffer so the user always
 1474                  * gets back something deterministic.
 1475                  */
 1476                 bzero( data, size );
 1477         } else if ( cmd & LINUX_IOC_VOID ) {
 1478                 *(caddr_t *)data = (caddr_t)args->arg;
 1479         }
 1480 
 1481 #if (__FreeBSD_version >= 500000)
 1482         if ( (error = fget( p, args->fd, &fp )) != 0 ) {
 1483                 if ( memp )
 1484                         free( memp, DRM(M_DRM) );
 1485                 return (error);
 1486         }
 1487         error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
 1488         fdrop( fp, p );
 1489 #else
 1490         error = fo_ioctl( fp, cmd, data, p );
 1491 #endif
 1492         if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
 1493                 error = copyout( data, (caddr_t)args->arg, (u_int)size );
 1494         if ( memp )
 1495                 free( memp, DRM(M_DRM) );
 1496         return error;
 1497 }
 1498 #endif /* DRM_LINUX */

Cache object: 8b6d1040fb4a1c9bb25c1cb7e3924150


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