Updated debug messages
[people/xl0/gpxe.git] / src / core / dev.c
index 002fa7a..e5f5640 100644 (file)
  * function (probe).
  */
 
-/* Defined by linker */
-extern struct boot_driver boot_drivers[];
-extern struct boot_driver boot_drivers_end[];
+/* Current attempted boot device */
+struct dev dev = {
+       .bus_driver = bus_drivers,
+       .device_driver = device_drivers,
+};
 
-/* Current attempted boot driver */
-static struct boot_driver *boot_driver = boot_drivers;
-
-/* Print all drivers */
+/*
+ * Print all drivers 
+ *
+ */
 void print_drivers ( void ) {
-       struct boot_driver *driver;
+       struct device_driver *driver;
 
-       for ( driver = boot_drivers ; driver < boot_drivers_end ; driver++ ) {
+       for ( driver = device_drivers ;
+             driver < device_drivers_end ;
+             driver++ ) {
                printf ( "%s ", driver->name );
        }
 }
 
-/* Get the next available boot device */
-int find_boot_device ( struct dev *dev ) {
-       for ( ; boot_driver < boot_drivers_end ; boot_driver++ ) {
-               dev->driver = boot_driver;
-               dev->name = boot_driver->name;
-               DBG ( "Probing driver %s...\n", dev->name );
-               if (  boot_driver->find_bus_boot_device ( dev,
-                                                 boot_driver->bus_driver ) ) {
-                       DBG ( "Found device %s (ID %hhx:%hx:%hx)\n",
-                             dev->name, dev->devid->bus_type,
-                             dev->devid->vendor_id, dev->devid->device_id );
-                       return 1;
-               }
-       }
+/*
+ * Move to the next location on any bus
+ *
+ */
+static inline int next_location ( struct bus_driver **bus_driver,
+                                 struct bus_loc *bus_loc ) {
+       /* Move to next location on this bus, if any */
+       if ( (*bus_driver)->next_location ( bus_loc ) )
+               return 1;
+
+       /* Move to first (zeroed) location on next bus, if any */
+       if ( ++(*bus_driver) < bus_drivers_end )
+               return 1;
+
+       /* Reset to first bus, return "no more locations" */
+       *bus_driver = bus_drivers;
+       return 0;
+}
+
+/*
+ * Find the next available device on any bus
+ *
+ * Set skip=1 to skip over the current device
+ *
+ */
+int find_any ( struct bus_driver **bus_driver, struct bus_loc *bus_loc,
+              struct bus_dev *bus_dev, signed int skip ) {
+       DBG ( "DEV searching for any device\n" );
+       do {
+               if ( --skip >= 0 )
+                       continue;
+               if ( ! (*bus_driver)->fill_device ( bus_dev, bus_loc ) )
+                       continue;
+               DBG ( "DEV found device %s\n",
+                     (*bus_driver)->describe ( bus_dev ) );
+               return 1;
+       } while ( next_location ( bus_driver, bus_loc ) );
+
+       DBG ( "DEV found no device\n" );
+       return 0;
+}
 
-       /* No more boot devices found */
-       boot_driver = boot_drivers;
+/*
+ * Find a driver by specified device.
+ *
+ * Set skip=1 to skip over the current driver
+ *
+ */
+int find_by_device ( struct device_driver **device_driver,
+                    struct bus_driver *bus_driver, struct bus_dev *bus_dev,
+                    signed int skip ) {
+       DBG ( "DEV searching for a driver for device %s\n",
+             bus_driver->describe ( bus_dev ) );
+       do {
+               if ( --skip >= 0 )
+                       continue;
+               if ( (*device_driver)->bus_driver != bus_driver )
+                       continue;
+               if ( ! bus_driver->check_driver ( bus_dev, *device_driver ))
+                       continue;
+               DBG ( "DEV found driver %s\n", (*device_driver)->name );
+               return 1;
+       } while ( ++(*device_driver) < device_drivers_end );
+       
+       /* Reset to first driver, return "not found" */
+       DBG ( "DEV found no driver for device %s\n",
+             bus_driver->describe ( bus_dev ) );
+       *device_driver = device_drivers;
        return 0;
 }
 
-/* Probe the boot device */
-int probe ( struct dev *dev ) {
-       return dev->driver->probe ( dev, dev->bus );
+/*
+ * Find a device by specified driver.
+ *
+ * Set skip=1 to skip over the current device
+ *
+ */
+int find_by_driver ( struct bus_loc *bus_loc, struct bus_dev *bus_dev,
+                    struct device_driver *device_driver,
+                    signed int skip ) {
+       struct bus_driver *bus_driver = device_driver->bus_driver;
+       
+       DBG ( "DEV searching for a device for driver %s\n",
+             device_driver->name );
+       do {
+               if ( --skip >= 0 )
+                       continue;
+               if ( ! bus_driver->fill_device ( bus_dev, bus_loc ) )
+                       continue;
+               if ( ! bus_driver->check_driver ( bus_dev, device_driver ) )
+                       continue;
+               DBG ( "DEV found device %s\n",
+                     bus_driver->describe ( bus_dev ) );
+               return 1;
+       } while ( bus_driver->next_location ( bus_loc ) );
+
+       DBG ( "DEV found no device for driver %s\n" );
+       return 0;
 }
 
-/* Disable a device */
-void disable ( struct dev *dev ) {
-       if ( dev->dev_op ) {
-               dev->dev_op->disable ( dev );
-               dev->dev_op = NULL;
+/*
+ * Find the next available (device,driver) combination
+ *
+ * Set skip=1 to skip over the current (device,driver)
+ *
+ * Note that the struct dev may not have been previously used, and so
+ * may not contain a valid (device,driver) combination.
+ *
+ */
+int find_any_with_driver ( struct dev *dev, signed int skip ) {
+       signed int skip_device = 0;
+       signed int skip_driver = skip;
+
+       while ( find_any ( &dev->bus_driver, &dev->bus_loc, &dev->bus_dev,
+                          skip_device ) ) {
+               if ( find_by_device ( &dev->device_driver, dev->bus_driver,
+                                     &dev->bus_dev, skip_driver ) ) {
+                       /* Set type_driver to be that of the device
+                        * driver
+                        */
+                       dev->type_driver = dev->device_driver->type_driver;
+                       /* Set type device instance to be the single
+                        * instance provided by the type driver
+                        */
+                       dev->type_dev = dev->type_driver->type_dev;
+                       return 1;
+               }
+               skip_driver = 0;
+               skip_device = 1;
        }
+
+       return 0;
 }