Merge branch 'master' of ssh://rom.etherboot.org/pub/scm/gpxe
This commit is contained in:
commit
0297a63877
|
@ -19,11 +19,12 @@
|
||||||
/**
|
/**
|
||||||
* @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
|
#undef basemem_packet
|
||||||
char __data16_array ( dhcp_basemem, [DHCP_BASEMEM_LEN] );
|
char __data16_array ( basemem_packet, [BASEMEM_PACKET_LEN] );
|
|
@ -22,6 +22,7 @@
|
||||||
#include <pic8259.h>
|
#include <pic8259.h>
|
||||||
#include <biosint.h>
|
#include <biosint.h>
|
||||||
#include <pnpbios.h>
|
#include <pnpbios.h>
|
||||||
|
#include <basemem_packet.h>
|
||||||
#include <gpxe/iobuf.h>
|
#include <gpxe/iobuf.h>
|
||||||
#include <gpxe/netdevice.h>
|
#include <gpxe/netdevice.h>
|
||||||
#include <gpxe/if_ether.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 */
|
/** UNDI transmit buffer descriptor */
|
||||||
static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd );
|
static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd );
|
||||||
#define undinet_tbd __use_data16 ( undinet_tbd )
|
#define undinet_tbd __use_data16 ( undinet_tbd )
|
||||||
|
@ -340,9 +334,9 @@ static int undinet_transmit ( struct net_device *netdev,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Copy packet to UNDI I/O buffer */
|
/* Copy packet to UNDI I/O buffer */
|
||||||
if ( len > sizeof ( undinet_iob ) )
|
if ( len > sizeof ( basemem_packet ) )
|
||||||
len = sizeof ( undinet_iob );
|
len = sizeof ( basemem_packet );
|
||||||
memcpy ( &undinet_iob, iobuf->data, len );
|
memcpy ( &basemem_packet, iobuf->data, len );
|
||||||
|
|
||||||
/* Create PXENV_UNDI_TRANSMIT data structure */
|
/* Create PXENV_UNDI_TRANSMIT data structure */
|
||||||
memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
|
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.ImmedLength = len;
|
||||||
undinet_tbd.Xmit.segment = rm_ds;
|
undinet_tbd.Xmit.segment = rm_ds;
|
||||||
undinet_tbd.Xmit.offset
|
undinet_tbd.Xmit.offset
|
||||||
= ( ( unsigned ) & __from_data16 ( undinet_iob ) );
|
= ( ( unsigned ) & __from_data16 ( basemem_packet ) );
|
||||||
|
|
||||||
/* Issue PXE API call */
|
/* Issue PXE API call */
|
||||||
if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT,
|
if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <realmode.h>
|
#include <realmode.h>
|
||||||
#include <gateA20.h>
|
#include <gateA20.h>
|
||||||
#include <memsizes.h>
|
#include <memsizes.h>
|
||||||
#include <dhcp_basemem.h>
|
#include <basemem_packet.h>
|
||||||
#include <gpxe/uaccess.h>
|
#include <gpxe/uaccess.h>
|
||||||
#include <gpxe/segment.h>
|
#include <gpxe/segment.h>
|
||||||
#include <gpxe/shutdown.h>
|
#include <gpxe/shutdown.h>
|
||||||
|
@ -321,7 +321,7 @@ static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
|
||||||
"=b" ( discard_b )
|
"=b" ( discard_b )
|
||||||
: "D" ( imgheader->execaddr.segoff ),
|
: "D" ( imgheader->execaddr.segoff ),
|
||||||
"S" ( imgheader->location ),
|
"S" ( imgheader->location ),
|
||||||
"b" ( __from_data16 ( dhcp_basemem ) )
|
"b" ( __from_data16 ( basemem_packet ) )
|
||||||
: "ecx", "edx", "ebp" );
|
: "ecx", "edx", "ebp" );
|
||||||
|
|
||||||
gateA20_set();
|
gateA20_set();
|
||||||
|
@ -356,7 +356,7 @@ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
|
||||||
: "D" ( imgheader->execaddr.linear ),
|
: "D" ( imgheader->execaddr.linear ),
|
||||||
"S" ( ( imgheader->location.segment << 4 ) +
|
"S" ( ( imgheader->location.segment << 4 ) +
|
||||||
imgheader->location.offset ),
|
imgheader->location.offset ),
|
||||||
"b" ( virt_to_phys ( dhcp_basemem ) ),
|
"b" ( virt_to_phys ( basemem_packet ) ),
|
||||||
"a" ( virt_to_phys ( &loaderinfo ) )
|
"a" ( virt_to_phys ( &loaderinfo ) )
|
||||||
: "ecx", "edx", "ebp", "memory" );
|
: "ecx", "edx", "ebp", "memory" );
|
||||||
|
|
||||||
|
@ -397,8 +397,8 @@ static int nbi_prepare_dhcp ( struct image *image ) {
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( rc = create_dhcp_packet ( boot_netdev, DHCPACK,
|
if ( ( rc = create_dhcp_packet ( boot_netdev, DHCPACK, basemem_packet,
|
||||||
dhcp_basemem, sizeof ( dhcp_basemem ),
|
sizeof ( basemem_packet ),
|
||||||
&dhcppkt ) ) != 0 ) {
|
&dhcppkt ) ) != 0 ) {
|
||||||
DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
|
DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct image_type pxe_image_type __image_type ( PROBE_PXE );
|
||||||
*/
|
*/
|
||||||
static int pxe_exec ( struct image *image __unused ) {
|
static int pxe_exec ( struct image *image __unused ) {
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Ensure that PXE stack is ready to use */
|
/* Ensure that PXE stack is ready to use */
|
||||||
pxe_init_structures();
|
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 */
|
/* Arbitrarily pick the first open network device to use for PXE */
|
||||||
for_each_netdev ( netdev ) {
|
for_each_netdev ( netdev ) {
|
||||||
pxe_netdev = netdev;
|
pxe_set_netdev ( netdev );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pxe_start_nbp();
|
/* Start PXE NBP */
|
||||||
|
rc = pxe_start_nbp();
|
||||||
|
|
||||||
|
/* Deactivate PXE */
|
||||||
|
pxe_set_netdev ( NULL );
|
||||||
|
pxe_unhook_int1a();
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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 */
|
|
@ -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 */
|
|
|
@ -705,6 +705,8 @@ static int isapnpbus_probe ( struct root_device *rootdev ) {
|
||||||
isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP;
|
isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP;
|
||||||
isapnp->dev.desc.vendor = isapnp->vendor_id;
|
isapnp->dev.desc.vendor = isapnp->vendor_id;
|
||||||
isapnp->dev.desc.device = isapnp->prod_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;
|
isapnp->dev.parent = &rootdev->dev;
|
||||||
list_add ( &isapnp->dev.siblings,
|
list_add ( &isapnp->dev.siblings,
|
||||||
&rootdev->dev.children );
|
&rootdev->dev.children );
|
||||||
|
|
|
@ -286,6 +286,9 @@ static int pcibus_probe ( struct root_device *rootdev ) {
|
||||||
pci->dev.desc.location = PCI_BUSDEVFN (bus, devfn);
|
pci->dev.desc.location = PCI_BUSDEVFN (bus, devfn);
|
||||||
pci->dev.desc.vendor = pci->vendor;
|
pci->dev.desc.vendor = pci->vendor;
|
||||||
pci->dev.desc.device = pci->device;
|
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;
|
pci->dev.parent = &rootdev->dev;
|
||||||
list_add ( &pci->dev.siblings, &rootdev->dev.children);
|
list_add ( &pci->dev.siblings, &rootdev->dev.children);
|
||||||
INIT_LIST_HEAD ( &pci->dev.children );
|
INIT_LIST_HEAD ( &pci->dev.children );
|
||||||
|
|
|
@ -30,6 +30,8 @@ struct arp_net_protocol {
|
||||||
#define __arp_net_protocol \
|
#define __arp_net_protocol \
|
||||||
__table ( struct arp_net_protocol, arp_net_protocols, 01 )
|
__table ( struct arp_net_protocol, arp_net_protocols, 01 )
|
||||||
|
|
||||||
|
extern struct net_protocol arp_protocol;
|
||||||
|
|
||||||
extern int arp_resolve ( struct net_device *netdev,
|
extern int arp_resolve ( struct net_device *netdev,
|
||||||
struct net_protocol *net_protocol,
|
struct net_protocol *net_protocol,
|
||||||
const void *dest_net_addr,
|
const void *dest_net_addr,
|
||||||
|
|
|
@ -27,6 +27,12 @@ struct device_description {
|
||||||
unsigned int vendor;
|
unsigned int vendor;
|
||||||
/** Device ID */
|
/** Device ID */
|
||||||
unsigned int device;
|
unsigned int device;
|
||||||
|
/** Device class */
|
||||||
|
unsigned long class;
|
||||||
|
/** I/O address */
|
||||||
|
unsigned long ioaddr;
|
||||||
|
/** IRQ */
|
||||||
|
unsigned int irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** PCI bus type */
|
/** PCI bus type */
|
||||||
|
|
|
@ -122,6 +122,8 @@ struct ll_protocol {
|
||||||
uint16_t ll_proto;
|
uint16_t ll_proto;
|
||||||
/** Link-layer address length */
|
/** Link-layer address length */
|
||||||
uint8_t ll_addr_len;
|
uint8_t ll_addr_len;
|
||||||
|
/** Link-layer header length */
|
||||||
|
uint8_t ll_header_len;
|
||||||
/** Link-layer broadcast address */
|
/** Link-layer broadcast address */
|
||||||
const uint8_t *ll_broadcast;
|
const uint8_t *ll_broadcast;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 */
|
|
@ -137,4 +137,6 @@ struct pcir_header {
|
||||||
|
|
||||||
extern struct net_device *pxe_netdev;
|
extern struct net_device *pxe_netdev;
|
||||||
|
|
||||||
|
extern void pxe_set_netdev ( struct net_device *netdev );
|
||||||
|
|
||||||
#endif /* PXE_H */
|
#endif /* PXE_H */
|
||||||
|
|
|
@ -22,12 +22,24 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dev.h"
|
#include <gpxe/netdevice.h>
|
||||||
#include "pxe.h"
|
#include "pxe.h"
|
||||||
|
|
||||||
#warning "pxe_netdev should hold a persistent reference to the net device"
|
|
||||||
struct net_device *pxe_netdev = NULL;
|
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
|
#if 0
|
||||||
|
|
||||||
/* Global pointer to currently installed PXE stack */
|
/* Global pointer to currently installed PXE stack */
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gpxe/uaccess.h>
|
#include <gpxe/uaccess.h>
|
||||||
#include <gpxe/dhcp.h>
|
#include <gpxe/dhcp.h>
|
||||||
#include <dhcp_basemem.h>
|
#include <basemem_packet.h>
|
||||||
#include "pxe.h"
|
#include "pxe.h"
|
||||||
#include "pxe_call.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;
|
len = get_cached_info->BufferSize;
|
||||||
if ( len == 0 ) {
|
if ( len == 0 ) {
|
||||||
len = sizeof ( dhcp_basemem );
|
len = sizeof ( basemem_packet );
|
||||||
get_cached_info->Buffer.segment = rm_ds;
|
get_cached_info->Buffer.segment = rm_ds;
|
||||||
get_cached_info->Buffer.offset =
|
get_cached_info->Buffer.offset =
|
||||||
( unsigned int ) ( & __from_data16 ( dhcp_basemem ) );
|
( unsigned int ) ( & __from_data16 ( basemem_packet ) );
|
||||||
get_cached_info->BufferLimit = len;
|
get_cached_info->BufferLimit = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <byteswap.h>
|
||||||
|
#include <basemem_packet.h>
|
||||||
#include <gpxe/netdevice.h>
|
#include <gpxe/netdevice.h>
|
||||||
|
#include <gpxe/iobuf.h>
|
||||||
#include <gpxe/device.h>
|
#include <gpxe/device.h>
|
||||||
#include <gpxe/pci.h>
|
#include <gpxe/pci.h>
|
||||||
#include <gpxe/isapnp.h>
|
|
||||||
#include <gpxe/if_ether.h>
|
#include <gpxe/if_ether.h>
|
||||||
|
#include <gpxe/ip.h>
|
||||||
|
#include <gpxe/arp.h>
|
||||||
|
#include <gpxe/rarp.h>
|
||||||
#include <gpxe/shutdown.h>
|
#include <gpxe/shutdown.h>
|
||||||
#include "pxe.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
|
PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
|
||||||
*undi_transmit ) {
|
*undi_transmit ) {
|
||||||
struct s_PXENV_UNDI_TBD *tbd;
|
struct s_PXENV_UNDI_TBD tbd;
|
||||||
const char *dest;
|
struct DataBlk *datablk;
|
||||||
unsigned int type;
|
struct io_buffer *iobuf;
|
||||||
unsigned int length;
|
struct net_protocol *net_protocol;
|
||||||
const char *data;
|
char destaddr[MAX_LL_ADDR_LEN];
|
||||||
|
const void *ll_dest;
|
||||||
|
size_t len;
|
||||||
|
unsigned int i;
|
||||||
|
int rc;
|
||||||
|
|
||||||
DBG ( "PXENV_UNDI_TRANSMIT" );
|
DBG ( "PXENV_UNDI_TRANSMIT" );
|
||||||
|
|
||||||
#if 0
|
/* Identify network-layer protocol */
|
||||||
/* 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 ) {
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 ) {
|
switch ( undi_transmit->Protocol ) {
|
||||||
case P_IP: type = ETH_P_IP; break;
|
case P_IP: net_protocol = &ipv4_protocol; break;
|
||||||
case P_ARP: type = ETH_P_ARP; break;
|
case P_ARP: net_protocol = &arp_protocol; break;
|
||||||
case P_RARP: type = ETH_P_RARP; break;
|
case P_RARP: net_protocol = &rarp_protocol; break;
|
||||||
case P_UNKNOWN:
|
case P_UNKNOWN: net_protocol = NULL; break;
|
||||||
media_header = (media_header_t*)data;
|
|
||||||
dest = media_header->dest;
|
|
||||||
type = ntohs ( media_header->nstype );
|
|
||||||
data += ETH_HLEN;
|
|
||||||
length -= ETH_HLEN;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
|
undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
|
||||||
return PXENV_EXIT_FAILURE;
|
return PXENV_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the packet */
|
/* Calculate total packet length */
|
||||||
eth_transmit ( dest, type, length, data );
|
copy_from_real ( &tbd, undi_transmit->TBD.segment,
|
||||||
#endif
|
undi_transmit->TBD.offset, sizeof ( tbd ) );
|
||||||
|
len = tbd.ImmedLength;
|
||||||
|
for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
|
||||||
|
datablk = &tbd.DataBlock[i];
|
||||||
|
len += datablk->TDDataLen;
|
||||||
|
}
|
||||||
|
|
||||||
undi_transmit->Status = PXENV_STATUS_SUCCESS;
|
/* Allocate and fill I/O buffer */
|
||||||
return PXENV_EXIT_SUCCESS;
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
/* 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
|
/* PXENV_UNDI_SET_STATION_ADDRESS
|
||||||
*
|
*
|
||||||
* Status: working (deliberately incomplete)
|
* Status: working
|
||||||
*/
|
*/
|
||||||
PXENV_EXIT_t
|
PXENV_EXIT_t
|
||||||
pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
|
pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
|
||||||
*undi_set_station_address ) {
|
*undi_set_station_address ) {
|
||||||
|
|
||||||
DBG ( "PXENV_UNDI_SET_STATION_ADDRESS" );
|
DBG ( "PXENV_UNDI_SET_STATION_ADDRESS" );
|
||||||
|
|
||||||
#if 0
|
/* If adapter is open, the change will have no effect; return
|
||||||
/* We don't offer a facility to set the MAC address; this
|
* an error
|
||||||
* 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 ( memcmp ( nic.node_addr,
|
if ( pxe_netdev->state & NETDEV_OPEN ) {
|
||||||
&undi_set_station_address->StationAddress,
|
undi_set_station_address->Status =
|
||||||
ETH_ALEN ) == 0 ) {
|
PXENV_STATUS_UNDI_INVALID_STATE;
|
||||||
undi_set_station_address->Status = PXENV_STATUS_SUCCESS;
|
return PXENV_EXIT_FAILURE;
|
||||||
return PXENV_EXIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
undi_set_station_address->Status = PXENV_STATUS_UNSUPPORTED;
|
/* Update MAC address */
|
||||||
return PXENV_EXIT_FAILURE;
|
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
|
/* 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 ) {
|
*undi_get_information ) {
|
||||||
struct device *dev = pxe_netdev->dev;
|
struct device *dev = pxe_netdev->dev;
|
||||||
struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
|
struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
|
||||||
unsigned int ioaddr;
|
|
||||||
unsigned int irqno;
|
|
||||||
|
|
||||||
DBG ( "PXENV_UNDI_GET_INFORMATION" );
|
DBG ( "PXENV_UNDI_GET_INFORMATION" );
|
||||||
|
|
||||||
switch ( dev->desc.bus_type ) {
|
undi_get_information->BaseIo = dev->desc.ioaddr;
|
||||||
case BUS_TYPE_PCI: {
|
undi_get_information->IntNumber = dev->desc.irq;
|
||||||
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;
|
|
||||||
/* Cheat: assume all cards can cope with this */
|
/* Cheat: assume all cards can cope with this */
|
||||||
undi_get_information->MaxTranUnit = ETH_MAX_MTU;
|
undi_get_information->MaxTranUnit = ETH_MAX_MTU;
|
||||||
undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
|
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 ) {
|
switch ( dev->desc.bus_type ) {
|
||||||
case BUS_TYPE_PCI: {
|
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;
|
struct pci_nic_info *info = &undi_get_nic_type->info.pci;
|
||||||
|
|
||||||
undi_get_nic_type->NicType = PCI_NIC;
|
undi_get_nic_type->NicType = PCI_NIC;
|
||||||
info->Vendor_ID = pci->vendor;
|
info->Vendor_ID = dev->desc.vendor;
|
||||||
info->Dev_ID = pci->device;
|
info->Dev_ID = dev->desc.device;
|
||||||
info->Base_Class = PCI_BASE_CLASS ( pci->class );
|
info->Base_Class = PCI_BASE_CLASS ( dev->desc.class );
|
||||||
info->Sub_Class = PCI_SUB_CLASS ( pci->class );
|
info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class );
|
||||||
info->Prog_Intf = PCI_PROG_INTF ( pci->class );
|
info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class );
|
||||||
info->BusDevFunc = PCI_BUSDEVFN ( pci->bus, pci->devfn );
|
info->BusDevFunc = dev->desc.location;
|
||||||
/* Cheat: remaining fields are probably unnecessary,
|
/* Cheat: remaining fields are probably unnecessary,
|
||||||
* and would require adding extra code to pci.c.
|
* 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;
|
undi_get_nic_type->info.pci.SubDevice_ID = 0xffff;
|
||||||
break; }
|
break; }
|
||||||
case BUS_TYPE_ISAPNP: {
|
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;
|
struct pnp_nic_info *info = &undi_get_nic_type->info.pnp;
|
||||||
|
|
||||||
undi_get_nic_type->NicType = PnP_NIC;
|
undi_get_nic_type->NicType = PnP_NIC;
|
||||||
info->EISA_Dev_ID = ( ( isapnp->vendor_id << 16 ) |
|
info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) |
|
||||||
isapnp->prod_id );
|
dev->desc.device );
|
||||||
info->CardSelNum = isapnp->csn;
|
info->CardSelNum = dev->desc.location;
|
||||||
/* Cheat: remaining fields are probably unnecessary,
|
/* Cheat: remaining fields are probably unnecessary,
|
||||||
* and would require adding extra code to isapnp.c.
|
* 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 ) {
|
*undi_get_iface_info ) {
|
||||||
DBG ( "PXENV_UNDI_GET_IFACE_INFO" );
|
DBG ( "PXENV_UNDI_GET_IFACE_INFO" );
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Just hand back some info, doesn't really matter what it is.
|
/* Just hand back some info, doesn't really matter what it is.
|
||||||
* Most PXE stacks seem to take this approach.
|
* 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->LinkSpeed = 10000000; /* 10 Mbps */
|
||||||
undi_get_iface_info->ServiceFlags = 0;
|
undi_get_iface_info->ServiceFlags = 0;
|
||||||
memset ( undi_get_iface_info->Reserved, 0,
|
memset ( undi_get_iface_info->Reserved, 0,
|
||||||
sizeof(undi_get_iface_info->Reserved) );
|
sizeof(undi_get_iface_info->Reserved) );
|
||||||
#endif
|
|
||||||
|
|
||||||
undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
|
undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
|
||||||
return PXENV_EXIT_SUCCESS;
|
return PXENV_EXIT_SUCCESS;
|
||||||
|
@ -463,17 +457,10 @@ PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE
|
||||||
* Status: working
|
* Status: working
|
||||||
*/
|
*/
|
||||||
PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
|
PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
|
||||||
DBG ( "PXENV_UNDI_ISR" );
|
struct io_buffer *iobuf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
#if 0
|
DBG ( "PXENV_UNDI_ISR" );
|
||||||
/* 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
|
/* Just in case some idiot actually looks at these fields when
|
||||||
* we weren't meant to fill them in...
|
* 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 ) {
|
switch ( undi_isr->FuncFlag ) {
|
||||||
case PXENV_UNDI_ISR_IN_START :
|
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" );
|
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" );
|
DBG ( " OURS" );
|
||||||
eth_irq ( DISABLE );
|
|
||||||
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
|
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
|
||||||
} else {
|
} else {
|
||||||
DBG ( " NOT_OURS" );
|
DBG ( " NOT_OURS" );
|
||||||
|
@ -505,62 +488,48 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PXENV_UNDI_ISR_IN_PROCESS :
|
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;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
/* No break - fall through to IN_GET_NEXT */
|
|
||||||
}
|
|
||||||
case PXENV_UNDI_ISR_IN_GET_NEXT :
|
case PXENV_UNDI_ISR_IN_GET_NEXT :
|
||||||
/* We only ever return one frame at a time */
|
DBG ( " PROCESS/GET_NEXT" );
|
||||||
DBG ( " GET_NEXT DONE" );
|
|
||||||
/* Re-enable interrupts */
|
/* Remove first packet from netdev RX queue */
|
||||||
eth_irq ( ENABLE );
|
iobuf = netdev_rx_dequeue ( pxe_netdev );
|
||||||
/* Force an interrupt if there's a packet still
|
if ( ! iobuf ) {
|
||||||
* waiting, since we only handle one packet per
|
/* No more packets remaining */
|
||||||
* interrupt.
|
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
|
||||||
*/
|
break;
|
||||||
if ( eth_poll ( 0 ) ) {
|
|
||||||
DBG ( " (RETRIGGER)" );
|
|
||||||
eth_irq ( FORCE );
|
|
||||||
}
|
}
|
||||||
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
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;
|
break;
|
||||||
default :
|
default :
|
||||||
|
DBG ( " INVALID(%04x)", undi_isr->FuncFlag );
|
||||||
|
|
||||||
/* Should never happen */
|
/* Should never happen */
|
||||||
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
|
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
|
||||||
undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
|
undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
|
||||||
return PXENV_EXIT_FAILURE;
|
return PXENV_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
undi_isr->Status = PXENV_STATUS_SUCCESS;
|
undi_isr->Status = PXENV_STATUS_SUCCESS;
|
||||||
return PXENV_EXIT_SUCCESS;
|
return PXENV_EXIT_SUCCESS;
|
||||||
|
|
|
@ -281,8 +281,7 @@ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
|
||||||
*
|
*
|
||||||
* This operation is meaningless for the ARP protocol.
|
* This operation is meaningless for the ARP protocol.
|
||||||
*/
|
*/
|
||||||
static const char *
|
static const char * arp_ntoa ( const void *net_addr __unused ) {
|
||||||
arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) {
|
|
||||||
return "<ARP>";
|
return "<ARP>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@ struct ll_protocol ethernet_protocol __ll_protocol = {
|
||||||
.name = "Ethernet",
|
.name = "Ethernet",
|
||||||
.ll_proto = htons ( ARPHRD_ETHER ),
|
.ll_proto = htons ( ARPHRD_ETHER ),
|
||||||
.ll_addr_len = ETH_ALEN,
|
.ll_addr_len = ETH_ALEN,
|
||||||
|
.ll_header_len = ETH_HLEN,
|
||||||
.ll_broadcast = eth_broadcast,
|
.ll_broadcast = eth_broadcast,
|
||||||
.tx = eth_tx,
|
.tx = eth_tx,
|
||||||
.rx = eth_rx,
|
.rx = eth_rx,
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
Reference in New Issue