sis_mm.c revision 119895
1119895Sanholt/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2119895Sanholt * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
3119895Sanholt *
4119895Sanholt * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5119895Sanholt * All rights reserved.
6119895Sanholt *
7119895Sanholt * Permission is hereby granted, free of charge, to any person obtaining a
8119895Sanholt * copy of this software and associated documentation files (the "Software"),
9119895Sanholt * to deal in the Software without restriction, including without limitation
10119895Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11119895Sanholt * and/or sell copies of the Software, and to permit persons to whom the
12119895Sanholt * Software is furnished to do so, subject to the following conditions:
13119895Sanholt *
14119895Sanholt * The above copyright notice and this permission notice (including the next
15119895Sanholt * paragraph) shall be included in all copies or substantial portions of the
16119895Sanholt * Software.
17119895Sanholt *
18119895Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19119895Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20119895Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21119895Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22119895Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23119895Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24119895Sanholt * DEALINGS IN THE SOFTWARE.
25119895Sanholt *
26119895Sanholt * Authors:
27119895Sanholt *    Sung-Ching Lin <sclin@sis.com.tw>
28119895Sanholt *
29119895Sanholt * $FreeBSD: head/sys/dev/drm/sis_mm.c 119895 2003-09-09 00:24:31Z anholt $
30119895Sanholt */
31119895Sanholt
32119895Sanholt#include "dev/drm/sis.h"
33119895Sanholt#include "dev/drm/drmP.h"
34119895Sanholt#include "dev/drm/sis_drm.h"
35119895Sanholt#include "dev/drm/sis_drv.h"
36119895Sanholt#include "dev/drm/sis_ds.h"
37119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS)
38119895Sanholt#include <linux/sisfb.h>
39119895Sanholt#endif
40119895Sanholt
41119895Sanholt#define MAX_CONTEXT 100
42119895Sanholt#define VIDEO_TYPE 0
43119895Sanholt#define AGP_TYPE 1
44119895Sanholt
45119895Sanholttypedef struct {
46119895Sanholt	int used;
47119895Sanholt	int context;
48119895Sanholt	set_t *sets[2]; /* 0 for video, 1 for AGP */
49119895Sanholt} sis_context_t;
50119895Sanholt
51119895Sanholtstatic sis_context_t global_ppriv[MAX_CONTEXT];
52119895Sanholt
53119895Sanholt
54119895Sanholtstatic int add_alloc_set(int context, int type, unsigned int val)
55119895Sanholt{
56119895Sanholt	int i, retval = 0;
57119895Sanholt
58119895Sanholt	for (i = 0; i < MAX_CONTEXT; i++) {
59119895Sanholt		if (global_ppriv[i].used && global_ppriv[i].context == context)
60119895Sanholt		{
61119895Sanholt			retval = setAdd(global_ppriv[i].sets[type], val);
62119895Sanholt			break;
63119895Sanholt		}
64119895Sanholt	}
65119895Sanholt	return retval;
66119895Sanholt}
67119895Sanholt
68119895Sanholtstatic int del_alloc_set(int context, int type, unsigned int val)
69119895Sanholt{
70119895Sanholt	int i, retval = 0;
71119895Sanholt
72119895Sanholt	for (i = 0; i < MAX_CONTEXT; i++) {
73119895Sanholt		if (global_ppriv[i].used && global_ppriv[i].context == context)
74119895Sanholt		{
75119895Sanholt			retval = setDel(global_ppriv[i].sets[type], val);
76119895Sanholt			break;
77119895Sanholt		}
78119895Sanholt	}
79119895Sanholt	return retval;
80119895Sanholt}
81119895Sanholt
82119895Sanholt/* fb management via fb device */
83119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS)
84119895Sanholt
85119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS )
86119895Sanholt{
87119895Sanholt	return 0;
88119895Sanholt}
89119895Sanholt
90119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS )
91119895Sanholt{
92119895Sanholt	drm_sis_mem_t fb;
93119895Sanholt	struct sis_memreq req;
94119895Sanholt	int retval = 0;
95119895Sanholt
96119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
97119895Sanholt
98119895Sanholt	req.size = fb.size;
99119895Sanholt	sis_malloc(&req);
100119895Sanholt	if (req.offset) {
101119895Sanholt		/* TODO */
102119895Sanholt		fb.offset = req.offset;
103119895Sanholt		fb.free = req.offset;
104119895Sanholt		if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
105119895Sanholt			DRM_DEBUG("adding to allocation set fails\n");
106119895Sanholt			sis_free(req.offset);
107119895Sanholt			retval = DRM_ERR(EINVAL);
108119895Sanholt		}
109119895Sanholt	} else {
110119895Sanholt		fb.offset = 0;
111119895Sanholt		fb.size = 0;
112119895Sanholt		fb.free = 0;
113119895Sanholt	}
114119895Sanholt
115119895Sanholt	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
116119895Sanholt
117119895Sanholt	DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
118119895Sanholt
119119895Sanholt	return retval;
120119895Sanholt}
121119895Sanholt
122119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS )
123119895Sanholt{
124119895Sanholt	drm_sis_mem_t fb;
125119895Sanholt	int retval = 0;
126119895Sanholt
127119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
128119895Sanholt
129119895Sanholt	if (!fb.free)
130119895Sanholt		return DRM_ERR(EINVAL);
131119895Sanholt
132119895Sanholt	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
133119895Sanholt		retval = DRM_ERR(EINVAL);
134119895Sanholt	sis_free(fb.free);
135119895Sanholt
136119895Sanholt	DRM_DEBUG("free fb, offset = %d\n", fb.free);
137119895Sanholt
138119895Sanholt	return retval;
139119895Sanholt}
140119895Sanholt
141119895Sanholt#else
142119895Sanholt
143119895Sanholt/* Called by the X Server to initialize the FB heap.  Allocations will fail
144119895Sanholt * unless this is called.  Offset is the beginning of the heap from the
145119895Sanholt * framebuffer offset (MaxXFBMem in XFree86).
146119895Sanholt *
147119895Sanholt * Memory layout according to Thomas Winischofer:
148119895Sanholt * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
149119895Sanholt *
150119895Sanholt *    X driver/sisfb                                  HW-   Command-
151119895Sanholt *  framebuffer memory           DRI heap           Cursor   queue
152119895Sanholt */
153119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS )
154119895Sanholt{
155119895Sanholt	DRM_DEVICE;
156119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
157119895Sanholt	drm_sis_fb_t fb;
158119895Sanholt
159119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb));
160119895Sanholt
161119895Sanholt	if (dev_priv == NULL) {
162119895Sanholt		dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
163119895Sanholt		    DRM_MEM_DRIVER);
164119895Sanholt		dev_priv = dev->dev_private;
165119895Sanholt		if (dev_priv == NULL)
166119895Sanholt			return ENOMEM;
167119895Sanholt	}
168119895Sanholt
169119895Sanholt	if (dev_priv->FBHeap != NULL)
170119895Sanholt		return DRM_ERR(EINVAL);
171119895Sanholt
172119895Sanholt	dev_priv->FBHeap = mmInit(fb.offset, fb.size);
173119895Sanholt
174119895Sanholt	DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
175119895Sanholt
176119895Sanholt	return 0;
177119895Sanholt}
178119895Sanholt
179119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS )
180119895Sanholt{
181119895Sanholt	DRM_DEVICE;
182119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
183119895Sanholt	drm_sis_mem_t fb;
184119895Sanholt	PMemBlock block;
185119895Sanholt	int retval = 0;
186119895Sanholt
187119895Sanholt	if (dev_priv == NULL || dev_priv->FBHeap == NULL)
188119895Sanholt		return DRM_ERR(EINVAL);
189119895Sanholt
190119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
191119895Sanholt
192119895Sanholt	block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
193119895Sanholt	if (block) {
194119895Sanholt		/* TODO */
195119895Sanholt		fb.offset = block->ofs;
196119895Sanholt		fb.free = (unsigned long)block;
197119895Sanholt		if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
198119895Sanholt			DRM_DEBUG("adding to allocation set fails\n");
199119895Sanholt			mmFreeMem((PMemBlock)fb.free);
200119895Sanholt			retval = DRM_ERR(EINVAL);
201119895Sanholt		}
202119895Sanholt	} else {
203119895Sanholt		fb.offset = 0;
204119895Sanholt		fb.size = 0;
205119895Sanholt		fb.free = 0;
206119895Sanholt	}
207119895Sanholt
208119895Sanholt	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
209119895Sanholt
210119895Sanholt	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
211119895Sanholt
212119895Sanholt	return retval;
213119895Sanholt}
214119895Sanholt
215119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS )
216119895Sanholt{
217119895Sanholt	DRM_DEVICE;
218119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
219119895Sanholt	drm_sis_mem_t fb;
220119895Sanholt
221119895Sanholt	if (dev_priv == NULL || dev_priv->FBHeap == NULL)
222119895Sanholt		return DRM_ERR(EINVAL);
223119895Sanholt
224119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
225119895Sanholt
226119895Sanholt	if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
227119895Sanholt		return DRM_ERR(EINVAL);
228119895Sanholt
229119895Sanholt	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
230119895Sanholt		return DRM_ERR(EINVAL);
231119895Sanholt	mmFreeMem((PMemBlock)fb.free);
232119895Sanholt
233119895Sanholt	DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
234119895Sanholt
235119895Sanholt	return 0;
236119895Sanholt}
237119895Sanholt
238119895Sanholt#endif
239119895Sanholt
240119895Sanholt/* agp memory management */
241119895Sanholt
242119895Sanholtint sis_ioctl_agp_init( DRM_IOCTL_ARGS )
243119895Sanholt{
244119895Sanholt	DRM_DEVICE;
245119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
246119895Sanholt	drm_sis_agp_t agp;
247119895Sanholt
248119895Sanholt	if (dev_priv == NULL) {
249119895Sanholt		dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
250119895Sanholt		    DRM_MEM_DRIVER);
251119895Sanholt		dev_priv = dev->dev_private;
252119895Sanholt		if (dev_priv == NULL)
253119895Sanholt			return ENOMEM;
254119895Sanholt	}
255119895Sanholt
256119895Sanholt	if (dev_priv->AGPHeap != NULL)
257119895Sanholt		return DRM_ERR(EINVAL);
258119895Sanholt
259119895Sanholt	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp));
260119895Sanholt
261119895Sanholt	dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
262119895Sanholt
263119895Sanholt	DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
264119895Sanholt
265119895Sanholt	return 0;
266119895Sanholt}
267119895Sanholt
268119895Sanholtint sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
269119895Sanholt{
270119895Sanholt	DRM_DEVICE;
271119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
272119895Sanholt	drm_sis_mem_t agp;
273119895Sanholt	PMemBlock block;
274119895Sanholt	int retval = 0;
275119895Sanholt
276119895Sanholt	if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
277119895Sanholt		return DRM_ERR(EINVAL);
278119895Sanholt
279119895Sanholt	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
280119895Sanholt
281119895Sanholt	block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
282119895Sanholt	if (block) {
283119895Sanholt		/* TODO */
284119895Sanholt		agp.offset = block->ofs;
285119895Sanholt		agp.free = (unsigned long)block;
286119895Sanholt		if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
287119895Sanholt			DRM_DEBUG("adding to allocation set fails\n");
288119895Sanholt			mmFreeMem((PMemBlock)agp.free);
289119895Sanholt			retval = -1;
290119895Sanholt		}
291119895Sanholt	} else {
292119895Sanholt		agp.offset = 0;
293119895Sanholt		agp.size = 0;
294119895Sanholt		agp.free = 0;
295119895Sanholt	}
296119895Sanholt
297119895Sanholt	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp));
298119895Sanholt
299119895Sanholt	DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
300119895Sanholt
301119895Sanholt	return retval;
302119895Sanholt}
303119895Sanholt
304119895Sanholtint sis_ioctl_agp_free( DRM_IOCTL_ARGS )
305119895Sanholt{
306119895Sanholt	DRM_DEVICE;
307119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
308119895Sanholt	drm_sis_mem_t agp;
309119895Sanholt
310119895Sanholt	if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
311119895Sanholt		return DRM_ERR(EINVAL);
312119895Sanholt
313119895Sanholt	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
314119895Sanholt
315119895Sanholt	if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
316119895Sanholt		return DRM_ERR(EINVAL);
317119895Sanholt
318119895Sanholt	mmFreeMem((PMemBlock)agp.free);
319119895Sanholt	if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
320119895Sanholt		return DRM_ERR(EINVAL);
321119895Sanholt
322119895Sanholt	DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
323119895Sanholt
324119895Sanholt	return 0;
325119895Sanholt}
326119895Sanholt
327119895Sanholtint sis_init_context(int context)
328119895Sanholt{
329119895Sanholt	int i;
330119895Sanholt
331119895Sanholt	for (i = 0; i < MAX_CONTEXT ; i++) {
332119895Sanholt		if (global_ppriv[i].used &&
333119895Sanholt		    (global_ppriv[i].context == context))
334119895Sanholt			break;
335119895Sanholt	}
336119895Sanholt
337119895Sanholt	if (i >= MAX_CONTEXT) {
338119895Sanholt		for (i = 0; i < MAX_CONTEXT ; i++) {
339119895Sanholt			if (!global_ppriv[i].used) {
340119895Sanholt				global_ppriv[i].context = context;
341119895Sanholt				global_ppriv[i].used = 1;
342119895Sanholt				global_ppriv[i].sets[0] = setInit();
343119895Sanholt				global_ppriv[i].sets[1] = setInit();
344119895Sanholt				DRM_DEBUG("init allocation set, socket=%d, "
345119895Sanholt				    "context = %d\n", i, context);
346119895Sanholt				break;
347119895Sanholt			}
348119895Sanholt		}
349119895Sanholt		if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
350119895Sanholt		    (global_ppriv[i].sets[1] == NULL))
351119895Sanholt		{
352119895Sanholt			return 0;
353119895Sanholt		}
354119895Sanholt	}
355119895Sanholt
356119895Sanholt	return 1;
357119895Sanholt}
358119895Sanholt
359119895Sanholtint sis_final_context(int context)
360119895Sanholt{
361119895Sanholt	int i;
362119895Sanholt
363119895Sanholt	for (i=0; i<MAX_CONTEXT; i++) {
364119895Sanholt		if (global_ppriv[i].used &&
365119895Sanholt		    (global_ppriv[i].context == context))
366119895Sanholt			break;
367119895Sanholt	}
368119895Sanholt
369119895Sanholt	if (i < MAX_CONTEXT) {
370119895Sanholt		set_t *set;
371119895Sanholt		unsigned int item;
372119895Sanholt		int retval;
373119895Sanholt
374119895Sanholt		DRM_DEBUG("find socket %d, context = %d\n", i, context);
375119895Sanholt
376119895Sanholt		/* Video Memory */
377119895Sanholt		set = global_ppriv[i].sets[0];
378119895Sanholt		retval = setFirst(set, &item);
379119895Sanholt		while (retval) {
380119895Sanholt			DRM_DEBUG("free video memory 0x%x\n", item);
381119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS)
382119895Sanholt			sis_free(item);
383119895Sanholt#else
384119895Sanholt			mmFreeMem((PMemBlock)item);
385119895Sanholt#endif
386119895Sanholt			retval = setNext(set, &item);
387119895Sanholt		}
388119895Sanholt		setDestroy(set);
389119895Sanholt
390119895Sanholt		/* AGP Memory */
391119895Sanholt		set = global_ppriv[i].sets[1];
392119895Sanholt		retval = setFirst(set, &item);
393119895Sanholt		while (retval) {
394119895Sanholt			DRM_DEBUG("free agp memory 0x%x\n", item);
395119895Sanholt			mmFreeMem((PMemBlock)item);
396119895Sanholt			retval = setNext(set, &item);
397119895Sanholt		}
398119895Sanholt		setDestroy(set);
399119895Sanholt
400119895Sanholt		global_ppriv[i].used = 0;
401119895Sanholt        }
402119895Sanholt
403119895Sanholt	return 1;
404119895Sanholt}
405