Use the magic of common symbols to allow struct dev to effectively grow at
authorMichael Brown <mcb30@etherboot.org>
Thu, 14 Apr 2005 10:10:54 +0000 (10:10 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 14 Apr 2005 10:10:54 +0000 (10:10 +0000)
link time to accommodate whatever bus objects are included.

src/core/main.c
src/drivers/bus/eisa.c
src/drivers/bus/mca.c
src/drivers/bus/pci.c
src/include/dev.h
src/include/eisa.h
src/include/mca.h
src/include/pci.h

index da1c58a..3cc777a 100644 (file)
@@ -144,7 +144,10 @@ static int initialized;
 
 
 /* Global instance of the current boot device */
-struct dev dev;
+DEV_BUS(struct {}, dev_bus);
+struct dev dev = {
+       .bus = &dev_bus,
+};
 
 /**************************************************************************
  * initialise() - perform any C-level initialisation
@@ -213,24 +216,6 @@ void exit(int status)
 }
 
 
-/*
- * Set PCI device to use.
- *
- * This routine can be called by e.g. the ROM prefix to specify that
- * the first device to be tried should be the device on which the ROM
- * was physically located.
- *
- * Note that this is deliberately in main.c rather than pci.c, because
- * this function should generalise to other bus types (e.g. ISAPnP),
- * and we don't want to end up dragging in pci.o unnecessarily.
- */
-void set_pci_device ( uint16_t busdevfn ) {
-       dev.devid.bus_type = PCI_BUS_TYPE;
-       dev.pci.busdevfn = busdevfn;
-       dev.pci.already_tried = 0;
-}
-
-
 #if 0
 
 static int main_loop(int state)
index a294895..c80974a 100644 (file)
 #define DBG(...)
 #endif
 
+/*
+ * Ensure that there is sufficient space in the shared dev_bus
+ * structure for a struct pci_device.
+ *
+ */
+DEV_BUS( struct eisa_device, eisa_dev );
+static char eisa_magic[0]; /* guaranteed unique symbol */
+
 /*
  * Fill in parameters for an EISA device based on slot number
  *
@@ -52,15 +60,14 @@ static int fill_eisa_device ( struct eisa_device *eisa ) {
  * Obtain a struct eisa * from a struct dev *
  *
  * If dev has not previously been used for an EISA device scan, blank
- * out dev.eisa
+ * out struct eisa
  */
 struct eisa_device * eisa_device ( struct dev *dev ) {
-       struct eisa_device *eisa = &dev->eisa;
+       struct eisa_device *eisa = dev->bus;;
 
-       if ( dev->devid.bus_type != EISA_BUS_TYPE ) {
+       if ( eisa->magic != eisa_magic ) {
                memset ( eisa, 0, sizeof ( *eisa ) );
-               dev->devid.bus_type = EISA_BUS_TYPE;
-               eisa->slot = EISA_MIN_SLOT;
+               eisa->magic = eisa_magic;
        }
        eisa->dev = dev;
        return eisa;
@@ -74,8 +81,13 @@ int find_eisa_device ( struct eisa_device *eisa, struct eisa_driver *driver ) {
        unsigned int i;
 
        /* Iterate through all possible EISA slots, starting where we
-        * left off/
+        * left off.  If eisa->slot is zero (which it will be if we
+        * have a zeroed structure), start from slot EISA_MIN_SLOT,
+        * since slot 0 doesn't exist.
         */
+       if ( ! eisa->slot ) {
+               eisa->slot = EISA_MIN_SLOT;
+       }
        for ( ; eisa->slot <= EISA_MAX_SLOT ; eisa->slot++ ) {
                /* If we've already used this device, skip it */
                if ( eisa->already_tried ) {
@@ -101,6 +113,8 @@ int find_eisa_device ( struct eisa_device *eisa, struct eisa_driver *driver ) {
                                                      eisa->prod_id ) );
                                if ( eisa->dev ) {
                                        eisa->dev->name = driver->name;
+                                       eisa->dev->devid.bus_type
+                                               = ISA_BUS_TYPE;
                                        eisa->dev->devid.vendor_id
                                                = eisa->mfg_id;
                                        eisa->dev->devid.device_id
index 28b99f7..1715c58 100644 (file)
 #define DBG(...)
 #endif
 
+/*
+ * Ensure that there is sufficient space in the shared dev_bus
+ * structure for a struct pci_device.
+ *
+ */
+DEV_BUS( struct mca_device, mca_dev );
+static char mca_magic[0]; /* guaranteed unique symbol */
+
 /*
  * Fill in parameters for an MCA device based on slot number
  *
@@ -53,14 +61,14 @@ static int fill_mca_device ( struct mca_device *mca ) {
  * Obtain a struct mca * from a struct dev *
  *
  * If dev has not previously been used for an MCA device scan, blank
- * out dev.mca
+ * out struct mca
  */
 struct mca_device * mca_device ( struct dev *dev ) {
-       struct mca_device *mca = &dev->mca;
+       struct mca_device *mca = dev->bus;
 
-       if ( dev->devid.bus_type != MCA_BUS_TYPE ) {
+       if ( mca->magic != mca_magic ) {
                memset ( mca, 0, sizeof ( *mca ) );
-               dev->devid.bus_type = MCA_BUS_TYPE;
+               mca->magic = mca_magic;
        }
        mca->dev = dev;
        return mca;
@@ -97,8 +105,10 @@ int find_mca_device ( struct mca_device *mca, struct mca_driver *driver ) {
                                      id->name, driver->name, id->id );
                                if ( mca->dev ) {
                                        mca->dev->name = driver->name;
-                                       mca->dev->devid.vendor_id =
-                                               GENERIC_MCA_VENDOR;
+                                       mca->dev->devid.bus_type
+                                               = MCA_BUS_TYPE;
+                                       mca->dev->devid.vendor_id
+                                               = GENERIC_MCA_VENDOR;
                                        mca->dev->devid.device_id = id->id;
                                }
                                mca->already_tried = 1;
index 4b4e9a1..d23a647 100644 (file)
@@ -9,6 +9,14 @@
 #define DBG(...)
 #endif
 
+/*
+ * Ensure that there is sufficient space in the shared dev_bus
+ * structure for a struct pci_device.
+ *
+ */
+DEV_BUS( struct pci_device, pci_dev );
+static char pci_magic[0]; /* guaranteed unique symbol */
+
 /*
  * Fill in parameters (vendor & device ids, class, membase etc.) for a
  * PCI device based on bus & devfn.
@@ -112,19 +120,33 @@ void adjust_pci_device ( struct pci_device *pci ) {
  * Obtain a struct pci * from a struct dev *
  *
  * If dev has not previously been used for a PCI device scan, blank
- * out dev.pci
+ * out struct pci
  */
 struct pci_device * pci_device ( struct dev *dev ) {
-       struct pci_device *pci = &dev->pci;
+       struct pci_device *pci = dev->bus;
 
-       if ( dev->devid.bus_type != PCI_BUS_TYPE ) {
+       if ( pci->magic != pci_magic ) {
                memset ( pci, 0, sizeof ( *pci ) );
-               dev->devid.bus_type = PCI_BUS_TYPE;
+               pci->magic = pci_magic;
        }
        pci->dev = dev;
        return pci;
 }
 
+/*
+ * Set PCI device to use.
+ *
+ * This routine can be called by e.g. the ROM prefix to specify that
+ * the first device to be tried should be the device on which the ROM
+ * was physically located.
+ *
+ */
+void set_pci_device ( uint16_t busdevfn ) {
+       pci_dev.magic = pci_magic;
+       pci_dev.busdevfn = busdevfn;
+       pci_dev.already_tried = 0;
+}
+
 /*
  * Find a PCI device matching the specified driver
  *
@@ -154,6 +176,7 @@ int find_pci_device ( struct pci_device *pci,
                /* Fill in dev structure, if present */
                if ( pci->dev ) {
                        pci->dev->name = driver->name;
+                       pci->dev->devid.bus_type = PCI_BUS_TYPE;
                        pci->dev->devid.vendor_id = pci->vendor;
                        pci->dev->devid.device_id = pci->dev_id;
                }
index a9e2916..b5a2edd 100644 (file)
@@ -3,11 +3,6 @@
 
 #include "stdint.h"
 
-/* Bus types */
-#include "pci.h"
-#include "eisa.h"
-#include "mca.h"
-
 /* Device types */
 #include "nic.h"
 
@@ -18,8 +13,7 @@ struct dev_id {
        uint8_t         bus_type;
 #define        PCI_BUS_TYPE    1
 #define        ISA_BUS_TYPE    2
-#define EISA_BUS_TYPE  3
-#define MCA_BUS_TYPE   4
+#define MCA_BUS_TYPE   3
 } __attribute__ ((packed));
 
 /* Dont use sizeof, that will include the padding */
@@ -29,18 +23,25 @@ struct dev {
        struct dev_operations *dev_op;
        const char *name;
        struct dev_id   devid;  /* device ID string (sent to DHCP server) */
-       /* All possible bus types */
-       union {
-               struct pci_device       pci;
-               struct eisa_device      eisa;
-               struct mca_device       mca;
-       };
+       /* Pointer to bus information for device.  Whatever sets up
+        * the struct dev must make sure that this points to a buffer
+        * large enough for the required struct <bus>_device.
+        */
+       void *bus;
        /* All possible device types */
        union {
                struct nic      nic;
        };
 };
 
+/*
+ * Macro to help create a common symbol with enough space for any
+ * struct <bus>_device.
+ *
+ * Use as e.g. DEV_BUS(struct pci_device);
+ */
+#define DEV_BUS(datatype,symbol) datatype symbol __asm__ ( "_dev_bus" );
+
 struct dev_operations {
        void ( *disable ) ( struct dev * );
        void ( *print_info ) ( struct dev * );
index 4fe14fc..ed0ccef 100644 (file)
@@ -27,6 +27,7 @@
  */
 struct dev;
 struct eisa_device {
+       char *magic; /* must be first */
        struct dev *dev;
        unsigned int slot;
        uint16_t ioaddr;
index e69b656..c12b1ca 100644 (file)
@@ -28,6 +28,7 @@
  */
 struct dev;
 struct mca_device {
+       char *magic; /* must be first */
        struct dev *dev;
        unsigned int slot;
        unsigned char pos[8];
index 36edc0f..988259a 100644 (file)
 #define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
 #define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit devices */
 #define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit devices */
-
 /*
  * A physical PCI device
  *
  */
 struct dev;
 struct pci_device {
+       char *                  magic; /* must be first */
        struct dev *            dev;
        uint32_t                membase;        /* BAR 1 */
        uint32_t                ioaddr;         /* first IO BAR */