aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sis/sis_mm.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/gpu/drm/sis/sis_mm.c
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/sis/sis_mm.c')
-rw-r--r--drivers/gpu/drm/sis/sis_mm.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
new file mode 100644
index 000000000000..b3878770fce1
--- /dev/null
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -0,0 +1,333 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
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
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 **************************************************************************/
28
29/*
30 * Authors:
31 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
32 */
33
34#include "drmP.h"
35#include "sis_drm.h"
36#include "sis_drv.h"
37
38#include <video/sisfb.h>
39
40#define VIDEO_TYPE 0
41#define AGP_TYPE 1
42
43
44#if defined(CONFIG_FB_SIS)
45/* fb management via fb device */
46
47#define SIS_MM_ALIGN_SHIFT 0
48#define SIS_MM_ALIGN_MASK 0
49
50static void *sis_sman_mm_allocate(void *private, unsigned long size,
51 unsigned alignment)
52{
53 struct sis_memreq req;
54
55 req.size = size;
56 sis_malloc(&req);
57 if (req.size == 0)
58 return NULL;
59 else
60 return (void *)~req.offset;
61}
62
63static void sis_sman_mm_free(void *private, void *ref)
64{
65 sis_free(~((unsigned long)ref));
66}
67
68static void sis_sman_mm_destroy(void *private)
69{
70 ;
71}
72
73static unsigned long sis_sman_mm_offset(void *private, void *ref)
74{
75 return ~((unsigned long)ref);
76}
77
78#else /* CONFIG_FB_SIS */
79
80#define SIS_MM_ALIGN_SHIFT 4
81#define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
82
83#endif /* CONFIG_FB_SIS */
84
85static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
86{
87 drm_sis_private_t *dev_priv = dev->dev_private;
88 drm_sis_fb_t *fb = data;
89 int ret;
90
91 mutex_lock(&dev->struct_mutex);
92#if defined(CONFIG_FB_SIS)
93 {
94 struct drm_sman_mm sman_mm;
95 sman_mm.private = (void *)0xFFFFFFFF;
96 sman_mm.allocate = sis_sman_mm_allocate;
97 sman_mm.free = sis_sman_mm_free;
98 sman_mm.destroy = sis_sman_mm_destroy;
99 sman_mm.offset = sis_sman_mm_offset;
100 ret =
101 drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
102 }
103#else
104 ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
105 fb->size >> SIS_MM_ALIGN_SHIFT);
106#endif
107
108 if (ret) {
109 DRM_ERROR("VRAM memory manager initialisation error\n");
110 mutex_unlock(&dev->struct_mutex);
111 return ret;
112 }
113
114 dev_priv->vram_initialized = 1;
115 dev_priv->vram_offset = fb->offset;
116
117 mutex_unlock(&dev->struct_mutex);
118 DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
119
120 return 0;
121}
122
123static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv,
124 void *data, int pool)
125{
126 drm_sis_private_t *dev_priv = dev->dev_private;
127 drm_sis_mem_t *mem = data;
128 int retval = 0;
129 struct drm_memblock_item *item;
130
131 mutex_lock(&dev->struct_mutex);
132
133 if (0 == ((pool == 0) ? dev_priv->vram_initialized :
134 dev_priv->agp_initialized)) {
135 DRM_ERROR
136 ("Attempt to allocate from uninitialized memory manager.\n");
137 mutex_unlock(&dev->struct_mutex);
138 return -EINVAL;
139 }
140
141 mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
142 item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0,
143 (unsigned long)file_priv);
144
145 mutex_unlock(&dev->struct_mutex);
146 if (item) {
147 mem->offset = ((pool == 0) ?
148 dev_priv->vram_offset : dev_priv->agp_offset) +
149 (item->mm->
150 offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
151 mem->free = item->user_hash.key;
152 mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
153 } else {
154 mem->offset = 0;
155 mem->size = 0;
156 mem->free = 0;
157 retval = -ENOMEM;
158 }
159
160 DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size,
161 mem->offset);
162
163 return retval;
164}
165
166static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
167{
168 drm_sis_private_t *dev_priv = dev->dev_private;
169 drm_sis_mem_t *mem = data;
170 int ret;
171
172 mutex_lock(&dev->struct_mutex);
173 ret = drm_sman_free_key(&dev_priv->sman, mem->free);
174 mutex_unlock(&dev->struct_mutex);
175 DRM_DEBUG("free = 0x%lx\n", mem->free);
176
177 return ret;
178}
179
180static int sis_fb_alloc(struct drm_device *dev, void *data,
181 struct drm_file *file_priv)
182{
183 return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
184}
185
186static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
187 struct drm_file *file_priv)
188{
189 drm_sis_private_t *dev_priv = dev->dev_private;
190 drm_sis_agp_t *agp = data;
191 int ret;
192 dev_priv = dev->dev_private;
193
194 mutex_lock(&dev->struct_mutex);
195 ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
196 agp->size >> SIS_MM_ALIGN_SHIFT);
197
198 if (ret) {
199 DRM_ERROR("AGP memory manager initialisation error\n");
200 mutex_unlock(&dev->struct_mutex);
201 return ret;
202 }
203
204 dev_priv->agp_initialized = 1;
205 dev_priv->agp_offset = agp->offset;
206 mutex_unlock(&dev->struct_mutex);
207
208 DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
209 return 0;
210}
211
212static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
213 struct drm_file *file_priv)
214{
215
216 return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
217}
218
219static drm_local_map_t *sis_reg_init(struct drm_device *dev)
220{
221 struct drm_map_list *entry;
222 drm_local_map_t *map;
223
224 list_for_each_entry(entry, &dev->maplist, head) {
225 map = entry->map;
226 if (!map)
227 continue;
228 if (map->type == _DRM_REGISTERS) {
229 return map;
230 }
231 }
232 return NULL;
233}
234
235int sis_idle(struct drm_device *dev)
236{
237 drm_sis_private_t *dev_priv = dev->dev_private;
238 uint32_t idle_reg;
239 unsigned long end;
240 int i;
241
242 if (dev_priv->idle_fault)
243 return 0;
244
245 if (dev_priv->mmio == NULL) {
246 dev_priv->mmio = sis_reg_init(dev);
247 if (dev_priv->mmio == NULL) {
248 DRM_ERROR("Could not find register map.\n");
249 return 0;
250 }
251 }
252
253 /*
254 * Implement a device switch here if needed
255 */
256
257 if (dev_priv->chipset != SIS_CHIP_315)
258 return 0;
259
260 /*
261 * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
262 * because its polling frequency is too low.
263 */
264
265 end = jiffies + (DRM_HZ * 3);
266
267 for (i=0; i<4; ++i) {
268 do {
269 idle_reg = SIS_READ(0x85cc);
270 } while ( !time_after_eq(jiffies, end) &&
271 ((idle_reg & 0x80000000) != 0x80000000));
272 }
273
274 if (time_after_eq(jiffies, end)) {
275 DRM_ERROR("Graphics engine idle timeout. "
276 "Disabling idle check\n");
277 dev_priv->idle_fault = 1;
278 }
279
280 /*
281 * The caller never sees an error code. It gets trapped
282 * in libdrm.
283 */
284
285 return 0;
286}
287
288
289void sis_lastclose(struct drm_device *dev)
290{
291 drm_sis_private_t *dev_priv = dev->dev_private;
292
293 if (!dev_priv)
294 return;
295
296 mutex_lock(&dev->struct_mutex);
297 drm_sman_cleanup(&dev_priv->sman);
298 dev_priv->vram_initialized = 0;
299 dev_priv->agp_initialized = 0;
300 dev_priv->mmio = NULL;
301 mutex_unlock(&dev->struct_mutex);
302}
303
304void sis_reclaim_buffers_locked(struct drm_device * dev,
305 struct drm_file *file_priv)
306{
307 drm_sis_private_t *dev_priv = dev->dev_private;
308
309 mutex_lock(&dev->struct_mutex);
310 if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
311 mutex_unlock(&dev->struct_mutex);
312 return;
313 }
314
315 if (dev->driver->dma_quiescent) {
316 dev->driver->dma_quiescent(dev);
317 }
318
319 drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
320 mutex_unlock(&dev->struct_mutex);
321 return;
322}
323
324struct drm_ioctl_desc sis_ioctls[] = {
325 DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
326 DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH),
327 DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
328 DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
329 DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
330 DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
331};
332
333int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);