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