1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * drm_dma.c -- DMA IOCTL and function support -*- linux-c -*- 8 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com 9 */ 10 /* 11 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 12 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 13 * All Rights Reserved. 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining a 16 * copy of this software and associated documentation files (the "Software"), 17 * to deal in the Software without restriction, including without limitation 18 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 * and/or sell copies of the Software, and to permit persons to whom the 20 * Software is furnished to do so, subject to the following conditions: 21 * 22 * The above copyright notice and this permission notice (including the next 23 * paragraph) shall be included in all copies or substantial portions of the 24 * Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 29 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 30 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 31 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 32 * OTHER DEALINGS IN THE SOFTWARE. 33 * 34 * Authors: 35 * Rickard E. (Rik) Faith <faith@valinux.com> 36 * Gareth Hughes <gareth@valinux.com> 37 * 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include "drmP.h" 43 44 int 45 drm_dma_setup(drm_device_t *dev) 46 { 47 int i; 48 49 dev->dma = drm_calloc(1, sizeof (*dev->dma), DRM_MEM_DMA); 50 if (dev->dma == NULL) 51 return (DRM_ERR(ENOMEM)); 52 53 mutex_init(&dev->dma_lock, NULL, MUTEX_DRIVER, NULL); 54 55 for (i = 0; i <= DRM_MAX_ORDER; i++) 56 (void) memset(&dev->dma->bufs[i], 0, 57 sizeof (dev->dma->bufs[0])); 58 59 return (0); 60 } 61 62 void 63 drm_dma_takedown(drm_device_t *dev) 64 { 65 drm_device_dma_t *dma = dev->dma; 66 int i, j; 67 68 if (dma == NULL) 69 return; 70 71 /* Clear dma buffers */ 72 for (i = 0; i <= DRM_MAX_ORDER; i++) { 73 if (dma->bufs[i].seg_count) { 74 DRM_DEBUG("drm_dma_takedown: order %d: buf_count = %d," 75 " seg_count = %d\n", 76 i, 77 dma->bufs[i].buf_count, 78 dma->bufs[i].seg_count); 79 drm_free(dma->bufs[i].seglist, 80 dma->bufs[i].seg_count * 81 sizeof (*dma->bufs[0].seglist), DRM_MEM_SEGS); 82 } 83 84 if (dma->bufs[i].buf_count) { 85 for (j = 0; j < dma->bufs[i].buf_count; j++) { 86 if (dma->bufs[i].buflist[j].dev_private) { 87 drm_free(dma->bufs[i].buflist[j]. 88 dev_private, 89 dma->bufs[i].buflist[j]. 90 dev_priv_size, DRM_MEM_BUFS); 91 } 92 } 93 drm_free(dma->bufs[i].buflist, 94 dma->bufs[i].buf_count * 95 sizeof (*dma->bufs[0].buflist), DRM_MEM_BUFS); 96 } 97 } 98 DRM_DEBUG("drm_dma_takedown: free buflist"); 99 if (dma->buflist) { 100 drm_free(dma->buflist, 101 dma->buf_count *sizeof (*dma->buflist), 102 DRM_MEM_BUFS); 103 } 104 105 if (dma->pagelist) { 106 drm_free(dma->pagelist, 107 dma->page_count *sizeof (*dma->pagelist), 108 DRM_MEM_PAGES); 109 } 110 111 drm_free(dev->dma, sizeof (*dev->dma), DRM_MEM_DRIVER); 112 dev->dma = NULL; 113 mutex_destroy(&dev->dma_lock); 114 } 115 116 117 /*ARGSUSED*/ 118 void 119 drm_free_buffer(drm_device_t *dev, drm_buf_t *buf) 120 { 121 if (!buf) 122 return; 123 124 buf->pending = 0; 125 buf->filp = NULL; 126 buf->used = 0; 127 } 128 129 void 130 drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp) 131 { 132 drm_device_dma_t *dma = dev->dma; 133 int i; 134 135 if (!dma) 136 return; 137 for (i = 0; i < dma->buf_count; i++) { 138 if (dma->buflist[i]->filp == filp) { 139 switch (dma->buflist[i]->list) { 140 case DRM_LIST_NONE: 141 drm_free_buffer(dev, dma->buflist[i]); 142 break; 143 case DRM_LIST_WAIT: 144 dma->buflist[i]->list = DRM_LIST_RECLAIM; 145 break; 146 default: 147 /* Buffer already on hardware. */ 148 break; 149 } 150 } 151 } 152 } 153 154 /* Call into the driver-specific DMA handler */ 155 int 156 drm_dma(DRM_IOCTL_ARGS) 157 { 158 DRM_DEVICE; 159 160 if (dev->dma_ioctl) { 161 return (dev->dma_ioctl(kdev, dev, data, mode, 162 credp, rvalp, filp)); 163 } else { 164 DRM_DEBUG("drm_dma: DMA ioctl on driver with no dma handler\n"); 165 return (DRM_ERR(EINVAL)); 166 } 167 } 168