Commit | Line | Data |
---|---|---|
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 | |
53 | const char * | |
54 | Module::get_help() | |
55 | { | |
56 | return MODNAME; | |
57 | } | |
58 | ||
59 | // return version string | |
60 | const char * | |
61 | Module::get_version() | |
62 | { | |
63 | return "1.00"; | |
64 | } | |
65 | ||
66 | ||
67 | // parse an arg | |
68 | bool | |
69 | Module::parse_arg(const char *) | |
70 | { | |
71 | return false; | |
72 | } | |
73 | ||
74 | // check args for sanity | |
75 | bool | |
76 | Module::check_args() | |
77 | { | |
78 | return true; | |
79 | } | |
80 | ||
81 | // called once after blaze has initialized devices and cpu data structs | |
82 | void | |
83 | Module::init_done() | |
84 | { | |
85 | } | |
86 | ||
87 | // called each time a new module instance has been created | |
88 | void | |
89 | Module::module_added(mmi_instance_t, const char*) | |
90 | { | |
91 | } | |
92 | ||
93 | // called each time a new module instance has been unloaded | |
94 | void | |
95 | Module::module_deleted(mmi_instance_t, const char*) | |
96 | { | |
97 | } | |
98 | ||
99 | // print interesting info about this module | |
100 | void | |
101 | Module::modinfo() | |
102 | { | |
103 | printf("module name <%s>, instance name <%s>\n", MODNAME, getName()); | |
104 | } | |
105 | ||
106 | // return pointer to interface | |
107 | void * | |
108 | Module::get_interface(const char*) | |
109 | { | |
110 | return NULL; | |
111 | } | |
112 | ||
113 | // dump/restore | |
114 | bool | |
115 | Module::dump(FILE *) | |
116 | { | |
117 | return true; | |
118 | } | |
119 | ||
120 | bool | |
121 | Module::restore(FILE *) | |
122 | { | |
123 | return true; | |
124 | } | |
125 | ||
126 | // stop/restart | |
127 | void | |
128 | Module::stop() | |
129 | { | |
130 | } | |
131 | ||
132 | void | |
133 | Module::restart() | |
134 | { | |
135 | } | |
136 | ||
137 | // called during sysconf | |
138 | void | |
139 | Module::get_dev_props() | |
140 | { | |
141 | } | |
142 | ||
143 | ////////////////////// | |
144 | // END STUB SECTION // | |
145 | ////////////////////// | |
146 | ||
147 | // debug printf | |
148 | void | |
149 | Module::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 | ||
159 | void | |
160 | Module::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 | ||
170 | void | |
171 | Module::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 | |
182 | const char * | |
183 | Module::_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 | |
191 | static 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 | ||
235 | static mmi_bool_t module_dump(void * mydata, const char * file_name) | |
236 | { | |
237 | return module_dump_restore((Module *)mydata, file_name, true); | |
238 | } | |
239 | ||
240 | static 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 | |
247 | extern "C" static void module_stop(void *ptr) | |
248 | { | |
249 | Module *module = (Module *) ptr; | |
250 | module->stop(); | |
251 | } | |
252 | ||
253 | extern "C" static void module_restart(void *ptr) | |
254 | { | |
255 | Module *module = (Module *) ptr; | |
256 | module->restart(); | |
257 | } | |
258 | ||
259 | // parse sysconf args | |
260 | static 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 | |
273 | extern "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 | |
289 | extern "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 | |
297 | extern "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 | |
306 | Module::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 | |
326 | Module::~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 | |
338 | extern "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 | |
349 | fprintf(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 | |
375 | extern "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 | |
383 | extern "C" void _fini() | |
384 | { | |
385 | } | |
386 | ||
387 | #endif |