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