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