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 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34#include "dev/drm/drmP.h"
35#include "dev/drm/drm.h"
36#include "dev/drm/sis_ds.h"
37
38/* Set Data Structure, not check repeated value
39 * temporarily used
40 */
41
42set_t *setInit(void)
43{
44	int i;
45	set_t *set;
46
47	set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
48	if (set != NULL) {
49		for (i = 0; i < SET_SIZE; i++) {
50			set->list[i].free_next = i + 1;
51			set->list[i].alloc_next = -1;
52		}
53		set->list[SET_SIZE - 1].free_next = -1;
54		set->free = 0;
55		set->alloc = -1;
56		set->trace = -1;
57	}
58	return set;
59}
60
61int setAdd(set_t * set, ITEM_TYPE item)
62{
63	int free = set->free;
64
65	if (free != -1) {
66		set->list[free].val = item;
67		set->free = set->list[free].free_next;
68	} else {
69		return 0;
70	}
71
72	set->list[free].alloc_next = set->alloc;
73	set->alloc = free;
74	set->list[free].free_next = -1;
75
76	return 1;
77}
78
79int setDel(set_t * set, ITEM_TYPE item)
80{
81	int alloc = set->alloc;
82	int prev = -1;
83
84	while (alloc != -1) {
85		if (set->list[alloc].val == item) {
86			if (prev != -1)
87				set->list[prev].alloc_next =
88				    set->list[alloc].alloc_next;
89			else
90				set->alloc = set->list[alloc].alloc_next;
91			break;
92		}
93		prev = alloc;
94		alloc = set->list[alloc].alloc_next;
95	}
96
97	if (alloc == -1)
98		return 0;
99
100	set->list[alloc].free_next = set->free;
101	set->free = alloc;
102	set->list[alloc].alloc_next = -1;
103
104	return 1;
105}
106
107/* setFirst -> setAdd -> setNext is wrong */
108
109int setFirst(set_t * set, ITEM_TYPE * item)
110{
111	if (set->alloc == -1)
112		return 0;
113
114	*item = set->list[set->alloc].val;
115	set->trace = set->list[set->alloc].alloc_next;
116
117	return 1;
118}
119
120int setNext(set_t * set, ITEM_TYPE * item)
121{
122	if (set->trace == -1)
123		return 0;
124
125	*item = set->list[set->trace].val;
126	set->trace = set->list[set->trace].alloc_next;
127
128	return 1;
129}
130
131int setDestroy(set_t * set)
132{
133	drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
134
135	return 1;
136}
137
138/*
139 * GLX Hardware Device Driver common code
140 * Copyright (C) 1999 Wittawat Yamwong
141 *
142 * Permission is hereby granted, free of charge, to any person obtaining a
143 * copy of this software and associated documentation files (the "Software"),
144 * to deal in the Software without restriction, including without limitation
145 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
146 * and/or sell copies of the Software, and to permit persons to whom the
147 * Software is furnished to do so, subject to the following conditions:
148 *
149 * The above copyright notice and this permission notice shall be included
150 * in all copies or substantial portions of the Software.
151 *
152 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
153 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
154 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
155 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
156 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
157 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
158 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
159 *
160 */
161
162#define ISFREE(bptr) ((bptr)->free)
163
164memHeap_t *mmInit(int ofs, int size)
165{
166	PMemBlock blocks;
167
168	if (size <= 0)
169		return NULL;
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 NULL;
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
199static TMemBlock *SliceBlock(TMemBlock * p,
200			     int startofs, int size,
201			     int reserved, int alignment)
202{
203	TMemBlock *newblock;
204
205	/* break left */
206	if (startofs > p->ofs) {
207		newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
208						    DRM_MEM_DRIVER);
209		newblock->ofs = startofs;
210		newblock->size = p->size - (startofs - p->ofs);
211		newblock->free = 1;
212		newblock->next = p->next;
213		p->size -= newblock->size;
214		p->next = newblock;
215		p = newblock;
216	}
217
218	/* break right */
219	if (size < p->size) {
220		newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
221						    DRM_MEM_DRIVER);
222		newblock->ofs = startofs + size;
223		newblock->size = p->size - size;
224		newblock->free = 1;
225		newblock->next = p->next;
226		p->size = size;
227		p->next = newblock;
228	}
229
230	/* p = middle block */
231	p->align = alignment;
232	p->free = 0;
233	p->reserved = reserved;
234	return p;
235}
236
237PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
238{
239	int mask, startofs, endofs;
240	TMemBlock *p;
241
242	if (heap == NULL || align2 < 0 || size <= 0)
243		return NULL;
244
245	mask = (1 << align2) - 1;
246	startofs = 0;
247	p = (TMemBlock *) heap;
248	while (p != NULL) {
249		if (ISFREE(p)) {
250			startofs = (p->ofs + mask) & ~mask;
251			if (startofs < startSearch) {
252				startofs = startSearch;
253			}
254			endofs = startofs + size;
255			if (endofs <= (p->ofs + p->size))
256				break;
257		}
258		p = p->next;
259	}
260	if (p == NULL)
261		return NULL;
262	p = SliceBlock(p, startofs, size, 0, mask + 1);
263	p->heap = heap;
264	return p;
265}
266
267static __inline__ int Join2Blocks(TMemBlock * p)
268{
269	if (p->free && p->next && p->next->free) {
270		TMemBlock *q = p->next;
271		p->size += q->size;
272		p->next = q->next;
273		drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
274		return 1;
275	}
276	return 0;
277}
278
279int mmFreeMem(PMemBlock b)
280{
281	TMemBlock *p, *prev;
282
283	if (b == NULL)
284		return 0;
285	if (b->heap == NULL)
286		return -1;
287
288	p = b->heap;
289	prev = NULL;
290	while (p != NULL && p != b) {
291		prev = p;
292		p = p->next;
293	}
294	if (p == NULL || p->free || p->reserved)
295		return -1;
296
297	p->free = 1;
298	Join2Blocks(p);
299	if (prev)
300		Join2Blocks(prev);
301	return 0;
302}
303