1 /*- 2 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Gareth Hughes <gareth@valinux.com> 26 * Eric Anholt <anholt@FreeBSD.org> 27 * 28 */ 29 30 /* 31 * Allocation of memory for scatter-gather mappings by the graphics chip. 32 * 33 * The memory allocated here is then made into an aperture in the card 34 * by drm_ati_pcigart_init(). 35 */ 36 #include "drmP.h" 37 38 void 39 drm_sg_cleanup(struct drm_device *dev, struct drm_sg_mem *entry) 40 { 41 if (entry == NULL) 42 return; 43 44 drm_dmamem_free(dev->dmat, entry->mem); 45 drm_free(entry); 46 } 47 48 int 49 drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather *request) 50 { 51 struct drm_sg_mem *entry; 52 bus_size_t size; 53 unsigned long pages; 54 55 if (dev->sg != NULL) 56 return (EINVAL); 57 58 entry = drm_calloc(1, sizeof(*entry)); 59 if (entry == NULL) 60 return (ENOMEM); 61 62 pages = round_page(request->size) / PAGE_SIZE; 63 size = pages << PAGE_SHIFT; 64 65 DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages); 66 67 if ((entry->mem = drm_dmamem_alloc(dev->dmat, size, PAGE_SIZE, pages, 68 PAGE_SIZE, 0, 0)) == NULL) 69 return (ENOMEM); 70 71 request->handle = entry->handle = (unsigned long)entry->mem->kva; 72 DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle); 73 74 DRM_LOCK(); 75 if (dev->sg) { 76 DRM_UNLOCK(); 77 drm_sg_cleanup(dev, entry); 78 return EINVAL; 79 } 80 dev->sg = entry; 81 DRM_UNLOCK(); 82 83 return (0); 84 } 85 86 int 87 drm_sg_alloc_ioctl(struct drm_device *dev, void *data, 88 struct drm_file *file_priv) 89 { 90 struct drm_scatter_gather *request = data; 91 int ret; 92 93 DRM_DEBUG("\n"); 94 95 ret = drm_sg_alloc(dev, request); 96 return ret; 97 } 98 99 int 100 drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv) 101 { 102 struct drm_scatter_gather *request = data; 103 struct drm_sg_mem *entry; 104 105 DRM_LOCK(); 106 entry = dev->sg; 107 dev->sg = NULL; 108 DRM_UNLOCK(); 109 110 if (entry == NULL || entry->handle != request->handle) 111 return EINVAL; 112 113 DRM_DEBUG("sg free virtual = 0x%lx\n", entry->handle); 114 115 drm_sg_cleanup(dev, entry); 116 117 return 0; 118 } 119