1 /* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
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 NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
27 * Sung-Ching Lin <sclin@sis.com.tw>
32 #include "dev/drm/sis.h"
33 #include "dev/drm/drmP.h"
34 #include "dev/drm/sis_drm.h"
35 #include "dev/drm/sis_drv.h"
36 #include "dev/drm/sis_ds.h"
37 #if defined(__linux__) && defined(CONFIG_FB_SIS)
38 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
39 #include <video/sisfb.h>
41 #include <linux/sisfb.h>
45 #define MAX_CONTEXT 100
52 set_t *sets[2]; /* 0 for video, 1 for AGP */
55 static sis_context_t global_ppriv[MAX_CONTEXT];
58 static int add_alloc_set(int context, int type, unsigned int val)
62 for (i = 0; i < MAX_CONTEXT; i++) {
63 if (global_ppriv[i].used && global_ppriv[i].context == context)
65 retval = setAdd(global_ppriv[i].sets[type], val);
72 static int del_alloc_set(int context, int type, unsigned int val)
76 for (i = 0; i < MAX_CONTEXT; i++) {
77 if (global_ppriv[i].used && global_ppriv[i].context == context)
79 retval = setDel(global_ppriv[i].sets[type], val);
86 /* fb management via fb device */
87 #if defined(__linux__) && defined(CONFIG_FB_SIS)
89 int sis_fb_init( DRM_IOCTL_ARGS )
94 int sis_fb_alloc( DRM_IOCTL_ARGS )
97 struct sis_memreq req;
100 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
106 fb.offset = req.offset;
107 fb.free = req.offset;
108 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
109 DRM_DEBUG("adding to allocation set fails\n");
110 sis_free(req.offset);
111 retval = DRM_ERR(EINVAL);
119 DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
121 DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
126 int sis_fb_free( DRM_IOCTL_ARGS )
131 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
134 return DRM_ERR(EINVAL);
136 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
137 retval = DRM_ERR(EINVAL);
140 DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
147 /* Called by the X Server to initialize the FB heap. Allocations will fail
148 * unless this is called. Offset is the beginning of the heap from the
149 * framebuffer offset (MaxXFBMem in XFree86).
151 * Memory layout according to Thomas Winischofer:
152 * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
154 * X driver/sisfb HW- Command-
155 * framebuffer memory DRI heap Cursor queue
157 int sis_fb_init( DRM_IOCTL_ARGS )
160 drm_sis_private_t *dev_priv = dev->dev_private;
163 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb));
165 if (dev_priv == NULL) {
166 dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
168 dev_priv = dev->dev_private;
169 if (dev_priv == NULL)
173 if (dev_priv->FBHeap != NULL)
174 return DRM_ERR(EINVAL);
176 dev_priv->FBHeap = mmInit(fb.offset, fb.size);
178 DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
183 int sis_fb_alloc( DRM_IOCTL_ARGS )
186 drm_sis_private_t *dev_priv = dev->dev_private;
191 if (dev_priv == NULL || dev_priv->FBHeap == NULL)
192 return DRM_ERR(EINVAL);
194 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
196 block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
199 fb.offset = block->ofs;
200 fb.free = (unsigned long)block;
201 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
202 DRM_DEBUG("adding to allocation set fails\n");
203 mmFreeMem((PMemBlock)fb.free);
204 retval = DRM_ERR(EINVAL);
212 DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
214 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
219 int sis_fb_free( DRM_IOCTL_ARGS )
222 drm_sis_private_t *dev_priv = dev->dev_private;
225 if (dev_priv == NULL || dev_priv->FBHeap == NULL)
226 return DRM_ERR(EINVAL);
228 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
230 if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
231 return DRM_ERR(EINVAL);
233 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
234 return DRM_ERR(EINVAL);
235 mmFreeMem((PMemBlock)fb.free);
237 DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
244 /* agp memory management */
246 int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
249 drm_sis_private_t *dev_priv = dev->dev_private;
252 if (dev_priv == NULL) {
253 dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
255 dev_priv = dev->dev_private;
256 if (dev_priv == NULL)
260 if (dev_priv->AGPHeap != NULL)
261 return DRM_ERR(EINVAL);
263 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp));
265 dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
267 DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
272 int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
275 drm_sis_private_t *dev_priv = dev->dev_private;
280 if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
281 return DRM_ERR(EINVAL);
283 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
285 block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
288 agp.offset = block->ofs;
289 agp.free = (unsigned long)block;
290 if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
291 DRM_DEBUG("adding to allocation set fails\n");
292 mmFreeMem((PMemBlock)agp.free);
301 DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp));
303 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
308 int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
311 drm_sis_private_t *dev_priv = dev->dev_private;
314 if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
315 return DRM_ERR(EINVAL);
317 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
319 if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
320 return DRM_ERR(EINVAL);
322 mmFreeMem((PMemBlock)agp.free);
323 if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
324 return DRM_ERR(EINVAL);
326 DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
331 int sis_init_context(int context)
335 for (i = 0; i < MAX_CONTEXT ; i++) {
336 if (global_ppriv[i].used &&
337 (global_ppriv[i].context == context))
341 if (i >= MAX_CONTEXT) {
342 for (i = 0; i < MAX_CONTEXT ; i++) {
343 if (!global_ppriv[i].used) {
344 global_ppriv[i].context = context;
345 global_ppriv[i].used = 1;
346 global_ppriv[i].sets[0] = setInit();
347 global_ppriv[i].sets[1] = setInit();
348 DRM_DEBUG("init allocation set, socket=%d, "
349 "context = %d\n", i, context);
353 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
354 (global_ppriv[i].sets[1] == NULL))
363 int sis_final_context(int context)
367 for (i=0; i<MAX_CONTEXT; i++) {
368 if (global_ppriv[i].used &&
369 (global_ppriv[i].context == context))
373 if (i < MAX_CONTEXT) {
378 DRM_DEBUG("find socket %d, context = %d\n", i, context);
381 set = global_ppriv[i].sets[0];
382 retval = setFirst(set, &item);
384 DRM_DEBUG("free video memory 0x%lx\n", item);
385 #if defined(__linux__) && defined(CONFIG_FB_SIS)
388 mmFreeMem((PMemBlock)item);
390 retval = setNext(set, &item);
395 set = global_ppriv[i].sets[1];
396 retval = setFirst(set, &item);
398 DRM_DEBUG("free agp memory 0x%lx\n", item);
399 mmFreeMem((PMemBlock)item);
400 retval = setNext(set, &item);
404 global_ppriv[i].used = 0;