Merge branch 'master' of ssh://rom.etherboot.org/pub/scm/gpxe
authorMarty Connor <mdc@etherboot.org>
Mon, 2 Jul 2007 19:36:19 +0000 (15:36 -0400)
committerMarty Connor <mdc@etherboot.org>
Mon, 2 Jul 2007 19:36:19 +0000 (15:36 -0400)
19 files changed:
src/arch/i386/core/basemem_packet.c [moved from src/arch/i386/core/dhcp_basemem.c with 76% similarity]
src/arch/i386/drivers/net/undinet.c
src/arch/i386/image/nbi.c
src/arch/i386/image/pxe_image.c
src/arch/i386/include/basemem_packet.h [new file with mode: 0644]
src/arch/i386/include/dhcp_basemem.h [deleted file]
src/drivers/bus/isapnp.c
src/drivers/bus/pci.c
src/include/gpxe/arp.h
src/include/gpxe/device.h
src/include/gpxe/netdevice.h
src/include/gpxe/rarp.h [new file with mode: 0644]
src/include/pxe.h
src/interface/pxe/pxe.c
src/interface/pxe/pxe_preboot.c
src/interface/pxe/pxe_undi.c
src/net/arp.c
src/net/ethernet.c
src/net/rarp.c [new file with mode: 0644]

similarity index 76%
rename from src/arch/i386/core/dhcp_basemem.c
rename to src/arch/i386/core/basemem_packet.c
index de40c30..eedfaba 100644 (file)
 /**
  * @file
  *
- * DHCP parameter block provided to external programs in base memory
+ * Packet buffer in base memory.  Used by various components which
+ * need to pass packets to and from external real-mode code.
  *
  */
 
-#include <dhcp_basemem.h>
+#include <basemem_packet.h>
 
-#undef dhcp_basemem
-char __data16_array ( dhcp_basemem, [DHCP_BASEMEM_LEN] );
+#undef basemem_packet
+char __data16_array ( basemem_packet, [BASEMEM_PACKET_LEN] );
index 865c6e8..6bc0fc3 100644 (file)
@@ -22,6 +22,7 @@
 #include <pic8259.h>
 #include <biosint.h>
 #include <pnpbios.h>
+#include <basemem_packet.h>
 #include <gpxe/iobuf.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/if_ether.h>
@@ -314,13 +315,6 @@ static int undinet_isr_triggered ( void ) {
  *****************************************************************************
  */
 
-/** Maximum length of a packet transmitted via the UNDI API */
-#define UNDI_IOB_LEN 1514
-
-/** UNDI I/O buffer */
-static char __data16_array ( undinet_iob, [UNDI_IOB_LEN] );
-#define undinet_iob __use_data16 ( undinet_iob )
-
 /** UNDI transmit buffer descriptor */
 static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd );
 #define undinet_tbd __use_data16 ( undinet_tbd )
