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