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_irq.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_irq.c -- IRQ IOCTL and function support
    2  * Created: Fri Oct 18 2003 by anholt@FreeBSD.org
    3  */
    4 /*-
    5  * Copyright 2003 Eric Anholt
    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  * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   23  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   25  *
   26  * Authors:
   27  *    Eric Anholt <anholt@FreeBSD.org>
   28  *
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/6.4/sys/dev/drm/drm_irq.c 153401 2005-12-14 00:52:59Z anholt $");
   33 
   34 #include "dev/drm/drmP.h"
   35 #include "dev/drm/drm.h"
   36 
   37 int drm_irq_by_busid(DRM_IOCTL_ARGS)
   38 {
   39         DRM_DEVICE;
   40         drm_irq_busid_t irq;
   41 
   42         DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
   43 
   44         if ((irq.busnum >> 8) != dev->pci_domain ||
   45             (irq.busnum & 0xff) != dev->pci_bus ||
   46             irq.devnum != dev->pci_slot ||
   47             irq.funcnum != dev->pci_func)
   48                 return EINVAL;
   49 
   50         irq.irq = dev->irq;
   51 
   52         DRM_DEBUG("%d:%d:%d => IRQ %d\n",
   53                   irq.busnum, irq.devnum, irq.funcnum, irq.irq);
   54 
   55         DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
   56 
   57         return 0;
   58 }
   59 
   60 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
   61 static irqreturn_t
   62 drm_irq_handler_wrap(DRM_IRQ_ARGS)
   63 {
   64         drm_device_t *dev = (drm_device_t *)arg;
   65 
   66         DRM_SPINLOCK(&dev->irq_lock);
   67         dev->driver.irq_handler(arg);
   68         DRM_SPINUNLOCK(&dev->irq_lock);
   69 }
   70 #endif
   71 
   72 int drm_irq_install(drm_device_t *dev)
   73 {
   74         int retcode;
   75 #ifdef __NetBSD__
   76         pci_intr_handle_t ih;
   77 #endif
   78 
   79         if (dev->irq == 0 || dev->dev_private == NULL)
   80                 return DRM_ERR(EINVAL);
   81 
   82         DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
   83 
   84         DRM_LOCK();
   85         if (dev->irq_enabled) {
   86                 DRM_UNLOCK();
   87                 return DRM_ERR(EBUSY);
   88         }
   89         dev->irq_enabled = 1;
   90 
   91         dev->context_flag = 0;
   92 
   93         DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
   94 
   95                                 /* Before installing handler */
   96         dev->driver.irq_preinstall(dev);
   97         DRM_UNLOCK();
   98 
   99                                 /* Install handler */
  100 #ifdef __FreeBSD__
  101         dev->irqrid = 0;
  102         dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, 
  103                                       &dev->irqrid, RF_SHAREABLE);
  104         if (!dev->irqr) {
  105                 retcode = ENOENT;
  106                 goto err;
  107         }
  108 #if __FreeBSD_version < 500000
  109         retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
  110                                  dev->irq_handler, dev, &dev->irqh);
  111 #else
  112         retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
  113                                  drm_irq_handler_wrap, dev, &dev->irqh);
  114 #endif
  115         if (retcode != 0)
  116                 goto err;
  117 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  118         if (pci_intr_map(&dev->pa, &ih) != 0) {
  119                 retcode = ENOENT;
  120                 goto err;
  121         }
  122         dev->irqh = pci_intr_establish(&dev->pa.pa_pc, ih, IPL_TTY,
  123             (irqreturn_t (*)(void *))dev->irq_handler, dev);
  124         if (!dev->irqh) {
  125                 retcode = ENOENT;
  126                 goto err;
  127         }
  128 #endif
  129 
  130                                 /* After installing handler */
  131         DRM_LOCK();
  132         dev->driver.irq_postinstall(dev);
  133         DRM_UNLOCK();
  134 
  135         return 0;
  136 err:
  137         DRM_LOCK();
  138         dev->irq_enabled = 0;
  139 #ifdef ___FreeBSD__
  140         if (dev->irqrid != 0) {
  141                 bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
  142                     dev->irqr);
  143                 dev->irqrid = 0;
  144         }
  145 #endif
  146         DRM_SPINUNINIT(dev->irq_lock);
  147         DRM_UNLOCK();
  148         return retcode;
  149 }
  150 
  151 int drm_irq_uninstall(drm_device_t *dev)
  152 {
  153 #ifdef __FreeBSD__
  154         int irqrid;
  155 #endif
  156 
  157         if (!dev->irq_enabled)
  158                 return DRM_ERR(EINVAL);
  159 
  160         dev->irq_enabled = 0;
  161 #ifdef __FreeBSD__
  162         irqrid = dev->irqrid;
  163         dev->irqrid = 0;
  164 #endif
  165 
  166         DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
  167 
  168         dev->driver.irq_uninstall(dev);
  169 
  170 #ifdef __FreeBSD__
  171         DRM_UNLOCK();
  172         bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
  173         bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr);
  174         DRM_LOCK();
  175 #elif defined(__NetBSD__) || defined(__OpenBSD__)
  176         pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
  177 #endif
  178         DRM_SPINUNINIT(dev->irq_lock);
  179 
  180         return 0;
  181 }
  182 
  183 int drm_control(DRM_IOCTL_ARGS)
  184 {
  185         DRM_DEVICE;
  186         drm_control_t ctl;
  187         int err;
  188 
  189         DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
  190 
  191         switch ( ctl.func ) {
  192         case DRM_INST_HANDLER:
  193                 /* Handle drivers whose DRM used to require IRQ setup but the
  194                  * no longer does.
  195                  */
  196                 if (!dev->driver.use_irq)
  197                         return 0;
  198                 if (dev->if_version < DRM_IF_VERSION(1, 2) &&
  199                     ctl.irq != dev->irq)
  200                         return DRM_ERR(EINVAL);
  201                 return drm_irq_install(dev);
  202         case DRM_UNINST_HANDLER:
  203                 if (!dev->driver.use_irq)
  204                         return 0;
  205                 DRM_LOCK();
  206                 err = drm_irq_uninstall(dev);
  207                 DRM_UNLOCK();
  208                 return err;
  209         default:
  210                 return DRM_ERR(EINVAL);
  211         }
  212 }
  213 
  214 int drm_wait_vblank(DRM_IOCTL_ARGS)
  215 {
  216         DRM_DEVICE;
  217         drm_wait_vblank_t vblwait;
  218         struct timeval now;
  219         int ret;
  220 
  221         if (!dev->irq_enabled)
  222                 return DRM_ERR(EINVAL);
  223 
  224         DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
  225                                   sizeof(vblwait) );
  226 
  227         if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
  228                 vblwait.request.sequence += atomic_read(&dev->vbl_received);
  229                 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
  230         }
  231 
  232         flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
  233         if (flags & _DRM_VBLANK_SIGNAL) {
  234 #if 0 /* disabled */
  235                 drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM,
  236                     M_NOWAIT | M_ZERO);
  237                 if (vbl_sig == NULL)
  238                         return ENOMEM;
  239 
  240                 vbl_sig->sequence = vblwait.request.sequence;
  241                 vbl_sig->signo = vblwait.request.signal;
  242                 vbl_sig->pid = DRM_CURRENTPID;
  243 
  244                 vblwait.reply.sequence = atomic_read(&dev->vbl_received);
  245                 
  246                 DRM_SPINLOCK(&dev->irq_lock);
  247                 TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
  248                 DRM_SPINUNLOCK(&dev->irq_lock);
  249                 ret = 0;
  250 #endif
  251                 ret = EINVAL;
  252         } else {
  253                 DRM_LOCK();
  254                 ret = dev->driver.vblank_wait(dev, &vblwait.request.sequence);
  255                 DRM_UNLOCK();
  256 
  257                 microtime(&now);
  258                 vblwait.reply.tval_sec = now.tv_sec;
  259                 vblwait.reply.tval_usec = now.tv_usec;
  260         }
  261 
  262         DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
  263                                 sizeof(vblwait) );
  264 
  265         return ret;
  266 }
  267 
  268 void drm_vbl_send_signals(drm_device_t *dev)
  269 {
  270 }
  271 
  272 #if 0 /* disabled */
  273 void drm_vbl_send_signals( drm_device_t *dev )
  274 {
  275         drm_vbl_sig_t *vbl_sig;
  276         unsigned int vbl_seq = atomic_read( &dev->vbl_received );
  277         struct proc *p;
  278 
  279         vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
  280         while (vbl_sig != NULL) {
  281                 drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
  282 
  283                 if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
  284                         p = pfind(vbl_sig->pid);
  285                         if (p != NULL)
  286                                 psignal(p, vbl_sig->signo);
  287 
  288                         TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
  289                         DRM_FREE(vbl_sig,sizeof(*vbl_sig));
  290                 }
  291                 vbl_sig = next;
  292         }
  293 }
  294 #endif

Cache object: 7a7805f7650914db6decf978e6908d83


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