brintos

brintos / linux-shallow public Read only

0
0
Text · 15.7 KiB · 2b44eb5 Raw
691 lines · c
1/*2 * Aic7xxx SCSI host adapter firmware assembler symbol table implementation3 *4 * Copyright (c) 1997 Justin T. Gibbs.5 * Copyright (c) 2002 Adaptec Inc.6 * All rights reserved.7 *8 * Redistribution and use in source and binary forms, with or without9 * modification, are permitted provided that the following conditions10 * are met:11 * 1. Redistributions of source code must retain the above copyright12 *    notice, this list of conditions, and the following disclaimer,13 *    without modification.14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer15 *    substantially similar to the "NO WARRANTY" disclaimer below16 *    ("Disclaimer") and any redistribution must be conditioned upon17 *    including a substantially similar Disclaimer requirement for further18 *    binary redistribution.19 * 3. Neither the names of the above-listed copyright holders nor the names20 *    of any contributors may be used to endorse or promote products derived21 *    from this software without specific prior written permission.22 *23 * Alternatively, this software may be distributed under the terms of the24 * GNU General Public License ("GPL") version 2 as published by the Free25 * Software Foundation.26 *27 * NO WARRANTY28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT32 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40 * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.c#24 $41 *42 * $FreeBSD$43 */44 45#include <sys/types.h>46 47#include "aicdb.h"48#include <fcntl.h>49#include <inttypes.h>50#include <regex.h>51#include <stdio.h>52#include <stdlib.h>53#include <string.h>54#include <sysexits.h>55#include <ctype.h>56 57#include "aicasm_symbol.h"58#include "aicasm.h"59 60static DB *symtable;61 62symbol_t *63symbol_create(char *name)64{65	symbol_t *new_symbol;66 67	new_symbol = (symbol_t *)malloc(sizeof(symbol_t));68	if (new_symbol == NULL) {69		perror("Unable to create new symbol");70		exit(EX_SOFTWARE);71	}72	memset(new_symbol, 0, sizeof(*new_symbol));73	new_symbol->name = strdup(name);74	if (new_symbol->name == NULL)75		 stop("Unable to strdup symbol name", EX_SOFTWARE);76	new_symbol->type = UNINITIALIZED;77	new_symbol->count = 1;78	return (new_symbol);79}80 81void82symbol_delete(symbol_t *symbol)83{84	if (symtable != NULL) {85		DBT	 key;86 87		key.data = symbol->name;88		key.size = strlen(symbol->name);89		symtable->del(symtable, &key, /*flags*/0);90	}91	switch(symbol->type) {92	case SCBLOC:93	case SRAMLOC:94	case REGISTER:95		if (symbol->info.rinfo != NULL)96			free(symbol->info.rinfo);97		break;98	case ALIAS:99		if (symbol->info.ainfo != NULL)100			free(symbol->info.ainfo);101		break;102	case MASK:103	case FIELD:104	case ENUM:105	case ENUM_ENTRY:106		if (symbol->info.finfo != NULL) {107			symlist_free(&symbol->info.finfo->symrefs);108			free(symbol->info.finfo);109		}110		break;111	case DOWNLOAD_CONST:112	case CONST:113		if (symbol->info.cinfo != NULL)114			free(symbol->info.cinfo);115		break;116	case LABEL:117		if (symbol->info.linfo != NULL)118			free(symbol->info.linfo);119		break;120	case UNINITIALIZED:121	default:122		break;123	}124	free(symbol->name);125	free(symbol);126}127 128void129symtable_open()130{131	symtable = dbopen(/*filename*/NULL,132			  O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,133			  /*openinfo*/NULL);134 135	if (symtable == NULL) {136		perror("Symbol table creation failed");137		exit(EX_SOFTWARE);138		/* NOTREACHED */139	}140}141 142void143symtable_close()144{145	if (symtable != NULL) {146		DBT	 key;147		DBT	 data;148 149		while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {150			symbol_t *stored_ptr;151 152			memcpy(&stored_ptr, data.data, sizeof(stored_ptr));153			symbol_delete(stored_ptr);154		}155		symtable->close(symtable);156	}157}158 159/*160 * The semantics of get is to return an uninitialized symbol entry161 * if a lookup fails.162 */163symbol_t *164symtable_get(char *name)165{166	symbol_t *stored_ptr;167	DBT	  key;168	DBT	  data;169	int	  retval;170 171	key.data = (void *)name;172	key.size = strlen(name);173 174	if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {175		if (retval == -1) {176			perror("Symbol table get operation failed");177			exit(EX_SOFTWARE);178			/* NOTREACHED */179		} else if (retval == 1) {180			/* Symbol wasn't found, so create a new one */181			symbol_t *new_symbol;182 183			new_symbol = symbol_create(name);184			data.data = &new_symbol;185			data.size = sizeof(new_symbol);186			if (symtable->put(symtable, &key, &data,187					  /*flags*/0) !=0) {188				perror("Symtable put failed");189				exit(EX_SOFTWARE);190			}191			return (new_symbol);192		} else {193			perror("Unexpected return value from db get routine");194			exit(EX_SOFTWARE);195			/* NOTREACHED */196		}197	}198	memcpy(&stored_ptr, data.data, sizeof(stored_ptr));199	stored_ptr->count++;200	data.data = &stored_ptr;201	if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {202		perror("Symtable put failed");203		exit(EX_SOFTWARE);204	}205	return (stored_ptr);206}207 208symbol_node_t *209symlist_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 222void223symlist_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 == NULL257		 || (field258		  && (curnode->symbol->type > newnode->symbol->type259		   || (curnode->symbol->type == newnode->symbol->type260		    && (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 ((field278				  && (cursymbol->type > symbol->type279				   || (cursymbol->type == symbol->type280				    && (cursymbol->info.finfo->value >281					symbol->info.finfo->value))))282				 || (!field283				   && (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 297void298symlist_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 311void312symlist_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 328void329aic_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 344void345aic_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 353void354aic_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 370static void371aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)372{373	if (dfile == NULL)374		return;375 376	fprintf(dfile,377"static const %sreg_parse_entry_t %s_parse_table[] = {\n",378		prefix,379		regnode->symbol->name);380}381 382static void383aic_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 439static void440aic_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 460void461symtable_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	int		 reg_count = 0, reg_used = 0;480	u_int		 i;481 482	if (symtable == NULL)483		return;484 485	SLIST_INIT(&registers);486	SLIST_INIT(&masks);487	SLIST_INIT(&constants);488	SLIST_INIT(&download_constants);489	SLIST_INIT(&aliases);490	SLIST_INIT(&exported_labels);491	flag = R_FIRST;492	while (symtable->seq(symtable, &key, &data, flag) == 0) {493		symbol_t *cursym;494 495		memcpy(&cursym, data.data, sizeof(cursym));496		switch(cursym->type) {497		case REGISTER:498		case SCBLOC:499		case SRAMLOC:500			symlist_add(&registers, cursym, SYMLIST_SORT);501			break;502		case MASK:503		case FIELD:504		case ENUM:505		case ENUM_ENTRY:506			symlist_add(&masks, cursym, SYMLIST_SORT);507			break;508		case CONST:509			symlist_add(&constants, cursym,510				    SYMLIST_INSERT_HEAD);511			break;512		case DOWNLOAD_CONST:513			symlist_add(&download_constants, cursym,514				    SYMLIST_INSERT_HEAD);515			break;516		case ALIAS:517			symlist_add(&aliases, cursym,518				    SYMLIST_INSERT_HEAD);519			break;520		case LABEL:521			if (cursym->info.linfo->exported == 0)522				break;523			symlist_add(&exported_labels, cursym,524				    SYMLIST_INSERT_HEAD);525			break;526		default:527			break;528		}529		flag = R_NEXT;530	}531 532	/* Register dianostic functions/declarations first. */533	aic_print_file_prologue(ofile);534	aic_print_reg_dump_types(ofile);535	aic_print_file_prologue(dfile);536	aic_print_include(dfile, stock_include_file);537	SLIST_FOREACH(curnode, &registers, links) {538 539		if (curnode->symbol->dont_generate_debug_code)540			continue;541 542		switch(curnode->symbol->type) {543		case REGISTER:544		case SCBLOC:545		case SRAMLOC:546		{547			symlist_t	*fields;548			symbol_node_t	*fieldnode;549			int		 num_entries;550 551			num_entries = 0;552			reg_count++;553			if (curnode->symbol->count == 1)554				break;555			fields = &curnode->symbol->info.rinfo->fields;556			SLIST_FOREACH(fieldnode, fields, links) {557				if (num_entries == 0)558					aic_print_reg_dump_start(dfile,559								 curnode);560				else if (dfile != NULL)561					fputs(",\n", dfile);562				num_entries++;563				aic_print_reg_dump_entry(dfile, fieldnode);564			}565			aic_print_reg_dump_end(ofile, dfile,566					       curnode, num_entries);567			reg_used++;568		}569		default:570			break;571		}572	}573	fprintf(stderr, "%s: %d of %d register definitions used\n", appname,574		reg_used, reg_count);575 576	/* Fold in the masks and bits */577	while (SLIST_FIRST(&masks) != NULL) {578		char *regname;579 580		curnode = SLIST_FIRST(&masks);581		SLIST_REMOVE_HEAD(&masks, links);582 583		regnode = SLIST_FIRST(&curnode->symbol->info.finfo->symrefs);584		regname = regnode->symbol->name;585		regnode = symlist_search(&registers, regname);586		SLIST_INSERT_AFTER(regnode, curnode, links);587	}588 589	/* Add the aliases */590	while (SLIST_FIRST(&aliases) != NULL) {591		char *regname;592 593		curnode = SLIST_FIRST(&aliases);594		SLIST_REMOVE_HEAD(&aliases, links);595 596		regname = curnode->symbol->info.ainfo->parent->name;597		regnode = symlist_search(&registers, regname);598		SLIST_INSERT_AFTER(regnode, curnode, links);599	}600 601	/* Output generated #defines. */602	while (SLIST_FIRST(&registers) != NULL) {603		symbol_node_t *curnode;604		u_int value;605		char *tab_str;606		char *tab_str2;607 608		curnode = SLIST_FIRST(&registers);609		SLIST_REMOVE_HEAD(&registers, links);610		switch(curnode->symbol->type) {611		case REGISTER:612		case SCBLOC:613		case SRAMLOC:614			fprintf(ofile, "\n");615			value = curnode->symbol->info.rinfo->address;616			tab_str = "\t";617			tab_str2 = "\t\t";618			break;619		case ALIAS:620		{621			symbol_t *parent;622 623			parent = curnode->symbol->info.ainfo->parent;624			value = parent->info.rinfo->address;625			tab_str = "\t";626			tab_str2 = "\t\t";627			break;628		}629		case MASK:630		case FIELD:631		case ENUM:632		case ENUM_ENTRY:633			value = curnode->symbol->info.finfo->value;634			tab_str = "\t\t";635			tab_str2 = "\t";636			break;637		default:638			value = 0; /* Quiet compiler */639			tab_str = NULL;640			tab_str2 = NULL;641			stop("symtable_dump: Invalid symbol type "642			     "encountered", EX_SOFTWARE);643			break;644		}645		fprintf(ofile, "#define%s%-16s%s0x%02x\n",646			tab_str, curnode->symbol->name, tab_str2,647			value);648		free(curnode);649	}650	fprintf(ofile, "\n\n");651 652	while (SLIST_FIRST(&constants) != NULL) {653		symbol_node_t *curnode;654 655		curnode = SLIST_FIRST(&constants);656		SLIST_REMOVE_HEAD(&constants, links);657		fprintf(ofile, "#define\t%-8s\t0x%02x\n",658			curnode->symbol->name,659			curnode->symbol->info.cinfo->value);660		free(curnode);661	}662 663	fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");664 665	for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {666		symbol_node_t *curnode;667 668		curnode = SLIST_FIRST(&download_constants);669		SLIST_REMOVE_HEAD(&download_constants, links);670		fprintf(ofile, "#define\t%-8s\t0x%02x\n",671			curnode->symbol->name,672			curnode->symbol->info.cinfo->value);673		free(curnode);674	}675	fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i);676 677	fprintf(ofile, "\n\n/* Exported Labels */\n");678 679	while (SLIST_FIRST(&exported_labels) != NULL) {680		symbol_node_t *curnode;681 682		curnode = SLIST_FIRST(&exported_labels);683		SLIST_REMOVE_HEAD(&exported_labels, links);684		fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n",685			curnode->symbol->name,686			curnode->symbol->info.linfo->address);687		free(curnode);688	}689}690 691