1 /* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
2 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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 * 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.
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
31 * $FreeBSD: src/sys/dev/drm/drm_dma.h,v 1.5.2.1 2003/04/26 07:05:28 anholt Exp $
34 #include "dev/drm/drmP.h"
36 #ifndef __HAVE_DMA_WAITQUEUE
37 #define __HAVE_DMA_WAITQUEUE 0
39 #ifndef __HAVE_DMA_RECLAIM
40 #define __HAVE_DMA_RECLAIM 0
42 #ifndef __HAVE_SHARED_IRQ
43 #define __HAVE_SHARED_IRQ 0
48 int DRM(dma_setup)( drm_device_t *dev )
52 dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER );
54 return DRM_ERR(ENOMEM);
56 memset( dev->dma, 0, sizeof(*dev->dma) );
58 for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
59 memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
64 void DRM(dma_takedown)(drm_device_t *dev)
66 drm_device_dma_t *dma = dev->dma;
71 /* Clear dma buffers */
72 for (i = 0; i <= DRM_MAX_ORDER; i++) {
73 if (dma->bufs[i].seg_count) {
74 DRM_DEBUG("order %d: buf_count = %d,"
77 dma->bufs[i].buf_count,
78 dma->bufs[i].seg_count);
79 for (j = 0; j < dma->bufs[i].seg_count; j++) {
80 DRM(free)((void *)dma->bufs[i].seglist[j],
81 dma->bufs[i].buf_size,
84 DRM(free)(dma->bufs[i].seglist,
85 dma->bufs[i].seg_count
86 * sizeof(*dma->bufs[0].seglist),
89 if(dma->bufs[i].buf_count) {
90 for(j = 0; j < dma->bufs[i].buf_count; j++) {
91 if(dma->bufs[i].buflist[j].dev_private) {
92 DRM(free)(dma->bufs[i].buflist[j].dev_private,
93 dma->bufs[i].buflist[j].dev_priv_size,
97 DRM(free)(dma->bufs[i].buflist,
98 dma->bufs[i].buf_count *
99 sizeof(*dma->bufs[0].buflist),
105 DRM(free)(dma->buflist,
106 dma->buf_count * sizeof(*dma->buflist),
111 DRM(free)(dma->pagelist,
112 dma->page_count * sizeof(*dma->pagelist),
115 DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
120 void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
129 #if !__HAVE_DMA_RECLAIM
130 void DRM(reclaim_buffers)(drm_device_t *dev, DRMFILE filp)
132 drm_device_dma_t *dma = dev->dma;
136 for (i = 0; i < dma->buf_count; i++) {
137 if (dma->buflist[i]->filp == filp) {
138 switch (dma->buflist[i]->list) {
140 DRM(free_buffer)(dev, dma->buflist[i]);
143 dma->buflist[i]->list = DRM_LIST_RECLAIM;
146 /* Buffer already on hardware. */
157 int DRM(irq_install)( drm_device_t *dev, int irq )
162 return DRM_ERR(EINVAL);
167 return DRM_ERR(EBUSY);
172 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
174 dev->context_flag = 0;
176 dev->dma->next_buffer = NULL;
177 dev->dma->this_buffer = NULL;
179 #if __HAVE_DMA_IRQ_BH
180 TASK_INIT(&dev->task, 0, DRM(dma_immediate_bh), dev);
183 #if __HAVE_VBL_IRQ && 0 /* disabled */
184 DRM_SPININIT( dev->vbl_lock, "vblsig" );
185 TAILQ_INIT( &dev->vbl_sig_list );
188 /* Before installing handler */
189 DRM(driver_irq_preinstall)( dev );
191 /* Install handler */
194 dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid,
195 0, ~0, 1, RF_SHAREABLE);
197 #elif defined(__NetBSD__)
198 if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
208 #if __FreeBSD_version < 500000
209 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
210 DRM(dma_service), dev, &dev->irqh);
212 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
213 DRM(dma_service), dev, &dev->irqh);
216 #elif defined(__NetBSD__)
217 dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY,
218 (int (*)(DRM_IRQ_ARGS))DRM(dma_service), dev);
223 bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
231 /* After installing handler */
232 DRM(driver_irq_postinstall)( dev );
237 int DRM(irq_uninstall)( drm_device_t *dev )
244 irqrid = dev->irqrid;
250 return DRM_ERR(EINVAL);
252 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
254 DRM(driver_irq_uninstall)( dev );
257 bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
258 bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr);
259 #elif defined(__NetBSD__)
260 pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
266 int DRM(control)( DRM_IOCTL_ARGS )
271 DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
273 switch ( ctl.func ) {
274 case DRM_INST_HANDLER:
275 return DRM(irq_install)( dev, ctl.irq );
276 case DRM_UNINST_HANDLER:
277 return DRM(irq_uninstall)( dev );
279 return DRM_ERR(EINVAL);
284 int DRM(wait_vblank)( DRM_IOCTL_ARGS )
287 drm_wait_vblank_t vblwait;
292 return DRM_ERR(EINVAL);
294 DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
297 if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
298 vblwait.request.sequence += atomic_read(&dev->vbl_received);
299 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
302 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
303 if (flags & _DRM_VBLANK_SIGNAL) {
305 drm_vbl_sig_t *vbl_sig = DRM_MALLOC(sizeof(drm_vbl_sig_t));
308 bzero(vbl_sig, sizeof(*vbl_sig));
310 vbl_sig->sequence = vblwait.request.sequence;
311 vbl_sig->signo = vblwait.request.signal;
312 vbl_sig->pid = DRM_CURRENTPID;
314 vblwait.reply.sequence = atomic_read(&dev->vbl_received);
316 DRM_SPINLOCK(&dev->vbl_lock);
317 TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
318 DRM_SPINUNLOCK(&dev->vbl_lock);
323 ret = DRM(vblank_wait)(dev, &vblwait.request.sequence);
326 vblwait.reply.tval_sec = now.tv_sec;
327 vblwait.reply.tval_usec = now.tv_usec;
330 DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
336 void DRM(vbl_send_signals)(drm_device_t *dev)
341 void DRM(vbl_send_signals)( drm_device_t *dev )
343 drm_vbl_sig_t *vbl_sig;
344 unsigned int vbl_seq = atomic_read( &dev->vbl_received );
347 DRM_SPINLOCK(&dev->vbl_lock);
349 vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
350 while (vbl_sig != NULL) {
351 drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
353 if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
354 p = pfind(vbl_sig->pid);
356 psignal(p, vbl_sig->signo);
358 TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
359 DRM_FREE(vbl_sig,sizeof(*vbl_sig));
364 DRM_SPINUNLOCK(&dev->vbl_lock);
368 #endif /* __HAVE_VBL_IRQ */
372 int DRM(control)( DRM_IOCTL_ARGS )
376 DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
378 switch ( ctl.func ) {
379 case DRM_INST_HANDLER:
380 case DRM_UNINST_HANDLER:
383 return DRM_ERR(EINVAL);
387 #endif /* __HAVE_DMA_IRQ */
389 #endif /* __HAVE_DMA */