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>
36 #if defined(__linux__) && defined(CONFIG_FB_SIS)
37 #include <video/sisfb.h>
40 #define MAX_CONTEXT 100
47 set_t
*sets
[2]; /* 0 for video, 1 for AGP */
50 static sis_context_t global_ppriv
[MAX_CONTEXT
];
53 static int add_alloc_set(int context
, int type
, unsigned int val
)
57 for (i
= 0; i
< MAX_CONTEXT
; i
++) {
58 if (global_ppriv
[i
].used
&& global_ppriv
[i
].context
== context
)
60 retval
= setAdd(global_ppriv
[i
].sets
[type
], val
);
67 static int del_alloc_set(int context
, int type
, unsigned int val
)
71 for (i
= 0; i
< MAX_CONTEXT
; i
++) {
72 if (global_ppriv
[i
].used
&& global_ppriv
[i
].context
== context
)
74 retval
= setDel(global_ppriv
[i
].sets
[type
], val
);
81 /* fb management via fb device */
82 #if defined(__linux__) && defined(CONFIG_FB_SIS)
84 int sis_fb_init( DRM_IOCTL_ARGS
)
89 int sis_fb_alloc( DRM_IOCTL_ARGS
)
92 struct sis_memreq req
;
93 drm_sis_mem_t __user
*argp
= (void __user
*)data
;
96 DRM_COPY_FROM_USER_IOCTL(fb
, argp
, sizeof(fb
));
102 fb
.offset
= req
.offset
;
103 fb
.free
= req
.offset
;
104 if (!add_alloc_set(fb
.context
, VIDEO_TYPE
, fb
.free
)) {
105 DRM_DEBUG("adding to allocation set fails\n");
106 sis_free(req
.offset
);
107 retval
= DRM_ERR(EINVAL
);
115 DRM_COPY_TO_USER_IOCTL(argp
, fb
, sizeof(fb
));
117 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb
.size
, req
.offset
);
122 int sis_fb_free( DRM_IOCTL_ARGS
)
127 DRM_COPY_FROM_USER_IOCTL(fb
, (drm_sis_mem_t __user
*)data
, sizeof(fb
));
130 return DRM_ERR(EINVAL
);
132 if (!del_alloc_set(fb
.context
, VIDEO_TYPE
, fb
.free
))
133 retval
= DRM_ERR(EINVAL
);
134 sis_free((u32
)fb
.free
);
136 DRM_DEBUG("free fb, offset = %lu\n", fb
.free
);
143 /* Called by the X Server to initialize the FB heap. Allocations will fail
144 * unless this is called. Offset is the beginning of the heap from the
145 * framebuffer offset (MaxXFBMem in XFree86).
147 * Memory layout according to Thomas Winischofer:
148 * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
150 * X driver/sisfb HW- Command-
151 * framebuffer memory DRI heap Cursor queue
153 int sis_fb_init( DRM_IOCTL_ARGS
)
156 drm_sis_private_t
*dev_priv
= dev
->dev_private
;
159 DRM_COPY_FROM_USER_IOCTL(fb
, (drm_sis_fb_t __user
*)data
, sizeof(fb
));
161 if (dev_priv
== NULL
) {
162 dev
->dev_private
= DRM(calloc
)(1, sizeof(drm_sis_private_t
),
164 dev_priv
= dev
->dev_private
;
165 if (dev_priv
== NULL
)
169 if (dev_priv
->FBHeap
!= NULL
)
170 return DRM_ERR(EINVAL
);
172 dev_priv
->FBHeap
= mmInit(fb
.offset
, fb
.size
);
174 DRM_DEBUG("offset = %u, size = %u", fb
.offset
, fb
.size
);
179 int sis_fb_alloc( DRM_IOCTL_ARGS
)
182 drm_sis_private_t
*dev_priv
= dev
->dev_private
;
183 drm_sis_mem_t __user
*argp
= (void __user
*)data
;
188 if (dev_priv
== NULL
|| dev_priv
->FBHeap
== NULL
)
189 return DRM_ERR(EINVAL
);
191 DRM_COPY_FROM_USER_IOCTL(fb
, argp
, sizeof(fb
));
193 block
= mmAllocMem(dev_priv
->FBHeap
, fb
.size
, 0, 0);
196 fb
.offset
= block
->ofs
;
197 fb
.free
= (unsigned long)block
;
198 if (!add_alloc_set(fb
.context
, VIDEO_TYPE
, fb
.free
)) {
199 DRM_DEBUG("adding to allocation set fails\n");
200 mmFreeMem((PMemBlock
)fb
.free
);
201 retval
= DRM_ERR(EINVAL
);
209 DRM_COPY_TO_USER_IOCTL(argp
, fb
, sizeof(fb
));
211 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb
.size
, fb
.offset
);
216 int sis_fb_free( DRM_IOCTL_ARGS
)
219 drm_sis_private_t
*dev_priv
= dev
->dev_private
;
222 if (dev_priv
== NULL
|| dev_priv
->FBHeap
== NULL
)
223 return DRM_ERR(EINVAL
);
225 DRM_COPY_FROM_USER_IOCTL(fb
, (drm_sis_mem_t __user
*)data
, sizeof(fb
));
227 if (!mmBlockInHeap(dev_priv
->FBHeap
, (PMemBlock
)fb
.free
))
228 return DRM_ERR(EINVAL
);
230 if (!del_alloc_set(fb
.context
, VIDEO_TYPE
, fb
.free
))
231 return DRM_ERR(EINVAL
);
232 mmFreeMem((PMemBlock
)fb
.free
);
234 DRM_DEBUG("free fb, free = 0x%lx\n", fb
.free
);
241 /* agp memory management */
243 int sis_ioctl_agp_init( DRM_IOCTL_ARGS
)
246 drm_sis_private_t
*dev_priv
= dev
->dev_private
;
249 if (dev_priv
== NULL
) {
250 dev
->dev_private
= DRM(calloc
)(1, sizeof(drm_sis_private_t
),
252 dev_priv
= dev
->dev_private
;
253 if (dev_priv
== NULL
)
257 if (dev_priv
->AGPHeap
!= NULL
)
258 return DRM_ERR(EINVAL
);
260 DRM_COPY_FROM_USER_IOCTL(agp
, (drm_sis_agp_t __user
*)data
, sizeof(agp
));
262 dev_priv
->AGPHeap
= mmInit(agp
.offset
, agp
.size
);
264 DRM_DEBUG("offset = %u, size = %u", agp
.offset
, agp
.size
);
269 int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS
)
272 drm_sis_private_t
*dev_priv
= dev
->dev_private
;
273 drm_sis_mem_t __user
*argp
= (void __user
*)data
;
278 if (dev_priv
== NULL
|| dev_priv
->AGPHeap
== NULL
)
279 return DRM_ERR(EINVAL
);
281 DRM_COPY_FROM_USER_IOCTL(agp
, argp
, sizeof(agp
));
283 block
= mmAllocMem(dev_priv
->AGPHeap
, agp
.size
, 0, 0);
286 agp
.offset
= block
->ofs
;
287 agp
.free
= (unsigned long)block
;
288 if (!add_alloc_set(agp
.context
, AGP_TYPE
, agp
.free
)) {
289 DRM_DEBUG("adding to allocation set fails\n");
290 mmFreeMem((PMemBlock
)agp
.free
);
299 DRM_COPY_TO_USER_IOCTL(argp
, agp
, sizeof(agp
));
301 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp
.size
, agp
.offset
);
306 int sis_ioctl_agp_free( DRM_IOCTL_ARGS
)
309 drm_sis_private_t
*dev_priv
= dev
->dev_private
;
312 if (dev_priv
== NULL
|| dev_priv
->AGPHeap
== NULL
)
313 return DRM_ERR(EINVAL
);
315 DRM_COPY_FROM_USER_IOCTL(agp
, (drm_sis_mem_t __user
*)data
, sizeof(agp
));
317 if (!mmBlockInHeap(dev_priv
->AGPHeap
, (PMemBlock
)agp
.free
))
318 return DRM_ERR(EINVAL
);
320 mmFreeMem((PMemBlock
)agp
.free
);
321 if (!del_alloc_set(agp
.context
, AGP_TYPE
, agp
.free
))
322 return DRM_ERR(EINVAL
);
324 DRM_DEBUG("free agp, free = 0x%lx\n", agp
.free
);
329 int sis_init_context(struct drm_device
*dev
, int context
)
333 for (i
= 0; i
< MAX_CONTEXT
; i
++) {
334 if (global_ppriv
[i
].used
&&
335 (global_ppriv
[i
].context
== context
))
339 if (i
>= MAX_CONTEXT
) {
340 for (i
= 0; i
< MAX_CONTEXT
; i
++) {
341 if (!global_ppriv
[i
].used
) {
342 global_ppriv
[i
].context
= context
;
343 global_ppriv
[i
].used
= 1;
344 global_ppriv
[i
].sets
[0] = setInit();
345 global_ppriv
[i
].sets
[1] = setInit();
346 DRM_DEBUG("init allocation set, socket=%d, "
347 "context = %d\n", i
, context
);
351 if ((i
>= MAX_CONTEXT
) || (global_ppriv
[i
].sets
[0] == NULL
) ||
352 (global_ppriv
[i
].sets
[1] == NULL
))
361 int sis_final_context(struct drm_device
*dev
, int context
)
365 for (i
=0; i
<MAX_CONTEXT
; i
++) {
366 if (global_ppriv
[i
].used
&&
367 (global_ppriv
[i
].context
== context
))
371 if (i
< MAX_CONTEXT
) {
376 DRM_DEBUG("find socket %d, context = %d\n", i
, context
);
379 set
= global_ppriv
[i
].sets
[0];
380 retval
= setFirst(set
, &item
);
382 DRM_DEBUG("free video memory 0x%x\n", item
);
383 #if defined(__linux__) && defined(CONFIG_FB_SIS)
386 mmFreeMem((PMemBlock
)item
);
388 retval
= setNext(set
, &item
);
393 set
= global_ppriv
[i
].sets
[1];
394 retval
= setFirst(set
, &item
);
396 DRM_DEBUG("free agp memory 0x%x\n", item
);
397 mmFreeMem((PMemBlock
)item
);
398 retval
= setNext(set
, &item
);
402 global_ppriv
[i
].used
= 0;
408 void DRM(driver_register_fns
)(drm_device_t
*dev
)
410 dev
->driver_features
= DRIVER_USE_AGP
| DRIVER_USE_MTRR
;
411 dev
->fn_tbl
.context_ctor
= sis_init_context
;
412 dev
->fn_tbl
.context_dtor
= sis_final_context
;