File: /usr/src/linux/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
1 /*
2 * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation
3 *
4 * Copyright (c) 1997 Justin T. Gibbs.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL").
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $Id: //depot/src/aic7xxx/aicasm/aicasm_symbol.c#7 $
32 *
33 * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_symbol.c,v 1.11 2000/09/22 22:19:54 gibbs Exp $
34 */
35
36 #include <sys/types.h>
37
38 #ifdef __linux__
39 #include "aicdb.h"
40 #else
41 #include <db.h>
42 #endif
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sysexits.h>
48
49 #include "aicasm_symbol.h"
50 #include "aicasm.h"
51
52 static DB *symtable;
53
54 symbol_t *
55 symbol_create(char *name)
56 {
57 symbol_t *new_symbol;
58
59 new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
60 if (new_symbol == NULL) {
61 perror("Unable to create new symbol");
62 exit(EX_SOFTWARE);
63 }
64 memset(new_symbol, 0, sizeof(*new_symbol));
65 new_symbol->name = strdup(name);
66 new_symbol->type = UNINITIALIZED;
67 return (new_symbol);
68 }
69
70 void
71 symbol_delete(symbol_t *symbol)
72 {
73 if (symtable != NULL) {
74 DBT key;
75
76 key.data = symbol->name;
77 key.size = strlen(symbol->name);
78 symtable->del(symtable, &key, /*flags*/0);
79 }
80 switch(symbol->type) {
81 case SCBLOC:
82 case SRAMLOC:
83 case REGISTER:
84 if (symbol->info.rinfo != NULL)
85 free(symbol->info.rinfo);
86 break;
87 case ALIAS:
88 if (symbol->info.ainfo != NULL)
89 free(symbol->info.ainfo);
90 break;
91 case MASK:
92 case BIT:
93 if (symbol->info.minfo != NULL) {
94 symlist_free(&symbol->info.minfo->symrefs);
95 free(symbol->info.minfo);
96 }
97 break;
98 case DOWNLOAD_CONST:
99 case CONST:
100 if (symbol->info.cinfo != NULL)
101 free(symbol->info.cinfo);
102 break;
103 case LABEL:
104 if (symbol->info.linfo != NULL)
105 free(symbol->info.linfo);
106 break;
107 case UNINITIALIZED:
108 default:
109 break;
110 }
111 free(symbol->name);
112 free(symbol);
113 }
114
115 void
116 symtable_open()
117 {
118 symtable = dbopen(/*filename*/NULL,
119 O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
120 /*openinfo*/NULL);
121
122 if (symtable == NULL) {
123 perror("Symbol table creation failed");
124 exit(EX_SOFTWARE);
125 /* NOTREACHED */
126 }
127 }
128
129 void
130 symtable_close()
131 {
132 if (symtable != NULL) {
133 DBT key;
134 DBT data;
135
136 while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
137 symbol_t *stored_ptr;
138
139 memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
140 symbol_delete(stored_ptr);
141 }
142 symtable->close(symtable);
143 }
144 }
145
146 /*
147 * The semantics of get is to return an uninitialized symbol entry
148 * if a lookup fails.
149 */
150 symbol_t *
151 symtable_get(char *name)
152 {
153 symbol_t *stored_ptr;
154 DBT key;
155 DBT data;
156 int retval;
157
158 key.data = (void *)name;
159 key.size = strlen(name);
160
161 if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
162 if (retval == -1) {
163 perror("Symbol table get operation failed");
164 exit(EX_SOFTWARE);
165 /* NOTREACHED */
166 } else if (retval == 1) {
167 /* Symbol wasn't found, so create a new one */
168 symbol_t *new_symbol;
169
170 new_symbol = symbol_create(name);
171 data.data = &new_symbol;
172 data.size = sizeof(new_symbol);
173 if (symtable->put(symtable, &key, &data,
174 /*flags*/0) !=0) {
175 perror("Symtable put failed");
176 exit(EX_SOFTWARE);
177 }
178 return (new_symbol);
179 } else {
180 perror("Unexpected return value from db get routine");
181 exit(EX_SOFTWARE);
182 /* NOTREACHED */
183 }
184 }
185 memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
186 return (stored_ptr);
187 }
188
189 symbol_node_t *
190 symlist_search(symlist_t *symlist, char *symname)
191 {
192 symbol_node_t *curnode;
193
194 curnode = SLIST_FIRST(symlist);
195 while(curnode != NULL) {
196 if (strcmp(symname, curnode->symbol->name) == 0)
197 break;
198 curnode = SLIST_NEXT(curnode, links);
199 }
200 return (curnode);
201 }
202
203 void
204 symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
205 {
206 symbol_node_t *newnode;
207
208 newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
209 if (newnode == NULL) {
210 stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
211 /* NOTREACHED */
212 }
213 newnode->symbol = symbol;
214 if (how == SYMLIST_SORT) {
215 symbol_node_t *curnode;
216 int mask;
217
218 mask = FALSE;
219 switch(symbol->type) {
220 case REGISTER:
221 case SCBLOC:
222 case SRAMLOC:
223 break;
224 case BIT:
225 case MASK:
226 mask = TRUE;
227 break;
228 default:
229 stop("symlist_add: Invalid symbol type for sorting",
230 EX_SOFTWARE);
231 /* NOTREACHED */
232 }
233
234 curnode = SLIST_FIRST(symlist);
235 if (curnode == NULL
236 || (mask && (curnode->symbol->info.minfo->mask >
237 newnode->symbol->info.minfo->mask))
238 || (!mask && (curnode->symbol->info.rinfo->address >
239 newnode->symbol->info.rinfo->address))) {
240 SLIST_INSERT_HEAD(symlist, newnode, links);
241 return;
242 }
243
244 while (1) {
245 if (SLIST_NEXT(curnode, links) == NULL) {
246 SLIST_INSERT_AFTER(curnode, newnode,
247 links);
248 break;
249 } else {
250 symbol_t *cursymbol;
251
252 cursymbol = SLIST_NEXT(curnode, links)->symbol;
253 if ((mask && (cursymbol->info.minfo->mask >
254 symbol->info.minfo->mask))
255 || (!mask &&(cursymbol->info.rinfo->address >
256 symbol->info.rinfo->address))){
257 SLIST_INSERT_AFTER(curnode, newnode,
258 links);
259 break;
260 }
261 }
262 curnode = SLIST_NEXT(curnode, links);
263 }
264 } else {
265 SLIST_INSERT_HEAD(symlist, newnode, links);
266 }
267 }
268
269 void
270 symlist_free(symlist_t *symlist)
271 {
272 symbol_node_t *node1, *node2;
273
274 node1 = SLIST_FIRST(symlist);
275 while (node1 != NULL) {
276 node2 = SLIST_NEXT(node1, links);
277 free(node1);
278 node1 = node2;
279 }
280 SLIST_INIT(symlist);
281 }
282
283 void
284 symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
285 symlist_t *symlist_src2)
286 {
287 symbol_node_t *node;
288
289 *symlist_dest = *symlist_src1;
290 while((node = SLIST_FIRST(symlist_src2)) != NULL) {
291 SLIST_REMOVE_HEAD(symlist_src2, links);
292 SLIST_INSERT_HEAD(symlist_dest, node, links);
293 }
294
295 /* These are now empty */
296 SLIST_INIT(symlist_src1);
297 SLIST_INIT(symlist_src2);
298 }
299
300 void
301 symtable_dump(FILE *ofile)
302 {
303 /*
304 * Sort the registers by address with a simple insertion sort.
305 * Put bitmasks next to the first register that defines them.
306 * Put constants at the end.
307 */
308 symlist_t registers;
309 symlist_t masks;
310 symlist_t constants;
311 symlist_t download_constants;
312 symlist_t aliases;
313
314 SLIST_INIT(®isters);
315 SLIST_INIT(&masks);
316 SLIST_INIT(&constants);
317 SLIST_INIT(&download_constants);
318 SLIST_INIT(&aliases);
319
320 if (symtable != NULL) {
321 DBT key;
322 DBT data;
323 int flag = R_FIRST;
324
325 while (symtable->seq(symtable, &key, &data, flag) == 0) {
326 symbol_t *cursym;
327
328 memcpy(&cursym, data.data, sizeof(cursym));
329 switch(cursym->type) {
330 case REGISTER:
331 case SCBLOC:
332 case SRAMLOC:
333 symlist_add(®isters, cursym, SYMLIST_SORT);
334 break;
335 case MASK:
336 case BIT:
337 symlist_add(&masks, cursym, SYMLIST_SORT);
338 break;
339 case CONST:
340 if (cursym->info.cinfo->define == FALSE) {
341 symlist_add(&constants, cursym,
342 SYMLIST_INSERT_HEAD);
343 }
344 break;
345 case DOWNLOAD_CONST:
346 symlist_add(&download_constants, cursym,
347 SYMLIST_INSERT_HEAD);
348 break;
349 case ALIAS:
350 symlist_add(&aliases, cursym,
351 SYMLIST_INSERT_HEAD);
352 break;
353 default:
354 break;
355 }
356 flag = R_NEXT;
357 }
358
359 /* Put in the masks and bits */
360 while (SLIST_FIRST(&masks) != NULL) {
361 symbol_node_t *curnode;
362 symbol_node_t *regnode;
363 char *regname;
364
365 curnode = SLIST_FIRST(&masks);
366 SLIST_REMOVE_HEAD(&masks, links);
367
368 regnode =
369 SLIST_FIRST(&curnode->symbol->info.minfo->symrefs);
370 regname = regnode->symbol->name;
371 regnode = symlist_search(®isters, regname);
372 SLIST_INSERT_AFTER(regnode, curnode, links);
373 }
374
375 /* Add the aliases */
376 while (SLIST_FIRST(&aliases) != NULL) {
377 symbol_node_t *curnode;
378 symbol_node_t *regnode;
379 char *regname;
380
381 curnode = SLIST_FIRST(&aliases);
382 SLIST_REMOVE_HEAD(&aliases, links);
383
384 regname = curnode->symbol->info.ainfo->parent->name;
385 regnode = symlist_search(®isters, regname);
386 SLIST_INSERT_AFTER(regnode, curnode, links);
387 }
388
389 /* Output what we have */
390 fprintf(ofile,
391 "/*
392 * DO NOT EDIT - This file is automatically generated
393 * from the following source files:
394 *
395 %s */\n", versions);
396 while (SLIST_FIRST(®isters) != NULL) {
397 symbol_node_t *curnode;
398 u_int8_t value;
399 char *tab_str;
400 char *tab_str2;
401
402 curnode = SLIST_FIRST(®isters);
403 SLIST_REMOVE_HEAD(®isters, links);
404 switch(curnode->symbol->type) {
405 case REGISTER:
406 case SCBLOC:
407 case SRAMLOC:
408 fprintf(ofile, "\n");
409 value = curnode->symbol->info.rinfo->address;
410 tab_str = "\t";
411 tab_str2 = "\t\t";
412 break;
413 case ALIAS:
414 {
415 symbol_t *parent;
416
417 parent = curnode->symbol->info.ainfo->parent;
418 value = parent->info.rinfo->address;
419 tab_str = "\t";
420 tab_str2 = "\t\t";
421 break;
422 }
423 case MASK:
424 case BIT:
425 value = curnode->symbol->info.minfo->mask;
426 tab_str = "\t\t";
427 tab_str2 = "\t";
428 break;
429 default:
430 value = 0; /* Quiet compiler */
431 tab_str = NULL;
432 tab_str2 = NULL;
433 stop("symtable_dump: Invalid symbol type "
434 "encountered", EX_SOFTWARE);
435 break;
436 }
437 fprintf(ofile, "#define%s%-16s%s0x%02x\n",
438 tab_str, curnode->symbol->name, tab_str2,
439 value);
440 free(curnode);
441 }
442 fprintf(ofile, "\n\n");
443
444 while (SLIST_FIRST(&constants) != NULL) {
445 symbol_node_t *curnode;
446
447 curnode = SLIST_FIRST(&constants);
448 SLIST_REMOVE_HEAD(&constants, links);
449 fprintf(ofile, "#define\t%-8s\t0x%02x\n",
450 curnode->symbol->name,
451 curnode->symbol->info.cinfo->value);
452 free(curnode);
453 }
454
455
456 fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
457
458 while (SLIST_FIRST(&download_constants) != NULL) {
459 symbol_node_t *curnode;
460
461 curnode = SLIST_FIRST(&download_constants);
462 SLIST_REMOVE_HEAD(&download_constants, links);
463 fprintf(ofile, "#define\t%-8s\t0x%02x\n",
464 curnode->symbol->name,
465 curnode->symbol->info.cinfo->value);
466 free(curnode);
467 }
468 }
469 }
470
471