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 */
24 .bus_driver
= bus_drivers
,
25 .device_driver
= device_drivers
,
32 void print_drivers ( void ) {
33 struct device_driver
*driver
;
35 for ( driver
= device_drivers
;
36 driver
< device_drivers_end
;
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
) )
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
);
58 /* Reset to first bus, return "no more locations" */
59 *bus_driver
= bus_drivers
;
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
);
75 if ( ! (*bus_driver
)->fill_device ( bus_dev
, bus_loc
) )
77 DBG ( "DEV found device %s\n",
78 (*bus_driver
)->describe_device ( bus_dev
) );
80 } while ( next_location ( bus_driver
, bus_loc
) );
82 DBG ( "DEV found no more devices\n" );
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
,
98 if ( (*device_driver
)->bus_driver
!= bus_driver
)
100 if ( ! bus_driver
->check_driver ( bus_dev
, *device_driver
))
102 DBG ( "DEV found driver %s for device %s\n",
103 (*device_driver
)->name
,
104 bus_driver
->describe_device ( bus_dev
) );
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
;
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
,
124 struct bus_driver
*bus_driver
= device_driver
->bus_driver
;
129 if ( ! bus_driver
->fill_device ( bus_dev
, bus_loc
) )
131 if ( ! bus_driver
->check_driver ( bus_dev
, device_driver
) )
133 DBG ( "DEV found device %s for driver %s\n",
134 bus_driver
->describe_device ( bus_dev
),
135 device_driver
->name
);
137 } while ( bus_driver
->next_location ( bus_loc
) );
139 DBG ( "DEV found no device for driver %s\n", device_driver
->name
);
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
,
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
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
;