drm_scatter.c revision 183833
1145132Sanholt/*- 2145132Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 3145132Sanholt * All Rights Reserved. 4145132Sanholt * 5145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 6145132Sanholt * copy of this software and associated documentation files (the "Software"), 7145132Sanholt * to deal in the Software without restriction, including without limitation 8145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 10145132Sanholt * Software is furnished to do so, subject to the following conditions: 11145132Sanholt * 12145132Sanholt * The above copyright notice and this permission notice (including the next 13145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 14145132Sanholt * Software. 15145132Sanholt * 16145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19145132Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20145132Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21145132Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22145132Sanholt * DEALINGS IN THE SOFTWARE. 23145132Sanholt * 24145132Sanholt * Authors: 25145132Sanholt * Gareth Hughes <gareth@valinux.com> 26145132Sanholt * Eric Anholt <anholt@FreeBSD.org> 27145132Sanholt * 28145132Sanholt */ 29145132Sanholt 30152909Sanholt#include <sys/cdefs.h> 31152909Sanholt__FBSDID("$FreeBSD: head/sys/dev/drm/drm_scatter.c 183833 2008-10-13 18:03:27Z rnoland $"); 32152909Sanholt 33182080Srnoland/** @file drm_scatter.c 34182080Srnoland * Allocation of memory for scatter-gather mappings by the graphics chip. 35182080Srnoland * 36182080Srnoland * The memory allocated here is then made into an aperture in the card 37182080Srnoland * by drm_ati_pcigart_init(). 38182080Srnoland */ 39182080Srnoland 40145132Sanholt#include "dev/drm/drmP.h" 41145132Sanholt 42145132Sanholt#define DEBUG_SCATTER 0 43145132Sanholt 44145132Sanholtvoid drm_sg_cleanup(drm_sg_mem_t *entry) 45145132Sanholt{ 46183833Srnoland free((void *)entry->handle, DRM_MEM_PAGES); 47183833Srnoland free(entry->busaddr, DRM_MEM_PAGES); 48183833Srnoland free(entry, DRM_MEM_SGLISTS); 49145132Sanholt} 50145132Sanholt 51183573Srnolandint drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request) 52145132Sanholt{ 53145132Sanholt drm_sg_mem_t *entry; 54145132Sanholt unsigned long pages; 55152909Sanholt int i; 56145132Sanholt 57183573Srnoland if (dev->sg) 58145132Sanholt return EINVAL; 59145132Sanholt 60183833Srnoland entry = malloc(sizeof(*entry), DRM_MEM_SGLISTS, M_WAITOK | M_ZERO); 61183573Srnoland if (!entry) 62145132Sanholt return ENOMEM; 63145132Sanholt 64182080Srnoland pages = round_page(request->size) / PAGE_SIZE; 65183573Srnoland DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages); 66145132Sanholt 67145132Sanholt entry->pages = pages; 68145132Sanholt 69183833Srnoland entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES, 70145132Sanholt M_WAITOK | M_ZERO); 71183573Srnoland if (!entry->busaddr) { 72145132Sanholt drm_sg_cleanup(entry); 73145132Sanholt return ENOMEM; 74145132Sanholt } 75145132Sanholt 76183833Srnoland entry->handle = (long)malloc(pages << PAGE_SHIFT, DRM_MEM_PAGES, 77152909Sanholt M_WAITOK | M_ZERO); 78152909Sanholt if (entry->handle == 0) { 79145132Sanholt drm_sg_cleanup(entry); 80145132Sanholt return ENOMEM; 81145132Sanholt } 82145132Sanholt 83152909Sanholt for (i = 0; i < pages; i++) { 84152909Sanholt entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE); 85152909Sanholt } 86145132Sanholt 87183573Srnoland DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle); 88145132Sanholt 89158682Sanholt entry->virtual = (void *)entry->handle; 90182080Srnoland request->handle = entry->handle; 91145132Sanholt 92145132Sanholt DRM_LOCK(); 93145132Sanholt if (dev->sg) { 94145132Sanholt DRM_UNLOCK(); 95145132Sanholt drm_sg_cleanup(entry); 96145132Sanholt return EINVAL; 97145132Sanholt } 98145132Sanholt dev->sg = entry; 99145132Sanholt DRM_UNLOCK(); 100145132Sanholt 101145132Sanholt return 0; 102145132Sanholt} 103145132Sanholt 104182080Srnolandint drm_sg_alloc_ioctl(struct drm_device *dev, void *data, 105182080Srnoland struct drm_file *file_priv) 106145132Sanholt{ 107183573Srnoland struct drm_scatter_gather *request = data; 108182080Srnoland int ret; 109182080Srnoland 110183573Srnoland DRM_DEBUG("%s\n", __FUNCTION__); 111182080Srnoland 112182080Srnoland ret = drm_sg_alloc(dev, request); 113182080Srnoland return ret; 114182080Srnoland} 115182080Srnoland 116182080Srnolandint drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv) 117182080Srnoland{ 118183573Srnoland struct drm_scatter_gather *request = data; 119145132Sanholt drm_sg_mem_t *entry; 120145132Sanholt 121145132Sanholt DRM_LOCK(); 122145132Sanholt entry = dev->sg; 123145132Sanholt dev->sg = NULL; 124145132Sanholt DRM_UNLOCK(); 125145132Sanholt 126183573Srnoland if (!entry || entry->handle != request->handle) 127145132Sanholt return EINVAL; 128145132Sanholt 129183573Srnoland DRM_DEBUG("sg free virtual = 0x%lx\n", entry->handle); 130145132Sanholt 131145132Sanholt drm_sg_cleanup(entry); 132145132Sanholt 133145132Sanholt return 0; 134145132Sanholt} 135