1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Fixes:
25 * Changed to use via_ prefixes on globals
26 * Fixed malloc failure paths
27 * Reformatted to Linux style
28 * Removed ITEM_TYPE typedef, FREE/MALLOC and other macro bits
29 */
30
31 #define __NO_VERSION__
32 #include <linux/module.h>
33 #include <linux/delay.h>
34 #include <linux/errno.h>
35 #include <linux/kernel.h>
36 #include <linux/slab.h>
37 #include <linux/poll.h>
38 #include <asm/io.h>
39 #include <linux/pci.h>
40
41 #include "via_ds.h"
42
43 #warning "Fix variable/global names to use via_"
44
45 extern unsigned int VIA_DEBUG;
46
via_set_init(void)47 set_t *via_set_init(void)
48 {
49 int i;
50 set_t *set;
51 set = (set_t *)kmalloc(sizeof(set_t), GFP_KERNEL);
52 if(set == NULL)
53 return NULL;
54 for (i = 0; i < SET_SIZE; i++) {
55 set->list[i].free_next = i + 1;
56 set->list[i].alloc_next = -1;
57 }
58 set->list[SET_SIZE - 1].free_next = -1;
59 set->free = 0;
60 set->alloc = -1;
61 set->trace = -1;
62 return set;
63 }
64
via_set_add(set_t * set,unsigned int item)65 int via_set_add(set_t * set, unsigned int item)
66 {
67 int free = set->free;
68 if (free != -1) {
69 set->list[free].val = item;
70 set->free = set->list[free].free_next;
71 } else {
72 return 0;
73 }
74 set->list[free].alloc_next = set->alloc;
75 set->alloc = free;
76 set->list[free].free_next = -1;
77 return 1;
78 }
79
via_set_del(set_t * set,unsigned int item)80 int via_set_del(set_t * set, unsigned int item)
81 {
82 int alloc = set->alloc;
83 int prev = -1;
84
85 while (alloc != -1) {
86 if (set->list[alloc].val == item) {
87 if (prev != -1)
88 set->list[prev].alloc_next = 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
via_set_first(set_t * set,unsigned int * item)109 int via_set_first(set_t * set, unsigned int * 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
118 return 1;
119 }
120
via_set_next(set_t * set,unsigned int * item)121 int via_set_next(set_t * set, unsigned int * item)
122 {
123 if (set->trace == -1)
124 return 0;
125
126 *item = set->list[set->trace].val;
127 set->trace = set->list[set->trace].alloc_next;
128
129 return 1;
130 }
131
via_set_destroy(set_t * set)132 int via_set_destroy(set_t * set)
133 {
134 kfree(set);
135 return 1;
136 }
137
138 #define ISFREE(bptr) ((bptr)->free)
139
140 #define PRINTF(fmt, arg...) do{}while(0)
141
via_mmDumpMemInfo(memHeap_t * heap)142 void via_mmDumpMemInfo(memHeap_t * heap)
143 {
144 TMemBlock *p;
145
146 PRINTF("Memory heap %p:\n", heap);
147
148 if (heap == 0)
149 PRINTF(" heap == 0\n");
150 else {
151 p = (TMemBlock *) heap;
152
153 while (p) {
154 PRINTF(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, p->free ? '.' : 'U', p->reserved ? 'R' : '.');
155 p = p->next;
156 }
157 }
158
159 PRINTF("End of memory blocks\n");
160 }
161
via_mmInit(int ofs,int size)162 memHeap_t *via_mmInit(int ofs, int size)
163 {
164 PMemBlock blocks;
165
166 if (size <= 0)
167 return 0;
168
169
170 blocks = (TMemBlock *) kmalloc(sizeof(TMemBlock), GFP_KERNEL);
171
172 if (blocks) {
173 memset(blocks, 0, sizeof(TMemBlock));
174 blocks->ofs = ofs;
175 blocks->size = size;
176 blocks->free = 1;
177 return (memHeap_t *) blocks;
178 } else
179 return NULL;
180 }
181
via_mmAddRange(memHeap_t * heap,int ofs,int size)182 memHeap_t *via_mmAddRange(memHeap_t * heap, int ofs, int size)
183 {
184 PMemBlock blocks;
185 blocks = (TMemBlock *) kmalloc(2 * sizeof(TMemBlock), GFP_KERNEL);
186
187 if (blocks) {
188 memset(blocks, 0, 2 * sizeof(TMemBlock));
189 blocks[0].size = size;
190 blocks[0].free = 1;
191 blocks[0].ofs = ofs;
192 blocks[0].next = &blocks[1];
193
194 /* Discontinuity - stops JoinBlock from trying to join non-adjacent
195 * ranges.
196 */
197 blocks[1].size = 0;
198 blocks[1].free = 0;
199 blocks[1].ofs = ofs + size;
200 blocks[1].next = (PMemBlock) heap;
201 return (memHeap_t *) blocks;
202 } else
203 return heap;
204 }
205
SliceBlock(TMemBlock * p,int startofs,int size,int reserved,int alignment)206 static TMemBlock *SliceBlock(TMemBlock * p, int startofs, int size, int reserved, int alignment)
207 {
208 TMemBlock *newblock;
209
210 /* break left */
211 if (startofs > p->ofs) {
212 newblock = (TMemBlock *) kmalloc(sizeof(TMemBlock), GFP_KERNEL);
213 if(newblock == NULL)
214 return NULL;
215 memset(newblock, 0, sizeof(TMemBlock));
216 newblock->ofs = startofs;
217 newblock->size = p->size - (startofs - p->ofs);
218 newblock->free = 1;
219 newblock->next = p->next;
220 p->size -= newblock->size;
221 p->next = newblock;
222 p = newblock;
223 }
224
225 /* break right */
226 if (size < p->size) {
227 newblock = (TMemBlock *) kmalloc(sizeof(TMemBlock), GFP_KERNEL);
228 if(newblock == NULL)
229 return NULL;
230 memset(newblock, 0, sizeof(TMemBlock));
231 newblock->ofs = startofs + size;
232 newblock->size = p->size - size;
233 newblock->free = 1;
234 newblock->next = p->next;
235 p->size = size;
236 p->next = newblock;
237 }
238
239 /* p = middle block */
240 p->align = alignment;
241 p->free = 0;
242 p->reserved = reserved;
243 return p;
244 }
245
via_mmAllocMem(memHeap_t * heap,int size,int align2,int startSearch)246 PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
247 {
248 int mask, startofs, endofs;
249 TMemBlock *p;
250
251 if (!heap || align2 < 0 || size <= 0)
252 return NULL;
253
254 mask = (1 << align2) - 1;
255 startofs = 0;
256 p = (TMemBlock *) heap;
257
258 while (p) {
259 if (ISFREE(p)) {
260 startofs = (p->ofs + mask) & ~mask;
261
262 if (startofs < startSearch)
263 startofs = startSearch;
264
265 endofs = startofs + size;
266
267 if (endofs <= (p->ofs + p->size))
268 break;
269 }
270
271 p = p->next;
272 }
273
274 if (!p)
275 return NULL;
276
277 p = SliceBlock(p, startofs, size, 0, mask + 1);
278 p->heap = heap;
279
280 return p;
281 }
282
Join2Blocks(TMemBlock * p)283 static __inline__ int Join2Blocks(TMemBlock * p)
284 {
285 if (p->free && p->next && p->next->free) {
286 TMemBlock *q = p->next;
287 p->size += q->size;
288 p->next = q->next;
289 kfree(q);
290
291 return 1;
292 }
293
294 return 0;
295 }
296
via_mmFreeMem(PMemBlock b)297 int via_mmFreeMem(PMemBlock b)
298 {
299 TMemBlock *p, *prev;
300
301 if (!b)
302 return 0;
303
304 if (!b->heap) {
305 return -1;
306 }
307
308 p = b->heap;
309 prev = NULL;
310
311 while (p && p != b) {
312 prev = p;
313 p = p->next;
314 }
315
316 if (!p || p->free || p->reserved) {
317 if (!p)
318 BUG();
319 else if (p->free)
320 BUG();
321 else
322 BUG();
323 return -1;
324 }
325
326 p->free = 1;
327 Join2Blocks(p);
328
329 if (prev)
330 Join2Blocks(prev);
331
332 return 0;
333 }
334
via_mm_ReserveMem(memHeap_t * heap,int offset,int size)335 int via_mm_ReserveMem(memHeap_t * heap, int offset, int size)
336 {
337 int endofs;
338 TMemBlock *p;
339
340 if (!heap || size <= 0)
341 return -1;
342 endofs = offset + size;
343 p = (TMemBlock *) heap;
344
345 while (p && p->ofs <= offset) {
346 if (ISFREE(p) && endofs <= (p->ofs + p->size)) {
347 SliceBlock(p, offset, size, 1, 1);
348 return 0;
349 }
350 p = p->next;
351 }
352 return -1;
353 }
354
via_mm_FreeReserved(memHeap_t * heap,int offset)355 int via_mm_FreeReserved(memHeap_t * heap, int offset)
356 {
357 TMemBlock *p, *prev;
358
359 if (!heap)
360 return -1;
361
362 p = (TMemBlock *) heap;
363 prev = NULL;
364
365 while (p && p->ofs != offset) {
366 prev = p;
367 p = p->next;
368 }
369
370 if (!p || !p->reserved)
371 return -1;
372 p->free = 1;
373 p->reserved = 0;
374 Join2Blocks(p);
375
376 if (prev)
377 Join2Blocks(prev);
378
379 return 0;
380 }
381
via_mm_Destroy(memHeap_t * heap)382 void via_mm_Destroy(memHeap_t * heap)
383 {
384 TMemBlock *p, *q;
385
386 if (!heap)
387 return;
388 p = (TMemBlock *) heap;
389
390 while (p) {
391 q = p->next;
392 kfree(p);
393 p = q;
394 }
395 }
396