Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / module.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: module.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 2004 by Sun Microsystems, Inc.
23 * All rights reserved.
24 *
25 * W% 06/01/25
26 */
27#include <stdio.h>
28#include <stdarg.h>
29#include <stdlib.h>
30#include <string.h>
31#include <limits.h>
32#include <sys/types.h>
33#include "types.h"
34#include "dr.h"
35#include "mmi.h"
36#include "module.h"
37#include "arg.h"
38#include <dlfcn.h>
39#include <link.h>
40
41
42#define NON_V4_MOD_NUM 6
43#define V4_DISTINCT 3
44
45//extern devRegistry * samDevs;
46
47//////////////////////////////////////////////////
48// VIRTUAL FUNCTION STUBS //
49// these should be implemented in each subclass //
50//////////////////////////////////////////////////
51
52// return help string
53const char *
54Module::get_help()
55{
56 return MODNAME;
57}
58
59// return version string
60const char *
61Module::get_version()
62{
63 return "1.00";
64}
65
66
67// parse an arg
68bool
69Module::parse_arg(const char *)
70{
71 return false;
72}
73
74// check args for sanity
75bool
76Module::check_args()
77{
78 return true;
79}
80
81// called once after blaze has initialized devices and cpu data structs
82void
83Module::init_done()
84{
85}
86
87// called each time a new module instance has been created
88void
89Module::module_added(mmi_instance_t, const char*)
90{
91}
92
93// called each time a new module instance has been unloaded
94void
95Module::module_deleted(mmi_instance_t, const char*)
96{
97}
98
99// print interesting info about this module
100void
101Module::modinfo()
102{
103 printf("module name <%s>, instance name <%s>\n", MODNAME, getName());
104}
105
106// return pointer to interface
107void *
108Module::get_interface(const char*)
109{
110 return NULL;
111}
112
113// dump/restore
114bool
115Module::dump(FILE *)
116{
117 return true;
118}
119
120bool
121Module::restore(FILE *)
122{
123 return true;
124}
125
126// stop/restart
127void
128Module::stop()
129{
130}
131
132void
133Module::restart()
134{
135}
136
137// called during sysconf
138void
139Module::get_dev_props()
140{
141}
142
143//////////////////////
144// END STUB SECTION //
145//////////////////////
146
147// debug printf
148void
149Module::debug_err(const char *fmt, ...)
150{
151 if (debug_level >= 0) {
152 va_list ap;
153 va_start(ap, fmt);
154 vfprintf(stderr, fmt, ap);
155 va_end(ap);
156 }
157}
158
159void
160Module::debug_info(const char *fmt, ...)
161{
162 if (debug_level >= 1) {
163 va_list ap;
164 va_start(ap, fmt);
165 vfprintf(stderr, fmt, ap);
166 va_end(ap);
167 }
168}
169
170void
171Module::debug_more(const char *fmt, ...)
172{
173 if (debug_level >= 2) {
174 va_list ap;
175 va_start(ap, fmt);
176 vfprintf(stderr, fmt, ap);
177 va_end(ap);
178 }
179}
180
181// generate "module:file(Lnn)" for debug output
182const char *
183Module::_here(const char *f, int n)
184{
185 const char *p = strrchr(f, '/');
186 snprintf(herebuf, sizeof herebuf, "%s:%s(L%d)", getName(), p?(p+1):f, n);
187 return herebuf;
188}
189
190// dump/restore
191static mmi_bool_t module_dump_restore(Module * module, const char * file_name, bool isDump)
192{
193 FILE *fp;
194 bool rc = false;
195 char *non_v4_mod[NON_V4_MOD_NUM] = {"excalibur", "pci_bus", "bi", "rtc", "scsi", "fc"};
196 char fn[PATH_MAX], *ptr, *v4_distinct_name[V4_DISTINCT] = {"schizo", "serial", "ll"};
197
198 fn[0] = '\0';
199
200// comment out when testing hh/parrot v5 modules with v4 blaze
201 if (restore_pure_v4_dump() && !isDump) {
202 for (int i = 0; i < NON_V4_MOD_NUM; i ++)
203 if (!strcmp(module->get_mod_name(), non_v4_mod[i]))
204 return mmi_true;
205 for (int i = 0; i < V4_DISTINCT; i ++)
206 if (!strcmp(module->get_mod_name(), v4_distinct_name[i])) {
207 strcpy(fn, file_name);
208 ptr = (char *)strrchr(fn, '/') + 1;
209 *ptr = '\0';
210 strcat((char *)fn, v4_distinct_name[i]);
211 strcat((char *)fn, ".dmp");
212 fp = fopen(fn, "r");
213 break;
214 }
215 }
216
217 if (!fn[0])
218 fp = fopen (file_name, isDump ? "w" : "r");
219
220 if (fp) {
221 rc = isDump ? module->dump(fp) : module->restore(fp);
222 fclose (fp);
223 }
224
225 if (!rc) {
226 if (fn[0])
227 perror(fn);
228 else
229 perror(file_name);
230 }
231
232 return (mmi_bool_t)rc;
233}
234
235static mmi_bool_t module_dump(void * mydata, const char * file_name)
236{
237 return module_dump_restore((Module *)mydata, file_name, true);
238}
239
240static mmi_bool_t module_restore(void * mydata, const char * file_name)
241{
242 return module_dump_restore((Module *)mydata, file_name, false);
243}
244
245
246// stop/restart
247extern "C" static void module_stop(void *ptr)
248{
249 Module *module = (Module *) ptr;
250 module->stop();
251}
252
253extern "C" static void module_restart(void *ptr)
254{
255 Module *module = (Module *) ptr;
256 module->restart();
257}
258
259// parse sysconf args
260static void module_parse_args(Module *module, mmi_instance_t instance, bool allargs)
261{
262 int argc = mmi_argc(instance);
263 for (int i = 0; i < argc; i++) {
264 char *arg = mmi_argv(instance, i);
265 if (!strncmp("-d", arg, 2)) { // debug_level: -d#
266 module->debug_level = (int) strtol(&arg[2], NULL, 0);
267 } else if (allargs && !module->parse_arg(arg))
268 module->debug_err("%s: WARNING: Ignoring arg '%s'\n", module->HERE, arg);
269 }
270}
271
272// config callback
273extern "C" static void module_reconfig(void *cb_data, mmi_instance_t target, const char *target_name, mmi_config_t ev)
274{
275 Module *module = (Module*)cb_data;
276
277 if (target == module->getInstance()) {
278 if (ev == MMI_CONFIG_DELETE_MODULE)
279 delete module;
280 else if (ev == MMI_CONFIG_INIT_DONE)
281 module->init_done();
282 } else if (ev == MMI_CONFIG_NEW_MODULE) {
283 module->module_added(target, target_name);
284 } else if (ev == MMI_CONFIG_DELETE_MODULE) {
285 module->module_deleted(target, target_name);
286 }
287}
288// callback to retrieve module information
289extern "C" static void module_get_modinfo (mmi_instance_t instance)
290{
291 Module *module = (Module *) instance;
292 module->modinfo();
293}
294
295
296// interface callback
297extern "C" static void *module_get_interface(void *cb_data, const char *name)
298{
299 Module *module = (Module *)cb_data;
300 if (!strcmp(name, MODULE_INTERFACE))
301 return module;
302 return module->get_interface(name);
303}
304
305// constructor
306Module::Module(const char *_modname, const char *_instance_name)
307 : debug_level(0)
308{
309 instance_name = makestr(_instance_name, instance_name);
310 modname = makestr(_modname, modname);
311 instance = mmi_get_instance(instance_name);
312 memset(herebuf, 0, sizeof herebuf);
313 module_parse_args(this, instance, false);
314 debug_more("%s: constructor\n", HERE);
315 mmi_register_start_stop (module_restart, module_stop, (void*)this);
316 mmi_register_dump_restore(getName(), module_dump, module_restore, (void*)this);
317 plist = new property_list();
318 if(mySamDevPtr = (devRegistry**)dlsym(RTLD_DEFAULT,"samDevs")){
319 samId = (*mySamDevPtr)->registerDev(this);
320 }else{
321 samId = -1;
322 }
323}
324
325// destructor
326Module::~Module()
327{
328 debug_more("%s: destructor\n", getName());
329 if (instance_name) {
330 free((void*)instance_name);
331 }
332 if (modname) {
333 free((void*)modname);
334 }
335}
336
337// called during ldm and sysconf, after _init
338extern "C" static void module_create_instance(const char *modname, const char *instance_name)
339{
340 Module *module = Module::create(modname, instance_name);
341 if (!module) {
342 fprintf(stderr, "%s: Could not create <%s>\n", MODNAME, instance_name);
343 } else {
344 mmi_instance_t instance = mmi_register_instance(modname, instance_name, (void*)module, Module::get_help_string());
345 if (!instance) {
346 fprintf(stderr, "%s: Could not register <%s>\n", MODNAME,instance_name);
347 } else {
348#if 0
349fprintf(stderr, "mmi_register_instance %s 0x%llx, data 0x%llx \n", instance_name, instance, (void*)module);
350#endif
351 module_parse_args(module, instance, true);
352 module->debug_more("%s: modname <%s> instance_name <%s>\n", MODNAME, modname, instance_name);
353 module->debug_info("%s: Version <%s>\n",MODNAME,module->get_version());
354 if (!module->check_args()) {
355 fprintf (stderr, "%s: Could not create object for <%s>\n", MODNAME,instance_name);
356
357 } else {
358 mmi_register_modinfo_cb(instance, module_get_modinfo);
359 mmi_register_interface_cb(instance, module_get_interface);
360 mmi_register_config_cb(instance, module_reconfig);
361 }
362 }
363 }
364}
365
366// The _init() and _fini() routines are only needed when we compile
367// a module into a .so. In case a module is linked statically to
368// another module (.so) we get multiple defined _init() and _inif()
369// routines. Currently modules for cosim are all linked statically.
370// MODULE_STATIC_LINKAGE excludes _init() and _fini() when defined.
371
372#ifndef MODULE_STATIC_LINKAGE
373
374// module init, called during dlopen
375extern "C" void _init()
376{
377 if (! mmi_register_instance_creator (MODNAME, module_create_instance )) {
378 fprintf (stderr, "%s: Failed to load\n", MODNAME);
379 }
380}
381
382// called by dlclose during uldm and exit
383extern "C" void _fini()
384{
385}
386
387#endif