sis_ds.c revision 139749
1/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw */
3/*-
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
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:
13 *
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
16 * 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 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.
25 *
26 * Authors:
27 *    Sung-Ching Lin <sclin@sis.com.tw>
28 *
29 * $FreeBSD: head/sys/dev/drm/sis_ds.c 139749 2005-01-06 01:43:34Z imp $
30 */
31
32#include "dev/drm/sis.h"
33#include "dev/drm/drmP.h"
34#include "dev/drm/drm.h"
35#include "dev/drm/sis_ds.h"
36
37/* Set Data Structure, not check repeated value
38 * temporarily used
39 */
40
41set_t *setInit(void)
42{
43	int i;
44	set_t *set;
45
46	set = (set_t *)DRM(alloc)(sizeof(set_t), DRM_MEM_DRIVER);
47	if (set != NULL) {
48		for (i = 0; i < SET_SIZE; i++) {
49			set->list[i].free_next = i + 1;
50			set->list[i].alloc_next = -1;
51		}
52		set->list[SET_SIZE-1].free_next = -1;
53		set->free = 0;
54		set->alloc = -1;
55		set->trace = -1;
56	}
57	return set;
58}
59
60int setAdd(set_t *set, ITEM_TYPE item)
61{
62	int free = set->free;
63
64	if (free != -1) {
65		set->list[free].val = item;
66		set->free = set->list[free].free_next;
67	} else {
68		return 0;
69	}
70
71	set->list[free].alloc_next = set->alloc;
72	set->alloc = free;
73	set->list[free].free_next = -1;
74
75	return 1;
76}
77
78int setDel(set_t *set, ITEM_TYPE item)
79{
80	int alloc = set->alloc;
81	int prev = -1;
82
83	while (alloc != -1) {
84		if (set->list[alloc].val == item) {
85			if (prev != -1)
86				set->list[prev].alloc_next =
87				    set->list[alloc].alloc_next;
88			else
89				set->alloc = set->list[alloc].alloc_next;
90			break;
91		}
92		prev = alloc;
93		alloc = set->list[alloc].alloc_next;
94	}
95
96	if (alloc == -1)
97		return 0;
98
99	set->list[alloc].free_next = set->free;
100	set->free = alloc;
101	set->list[alloc].alloc_next = -1;
102
103	return 1;
104}
105
106/* setFirst -> setAdd -> setNext is wrong */
107
108int setFirst(set_t *set, ITEM_TYPE *item)
109{
110	if (set->alloc == -1)
111		return 0;
112
113	*item = set->list[set->alloc].val;
114	set->trace = set->list[set->alloc].alloc_next;
115
116	return 1;
117}
118
119int setNext(set_t *set, ITEM_TYPE *item)
120{
121	if (set->trace == -1)
122		return 0;
123
124	*item = set->list[set->trace].val;
125	set->trace = set->list[set->trace].alloc_next;
126
127	return 1;
128}
129
130int setDestroy(set_t *set)
131{
132	DRM(free)(set, sizeof(set_t), DRM_MEM_DRIVER);
133
134	return 1;
135}
136
137/*
138 * GLX Hardware Device Driver common code
139 * Copyright (C) 1999 Keith Whitwell
140 *
141 * Permission is hereby granted, free of charge, to any person obtaining a
142 * copy of this software and associated documentation files (the "Software"),
143 * to deal in the Software without restriction, including without limitation
144 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
145 * and/or sell copies of the Software, and to permit persons to whom the
146 * Software is furnished to do so, subject to the following conditions:
147 *
148 * The above copyright notice and this permission notice shall be included
149 * in all copies or substantial portions of the Software.
150 *
151 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
152 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
153 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
154 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
155 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
156 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
157 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
158 *
159 */
160
161#define ISFREE(bptr) ((bptr)->free)
162
163memHeap_t *mmInit(int ofs,
164		  int size)
165{
166	PMemBlock blocks;
167
168	if (size <= 0)
169		return 0;
170
171	blocks = (TMemBlock *)DRM(calloc)(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
172	if (blocks != NULL) {
173		blocks->ofs = ofs;
174		blocks->size = size;
175		blocks->free = 1;
176		return (memHeap_t *)blocks;
177	} else
178		return 0;
179}
180
181/* Checks if a pointer 'b' is part of the heap 'heap' */
182int mmBlockInHeap(memHeap_t *heap, PMemBlock b)
183{
184	TMemBlock *p;
185
186	if (heap == NULL || b == NULL)
187		return 0;
188
189	p = heap;
190	while (p != NULL && p != b) {
191		p = p->next;
192	}
193	if (p == b)
194		return 1;
195	else
196		return 0;
197}
198
199/* Kludgey workaround for existing i810 server.  Remove soon.
200 */
201memHeap_t *mmAddRange( memHeap_t *heap,
202		       int ofs,
203		       int size )
204{
205	PMemBlock blocks;
206	blocks = (TMemBlock *)DRM(calloc)(2, sizeof(TMemBlock), DRM_MEM_DRIVER);
207	if (blocks != NULL) {
208		blocks[0].size = size;
209		blocks[0].free = 1;
210		blocks[0].ofs = ofs;
211		blocks[0].next = &blocks[1];
212
213		/* Discontinuity - stops JoinBlock from trying to join
214		 * non-adjacent ranges.
215		 */
216		blocks[1].size = 0;
217		blocks[1].free = 0;
218		blocks[1].ofs = ofs+size;
219		blocks[1].next = (PMemBlock)heap;
220		return (memHeap_t *)blocks;
221	} else
222		return heap;
223}
224
225static TMemBlock* SliceBlock(TMemBlock *p,
226			     int startofs, int size,
227			     int reserved, int alignment)
228{
229	TMemBlock *newblock;
230
231	/* break left */
232	if (startofs > p->ofs) {
233		newblock = (TMemBlock*) DRM(calloc)(1, sizeof(TMemBlock),
234		    DRM_MEM_DRIVER);
235		newblock->ofs = startofs;
236		newblock->size = p->size - (startofs - p->ofs);
237		newblock->free = 1;
238		newblock->next = p->next;
239		p->size -= newblock->size;
240		p->next = newblock;
241		p = newblock;
242	}
243
244	/* break right */
245	if (size < p->size) {
246		newblock = (TMemBlock*) DRM(calloc)(1, sizeof(TMemBlock),
247		    DRM_MEM_DRIVER);
248		newblock->ofs = startofs + size;
249		newblock->size = p->size - size;
250		newblock->free = 1;
251		newblock->next = p->next;
252		p->size = size;
253		p->next = newblock;
254	}
255
256	/* p = middle block */
257	p->align = alignment;
258	p->free = 0;
259	p->reserved = reserved;
260	return p;
261}
262
263PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
264{
265	int mask,startofs, endofs;
266	TMemBlock *p;
267
268	if (heap == NULL || align2 < 0 || size <= 0)
269		return NULL;
270
271	mask = (1 << align2)-1;
272	startofs = 0;
273	p = (TMemBlock *)heap;
274	while (p != NULL) {
275		if (ISFREE(p)) {
276			startofs = (p->ofs + mask) & ~mask;
277			if ( startofs < startSearch ) {
278				startofs = startSearch;
279			}
280			endofs = startofs+size;
281			if (endofs <= (p->ofs+p->size))
282				break;
283		}
284		p = p->next;
285	}
286	if (p == NULL)
287		return NULL;
288	p = SliceBlock(p,startofs,size,0,mask+1);
289	p->heap = heap;
290	return p;
291}
292
293static __inline__ int Join2Blocks(TMemBlock *p)
294{
295	if (p->free && p->next && p->next->free) {
296		TMemBlock *q = p->next;
297		p->size += q->size;
298		p->next = q->next;
299		DRM(free)(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
300		return 1;
301	}
302	return 0;
303}
304
305int mmFreeMem(PMemBlock b)
306{
307	TMemBlock *p, *prev;
308
309	if (b == NULL)
310		return 0;
311	if (b->heap == NULL)
312		return -1;
313
314	p = b->heap;
315	prev = NULL;
316	while (p != NULL && p != b) {
317		prev = p;
318		p = p->next;
319	}
320	if (p == NULL || p->free || p->reserved)
321		return -1;
322
323	p->free = 1;
324	Join2Blocks(p);
325	if (prev)
326	Join2Blocks(prev);
327	return 0;
328}
329
330int mmReserveMem(memHeap_t *heap, int offset,int size)
331{
332	int endofs;
333	TMemBlock *p;
334
335	if (heap == NULL || size <= 0)
336		return -1;
337
338	endofs = offset + size;
339	p = (TMemBlock *)heap;
340	while (p && p->ofs <= offset) {
341		if (ISFREE(p) && endofs <= (p->ofs+p->size)) {
342			SliceBlock(p,offset,size,1,1);
343			return 0;
344		}
345		p = p->next;
346	}
347	return -1;
348}
349
350int mmFreeReserved(memHeap_t *heap, int offset)
351{
352	TMemBlock *p,*prev;
353
354	if (heap == NULL)
355		return -1;
356
357	p = (TMemBlock *)heap;
358	prev = NULL;
359	while (p != NULL && p->ofs != offset) {
360		prev = p;
361		p = p->next;
362	}
363	if (p == NULL || !p->reserved)
364		return -1;
365
366	p->free = 1;
367	p->reserved = 0;
368	Join2Blocks(p);
369	if (prev != NULL)
370		Join2Blocks(prev);
371	return 0;
372}
373
374void mmDestroy(memHeap_t *heap)
375{
376	TMemBlock *p,*q;
377
378	if (heap == NULL)
379		return;
380
381	p = (TMemBlock *)heap;
382	while (p != NULL) {
383		q = p->next;
384		DRM(free)(p, sizeof(TMemBlock), DRM_MEM_DRIVER);
385		p = q;
386	}
387}
388