7 * Each bus driver defines several methods, which are described in
8 * dev.h. This file provides a centralised, bus-independent mechanism
9 * for locating devices and drivers.
13 /* Linker symbols for the various tables */
14 static struct bus_driver bus_drivers
[0]
15 __table_start ( struct bus_driver
, bus_driver
);
16 static struct bus_driver bus_drivers_end
[0]
17 __table_end ( struct bus_driver
, bus_driver
);
18 static struct device_driver device_drivers
[0]
19 __table_start ( struct device_driver
, device_driver
);
20 static struct device_driver device_drivers_end
[0]
21 __table_end ( struct device_driver
, device_driver
);
23 /* Current attempted boot device */
25 .bus_driver
= bus_drivers
,
26 .device_driver
= device_drivers
,
33 void print_drivers ( void ) {
34 struct device_driver
*driver
;
36 for ( driver
= device_drivers
;
37 driver
< device_drivers_end
;
39 printf ( "%s ", driver
->name
);
44 * Move to the next location on any bus
47 static inline int next_location ( struct bus_driver
**bus_driver
,
48 struct bus_loc
*bus_loc
) {
49 /* Move to next location on this bus, if any */
50 if ( (*bus_driver
)->next_location ( bus_loc
) )
53 /* Move to first (zeroed) location on next bus, if any */
54 if ( ++(*bus_driver
) < bus_drivers_end
) {
55 DBG ( "DEV scanning %s bus\n", (*bus_driver
)->name
);
59 /* Reset to first bus, return "no more locations" */
60 *bus_driver
= bus_drivers
;
65 * Find the next available device on any bus
67 * Set skip=1 to skip over the current device
70 int find_any ( struct bus_driver
**bus_driver
, struct bus_loc
*bus_loc
,
71 struct bus_dev
*bus_dev
, signed int skip
) {
72 DBG ( "DEV scanning %s bus\n", (*bus_driver
)->name
);
76 if ( ! (*bus_driver
)->fill_device ( bus_dev
, bus_loc
) )
78 DBG ( "DEV found device %s\n",
79 (*bus_driver
)->describe_device ( bus_dev
) );
81 } while ( next_location ( bus_driver
, bus_loc
) );
83 DBG ( "DEV found no more devices\n" );
88 * Find a driver by specified device.
90 * Set skip=1 to skip over the current driver
93 int find_by_device ( struct device_driver
**device_driver
,
94 struct bus_driver
*bus_driver
, struct bus_dev
*bus_dev
,
99 if ( (*device_driver
)->bus_driver
!= bus_driver
)
101 if ( ! bus_driver
->check_driver ( bus_dev
, *device_driver
))
103 DBG ( "DEV found driver %s for device %s\n",
104 (*device_driver
)->name
,
105 bus_driver
->describe_device ( bus_dev
) );
107 } while ( ++(*device_driver
) < device_drivers_end
);
109 /* Reset to first driver, return "not found" */
110 DBG ( "DEV found no driver for device %s\n",
111 bus_driver
->describe_device ( bus_dev
) );
112 *device_driver
= device_drivers
;
117 * Find a device by specified driver.
119 * Set skip=1 to skip over the current device
122 int find_by_driver ( struct bus_loc
*bus_loc
, struct bus_dev
*bus_dev
,
123 struct device_driver
*device_driver
,
125 struct bus_driver
*bus_driver
= device_driver
->bus_driver
;
130 if ( ! bus_driver
->fill_device ( bus_dev
, bus_loc
) )
132 if ( ! bus_driver
->check_driver ( bus_dev
, device_driver
) )
134 DBG ( "DEV found device %s for driver %s\n",
135 bus_driver
->describe_device ( bus_dev
),
136 device_driver
->name
);
138 } while ( bus_driver
->next_location ( bus_loc
) );
140 DBG ( "DEV found no device for driver %s\n", device_driver
->name
);
145 * Find the next available (device,driver) combination
147 * Set skip=1 to skip over the current (device,driver)
149 * Note that the struct dev may not have been previously used, and so
150 * may not contain a valid (device,driver) combination.
153 int find_any_with_driver ( struct dev
*dev
, signed int skip
) {
154 signed int skip_device
= 0;
155 signed int skip_driver
= skip
;
157 while ( find_any ( &dev
->bus_driver
, &dev
->bus_loc
, &dev
->bus_dev
,
159 if ( find_by_device ( &dev
->device_driver
, dev
->bus_driver
,
160 &dev
->bus_dev
, skip_driver
) ) {
161 /* Set type_driver to be that of the device
164 dev
->type_driver
= dev
->device_driver
->type_driver
;
165 /* Set type device instance to be the single
166 * instance provided by the type driver
168 dev
->type_dev
= dev
->type_driver
->type_dev
;