@@ -340,9 +334,9 @@ static int undinet_transmit ( struct net_device *netdev,
        int rc;
 
        /* Copy packet to UNDI I/O buffer */
-       if ( len > sizeof ( undinet_iob ) )
-               len = sizeof ( undinet_iob );
-       memcpy ( &undinet_iob, iobuf->data, len );
+       if ( len > sizeof ( basemem_packet ) )
+               len = sizeof ( basemem_packet );
+       memcpy ( &basemem_packet, iobuf->data, len );
 
        /* Create PXENV_UNDI_TRANSMIT data structure */
        memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
@@ -357,7 +351,7 @@ static int undinet_transmit ( struct net_device *netdev,
        undinet_tbd.ImmedLength = len;
        undinet_tbd.Xmit.segment = rm_ds;
        undinet_tbd.Xmit.offset 
-               = ( ( unsigned ) & __from_data16 ( undinet_iob ) );
+               = ( ( unsigned ) & __from_data16 ( basemem_packet ) );
 
        /* Issue PXE API call */
        if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT,
index fe0757c..6084b21 100644 (file)
@@ -3,7 +3,7 @@
 #include <realmode.h>
 #include <gateA20.h>
 #include <memsizes.h>
-#include <dhcp_basemem.h>
+#include <basemem_packet.h>
 #include <gpxe/uaccess.h>
 #include <gpxe/segment.h>
 #include <gpxe/shutdown.h>
@@ -321,7 +321,7 @@ static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
                  "=b" ( discard_b )
                : "D" ( imgheader->execaddr.segoff ),
                  "S" ( imgheader->location ),
-                 "b" ( __from_data16 ( dhcp_basemem ) )
+                 "b" ( __from_data16 ( basemem_packet ) )
                : "ecx", "edx", "ebp" );
 
        gateA20_set();
@@ -356,7 +356,7 @@ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
                : "D" ( imgheader->execaddr.linear ),
                  "S" ( ( imgheader->location.segment << 4 ) +
                        imgheader->location.offset ),
-                 "b" ( virt_to_phys ( dhcp_basemem ) ),
+                 "b" ( virt_to_phys ( basemem_packet ) ),
                  "a" ( virt_to_phys ( &loaderinfo ) )
                : "ecx", "edx", "ebp", "memory" );
 
@@ -397,8 +397,8 @@ static int nbi_prepare_dhcp ( struct image *image ) {
                return -ENODEV;
        }
 
