pxe_netdev now holds a reference to the network device.
authorMichael Brown <mcb30@etherboot.org>
Mon, 2 Jul 2007 16:43:32 +0000 (17:43 +0100)
committerMichael Brown <mcb30@etherboot.org>
Mon, 2 Jul 2007 16:43:32 +0000 (17:43 +0100)
Use generic fields in struct device_description rather than assuming
that the struct device * is contained within a pci_device or
isapnp_device; this assumption is broken when using the undionly
driver.

Add PXENV_UNDI_SET_STATION_ADDRESS.

src/arch/i386/image/pxe_image.c
src/drivers/bus/isapnp.c
src/drivers/bus/pci.c
src/include/gpxe/device.h
src/include/pxe.h
src/interface/pxe/pxe.c
src/interface/pxe/pxe_undi.c

index 9cf5469..c646929 100644 (file)
@@ -40,6 +40,7 @@ struct image_type pxe_image_type __image_type ( PROBE_PXE );
  */
 static int pxe_exec ( struct image *image __unused ) {
        struct net_device *netdev;
+       int rc;
 
        /* Ensure that PXE stack is ready to use */
        pxe_init_structures();
@@ -47,11 +48,18 @@ static int pxe_exec ( struct image *image __unused ) {
 
        /* Arbitrarily pick the first open network device to use for PXE */
        for_each_netdev ( netdev ) {
-               pxe_netdev = netdev;
+               pxe_set_netdev ( netdev );
                break;
        }
 
-       return pxe_start_nbp();
+       /* Start PXE NBP */
+       rc = pxe_start_nbp();
+
+       /* Deactivate PXE */
+       pxe_set_netdev ( NULL );
+       pxe_unhook_int1a();
+
+       return rc;
 }
 
 /**
index 96bc60e..79268d4 100644 (file)
@@ -705,6 +705,8 @@ static int isapnpbus_probe ( struct root_device *rootdev ) {
                        isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP;
                        isapnp->dev.desc.vendor = isapnp->vendor_id;
                        isapnp->dev.desc.device = isapnp->prod_id;
+                       isapnp->dev.desc.ioaddr = isapnp->ioaddr;
+                       isapnp->dev.desc.irq = isapnp->irqno;
                        isapnp->dev.parent = &rootdev->dev;
                        list_add ( &isapnp->dev.siblings,
                                   &rootdev->dev.children );
index 577691f..967441a 100644 (file)
@@ -286,6 +286,9 @@ static int pcibus_probe ( struct root_device *rootdev ) {
                        pci->dev.desc.location = PCI_BUSDEVFN (bus, devfn);
                        pci->dev.desc.vendor = pci->vendor;
                        pci->dev.desc.device = pci->device;
+                       pci->dev.desc.class = pci->class;
+                       pci->dev.desc.ioaddr = pci->ioaddr;
+                       pci->dev.desc.irq = pci->irq;
                        pci->dev.parent = &rootdev->dev;
                        list_add ( &pci->dev.siblings, &rootdev->dev.children);
                        INIT_LIST_HEAD ( &pci->dev.children );
index f88a2da..caabdae 100644 (file)
@@ -27,6 +27,12 @@ struct device_description {
        unsigned int vendor;
        /** Device ID */
        unsigned int device;
+       /** Device class */
+       unsigned long class;
+       /** I/O address */
+       unsigned long ioaddr;
+       /** IRQ */
+       unsigned int irq;
 };
 
 /** PCI bus type */
