Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / tracemod / tm_api.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: tm_api.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/*
22 * Copyright (C) 1991, 2001 Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25#pragma ident "@(#)1.4 01/11/06 tm_api.cc"
26
27/*
28 * Copyright (c) 1989, Sun Microsystems, Inc. All Rights Reserved. Sun
29 * considers its source code as an unpublished, proprietary trade secret, and
30 * it is available only under strict license provisions. This copyright
31 * notice is placed here only to protect Sun in the event the source is
32 * deemed a published work. Disassembly, decompilation, or other means of
33 * reducing the object code to human readable form is prohibited by the
34 * license agreement under which this code is provided to the user or company
35 * in possession of this copy
36 *
37 * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
38 * Government is subject to restrictions as set forth in subparagraph
39 * (c) (1) (ii) of the Rights in Technical Data and Computer Software clause
40 * at DFARS 52.227-7013 and in similar clauses in the FAR and NASA FAR
41 * Supplement
42 */
43
44#include <sys/types.h>
45#include <assert.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <strings.h>
50#include <synch.h>
51#include <dlfcn.h>
52#include <limits.h>
53
54#include "types.h"
55#include "blaze_globals.h"
56#include "system.h"
57
58typedef void* TM_OPAQUE_DATA;
59#include "tracemod.h"
60
61#include "ui.h"
62#include "tm_impl.h"
63
64LdmNode *head_ldm = NULL; // The head of tracing LDM's
65LdmNode *head_spec_ldm = NULL; // The head of the list of BLAZE extensions
66
67uint64_t tm_time_target = 0xffffffffffffffffLLU; // Is used for global time interval event handler
68uint64_t tm_time_interval = 0; // Is used for global time interval event handler
69
70static LdmCmdNode *head_ldm_cmd = NULL;
71static char help_string [] = "usage : mod load <type> <sofile> [<arglist>] | mod unload <name>\n\
72 type ::= analyzer | py | remote\n";
73
74static char mmi_help_string_1 [] = "usage : ldm <dev name> <instance name> [<sofile><arglist>]";
75static char mmi_help_string_2 [] = "usage : uldm <instance name>";
76static char mmi_help_string_3 [] = "usage : ioa <ADDR1> <ADDR2> ";
77static char mmi_help_string_4 [] = "usage : sysconf [-p <modpath> ] <modname> "
78 "[ <instance_name> [ args... ] ]";
79static char mmi_help_string_5 [] = "usage : module [<modname> ...]";
80
81//////////////////////////////////////////////////
82
83
84
85//
86//TODO: commands which require STOP
87//
88//////////////////////////////////////////////////
89
90Ldm * ldm_add_spec (char * name, const char *soname)
91{
92 int ii;
93 Ldm *pldm;
94 LdmNode *pnode;
95
96 if (soname) {
97 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
98
99 pldm = pnode->GetData ();
100 if (strcmp (name, pldm->name) == NULL) {
101 ui->error("module %s - %s is already loaded !\n", name, soname);
102 return NULL;
103 }
104 if (pldm->soname && (strcmp(soname, pldm->soname) == NULL )) {
105 ui->error("module %s - %s is already loaded !\n", name, soname);
106 return NULL;
107 }
108
109 }
110 }
111 else {
112 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
113 pldm = pnode->GetData ();
114 if (strcmp (name, pldm->name) == NULL) {
115 return NULL;
116 }
117 }
118 }
119
120 pnode = LdmNode::CreateInstance ("MOD list");
121 if (pnode == NULL) {
122 ui->error("Unable to load %s-%s : unable to allocate memory\n",
123 soname ? soname : "**", name);
124 return NULL;
125 }
126 pldm = pnode->GetData ();
127
128 pldm->name = (char*)strdup(name);
129 pldm->soname = soname ? (char*)strdup(soname) : NULL;
130 pldm->mode = TM_CBMODE;
131
132 for (ii = 0; ii < MAX_MP; ii++)
133 pldm->memop[ii] = TM_CONST_BADMEM;
134
135 pldm->type = TM_TYPE_EXT_UNKNOWN;
136
137 LdmNode::AddTail (&head_spec_ldm, pnode);
138 return pldm;
139} // ldm_add_spec()
140
141//////////////////////////////////////////////////
142
143static Ldm * ldm_add (char * name, const char *soname)
144{
145 int ii;
146
147 LdmNode *pnode;
148 for (pnode=head_ldm; pnode; pnode=pnode->Next()) {
149 Ldm * pldm = pnode->GetData();
150
151 if ((strcmp (name, pldm->name) == NULL) || (strcmp (soname, pldm->soname) == NULL)) {
152 ui->error("module %s - %s is already loaded !\n", name, soname);
153 return NULL;
154 }
155 }
156
157 pnode = LdmNode::CreateInstance ("MOD list");
158 if (pnode == NULL) {
159 ui->error("Unable to register MODULE <%s>\n", name);
160 return NULL;
161 }
162
163 Ldm * pldm = pnode->GetData ();
164
165 pldm->name = (char*)strdup(name);
166 pldm->soname = (char*)strdup(soname);
167 pldm->mode = TM_CBMODE;
168 for (ii = 0; ii < MAX_MP; ii++)
169 pldm->memop[ii] = TM_CONST_BADMEM;
170 pldm->type = TM_TYPE_LDM;
171
172 LdmNode::AddTail (&head_ldm, pnode);
173
174
175 return pldm;
176}
177
178//////////////////////////////////////////////////////
179
180static void ldm_delete_head ()
181{
182 LdmNode::DeleteHead(&head_ldm);
183}
184
185//////////////////////////////////////////////////////
186
187void ldm_delete_head_spec ()
188{
189 LdmNode::DeleteHead(&head_spec_ldm);
190}
191
192//////////////////////////////////////////////////
193
194static LdmCmd * ldm_cmd_add (const char * name, fn_ui_1 action1, fn_ui_2 action2)
195{
196 LdmCmd *pldm_cmd;
197 LdmCmdNode *pnode = LdmCmdNode::CreateInstance ("CMD list");
198
199 if (pnode == NULL) {
200 ui->error("Unable to register UI CMD <%s>\n", name);
201 return NULL;
202 }
203 pldm_cmd = pnode->GetData ();
204
205 pldm_cmd->name = (char*)strdup(name);
206 pldm_cmd->cmd_action_1 = action1;
207 pldm_cmd->cmd_action_2 = action2;
208
209 LdmCmdNode::AddHead (&head_ldm_cmd, pnode);
210 return pldm_cmd;
211}
212
213//////////////////////////////////////////////////
214
215
216// ----------------------------------------------------------------------------
217
218struct mod_list {
219 char * name;
220 struct mod_list * next;
221} mod_list = {"$ORIGIN/../lib/", NULL}; /* $ORIGIN always at end of search */
222
223
224void mod_setdefault (char * subdir) /* change "../lib/" to "../lib-obp/" */
225{ /* in the $origin search path */
226 static char new_default[PATH_MAX];
227
228 sprintf (new_default, "$ORIGIN/../%s/", subdir);
229 mod_list.name = new_default;
230}
231
232
233struct mod_list * mod_head = & mod_list;
234struct mod_list * mod_tail = & mod_list;
235
236
237// hmmm, shouldn't mod_addpath() do a "push" rather than an "insert"...
238
239void mod_addpath (char * path) /* subsequent dirs are inserted in */
240{ /* front of the $ORIGIN last entry */
241 struct mod_list * p;
242 p = (struct mod_list*) malloc (sizeof (struct mod_list));
243 p->name = strdup (path);
244 p->next = mod_tail;
245 if (mod_head == mod_tail) {
246 mod_head = p;
247 } else {
248 struct mod_list * q = mod_head;
249 while (q->next != mod_tail) q = q->next;
250 q->next = p;
251 }
252}
253
254
255void * mod_dlopen (char * pathp, char * fname, int flags)
256{
257 void * result = NULL;
258 char temp[PATH_MAX];
259
260 const char * dlerr;
261
262 if ( (fname[0] == '/') /* don't mess with absolute file paths */
263 ||(fname[0] == '.' && fname[1] == '/')
264 ||(fname[0] == '.' && fname[1] == '.' && fname[2] == '/')) {
265 sprintf (temp, "%s", fname);
266 result = dlopen (temp, flags);
267 if (result == NULL) {
268 dlerr = dlerror();
269 if (dlerr != NULL) {
270 ui->error("dlopen(%s)...\n %s\n", temp, dlerr);
271 }
272 }
273
274 } else if (pathp != NULL) { /* use explicit path if provided */
275 sprintf (temp, "%s/%s", pathp, fname);
276 result = dlopen (temp, flags);
277
278 if (result == NULL) {
279 dlerr = dlerror();
280 if (dlerr != NULL) {
281 ui->error("dlopen(%s)...\n %s\n", temp, dlerr);
282 }
283 }
284
285 } else { /* otherwise use searchlist */
286 for (struct mod_list * p = mod_head; p != NULL; p = p->next) {
287
288 sprintf (temp, "%s/%s", p->name, fname);
289 result = dlopen (temp, flags);
290
291 if (result == NULL) {
292 dlerr = dlerror();
293 if(dlerr) {
294 ui->output("dlopen(%s): trying path %s...\n %s\n", fname, temp, dlerr);
295 }
296 } else
297 break; /* <-- found it ! */
298 }
299 }
300
301 if (result != NULL)
302 ui->verbose("dlopen(%s): loaded successfully\n", temp);
303 else {
304 ui->error("dlopen(%s): failed (unresolved symbols or sysconf search path incorrect)\n",fname);
305 }
306
307 return result;
308}
309
310// ----------------------------------------------------------------------------
311
312
313
314
315
316// the following mod commands are currently supported:
317// mod load <modname> <module.so>
318// mod unload <modname>
319//
320const char mod_cmd_usage[] = "Usage: mod <load|unload> <analyzer|py> [path/lib_name.so]\n";
321//
322static void * dlhandle = NULL;
323//
324void *(*vtracer_initfn)(const char *) = NULL;
325void (*vtracer_finifn)() = NULL;
326//
327
328
329int init_tracer(char* fname, char* modname, void* lib_handle)
330{
331
332 dlhandle = lib_handle;
333
334 // FIXME: currently, only one vtrace module is supported. 2005.09.27
335 if (g_vcpu[0]->sys_intf.vtrace != NULL) {
336 ui->error("a vtracer is already loaded. Only one vtracer is supported at this time\n");
337 return 0;
338 }
339
340
341 vtracer_initfn = (void *(*)(const char *)) dlsym(dlhandle, "vtracer_init");
342 if (vtracer_initfn == NULL) {
343 ui->error("mod load: could not find symbol vtracer_init() in %s: %s\n", fname, dlerror());
344 dlclose(dlhandle);
345 return 0;
346 }
347 vtracer_finifn = (void (*)()) dlsym(dlhandle, "vtracer_fini");
348 if (vtracer_finifn == NULL) {
349 ui->error("mod load: could not find symbol vtracer_fini() in %s: %s\n", fname, dlerror());
350 dlclose(dlhandle);
351 return 0;
352 }
353
354 VTracer * the_vtracer = (VTracer *) vtracer_initfn(modname);
355
356 for (int i=0; i<=g_vcpu_id_max; i++)
357 {
358 Vcpu *vcpu = get_vcpu(i);
359 if (vcpu)
360 {
361 vcpu->sys_intf.vtrace = the_vtracer;
362 vcpu->config.trace_on = 1;
363 }
364 }
365 return 1;
366}
367
368
369int close_tracer()
370{
371 if (dlhandle != NULL) {
372 if (vtracer_finifn != NULL) {
373 vtracer_finifn();
374 }
375
376 dlclose(dlhandle);
377 dlhandle = NULL;
378
379 int i;
380 for (i=0; i<=g_vcpu_id_max; i++)
381 {
382 Vcpu *vcpu = get_vcpu(i);
383 if (!vcpu)
384 continue;
385 vcpu->sys_intf.vtrace = NULL;
386 vcpu->config.trace_on = 0;
387 }
388 return 0;
389 }
390 else
391 {
392 ui->error("mod unload: no vtracer module is currently loaded\n");
393 return 1;
394 }
395}
396
397///////////////////////////////////////////////////////////////////////////////
398//
399// py init
400
401typedef int (*init_py_t)(char*, char*, void*);
402
403int init_py(char* fname, char* modname, void* lib_handle)
404{
405 init_py_t py_initfn = (init_py_t)dlsym(lib_handle, "init_py_interface");
406 if (py_initfn == NULL)
407 {
408 ui->error("mod load: could not find symbol init_py_interface() in %s: %s\n", fname, dlerror());
409 dlclose(dlhandle);
410 return 0;
411 }
412
413 return py_initfn (fname, modname, lib_handle);
414}
415
416
417///////////////////////////////////////////////////////////////////////
418//
419
420int mod_cmd_action(void*, int argc, char **argv)
421{
422 if (argc == 1) {
423 ui->output(mod_cmd_usage);
424 return 1;
425 }
426
427 char * modname = NULL;
428 char * fname = NULL;
429
430 if (strcmp(argv[1], "load") == 0)
431 {
432 if (argc != 4 && argc != 3)
433 {
434 ui->output(mod_cmd_usage);
435 return 0;
436 }
437 modname = argv[2];
438
439 char suffixedname[PATH_MAX];
440 if (argc == 4) fname = argv[3];
441 else
442 { /* if there isn't an argv[3] then construct one from argv[2] */
443 sprintf (suffixedname, "%s.so", argv[2]);
444 fname = suffixedname;
445 }
446
447
448 if (ANY_RUNNING_STATE(blaze_run_state)) {
449 ui->error("not in stop state, use stop command first\n");
450 return 0;
451 }
452
453
454 void *dlib_handle = mod_dlopen (NULL, fname, RTLD_LAZY|RTLD_GLOBAL);
455 if (dlib_handle == NULL)
456 {
457 return 0;
458 }
459
460 if (strcmp(modname,"analyzer")==0)
461 {
462 return init_tracer(fname, modname, dlib_handle);
463 }
464 else if(strcmp(modname,"py")==0)
465 {
466 ui->verbose("loading python interpreter....\n");
467 return init_py(fname, modname, dlib_handle);
468 }
469 else if(strcmp(modname,"remote")==0)
470 {
471 extern int init_remote_debugger_interface (char*, char*, void*);
472 ui->verbose(" loading interface for remote debugger....\n");
473 return init_remote_debugger_interface(fname, modname, dlib_handle);
474 }
475 else if (strcmp(modname,"lib")==0)
476 {
477 ui->verbose("lib %s was loaded. \n", fname);
478 return 1;
479 }
480 else
481 {
482 ui->error(" %s : unknown module name\n%s\n", modname, mod_cmd_usage);
483 dlclose(dlib_handle);
484 return 0;
485 }
486 }
487 else if (strcmp(argv[1], "unload") == 0)
488 {
489 if (argc < 3)
490 {
491 ui->output(mod_cmd_usage);
492 return 0;
493 }
494 modname = argv[2];
495
496 if (strcmp(modname,"analyzer")==0)
497 {
498 return close_tracer ();
499 }
500 else if(strcmp(modname,"py")==0)
501 {
502 ui->error("cannot unload python interpreter module\n");
503 return 0;
504 }
505 else if(strcmp(modname,"remote")==0)
506 {
507 ui->error("cannot unload remote interface module\n");
508 return 0;
509 }
510 else
511 {
512 ui->error("%s: unknown module name\n%s\n", modname, mod_cmd_usage);
513 return 0;
514 }
515
516 } /* if argv[1] eq ? */
517 else
518 {
519 ui->error("Invalid argument %s\n%s\n", argv[1], mod_cmd_usage);
520 return 1;
521 }
522
523} // int mod_cmd_action(void*, int argc, char **argv)
524
525
526
527
528//////////////////////////////////////////////////
529
530int extra_cmd_action_1 (void*, int /*argc*/, char **argv)
531{
532 LdmCmdNode *pnode = head_ldm_cmd;
533 LdmCmd *pldm_cmd;
534
535 for (;pnode;pnode = pnode->Next()) {
536 pldm_cmd = pnode->GetData ();
537 if (strcmp(argv[0], pldm_cmd->name) == NULL) {
538 if (pldm_cmd->cmd_action_1)
539 return pldm_cmd->cmd_action_1 (pldm_cmd->ldm->client_data, argv[1]);
540 }
541 }
542 return 1;
543}
544
545//////////////////////////////////////////////////
546
547int extra_cmd_action_2 (void*, int argc, char **argv)
548{
549
550 LdmCmdNode *pnode = head_ldm_cmd;
551 LdmCmd *pldm_cmd;
552
553 for (;pnode; pnode = pnode->Next()) {
554 pldm_cmd = pnode->GetData ();
555 if (strcmp(argv[0], pldm_cmd->name) == NULL) {
556 if (pldm_cmd->cmd_action_2)
557 return pldm_cmd->cmd_action_2 (pldm_cmd->ldm->client_data, argc, argv);
558 }
559 }
560 return 1;
561}
562
563//////////////////////////////////////////////////
564//////////////////////////////////////////////////
565
566extern int mmi_cmd_action (void*, int argc, char **argv) ;
567
568void init_tm ()
569{
570 UI_register_cmd_2 ((char*)"mod", help_string, mod_cmd_action, NULL);
571 UI_register_cmd_2 ((char*)"mmi", mmi_help_string_1, mmi_cmd_action, NULL);
572 UI_register_cmd_2 ((char*)"ldm", mmi_help_string_1, mmi_cmd_action, NULL);
573 UI_register_cmd_2 ((char*)"ioa", mmi_help_string_1, mmi_cmd_action, NULL);
574 UI_register_cmd_2 ((char*)"uldm",mmi_help_string_2, mmi_cmd_action, NULL);
575 UI_register_cmd_2 ((char*)"cfg", mmi_help_string_4, mmi_cmd_action, NULL);
576 UI_register_cmd_2 ((char*)"sysconf", mmi_help_string_4, mmi_cmd_action, NULL);
577 UI_register_cmd_2 ((char*)"modinfo", mmi_help_string_5, mmi_cmd_action, NULL);
578
579 ldm_tick_ext_init();
580}
581
582
583//////////////////////////////////////////////////
584//////////////////////////////////////////////////
585//// TM API routines ////
586//////////////////////////////////////////////////
587//////////////////////////////////////////////////
588
589
590void TM_enable_interval (uint64_t ti)
591{
592 tm_time_interval = ti;
593 tm_time_target = ti + SYSTEM_get_ticks ();
594}
595void TM_disable_interval ()
596{
597 tm_time_target = 0xffffffffffffffffLLU;
598 tm_time_interval = 0;
599}
600
601//////////////////////////////////////////////////
602
603void TM_invalidate (tracemod_t *pmod)
604{
605 pmod->valid = 0;
606}
607
608//////////////////////////////////////////////////
609static void delete_args(Ldm *pldm)
610{
611 for (int i = 0; i < pldm->argc; i++)
612 free(pldm->argv[i]);
613 if (pldm->argv)
614 free(pldm->argv);
615}
616
617
618//////////////////////////////////////////////////
619void TM_clean_mod ()
620{
621 Ldm *pldm;
622 LdmNode *pnode, *prv = NULL;
623 bool_t rem = FALSE;
624
625 while (TRUE) {
626 for (pnode=head_ldm; pnode!=NULL; pnode = pnode->Next()) {
627 pldm = pnode->GetData ();
628 if (!pldm->valid) {
629 ui->error("TM: invalidating module <%s>\n", pldm->name);
630 if (pldm->so_handle) {
631 if (dlclose (pldm->so_handle))
632 ui->error("TM: dlclose failed: %s\n", dlerror());
633 }
634 delete_args(pldm);
635 LdmNode::DeleteNode (&head_ldm, prv);
636 rem = TRUE;
637 break;
638 }
639 prv = pnode;
640 }
641 if (rem) {
642 rem = FALSE;
643 continue;
644 }
645 else {
646 break;
647 }
648 }
649}
650
651//////////////////////////////////////////////////
652
653Ldm * TM_find_mod_spec (char * name)
654{
655 Ldm *pldm;
656 LdmNode *pnode;
657
658 if (!name)
659 return NULL;
660
661 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
662 pldm = pnode->GetData ();
663 if (strcmp(pldm->name, name) == NULL) {
664 return pldm;
665 }
666 }
667 return NULL;
668}
669
670//////////////////////////////////////////////////
671
672Ldm * TM_find_mod_spec_instance (tracemod_t *parent, char * name)
673{
674 Ldm *pldm;
675 LdmNode *pnode;
676
677 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
678 pldm = pnode->GetData ();
679 if ((pldm->parent == parent) && (!name || !strcmp(pldm->name, name))) {
680 return pldm;
681 }
682 }
683 return NULL;
684}
685
686//////////////////////////////////////////////////
687void TM_clean_mod_spec ()
688{
689 Ldm *pldm;
690 LdmNode *pnode, *prv = NULL;
691 bool_t rem = FALSE;
692
693 while (TRUE) {
694 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
695
696 pldm = pnode->GetData ();
697 if (!pldm->valid) {
698 ui->error("TM: invalidating module <%s>\n", pldm->name);
699 if (pldm->so_handle) {
700 if (dlclose (pldm->so_handle))
701 ui->error("TM: dlclose failed: %s\n", dlerror());
702 }
703 delete_args(pldm);
704 LdmNode::DeleteNode (&head_spec_ldm, prv);
705 rem = TRUE;
706 break;
707 }
708 prv = pnode;
709 }
710 if (rem) {
711 rem = FALSE;
712 continue;
713 }
714 else {
715 break;
716 }
717 }
718}
719
720//////////////////////////////////////////////////
721
722bool_t TM_verify (tracemod_t *pmod)
723{
724
725 Ldm *pldm;
726 LdmNode *pnode;
727
728 if (!pmod)
729 return FALSE;
730
731 for (pnode=head_ldm; pnode!=NULL; pnode=pnode->Next()) {
732 pldm = pnode->GetData ();
733 if (pmod == pldm) {
734 return TRUE;
735 }
736 }
737
738 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
739 pldm = pnode->GetData ();
740 if (pmod == pldm) {
741 return TRUE;
742 }
743 }
744 return FALSE;
745}
746
747//////////////////////////////////////////////////
748
749tracemod_t *TM_self_register (const char* mod_name,
750 const char *help, TM_OPAQUE_DATA client_data)
751{
752 Ldm *pldm;
753 LdmNode *pnode;
754
755 for (pnode=head_ldm; pnode!=NULL; pnode=pnode->Next()) {
756 pldm = pnode->GetData ();
757 if (strcmp(mod_name, pldm->name) == NULL) {
758 pldm->help = (char*) help;
759 pldm->client_data = client_data;
760 pldm->valid = TRUE;
761 return pldm;
762 }
763 }
764 ui->error("TM : unable to find MODULE <%s> \n", mod_name);
765 return NULL;
766}
767
768//////////////////////////////////////////////////
769
770tracemod_t *TM_self_register_spec (const char* mod_name, TM_OPAQUE_DATA client_data)
771{
772 Ldm *pldm;
773 LdmNode *pnode;
774
775
776 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
777 pldm = pnode->GetData ();
778 if (strcmp(mod_name, pldm->name) == NULL) {
779 pldm->help = NULL;
780 pldm->client_data = client_data;
781 pldm->valid = TRUE;
782 return pldm;
783 }
784 }
785
786 ui->error("TM : unable to find MODULE <%s> \n", mod_name);
787 return NULL;
788}
789
790//////////////////////////////////////////////////
791
792void TM_ui_register_1 (tracemod_t* pmod, const char* name,
793 const char */*shelp*/, const char * lhelp, fn_ui_1 fn)
794{
795 LdmNode *pnode;
796 Ldm *pldm;
797 LdmCmd *pldm_cmd;
798
799 for (pnode=head_ldm; pnode!=NULL; pnode=pnode->Next()) {
800
801 pldm = pnode->GetData ();
802 if (pmod == pldm) {
803 if (pldm_cmd = ldm_cmd_add (name, fn, NULL)) {
804 UI_register_cmd_1 ((char*)name, (char*)lhelp, extra_cmd_action_1, NULL);
805 pldm_cmd->ldm = pldm;
806 }
807 return;
808 }
809 }
810
811 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
812 pldm = pnode->GetData ();
813 if (pmod == pldm) {
814 if (pldm_cmd = ldm_cmd_add (name, fn, NULL)) {
815 UI_register_cmd_1 ((char*)name, (char*)lhelp, extra_cmd_action_1, NULL);
816 pldm_cmd->ldm = pldm;
817 }
818 return;
819 }
820 }
821
822 ui->error("TM: module <%s> not found\n", pldm->name);
823}
824
825//////////////////////////////////////////////////
826
827void TM_ui_register_2 (tracemod_t* pmod, const char* name,
828 const char */*shelp*/, const char * lhelp, fn_ui_2 fn)
829{
830 LdmNode *pnode;
831 Ldm *pldm;
832 LdmCmd *pldm_cmd;
833
834 for (pnode=head_ldm; pnode!=NULL; pnode=pnode->Next()) {
835
836 pldm = pnode->GetData ();
837 if (pmod == pldm) {
838 if (pldm_cmd = ldm_cmd_add (name, NULL, fn)) {
839 UI_register_cmd_2 ((char*)name, (char*)lhelp, extra_cmd_action_2, NULL);
840 pldm_cmd->ldm = pldm;
841 }
842 return;
843 }
844 }
845
846 for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
847 pldm = pnode->GetData ();
848 if (pmod == pldm) {
849 if (pldm_cmd = ldm_cmd_add (name, NULL, fn)) {
850 UI_register_cmd_2 ((char*)name, (char*)lhelp, extra_cmd_action_2, NULL);
851 pldm_cmd->ldm = pldm;
852 }
853 return;
854 }
855 }
856
857 ui->error("TM: module <%s> not found\n", pldm->name);
858}
859
860//////////////////////////////////////////////////
861
862void TM_time_interval_register (tracemod_t *pmod, fn_time_interval fn)
863{
864 pmod->ti_action = fn;
865}
866//////////////////////////////////////////////////
867
868void TM_ui_unregister (tracemod_t* /*pmod*/, const char *name)
869{
870
871 LdmCmdNode *pnode = head_ldm_cmd, *prv = NULL;
872 LdmCmd *pldm_cmd;
873
874 for (;pnode; pnode = pnode->Next()) {
875 pldm_cmd = pnode->GetData();
876 if (strcmp(name, pldm_cmd->name) == NULL) {
877 if (prv == NULL) {
878 LdmCmdNode::DeleteHead (&pnode);
879 UI_invalidate_cmd ((char*)name);
880 return;
881 }
882 else {
883 LdmCmdNode::DeleteNode ((LdmCmdNode**)&head_ldm_cmd, prv);
884 UI_invalidate_cmd ((char*)name);
885 return;
886 }
887 }
888 prv = pnode;
889 }
890}
891
892
893//////////////////////////////////////////////////
894
895void TM_set_type_ext (tracemod_t *pmod, Byte type)
896{
897 if (
898 (type != TM_TYPE_EXT_CPU) &&
899 (type != TM_TYPE_EXT_DEVICE) &&
900 (type != TM_TYPE_EXT_SIM)
901 ) {
902 ui->error("TM : TM_set_type_ext (unknown type = 0x%x) \n", type);
903 return;
904 }
905 pmod->type = type;
906}
907
908//////////////////////////////////////////////////
909
910void TM_cpustate_register (tracemod_t* pmod, fn_cpustat fn)
911{
912 pmod->cpustat_action = fn;
913}
914void TM_cpustate_registerB (tracemod_t* pmod, fn_cpustatB fn)
915{
916 pmod->cpustat_actionB = fn;
917}
918
919void TM_set_mode (tracemod_t *pmod, Byte mode)
920{
921 pmod->mode |= mode;
922
923 if (mode & TM_EXT_IO) {
924 return;
925 }
926}
927
928
929bool_t TM_mt_safe ()
930{
931 Ldm *pldm;
932 LdmNode *pnode;
933 for (pnode=head_ldm; pnode!=NULL; pnode=pnode->Next()) {
934
935 pldm = pnode->GetData ();
936 if (!(pldm->mode & TM_MT_SAFE)) {
937 return FALSE;
938 }
939 }
940 return TRUE;
941}
942