1 /* drm_dma.c -- DMA IOCTL and function support
2 * Created: Fri Oct 18 2003 by anholt@FreeBSD.org
5 * Copyright 2003 Eric Anholt
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:
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
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.
27 * Eric Anholt <anholt@FreeBSD.org>
32 #include "dev/drm/drmP.h"
33 #include "dev/drm/drm.h"
35 int drm_irq_by_busid(DRM_IOCTL_ARGS)
40 DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
42 if ((irq.busnum >> 8) != dev->pci_domain ||
43 (irq.busnum & 0xff) != dev->pci_bus ||
44 irq.devnum != dev->pci_slot ||
45 irq.funcnum != dev->pci_func)
50 DRM_DEBUG("%d:%d:%d => IRQ %d\n",
51 irq.busnum, irq.devnum, irq.funcnum, irq.irq);
53 DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
58 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
60 drm_irq_handler_wrap(DRM_IRQ_ARGS)
62 drm_device_t *dev = (drm_device_t *)arg;
64 DRM_SPINLOCK(&dev->irq_lock);
65 dev->irq_handler(arg);
66 DRM_SPINUNLOCK(&dev->irq_lock);
70 int drm_irq_install(drm_device_t *dev)
74 if (dev->irq == 0 || dev->dev_private == NULL)
75 return DRM_ERR(EINVAL);
77 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
80 if (dev->irq_enabled) {
82 return DRM_ERR(EBUSY);
86 dev->context_flag = 0;
88 DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
90 /* Before installing handler */
91 dev->irq_preinstall(dev);
97 dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ,
98 &dev->irqrid, RF_SHAREABLE);
103 #if __FreeBSD_version < 500000
104 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
105 dev->irq_handler, dev, &dev->irqh);
107 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
108 drm_irq_handler_wrap, dev, &dev->irqh);
112 #elif defined(__NetBSD__) || defined(__OpenBSD__)
113 if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
117 dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY,
118 (irqreturn_t (*)(DRM_IRQ_ARGS))dev->irq_handler, dev);
125 /* After installing handler */
127 dev->irq_postinstall(dev);
133 dev->irq_enabled = 0;
135 if (dev->irqrid != 0) {
136 bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
141 DRM_SPINUNINIT(dev->irq_lock);
146 int drm_irq_uninstall(drm_device_t *dev)
150 if (!dev->irq_enabled)
151 return DRM_ERR(EINVAL);
153 dev->irq_enabled = 0;
154 irqrid = dev->irqrid;
157 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
159 dev->irq_uninstall(dev);
163 bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
164 bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr);
166 #elif defined(__NetBSD__) || defined(__OpenBSD__)
167 pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
169 DRM_SPINUNINIT(dev->irq_lock);
174 int drm_control(DRM_IOCTL_ARGS)
180 DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
182 switch ( ctl.func ) {
183 case DRM_INST_HANDLER:
184 /* Handle drivers whose DRM used to require IRQ setup but the
189 if (dev->if_version < DRM_IF_VERSION(1, 2) &&
191 return DRM_ERR(EINVAL);
192 return drm_irq_install(dev);
193 case DRM_UNINST_HANDLER:
197 err = drm_irq_uninstall(dev);
201 return DRM_ERR(EINVAL);
205 int drm_wait_vblank(DRM_IOCTL_ARGS)
208 drm_wait_vblank_t vblwait;
212 if (!dev->irq_enabled)
213 return DRM_ERR(EINVAL);
215 DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
218 if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
219 vblwait.request.sequence += atomic_read(&dev->vbl_received);
220 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
223 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
224 if (flags & _DRM_VBLANK_SIGNAL) {
226 drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM,
231 vbl_sig->sequence = vblwait.request.sequence;
232 vbl_sig->signo = vblwait.request.signal;
233 vbl_sig->pid = DRM_CURRENTPID;
235 vblwait.reply.sequence = atomic_read(&dev->vbl_received);
237 DRM_SPINLOCK(&dev->irq_lock);
238 TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
239 DRM_SPINUNLOCK(&dev->irq_lock);
245 ret = dev->vblank_wait(dev, &vblwait.request.sequence);
249 vblwait.reply.tval_sec = now.tv_sec;
250 vblwait.reply.tval_usec = now.tv_usec;
253 DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
259 void drm_vbl_send_signals(drm_device_t *dev)
264 void drm_vbl_send_signals( drm_device_t *dev )
266 drm_vbl_sig_t *vbl_sig;
267 unsigned int vbl_seq = atomic_read( &dev->vbl_received );
270 vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
271 while (vbl_sig != NULL) {
272 drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
274 if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
275 p = pfind(vbl_sig->pid);
277 psignal(p, vbl_sig->signo);
279 TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
280 DRM_FREE(vbl_sig,sizeof(*vbl_sig));