index aba774e..301bb10 100644 (file)
@@ -137,4 +137,6 @@ struct pcir_header {
 
 extern struct net_device *pxe_netdev;
 
+extern void pxe_set_netdev ( struct net_device *netdev );
+
 #endif /* PXE_H */
index 8aa7df0..5e67758 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "dev.h"
+#include <gpxe/netdevice.h>
 #include "pxe.h"
 
-#warning "pxe_netdev should hold a persistent reference to the net device"
 struct net_device *pxe_netdev = NULL;
 
+/**
+ * Set network device as current PXE network device
+ *
+ * @v netdev           Network device, or NULL
+ */
+void pxe_set_netdev ( struct net_device *netdev ) {
+       if ( pxe_netdev )
+               netdev_put ( pxe_netdev );
+       pxe_netdev = NULL;
+       if ( netdev )
+               pxe_netdev = netdev_get ( netdev );
+}
+
 #if 0
 
 /* Global pointer to currently installed PXE stack */
index 4a9b339..e108764 100644 (file)
 
 #include <stdint.h>
 #include <string.h>
+#include <byteswap.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/device.h>
 #include <gpxe/pci.h>
-#include <gpxe/isapnp.h>
 #include <gpxe/if_ether.h>
 #include <gpxe/shutdown.h>
 #include "pxe.h"
@@ -200,30 +200,30 @@ pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS
 
 /* PXENV_UNDI_SET_STATION_ADDRESS
  *
- * Status: working (deliberately incomplete)
+ * Status: working
  */
 PXENV_EXIT_t 
 pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
                                 *undi_set_station_address ) {
+
        DBG ( "PXENV_UNDI_SET_STATION_ADDRESS" );
 
-#if 0
-       /* We don't offer a facility to set the MAC address; this
-        * would require adding extra code to all the Etherboot
-        * drivers, for very little benefit.  If we're setting it to
-        * the current value anyway then return success, otherwise
-        * return UNSUPPORTED.
+       /* If adapter is open, the change will have no effect; return
+        * an error
         */
-       if ( memcmp ( nic.node_addr,
-                     &undi_set_station_address->StationAddress,
-                     ETH_ALEN ) == 0 ) {
-               undi_set_station_address->Status = PXENV_STATUS_SUCCESS;
-               return PXENV_EXIT_SUCCESS;
+       if ( pxe_netdev->state & NETDEV_OPEN ) {
+               undi_set_station_address->Status =
+                       PXENV_STATUS_UNDI_INVALID_STATE;
+               return PXENV_EXIT_FAILURE;
        }
-#endif
 
-       undi_set_station_address->Status = PXENV_STATUS_UNSUPPORTED;
-       return PXENV_EXIT_FAILURE;
+       /* Update MAC address */
+       memcpy ( pxe_netdev->ll_addr,
+                &undi_set_station_address->StationAddress,
+                pxe_netdev->ll_protocol->ll_addr_len );
+
+       undi_set_station_address = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
 }
 
 /* PXENV_UNDI_SET_PACKET_FILTER
@@ -248,33 +248,11 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
                                          *undi_get_information ) {
        struct device *dev = pxe_netdev->dev;
        struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
-       unsigned int ioaddr;
-       unsigned int irqno;
 
        DBG ( "PXENV_UNDI_GET_INFORMATION" );
 
-       switch ( dev->desc.bus_type ) {
-       case BUS_TYPE_PCI: {
-               struct pci_device *pci =
-                       container_of ( dev, struct pci_device, dev );
-
-               ioaddr = pci->ioaddr;
-               irqno = pci->irq;
-               break; }
-       case BUS_TYPE_ISAPNP: {
-               struct isapnp_device *isapnp =
-                       container_of ( dev, struct isapnp_device, dev );
-
-               ioaddr = isapnp->ioaddr;
-               irqno = isapnp->irqno;
-               break; }
-       default:
-               undi_get_information->Status = PXENV_STATUS_FAILURE;
-               return PXENV_EXIT_FAILURE;
-       }
-
-       undi_get_information->BaseIo = ioaddr;
-       undi_get_information->IntNumber = irqno;
+       undi_get_information->BaseIo = dev->desc.ioaddr;
+       undi_get_information->IntNumber = dev->desc.irq;
        /* Cheat: assume all cards can cope with this */
        undi_get_information->MaxTranUnit = ETH_MAX_MTU;
        undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
@@ -384,17 +362,15 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
 
        switch ( dev->desc.bus_type ) {
        case BUS_TYPE_PCI: {
-               struct pci_device *pci =
-                       container_of ( dev, struct pci_device, dev );
                struct pci_nic_info *info = &undi_get_nic_type->info.pci;
 
                undi_get_nic_type->NicType = PCI_NIC;
-               info->Vendor_ID = pci->vendor;
-               info->Dev_ID = pci->device;
-               info->Base_Class = PCI_BASE_CLASS ( pci->class );
-               info->Sub_Class = PCI_SUB_CLASS ( pci->class );
-               info->Prog_Intf = PCI_PROG_INTF ( pci->class );
-               info->BusDevFunc = PCI_BUSDEVFN ( pci->bus, pci->devfn );
+               info->Vendor_ID = dev->desc.vendor;
+               info->Dev_ID = dev->desc.device;
+               info->Base_Class = PCI_BASE_CLASS ( dev->desc.class );
+               info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class );
+               info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class );
+               info->BusDevFunc = dev->desc.location;
                /* Cheat: remaining fields are probably unnecessary,
                 * and would require adding extra code to pci.c.
                 */
@@ -402,14 +378,12 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
                undi_get_nic_type->info.pci.SubDevice_ID = 0xffff;
                break; }
        case BUS_TYPE_ISAPNP: {
-               struct isapnp_device *isapnp =
-                       container_of ( dev, struct isapnp_device, dev );
                struct pnp_nic_info *info = &undi_get_nic_type->info.pnp;
 
                undi_get_nic_type->NicType = PnP_NIC;
-               info->EISA_Dev_ID = ( ( isapnp->vendor_id << 16 ) |
-                                     isapnp->prod_id );
-               info->CardSelNum = isapnp->csn;
+               info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) |
+                                     dev->desc.device );
+               info->CardSelNum = dev->desc.location;
                /* Cheat: remaining fields are probably unnecessary,
                 * and would require adding extra code to isapnp.c.
                 */