Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | <html> |
2 | <head> | |
3 | <title>SPARC Architectural Model: Device and Utility API</title> | |
4 | </head> | |
5 | <body bgcolor="#FFFFFF" LANG="en-US"> | |
6 | ||
7 | <h2>class Module</h2> | |
8 | <br>common/module.cc: | |
9 | <br> | |
10 | <br>#include "module.h" | |
11 | ||
12 | <font size=-1> | |
13 | <pre> | |
14 | public: | |
15 | int debug_level; | |
16 | void debug_err(const char *, ...); | |
17 | void debug_info(const char *, ...); | |
18 | void debug_more(const char *, ...); | |
19 | ||
20 | protected: | |
21 | const char *modname; | |
22 | const char *instance_name; | |
23 | module_t *module; | |
24 | module_t *instance; | |
25 | char herebuf[80]; | |
26 | ||
27 | public: | |
28 | module_t *getInstance() { return instance; }; | |
29 | const char *getName() { return instance_name; }; | |
30 | const char *_here(const char *, int); | |
31 | Module(const char *modname, const char *instance_name); | |
32 | virtual ~Module(); | |
33 | ||
34 | public: // to be supplied by the subclass | |
35 | static Module *create(const char *modname, const char *instance_name); | |
36 | static const char *get_help_string(); | |
37 | virtual const char *get_help(); | |
38 | virtual bool parse_arg(const char *); | |
39 | virtual bool check_args(); | |
40 | virtual void init_done(); | |
41 | virtual void module_added(module_t*, const char*); | |
42 | virtual void module_deleted(module_t*, const char*); | |
43 | virtual void modinfo(); | |
44 | virtual void *get_interface(const char*); | |
45 | virtual bool_t dump(FILE *fp); | |
46 | virtual bool_t restore(FILE *fp); | |
47 | virtual void stop(); | |
48 | virtual void restart(); | |
49 | </pre> | |
50 | </font> | |
51 | ||
52 | <h4>Description</h4> | |
53 | This is the base class for all modules. It provides the main entry point | |
54 | (_init), and manages several mmi callbacks. | |
55 | <p> | |
56 | A subclass must define Module::create() and Module::get_help_string(). | |
57 | These are not defined in module.cc. | |
58 | Module::create() is a factory function which creates the new subclass. | |
59 | Module::get_help_string() simply provides a pointer to a one-line help string for the module. | |
60 | <p> | |
61 | There are stubs for each of the virtual functions defined in module.cc. | |
62 | Subclasses generally provide definitions for each of the virtual functions. | |
63 | <p> | |
64 | A subclass may also reference an interface class. | |
65 | This is called multiple inheritance, with Module and interface classes as base classes for each module. | |
66 | <p> | |
67 | Thus, a subclass operates by providing definitions for virtual functions in | |
68 | interface classes, and by providing definitions for the virtual functions in | |
69 | Module. | |
70 | <p> | |
71 | The sequence of calls to module functions is carefully arranged. | |
72 | It is important to keep this in mind when designing the subclass. | |
73 | <p> | |
74 | Functions are called in this order: | |
75 | <p><b>Module::get_help_string()</b> registers a string with mmi when it creates the instance. | |
76 | <p><b>Module::create()</b> is the factory function that must create a new subclass of Module. | |
77 | This calls the constructors for Module, any intermediate classes (for example, | |
78 | PciDev), and the subclass. It is important to do as little as possible in the | |
79 | constructors. Simply set class attributes to initial values. | |
80 | Initial values are usually "0" for integer types, and "NULL" for pointer types. | |
81 | It is best practice to *always* initialize data members to something. | |
82 | It is OK to set default values for module arguments here, so long as they are | |
83 | strings or integers. | |
84 | But note that string arguments should be intialized with <tt>strdup("foo")</tt>, not <tt>"foo"</tt>. | |
85 | <p><b>parse_arg()</b> will be called for each argument on the sysconf command line. | |
86 | Module.cc parses any -d# argument (set debug level). | |
87 | Any other arguments are defined by the subclass. | |
88 | There are utilities in <b>common/arg.cc</b> that help with argument parsing. | |
89 | (Special note about <i>argval()</i>: | |
90 | make sure any string pointers are initialized to NULL or a heap item. | |
91 | It will <i>free()</i> the previous string before returning the new string pointer. | |
92 | It is best practice to initialize *every* member data item in the constructor.) | |
93 | <p><b>check_args()</b> is an important step. | |
94 | If any required arguments are missing, or have improper values, the function may return "false", | |
95 | which will cause the module to immediately unload. | |
96 | Note: this is not the time to look for interfaces to other modules, because other modules may not be loaded at this point. | |
97 | Only the names of other modules are noted at this point. | |
98 | <p><b>module_added()</b> is called for each module already loaded. | |
99 | This is also called if a module is loaded later on. | |
100 | This is the place to expect to find the interfaces to another module. | |
101 | <p><b>init_done()</b> is called after Blaze has initialized CPU and device objects (<i>init_devices()</i>). | |
102 | If the module is loaded after this time, init_done() is called immediately. | |
103 | Note that "init done" does not mean "config done". | |
104 | It is possible to load modules at any time. | |
105 | Use the module_added hook to connect to new modules. | |
106 | <p>The remaining functions may be called in any order, or not at all. | |
107 | In particular: | |
108 | <p><b>module_deleted()</b> is called whenever a module is unloaded. | |
109 | This is when the subclass will delete any interface pointers it may have to the module. | |
110 | Also, note that module_added may be called later on, and the subclass can then reconnect. | |
111 | If the instance itself is being unloaded, module.cc will delete the subclass instead, | |
112 | and the destructor for the subclass will be called instead. | |
113 | <p><b>get_interface()</b> is called by other modules whenever it wants an interface pointer to the subclass. | |
114 | The definition of an interface is very open ended. | |
115 | It can be an interface class, a scalar value, or a pointer to a structure. | |
116 | For interface classes, it is necessary to use casts, due to the rules of multiple inheritance. | |
117 | For example, | |
118 | <br> <font size=-1><tt>return (PciDevIf*)this</tt></font> | |
119 | <br>returns the proper interface pointer for the interface class PciDevIf. | |
120 | <p><b>modinfo</b> prints information about the subclass. It does not return a value. | |
121 | It is called by the <b>modinfo</b> UI command. | |
122 | <p><b>dump/restore</b> support the Blaze DR facility. These are optional. | |
123 | Module.cc will create the dump file whether or not it has any contents. | |
124 | <p><b>stop/restart</b> support the <b>stop</b> UI command. These are optional, and rarely needed. | |
125 | <p><b>debug_level</b> is set by the sysconf command line arg <i>-d#</i>. There are three levels defined: | |
126 | <br> -d0: <i>debug_err</i>, are error messages that always print. | |
127 | <br> -d1: <i>debug_info</i>, is for I/O traces. | |
128 | <br> -d2: <i>debug_more</i>, says to print errors, info, and more details. | |
129 | <p><b>_here()</b> is the function called by the macro <i>HERE</i>, defined as: | |
130 | <br> <font size=-1><tt>#define HERE _here(__FILE__, __LINE__)</tt></font> | |
131 | <br>This macro helps to locate every message in the source code | |
132 | by composing a common prefix for debug messages: | |
133 | <br> <font size=-1><i>instance_name</i>:<i>__FILE__</i>(L<i>__LINE__</i>)</font> | |
134 | <br>For example, | |
135 | <br> <font size=-1><tt>debug_more("%s: Mips %6.2f\n", HERE, ticks / elapsed / 1e6);</tt></font> | |
136 | <br> <font size=-1><tt>sample25A:sample_mod.cc(L194): Mips 2.11</tt></font> | |
137 | <br>Note that a static function can also use the macro: | |
138 | <font size=-1><tt>sample->HERE</tt></font> is legal. | |
139 | <h4>Makefile</h4> | |
140 | module.cc is common code. | |
141 | This means that it is compiled into each module, and preprocesser macros are expanded uniquely. | |
142 | Here is the Makefile from the example PCI device <b>sample</b>: | |
143 | <font size=-1> | |
144 | <pre> | |
145 | # Makefile for sample PCI device loadable module | |
146 | # Copyright 2004 Sun Microsystems Inc | |
147 | # All rights reserved | |
148 | # | |
149 | # @(#)Makefile 1.4 04/08/05 | |
150 | # | |
151 | ||
152 | MOD = sample | |
153 | CCFILES = \ | |
154 | pci_dev.cc \ | |
155 | sample_mod.cc \ | |
156 | module.cc \ | |
157 | arg.cc | |
158 | ||
159 | CPPFLAGS += -DMODNAME=\"$(MOD)\" | |
160 | ||
161 | # make link names unique for common classes | |
162 | CPPFLAGS += -DModule=$(MOD)Module | |
163 | CPPFLAGS += -DPciDev=$(MOD)PciDev | |
164 | ||
165 | include ../Makefile.modules | |
166 | ||
167 | </pre> | |
168 | </font> | |
169 | ||
170 | modules/Makefile always includes header files from common/include, | |
171 | and allows inclusion of code from common. | |
172 | pci_dev.cc, module.cc, and arg.cc are in common. | |
173 | Makefile and sample_mod.cc are in sample. | |
174 | <p> | |
175 | Note that <i>-DModule</i> and <i>-DPciDev</i> actually rename <i>class Module</i> and <i>class PciDev</i>. | |
176 | This is not strictly necessary, so as long as modules are loaded with <i>dlopen(..., RTLD_LOCAL)</i>. | |
177 | Using <i>RTLD_LOCAL</i> ensures that the symbols from a module are not merged with the global symbol table. | |
178 | However, <i>RTLD_GLOBAL</i> would certainly cause an ambiguity if two or more modules publish the same names. | |
179 | The best reason to create unique global names is to help with debugging. | |
180 | This way it is easier to distinguish 'sampleModule' from 'fooModule' in the blaze binary at runtime. | |
181 | <p> | |
182 | <b>arg.cc</b> could be a library (compiled once), but there is no provision for this. | |
183 | </body> | |
184 | </html> |