Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / parser / parser.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: parser.c
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident "@(#)parser.c 1.35 07/04/02 SMI"
29
30#include <sys/types.h>
31#include <errno.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <stdio.h>
35#include <dlfcn.h>
36#include <link.h>
37#include <string.h>
38#include <search.h>
39
40#include "basics.h"
41#include "fatal.h"
42#include "strutil.h"
43#include "allocate.h"
44#include "simcore.h"
45#include "config.h"
46#include "options.h"
47#include "fileutil.h"
48#include "lexer.h"
49#include "sam_dev.h"
50
51#if ERROR_INJECTION
52#define CPP_OPTIONS " -DERROR_INJECTION"
53#else
54#define CPP_OPTIONS ""
55#endif
56
57#define MAX_TRIES 4
58
59extern void lex_fatal(char * str, ...);
60
61 /*
62 * Parse the top-level config file.
63 * Essentially this is restricted to the systems
64 * directive in the config file
65 */
66
67
68
69static void parse_proc(domain_t *domainp);
70static void parse_device(domain_t *domainp);
71static void parse_mmi_device(domain_t *domainp);
72static void parse_addressmap(domain_t *domainp);
73static void parse_domain(domain_t *domainp);
74static void parse_domains(system_t *systemp);
75static void parse_systems();
76static void parse_service_processor(system_t *systemp);
77static void parse_debug();
78static void parse_save_state();
79void *dlopen_lib(char *mdlnamep, char *symname, char *libname);
80
81proc_type_t * find_proc_type(char * procname);
82dev_type_t * find_dev_type(char * devname);
83extern void sam_init_device(char *dev_namep, config_dev_t *config_devp);
84extern void sam_parse_dev(domain_t *domainp, config_dev_t *config_devp);
85extern dev_type_t *sam_load_device(config_dev_t *config_devp);
86
87target_config_t target_config; /* define here ? */
88
89 /* list of dev_type_t pointers to dl'd devices */
90LIST_DEF(dev_cache, dev_type_t);
91
92 /* list of proc_type_t pointers to dl'd processors */
93LIST_DEF(proc_cache, proc_type_t);
94
95
96 /*
97 * Setup empty configuration prior to config parsing
98 */
99
100void init_target_config()
101{
102 LIST_INIT(target_config.systems, system_t);
103
104 /* Init list of loaded device libraries */
105
106 LIST_INIT(dev_cache, dev_type_t);
107
108 /* Init list of loaded processor libraries */
109
110 LIST_INIT(proc_cache, proc_type_t);
111}
112
113
114
115
116
117 /*
118 * This function calls into the lexer to
119 * parse the config and state files.
120 */
121
122void parse_config_file()
123{
124 char tempfilep[64];
125 char buffer[8192]; /* big space */
126 int count;
127 int res;
128 FILE * fp;
129
130 /*
131 * First step is to run the C pre-processor
132 * over the config file.
133 * Output from the pre-processor, is piped
134 * directly into the lexer.
135 * This is complicated because the pre-processor also
136 * outputs errors, and may fail.
137 */
138
139 /* FIXME:
140 * Should probably do this properly with pipes etc.
141 * but for now, just use a temp file in /tmp
142 * for the sake of convenience.
143 */
144
145 for (count = 0; count < MAX_TRIES; count++) {
146 sprintf(tempfilep, "/tmp/sim.cfg.%d.%02d", (int)getpid(), count);
147 if (!file_exists(tempfilep)) break;
148 }
149 if (count == 5) fatal("Unable to create a temporary file for config pre-processing");
150 errno = 0;
151 sprintf(buffer, "%s" CPP_OPTIONS " %s %s > %s",
152 options.cpp_cmd, options.cpp_optionsp,
153 options.config_filep, tempfilep);
154
155 do {
156DBG( printf("system(%s)\n", buffer); );
157 res = system(buffer);
158 } while (res == -1 && (errno == EAGAIN || errno == EINTR));
159 if (res == -1) fatal("Failed trying to pre-process config file %s\n", options.config_filep);
160
161DBG( printf("Exit status %d\n", res); );
162
163 fp = fopen_check(tempfilep, "r");
164 init_lexer(options.config_filep, fp, tempfilep);
165
166 parse_debug(); /* process any debug directives */
167
168 parse_systems();
169
170 fclose(fp);
171
172 unlink(tempfilep); /* clean up - remove temp file */
173
174
175
176 if (options.dumpconfig)
177 dump_config(stdout);
178}
179
180
181
182 /*
183 * Parse optional debug directive
184 */
185
186void parse_debug()
187{
188 lexer_tok_t tok;
189
190 tok = lex_get_token();
191 if (tok != T_Token || !streq(lex.strp, "debug")) {
192 lex_unget();
193 return;
194 }
195 lex_get(T_L_Brace);
196
197 do {
198 tok = lex_get_token();
199 switch (tok) {
200 case T_Token:
201 if (streq(lex.strp, "save_state"))
202 parse_save_state();
203 else
204 lex_fatal("Unexpected string in debug directive\n");
205 break;
206 case T_R_Brace:
207 return;
208 default:
209 lex_fatal("Unexpected token in debug directive.\n");
210 }
211 } while (1);
212
213}
214
215void
216parse_save_state()
217{
218 lexer_tok_t tok;
219
220 lex_get(T_L_Brace);
221
222 do {
223 tok = lex_get_token();
224 switch (tok) {
225 case T_Token:
226 if (streq(lex.strp, "filename")) {
227 lex_get(T_String);
228 options.save_restore.filenamep = Xstrdup(lex.strp);
229 printf("debug:save_state:filename = %s\n",
230 options.save_restore.filenamep);
231 } else
232 if (streq(lex.strp, "format")) {
233 lex_get(T_String);
234 if (streq(lex.strp, "legion"))
235 options.save_restore.legion_format = true;
236 else if (streq(lex.strp, "axis"))
237 options.save_restore.legion_format = false;
238 else
239 lex_fatal("expected either legion or axis");
240
241 printf("debug:save_state:format = %s\n",
242 options.save_restore.legion_format ? "legion" : "axis");
243 } else
244 if (streq(lex.strp, "icount")) {
245 lex_get(T_Number);
246 options.save_restore.trigger_icount = lex.val;
247 printf("debug:save_state:icount = 0x%llx\n",
248 options.save_restore.trigger_icount);
249 } else
250 if (streq(lex.strp, "trap_pc")) {
251 lex_get(T_Number);
252 options.save_restore.trap_pc = lex.val;
253 printf("debug:save_state:trap_pc = 0x%llx\n",
254 options.save_restore.trap_pc);
255 } else
256 if (streq(lex.strp, "patch")) {
257 lex_get(T_Number); /* addr */
258 options.save_restore.mem_patch.addr = lex.val;
259 lex_get(T_Number); /* val */
260 options.save_restore.mem_patch.val = lex.val;
261 printf("debug:save_state:patch addr=0x%llx with val=0x%llx\n",
262 options.save_restore.mem_patch.addr,
263 options.save_restore.mem_patch.val);
264 }
265 lex_get(T_S_Colon);
266 break;
267 case T_R_Brace:
268 return;
269 default:
270 lex_fatal("Unexpected token in save_state directive.\n");
271 }
272 } while (1);
273
274}
275
276 /*
277 * Top level of parser ... look for one or more
278 * system directives.
279 */
280
281
282void parse_systems()
283{
284 LIST_INIT( target_config.systems, system_t );
285
286 do {
287 system_t * systemp;
288 lexer_tok_t tok;
289 int idx;
290
291 tok = lex_get_token();
292 if (tok == T_EOF) break;
293 if (tok != T_Token || !streq(lex.strp, "system"))
294 lex_fatal("system definition expected");
295
296 lex_get(T_String);
297
298 idx = target_config.systems.count;
299 systemp = LIST_ADD( target_config.systems, system_t );
300 systemp->namep = Xstrdup(lex.strp);
301 systemp->idx = idx;
302 systemp->fake_sp = true;
303
304 lex_get(T_L_Brace);
305
306 parse_service_processor(systemp); /* if any */
307
308 parse_domains(systemp);
309
310 lex_get(T_R_Brace);
311
312 } while (1);
313
314 if (target_config.systems.count == 0) lex_fatal("at least one system expected");
315}
316
317
318 /*
319 * Read one service_processor into the specified system, if it exists
320 */
321
322void parse_service_processor(system_t *systemp)
323{
324 domain_t *domainp;
325 config_dev_t *config_devp;
326 lexer_tok_t tok;
327 char symname[BUFSIZ], libname[BUFSIZ], mdlname[BUFSIZ];
328 dev_type_t *dev_typep = NULL;
329
330 tok = lex_get_token();
331 if (tok == T_EOF)
332 lex_fatal("unexpected EOF");
333 if (tok == T_R_Brace)
334 lex_fatal("service_processor specific token expected");
335
336 if (tok != T_Token || !streq(lex.strp, "service_processor")) {
337 /* No Service processor - we're done */
338 lex_unget();
339 return;
340 }
341
342 lex_get(T_String); /* get the name of the service_proc */
343
344 sprintf(mdlname, "%s", lex.strp);
345 sprintf(symname, "dev_type_%s", mdlname);
346DBG( printf("parse_service_processor - parsed %s - looking for %s\n",
347 mdlname, symname); );
348
349 dev_typep = (dev_type_t *)dlopen_lib(mdlname, symname, libname);
350
351 if (dev_typep == (dev_type_t *)0)
352 lex_fatal("unknown dev type \"%s\"", mdlname);
353
354 systemp->service_procp = Xmalloc(sizeof (service_proc_t));
355
356 /* parse service_processor */
357 dev_typep->parse_dev(NULL);
358
359 /* save pointer to the service_processor handle */
360 systemp->service_procp->dev_typep = dev_typep;
361 systemp->service_procp->namep = Xstrdup(mdlname);
362
363#ifdef NOT_NOW
364 /* Turn off fake SP flag */
365 systemp->fake_sp = false;
366#endif
367
368 return;
369}
370
371
372 /*
373 * Read one or more domains into the specified system
374 */
375
376void parse_domains(system_t *systemp)
377{
378 LIST_INIT(systemp->domains, domain_t);
379
380 do {
381 domain_t * domainp;
382 lexer_tok_t tok;
383 int idx;
384
385 tok = lex_get_token();
386 if (tok == T_EOF) lex_fatal("unexpected EOF");
387 if (tok == T_R_Brace) break;
388 if (tok != T_Token || !streq(lex.strp, "domain"))
389 lex_fatal("domain definition expected");
390
391 idx = systemp->domains.count;
392 domainp = LIST_ADD( systemp->domains, domain_t );
393 domainp->idx = idx;
394 domainp->systemp = systemp;
395
396 lex_get(T_L_Brace);
397
398 parse_domain(domainp);
399
400 lex_get(T_R_Brace);
401 } while (1);
402
403 if (systemp->domains.count == 0) lex_fatal("At least one domain expected for system \"%s\"", systemp->namep);
404
405 lex_unget();
406}
407
408
409
410 /*
411 * OK, the more complicated function
412 * to determine and connect the different
413 * components of a domain.
414 */
415
416void parse_domain(domain_t *domainp)
417{
418 LIST_INIT( domainp->procs, config_proc_t );
419 domainp->device.count = 0;
420 domainp->device.listp = (config_dev_t *)0;
421
422 do {
423 lexer_tok_t tok;
424
425 tok = lex_get_token();
426 if (tok == T_EOF) lex_fatal("unexpected EOF within domain defn");
427 if (tok == T_R_Brace) break;
428 if (tok != T_Token) goto fail;
429
430 if (streq(lex.strp, "sysclkfreq")) {
431 domainp->sysclkfreq = parse_number_assign();
432 } else
433 if (streq(lex.strp, "processor")) {
434 parse_proc(domainp);
435 } else
436 if (streq(lex.strp, "addressmap")) {
437 parse_addressmap(domainp);
438 } else {
439fail:
440 lex_fatal("domain specific token expected");
441 }
442
443 } while (1);
444
445 lex_unget();
446
447 if (domainp->sysclkfreq == 0) lex_fatal("sysclkfreq not specified in domain definition");
448
449 /* processor specific domain check of stuff parsed from conf file */
450 LIST_ENTRY(domainp->procs, 0)->proc_typep->domain_check(domainp);
451
452}
453
454
455
456
457
458
459 /*
460 * Handle the proc "name" wrapper around a processor definition.
461 * This enables us to select the correct processor handler
462 * then call into that handler to complete the parsing
463 * of this specific processor.
464 */
465
466void parse_proc(domain_t *domainp)
467{
468 proc_type_t * proc_typep;
469 config_proc_t * config_procp;
470
471 lex_get(T_String); /* get the name of the proc type */
472
473 proc_typep = find_proc_type(lex.strp);
474 if (proc_typep == (proc_type_t *)0) lex_fatal("unknown processor type \"%s\"", lex.strp);
475
476 /*
477 * If the processor type module has not been loaded and
478 * initialised .. do so now
479 */
480 if (!proc_typep->flag_initialised) {
481 if (!proc_typep->init_module(proc_typep)) fatal("Failed initialising processor module %s", proc_typep->proc_type_namep);
482 }
483
484 lex_get(T_L_Brace);
485
486 /* OK, allocate the proc entry */
487 config_procp = LIST_ADD( domainp->procs, config_proc_t );
488
489 config_procp->proc_id = domainp->procs.count -1;
490 config_procp->proc_typep = proc_typep;
491 config_procp->domainp = domainp;
492
493 /* based on the proc type we call the proc-dependent parser */
494 proc_typep->parse_proc(domainp, config_procp);
495
496 /* finish up cleanly */
497
498 lex_get(T_R_Brace);
499}
500
501
502
503
504
505
506
507 /*
508 * This function (eventually) parses the address map
509 * for each domain. Basically, this creates the devices
510 * that are attached directly to the domain memory bus.
511 *
512 * Unnecessary ? FIXME
513 */
514
515void parse_addressmap(domain_t *domainp)
516{
517 lexer_tok_t tok;
518
519 lex_get(T_L_Brace);
520
521 /* for now - just swallow until the } */
522 while (1) {
523 tok = lex_get_token();
524 if (tok == T_EOF) lex_fatal("unexpected end of file");
525 if (tok == T_R_Brace) break;
526
527 if (tok != T_Token) lex_fatal("addressmap element expected");
528
529 if (streq(lex.strp, "device")) {
530 parse_device(domainp);
531 } else if (streq(lex.strp, "mmi_device")) {
532 parse_mmi_device(domainp);
533 } else {
534 lex_fatal("unknown/unexpected token %s in addressmap", lex.strp);
535 }
536
537 } while (tok != T_EOF && tok != T_R_Brace);
538 lex_unget();
539
540 /* finish up cleanly */
541 lex_get(T_R_Brace);
542}
543
544
545
546
547
548
549 /*
550 * having decided the address map entry is a device,
551 * parse its name, base, and extent, then drop into the
552 * device's own parsing routine.
553 */
554
555void parse_device(domain_t *domainp)
556{
557 config_dev_t * config_devp, *overlapp;
558 config_addr_t *config_addrp;
559 dev_type_t * dev_typep;
560 bool_t is_size;
561 lexer_tok_t tok;
562
563 /*
564 * We've found a device name so check whether we have a library
565 * for this dev_type.
566 */
567 lex_get(T_String);
568 dev_typep = find_dev_type(lex.strp);
569 if (dev_typep == (dev_type_t *)0) lex_fatal("unknown dev type \"%s\"",lex.strp);
570 /* OK, allocate the proc entry */
571 config_devp = Xmalloc(sizeof (config_dev_t));
572
573 config_devp->is_implied = false; /* this is a real device */
574 config_devp->dev_typep = dev_typep;
575 config_devp->devp = (void*)0; /* gets allocated in the dev parser */
576 config_devp->addrp = NULL; /* see insert_domain_address() */
577
578 do {
579 tpaddr_t baseaddr, topaddr;
580
581 lex_get(T_Number);
582 baseaddr = lex.val;
583
584 is_size = false;
585 tok = lex_get_token();
586 if (tok == T_Plus) is_size = true; else lex_unget();
587
588 lex_get(T_Number);
589 topaddr = lex.val;
590 if (is_size)
591 topaddr += baseaddr;
592
593 if (topaddr <= baseaddr)
594 lex_fatal("top address <= base address with device %s",
595 config_devp->dev_typep->dev_type_namep);
596
597 insert_domain_address(domainp, config_devp, baseaddr, topaddr);
598
599 } while (lex_get_token() == T_Comma);
600
601 lex_unget();
602
603 /* Insert device into the domain */
604 overlapp = insert_domain_device(domainp, config_devp);
605
606 if (overlapp != NULL) {
607 lex_fatal("device \"%s\" @ 0x%llx overlaps with device \"%s\" @ 0x%llx",
608 overlapp->dev_typep->dev_type_namep,
609 overlapp->addrp->baseaddr,
610 config_devp->dev_typep->dev_type_namep,
611 config_devp->addrp->baseaddr);
612 }
613
614 /* based on the dev type we call the dev-dependent parser */
615 dev_typep->parse_dev(config_devp);
616}
617
618
619
620/*
621 * Parse MMI device
622 */
623void parse_mmi_device(domain_t *domainp)
624{
625 config_dev_t * config_devp, *overlapp;
626 config_addr_t *config_addrp;
627 dev_type_t * dev_typep;
628 lexer_tok_t tok;
629
630 config_devp = Xmalloc(sizeof (config_dev_t));
631
632 /*
633 * parse to get the MMI device name
634 */
635 lex_get(T_String);
636 if (lex.strp == NULL)
637 lex_fatal("missing MMI device name in parse_mmi_device");
638
639 sam_init_device(lex.strp, config_devp);
640
641 /*
642 * finish the parsing
643 */
644 sam_parse_dev(domainp, config_devp);
645
646 /*
647 * load MMI SAM device module
648 */
649 dev_typep = sam_load_device(config_devp);
650 if (dev_typep == (dev_type_t *)0) lex_fatal("unknown dev type \"%s\"",lex.strp);
651
652 /*
653 * Found a matching library, add it to the loaded list.
654 *
655 * NOTE: We do not dlclose() the libarary here as we know it will be
656 * needed later on when the functions in the dev_typep are accessed.
657 */
658 LIST_ADD_PTR(dev_cache, dev_type_t, dev_typep);
659}
660
661 /*
662 * Support functions for other parser codes
663 */
664
665 /*
666 * Parse a number assignment:
667 * e.g. 0x40000 ;
668 */
669
670uint64_t parse_number_assign()
671{
672 uint64_t val;
673
674 lex_get(T_Number);
675 val = lex.val;
676 lex_get(T_S_Colon);
677
678 return (val);
679}
680
681/*
682 * dlopen a lib["mdlnamep"].so in the plugins/ dir or in the
683 * options.libpath search path and locate the symbol "symname".
684 * If there is a pre-existing handle - use it.
685 * If the library was successfully opened, save the handle.
686 * Once a valid handle is avail, get the address of symname and return.
687 * Don't log error on failure to add to htable; non-fatal, only affects
688 * performance.
689 */
690#define MAX_DLENT 128 /* max dlentries cacheable */
691typedef struct {
692 char *so_path; /* fq path to lib where symbol found */
693 void *so_addr; /* shared object symbol address */
694} dlitem_t;
695
696void *
697dlopen_lib(char *mdlnamep, char *symname, char *libname)
698{
699 static int first_pass = 0;
700 void *dlh = NULL, *fptr = NULL;
701 int idx;
702 char *pathp;
703 ENTRY item, *f_item;
704 char hkey[128];
705 dlitem_t *dip;
706
707 if (first_pass == 0) {
708 (void) hcreate(MAX_DLENT);
709 first_pass = 1;
710 }
711
712 sprintf(hkey, "%s%s", mdlnamep, symname);
713 item.key = hkey;
714DBG( printf("Looking for module [%s][%s]\n", mdlnamep, symname); );
715
716 if ((f_item = hsearch(item, FIND)) != NULL) {
717 /* found it, return info */
718 dip = (dlitem_t *)f_item->data;
719 strcpy(libname, dip->so_path);
720DBG( printf("Found [%s][%s] %p\n",
721 mdlnamep, symname, dip->so_addr); );
722 return (dip->so_addr);
723 }
724
725 /* not found, try to open and add it on libpath */
726 for (idx = 0; idx < options.libpath.count; idx++) {
727 pathp = LIST_ENTRY(options.libpath, idx);
728 sprintf(libname, "%s/lib%s.so", pathp, mdlnamep);
729
730DBG( printf("Loading the [%s] module - %s\n", mdlnamep, libname); );
731
732 if (NULL != (dlh = dlopen(libname, RTLD_NOW))) {
733 goto dlopen_success;
734 }
735 }
736
737 /* not found, try to open and add it on compiled in default paths */
738 sprintf(libname, "lib%s.so", mdlnamep);
739DBG( printf("Loading the [%s] module - %s\n", mdlnamep, libname); );
740
741 if (NULL == (dlh = dlopen(libname, RTLD_NOW))) {
742 printf("\tdlopen_lib error opening [%s]\t%s\n",
743 mdlnamep, dlerror());
744 return (NULL);
745 }
746
747dlopen_success:
748 /* Found a library in libpath that we can open */
749DBG( printf("\tFound and opened [%s]\n", libname); );
750
751 /* Extract and return the symbol address from the shared object */
752 if (NULL == (fptr = dlsym(dlh, symname))) {
753 printf("\tdlopen_lib: [%s]\n", dlerror());
754 /* do not add entry if no symbol found */
755 return (NULL);
756 }
757
758 /* Have a valid lib,symbol - add to lookup table */
759 dip = Xmalloc(sizeof (*dip));
760 dip->so_path = Xstrdup(libname);
761 dip->so_addr = (void *)fptr;
762 item.data = (void *)dip;
763 item.key = Xstrdup(hkey);
764
765 /* add item to lookup table */
766 if (NULL == hsearch(item, ENTER)) {
767 free((void *)dip->so_path);
768 free(item.data);
769 free((void *)item.key);
770 }
771
772 return (fptr);
773}
774
775
776/*
777 * Call dlopen_lib() to load the device module lib["devnamep"].so in
778 * the plugins/ dir. If a matching library is found:
779 *
780 * - use dlsym() to look for it's dev_type_t structure
781 * - check the dev_type_t name value matches the "devnamep"
782 * - add the matching library to the loaded list
783 * - return a pointer to the dev_type_t for this device
784 */
785dev_type_t * find_dev_type(char *devnamep)
786{
787 char symname[BUFSIZ], libname[BUFSIZ];
788 dev_type_t *dev_typep = NULL;
789 int idx;
790
791 if (devnamep == NULL)
792 return ((dev_type_t *)0);
793
794 /*
795 * First look through the cached list of device
796 * modules we've already opened.
797 */
798 for (idx = 0; idx < dev_cache.count; idx++) {
799 dev_typep = LIST_ENTRY(dev_cache, idx);
800
801 if (streq(dev_typep->dev_type_namep, devnamep))
802 return (dev_typep);
803 }
804
805 /*
806 * Dlopen the device module library
807 */
808 sprintf(symname, "dev_type_%s", devnamep);
809
810 dev_typep = (dev_type_t *)dlopen_lib(devnamep, symname, libname);
811 if (dev_typep == NULL)
812 return ((dev_type_t *)0);
813
814 /*
815 * Make sure the name in the dev_type_name matches the device
816 */
817 if (!streq(dev_typep->dev_type_namep, devnamep)) {
818 printf("\nERROR: name does not match. %s != %s in %s:%s\n",
819 dev_typep->dev_type_namep, devnamep, libname, symname);
820 return ((dev_type_t *)0);
821 }
822
823 /*
824 * Found a matching library, add it to the loaded list.
825 *
826 * NOTE: We do not dlclose() the libarary here as we know it will be
827 * needed later on when the functions in the dev_typep are accessed.
828 */
829 LIST_ADD_PTR(dev_cache, dev_type_t, dev_typep);
830
831 return (dev_typep);
832}
833
834
835/*
836 * Call dlopen_lib() to load the proc module lib["procnamep"].so in
837 * the plugins/ dir. If a matching library is found:
838 *
839 * - use dlsym() to look for it's proc_type_t structure
840 * - check the proc_type_t name value matches the "procnamep"
841 * - add the matching library to the loaded list
842 * - return a pointer to the proc_type_t for this proc
843 */
844proc_type_t * find_proc_type(char *procnamep)
845{
846 char symname[BUFSIZ], libname[BUFSIZ];
847 proc_type_t *proc_typep = NULL;
848 int idx;
849
850
851 if (procnamep == NULL)
852 return ((proc_type_t *)0);
853
854 /* First look through the cached list of processor
855 * modules we've already opened.
856 */
857
858 for (idx = 0; idx < proc_cache.count; idx++) {
859 proc_typep = LIST_ENTRY(proc_cache, idx);
860
861 if (streq(proc_typep->proc_type_namep, procnamep))
862 return (proc_typep);
863 }
864
865 /*
866 * Dlopen the proc module library
867 */
868 sprintf(symname, "proc_type_%s", procnamep);
869
870 proc_typep = (proc_type_t *)dlopen_lib(procnamep, symname, libname);
871 if (proc_typep == NULL)
872 return ((proc_type_t *)0);
873
874 /*
875 * Make sure the name in the proc_type_name matches the device
876 */
877 if (!streq(proc_typep->proc_type_namep, procnamep)) {
878 printf("\nERROR: name does not match. %s != %s in %s:%s\n",
879 proc_typep->proc_type_namep, procnamep, libname, symname);
880 return ((proc_type_t *)0);
881 }
882
883 /*
884 * Found a matching library, add it to the loaded list.
885 *
886 * NOTE: We do not dlclose() the libarary here as we know it will be
887 * needed later on when the functions in the proc_typep are accessed.
888 */
889 LIST_ADD_PTR(proc_cache, proc_type_t, proc_typep);
890
891 return (proc_typep);
892}
893
894 /*
895 * Insert a config device into the address map of a certain domain
896 * Returns NULL on success, the overlapping device node on failure.
897 */
898
899config_dev_t *
900insert_domain_device(domain_t *domainp, config_dev_t *config_devp)
901{
902 config_dev_t **pdp, *dp;
903
904 config_devp->domainp = domainp;
905 config_devp->device_id = domainp->device.count;
906
907 ASSERT(config_devp->addrp->topaddr > config_devp->addrp->baseaddr);
908 ASSERT(config_devp->addrp->range != (tvaddr_t)0);
909
910 /* insert into sorted list of devices ... */
911 for (pdp = &(domainp->device.listp); (dp = *pdp) != (config_dev_t *)0; pdp = &(dp->nextp)) {
912 if (dp->addrp->topaddr <= config_devp->addrp->baseaddr) continue;
913 if (dp->addrp->baseaddr >= config_devp->addrp->topaddr) break;
914
915 return (dp);
916 }
917
918 /* link device into list in order */
919 config_devp->nextp = *pdp;
920 *pdp = config_devp;
921 domainp->device.count ++;
922DBG( printf("insert_domain_device %p name=<%s> base=%p, top=%p\n",
923 config_devp, config_devp->dev_typep->dev_type_namep,
924 config_devp->addrp->baseaddr,
925 config_devp->addrp->topaddr); );
926 return (NULL);
927}
928
929/*
930 * Insert a config address into the address map of a certain domain
931 * Returns NULL on success, the overlapping device node on failure.
932 */
933
934config_addr_t *
935insert_domain_address(domain_t *domainp, config_dev_t *devp, tpaddr_t baseaddr, tpaddr_t topaddr)
936{
937 config_addr_t **pap, *ap, *addrp;
938
939 addrp = Xmalloc(sizeof (config_addr_t));
940
941 addrp->config_devp = devp;
942 addrp->baseaddr = baseaddr;
943 addrp->topaddr = topaddr;
944 /* save us annoying adds and subs all the time */
945 addrp->range = topaddr - baseaddr;
946
947 if (devp->addrp == NULL)
948 devp->addrp = addrp;
949
950 /* insert into sorted list of addresses ... */
951 for (pap = &(domainp->address.listp); (ap = *pap) != NULL;
952 pap = &(ap->nextp)) {
953 if (ap->topaddr <= addrp->baseaddr) continue;
954 if (ap->baseaddr >= addrp->topaddr) break;
955 return (ap);
956 }
957
958 /* link device into list in order */
959 addrp->nextp = *pap;
960 *pap = addrp;
961 domainp->address.count++;
962DBG( printf("insert_domain_address devp=%p addrp=%p base=%llx, "
963 "top=%llx\n",
964 addrp->config_devp, addrp, addrp->baseaddr,
965 addrp->topaddr); );
966 return (NULL);
967}