-       if ( ( rc = create_dhcp_packet ( boot_netdev, DHCPACK,
-                                        dhcp_basemem, sizeof ( dhcp_basemem ),
+       if ( ( rc = create_dhcp_packet ( boot_netdev, DHCPACK, basemem_packet,
+                                        sizeof ( basemem_packet ),
                                         &dhcppkt ) ) != 0 ) {
                DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
                return rc;
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;
 }
 
 /**
diff --git a/src/arch/i386/include/basemem_packet.h b/src/arch/i386/include/basemem_packet.h
new file mode 100644 (file)
index 0000000..2f7212d
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef BASEMEM_PACKET_H
+#define BASEMEM_PACKET_H
+
+#include <realmode.h>
+
+/** Maximum length of base memory packet buffer */
+#define BASEMEM_PACKET_LEN 1514
+
+/** Base memory packet buffer */
+extern char __data16_array ( basemem_packet, [BASEMEM_PACKET_LEN] );
+#define basemem_packet __use_data16 ( basemem_packet )
+
+#endif /* BASEMEM_PACKET_H */
diff --git a/src/arch/i386/include/dhcp_basemem.h b/src/arch/i386/include/dhcp_basemem.h
deleted file mode 100644 (file)
index 82d5ccb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef DHCP_BASEMEM_H
-#define DHCP_BASEMEM_H
-
-#include <realmode.h>
-
-/** Maximum length of a DHCP data buffer */
-#define DHCP_BASEMEM_LEN 1514
-
-/** DHCP data buffer */
-extern char __data16_array ( dhcp_basemem, [DHCP_BASEMEM_LEN] );
-#define dhcp_basemem __use_data16 ( dhcp_basemem )
-
-#endif /* DHCP_BASEMEM_H */
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 1c702b0..6464ce0 100644 (file)
@@ -30,6 +30,8 @@ struct arp_net_protocol {
 #define __arp_net_protocol \
        __table ( struct arp_net_protocol, arp_net_protocols, 01 )
 
+extern struct net_protocol arp_protocol;
+
 extern int arp_resolve ( struct net_device *netdev,
                         struct net_protocol *net_protocol,
                         const void *dest_net_addr,
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 9800ef5..0060e7d 100644 (file)
@@ -122,6 +122,8 @@ struct ll_protocol {
        uint16_t ll_proto;
        /** Link-layer address length */
        uint8_t ll_addr_len;
+       /** Link-layer header length */
+       uint8_t ll_header_len;
        /** Link-layer broadcast address */
        const uint8_t *ll_broadcast;
 };
diff --git a/src/include/gpxe/rarp.h b/src/include/gpxe/rarp.h
new file mode 100644 (file)
index 0000000..81e03bd
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _GPXE_RARP_H
+#define _GPXE_RARP_H
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+struct net_protocol;
+
+extern struct net_protocol rarp_protocol;
+
+#endif /* _GPXE_RARP_H */
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 3cbbf22..15752b2 100644 (file)
@@ -28,7 +28,7 @@
 #include <stdlib.h>
 #include <gpxe/uaccess.h>
 #include <gpxe/dhcp.h>
-#include <dhcp_basemem.h>
+#include <basemem_packet.h>
 #include "pxe.h"
 #include "pxe_call.h"
 
@@ -99,10 +99,10 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO
         */
        len = get_cached_info->BufferSize;
        if ( len == 0 ) {
-               len = sizeof ( dhcp_basemem );
+               len = sizeof ( basemem_packet );
                get_cached_info->Buffer.segment = rm_ds;
                get_cached_info->Buffer.offset =
-                       ( unsigned int ) ( & __from_data16 ( dhcp_basemem ) );
+                       ( unsigned int ) ( & __from_data16 ( basemem_packet ) );
                get_cached_info->BufferLimit = len;
        }
 
index 4a9b339..9488d9f 100644 (file)
  */
 
 #include <stdint.h>
+#include <stdio.h>
 #include <string.h>
+#include <byteswap.h>
+#include <basemem_packet.h>
 #include <gpxe/netdevice.h>
+#include <gpxe/iobuf.h>
 #include <gpxe/device.h>
 #include <gpxe/pci.h>
-#include <gpxe/isapnp.h>
 #include <gpxe/if_ether.h>
+#include <gpxe/ip.h>
+#include <gpxe/arp.h>
+#include <gpxe/rarp.h>
 #include <gpxe/shutdown.h>
 #include "pxe.h"
 
@@ -128,61 +134,76 @@ PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
  */
 PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
                                   *undi_transmit ) {
-       struct s_PXENV_UNDI_TBD *tbd;
-       const char *dest;
-       unsigned int type;
-       unsigned int length;
-       const char *data;
+       struct s_PXENV_UNDI_TBD tbd;
+       struct DataBlk *datablk;
+       struct io_buffer *iobuf;
+       struct net_protocol *net_protocol;
+       char destaddr[MAX_LL_ADDR_LEN];
+       const void *ll_dest;
+       size_t len;
+       unsigned int i;
+       int rc;
 
        DBG ( "PXENV_UNDI_TRANSMIT" );
 
-#if 0
-       /* We support only the "immediate" portion of the TBD.  Who
-        * knows what Intel's "engineers" were smoking when they came
-        * up with the array of transmit data blocks...
-        */
-       tbd = SEGOFF16_TO_PTR ( undi_transmit->TBD );
-       if ( tbd->DataBlkCount > 0 ) {
+       /* Identify network-layer protocol */
+       switch ( undi_transmit->Protocol ) {
+       case P_IP:      net_protocol = &ipv4_protocol;  break;
+       case P_ARP:     net_protocol = &arp_protocol;   break;
+       case P_RARP:    net_protocol = &rarp_protocol;  break;
+       case P_UNKNOWN: net_protocol = NULL;            break;
+       default:
                undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
                return PXENV_EXIT_FAILURE;
        }
-       data = SEGOFF16_TO_PTR ( tbd->Xmit );
-       length = tbd->ImmedLength;
 
-       /* If destination is broadcast, we need to supply the MAC address */
-       if ( undi_transmit->XmitFlag == XMT_BROADCAST ) {
-               dest = broadcast_mac;
-       } else {
-               dest = SEGOFF16_TO_PTR ( undi_transmit->DestAddr );
+       /* Calculate total packet length */
+       copy_from_real ( &tbd, undi_transmit->TBD.segment,
+                        undi_transmit->TBD.offset, sizeof ( tbd ) );
+       len = tbd.ImmedLength;
+       for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
+               datablk = &tbd.DataBlock[i];
+               len += datablk->TDDataLen;
        }
 
-       /* We can't properly support P_UNKNOWN without rewriting all
-        * the driver transmit() methods, so we cheat: if P_UNKNOWN is
-        * specified we rip the destination address and type out of
-        * the pre-assembled packet, then skip over the header.
-        */
-       switch ( undi_transmit->Protocol ) {
-       case P_IP:      type = ETH_P_IP;        break;
-       case P_ARP:     type = ETH_P_ARP;       break;
-       case P_RARP:    type = ETH_P_RARP;      break;
-       case P_UNKNOWN:
-               media_header = (media_header_t*)data;
-               dest = media_header->dest;
-               type = ntohs ( media_header->nstype );
-               data += ETH_HLEN;
-               length -= ETH_HLEN;
-               break;
-       default:
-               undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
+       /* Allocate and fill I/O buffer */
+       iobuf = alloc_iob ( len );
+       if ( ! iobuf ) {
+               undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
                return PXENV_EXIT_FAILURE;
        }
+       copy_from_real ( iob_put ( iobuf, tbd.ImmedLength ), tbd.Xmit.segment,
+                        tbd.Xmit.offset, tbd.ImmedLength );
+       for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
+               datablk = &tbd.DataBlock[i];
+               copy_from_real ( iob_put ( iobuf, datablk->TDDataLen ),
+                                datablk->TDDataPtr.segment,
+                                datablk->TDDataPtr.offset,
+                                datablk->TDDataLen );
+       }
 
-       /* Send the packet */
-       eth_transmit ( dest, type, length, data );
-#endif
-       
-       undi_transmit->Status = PXENV_STATUS_SUCCESS;
-       return PXENV_EXIT_SUCCESS;
+       /* Transmit packet */
+       if ( net_protocol == NULL ) {
+               /* Link-layer header already present */
+               rc = netdev_tx ( pxe_netdev, iobuf );
+       } else {
+               /* Calculate destination address */
+               if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
+                       copy_from_real ( destaddr,
+                                        undi_transmit->DestAddr.segment,
+                                        undi_transmit->DestAddr.offset,
+                                        pxe_netdev->ll_protocol->ll_addr_len );
+                       ll_dest = destaddr;
+               } else {
+                       ll_dest = pxe_netdev->ll_protocol->ll_broadcast;
+               }
+               rc = net_tx ( iobuf, pxe_netdev, net_protocol, ll_dest );
+       }
+
+#warning "TX completion?"
+
+       undi_transmit->Status = PXENV_STATUS ( rc );
+       return ( ( rc == 0 ) ? PXENV_EXIT_SUCCESS : PXENV_EXIT_FAILURE );
 }
 
 /* PXENV_UNDI_SET_MCAST_ADDRESS
@@ -200,30 +221,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 +269,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 +383,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 +399,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.
                 */
@@ -431,16 +426,15 @@ PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO
                                         *undi_get_iface_info ) {
        DBG ( "PXENV_UNDI_GET_IFACE_INFO" );
 
-#if 0
        /* Just hand back some info, doesn't really matter what it is.
         * Most PXE stacks seem to take this approach.
         */
-       sprintf ( undi_get_iface_info->IfaceType, "Etherboot" );
+       snprintf ( ( char * ) undi_get_iface_info->IfaceType,
+                  sizeof ( undi_get_iface_info->IfaceType ), "Etherboot" );
        undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
        undi_get_iface_info->ServiceFlags = 0;
        memset ( undi_get_iface_info->Reserved, 0,
                 sizeof(undi_get_iface_info->Reserved) );
-#endif
 
        undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
        return PXENV_EXIT_SUCCESS;
@@ -463,18 +457,11 @@ PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE
  * Status: working
  */
 PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
+       struct io_buffer *iobuf;
+       size_t len;
+
        DBG ( "PXENV_UNDI_ISR" );
 
-#if 0
-       /* We can't call ENSURE_READY, because this could be being
-        * called as part of an interrupt service routine.  Instead,
-        * we should simply die if we're not READY.
-        */
-       if ( ( pxe_stack == NULL ) || ( pxe_stack->state < READY ) ) {
-               undi_isr->Status = PXENV_STATUS_UNDI_INVALID_STATE;
-               return PXENV_EXIT_FAILURE;
-       }
-       
        /* Just in case some idiot actually looks at these fields when
         * we weren't meant to fill them in...
         */
@@ -486,18 +473,14 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
 
        switch ( undi_isr->FuncFlag ) {
        case PXENV_UNDI_ISR_IN_START :
-               /* Is there a packet waiting?  If so, disable
-                * interrupts on the NIC and return "it's ours".  Do
-                * *not* necessarily acknowledge the interrupt; this
-                * can happen later when eth_poll(1) is called.  As
-                * long as the interrupt is masked off so that it
-                * doesn't immediately retrigger the 8259A then all
-                * should be well.
-                */
                DBG ( " START" );
-               if ( eth_poll ( 0 ) ) {
+
+               /* Call poll().  This should acknowledge the device
+                * interrupt and queue up any received packet.
+                */
+               if ( netdev_poll ( pxe_netdev, -1U ) ) {
+                       /* Packet waiting in queue */
                        DBG ( " OURS" );
-                       eth_irq ( DISABLE );
                        undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
                } else {
                        DBG ( " NOT_OURS" );
@@ -505,62 +488,48 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
                }
                break;
        case PXENV_UNDI_ISR_IN_PROCESS :
-               /* Call poll(), return packet.  If no packet, return "done".
-                */
-               DBG ( " PROCESS" );
-               if ( eth_poll ( 1 ) ) {
-                       DBG ( " RECEIVE %d", nic.packetlen );
-                       if ( nic.packetlen > sizeof(pxe_stack->packet) ) {
-                               /* Should never happen */
-                               undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
-                               undi_isr->Status =
-                                       PXENV_STATUS_OUT_OF_RESOURCES;
-                               return PXENV_EXIT_FAILURE;
-                       }
-                       undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
-                       undi_isr->BufferLength = nic.packetlen;
-                       undi_isr->FrameLength = nic.packetlen;
-                       undi_isr->FrameHeaderLength = ETH_HLEN;
-                       memcpy ( pxe_stack->packet, nic.packet, nic.packetlen);
-                       PTR_TO_SEGOFF16 ( pxe_stack->packet, undi_isr->Frame );
-                       switch ( ntohs(media_header->nstype) ) {
-                       case ETH_P_IP:  undi_isr->ProtType = P_IP;      break;
-                       case ETH_P_ARP: undi_isr->ProtType = P_ARP;     break;
-                       case ETH_P_RARP: undi_isr->ProtType = P_RARP;   break;
-                       default :       undi_isr->ProtType = P_UNKNOWN;
-                       }
-                       if ( memcmp ( media_header->dest, broadcast_mac,
-                                     sizeof(broadcast_mac) ) ) {
-                               undi_isr->PktType = XMT_BROADCAST;
-                       } else {
-                               undi_isr->PktType = XMT_DESTADDR;
-                       }
+       case PXENV_UNDI_ISR_IN_GET_NEXT :
+               DBG ( " PROCESS/GET_NEXT" );
+               
+               /* Remove first packet from netdev RX queue */
+               iobuf = netdev_rx_dequeue ( pxe_netdev );
+               if ( ! iobuf ) {
+                       /* No more packets remaining */
+                       undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
                        break;
-               } else {
-                       /* No break - fall through to IN_GET_NEXT */
                }
-       case PXENV_UNDI_ISR_IN_GET_NEXT :
-               /* We only ever return one frame at a time */
-               DBG ( " GET_NEXT DONE" );
-               /* Re-enable interrupts */
-               eth_irq ( ENABLE );
-               /* Force an interrupt if there's a packet still
-                * waiting, since we only handle one packet per
-                * interrupt.
-                */
-               if ( eth_poll ( 0 ) ) {
-                       DBG ( " (RETRIGGER)" );
-                       eth_irq ( FORCE );
+
+               /* Copy packet to base memory buffer */
+               len = iob_len ( iobuf );
+               DBG ( " RECEIVE %zd", len );
+               if ( len > sizeof ( basemem_packet ) ) {
+                       /* Should never happen */
+                       undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
+                       undi_isr->Status = PXENV_STATUS_OUT_OF_RESOURCES;
+                       return PXENV_EXIT_FAILURE;
                }
-               undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
+               memcpy ( basemem_packet, iobuf->data, len );
+
+               undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
+               undi_isr->BufferLength = len;
+               undi_isr->FrameLength = len;
+               undi_isr->FrameHeaderLength =
+                       pxe_netdev->ll_protocol->ll_header_len;
+               undi_isr->Frame.segment = rm_ds;
+               undi_isr->Frame.offset =
+                       ( ( unsigned ) & __from_data16 ( basemem_packet ) );
+               /* Probably ought to fill in packet type */
+               undi_isr->ProtType = P_UNKNOWN;
+               undi_isr->PktType = XMT_DESTADDR;
                break;
        default :
+               DBG ( " INVALID(%04x)", undi_isr->FuncFlag );
+
                /* Should never happen */
                undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
                undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
                return PXENV_EXIT_FAILURE;
        }
-#endif
 
        undi_isr->Status = PXENV_STATUS_SUCCESS;
        return PXENV_EXIT_SUCCESS;
index 383dc84..011d4fe 100644 (file)
@@ -281,8 +281,7 @@ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
  *
  * This operation is meaningless for the ARP protocol.
  */
-static const char *
-arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) {
+static const char * arp_ntoa ( const void *net_addr __unused ) {
        return "<ARP>";
 }
 
index 7108bef..8f259fb 100644 (file)
@@ -108,6 +108,7 @@ struct ll_protocol ethernet_protocol __ll_protocol = {
        .name           = "Ethernet",
        .ll_proto       = htons ( ARPHRD_ETHER ),
        .ll_addr_len    = ETH_ALEN,
+       .ll_header_len  = ETH_HLEN,
        .ll_broadcast   = eth_broadcast,
        .tx             = eth_tx,
        .rx             = eth_rx,
diff --git a/src/net/rarp.c b/src/net/rarp.c
new file mode 100644 (file)
index 0000000..bb5e6ad
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/rarp.h>
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+/**
+ * Process incoming ARP packets
+ *
+ * @v iobuf            I/O buffer
+ * @v netdev           Network device
+ * @v ll_source                Link-layer source address
+ * @ret rc             Return status code
+ *
+ * This is a dummy method which simply discards RARP packets.
+ */
+static int rarp_rx ( struct io_buffer *iobuf,
+                    struct net_device *netdev __unused,
+                    const void *ll_source __unused ) {
+       free_iob ( iobuf );
+       return 0;
+}
+
+
+/**
+ * Transcribe RARP address
+ *
+ * @v net_addr RARP address
+ * @ret string "<RARP>"
+ *
+ * This operation is meaningless for the RARP protocol.
+ */
+static const char * rarp_ntoa ( const void *net_addr __unused ) {
+       return "<RARP>";
+}
+
+/** RARP protocol */
+struct net_protocol rarp_protocol __net_protocol = {
+       .name = "RARP",
+       .net_proto = htons ( ETH_P_RARP ),
+       .rx = rarp_rx,
+       .ntoa = rarp_ntoa,
+};