Annotation of sys/dev/microcode/aic7xxx/aicasm_symbol.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: aicasm_symbol.c,v 1.9 2003/12/24 23:27:55 krw Exp $ */
2: /* $NetBSD: aicasm_symbol.c,v 1.4 2003/07/14 15:42:40 lukem Exp $ */
3:
4: /*
5: * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation
6: *
7: * Copyright (c) 1997 Justin T. Gibbs.
8: * Copyright (c) 2002 Adaptec Inc.
9: * All rights reserved.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions, and the following disclaimer,
16: * without modification.
17: * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18: * substantially similar to the "NO WARRANTY" disclaimer below
19: * ("Disclaimer") and any redistribution must be conditioned upon
20: * including a substantially similar Disclaimer requirement for further
21: * binary redistribution.
22: * 3. Neither the names of the above-listed copyright holders nor the names
23: * of any contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * Alternatively, this software may be distributed under the terms of the
27: * GNU General Public License ("GPL") version 2 as published by the Free
28: * Software Foundation.
29: *
30: * NO WARRANTY
31: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41: * POSSIBILITY OF SUCH DAMAGES.
42: *
43: * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_symbol.c,v 1.23 2003/01/20 18:01:37 gibbs Exp $
44: */
45:
46: #include <sys/cdefs.h>
47: /* __RCSID("$NetBSD: aicasm_symbol.c,v 1.4 2003/07/14 15:42:40 lukem Exp $"); */
48:
49: #include <sys/types.h>
50:
51: #ifdef __linux__
52: #include "aicdb.h"
53: #else
54: #include <db.h>
55: #endif
56: #include <fcntl.h>
57: #include <inttypes.h>
58: #include <regex.h>
59: #include <stdio.h>
60: #include <stdlib.h>
61: #include <string.h>
62: #include <sysexits.h>
63:
64: #include "aicasm_symbol.h"
65: #include "aicasm.h"
66:
67: static DB *symtable;
68:
69: symbol_t *
70: symbol_create(char *name)
71: {
72: symbol_t *new_symbol;
73:
74: new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
75: if (new_symbol == NULL) {
76: perror("Unable to create new symbol");
77: exit(EX_SOFTWARE);
78: }
79: memset(new_symbol, 0, sizeof(*new_symbol));
80: new_symbol->name = strdup(name);
81: if (new_symbol->name == NULL)
82: stop("Unable to strdup symbol name", EX_SOFTWARE);
83: new_symbol->type = UNINITIALIZED;
84: return (new_symbol);
85: }
86:
87: void
88: symbol_delete(symbol_t *symbol)
89: {
90: if (symtable != NULL) {
91: DBT key;
92:
93: key.data = symbol->name;
94: key.size = strlen(symbol->name);
95: symtable->del(symtable, &key, /*flags*/0);
96: }
97: switch(symbol->type) {
98: case SCBLOC:
99: case SRAMLOC:
100: case REGISTER:
101: if (symbol->info.rinfo != NULL)
102: free(symbol->info.rinfo);
103: break;
104: case ALIAS:
105: if (symbol->info.ainfo != NULL)
106: free(symbol->info.ainfo);
107: break;
108: case MASK:
109: case FIELD:
110: case ENUM:
111: case ENUM_ENTRY:
112: if (symbol->info.finfo != NULL) {
113: symlist_free(&symbol->info.finfo->symrefs);
114: free(symbol->info.finfo);
115: }
116: break;
117: case DOWNLOAD_CONST:
118: case CONST:
119: if (symbol->info.cinfo != NULL)
120: free(symbol->info.cinfo);
121: break;
122: case LABEL:
123: if (symbol->info.linfo != NULL)
124: free(symbol->info.linfo);
125: break;
126: case UNINITIALIZED:
127: default:
128: break;
129: }
130: free(symbol->name);
131: free(symbol);
132: }
133:
134: void
135: symtable_open()
136: {
137: symtable = dbopen(/*filename*/NULL,
138: O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
139: /*openinfo*/NULL);
140:
141: if (symtable == NULL) {
142: perror("Symbol table creation failed");
143: exit(EX_SOFTWARE);
144: /* NOTREACHED */
145: }
146: }
147:
148: void
149: symtable_close()
150: {
151: if (symtable != NULL) {
152: DBT key;
153: DBT data;
154:
155: while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
156: symbol_t *stored_ptr;
157:
158: memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
159: symbol_delete(stored_ptr);
160: }
161: symtable->close(symtable);
162: }
163: }
164:
165: /*
166: * The semantics of get is to return an uninitialized symbol entry
167: * if a lookup fails.
168: */
169: symbol_t *
170: symtable_get(char *name)
171: {
172: symbol_t *stored_ptr;
173: DBT key;
174: DBT data;
175: int retval;
176:
177: key.data = (void *)name;
178: key.size = strlen(name);
179:
180: if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
181: if (retval == -1) {
182: perror("Symbol table get operation failed");
183: exit(EX_SOFTWARE);
184: /* NOTREACHED */
185: } else if (retval == 1) {
186: /* Symbol wasn't found, so create a new one */
187: symbol_t *new_symbol;
188:
189: new_symbol = symbol_create(name);
190: data.data = &new_symbol;
191: data.size = sizeof(new_symbol);
192: if (symtable->put(symtable, &key, &data,
193: /*flags*/0) !=0) {
194: perror("Symtable put failed");
195: exit(EX_SOFTWARE);
196: }
197: return (new_symbol);
198: } else {
199: perror("Unexpected return value from db get routine");
200: exit(EX_SOFTWARE);
201: /* NOTREACHED */
202: }
203: }
204: memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
205: return (stored_ptr);
206: }
207:
208: symbol_node_t *
209: symlist_search(symlist_t *symlist, char *symname)
210: {
211: symbol_node_t *curnode;
212:
213: curnode = SLIST_FIRST(symlist);
214: while(curnode != NULL) {
215: if (strcmp(symname, curnode->symbol->name) == 0)
216: break;
217: curnode = SLIST_NEXT(curnode, links);
218: }
219: return (curnode);
220: }
221:
222: void
223: symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
224: {
225: symbol_node_t *newnode;
226:
227: newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
228: if (newnode == NULL) {
229: stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
230: /* NOTREACHED */
231: }
232: newnode->symbol = symbol;
233: if (how == SYMLIST_SORT) {
234: symbol_node_t *curnode;
235: int field;
236:
237: field = FALSE;
238: switch(symbol->type) {
239: case REGISTER:
240: case SCBLOC:
241: case SRAMLOC:
242: break;
243: case FIELD:
244: case MASK:
245: case ENUM:
246: case ENUM_ENTRY:
247: field = TRUE;
248: break;
249: default:
250: stop("symlist_add: Invalid symbol type for sorting",
251: EX_SOFTWARE);
252: /* NOTREACHED */
253: }
254:
255: curnode = SLIST_FIRST(symlist);
256: if (curnode == NULL
257: || (field
258: && (curnode->symbol->type > newnode->symbol->type
259: || (curnode->symbol->type == newnode->symbol->type
260: && (curnode->symbol->info.finfo->value >
261: newnode->symbol->info.finfo->value))))
262: || (!field && (curnode->symbol->info.rinfo->address >
263: newnode->symbol->info.rinfo->address))) {
264: SLIST_INSERT_HEAD(symlist, newnode, links);
265: return;
266: }
267:
268: while (1) {
269: if (SLIST_NEXT(curnode, links) == NULL) {
270: SLIST_INSERT_AFTER(curnode, newnode,
271: links);
272: break;
273: } else {
274: symbol_t *cursymbol;
275:
276: cursymbol = SLIST_NEXT(curnode, links)->symbol;
277: if ((field
278: && (cursymbol->type > symbol->type
279: || (cursymbol->type == symbol->type
280: && (cursymbol->info.finfo->value >
281: symbol->info.finfo->value))))
282: || (!field
283: && (cursymbol->info.rinfo->address >
284: symbol->info.rinfo->address))) {
285: SLIST_INSERT_AFTER(curnode, newnode,
286: links);
287: break;
288: }
289: }
290: curnode = SLIST_NEXT(curnode, links);
291: }
292: } else {
293: SLIST_INSERT_HEAD(symlist, newnode, links);
294: }
295: }
296:
297: void
298: symlist_free(symlist_t *symlist)
299: {
300: symbol_node_t *node1, *node2;
301:
302: node1 = SLIST_FIRST(symlist);
303: while (node1 != NULL) {
304: node2 = SLIST_NEXT(node1, links);
305: free(node1);
306: node1 = node2;
307: }
308: SLIST_INIT(symlist);
309: }
310:
311: void
312: symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
313: symlist_t *symlist_src2)
314: {
315: symbol_node_t *node;
316:
317: *symlist_dest = *symlist_src1;
318: while((node = SLIST_FIRST(symlist_src2)) != NULL) {
319: SLIST_REMOVE_HEAD(symlist_src2, links);
320: SLIST_INSERT_HEAD(symlist_dest, node, links);
321: }
322:
323: /* These are now empty */
324: SLIST_INIT(symlist_src1);
325: SLIST_INIT(symlist_src2);
326: }
327:
328: void
329: aic_print_file_prologue(FILE *ofile)
330: {
331:
332: if (ofile == NULL)
333: return;
334:
335: fprintf(ofile,
336: "/*\n"
337: " * DO NOT EDIT - This file is automatically generated\n"
338: " * from the following source files:\n"
339: " *\n"
340: "%s */\n",
341: versions);
342: }
343:
344: void
345: aic_print_include(FILE *dfile, char *include_file)
346: {
347:
348: if (dfile == NULL)
349: return;
350: fprintf(dfile, "\n#include \"%s\"\n\n", include_file);
351: }
352:
353: void
354: aic_print_reg_dump_types(FILE *ofile)
355: {
356: if (ofile == NULL)
357: return;
358:
359: fprintf(ofile,
360: "typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
361: "typedef struct %sreg_parse_entry {\n"
362: " char *name;\n"
363: " uint8_t value;\n"
364: " uint8_t mask;\n"
365: "} %sreg_parse_entry_t;\n"
366: "\n",
367: prefix, prefix, prefix);
368: }
369:
370: static void
371: aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
372: {
373: if (dfile == NULL)
374: return;
375:
376: fprintf(dfile,
377: "static %sreg_parse_entry_t %s_parse_table[] = {\n",
378: prefix,
379: regnode->symbol->name);
380: }
381:
382: static void
383: aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
384: symbol_node_t *regnode, u_int num_entries)
385: {
386: char *lower_name;
387: char *letter;
388:
389: lower_name = strdup(regnode->symbol->name);
390: if (lower_name == NULL)
391: stop("Unable to strdup symbol name", EX_SOFTWARE);
392:
393: for (letter = lower_name; *letter != '\0'; letter++)
394: *letter = tolower(*letter);
395:
396: if (dfile != NULL) {
397: if (num_entries != 0)
398: fprintf(dfile,
399: "\n"
400: "};\n"
401: "\n");
402:
403: fprintf(dfile,
404: "int\n"
405: "%s%s_print(u_int regvalue, u_int *cur_col, u_int wrap)\n"
406: "{\n"
407: " return (%sprint_register(%s%s, %d, \"%s\",\n"
408: " 0x%02x, regvalue, cur_col, wrap));\n"
409: "}\n"
410: "\n",
411: prefix,
412: lower_name,
413: prefix,
414: num_entries != 0 ? regnode->symbol->name : "NULL",
415: num_entries != 0 ? "_parse_table" : "",
416: num_entries,
417: regnode->symbol->name,
418: regnode->symbol->info.rinfo->address);
419: }
420:
421: fprintf(ofile,
422: "#if AIC_DEBUG_REGISTERS\n"
423: "%sreg_print_t %s%s_print;\n"
424: "#else\n"
425: "#define %s%s_print(regvalue, cur_col, wrap) \\\n"
426: " %sprint_register(NULL, 0, \"%s\", 0x%02x, regvalue, cur_col, wrap)\n"
427: "#endif\n"
428: "\n",
429: prefix,
430: prefix,
431: lower_name,
432: prefix,
433: lower_name,
434: prefix,
435: regnode->symbol->name,
436: regnode->symbol->info.rinfo->address);
437: }
438:
439: static void
440: aic_print_reg_dump_entry(FILE *dfile, symbol_node_t *curnode)
441: {
442: int num_tabs;
443:
444: if (dfile == NULL)
445: return;
446:
447: fprintf(dfile,
448: " { \"%s\",",
449: curnode->symbol->name);
450:
451: num_tabs = 3 - (strlen(curnode->symbol->name) + 5) / 8;
452:
453: while (num_tabs-- > 0)
454: fputc('\t', dfile);
455: fprintf(dfile, "0x%02x, 0x%02x }",
456: curnode->symbol->info.finfo->value,
457: curnode->symbol->info.finfo->mask);
458: }
459:
460: void
461: symtable_dump(FILE *ofile, FILE *dfile)
462: {
463: /*
464: * Sort the registers by address with a simple insertion sort.
465: * Put bitmasks next to the first register that defines them.
466: * Put constants at the end.
467: */
468: symlist_t registers;
469: symlist_t masks;
470: symlist_t constants;
471: symlist_t download_constants;
472: symlist_t aliases;
473: symlist_t exported_labels;
474: symbol_node_t *curnode;
475: symbol_node_t *regnode;
476: DBT key;
477: DBT data;
478: int flag;
479: u_int i;
480:
481: if (symtable == NULL)
482: return;
483:
484: SLIST_INIT(®isters);
485: SLIST_INIT(&masks);
486: SLIST_INIT(&constants);
487: SLIST_INIT(&download_constants);
488: SLIST_INIT(&aliases);
489: SLIST_INIT(&exported_labels);
490: flag = R_FIRST;
491: while (symtable->seq(symtable, &key, &data, flag) == 0) {
492: symbol_t *cursym;
493:
494: memcpy(&cursym, data.data, sizeof(cursym));
495: switch(cursym->type) {
496: case REGISTER:
497: case SCBLOC:
498: case SRAMLOC:
499: symlist_add(®isters, cursym, SYMLIST_SORT);
500: break;
501: case MASK:
502: case FIELD:
503: case ENUM:
504: case ENUM_ENTRY:
505: symlist_add(&masks, cursym, SYMLIST_SORT);
506: break;
507: case CONST:
508: symlist_add(&constants, cursym,
509: SYMLIST_INSERT_HEAD);
510: break;
511: case DOWNLOAD_CONST:
512: symlist_add(&download_constants, cursym,
513: SYMLIST_INSERT_HEAD);
514: break;
515: case ALIAS:
516: symlist_add(&aliases, cursym,
517: SYMLIST_INSERT_HEAD);
518: break;
519: case LABEL:
520: if (cursym->info.linfo->exported == 0)
521: break;
522: symlist_add(&exported_labels, cursym,
523: SYMLIST_INSERT_HEAD);
524: break;
525: default:
526: break;
527: }
528: flag = R_NEXT;
529: }
530:
531: /* Register dianostic functions/declarations first. */
532: aic_print_file_prologue(ofile);
533: aic_print_reg_dump_types(ofile);
534: aic_print_file_prologue(dfile);
535: aic_print_include(dfile, stock_include_file);
536: SLIST_FOREACH(curnode, ®isters, links) {
537:
538: switch(curnode->symbol->type) {
539: case REGISTER:
540: case SCBLOC:
541: case SRAMLOC:
542: {
543: symlist_t *fields;
544: symbol_node_t *fieldnode;
545: int num_entries;
546:
547: num_entries = 0;
548: fields = &curnode->symbol->info.rinfo->fields;
549: SLIST_FOREACH(fieldnode, fields, links) {
550: if (num_entries == 0)
551: aic_print_reg_dump_start(dfile,
552: curnode);
553: else if (dfile != NULL)
554: fputs(",\n", dfile);
555: num_entries++;
556: aic_print_reg_dump_entry(dfile, fieldnode);
557: }
558: aic_print_reg_dump_end(ofile, dfile,
559: curnode, num_entries);
560: }
561: default:
562: break;
563: }
564: }
565:
566: /* Fold in the masks and bits */
567: while (SLIST_FIRST(&masks) != NULL) {
568: char *regname;
569:
570: curnode = SLIST_FIRST(&masks);
571: SLIST_REMOVE_HEAD(&masks, links);
572:
573: regnode = SLIST_FIRST(&curnode->symbol->info.finfo->symrefs);
574: regname = regnode->symbol->name;
575: regnode = symlist_search(®isters, regname);
576: SLIST_INSERT_AFTER(regnode, curnode, links);
577: }
578:
579: /* Add the aliases */
580: while (SLIST_FIRST(&aliases) != NULL) {
581: char *regname;
582:
583: curnode = SLIST_FIRST(&aliases);
584: SLIST_REMOVE_HEAD(&aliases, links);
585:
586: regname = curnode->symbol->info.ainfo->parent->name;
587: regnode = symlist_search(®isters, regname);
588: SLIST_INSERT_AFTER(regnode, curnode, links);
589: }
590:
591: /* Output generated #defines. */
592: while (SLIST_FIRST(®isters) != NULL) {
593: symbol_node_t *curnode;
594: u_int value;
595: char *tab_str;
596: char *tab_str2;
597:
598: curnode = SLIST_FIRST(®isters);
599: SLIST_REMOVE_HEAD(®isters, links);
600: switch(curnode->symbol->type) {
601: case REGISTER:
602: case SCBLOC:
603: case SRAMLOC:
604: fprintf(ofile, "\n");
605: value = curnode->symbol->info.rinfo->address;
606: tab_str = "\t";
607: tab_str2 = "\t\t";
608: break;
609: case ALIAS:
610: {
611: symbol_t *parent;
612:
613: parent = curnode->symbol->info.ainfo->parent;
614: value = parent->info.rinfo->address;
615: tab_str = "\t";
616: tab_str2 = "\t\t";
617: break;
618: }
619: case MASK:
620: case FIELD:
621: case ENUM:
622: case ENUM_ENTRY:
623: value = curnode->symbol->info.finfo->value;
624: tab_str = "\t\t";
625: tab_str2 = "\t";
626: break;
627: default:
628: value = 0; /* Quiet compiler */
629: tab_str = NULL;
630: tab_str2 = NULL;
631: stop("symtable_dump: Invalid symbol type "
632: "encountered", EX_SOFTWARE);
633: break;
634: }
635: fprintf(ofile, "#define%s%-16s%s0x%02x\n",
636: tab_str, curnode->symbol->name, tab_str2,
637: value);
638: free(curnode);
639: }
640: fprintf(ofile, "\n\n");
641:
642: while (SLIST_FIRST(&constants) != NULL) {
643: symbol_node_t *curnode;
644:
645: curnode = SLIST_FIRST(&constants);
646: SLIST_REMOVE_HEAD(&constants, links);
647: fprintf(ofile, "#define\t%-8s\t0x%02x\n",
648: curnode->symbol->name,
649: curnode->symbol->info.cinfo->value);
650: free(curnode);
651: }
652:
653:
654: fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
655:
656: for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
657: symbol_node_t *curnode;
658:
659: curnode = SLIST_FIRST(&download_constants);
660: SLIST_REMOVE_HEAD(&download_constants, links);
661: fprintf(ofile, "#define\t%-8s\t0x%02x\n",
662: curnode->symbol->name,
663: curnode->symbol->info.cinfo->value);
664: free(curnode);
665: }
666: fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i);
667:
668: fprintf(ofile, "\n\n/* Exported Labels */\n");
669:
670: while (SLIST_FIRST(&exported_labels) != NULL) {
671: symbol_node_t *curnode;
672:
673: curnode = SLIST_FIRST(&exported_labels);
674: SLIST_REMOVE_HEAD(&exported_labels, links);
675: fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n",
676: curnode->symbol->name,
677: curnode->symbol->info.linfo->address);
678: free(curnode);
679: }
680: }
681:
CVSweb