327a271434bad905b53aa6af9cf2a572e81c7272
[people/lynusvaz/gpxe.git] / src / include / dev.h
1 #ifndef DEV_H
2 #define DEV_H
3
4 #include "stdint.h"
5 #include "string.h"
6 #include "dhcp.h" /* for dhcp_dev_id */
7
8 /*
9  * Forward declarations
10  *
11  */
12 struct type_dev;
13 struct type_driver;
14 struct bus_driver;
15 struct bus_dev;
16 struct device_driver;
17
18 /*
19  * When looking at the following data structures, mentally substitute
20  * "<bus>_" in place of "bus_" and everything will become clear.
21  * "struct bus_location" becomes "struct <bus>_location", which means
22  * "the location of a device on a <bus> bus", where <bus> is a
23  * particular type of bus such as "pci" or "isapnp".
24  *
25  */
26
27 /*
28  * A physical device location on a bus.
29  *
30  */
31 #define BUS_LOC_SIZE 4
32 struct bus_loc {
33         char bytes[BUS_LOC_SIZE];
34 };
35
36 /* 
37  * A structure fully describing a physical device on a bus.
38  *
39  */
40 #define BUS_DEV_SIZE 32
41 struct bus_dev {
42         char bytes[BUS_DEV_SIZE];
43 };
44
45 /*
46  * Individual buses will have different sizes for their <bus>_location
47  * and <bus>_device structures.  We need to be able to allocate static
48  * storage that's large enough to contain these structures for any
49  * bus type that's being used in the current binary.
50  *
51  * We can't just create a union of all the various types, because some
52  * may be architecture-dependent (and some are even embedded in
53  * specific drivers, e.g. 3c509), so this would quickly get messy.
54  *
55  * We could use the magic of common symbols.  Each bus could declare a
56  * common symbol with the name "_bus_dev" of the correct size; this
57  * is easily done using code like
58  *      struct pci_device _bus_dev;
59  * The linker would then use the largest size of the "_bus_dev" symbol
60  * in any included object, thus giving us a single _bus_dev symbol of
61  * *exactly* the required size.  However, there's no way to extract
62  * the size of this symbol, either directly as a linker symbol
63  * ("_bus_dev_size = SIZEOF(_bus_dev)"; the linker language just
64  * doesn't provide this construct) or via any linker trickery I can
65  * think of (such as creating a special common symbol section just for
66  * this symbol then using SIZE(section) to read the size of the
67  * section; ld recognises only a single common symbol section called
68  * "COMMON").
69  *
70  * Since there's no way to get the size of the symbol, this
71  * effectively limits us to just one instance of the symbol.  This is
72  * all very well for the simple case of "just boot from any single
73  * device you can", but becomes limiting when you want to do things
74  * like introducing PCMCIA buses (which must instantiate other devices
75  * such as PCMCIA controllers).
76  *
77  * So, we declare the maximum sizes of these constructions to be
78  * compile-time constants.  Each individual bus driver should define
79  * its own struct <bus>_location and struct <bus>_device however it
80  * likes, and can freely cast pointers from struct bus_loc to
81  * struct <bus>_location (and similarly for bus_dev).  To guard
82  * against bounding errors, each bus driver *MUST* use the macros
83  * BUS_LOC_CHECK() and BUS_DEV_CHECK(), as in:
84  *
85  *   BUS_LOC_CHECK ( struct pci_location );
86  *   BUS_DEV_CHECK ( struct pci_device );
87  *
88  * These macros will generate a link-time error if the size of the
89  * <bus> structure exceeds the declared maximum size.
90  *
91  * The macros will generate no binary object code, but must be placed
92  * inside a function (in order to generate syntactically valid C).
93  * The easiest wy to do this is to place them in the
94  * <bus>_next_location() function.
95  *
96  * If anyone can think of a better way of doing this that avoids *ALL*
97  * of the problems described above, please implement it!
98  *
99  */
100
101 #define LINKER_ASSERT(test,error_symbol)                \
102         if ( ! (test) ) {                               \
103                 extern void error_symbol ( void );      \
104                 error_symbol();                         \
105         }
106
107 #define BUS_LOC_CHECK(datatype)                                       \
108         LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_loc) ),  \
109                        __BUS_LOC_SIZE_is_too_small__see_dev_h )
110 #define BUS_DEV_CHECK(datatype)                                       \
111         LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_dev) ),    \
112                        __BUS_DEV_SIZE_is_too_small__see_dev_h )
113
114 /*
115  * Bus-level operations.
116  *
117  * int next_location ( struct bus_loc * bus_loc )
118  *
119  *      Increment bus_loc to point to the next possible device on
120  *      the bus (e.g. the next PCI busdevfn, or the next ISAPnP CSN).
121  *      If there are no more valid locations, return 0 and leave
122  *      struct bus_loc zeroed, otherwise return true.
123  *
124  * int fill_device ( struct bus_dev *bus_dev,
125  *                   struct bus_loc *bus_loc )
126  *
127  *      Fill out a bus_dev structure with the parameters for the
128  *      device at bus_loc.  (For example, fill in the PCI vendor
129  *      and device IDs).  Return true if there is a device physically
130  *      present at this location, otherwise 0.
131  *
132  * int check_driver ( struct bus_dev *bus_dev,
133  *                    struct device_driver *device_driver )
134  *
135  *      Test whether or not the specified driver is capable of driving
136  *      the specified device by, for example, comparing the device's
137  *      PCI IDs against the list of PCI IDs claimed by the driver.
138  *
139  * char * describe ( struct bus_dev *bus_dev )
140  *
141  *      Return a text string describing the bus device bus_dev
142  *      (e.g. "PCI 00:01.2")
143  *
144  * char * name ( struct bus_dev *bus_dev )
145  *
146  *      Return a text string describing the bus device bus_dev
147  *      (e.g. "dfe538")
148  *
149  */
150 struct bus_driver {
151         int ( *next_location ) ( struct bus_loc *bus_loc );
152         int ( *fill_device ) ( struct bus_dev *bus_dev,
153                                struct bus_loc *bus_loc );
154         int ( *check_driver ) ( struct bus_dev *bus_dev,
155                                 struct device_driver *device_driver );
156         char * ( *describe ) ( struct bus_dev *bus_dev );
157         char * ( *name ) ( struct bus_dev *bus_dev );
158 };
159
160 #define __bus_driver __attribute__ (( used, __section__ ( ".drivers.bus" ) ))
161
162 /*
163  * A structure fully describing the bus-independent parts of a
164  * particular type (e.g. nic or disk) of device.
165  *
166  * Unlike struct bus_dev, e can limit ourselves to having no more than
167  * one instance of this data structure.  We therefore place an
168  * instance in each type driver file (e.g. nic.c), and simply use a
169  * pointer to the struct type_dev in the struct dev.
170  *
171  */
172 struct type_dev;
173
174 /*
175  * A type driver (e.g. nic, disk)
176  *
177  */
178 struct type_driver {
179         char *name;
180         struct type_dev *type_dev; /* single instance */
181         char * ( * describe ) ( struct type_dev *type_dev );
182 };
183
184 #define __type_driver __attribute__ (( used, __section__ ( ".drivers.type" ) ))
185
186 /*
187  * A driver for a device.
188  *
189  */
190 struct device_driver {
191         const char *name;
192         struct type_driver *type_driver;
193         struct bus_driver *bus_driver;
194         struct bus_driver_info *bus_driver_info;
195         int ( * probe ) ( struct type_dev *type_dev,
196                           struct bus_dev *bus_dev );
197         void ( * disable ) ( struct type_dev *type_dev,
198                              struct bus_dev *bus_dev );
199 };
200
201 #define __device_driver \
202         __attribute__ (( used, __section__ ( ".drivers.device" ) ))
203
204 #define DRIVER(_name,_name_string,_type_driver,_bus_driver,_bus_info,         \
205                _probe,_disable)                                               \
206         static struct device_driver _name __device_driver = {                 \
207                 .name = _name_string,                                         \
208                 .type_driver = &_type_driver,                                 \
209                 .bus_driver = &_bus_driver,                                   \
210                 .bus_driver_info = ( struct bus_driver_info * ) &_bus_info,   \
211                 .probe = ( int (*) () ) _probe,                               \
212                 .disable = ( void (*) () ) _disable,                          \
213         };
214
215 /*
216  * A bootable device, comprising a physical device on a bus, a driver
217  * for that device, and a type device
218  *
219  */
220 struct dev {
221         struct bus_driver       *bus_driver;
222         struct bus_loc          bus_loc;
223         struct bus_dev          bus_dev;
224         struct device_driver    *device_driver;
225         struct type_driver      *type_driver;
226         struct type_dev         *type_dev;
227 };
228
229 /* The current boot device */
230 extern struct dev dev;
231
232 /*
233  * Functions in dev.c 
234  *
235  */
236 extern void print_drivers ( void );
237 extern int find_any ( struct bus_driver **bus_driver, struct bus_loc *bus_loc,
238                       struct bus_dev *bus_dev, signed int skip );
239 extern int find_by_device ( struct device_driver **device_driver,
240                             struct bus_driver *bus_driver,
241                             struct bus_dev *bus_dev,
242                             signed int skip );
243 extern int find_by_driver ( struct bus_loc *bus_loc, struct bus_dev *bus_dev,
244                             struct device_driver *device_driver,
245                             signed int skip );
246 extern int find_any_with_driver ( struct dev *dev, signed int skip );
247
248 /*
249  * Functions inlined to save space
250  *
251  */
252
253 /* Probe a device */
254 static inline int probe ( struct dev *dev ) {
255         return dev->device_driver->probe ( dev->type_dev, &dev->bus_dev );
256 }
257 /* Disable a device */
258 static inline void disable ( struct dev *dev ) {
259         dev->device_driver->disable ( dev->type_dev, &dev->bus_dev );
260 }
261 /* Set the default boot device */
262 static inline void select_device ( struct dev *dev,
263                                    struct bus_driver *bus_driver,
264                                    struct bus_loc *bus_loc ) {
265         dev->bus_driver = bus_driver;
266         memcpy ( &dev->bus_loc, bus_loc, sizeof ( dev->bus_loc ) );
267 }
268
269 /* Linker symbols for the various tables */
270 extern struct bus_driver bus_drivers[];
271 extern struct bus_driver bus_drivers_end[];
272 extern struct type_driver type_drivers[];
273 extern struct type_driver type_drivers_end[];
274 extern struct device_driver device_drivers[];
275 extern struct device_driver device_drivers_end[];
276
277 #endif /* DEV_H */