Updated email mdc's email address
[gpxe.git] / src / core / dev.c
blob541a9eb1bb1c870d4db3b23481ab8727d3b528e0
1 #include "etherboot.h"
2 #include "stddef.h"
3 #include "dev.h"
5 /*
6 * Each bus driver defines several methods, which are described in
7 * dev.h. This file provides a centralised, bus-independent mechanism
8 * for locating devices and drivers.
12 /* Linker symbols for the various tables */
13 static struct bus_driver bus_drivers[0]
14 __table_start ( struct bus_driver, bus_driver );
15 static struct bus_driver bus_drivers_end[0]
16 __table_end ( struct bus_driver, bus_driver );
17 static struct device_driver device_drivers[0]
18 __table_start ( struct device_driver, device_driver );
19 static struct device_driver device_drivers_end[0]
20 __table_end ( struct device_driver, device_driver );
22 /* Current attempted boot device */
23 struct dev dev = {
24 .bus_driver = bus_drivers,
25 .device_driver = device_drivers,
29 * Print all drivers
32 void print_drivers ( void ) {
33 struct device_driver *driver;
35 for ( driver = device_drivers ;
36 driver < device_drivers_end ;
37 driver++ ) {
38 printf ( "%s ", driver->name );
43 * Move to the next location on any bus
46 static inline int next_location ( struct bus_driver **bus_driver,
47 struct bus_loc *bus_loc ) {
48 /* Move to next location on this bus, if any */
49 if ( (*bus_driver)->next_location ( bus_loc ) )
50 return 1;
52 /* Move to first (zeroed) location on next bus, if any */
53 if ( ++(*bus_driver) < bus_drivers_end ) {
54 DBG ( "DEV scanning %s bus\n", (*bus_driver)->name );
55 return 1;
58 /* Reset to first bus, return "no more locations" */
59 *bus_driver = bus_drivers;
60 return 0;
64 * Find the next available device on any bus
66 * Set skip=1 to skip over the current device
69 int find_any ( struct bus_driver **bus_driver, struct bus_loc *bus_loc,
70 struct bus_dev *bus_dev, signed int skip ) {
71 DBG ( "DEV scanning %s bus\n", (*bus_driver)->name );
72 do {
73 if ( --skip >= 0 )
74 continue;
75 if ( ! (*bus_driver)->fill_device ( bus_dev, bus_loc ) )
76 continue;
77 DBG ( "DEV found device %s\n",
78 (*bus_driver)->describe_device ( bus_dev ) );
79 return 1;
80 } while ( next_location ( bus_driver, bus_loc ) );
82 DBG ( "DEV found no more devices\n" );
83 return 0;
87 * Find a driver by specified device.
89 * Set skip=1 to skip over the current driver
92 int find_by_device ( struct device_driver **device_driver,
93 struct bus_driver *bus_driver, struct bus_dev *bus_dev,
94 signed int skip ) {
95 do {
96 if ( --skip >= 0 )
97 continue;
98 if ( (*device_driver)->bus_driver != bus_driver )
99 continue;
100 if ( ! bus_driver->check_driver ( bus_dev, *device_driver ))
101 continue;
102 DBG ( "DEV found driver %s for device %s\n",
103 (*device_driver)->name,
104 bus_driver->describe_device ( bus_dev ) );
105 return 1;
106 } while ( ++(*device_driver) < device_drivers_end );
108 /* Reset to first driver, return "not found" */
109 DBG ( "DEV found no driver for device %s\n",
110 bus_driver->describe_device ( bus_dev ) );
111 *device_driver = device_drivers;
112 return 0;
116 * Find a device by specified driver.
118 * Set skip=1 to skip over the current device
121 int find_by_driver ( struct bus_loc *bus_loc, struct bus_dev *bus_dev,
122 struct device_driver *device_driver,
123 signed int skip ) {
124 struct bus_driver *bus_driver = device_driver->bus_driver;
126 do {
127 if ( --skip >= 0 )
128 continue;
129 if ( ! bus_driver->fill_device ( bus_dev, bus_loc ) )
130 continue;
131 if ( ! bus_driver->check_driver ( bus_dev, device_driver ) )
132 continue;
133 DBG ( "DEV found device %s for driver %s\n",
134 bus_driver->describe_device ( bus_dev ),
135 device_driver->name );
136 return 1;
137 } while ( bus_driver->next_location ( bus_loc ) );
139 DBG ( "DEV found no device for driver %s\n", device_driver->name );
140 return 0;
144 * Find the next available (device,driver) combination
146 * Set skip=1 to skip over the current (device,driver)
148 * Note that the struct dev may not have been previously used, and so
149 * may not contain a valid (device,driver) combination.
152 int find_any_with_driver ( struct dev *dev, signed int skip ) {
153 signed int skip_device = 0;
154 signed int skip_driver = skip;
156 while ( find_any ( &dev->bus_driver, &dev->bus_loc, &dev->bus_dev,
157 skip_device ) ) {
158 if ( find_by_device ( &dev->device_driver, dev->bus_driver,
159 &dev->bus_dev, skip_driver ) ) {
160 /* Set type_driver to be that of the device
161 * driver
163 dev->type_driver = dev->device_driver->type_driver;
164 /* Set type device instance to be the single
165 * instance provided by the type driver
167 dev->type_dev = dev->type_driver->type_dev;
168 return 1;
170 skip_driver = 0;
171 skip_device = 1;
174 return 0;