sis_mm.c revision 130331
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 130331 2004-06-11 03:26:59Z 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)
38130331Sanholt#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
39130331Sanholt#include <video/sisfb.h>
40130331Sanholt#else
41119895Sanholt#include <linux/sisfb.h>
42119895Sanholt#endif
43130331Sanholt#endif
44119895Sanholt
45119895Sanholt#define MAX_CONTEXT 100
46119895Sanholt#define VIDEO_TYPE 0
47119895Sanholt#define AGP_TYPE 1
48119895Sanholt
49119895Sanholttypedef struct {
50119895Sanholt	int used;
51119895Sanholt	int context;
52119895Sanholt	set_t *sets[2]; /* 0 for video, 1 for AGP */
53119895Sanholt} sis_context_t;
54119895Sanholt
55119895Sanholtstatic sis_context_t global_ppriv[MAX_CONTEXT];
56119895Sanholt
57119895Sanholt
58119895Sanholtstatic int add_alloc_set(int context, int type, unsigned int val)
59119895Sanholt{
60119895Sanholt	int i, retval = 0;
61119895Sanholt
62119895Sanholt	for (i = 0; i < MAX_CONTEXT; i++) {
63119895Sanholt		if (global_ppriv[i].used && global_ppriv[i].context == context)
64119895Sanholt		{
65119895Sanholt			retval = setAdd(global_ppriv[i].sets[type], val);
66119895Sanholt			break;
67119895Sanholt		}
68119895Sanholt	}
69119895Sanholt	return retval;
70119895Sanholt}
71119895Sanholt
72119895Sanholtstatic int del_alloc_set(int context, int type, unsigned int val)
73119895Sanholt{
74119895Sanholt	int i, retval = 0;
75119895Sanholt
76119895Sanholt	for (i = 0; i < MAX_CONTEXT; i++) {
77119895Sanholt		if (global_ppriv[i].used && global_ppriv[i].context == context)
78119895Sanholt		{
79119895Sanholt			retval = setDel(global_ppriv[i].sets[type], val);
80119895Sanholt			break;
81119895Sanholt		}
82119895Sanholt	}
83119895Sanholt	return retval;
84119895Sanholt}
85119895Sanholt
86119895Sanholt/* fb management via fb device */
87119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS)
88119895Sanholt
89119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS )
90119895Sanholt{
91119895Sanholt	return 0;
92119895Sanholt}
93119895Sanholt
94119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS )
95119895Sanholt{
96119895Sanholt	drm_sis_mem_t fb;
97119895Sanholt	struct sis_memreq req;
98119895Sanholt	int retval = 0;
99119895Sanholt
100119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
101119895Sanholt
102119895Sanholt	req.size = fb.size;
103119895Sanholt	sis_malloc(&req);
104119895Sanholt	if (req.offset) {
105119895Sanholt		/* TODO */
106119895Sanholt		fb.offset = req.offset;
107119895Sanholt		fb.free = req.offset;
108119895Sanholt		if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
109119895Sanholt			DRM_DEBUG("adding to allocation set fails\n");
110119895Sanholt			sis_free(req.offset);
111119895Sanholt			retval = DRM_ERR(EINVAL);
112119895Sanholt		}
113119895Sanholt	} else {
114119895Sanholt		fb.offset = 0;
115119895Sanholt		fb.size = 0;
116119895Sanholt		fb.free = 0;
117119895Sanholt	}
118119895Sanholt
119119895Sanholt	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
120119895Sanholt
121119895Sanholt	DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
122119895Sanholt
123119895Sanholt	return retval;
124119895Sanholt}
125119895Sanholt
126119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS )
127119895Sanholt{
128119895Sanholt	drm_sis_mem_t fb;
129119895Sanholt	int retval = 0;
130119895Sanholt
131119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
132119895Sanholt
133119895Sanholt	if (!fb.free)
134119895Sanholt		return DRM_ERR(EINVAL);
135119895Sanholt
136119895Sanholt	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
137119895Sanholt		retval = DRM_ERR(EINVAL);
138119895Sanholt	sis_free(fb.free);
139119895Sanholt
140121447Sanholt	DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
141119895Sanholt
142119895Sanholt	return retval;
143119895Sanholt}
144119895Sanholt
145119895Sanholt#else
146119895Sanholt
147119895Sanholt/* Called by the X Server to initialize the FB heap.  Allocations will fail
148119895Sanholt * unless this is called.  Offset is the beginning of the heap from the
149119895Sanholt * framebuffer offset (MaxXFBMem in XFree86).
150119895Sanholt *
151119895Sanholt * Memory layout according to Thomas Winischofer:
152119895Sanholt * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
153119895Sanholt *
154119895Sanholt *    X driver/sisfb                                  HW-   Command-
155119895Sanholt *  framebuffer memory           DRI heap           Cursor   queue
156119895Sanholt */
157119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS )
158119895Sanholt{
159119895Sanholt	DRM_DEVICE;
160119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
161119895Sanholt	drm_sis_fb_t fb;
162119895Sanholt
163119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb));
164119895Sanholt
165119895Sanholt	if (dev_priv == NULL) {
166119895Sanholt		dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
167119895Sanholt		    DRM_MEM_DRIVER);
168119895Sanholt		dev_priv = dev->dev_private;
169119895Sanholt		if (dev_priv == NULL)
170119895Sanholt			return ENOMEM;
171119895Sanholt	}
172119895Sanholt
173119895Sanholt	if (dev_priv->FBHeap != NULL)
174119895Sanholt		return DRM_ERR(EINVAL);
175119895Sanholt
176119895Sanholt	dev_priv->FBHeap = mmInit(fb.offset, fb.size);
177119895Sanholt
178119895Sanholt	DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
179119895Sanholt
180119895Sanholt	return 0;
181119895Sanholt}
182119895Sanholt
183119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS )
184119895Sanholt{
185119895Sanholt	DRM_DEVICE;
186119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
187119895Sanholt	drm_sis_mem_t fb;
188119895Sanholt	PMemBlock block;
189119895Sanholt	int retval = 0;
190119895Sanholt
191119895Sanholt	if (dev_priv == NULL || dev_priv->FBHeap == NULL)
192119895Sanholt		return DRM_ERR(EINVAL);
193119895Sanholt
194119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
195119895Sanholt
196119895Sanholt	block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
197119895Sanholt	if (block) {
198119895Sanholt		/* TODO */
199119895Sanholt		fb.offset = block->ofs;
200119895Sanholt		fb.free = (unsigned long)block;
201119895Sanholt		if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
202119895Sanholt			DRM_DEBUG("adding to allocation set fails\n");
203119895Sanholt			mmFreeMem((PMemBlock)fb.free);
204119895Sanholt			retval = DRM_ERR(EINVAL);
205119895Sanholt		}
206119895Sanholt	} else {
207119895Sanholt		fb.offset = 0;
208119895Sanholt		fb.size = 0;
209119895Sanholt		fb.free = 0;
210119895Sanholt	}
211119895Sanholt
212119895Sanholt	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
213119895Sanholt
214119895Sanholt	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
215119895Sanholt
216119895Sanholt	return retval;
217119895Sanholt}
218119895Sanholt
219119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS )
220119895Sanholt{
221119895Sanholt	DRM_DEVICE;
222119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
223119895Sanholt	drm_sis_mem_t fb;
224119895Sanholt
225119895Sanholt	if (dev_priv == NULL || dev_priv->FBHeap == NULL)
226119895Sanholt		return DRM_ERR(EINVAL);
227119895Sanholt
228119895Sanholt	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
229119895Sanholt
230119895Sanholt	if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
231119895Sanholt		return DRM_ERR(EINVAL);
232119895Sanholt
233119895Sanholt	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
234119895Sanholt		return DRM_ERR(EINVAL);
235119895Sanholt	mmFreeMem((PMemBlock)fb.free);
236119895Sanholt
237119895Sanholt	DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
238119895Sanholt
239119895Sanholt	return 0;
240119895Sanholt}
241119895Sanholt
242119895Sanholt#endif
243119895Sanholt
244119895Sanholt/* agp memory management */
245119895Sanholt
246119895Sanholtint sis_ioctl_agp_init( DRM_IOCTL_ARGS )
247119895Sanholt{
248119895Sanholt	DRM_DEVICE;
249119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
250119895Sanholt	drm_sis_agp_t agp;
251119895Sanholt
252119895Sanholt	if (dev_priv == NULL) {
253119895Sanholt		dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
254119895Sanholt		    DRM_MEM_DRIVER);
255119895Sanholt		dev_priv = dev->dev_private;
256119895Sanholt		if (dev_priv == NULL)
257119895Sanholt			return ENOMEM;
258119895Sanholt	}
259119895Sanholt
260119895Sanholt	if (dev_priv->AGPHeap != NULL)
261119895Sanholt		return DRM_ERR(EINVAL);
262119895Sanholt
263119895Sanholt	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp));
264119895Sanholt
265119895Sanholt	dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
266119895Sanholt
267119895Sanholt	DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
268119895Sanholt
269119895Sanholt	return 0;
270119895Sanholt}
271119895Sanholt
272119895Sanholtint sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
273119895Sanholt{
274119895Sanholt	DRM_DEVICE;
275119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
276119895Sanholt	drm_sis_mem_t agp;
277119895Sanholt	PMemBlock block;
278119895Sanholt	int retval = 0;
279119895Sanholt
280119895Sanholt	if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
281119895Sanholt		return DRM_ERR(EINVAL);
282119895Sanholt
283119895Sanholt	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
284119895Sanholt
285119895Sanholt	block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
286119895Sanholt	if (block) {
287119895Sanholt		/* TODO */
288119895Sanholt		agp.offset = block->ofs;
289119895Sanholt		agp.free = (unsigned long)block;
290119895Sanholt		if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
291119895Sanholt			DRM_DEBUG("adding to allocation set fails\n");
292119895Sanholt			mmFreeMem((PMemBlock)agp.free);
293119895Sanholt			retval = -1;
294119895Sanholt		}
295119895Sanholt	} else {
296119895Sanholt		agp.offset = 0;
297119895Sanholt		agp.size = 0;
298119895Sanholt		agp.free = 0;
299119895Sanholt	}
300119895Sanholt
301119895Sanholt	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp));
302119895Sanholt
303119895Sanholt	DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
304119895Sanholt
305119895Sanholt	return retval;
306119895Sanholt}
307119895Sanholt
308119895Sanholtint sis_ioctl_agp_free( DRM_IOCTL_ARGS )
309119895Sanholt{
310119895Sanholt	DRM_DEVICE;
311119895Sanholt	drm_sis_private_t *dev_priv = dev->dev_private;
312119895Sanholt	drm_sis_mem_t agp;
313119895Sanholt
314119895Sanholt	if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
315119895Sanholt		return DRM_ERR(EINVAL);
316119895Sanholt
317119895Sanholt	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
318119895Sanholt
319119895Sanholt	if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
320119895Sanholt		return DRM_ERR(EINVAL);
321119895Sanholt
322119895Sanholt	mmFreeMem((PMemBlock)agp.free);
323119895Sanholt	if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
324119895Sanholt		return DRM_ERR(EINVAL);
325119895Sanholt
326119895Sanholt	DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
327119895Sanholt
328119895Sanholt	return 0;
329119895Sanholt}
330119895Sanholt
331119895Sanholtint sis_init_context(int context)
332119895Sanholt{
333119895Sanholt	int i;
334119895Sanholt
335119895Sanholt	for (i = 0; i < MAX_CONTEXT ; i++) {
336119895Sanholt		if (global_ppriv[i].used &&
337119895Sanholt		    (global_ppriv[i].context == context))
338119895Sanholt			break;
339119895Sanholt	}
340119895Sanholt
341119895Sanholt	if (i >= MAX_CONTEXT) {
342119895Sanholt		for (i = 0; i < MAX_CONTEXT ; i++) {
343119895Sanholt			if (!global_ppriv[i].used) {
344119895Sanholt				global_ppriv[i].context = context;
345119895Sanholt				global_ppriv[i].used = 1;
346119895Sanholt				global_ppriv[i].sets[0] = setInit();
347119895Sanholt				global_ppriv[i].sets[1] = setInit();
348119895Sanholt				DRM_DEBUG("init allocation set, socket=%d, "
349119895Sanholt				    "context = %d\n", i, context);
350119895Sanholt				break;
351119895Sanholt			}
352119895Sanholt		}
353119895Sanholt		if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
354119895Sanholt		    (global_ppriv[i].sets[1] == NULL))
355119895Sanholt		{
356119895Sanholt			return 0;
357119895Sanholt		}
358119895Sanholt	}
359119895Sanholt
360119895Sanholt	return 1;
361119895Sanholt}
362119895Sanholt
363119895Sanholtint sis_final_context(int context)
364119895Sanholt{
365119895Sanholt	int i;
366119895Sanholt
367119895Sanholt	for (i=0; i<MAX_CONTEXT; i++) {
368119895Sanholt		if (global_ppriv[i].used &&
369119895Sanholt		    (global_ppriv[i].context == context))
370119895Sanholt			break;
371119895Sanholt	}
372119895Sanholt
373119895Sanholt	if (i < MAX_CONTEXT) {
374119895Sanholt		set_t *set;
375126525Sobrien		ITEM_TYPE item;
376119895Sanholt		int retval;
377119895Sanholt
378119895Sanholt		DRM_DEBUG("find socket %d, context = %d\n", i, context);
379119895Sanholt
380119895Sanholt		/* Video Memory */
381119895Sanholt		set = global_ppriv[i].sets[0];
382119895Sanholt		retval = setFirst(set, &item);
383119895Sanholt		while (retval) {
384126525Sobrien			DRM_DEBUG("free video memory 0x%lx\n", item);
385119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS)
386119895Sanholt			sis_free(item);
387119895Sanholt#else
388119895Sanholt			mmFreeMem((PMemBlock)item);
389119895Sanholt#endif
390119895Sanholt			retval = setNext(set, &item);
391119895Sanholt		}
392119895Sanholt		setDestroy(set);
393119895Sanholt
394119895Sanholt		/* AGP Memory */
395119895Sanholt		set = global_ppriv[i].sets[1];
396119895Sanholt		retval = setFirst(set, &item);
397119895Sanholt		while (retval) {
398126525Sobrien			DRM_DEBUG("free agp memory 0x%lx\n", item);
399119895Sanholt			mmFreeMem((PMemBlock)item);
400119895Sanholt			retval = setNext(set, &item);
401119895Sanholt		}
402119895Sanholt		setDestroy(set);
403119895Sanholt
404119895Sanholt		global_ppriv[i].used = 0;
405119895Sanholt        }
406119895Sanholt
407119895Sanholt	return 1;
408119895Sanholt}
409