1: /* $Header: vsalloc.c,v 10.3 86/02/01 15:47:58 tony Rel $ */
2: /* vsalloc.c routines to allocate and free vs framebuffer memory
3: *
4: * VSMemInit Initializes the free list
5: * VSAlloc Allocates a chunk of memory
6: * VSFree Frees a chunk of memory
7: *
8: * The method used is a variant on the method described in Knuth
9: * volume 1, page 441. The modification is that since we can't directly
10: * modify the memory in the vs, we maintain an ordered linked list of
11: * extents with either free chain pointers or addresses of blocks
12: *
13: */
14:
15: /****************************************************************************
16: * *
17: * Copyright (c) 1983, 1984 by *
18: * DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
19: * All rights reserved. *
20: * *
21: * This software is furnished on an as-is basis and may be used and copied *
22: * only with inclusion of the above copyright notice. This software or any *
23: * other copies thereof may be provided or otherwise made available to *
24: * others only for non-commercial purposes. No title to or ownership of *
25: * the software is hereby transferred. *
26: * *
27: * The information in this software is subject to change without notice *
28: * and should not be construed as a commitment by DIGITAL EQUIPMENT *
29: * CORPORATION. *
30: * *
31: * DIGITAL assumes no responsibility for the use or reliability of its *
32: * software on equipment which is not supplied by DIGITAL. *
33: * *
34: * *
35: ****************************************************************************/
36:
37: #include "vs100.h"
38: #include <errno.h>
39:
40: extern int errno;
41:
42: char *Xalloc();
43:
44: #define slopsize 10 /* Amount we're willing to overallocate */
45:
46: static VSArea listhead;
47:
48: /* Initialize the memory structures. Called by DownLoad, usually */
49:
50: int VSMemInit()
51: {
52: MemArea freefb, freepg;
53: register VSArea *fb, *buf, *pg;
54: VSArea *AllocVSArea();
55:
56: if (ReportStatus ((int *) NULL, (short *) NULL, (short *) NULL,
57: (BitMap *) NULL, &freefb, &freepg, (MemArea *) NULL,
58: 0) == -1) return (-1);
59:
60: if ((fb = AllocVSArea()) == NULL) return (-1);
61: if ((buf = AllocVSArea()) == NULL) return (-1);
62: if ((pg = AllocVSArea()) == NULL) return (-1);
63:
64: /* Make the list of memory areas */
65:
66: listhead.next = buf->prev = fb;
67: fb->next = pg->prev = buf;
68: buf->next = listhead.prev = pg;
69: pg->next = fb->prev = &listhead;
70:
71: /* Now set up the free list */
72:
73: listhead.vsFree.next = pg->vsFree.prev = fb;
74: fb->vsFree.next = listhead.vsFree.prev = pg;
75: pg->vsFree.next = fb->vsFree.prev = &listhead;
76:
77: /* Set up the sizes and addresses */
78:
79: listhead.vsPtr = NULL;
80: listhead.vsFreeFlag = VS_INUSE;
81: listhead.vsSize = 0;
82:
83: fb->vsPtr = *(caddr_t *) freefb.m_base;
84: fb->vsFreeFlag = VS_FREE;
85: fb->vsSize = *(long *) freefb.m_size;
86:
87: /* There's at least one version of the software that returns
88: bogus information there, so... (ug) */
89:
90: if (fb->vsPtr == (caddr_t) 0x12ee00) {
91: fb->vsPtr = (caddr_t) 0x117700;
92: fb->vsSize = 35072;
93: }
94:
95: /* Hack to deal with the crummy framebuffer bug: can't use
96: first 8 bytes */
97:
98: if (fb->vsPtr == (caddr_t) 0x117700) {
99: fb->vsPtr += 8;
100: fb->vsSize -= 8;
101: }
102:
103: buf->vsPtr = 0;
104: buf->vsFreeFlag = VS_INUSE;
105: buf->vsSize = 0;
106:
107: pg->vsPtr = *(caddr_t *) freepg.m_base;
108: pg->vsFreeFlag = VS_FREE;
109: pg->vsSize = *(long *) freepg.m_size;
110:
111: return (0);
112: }
113:
114: /* Allocate size bytes of specified type (bitmap, halftone, or font) */
115:
116: VSArea *VSAlloc (size, type)
117: int size, type;
118: {
119: register VSArea *f = listhead.vsFree.next, *new;
120:
121: /* Make sure size is a multiple of 2 */
122:
123: if (size & 0x1) size++;
124:
125: while (f != &listhead && f->vsSize < size) f = f->vsFree.next;
126:
127: if (f == &listhead) {
128: DeallocateSpace();
129: errno = ENOMEM;
130: return (NULL); /* No space */
131: }
132:
133: if (f->vsSize <= size + slopsize) { /* Don't split block */
134: f->vsFree.next->vsFree.prev = f->vsFree.prev;
135: f->vsFree.prev->vsFree.next = f->vsFree.next;
136: f->vsFreeFlag = VS_INUSE;
137: f->vsType = type;
138: return (f);
139:
140: } else { /* Split into two smaller blocks */
141: if ((new = AllocVSArea()) == NULL) return (NULL);
142: new->prev = f->prev;
143: new->next = f;
144: f->prev->next = new;
145: f->prev = new;
146: new->vsSize = size;
147: f->vsSize -= size;
148: new->vsPtr = f->vsPtr;
149: f->vsPtr += size;
150:
151: new->vsFreeFlag = VS_INUSE;
152: new->vsType = type;
153:
154: return (new);
155: }
156: }
157:
158: /* Free the allocated storage */
159:
160: int VSFree (block)
161: register VSArea *block;
162: {
163: register VSArea *temp;
164:
165: if (block->prev->vsFreeFlag == VS_FREE) { /* Coalesce areas */
166: temp = block;
167: block = block->prev;
168: block->vsSize += temp->vsSize;
169: block->next = temp->next;
170: temp->next->prev = block;
171: FreeVSArea (temp);
172: block->vsFree.next->vsFree.prev = block->vsFree.prev;
173: block->vsFree.prev->vsFree.next = block->vsFree.next;
174: }
175:
176: if (block->next->vsFreeFlag == VS_FREE) { /* ditto */
177: temp = block;
178: block = block->next;
179: block->vsPtr = temp->vsPtr;
180: block->vsSize += temp->vsSize;
181: block->prev = temp->prev;
182: temp->prev->next = block;
183: FreeVSArea (temp);
184: block->vsFree.next->vsFree.prev = block->vsFree.prev;
185: block->vsFree.prev->vsFree.next = block->vsFree.next;
186: }
187:
188: /* Link the block into the free list */
189:
190: block->vsFreeFlag = VS_FREE;
191: block->vsFree.next = listhead.vsFree.next;
192: block->vsFree.prev = &listhead;
193: listhead.vsFree.next->vsFree.prev = block;
194: listhead.vsFree.next = block;
195: }
196:
197: /* Boring routines to manage the allocation of the memory area descriptors
198: * on the Vax.
199: */
200:
201: static VSArea *freeVSAreaHead = NULL;
202: #define alloc_at_once 10
203:
204: VSArea *AllocVSArea()
205: {
206: register VSArea *block;
207: register int i;
208:
209: if ((block = freeVSAreaHead) == NULL) {
210: block = (VSArea *) Xalloc (alloc_at_once * sizeof (VSArea));
211: freeVSAreaHead = block;
212: i = alloc_at_once;
213: while (--i)
214: block = block->next = block + 1;
215: block->next = NULL;
216: block = freeVSAreaHead;
217: }
218: freeVSAreaHead = block->next;
219:
220: return (block);
221: }
222:
223: FreeVSArea(block)
224: VSArea *block;
225: {
226: block->next = freeVSAreaHead;
227: freeVSAreaHead = block;
228: }
Defined functions
Defined variables
Defined macros