mirror of
https://github.com/xcat2/xNBA.git
synced 2026-09-30 14:55:11 +00:00
Merge branch 'master' of git://git.ipxe.org/ipxe
This commit is contained in:
@@ -65,6 +65,7 @@ SRCDIRS += drivers/net
|
||||
SRCDIRS += drivers/net/e1000
|
||||
SRCDIRS += drivers/net/e1000e
|
||||
SRCDIRS += drivers/net/igb
|
||||
SRCDIRS += drivers/net/igbvf
|
||||
SRCDIRS += drivers/net/phantom
|
||||
SRCDIRS += drivers/net/rtl818x
|
||||
SRCDIRS += drivers/net/ath5k
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -43,6 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** An UNDI NIC */
|
||||
struct undi_nic {
|
||||
/** Device supports IRQs */
|
||||
int irq_supported;
|
||||
/** Assigned IRQ number */
|
||||
unsigned int irq;
|
||||
/** Currently processing ISR */
|
||||
@@ -251,8 +253,10 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||
int rc;
|
||||
|
||||
if ( ! undinic->isr_processing ) {
|
||||
/* Do nothing unless ISR has been triggered */
|
||||
if ( ! undinet_isr_triggered() ) {
|
||||
/* If interrupts are supported, then do nothing unless
|
||||
* the ISR has been triggered.
|
||||
*/
|
||||
if ( undinic->irq_supported && ( ! undinet_isr_triggered() ) ){
|
||||
/* Allow interrupt to occur */
|
||||
__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
|
||||
"nop\n\t"
|
||||
@@ -357,10 +361,12 @@ static int undinet_open ( struct net_device *netdev ) {
|
||||
struct s_PXENV_UNDI_OPEN undi_open;
|
||||
int rc;
|
||||
|
||||
/* Hook interrupt service routine and enable interrupt */
|
||||
undinet_hook_isr ( undinic->irq );
|
||||
enable_irq ( undinic->irq );
|
||||
send_eoi ( undinic->irq );
|
||||
/* Hook interrupt service routine and enable interrupt if supported */
|
||||
if ( undinic->irq_supported ) {
|
||||
undinet_hook_isr ( undinic->irq );
|
||||
enable_irq ( undinic->irq );
|
||||
send_eoi ( undinic->irq );
|
||||
}
|
||||
|
||||
/* Set station address. Required for some PXE stacks; will
|
||||
* spuriously fail on others. Ignore failures. We only ever
|
||||
@@ -425,9 +431,11 @@ static void undinet_close ( struct net_device *netdev ) {
|
||||
pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE,
|
||||
&undi_close, sizeof ( undi_close ) );
|
||||
|
||||
/* Disable interrupt and unhook ISR */
|
||||
disable_irq ( undinic->irq );
|
||||
undinet_unhook_isr ( undinic->irq );
|
||||
/* Disable interrupt and unhook ISR if supported */
|
||||
if ( undinic->irq_supported ) {
|
||||
disable_irq ( undinic->irq );
|
||||
undinet_unhook_isr ( undinic->irq );
|
||||
}
|
||||
|
||||
DBGC ( undinic, "UNDINIC %p closed\n", undinic );
|
||||
}
|
||||
@@ -524,13 +532,8 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
goto err_undi_get_information;
|
||||
memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
|
||||
undinic->irq = undi_info.IntNumber;
|
||||
if ( undinic->irq > IRQ_MAX ) {
|
||||
DBGC ( undinic, "UNDINIC %p invalid IRQ %d\n",
|
||||
undinic, undinic->irq );
|
||||
goto err_bad_irq;
|
||||
}
|
||||
DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n",
|
||||
undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
|
||||
DBGC ( undinic, "UNDINIC %p has MAC address %s\n",
|
||||
undinic, eth_ntoa ( netdev->hw_addr ) );
|
||||
|
||||
/* Get interface information */
|
||||
memset ( &undi_iface, 0, sizeof ( undi_iface ) );
|
||||
@@ -541,6 +544,17 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
|
||||
undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
|
||||
undi_iface.ServiceFlags );
|
||||
if ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) {
|
||||
if ( undinic->irq > IRQ_MAX ) {
|
||||
DBGC ( undinic, "UNDINIC %p has invalid IRQ %d\n",
|
||||
undinic, undinic->irq );
|
||||
rc = -EINVAL;
|
||||
goto err_bad_irq;
|
||||
}
|
||||
undinic->irq_supported = 1;
|
||||
DBGC ( undinic, "UNDINIC %p uses IRQ %d\n",
|
||||
undinic, undinic->irq );
|
||||
}
|
||||
if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
|
||||
sizeof ( undi_iface.IfaceType ) ) == 0 ) {
|
||||
DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
|
||||
@@ -559,8 +573,8 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
err_undi_get_iface_info:
|
||||
err_bad_irq:
|
||||
err_undi_get_iface_info:
|
||||
err_undi_get_information:
|
||||
err_undi_initialize:
|
||||
/* Shut down UNDI stack */
|
||||
|
||||
@@ -1,26 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <ipxe/netdevice.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <hci/ifmgmt_cmd.h>
|
||||
#include <pxe_call.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* PXE commands
|
||||
*
|
||||
*/
|
||||
|
||||
/** "startpxe" command descriptor */
|
||||
static struct command_descriptor startpxe_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>]", "" );
|
||||
|
||||
/**
|
||||
* "startpxe" payload
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int startpxe_payload ( struct net_device *netdev ) {
|
||||
|
||||
if ( netdev_is_open ( netdev ) )
|
||||
pxe_activate ( netdev );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "startpxe" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int startpxe_exec ( int argc, char **argv ) {
|
||||
return ifcommon_exec ( argc, argv, startpxe_payload,
|
||||
"Activate PXE on" );
|
||||
return ifcommon_exec ( argc, argv, &startpxe_cmd, startpxe_payload, 0 );
|
||||
}
|
||||
|
||||
/** "stoppxe" options */
|
||||
struct stoppxe_options {};
|
||||
|
||||
/** "stoppxe" option list */
|
||||
static struct option_descriptor stoppxe_opts[] = {};
|
||||
|
||||
/** "stoppxe" command descriptor */
|
||||
static struct command_descriptor stoppxe_cmd =
|
||||
COMMAND_DESC ( struct stoppxe_options, stoppxe_opts, 0, 0,
|
||||
"", "" );
|
||||
|
||||
/**
|
||||
* The "stoppxe" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int stoppxe_exec ( int argc __unused, char **argv __unused ) {
|
||||
struct stoppxe_options opts;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &stoppxe_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
pxe_deactivate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** PXE commands */
|
||||
struct command pxe_commands[] __command = {
|
||||
{
|
||||
.name = "startpxe",
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <realmode.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Reboot command
|
||||
*
|
||||
*/
|
||||
|
||||
/** "reboot" options */
|
||||
struct reboot_options {};
|
||||
|
||||
/** "reboot" option list */
|
||||
static struct option_descriptor reboot_opts[] = {};
|
||||
|
||||
/** "reboot" command descriptor */
|
||||
static struct command_descriptor reboot_cmd =
|
||||
COMMAND_DESC ( struct reboot_options, reboot_opts, 0, 0, "", "" );
|
||||
|
||||
/**
|
||||
* The "reboot" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int reboot_exec ( int argc, char **argv ) {
|
||||
struct reboot_options opts;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &reboot_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Reboot system */
|
||||
__asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "reboot" command */
|
||||
struct command reboot_command __command = {
|
||||
.name = "reboot",
|
||||
.exec = reboot_exec,
|
||||
};
|
||||
@@ -166,11 +166,13 @@ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
|
||||
|
||||
/* Record source IP address */
|
||||
pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip;
|
||||
DBG ( " %s", inet_ntoa ( pxe_udp.local.sin_addr ) );
|
||||
DBG ( " %s\n", inet_ntoa ( pxe_udp.local.sin_addr ) );
|
||||
|
||||
/* Open promiscuous UDP connection */
|
||||
intf_restart ( &pxe_udp.xfer, 0 );
|
||||
if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
|
||||
DBG ( "PXENV_UDP_OPEN could not open promiscuous socket: %s\n",
|
||||
strerror ( rc ) );
|
||||
pxenv_udp_open->Status = PXENV_STATUS ( rc );
|
||||
return PXENV_EXIT_FAILURE;
|
||||
}
|
||||
@@ -201,7 +203,7 @@ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
|
||||
*
|
||||
*/
|
||||
PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
|
||||
DBG ( "PXENV_UDP_CLOSE" );
|
||||
DBG ( "PXENV_UDP_CLOSE\n" );
|
||||
|
||||
/* Close UDP connection */
|
||||
intf_restart ( &pxe_udp.xfer, 0 );
|
||||
@@ -288,6 +290,7 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
|
||||
len = pxenv_udp_write->buffer_size;
|
||||
iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len );
|
||||
if ( ! iobuf ) {
|
||||
DBG ( " out of memory\n" );
|
||||
pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES;
|
||||
return PXENV_EXIT_FAILURE;
|
||||
}
|
||||
@@ -295,7 +298,7 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
|
||||
pxenv_udp_write->buffer.offset );
|
||||
copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len );
|
||||
|
||||
DBG ( " %04x:%04x+%x %d->%s:%d", pxenv_udp_write->buffer.segment,
|
||||
DBG ( " %04x:%04x+%x %d->%s:%d\n", pxenv_udp_write->buffer.segment,
|
||||
pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size,
|
||||
ntohs ( pxenv_udp_write->src_port ),
|
||||
inet_ntoa ( dest.sin_addr ),
|
||||
@@ -303,6 +306,8 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
|
||||
|
||||
/* Transmit packet */
|
||||
if ( ( rc = xfer_deliver ( &pxe_udp.xfer, iobuf, &meta ) ) != 0 ) {
|
||||
DBG ( "PXENV_UDP_WRITE could not transmit: %s\n",
|
||||
strerror ( rc ) );
|
||||
pxenv_udp_write->Status = PXENV_STATUS ( rc );
|
||||
return PXENV_EXIT_FAILURE;
|
||||
}
|
||||
@@ -360,36 +365,36 @@ PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
|
||||
uint16_t d_port_wanted = pxenv_udp_read->d_port;
|
||||
uint16_t d_port;
|
||||
|
||||
DBG ( "PXENV_UDP_READ" );
|
||||
|
||||
/* Try receiving a packet */
|
||||
pxe_udp.pxenv_udp_read = pxenv_udp_read;
|
||||
step();
|
||||
if ( pxe_udp.pxenv_udp_read ) {
|
||||
/* No packet received */
|
||||
DBG2 ( "PXENV_UDP_READ\n" );
|
||||
pxe_udp.pxenv_udp_read = NULL;
|
||||
goto no_packet;
|
||||
}
|
||||
dest_ip.s_addr = pxenv_udp_read->dest_ip;
|
||||
d_port = pxenv_udp_read->d_port;
|
||||
DBG ( "PXENV_UDP_READ" );
|
||||
|
||||
/* Filter on destination address and/or port */
|
||||
if ( dest_ip_wanted.s_addr &&
|
||||
( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) {
|
||||
DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) );
|
||||
DBG ( " (wanted %s)", inet_ntoa ( dest_ip_wanted ) );
|
||||
DBG ( " (wanted %s)\n", inet_ntoa ( dest_ip_wanted ) );
|
||||
goto no_packet;
|
||||
}
|
||||
if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
|
||||
DBG ( " wrong port %d ", htons ( d_port ) );
|
||||
DBG ( " (wanted %d)", htons ( d_port_wanted ) );
|
||||
DBG ( " wrong port %d", htons ( d_port ) );
|
||||
DBG ( " (wanted %d)\n", htons ( d_port_wanted ) );
|
||||
goto no_packet;
|
||||
}
|
||||
|
||||
DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
|
||||
pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
|
||||
inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) ));
|
||||
DBG ( "%d<-%s:%d", ntohs ( pxenv_udp_read->s_port ),
|
||||
DBG ( "%d<-%s:%d\n", ntohs ( pxenv_udp_read->s_port ),
|
||||
inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
|
||||
ntohs ( pxenv_udp_read->d_port ) );
|
||||
|
||||
|
||||
@@ -58,8 +58,10 @@ struct net_device *pxe_netdev = NULL;
|
||||
* @v netdev Network device, or NULL
|
||||
*/
|
||||
void pxe_set_netdev ( struct net_device *netdev ) {
|
||||
if ( pxe_netdev )
|
||||
if ( pxe_netdev ) {
|
||||
netdev_rx_unfreeze ( pxe_netdev );
|
||||
netdev_put ( pxe_netdev );
|
||||
}
|
||||
pxe_netdev = NULL;
|
||||
if ( netdev )
|
||||
pxe_netdev = netdev_get ( netdev );
|
||||
@@ -76,6 +78,7 @@ static int pxe_netdev_open ( void ) {
|
||||
if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
netdev_rx_freeze ( pxe_netdev );
|
||||
netdev_irq ( pxe_netdev, 1 );
|
||||
return 0;
|
||||
}
|
||||
@@ -85,6 +88,7 @@ static int pxe_netdev_open ( void ) {
|
||||
*
|
||||
*/
|
||||
static void pxe_netdev_close ( void ) {
|
||||
netdev_rx_unfreeze ( pxe_netdev );
|
||||
netdev_irq ( pxe_netdev, 0 );
|
||||
netdev_close ( pxe_netdev );
|
||||
undi_tx_count = 0;
|
||||
@@ -228,17 +232,17 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
|
||||
struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
|
||||
char destaddr[MAX_LL_ADDR_LEN];
|
||||
const void *ll_dest;
|
||||
size_t ll_hlen = ll_protocol->ll_header_len;
|
||||
size_t len;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
DBG2 ( "PXENV_UNDI_TRANSMIT" );
|
||||
|
||||
/* Forcibly enable interrupts at this point, to work around
|
||||
* callers that never call PXENV_UNDI_OPEN before attempting
|
||||
* to use the UNDI API.
|
||||
/* Forcibly enable interrupts and freeze receive queue
|
||||
* processing at this point, to work around callers that never
|
||||
* call PXENV_UNDI_OPEN before attempting to use the UNDI API.
|
||||
*/
|
||||
netdev_rx_freeze ( pxe_netdev );
|
||||
netdev_irq ( pxe_netdev, 1 );
|
||||
|
||||
/* Identify network-layer protocol */
|
||||
@@ -248,7 +252,6 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
|
||||
case P_RARP: net_protocol = &rarp_protocol; break;
|
||||
case P_UNKNOWN:
|
||||
net_protocol = NULL;
|
||||
ll_hlen = 0;
|
||||
break;
|
||||
default:
|
||||
DBG2 ( " %02x invalid protocol\n", undi_transmit->Protocol );
|
||||
@@ -271,13 +274,13 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
|
||||
}
|
||||
|
||||
/* Allocate and fill I/O buffer */
|
||||
iobuf = alloc_iob ( ll_hlen + len );
|
||||
iobuf = alloc_iob ( MAX_LL_HEADER_LEN + len );
|
||||
if ( ! iobuf ) {
|
||||
DBG2 ( " could not allocate iobuf\n" );
|
||||
undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
|
||||
return PXENV_EXIT_FAILURE;
|
||||
}
|
||||
iob_reserve ( iobuf, ll_hlen );
|
||||
iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
|
||||
copy_from_real ( iob_put ( iobuf, tbd.ImmedLength ), tbd.Xmit.segment,
|
||||
tbd.Xmit.offset, tbd.ImmedLength );
|
||||
for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
|
||||
@@ -558,12 +561,12 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
|
||||
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.
|
||||
/* Earlier versions of the PXE specification do not
|
||||
* have the SubVendor_ID and SubDevice_ID fields. It
|
||||
* is possible that some NBPs will not provide space
|
||||
* for them, and so we must not fill them in.
|
||||
*/
|
||||
undi_get_nic_type->info.pci.SubVendor_ID = 0xffff;
|
||||
undi_get_nic_type->info.pci.SubDevice_ID = 0xffff;
|
||||
DBG ( " PCI %02x:%02x.%x %04x:%04x (%04x:%04x) %02x%02x%02x "
|
||||
DBG ( " PCI %02x:%02x.%x %04x:%04x ('%04x:%04x') %02x%02x%02x "
|
||||
"rev %02x\n", PCI_BUS ( info->BusDevFunc ),
|
||||
PCI_SLOT ( info->BusDevFunc ),
|
||||
PCI_FUNC ( info->BusDevFunc ), info->Vendor_ID,
|
||||
@@ -672,7 +675,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
|
||||
/* Call poll(). This should acknowledge the device
|
||||
* interrupt and queue up any received packet.
|
||||
*/
|
||||
netdev_poll ( pxe_netdev );
|
||||
net_poll();
|
||||
|
||||
/* A 100% accurate determination of "OURS" vs "NOT
|
||||
* OURS" is difficult to achieve without invasive and
|
||||
@@ -711,7 +714,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
|
||||
* PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to
|
||||
* cope with these out-of-spec clients.
|
||||
*/
|
||||
netdev_poll ( pxe_netdev );
|
||||
net_poll();
|
||||
|
||||
/* If we have not yet marked a TX as complete, and the
|
||||
* netdev TX queue is empty, report the TX completion.
|
||||
@@ -782,7 +785,15 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
|
||||
undi_isr->Frame.segment = rm_ds;
|
||||
undi_isr->Frame.offset = __from_data16 ( basemem_packet );
|
||||
undi_isr->ProtType = prottype;
|
||||
undi_isr->PktType = XMT_DESTADDR;
|
||||
if ( memcmp ( ll_dest, pxe_netdev->ll_addr,
|
||||
ll_protocol->ll_addr_len ) == 0 ) {
|
||||
undi_isr->PktType = P_DIRECTED;
|
||||
} else if ( memcmp ( ll_dest, pxe_netdev->ll_broadcast,
|
||||
ll_protocol->ll_addr_len ) == 0 ) {
|
||||
undi_isr->PktType = P_BROADCAST;
|
||||
} else {
|
||||
undi_isr->PktType = P_MULTICAST;
|
||||
}
|
||||
DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d",
|
||||
undi_isr->Frame.segment, undi_isr->Frame.offset,
|
||||
undi_isr->BufferLength, undi_isr->FrameLength,
|
||||
|
||||
@@ -165,14 +165,23 @@ test_a20_long:
|
||||
pushl %ecx
|
||||
movl $TEST_A20_LONG_MAX_RETRIES, %ecx
|
||||
1: pushw %ax
|
||||
pushw %ds
|
||||
pushw %es
|
||||
|
||||
/* Flatten real mode so we can access the test pattern's 1MB offset */
|
||||
call flatten_real_mode
|
||||
/* Set up segment registers for access across the 1MB boundary */
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds
|
||||
decw %ax
|
||||
movw %ax, %es
|
||||
|
||||
2: /* Modify and check test pattern; succeed if we see a difference */
|
||||
incw %cs:test_a20_data
|
||||
addr32 movw %cs:(test_a20_data + 0x100000 ), %ax
|
||||
cmpw %cs:test_a20_data, %ax
|
||||
pushfw
|
||||
cli
|
||||
xchgw %ds:0, %cx
|
||||
movw %es:0x10, %ax
|
||||
xchgw %ds:0, %cx
|
||||
popfw
|
||||
cmpw %ax, %cx
|
||||
clc
|
||||
jnz 99f
|
||||
|
||||
@@ -182,17 +191,13 @@ test_a20_long:
|
||||
stc
|
||||
|
||||
99: /* Restore registers and return */
|
||||
popw %es
|
||||
popw %ds
|
||||
popw %ax
|
||||
popl %ecx
|
||||
ret
|
||||
.size test_a20_long, . - test_a20_long
|
||||
|
||||
.section ".text16.early.data", "aw", @progbits
|
||||
.align 2
|
||||
test_a20_data:
|
||||
.word 0xdead
|
||||
.size test_a20_data, . - test_a20_data
|
||||
|
||||
/****************************************************************************
|
||||
* enable_a20_bios
|
||||
*
|
||||
@@ -414,6 +419,7 @@ enable_a20_method:
|
||||
access_highmem:
|
||||
/* Enable A20 line */
|
||||
call enable_a20
|
||||
/* CPU will be in flat real mode as a result of this call */
|
||||
/* Set up 4GB limits */
|
||||
call flatten_real_mode
|
||||
lret
|
||||
.size access_highmem, . - access_highmem
|
||||
|
||||
@@ -234,6 +234,12 @@ REQUIRE_OBJECT ( pxe_cmd );
|
||||
#ifdef LOTEST_CMD
|
||||
REQUIRE_OBJECT ( lotest_cmd );
|
||||
#endif
|
||||
#ifdef VLAN_CMD
|
||||
REQUIRE_OBJECT ( vlan_cmd );
|
||||
#endif
|
||||
#ifdef REBOOT_CMD
|
||||
REQUIRE_OBJECT ( reboot_cmd );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Drag in miscellaneous objects
|
||||
|
||||
@@ -28,7 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#define PXE_STACK /* PXE stack in iPXE - required for PXELINUX */
|
||||
#define PXE_MENU /* PXE menu booting */
|
||||
#define PXE_CMD /* PXE commands */
|
||||
|
||||
#define SANBOOT_PROTO_ISCSI /* iSCSI protocol */
|
||||
#define SANBOOT_PROTO_AOE /* AoE protocol */
|
||||
|
||||
@@ -123,7 +123,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#undef TIME_CMD /* Time commands */
|
||||
#undef DIGEST_CMD /* Image crypto digest commands */
|
||||
#undef LOTEST_CMD /* Loopback testing commands */
|
||||
//#undef PXE_CMD /* PXE commands */
|
||||
#undef VLAN_CMD /* VLAN commands */
|
||||
#undef PXE_CMD /* PXE commands */
|
||||
#undef REBOOT_CMD /* Reboot command */
|
||||
|
||||
/*
|
||||
* Error message tables to include
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <ipxe/crypto.h>
|
||||
#include <ipxe/md5.h>
|
||||
|
||||
/**
|
||||
* Print an MD5 checksum with specified display address
|
||||
*
|
||||
* @v dispaddr Display address
|
||||
* @v data Data to checksum
|
||||
* @v len Length of data
|
||||
*/
|
||||
void dbg_md5_da ( unsigned long dispaddr, const void *data,
|
||||
unsigned long len ) {
|
||||
struct digest_algorithm *digest = &md5_algorithm;
|
||||
uint8_t digest_ctx[digest->ctxsize];
|
||||
uint8_t digest_out[digest->digestsize];
|
||||
unsigned int i;
|
||||
|
||||
printf ( "md5sum ( %#08lx, %#lx ) = ", dispaddr, len );
|
||||
digest_init ( digest, digest_ctx );
|
||||
digest_update ( digest, digest_ctx, data, len );
|
||||
digest_final ( digest, digest_ctx, digest_out );
|
||||
for ( i = 0 ; i < sizeof ( digest_out ) ; i++ )
|
||||
printf ( "%02x", digest_out[i] );
|
||||
printf ( "\n" );
|
||||
}
|
||||
+247
-52
@@ -29,7 +29,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <assert.h>
|
||||
#include <ipxe/tables.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/settings.h>
|
||||
#include <ipxe/shell.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -37,16 +39,15 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
/* Avoid dragging in getopt.o unless a command really uses it */
|
||||
int optind;
|
||||
int nextchar;
|
||||
/** Shell stop state */
|
||||
static int stop_state;
|
||||
|
||||
/**
|
||||
* Execute command
|
||||
*
|
||||
* @v command Command name
|
||||
* @v argv Argument list
|
||||
* @ret rc Command exit status
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Execute the named command. Unlike a traditional POSIX execv(),
|
||||
* this function returns the exit status of the command.
|
||||
@@ -58,12 +59,12 @@ int execv ( const char *command, char * const argv[] ) {
|
||||
/* Count number of arguments */
|
||||
for ( argc = 0 ; argv[argc] ; argc++ ) {}
|
||||
|
||||
/* An empty command is deemed to do nothing, successfully */
|
||||
if ( command == NULL )
|
||||
return 0;
|
||||
|
||||
/* Sanity checks */
|
||||
if ( ! command ) {
|
||||
DBG ( "No command\n" );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( ! argc ) {
|
||||
if ( argc == 0 ) {
|
||||
DBG ( "%s: empty argument list\n", command );
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -115,17 +116,21 @@ static char * expand_command ( const char *command ) {
|
||||
|
||||
head = expcmd;
|
||||
|
||||
/* Locate opener */
|
||||
start = strstr ( expcmd, "${" );
|
||||
if ( ! start )
|
||||
/* Locate setting to be expanded */
|
||||
start = NULL;
|
||||
end = NULL;
|
||||
for ( tmp = expcmd ; *tmp ; tmp++ ) {
|
||||
if ( ( tmp[0] == '$' ) && ( tmp[1] == '{' ) )
|
||||
start = tmp;
|
||||
if ( start && ( tmp[0] == '}' ) ) {
|
||||
end = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! end )
|
||||
break;
|
||||
*start = '\0';
|
||||
name = ( start + 2 );
|
||||
|
||||
/* Locate closer */
|
||||
end = strstr ( name, "}" );
|
||||
if ( ! end )
|
||||
break;
|
||||
*end = '\0';
|
||||
tail = ( end + 1 );
|
||||
|
||||
@@ -156,83 +161,192 @@ static char * expand_command ( const char *command ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Split command line into argv array
|
||||
* Split command line into tokens
|
||||
*
|
||||
* @v args Command line
|
||||
* @v argv Argument array to populate, or NULL
|
||||
* @ret argc Argument count
|
||||
* @v command Command line
|
||||
* @v tokens Token list to populate, or NULL
|
||||
* @ret count Number of tokens
|
||||
*
|
||||
* Splits the command line into whitespace-delimited arguments. If @c
|
||||
* argv is non-NULL, any whitespace in the command line will be
|
||||
* Splits the command line into whitespace-delimited tokens. If @c
|
||||
* tokens is non-NULL, any whitespace in the command line will be
|
||||
* replaced with NULs.
|
||||
*/
|
||||
static int split_args ( char *args, char * argv[] ) {
|
||||
int argc = 0;
|
||||
static int split_command ( char *command, char **tokens ) {
|
||||
int count = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
/* Skip over any whitespace / convert to NUL */
|
||||
while ( isspace ( *args ) ) {
|
||||
if ( argv )
|
||||
*args = '\0';
|
||||
args++;
|
||||
while ( isspace ( *command ) ) {
|
||||
if ( tokens )
|
||||
*command = '\0';
|
||||
command++;
|
||||
}
|
||||
/* Check for end of line */
|
||||
if ( ! *args )
|
||||
if ( ! *command )
|
||||
break;
|
||||
/* We have found the start of the next argument */
|
||||
if ( argv )
|
||||
argv[argc] = args;
|
||||
argc++;
|
||||
if ( tokens )
|
||||
tokens[count] = command;
|
||||
count++;
|
||||
/* Skip to start of next whitespace, if any */
|
||||
while ( *args && ! isspace ( *args ) ) {
|
||||
args++;
|
||||
while ( *command && ! isspace ( *command ) ) {
|
||||
command++;
|
||||
}
|
||||
}
|
||||
return argc;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process next command only if previous command succeeded
|
||||
*
|
||||
* @v rc Status of previous command
|
||||
* @ret process Process next command
|
||||
*/
|
||||
static int process_on_success ( int rc ) {
|
||||
return ( rc == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process next command only if previous command failed
|
||||
*
|
||||
* @v rc Status of previous command
|
||||
* @ret process Process next command
|
||||
*/
|
||||
static int process_on_failure ( int rc ) {
|
||||
return ( rc != 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find command terminator
|
||||
*
|
||||
* @v tokens Token list
|
||||
* @ret process_next "Should next command be processed?" function
|
||||
* @ret argc Argument count
|
||||
*/
|
||||
static int command_terminator ( char **tokens,
|
||||
int ( **process_next ) ( int rc ) ) {
|
||||
unsigned int i;
|
||||
|
||||
/* Find first terminating token */
|
||||
for ( i = 0 ; tokens[i] ; i++ ) {
|
||||
if ( tokens[i][0] == '#' ) {
|
||||
/* Start of a comment */
|
||||
break;
|
||||
} else if ( strcmp ( tokens[i], "||" ) == 0 ) {
|
||||
/* Short-circuit logical OR */
|
||||
*process_next = process_on_failure;
|
||||
return i;
|
||||
} else if ( strcmp ( tokens[i], "&&" ) == 0 ) {
|
||||
/* Short-circuit logical AND */
|
||||
*process_next = process_on_success;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of token list */
|
||||
*process_next = NULL;
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set shell stop state
|
||||
*
|
||||
* @v stop Shell stop state
|
||||
*/
|
||||
void shell_stop ( int stop ) {
|
||||
stop_state = stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test and consume shell stop state
|
||||
*
|
||||
* @v stop Shell stop state to consume
|
||||
* @v stopped Shell had been stopped
|
||||
*/
|
||||
int shell_stopped ( int stop ) {
|
||||
int stopped;
|
||||
|
||||
/* Test to see if we need to stop */
|
||||
stopped = ( stop_state >= stop );
|
||||
|
||||
/* Consume stop state */
|
||||
if ( stop_state <= stop )
|
||||
stop_state = 0;
|
||||
|
||||
return stopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute command line
|
||||
*
|
||||
* @v command Command line
|
||||
* @ret rc Command exit status
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Execute the named command and arguments.
|
||||
*/
|
||||
int system ( const char *command ) {
|
||||
char *args;
|
||||
int ( * process_next ) ( int rc );
|
||||
char *expcmd;
|
||||
char **argv;
|
||||
int argc;
|
||||
int count;
|
||||
int process;
|
||||
int rc = 0;
|
||||
|
||||
/* Perform variable expansion */
|
||||
args = expand_command ( command );
|
||||
if ( ! args )
|
||||
expcmd = expand_command ( command );
|
||||
if ( ! expcmd )
|
||||
return -ENOMEM;
|
||||
|
||||
/* Count arguments */
|
||||
argc = split_args ( args, NULL );
|
||||
/* Count tokens */
|
||||
count = split_command ( expcmd, NULL );
|
||||
|
||||
/* Create argv array and execute command */
|
||||
if ( argc ) {
|
||||
char * argv[argc + 1];
|
||||
/* Create token array */
|
||||
if ( count ) {
|
||||
char * tokens[count + 1];
|
||||
|
||||
split_args ( args, argv );
|
||||
argv[argc] = NULL;
|
||||
split_command ( expcmd, tokens );
|
||||
tokens[count] = NULL;
|
||||
process = 1;
|
||||
|
||||
if ( argv[0][0] != '#' )
|
||||
rc = execv ( argv[0], argv );
|
||||
for ( argv = tokens ; ; argv += ( argc + 1 ) ) {
|
||||
|
||||
/* Find command terminator */
|
||||
argc = command_terminator ( argv, &process_next );
|
||||
|
||||
/* Execute command */
|
||||
if ( process ) {
|
||||
argv[argc] = NULL;
|
||||
rc = execv ( argv[0], argv );
|
||||
}
|
||||
|
||||
/* Stop processing, if applicable */
|
||||
if ( shell_stopped ( SHELL_STOP_COMMAND ) )
|
||||
break;
|
||||
|
||||
/* Stop processing if we have reached the end
|
||||
* of the command.
|
||||
*/
|
||||
if ( ! process_next )
|
||||
break;
|
||||
|
||||
/* Determine whether or not to process next command */
|
||||
process = process_next ( rc );
|
||||
}
|
||||
}
|
||||
|
||||
free ( args );
|
||||
/* Free expanded command */
|
||||
free ( expcmd );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "echo" command
|
||||
* "echo" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int echo_exec ( int argc, char **argv ) {
|
||||
int i;
|
||||
@@ -249,3 +363,84 @@ struct command echo_command __command = {
|
||||
.name = "echo",
|
||||
.exec = echo_exec,
|
||||
};
|
||||
|
||||
/** "exit" options */
|
||||
struct exit_options {};
|
||||
|
||||
/** "exit" option list */
|
||||
static struct option_descriptor exit_opts[] = {};
|
||||
|
||||
/** "exit" command descriptor */
|
||||
static struct command_descriptor exit_cmd =
|
||||
COMMAND_DESC ( struct exit_options, exit_opts, 0, 1,
|
||||
"[<status>]", "" );
|
||||
|
||||
/**
|
||||
* "exit" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int exit_exec ( int argc, char **argv ) {
|
||||
struct exit_options opts;
|
||||
unsigned int exit_code = 0;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &exit_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse exit status, if present */
|
||||
if ( optind != argc ) {
|
||||
if ( ( rc = parse_integer ( argv[optind], &exit_code ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Stop shell processing */
|
||||
shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
/** "exit" command */
|
||||
struct command exit_command __command = {
|
||||
.name = "exit",
|
||||
.exec = exit_exec,
|
||||
};
|
||||
|
||||
/** "isset" options */
|
||||
struct isset_options {};
|
||||
|
||||
/** "isset" option list */
|
||||
static struct option_descriptor isset_opts[] = {};
|
||||
|
||||
/** "isset" command descriptor */
|
||||
static struct command_descriptor isset_cmd =
|
||||
COMMAND_DESC ( struct isset_options, isset_opts, 0, MAX_ARGUMENTS,
|
||||
"[...]", "" );
|
||||
|
||||
/**
|
||||
* "isset" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int isset_exec ( int argc, char **argv ) {
|
||||
struct isset_options opts;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &isset_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Return success iff any arguments exist */
|
||||
return ( ( optind == argc ) ? -ENOENT : 0 );
|
||||
}
|
||||
|
||||
/** "isset" command */
|
||||
struct command isset_command __command = {
|
||||
.name = "isset",
|
||||
.exec = isset_exec,
|
||||
};
|
||||
|
||||
+106
-38
@@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <string.h>
|
||||
#include <ipxe/init.h>
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/io.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -30,12 +31,30 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
enum {
|
||||
/** Constant for identifying valid trace buffers */
|
||||
fnrec_magic = 'f' << 24 | 'n' << 16 | 'r' << 8 | 'e',
|
||||
/** Constant for identifying valid trace buffers */
|
||||
#define FNREC_MAGIC ( 'f' << 24 | 'n' << 16 | 'r' << 8 | 'e' )
|
||||
|
||||
/** Trace buffer length */
|
||||
fnrec_buffer_length = 4096 / sizeof ( unsigned long ),
|
||||
/** Number of trace buffer entries */
|
||||
#define FNREC_NUM_ENTRIES 4096
|
||||
|
||||
/** Trace buffer physical address
|
||||
*
|
||||
* Fixed at 17MB
|
||||
*/
|
||||
#define FNREC_PHYS_ADDRESS ( 17 * 1024 * 1024 )
|
||||
|
||||
/** A trace buffer entry */
|
||||
struct fnrec_entry {
|
||||
/** Called function address */
|
||||
void *called_fn;
|
||||
/** Call site */
|
||||
void *call_site;
|
||||
/** Entry count */
|
||||
uint16_t entry_count;
|
||||
/** Exit count */
|
||||
uint16_t exit_count;
|
||||
/** Checksum */
|
||||
unsigned long checksum;
|
||||
};
|
||||
|
||||
/** A trace buffer */
|
||||
@@ -44,10 +63,11 @@ struct fnrec_buffer {
|
||||
uint32_t magic;
|
||||
|
||||
/** Next trace buffer entry to fill */
|
||||
uint32_t idx;
|
||||
unsigned int idx;
|
||||
|
||||
/** Function address trace buffer */
|
||||
unsigned long data[fnrec_buffer_length];
|
||||
/** Trace buffer */
|
||||
struct fnrec_entry data[FNREC_NUM_ENTRIES]
|
||||
__attribute__ (( aligned ( 64 ) ));
|
||||
};
|
||||
|
||||
/** The trace buffer */
|
||||
@@ -59,7 +79,15 @@ static struct fnrec_buffer *fnrec_buffer;
|
||||
* @ret is_valid Buffer is valid
|
||||
*/
|
||||
static int fnrec_is_valid ( void ) {
|
||||
return fnrec_buffer && fnrec_buffer->magic == fnrec_magic;
|
||||
return ( fnrec_buffer && ( fnrec_buffer->magic == FNREC_MAGIC ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the trace buffer
|
||||
*
|
||||
*/
|
||||
static void fnrec_invalidate ( void ) {
|
||||
fnrec_buffer->magic = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,43 +95,64 @@ static int fnrec_is_valid ( void ) {
|
||||
*/
|
||||
static void fnrec_reset ( void ) {
|
||||
memset ( fnrec_buffer, 0, sizeof ( *fnrec_buffer ) );
|
||||
fnrec_buffer->magic = fnrec_magic;
|
||||
fnrec_buffer->magic = FNREC_MAGIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to the end of the buffer if it is not a repetition
|
||||
* Append an entry to the trace buffer
|
||||
*
|
||||
* @v l Value to append
|
||||
* @v called_fn Called function
|
||||
* @v call_site Call site
|
||||
* @ret entry Trace buffer entry
|
||||
*/
|
||||
static void fnrec_append_unique ( unsigned long l ) {
|
||||
static unsigned long lastval;
|
||||
uint32_t idx = fnrec_buffer->idx;
|
||||
static struct fnrec_entry * fnrec_append ( void *called_fn, void *call_site ) {
|
||||
struct fnrec_entry *entry;
|
||||
|
||||
/* Avoid recording the same value repeatedly */
|
||||
if ( l == lastval )
|
||||
return;
|
||||
/* Re-use existing entry, if possible */
|
||||
entry = &fnrec_buffer->data[ fnrec_buffer->idx ];
|
||||
if ( ( entry->called_fn == called_fn ) &&
|
||||
( entry->call_site == call_site ) &&
|
||||
( entry->entry_count >= entry->exit_count ) ) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
fnrec_buffer->data[idx] = l;
|
||||
fnrec_buffer->idx = ( idx + 1 ) % fnrec_buffer_length;
|
||||
lastval = l;
|
||||
/* Otherwise, create a new entry */
|
||||
fnrec_buffer->idx = ( ( fnrec_buffer->idx + 1 ) % FNREC_NUM_ENTRIES );
|
||||
entry = &fnrec_buffer->data[ fnrec_buffer->idx ];
|
||||
entry->called_fn = called_fn;
|
||||
entry->call_site = call_site;
|
||||
entry->entry_count = 0;
|
||||
entry->exit_count = 0;
|
||||
entry->checksum = ( ( ( unsigned long ) called_fn ) ^
|
||||
( ( unsigned long ) call_site ) );
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the contents of the trace buffer in chronological order
|
||||
*/
|
||||
static void fnrec_dump ( void ) {
|
||||
size_t i;
|
||||
|
||||
if ( !fnrec_is_valid() ) {
|
||||
printf ( "fnrec buffer not found\n" );
|
||||
return;
|
||||
}
|
||||
struct fnrec_entry *entry;
|
||||
unsigned int i;
|
||||
unsigned int idx;
|
||||
unsigned long checksum;
|
||||
|
||||
printf ( "fnrec buffer dump:\n" );
|
||||
for ( i = 0; i < fnrec_buffer_length; i++ ) {
|
||||
unsigned long l = fnrec_buffer->data[
|
||||
( fnrec_buffer->idx + i ) % fnrec_buffer_length];
|
||||
printf ( "%08lx%c", l, i % 8 == 7 ? '\n' : ' ' );
|
||||
for ( i = 1 ; i <= FNREC_NUM_ENTRIES ; i++ ) {
|
||||
idx = ( ( fnrec_buffer->idx + i ) % FNREC_NUM_ENTRIES );
|
||||
entry = &fnrec_buffer->data[idx];
|
||||
if ( ( entry->entry_count == 0 ) && ( entry->exit_count == 0 ) )
|
||||
continue;
|
||||
checksum = ( ( ( ( unsigned long ) entry->called_fn ) ^
|
||||
( ( unsigned long ) entry->call_site ) ) +
|
||||
entry->entry_count + entry->exit_count );
|
||||
printf ( "%p %p %d %d", entry->called_fn, entry->call_site,
|
||||
entry->entry_count, entry->exit_count );
|
||||
if ( entry->checksum != checksum ) {
|
||||
printf ( " (checksum wrong at phys %08lx)",
|
||||
virt_to_phys ( entry ) );
|
||||
}
|
||||
printf ( "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +160,14 @@ static void fnrec_dump ( void ) {
|
||||
* Function tracer initialisation function
|
||||
*/
|
||||
static void fnrec_init ( void ) {
|
||||
/* Hardcoded to 17 MB */
|
||||
fnrec_buffer = phys_to_virt ( 17 * 1024 * 1024 );
|
||||
fnrec_dump();
|
||||
|
||||
fnrec_buffer = phys_to_virt ( FNREC_PHYS_ADDRESS );
|
||||
if ( fnrec_is_valid() ) {
|
||||
fnrec_invalidate();
|
||||
fnrec_dump();
|
||||
} else {
|
||||
printf ( "fnrec buffer not found\n" );
|
||||
}
|
||||
fnrec_reset();
|
||||
}
|
||||
|
||||
@@ -125,10 +179,24 @@ struct init_fn fnrec_init_fn __init_fn ( INIT_NORMAL ) = {
|
||||
* These functions are called from every C function. The compiler inserts
|
||||
* these calls when -finstrument-functions is used.
|
||||
*/
|
||||
void __cyg_profile_func_enter ( void *called_fn, void *call_site __unused ) {
|
||||
if ( fnrec_is_valid() )
|
||||
fnrec_append_unique ( ( unsigned long ) called_fn );
|
||||
void __cyg_profile_func_enter ( void *called_fn, void *call_site ) {
|
||||
struct fnrec_entry *entry;
|
||||
|
||||
if ( fnrec_is_valid() ) {
|
||||
entry = fnrec_append ( called_fn, call_site );
|
||||
entry->entry_count++;
|
||||
entry->checksum++;
|
||||
mb();
|
||||
}
|
||||
}
|
||||
|
||||
void __cyg_profile_func_exit ( void *called_fn __unused, void *call_site __unused ) {
|
||||
void __cyg_profile_func_exit ( void *called_fn, void *call_site ) {
|
||||
struct fnrec_entry *entry;
|
||||
|
||||
if ( fnrec_is_valid() ) {
|
||||
entry = fnrec_append ( called_fn, call_site );
|
||||
entry->exit_count++;
|
||||
entry->checksum++;
|
||||
mb();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <assert.h>
|
||||
#include <ipxe/serial.h>
|
||||
#include <ipxe/gdbstub.h>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
+22
-9
@@ -197,15 +197,14 @@ static struct settings_operations nvo_settings_operations = {
|
||||
*
|
||||
* @v nvo Non-volatile options block
|
||||
* @v nvs Underlying non-volatile storage device
|
||||
* @v fragments List of option-containing fragments
|
||||
* @v fragments List of option-containing fragments, or NULL
|
||||
* @v refcnt Containing object reference counter, or NULL
|
||||
*/
|
||||
void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
|
||||
struct nvo_fragment *fragments, struct refcnt *refcnt ) {
|
||||
nvo->nvs = nvs;
|
||||
nvo->fragments = fragments;
|
||||
settings_init ( &nvo->settings, &nvo_settings_operations, refcnt,
|
||||
"nvo", 0 );
|
||||
settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,24 +218,38 @@ int register_nvo ( struct nvo_block *nvo, struct settings *parent ) {
|
||||
struct nvo_fragment *fragment = nvo->fragments;
|
||||
int rc;
|
||||
|
||||
/* Calculate total length of all fragments */
|
||||
for ( fragment = nvo->fragments ; fragment->len ; fragment++ )
|
||||
nvo->total_len += fragment->len;
|
||||
/* Calculate total length of all fragments, if applicable */
|
||||
if ( fragment ) {
|
||||
for ( ; fragment->len ; fragment++ )
|
||||
nvo->total_len += fragment->len;
|
||||
} else {
|
||||
nvo->total_len = nvo->nvs->size;
|
||||
}
|
||||
|
||||
/* Allocate memory for options and read in from NVS */
|
||||
nvo->data = malloc ( nvo->total_len );
|
||||
/* Allocate memory for options (and fragment list, if applicable) */
|
||||
nvo->data = zalloc ( nvo->total_len +
|
||||
( fragment ? 0 : ( 2 * sizeof ( *fragment ) ) ) );
|
||||
if ( ! nvo->data ) {
|
||||
DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
|
||||
nvo, nvo->total_len );
|
||||
rc = -ENOMEM;
|
||||
goto err_malloc;
|
||||
}
|
||||
|
||||
/* Create fragment list, if applicable */
|
||||
if ( ! fragment ) {
|
||||
fragment = ( nvo->data + nvo->total_len );
|
||||
fragment->len = nvo->total_len;
|
||||
nvo->fragments = fragment;
|
||||
}
|
||||
|
||||
/* Read data from NVS */
|
||||
if ( ( rc = nvo_load ( nvo ) ) != 0 )
|
||||
goto err_load;
|
||||
|
||||
/* Verify and register options */
|
||||
nvo_init_dhcpopts ( nvo );
|
||||
if ( ( rc = register_settings ( &nvo->settings, parent ) ) != 0 )
|
||||
if ( ( rc = register_settings ( &nvo->settings, parent, "nvo" ) ) != 0 )
|
||||
goto err_register;
|
||||
|
||||
DBGC ( nvo, "NVO %p registered\n", nvo );
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Command line option parsing
|
||||
*
|
||||
*/
|
||||
|
||||
/** Return status code for "--help" option */
|
||||
#define ECANCELED_NO_OP __einfo_error ( EINFO_ECANCELED_NO_OP )
|
||||
#define EINFO_ECANCELED_NO_OP \
|
||||
__einfo_uniqify ( EINFO_ECANCELED, 0x01, "Nothing to do" )
|
||||
|
||||
/**
|
||||
* Parse string value
|
||||
*
|
||||
* @v text Text
|
||||
* @ret value String value
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int parse_string ( const char *text, const char **value ) {
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Parse string */
|
||||
*value = text;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse integer value
|
||||
*
|
||||
* @v text Text
|
||||
* @ret value Integer value
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int parse_integer ( const char *text, unsigned int *value ) {
|
||||
char *endp;
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Parse integer */
|
||||
*value = strtoul ( text, &endp, 0 );
|
||||
if ( *endp ) {
|
||||
printf ( "\"%s\": invalid integer value\n", text );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse network device name
|
||||
*
|
||||
* @v text Text
|
||||
* @ret netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int parse_netdev ( const char *text, struct net_device **netdev ) {
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Find network device */
|
||||
*netdev = find_netdev ( text );
|
||||
if ( ! *netdev ) {
|
||||
printf ( "\"%s\": no such network device\n", text );
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse image name
|
||||
*
|
||||
* @v text Text
|
||||
* @ret image Image
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int parse_image ( const char *text, struct image **image ) {
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Find network device */
|
||||
*image = find_image ( text );
|
||||
if ( ! *image ) {
|
||||
printf ( "\"%s\": no such image\n", text );
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage message
|
||||
*
|
||||
* @v cmd Command descriptor
|
||||
* @v argv Argument list
|
||||
*/
|
||||
void print_usage ( struct command_descriptor *cmd, char **argv ) {
|
||||
printf ( "Usage:\n\n %s %s\n", argv[0], cmd->usage_description );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line options
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @v cmd Command descriptor
|
||||
* @v opts Options
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int parse_options ( int argc, char **argv, struct command_descriptor *cmd,
|
||||
void *opts ) {
|
||||
struct option longopts[ cmd->num_options + 1 /* help */ + 1 /* end */ ];
|
||||
char shortopts[ cmd->num_options * 3 /* possible "::" */ + 1 /* "h" */
|
||||
+ 1 /* NUL */ ];
|
||||
unsigned int shortopt_idx = 0;
|
||||
int ( * parse ) ( const char *text, void *value );
|
||||
void *value;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int num_args;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Construct long and short option lists for getopt_long() */
|
||||
memset ( longopts, 0, sizeof ( longopts ) );
|
||||
for ( i = 0 ; i < cmd->num_options ; i++ ) {
|
||||
longopts[i].name = cmd->options[i].longopt;
|
||||
longopts[i].has_arg = cmd->options[i].has_arg;
|
||||
longopts[i].val = cmd->options[i].shortopt;
|
||||
shortopts[shortopt_idx++] = cmd->options[i].shortopt;
|
||||
assert ( cmd->options[i].has_arg <= optional_argument );
|
||||
for ( j = cmd->options[i].has_arg ; j > 0 ; j-- )
|
||||
shortopts[shortopt_idx++] = ':';
|
||||
}
|
||||
longopts[i].name = "help";
|
||||
longopts[i].val = 'h';
|
||||
shortopts[shortopt_idx++] = 'h';
|
||||
shortopts[shortopt_idx++] = '\0';
|
||||
assert ( shortopt_idx <= sizeof ( shortopts ) );
|
||||
DBGC ( cmd, "Command \"%s\" has options \"%s\", %d-%d args, len %d\n",
|
||||
argv[0], shortopts, cmd->min_args, cmd->max_args, cmd->len );
|
||||
|
||||
/* Clear options */
|
||||
memset ( opts, 0, cmd->len );
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, shortopts, longopts,
|
||||
NULL ) ) >= 0 ) {
|
||||
switch ( c ) {
|
||||
case 'h' :
|
||||
/* Print help */
|
||||
print_usage ( cmd, argv );
|
||||
return -ECANCELED_NO_OP;
|
||||
case '?' :
|
||||
case ':' :
|
||||
/* Print usage message */
|
||||
print_usage ( cmd, argv );
|
||||
return -EINVAL;
|
||||
default:
|
||||
/* Search for an option to parse */
|
||||
for ( i = 0 ; i < cmd->num_options ; i++ ) {
|
||||
if ( c != cmd->options[i].shortopt )
|
||||
continue;
|
||||
parse = cmd->options[i].parse;
|
||||
value = ( opts + cmd->options[i].offset );
|
||||
if ( ( rc = parse ( optarg, value ) ) != 0 )
|
||||
return rc;
|
||||
break;
|
||||
}
|
||||
assert ( i < cmd->num_options );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check remaining arguments */
|
||||
num_args = ( argc - optind );
|
||||
if ( ( num_args < cmd->min_args ) || ( num_args > cmd->max_args ) ) {
|
||||
print_usage ( cmd, argv );
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -25,6 +25,9 @@
|
||||
* at some point. If there's anything obvious or better, not-so-obvious,
|
||||
* please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pcmcia.h>
|
||||
#include <i82365.h>
|
||||
|
||||
+32
-11
@@ -281,9 +281,9 @@ static struct settings * autovivify_child_settings ( struct settings *parent,
|
||||
return NULL;
|
||||
}
|
||||
memcpy ( new_child->name, name, sizeof ( new_child->name ) );
|
||||
generic_settings_init ( &new_child->generic, NULL, new_child->name );
|
||||
generic_settings_init ( &new_child->generic, NULL );
|
||||
settings = &new_child->generic.settings;
|
||||
register_settings ( settings, parent );
|
||||
register_settings ( settings, parent, new_child->name );
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -422,9 +422,11 @@ static void reprioritise_settings ( struct settings *settings ) {
|
||||
*
|
||||
* @v settings Settings block
|
||||
* @v parent Parent settings block, or NULL
|
||||
* @v name Settings block name
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int register_settings ( struct settings *settings, struct settings *parent ) {
|
||||
int register_settings ( struct settings *settings, struct settings *parent,
|
||||
const char *name ) {
|
||||
struct settings *old_settings;
|
||||
|
||||
/* NULL parent => add to settings root */
|
||||
@@ -432,6 +434,9 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
|
||||
if ( parent == NULL )
|
||||
parent = &settings_root;
|
||||
|
||||
/* Apply settings block name */
|
||||
settings->name = name;
|
||||
|
||||
/* Remove any existing settings with the same name */
|
||||
if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
|
||||
unregister_settings ( old_settings );
|
||||
@@ -641,6 +646,29 @@ int fetch_string_setting_copy ( struct settings *settings,
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch value of IPv4 address setting
|
||||
*
|
||||
* @v settings Settings block, or NULL to search all blocks
|
||||
* @v setting Setting to fetch
|
||||
* @v inp IPv4 addresses to fill in
|
||||
* @v count Maximum number of IPv4 addresses
|
||||
* @ret len Length of setting, or negative error
|
||||
*/
|
||||
int fetch_ipv4_array_setting ( struct settings *settings,
|
||||
struct setting *setting,
|
||||
struct in_addr *inp, unsigned int count ) {
|
||||
int len;
|
||||
|
||||
len = fetch_setting ( settings, setting, inp,
|
||||
( sizeof ( *inp ) * count ) );
|
||||
if ( len < 0 )
|
||||
return len;
|
||||
if ( ( len % sizeof ( *inp ) ) != 0 )
|
||||
return -ERANGE;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch value of IPv4 address setting
|
||||
*
|
||||
@@ -651,14 +679,7 @@ int fetch_string_setting_copy ( struct settings *settings,
|
||||
*/
|
||||
int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
|
||||
struct in_addr *inp ) {
|
||||
int len;
|
||||
|
||||
len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
|
||||
if ( len < 0 )
|
||||
return len;
|
||||
if ( len < ( int ) sizeof ( *inp ) )
|
||||
return -ERANGE;
|
||||
return len;
|
||||
return fetch_ipv4_array_setting ( settings, setting, inp, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
/*
|
||||
* stupid library routines.. The optimized versions should generally be found
|
||||
* as inline code in <asm-xx/string.h>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/**
|
||||
* AES implementation - this is a small code version. There are much faster
|
||||
* versions around but they are much larger in size (i.e. they use large
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef BIGINT_HEADER
|
||||
#define BIGINT_HEADER
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/**
|
||||
* @file crypto.h
|
||||
*/
|
||||
|
||||
@@ -103,13 +103,18 @@ static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) {
|
||||
*
|
||||
* @v ipaddr IP address field
|
||||
* @v setting Configuration setting
|
||||
* @v tag DHCP option tag
|
||||
* @v count Maximum number of IP addresses
|
||||
*/
|
||||
static void ibft_set_ipaddr_setting ( struct ibft_ipaddr *ipaddr,
|
||||
struct setting *setting ) {
|
||||
struct in_addr in;
|
||||
fetch_ipv4_setting ( NULL, setting, &in );
|
||||
ibft_set_ipaddr ( ipaddr, in );
|
||||
struct setting *setting,
|
||||
unsigned int count ) {
|
||||
struct in_addr in[count];
|
||||
unsigned int i;
|
||||
|
||||
fetch_ipv4_array_setting ( NULL, setting, in, count );
|
||||
for ( i = 0 ; i < count ; i++ ) {
|
||||
ibft_set_ipaddr ( &ipaddr[i], in[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,12 +238,15 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
|
||||
IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
|
||||
|
||||
/* Extract values from configuration settings */
|
||||
ibft_set_ipaddr_setting ( &nic->ip_address, &ip_setting );
|
||||
ibft_set_ipaddr_setting ( &nic->ip_address, &ip_setting, 1 );
|
||||
DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
|
||||
ibft_set_ipaddr_setting ( &nic->gateway, &gateway_setting );
|
||||
ibft_set_ipaddr_setting ( &nic->gateway, &gateway_setting, 1 );
|
||||
DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
|
||||
ibft_set_ipaddr_setting ( &nic->dns[0], &dns_setting );
|
||||
DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) );
|
||||
ibft_set_ipaddr_setting ( &nic->dns[0], &dns_setting,
|
||||
( sizeof ( nic->dns ) /
|
||||
sizeof ( nic->dns[0] ) ) );
|
||||
DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) );
|
||||
DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
|
||||
if ( ( rc = ibft_set_string_setting ( strings, &nic->hostname,
|
||||
&hostname_setting ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
+17
-19
@@ -64,8 +64,9 @@ static unsigned long pci_bar ( struct pci_device *pci, unsigned int reg ) {
|
||||
if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
|
||||
return ( ( ( uint64_t ) high << 32 ) | low );
|
||||
} else {
|
||||
DBG ( "Unhandled 64-bit BAR %08x%08x\n",
|
||||
high, low );
|
||||
DBGC ( pci, PCI_FMT " unhandled 64-bit BAR "
|
||||
"%08x%08x\n",
|
||||
PCI_ARGS ( pci ), high, low );
|
||||
return PCI_BASE_ADDRESS_MEM_TYPE_64;
|
||||
}
|
||||
}
|
||||
@@ -148,19 +149,16 @@ void adjust_pci_device ( struct pci_device *pci ) {
|
||||
new_command = ( pci_command | PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_MEM | PCI_COMMAND_IO );
|
||||
if ( pci_command != new_command ) {
|
||||
DBG ( "PCI BIOS has not enabled device %02x:%02x.%x! "
|
||||
"Updating PCI command %04x->%04x\n", pci->bus,
|
||||
PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ),
|
||||
pci_command, new_command );
|
||||
DBGC ( pci, PCI_FMT " device not enabled by BIOS! Updating "
|
||||
"PCI command %04x->%04x\n",
|
||||
PCI_ARGS ( pci ), pci_command, new_command );
|
||||
pci_write_config_word ( pci, PCI_COMMAND, new_command );
|
||||
}
|
||||
|
||||
pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
|
||||
if ( pci_latency < 32 ) {
|
||||
DBG ( "PCI device %02x:%02x.%x latency timer is unreasonably "
|
||||
"low at %d. Setting to 32.\n", pci->bus,
|
||||
PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ),
|
||||
pci_latency );
|
||||
DBGC ( pci, PCI_FMT " latency timer is unreasonably low at "
|
||||
"%d. Setting to 32.\n", PCI_ARGS ( pci ), pci_latency );
|
||||
pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
|
||||
}
|
||||
}
|
||||
@@ -180,10 +178,9 @@ static int pci_probe ( struct pci_device *pci ) {
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
DBG ( "Adding PCI device %02x:%02x.%x (%04x:%04x mem %lx io %lx "
|
||||
"irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ),
|
||||
PCI_FUNC ( pci->devfn ), pci->vendor, pci->device,
|
||||
pci->membase, pci->ioaddr, pci->irq );
|
||||
DBGC ( pci, PCI_FMT " is %04x:%04x mem %lx io %lx irq %d\n",
|
||||
PCI_ARGS ( pci ), pci->vendor, pci->device, pci->membase,
|
||||
pci->ioaddr, pci->irq );
|
||||
|
||||
for_each_table_entry ( driver, PCI_DRIVERS ) {
|
||||
for ( i = 0 ; i < driver->id_count ; i++ ) {
|
||||
@@ -196,16 +193,18 @@ static int pci_probe ( struct pci_device *pci ) {
|
||||
continue;
|
||||
pci->driver = driver;
|
||||
pci->driver_name = id->name;
|
||||
DBG ( "...using driver %s\n", pci->driver_name );
|
||||
DBGC ( pci, "...using driver %s\n", pci->driver_name );
|
||||
if ( ( rc = driver->probe ( pci, id ) ) != 0 ) {
|
||||
DBG ( "......probe failed\n" );
|
||||
DBGC ( pci, "......probe failed: %s\n",
|
||||
strerror ( rc ) );
|
||||
continue;
|
||||
}
|
||||
DBGC ( pci, PCI_FMT " added\n", PCI_ARGS ( pci ) );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DBG ( "...no driver found\n" );
|
||||
DBGC ( pci, "...no driver found\n" );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
@@ -216,8 +215,7 @@ static int pci_probe ( struct pci_device *pci ) {
|
||||
*/
|
||||
static void pci_remove ( struct pci_device *pci ) {
|
||||
pci->driver->remove ( pci );
|
||||
DBG ( "Removed PCI device %02x:%02x.%x\n", pci->bus,
|
||||
PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ) );
|
||||
DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <byteswap.h>
|
||||
#include <ipxe/pci.h>
|
||||
#include <ipxe/isapnp.h>
|
||||
#include <ipxe/pcivpd.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* PCI Vital Product Data
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise PCI Vital Product Data
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v pci PCI device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int pci_vpd_init ( struct pci_vpd *vpd, struct pci_device *pci ) {
|
||||
|
||||
/* Initialise structure */
|
||||
vpd->pci = pci;
|
||||
pci_vpd_invalidate_cache ( vpd );
|
||||
|
||||
/* Locate VPD capability */
|
||||
vpd->cap = pci_find_capability ( pci, PCI_CAP_ID_VPD );
|
||||
if ( ! vpd->cap ) {
|
||||
DBGC ( vpd, PCI_FMT " does not support VPD\n",
|
||||
PCI_ARGS ( pci ) );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
DBGC ( vpd, PCI_FMT " VPD is at offset %02x\n",
|
||||
PCI_ARGS ( pci ), vpd->cap );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one dword of PCI Vital Product Data
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v address Address to read
|
||||
* @ret data Read data
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int pci_vpd_read_dword ( struct pci_vpd *vpd, int address,
|
||||
uint32_t *data ) {
|
||||
struct pci_device *pci = vpd->pci;
|
||||
unsigned int cap = vpd->cap;
|
||||
unsigned int retries;
|
||||
uint16_t flag;
|
||||
|
||||
/* Return cached value, if present */
|
||||
if ( pci_vpd_cache_is_valid ( vpd ) &&
|
||||
( vpd->cache.address == address ) ) {
|
||||
*data = vpd->cache.data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initiate read */
|
||||
pci_write_config_word ( pci, ( cap + PCI_VPD_ADDRESS ), address );
|
||||
|
||||
/* Wait for read to complete */
|
||||
for ( retries = 0 ; retries < PCI_VPD_MAX_WAIT_MS ; retries++ ) {
|
||||
|
||||
/* Check if data is ready */
|
||||
pci_read_config_word ( pci, ( cap + PCI_VPD_ADDRESS ), &flag );
|
||||
if ( flag & PCI_VPD_FLAG ) {
|
||||
|
||||
/* Read data */
|
||||
pci_read_config_dword ( pci, ( cap + PCI_VPD_DATA ),
|
||||
data );
|
||||
DBGC2 ( vpd, PCI_FMT " VPD %04x => %08x\n",
|
||||
PCI_ARGS ( pci ), address, htonl ( *data ) );
|
||||
|
||||
/* Populate cache */
|
||||
vpd->cache.address = address;
|
||||
vpd->cache.data = *data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait 1ms before retrying */
|
||||
mdelay ( 1 );
|
||||
}
|
||||
|
||||
DBGC ( vpd, PCI_FMT " VPD %04x read via %02x timed out\n",
|
||||
PCI_ARGS ( pci ), address, cap );
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one dword of PCI Vital Product Data
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v address Address to write
|
||||
* @v data Data to write
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int pci_vpd_write_dword ( struct pci_vpd *vpd, int address,
|
||||
uint32_t data ) {
|
||||
struct pci_device *pci = vpd->pci;
|
||||
unsigned int cap = vpd->cap;
|
||||
unsigned int retries;
|
||||
uint16_t flag;
|
||||
|
||||
/* Invalidate cache */
|
||||
pci_vpd_invalidate_cache ( vpd );
|
||||
|
||||
DBGC2 ( vpd, PCI_FMT " VPD %04x <= %08x\n",
|
||||
PCI_ARGS ( pci ), address, htonl ( data ) );
|
||||
|
||||
/* Write data */
|
||||
pci_write_config_dword ( pci, ( cap + PCI_VPD_DATA ), data );
|
||||
|
||||
/* Initiate write */
|
||||
pci_write_config_word ( pci, ( cap + PCI_VPD_ADDRESS ),
|
||||
( address | PCI_VPD_FLAG ) );
|
||||
|
||||
/* Wait for write to complete */
|
||||
for ( retries = 0 ; retries < PCI_VPD_MAX_WAIT_MS ; retries++ ) {
|
||||
|
||||
/* Check if write has completed */
|
||||
pci_read_config_word ( pci, ( cap + PCI_VPD_ADDRESS ), &flag );
|
||||
if ( ! ( flag & PCI_VPD_FLAG ) )
|
||||
return 0;
|
||||
|
||||
/* Wait 1ms before retrying */
|
||||
mdelay ( 1 );
|
||||
}
|
||||
|
||||
DBGC ( vpd, PCI_FMT " VPD %04x write via %02x timed out\n",
|
||||
PCI_ARGS ( pci ), address, cap );
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read PCI VPD
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v address Starting address
|
||||
* @v buf Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int pci_vpd_read ( struct pci_vpd *vpd, unsigned int address, void *buf,
|
||||
size_t len ) {
|
||||
uint8_t *bytes = buf;
|
||||
uint32_t data;
|
||||
size_t skip_len;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
/* Calculate length to skip at start of data */
|
||||
skip_len = ( address & 0x03 );
|
||||
|
||||
/* Read data, a dword at a time */
|
||||
for ( address &= ~0x03 ; len ; address += 4 ) {
|
||||
|
||||
/* Read whole dword */
|
||||
if ( ( rc = pci_vpd_read_dword ( vpd, address, &data ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Copy data to buffer */
|
||||
for ( i = 4 ; i ; i-- ) {
|
||||
if ( skip_len ) {
|
||||
skip_len--;
|
||||
} else if ( len ) {
|
||||
*(bytes++) = data;
|
||||
len--;
|
||||
}
|
||||
data = ( ( data << 24 ) | ( data >> 8 ) );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write PCI VPD
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v address Starting address
|
||||
* @v buf Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int pci_vpd_write ( struct pci_vpd *vpd, unsigned int address, const void *buf,
|
||||
size_t len ) {
|
||||
const uint8_t *bytes = buf;
|
||||
uint32_t data;
|
||||
size_t skip_len;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
/* Calculate length to skip at start of data */
|
||||
skip_len = ( address & 0x03 );
|
||||
|
||||
/* Write data, a dword at a time */
|
||||
for ( address &= ~0x03 ; len ; address += 4 ) {
|
||||
|
||||
/* Read existing dword, if necessary */
|
||||
if ( skip_len || ( len <= 0x03 ) ) {
|
||||
if ( ( rc = pci_vpd_read_dword ( vpd, address,
|
||||
&data ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Copy data from buffer */
|
||||
for ( i = 4 ; i ; i-- ) {
|
||||
if ( skip_len ) {
|
||||
skip_len--;
|
||||
} else if ( len ) {
|
||||
data = ( ( data & ~0xff ) | *(bytes++) );
|
||||
len--;
|
||||
}
|
||||
data = ( ( data << 24 ) | ( data >> 8 ) );
|
||||
}
|
||||
|
||||
/* Write whole dword */
|
||||
if ( ( rc = pci_vpd_write_dword ( vpd, address, data ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump PCI VPD region (for debugging)
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v address Starting address
|
||||
* @v len Length of data
|
||||
*/
|
||||
static void pci_vpd_dump ( struct pci_vpd *vpd, unsigned int address,
|
||||
size_t len ) {
|
||||
int rc;
|
||||
|
||||
/* Do nothing in non-debug builds */
|
||||
if ( ! DBG_LOG )
|
||||
return;
|
||||
|
||||
/* Read data */
|
||||
{
|
||||
char buf[len];
|
||||
if ( ( rc = pci_vpd_read ( vpd, address, buf,
|
||||
sizeof ( buf ) ) ) != 0 )
|
||||
return;
|
||||
DBGC_HDA ( vpd, address, buf, sizeof ( buf ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate PCI VPD tag
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v tag ISAPnP tag
|
||||
* @ret address Address of tag body
|
||||
* @ret len Length of tag body
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int pci_vpd_find_tag ( struct pci_vpd *vpd, unsigned int tag,
|
||||
unsigned int *address, size_t *len ) {
|
||||
uint8_t read_tag;
|
||||
uint16_t read_len;
|
||||
int rc;
|
||||
|
||||
/* Scan through tags looking for a match */
|
||||
*address = 0;
|
||||
do {
|
||||
/* Read tag byte */
|
||||
if ( ( rc = pci_vpd_read ( vpd, (*address)++, &read_tag,
|
||||
sizeof ( read_tag ) ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Extract tag and length */
|
||||
if ( ISAPNP_IS_LARGE_TAG ( read_tag ) ) {
|
||||
if ( ( rc = pci_vpd_read ( vpd, *address, &read_len,
|
||||
sizeof ( read_len ) ) ) != 0)
|
||||
return rc;
|
||||
*address += sizeof ( read_len );
|
||||
read_len = le16_to_cpu ( read_len );
|
||||
read_tag = ISAPNP_LARGE_TAG_NAME ( read_tag );
|
||||
} else {
|
||||
read_len = ISAPNP_SMALL_TAG_LEN ( read_tag );
|
||||
read_tag = ISAPNP_SMALL_TAG_NAME ( read_tag );
|
||||
}
|
||||
|
||||
/* Check for tag match */
|
||||
if ( tag == read_tag ) {
|
||||
*len = read_len;
|
||||
DBGC ( vpd, PCI_FMT " VPD tag %02x is at "
|
||||
"[%04x,%04zx)\n", PCI_ARGS ( vpd->pci ), tag,
|
||||
*address, ( *address + *len ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Move to next tag */
|
||||
*address += read_len;
|
||||
|
||||
} while ( read_tag != ISAPNP_TAG_END );
|
||||
|
||||
DBGC ( vpd, PCI_FMT " VPD tag %02x not found\n",
|
||||
PCI_ARGS ( vpd->pci ), tag );
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate PCI VPD field
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @v field VPD field descriptor
|
||||
* @ret address Address of field body
|
||||
* @ret len Length of field body
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int pci_vpd_find ( struct pci_vpd *vpd, unsigned int field,
|
||||
unsigned int *address, size_t *len ) {
|
||||
struct pci_vpd_field read_field;
|
||||
int rc;
|
||||
|
||||
/* Locate containing tag */
|
||||
if ( ( rc = pci_vpd_find_tag ( vpd, PCI_VPD_TAG ( field ),
|
||||
address, len ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Return immediately if we are searching for a whole-tag field */
|
||||
if ( ! PCI_VPD_KEYWORD ( field ) ) {
|
||||
pci_vpd_dump ( vpd, *address, *len );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Scan through fields looking for a match */
|
||||
while ( *len >= sizeof ( read_field ) ) {
|
||||
|
||||
/* Read field header */
|
||||
if ( ( rc = pci_vpd_read ( vpd, *address, &read_field,
|
||||
sizeof ( read_field ) ) ) != 0 )
|
||||
return rc;
|
||||
*address += sizeof ( read_field );
|
||||
*len -= sizeof ( read_field );
|
||||
|
||||
/* Check for keyword match */
|
||||
if ( read_field.keyword == PCI_VPD_KEYWORD ( field ) ) {
|
||||
*len = read_field.len;
|
||||
DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
|
||||
" is at [%04x,%04zx)\n", PCI_ARGS ( vpd->pci ),
|
||||
PCI_VPD_FIELD_ARGS ( field ),
|
||||
*address, ( *address + *len ) );
|
||||
pci_vpd_dump ( vpd, *address, *len );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Move to next field */
|
||||
if ( read_field.len > *len )
|
||||
break;
|
||||
*address += read_field.len;
|
||||
*len -= read_field.len;
|
||||
}
|
||||
|
||||
DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " not found\n",
|
||||
PCI_ARGS ( vpd->pci ), PCI_VPD_FIELD_ARGS ( field ) );
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include "etherboot.h"
|
||||
#include "ipxe/io.h"
|
||||
#include "ipxe/virtio-ring.h"
|
||||
|
||||
@@ -38,6 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/ib_smc.h>
|
||||
#include <ipxe/if_ether.h>
|
||||
#include <ipxe/ethernet.h>
|
||||
#include <ipxe/fcoe.h>
|
||||
#include <ipxe/vlan.h>
|
||||
#include "hermon.h"
|
||||
|
||||
/**
|
||||
@@ -1647,6 +1649,7 @@ static int hermon_complete ( struct ib_device *ibdev,
|
||||
len = MLX_GET ( &cqe->normal, byte_cnt );
|
||||
assert ( len <= iob_tailroom ( iobuf ) );
|
||||
iob_put ( iobuf, len );
|
||||
memset ( &recv_av, 0, sizeof ( recv_av ) );
|
||||
switch ( qp->type ) {
|
||||
case IB_QPT_SMI:
|
||||
case IB_QPT_GSI:
|
||||
@@ -1656,7 +1659,6 @@ static int hermon_complete ( struct ib_device *ibdev,
|
||||
iob_pull ( iobuf, sizeof ( *grh ) );
|
||||
/* Construct address vector */
|
||||
av = &recv_av;
|
||||
memset ( av, 0, sizeof ( *av ) );
|
||||
av->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
|
||||
av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
|
||||
av->sl = MLX_GET ( &cqe->normal, sl );
|
||||
@@ -1667,7 +1669,10 @@ static int hermon_complete ( struct ib_device *ibdev,
|
||||
av = &qp->av;
|
||||
break;
|
||||
case IB_QPT_ETH:
|
||||
av = NULL;
|
||||
/* Construct address vector */
|
||||
av = &recv_av;
|
||||
av->vlan_present = MLX_GET ( &cqe->normal, vlan );
|
||||
av->vlan = MLX_GET ( &cqe->normal, vid );
|
||||
break;
|
||||
default:
|
||||
assert ( 0 );
|
||||
@@ -2274,9 +2279,19 @@ static void hermon_eth_complete_send ( struct ib_device *ibdev __unused,
|
||||
*/
|
||||
static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused,
|
||||
struct ib_queue_pair *qp,
|
||||
struct ib_address_vector *av __unused,
|
||||
struct ib_address_vector *av,
|
||||
struct io_buffer *iobuf, int rc ) {
|
||||
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
|
||||
struct net_device *vlan;
|
||||
|
||||
/* Find VLAN device, if applicable */
|
||||
if ( av->vlan_present ) {
|
||||
if ( ( vlan = vlan_find ( netdev, av->vlan ) ) != NULL ) {
|
||||
netdev = vlan;
|
||||
} else if ( rc == 0 ) {
|
||||
rc = -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hand off to network layer */
|
||||
if ( rc == 0 ) {
|
||||
@@ -2368,8 +2383,10 @@ static int hermon_eth_open ( struct net_device *netdev ) {
|
||||
v_pptx, 1 );
|
||||
MLX_FILL_1 ( &set_port.general, 1,
|
||||
mtu, ( ETH_FRAME_LEN + 40 /* Used by card */ ) );
|
||||
MLX_FILL_1 ( &set_port.general, 2, pptx, 1 );
|
||||
MLX_FILL_1 ( &set_port.general, 3, pprx, 1 );
|
||||
MLX_FILL_1 ( &set_port.general, 2,
|
||||
pfctx, ( 1 << FCOE_VLAN_PRIORITY ) );
|
||||
MLX_FILL_1 ( &set_port.general, 3,
|
||||
pfcrx, ( 1 << FCOE_VLAN_PRIORITY ) );
|
||||
if ( ( rc = hermon_cmd_set_port ( hermon, 1,
|
||||
( HERMON_SET_PORT_GENERAL_PARAM |
|
||||
ibdev->port ),
|
||||
|
||||
@@ -211,7 +211,7 @@ struct hermonprm_sense_port_st {
|
||||
pseudo_bit_t reserved0[0x00020];
|
||||
/* -------------- */
|
||||
pseudo_bit_t port_type[0x00002];
|
||||
pseudo_bit_t reserved1[0x00018];
|
||||
pseudo_bit_t reserved1[0x0001e];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
struct hermonprm_set_port_ib_st {
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef _ATL1E_H_
|
||||
#define _ATL1E_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _IGBVF_H_
|
||||
#define _IGBVF_H_
|
||||
|
||||
#include "igbvf_vf.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct igbvf_info;
|
||||
struct igbvf_adapter;
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
|
||||
|
||||
/* Tx/Rx descriptor defines */
|
||||
#define IGBVF_DEFAULT_TXD 256
|
||||
#define IGBVF_MAX_TXD 4096
|
||||
#define IGBVF_MIN_TXD 80
|
||||
|
||||
#define IGBVF_DEFAULT_RXD 256
|
||||
#define IGBVF_MAX_RXD 4096
|
||||
#define IGBVF_MIN_RXD 80
|
||||
|
||||
#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* RX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGBVF_RX_PTHRESH 16
|
||||
#define IGBVF_RX_HTHRESH 8
|
||||
#define IGBVF_RX_WTHRESH 1
|
||||
|
||||
#define IGBVF_TX_PTHRESH 8
|
||||
#define IGBVF_TX_HTHRESH 1
|
||||
#define IGBVF_TX_WTHRESH 1
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
#define IGBVF_FC_PAUSE_TIME 0x0680 /* 858 usec */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define IGBVF_TX_QUEUE_WAKE 32
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGBVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGBVF_EEPROM_APME 0x0400
|
||||
|
||||
#define IGBVF_MNG_VLAN_NONE (-1)
|
||||
|
||||
enum igbvf_boards {
|
||||
board_vf,
|
||||
};
|
||||
|
||||
struct igbvf_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
* wrappers around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igbvf_buffer {
|
||||
dma_addr_t dma;
|
||||
dma_addr_t page_dma;
|
||||
struct sk_buff *skb;
|
||||
union {
|
||||
/* Tx */
|
||||
struct {
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
};
|
||||
/* Rx */
|
||||
struct {
|
||||
struct page *page;
|
||||
unsigned int page_offset;
|
||||
};
|
||||
};
|
||||
struct page *page;
|
||||
};
|
||||
|
||||
struct igbvf_ring {
|
||||
struct igbvf_adapter *adapter; /* backlink */
|
||||
void *desc; /* pointer to ring memory */
|
||||
dma_addr_t dma; /* phys address of ring */
|
||||
unsigned int size; /* length of ring in bytes */
|
||||
unsigned int count; /* number of desc. in ring */
|
||||
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
u16 head;
|
||||
u16 tail;
|
||||
|
||||
/* array of buffer information structs */
|
||||
struct igbvf_buffer *buffer_info;
|
||||
#if 0
|
||||
struct napi_struct napi;
|
||||
|
||||
char name[IFNAMSIZ + 5];
|
||||
#endif
|
||||
u32 eims_value;
|
||||
u32 itr_val;
|
||||
u16 itr_register;
|
||||
int set_itr;
|
||||
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
struct igbvf_queue_stats stats;
|
||||
};
|
||||
|
||||
/* board specific private data structure */
|
||||
struct igbvf_adapter {
|
||||
#if 0
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list blink_timer;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
|
||||
const struct igbvf_info *ei;
|
||||
|
||||
struct vlan_group *vlgrp;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 polling_interval;
|
||||
u16 mng_vlan_id;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
|
||||
|
||||
/* track device up/down/testing state */
|
||||
unsigned long state;
|
||||
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
/*
|
||||
* Tx
|
||||
*/
|
||||
struct igbvf_ring *tx_ring /* One per active queue */
|
||||
____cacheline_aligned_in_smp;
|
||||
|
||||
unsigned long tx_queue_len;
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
|
||||
bool detect_tx_hung;
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
|
||||
/* Tx stats */
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u32 tx_dma_failed;
|
||||
|
||||
/*
|
||||
* Rx
|
||||
*/
|
||||
struct igbvf_ring *rx_ring;
|
||||
|
||||
/* Rx stats */
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u64 rx_hdr_split;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_dma_failed;
|
||||
|
||||
unsigned int rx_ps_hdr_size;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
spinlock_t stats_lock; /* prevent concurrent stats updates */
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
|
||||
/* The VF counters don't clear on read so we have to get a base
|
||||
* count on driver start up and always subtract that base on
|
||||
* on the first update, thus the flag..
|
||||
*/
|
||||
struct e1000_vf_stats stats;
|
||||
u64 zero_base;
|
||||
|
||||
struct igbvf_ring test_tx_ring;
|
||||
struct igbvf_ring test_rx_ring;
|
||||
u32 test_icr;
|
||||
|
||||
u32 msg_enable;
|
||||
struct msix_entry *msix_entries;
|
||||
int int_mode;
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
u32 int_counter0;
|
||||
u32 int_counter1;
|
||||
|
||||
u32 eeprom_wol;
|
||||
u32 wol;
|
||||
u32 pba;
|
||||
|
||||
bool fc_autoneg;
|
||||
|
||||
unsigned long led_status;
|
||||
|
||||
unsigned int flags;
|
||||
unsigned long last_reset;
|
||||
u32 *config_space;
|
||||
#endif
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_device *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
|
||||
u32 min_frame_size;
|
||||
u32 max_frame_size;
|
||||
|
||||
u32 max_hw_frame_size;
|
||||
|
||||
#define NUM_TX_DESC 8
|
||||
#define NUM_RX_DESC 8
|
||||
|
||||
struct io_buffer *tx_iobuf[NUM_TX_DESC];
|
||||
struct io_buffer *rx_iobuf[NUM_RX_DESC];
|
||||
|
||||
union e1000_adv_tx_desc *tx_base;
|
||||
union e1000_adv_rx_desc *rx_base;
|
||||
|
||||
uint32_t tx_ring_size;
|
||||
uint32_t rx_ring_size;
|
||||
|
||||
uint32_t tx_head;
|
||||
uint32_t tx_tail;
|
||||
uint32_t tx_fill_ctr;
|
||||
|
||||
uint32_t rx_curr;
|
||||
|
||||
uint32_t ioaddr;
|
||||
uint32_t irqno;
|
||||
|
||||
uint32_t tx_int_delay;
|
||||
uint32_t tx_abs_int_delay;
|
||||
uint32_t txd_cmd;
|
||||
};
|
||||
|
||||
struct igbvf_info {
|
||||
enum e1000_mac_type mac;
|
||||
unsigned int flags;
|
||||
u32 pba;
|
||||
void (*init_ops)(struct e1000_hw *);
|
||||
s32 (*get_variants)(struct igbvf_adapter *);
|
||||
};
|
||||
|
||||
/* hardware capability, feature, and workaround flags */
|
||||
#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
|
||||
|
||||
#define IGBVF_DESC_UNUSED(R) \
|
||||
((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
|
||||
(R)->next_to_clean - (R)->next_to_use - 1)
|
||||
|
||||
#define IGBVF_RX_DESC_ADV(R, i) \
|
||||
(&(((union e1000_adv_rx_desc *)((R).desc))[i]))
|
||||
#define IGBVF_TX_DESC_ADV(R, i) \
|
||||
(&(((union e1000_adv_tx_desc *)((R).desc))[i]))
|
||||
#define IGBVF_TX_CTXTDESC_ADV(R, i) \
|
||||
(&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
|
||||
|
||||
enum igbvf_state_t {
|
||||
__IGBVF_TESTING,
|
||||
__IGBVF_RESETTING,
|
||||
__IGBVF_DOWN
|
||||
};
|
||||
|
||||
enum latency_range {
|
||||
lowest_latency = 0,
|
||||
low_latency = 1,
|
||||
bulk_latency = 2,
|
||||
latency_invalid = 255
|
||||
};
|
||||
|
||||
extern char igbvf_driver_name[];
|
||||
extern const char igbvf_driver_version[];
|
||||
|
||||
extern void igbvf_check_options(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_set_ethtool_ops(struct net_device *netdev);
|
||||
#ifdef ETHTOOL_OPS_COMPAT
|
||||
extern int ethtool_ioctl(struct ifreq *ifr);
|
||||
#endif
|
||||
|
||||
extern int igbvf_up(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_down(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_reinit_locked(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_reset(struct igbvf_adapter *adapter);
|
||||
extern int igbvf_setup_rx_resources(struct igbvf_adapter *adapter);
|
||||
extern int igbvf_setup_tx_resources(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_free_rx_resources(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_free_tx_resources(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_update_stats(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_set_interrupt_capability(struct igbvf_adapter *adapter);
|
||||
extern void igbvf_reset_interrupt_capability(struct igbvf_adapter *adapter);
|
||||
|
||||
extern unsigned int copybreak;
|
||||
|
||||
static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
|
||||
{
|
||||
return readl(hw->hw_addr + reg);
|
||||
}
|
||||
|
||||
static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
|
||||
{
|
||||
writel(val, hw->hw_addr + reg);
|
||||
}
|
||||
#define er32(reg) E1000_READ_REG(hw, E1000_##reg)
|
||||
#define ew32(reg,val) E1000_WRITE_REG(hw, E1000_##reg, (val))
|
||||
#define e1e_flush() er32(STATUS)
|
||||
|
||||
#endif /* _IGBVF_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,955 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
Copyright(c) 2010 Eric Keller <ekeller@princeton.edu>
|
||||
Copyright(c) 2010 Red Hat Inc.
|
||||
Alex Williamson <alex.williamson@redhat.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#include "igbvf.h"
|
||||
|
||||
/**
|
||||
* igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
**/
|
||||
int igbvf_setup_tx_resources ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
DBG ( "igbvf_setup_tx_resources\n" );
|
||||
|
||||
/* Allocate transmit descriptor ring memory.
|
||||
It must not cross a 64K boundary because of hardware errata #23
|
||||
so we use malloc_dma() requesting a 128 byte block that is
|
||||
128 byte aligned. This should guarantee that the memory
|
||||
allocated will not cross a 64K boundary, because 128 is an
|
||||
even multiple of 65536 ( 65536 / 128 == 512 ), so all possible
|
||||
allocations of 128 bytes on a 128 byte boundary will not
|
||||
cross 64K bytes.
|
||||
*/
|
||||
|
||||
adapter->tx_base =
|
||||
malloc_dma ( adapter->tx_ring_size, adapter->tx_ring_size );
|
||||
|
||||
if ( ! adapter->tx_base ) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset ( adapter->tx_base, 0, adapter->tx_ring_size );
|
||||
|
||||
DBG ( "adapter->tx_base = %#08lx\n", virt_to_bus ( adapter->tx_base ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_free_tx_resources - Free Tx Resources per Queue
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Free all transmit software resources
|
||||
**/
|
||||
void igbvf_free_tx_resources ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
DBG ( "igbvf_free_tx_resources\n" );
|
||||
|
||||
free_dma ( adapter->tx_base, adapter->tx_ring_size );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_free_rx_resources - Free Rx Resources
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Free all receive software resources
|
||||
**/
|
||||
void igbvf_free_rx_resources ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
int i;
|
||||
|
||||
DBG ( "igbvf_free_rx_resources\n" );
|
||||
|
||||
free_dma ( adapter->rx_base, adapter->rx_ring_size );
|
||||
|
||||
for ( i = 0; i < NUM_RX_DESC; i++ ) {
|
||||
free_iob ( adapter->rx_iobuf[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_refill_rx_ring - allocate Rx io_buffers
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
**/
|
||||
static int igbvf_refill_rx_ring ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
int i, rx_curr;
|
||||
int rc = 0;
|
||||
union e1000_adv_rx_desc *rx_curr_desc;
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct io_buffer *iob;
|
||||
|
||||
DBGP ("igbvf_refill_rx_ring\n");
|
||||
|
||||
for ( i = 0; i < NUM_RX_DESC; i++ ) {
|
||||
rx_curr = ( ( adapter->rx_curr + i ) % NUM_RX_DESC );
|
||||
rx_curr_desc = adapter->rx_base + rx_curr;
|
||||
|
||||
if ( rx_curr_desc->wb.upper.status_error & E1000_RXD_STAT_DD )
|
||||
continue;
|
||||
|
||||
if ( adapter->rx_iobuf[rx_curr] != NULL )
|
||||
continue;
|
||||
|
||||
DBG2 ( "Refilling rx desc %d\n", rx_curr );
|
||||
|
||||
iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
|
||||
adapter->rx_iobuf[rx_curr] = iob;
|
||||
|
||||
rx_curr_desc->wb.upper.status_error = 0;
|
||||
|
||||
if ( ! iob ) {
|
||||
DBG ( "alloc_iob failed\n" );
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
} else {
|
||||
rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
|
||||
rx_curr_desc->read.hdr_addr = 0;
|
||||
ew32 ( RDT(0), rx_curr );
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_irq_disable - Mask off interrupt generation on the NIC
|
||||
* @adapter: board private structure
|
||||
**/
|
||||
static void igbvf_irq_disable ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
ew32 ( EIMC, ~0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_irq_enable - Enable default interrupt generation settings
|
||||
* @adapter: board private structure
|
||||
**/
|
||||
static void igbvf_irq_enable ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
ew32 ( EIAC, IMS_ENABLE_MASK );
|
||||
ew32 ( EIAM, IMS_ENABLE_MASK );
|
||||
ew32 ( EIMS, IMS_ENABLE_MASK );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_irq - enable or Disable interrupts
|
||||
*
|
||||
* @v adapter e1000 adapter
|
||||
* @v action requested interrupt action
|
||||
**/
|
||||
static void igbvf_irq ( struct net_device *netdev, int enable )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
|
||||
DBG ( "igbvf_irq\n" );
|
||||
|
||||
if ( enable ) {
|
||||
igbvf_irq_enable ( adapter );
|
||||
} else {
|
||||
igbvf_irq_disable ( adapter );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_process_tx_packets - process transmitted packets
|
||||
*
|
||||
* @v netdev network interface device structure
|
||||
**/
|
||||
static void igbvf_process_tx_packets ( struct net_device *netdev )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
uint32_t i;
|
||||
uint32_t tx_status;
|
||||
union e1000_adv_tx_desc *tx_curr_desc;
|
||||
|
||||
/* Check status of transmitted packets
|
||||
*/
|
||||
DBGP ( "process_tx_packets: tx_head = %d, tx_tail = %d\n", adapter->tx_head,
|
||||
adapter->tx_tail );
|
||||
|
||||
while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {
|
||||
|
||||
tx_curr_desc = ( void * ) ( adapter->tx_base ) +
|
||||
( i * sizeof ( *adapter->tx_base ) );
|
||||
|
||||
tx_status = tx_curr_desc->wb.status;
|
||||
DBG ( " tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
|
||||
DBG ( " tx_status = %#08x\n", tx_status );
|
||||
|
||||
/* if the packet at tx_head is not owned by hardware it is for us */
|
||||
if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
|
||||
break;
|
||||
|
||||
DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
|
||||
adapter->tx_head, adapter->tx_tail, tx_status );
|
||||
|
||||
netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
|
||||
DBG ( "Success transmitting packet, tx_status: %#08x\n",
|
||||
tx_status );
|
||||
|
||||
/* Decrement count of used descriptors, clear this descriptor
|
||||
*/
|
||||
adapter->tx_fill_ctr--;
|
||||
memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
|
||||
|
||||
adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_process_rx_packets - process received packets
|
||||
*
|
||||
* @v netdev network interface device structure
|
||||
**/
|
||||
static void igbvf_process_rx_packets ( struct net_device *netdev )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t i;
|
||||
uint32_t rx_status;
|
||||
uint32_t rx_len;
|
||||
uint32_t rx_err;
|
||||
union e1000_adv_rx_desc *rx_curr_desc;
|
||||
|
||||
DBGP ( "igbvf_process_rx_packets\n" );
|
||||
|
||||
/* Process received packets
|
||||
*/
|
||||
while ( 1 ) {
|
||||
i = adapter->rx_curr;
|
||||
|
||||
rx_curr_desc = ( void * ) ( adapter->rx_base ) +
|
||||
( i * sizeof ( *adapter->rx_base ) );
|
||||
rx_status = rx_curr_desc->wb.upper.status_error;
|
||||
|
||||
DBG2 ( "Before DD Check RX_status: %#08x, rx_curr: %d\n",
|
||||
rx_status, i );
|
||||
|
||||
if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
|
||||
break;
|
||||
|
||||
if ( adapter->rx_iobuf[i] == NULL )
|
||||
break;
|
||||
|
||||
DBG ( "E1000_RCTL = %#08x\n", er32 (RCTL) );
|
||||
|
||||
rx_len = rx_curr_desc->wb.upper.length;
|
||||
|
||||
DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n",
|
||||
i, rx_status, rx_len );
|
||||
|
||||
rx_err = rx_status;
|
||||
|
||||
iob_put ( adapter->rx_iobuf[i], rx_len );
|
||||
|
||||
if ( rx_err & E1000_RXDEXT_ERR_FRAME_ERR_MASK ) {
|
||||
|
||||
netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
|
||||
DBG ( "igbvf_process_rx_packets: Corrupted packet received!"
|
||||
" rx_err: %#08x\n", rx_err );
|
||||
} else {
|
||||
/* Add this packet to the receive queue. */
|
||||
netdev_rx ( netdev, adapter->rx_iobuf[i] );
|
||||
}
|
||||
adapter->rx_iobuf[i] = NULL;
|
||||
|
||||
memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
|
||||
|
||||
adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_poll - Poll for received packets
|
||||
*
|
||||
* @v netdev Network device
|
||||
*/
|
||||
static void igbvf_poll ( struct net_device *netdev )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
uint32_t rx_status;
|
||||
union e1000_adv_rx_desc *rx_curr_desc;
|
||||
|
||||
DBGP ( "igbvf_poll\n" );
|
||||
|
||||
rx_curr_desc = ( void * ) ( adapter->rx_base ) +
|
||||
( adapter->rx_curr * sizeof ( *adapter->rx_base ) );
|
||||
rx_status = rx_curr_desc->wb.upper.status_error;
|
||||
|
||||
if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
|
||||
return;
|
||||
|
||||
igbvf_process_tx_packets ( netdev );
|
||||
|
||||
igbvf_process_rx_packets ( netdev );
|
||||
|
||||
igbvf_refill_rx_ring ( adapter );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_config_collision_dist_generic - Configure collision distance
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Configures the collision distance to the default value and is used
|
||||
* during link setup. Currently no func pointer exists and all
|
||||
* implementations are handled in the generic version of this function.
|
||||
**/
|
||||
void igbvf_config_collision_dist ( struct e1000_hw *hw )
|
||||
{
|
||||
u32 tctl;
|
||||
|
||||
DBG ("igbvf_config_collision_dist");
|
||||
|
||||
tctl = er32 (TCTL);
|
||||
|
||||
tctl &= ~E1000_TCTL_COLD;
|
||||
tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
|
||||
|
||||
ew32 (TCTL, tctl);
|
||||
e1e_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_configure_tx - Configure Transmit Unit after Reset
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Configure the Tx unit of the MAC after a reset.
|
||||
**/
|
||||
static void igbvf_configure_tx ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 tctl, txdctl;
|
||||
|
||||
DBG ( "igbvf_configure_tx\n" );
|
||||
|
||||
/* disable transmits while setting up the descriptors */
|
||||
tctl = er32 ( TCTL );
|
||||
ew32 ( TCTL, tctl & ~E1000_TCTL_EN );
|
||||
e1e_flush();
|
||||
mdelay (10);
|
||||
|
||||
ew32 ( TDBAH(0), 0 );
|
||||
ew32 ( TDBAL(0), virt_to_bus ( adapter->tx_base ) );
|
||||
ew32 ( TDLEN(0), adapter->tx_ring_size );
|
||||
|
||||
DBG ( "E1000_TDBAL(0): %#08x\n", er32 ( TDBAL(0) ) );
|
||||
DBG ( "E1000_TDLEN(0): %d\n", er32 ( TDLEN(0) ) );
|
||||
|
||||
/* Setup the HW Tx Head and Tail descriptor pointers */
|
||||
ew32 ( TDH(0), 0 );
|
||||
ew32 ( TDT(0), 0 );
|
||||
|
||||
adapter->tx_head = 0;
|
||||
adapter->tx_tail = 0;
|
||||
adapter->tx_fill_ctr = 0;
|
||||
|
||||
txdctl = er32(TXDCTL(0));
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
ew32 ( TXDCTL(0), txdctl );
|
||||
|
||||
txdctl = er32 ( TXDCTL(0) );
|
||||
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
|
||||
ew32 ( TXDCTL(0), txdctl );
|
||||
|
||||
/* Setup Transmit Descriptor Settings for eop descriptor */
|
||||
adapter->txd_cmd = E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_IFCS;
|
||||
|
||||
/* Advanced descriptor */
|
||||
adapter->txd_cmd |= E1000_ADVTXD_DCMD_DEXT;
|
||||
|
||||
/* (not part of cmd, but in same 32 bit word...) */
|
||||
adapter->txd_cmd |= E1000_ADVTXD_DTYP_DATA;
|
||||
|
||||
/* enable Report Status bit */
|
||||
adapter->txd_cmd |= E1000_ADVTXD_DCMD_RS;
|
||||
|
||||
/* Program the Transmit Control Register */
|
||||
tctl &= ~E1000_TCTL_CT;
|
||||
tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
|
||||
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
|
||||
|
||||
igbvf_config_collision_dist ( hw );
|
||||
|
||||
/* Enable transmits */
|
||||
tctl |= E1000_TCTL_EN;
|
||||
ew32(TCTL, tctl);
|
||||
e1e_flush();
|
||||
}
|
||||
|
||||
/* igbvf_reset - bring the hardware into a known good state
|
||||
*
|
||||
* This function boots the hardware and enables some settings that
|
||||
* require a configuration cycle of the hardware - those cannot be
|
||||
* set/changed during runtime. After reset the device needs to be
|
||||
* properly configured for Rx, Tx etc.
|
||||
*/
|
||||
void igbvf_reset ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_mac_info *mac = &adapter->hw.mac;
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
/* Allow time for pending master requests to run */
|
||||
if ( mac->ops.reset_hw(hw) )
|
||||
DBG ("PF still resetting\n");
|
||||
|
||||
mac->ops.init_hw ( hw );
|
||||
|
||||
if ( is_valid_ether_addr(adapter->hw.mac.addr) ) {
|
||||
memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
|
||||
}
|
||||
}
|
||||
|
||||
extern void igbvf_init_function_pointers_vf(struct e1000_hw *hw);
|
||||
|
||||
/**
|
||||
* igbvf_sw_init - Initialize general software structures (struct igbvf_adapter)
|
||||
* @adapter: board private structure to initialize
|
||||
*
|
||||
* igbvf_sw_init initializes the Adapter private data structure.
|
||||
* Fields are initialized based on PCI device information and
|
||||
* OS network device settings (MTU size).
|
||||
**/
|
||||
static int __devinit igbvf_sw_init ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct pci_device *pdev = adapter->pdev;
|
||||
int rc;
|
||||
|
||||
/* PCI config space info */
|
||||
|
||||
hw->vendor_id = pdev->vendor;
|
||||
hw->device_id = pdev->device;
|
||||
|
||||
pci_read_config_byte ( pdev, PCI_REVISION_ID, &hw->revision_id );
|
||||
|
||||
pci_read_config_word ( pdev, PCI_COMMAND, &hw->bus.pci_cmd_word );
|
||||
|
||||
adapter->max_frame_size = MAXIMUM_ETHERNET_VLAN_SIZE + ETH_HLEN + ETH_FCS_LEN;
|
||||
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
|
||||
|
||||
/* Set various function pointers */
|
||||
igbvf_init_function_pointers_vf ( &adapter->hw );
|
||||
|
||||
rc = adapter->hw.mac.ops.init_params ( &adapter->hw );
|
||||
if (rc) {
|
||||
DBG ("hw.mac.ops.init_params(&adapter->hw) Failure\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = adapter->hw.mbx.ops.init_params ( &adapter->hw );
|
||||
if (rc) {
|
||||
DBG ("hw.mbx.ops.init_params(&adapter->hw) Failure\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Explicitly disable IRQ since the NIC can be in any state. */
|
||||
igbvf_irq_disable ( adapter );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_setup_srrctl - configure the receive control registers
|
||||
* @adapter: Board private structure
|
||||
**/
|
||||
static void igbvf_setup_srrctl ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 srrctl = 0;
|
||||
|
||||
DBG ( "igbvf_setup_srrctl\n" );
|
||||
|
||||
srrctl &= ~(E1000_SRRCTL_DESCTYPE_MASK |
|
||||
E1000_SRRCTL_BSIZEHDR_MASK |
|
||||
E1000_SRRCTL_BSIZEPKT_MASK);
|
||||
|
||||
/* Enable queue drop to avoid head of line blocking */
|
||||
srrctl |= E1000_SRRCTL_DROP_EN;
|
||||
|
||||
/* Setup buffer sizes */
|
||||
srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
|
||||
srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
|
||||
|
||||
ew32 ( SRRCTL(0), srrctl );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_configure_rx - Configure 8254x Receive Unit after Reset
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Configure the Rx unit of the MAC after a reset.
|
||||
**/
|
||||
static void igbvf_configure_rx ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 rxdctl;
|
||||
|
||||
DBG ( "igbvf_configure_rx\n" );
|
||||
|
||||
/* disable receives */
|
||||
rxdctl = er32 ( RXDCTL(0) );
|
||||
ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
|
||||
msleep ( 10 );
|
||||
|
||||
/*
|
||||
* Setup the HW Rx Head and Tail Descriptor Pointers and
|
||||
* the Base and Length of the Rx Descriptor Ring
|
||||
*/
|
||||
ew32 ( RDBAL(0), virt_to_bus (adapter->rx_base) );
|
||||
ew32 ( RDBAH(0), 0 );
|
||||
ew32 ( RDLEN(0), adapter->rx_ring_size );
|
||||
adapter->rx_curr = 0;
|
||||
ew32 ( RDH(0), 0 );
|
||||
ew32 ( RDT(0), 0 );
|
||||
|
||||
rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
|
||||
rxdctl &= 0xFFF00000;
|
||||
rxdctl |= IGBVF_RX_PTHRESH;
|
||||
rxdctl |= IGBVF_RX_HTHRESH << 8;
|
||||
rxdctl |= IGBVF_RX_WTHRESH << 16;
|
||||
|
||||
igbvf_rlpml_set_vf ( hw, adapter->max_frame_size );
|
||||
|
||||
/* enable receives */
|
||||
ew32 ( RXDCTL(0), rxdctl );
|
||||
ew32 ( RDT(0), NUM_RX_DESC );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_setup_rx_resources - allocate Rx resources (Descriptors)
|
||||
*
|
||||
* @v adapter e1000 private structure
|
||||
**/
|
||||
int igbvf_setup_rx_resources ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
int i;
|
||||
union e1000_adv_rx_desc *rx_curr_desc;
|
||||
struct io_buffer *iob;
|
||||
|
||||
DBG ( "igbvf_setup_rx_resources\n" );
|
||||
|
||||
/* Allocate receive descriptor ring memory.
|
||||
It must not cross a 64K boundary because of hardware errata
|
||||
*/
|
||||
|
||||
adapter->rx_base =
|
||||
malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
|
||||
|
||||
if ( ! adapter->rx_base ) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset ( adapter->rx_base, 0, adapter->rx_ring_size );
|
||||
|
||||
for ( i = 0; i < NUM_RX_DESC; i++ ) {
|
||||
rx_curr_desc = adapter->rx_base + i;
|
||||
iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
|
||||
adapter->rx_iobuf[i] = iob;
|
||||
rx_curr_desc->wb.upper.status_error = 0;
|
||||
if ( ! iob ) {
|
||||
DBG ( "alloc_iob failed\n" );
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
|
||||
rx_curr_desc->read.hdr_addr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_open - Called when a network interface is made active
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* Returns 0 on success, negative value on failure
|
||||
*
|
||||
* The open entry point is called when a network interface is made
|
||||
* active by the system (IFF_UP). At this point all resources needed
|
||||
* for transmit and receive operations are allocated, the interrupt
|
||||
* handler is registered with the OS, the watchdog timer is started,
|
||||
* and the stack is notified that the interface is ready.
|
||||
**/
|
||||
static int igbvf_open ( struct net_device *netdev )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
int err;
|
||||
|
||||
DBG ("igbvf_open\n");
|
||||
|
||||
/* allocate transmit descriptors */
|
||||
err = igbvf_setup_tx_resources ( adapter );
|
||||
if (err) {
|
||||
DBG ( "Error setting up TX resources!\n" );
|
||||
goto err_setup_tx;
|
||||
}
|
||||
|
||||
igbvf_configure_tx ( adapter );
|
||||
|
||||
igbvf_setup_srrctl( adapter );
|
||||
|
||||
err = igbvf_setup_rx_resources( adapter );
|
||||
if (err) {
|
||||
DBG ( "Error setting up RX resources!\n" );
|
||||
goto err_setup_rx;
|
||||
}
|
||||
|
||||
igbvf_configure_rx ( adapter );
|
||||
|
||||
return 0;
|
||||
|
||||
err_setup_rx:
|
||||
DBG ( "err_setup_rx\n" );
|
||||
igbvf_free_tx_resources ( adapter );
|
||||
return err;
|
||||
|
||||
err_setup_tx:
|
||||
DBG ( "err_setup_tx\n" );
|
||||
igbvf_reset ( adapter );
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_close - Disables a network interface
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* Returns 0, this is not allowed to fail
|
||||
*
|
||||
* The close entry point is called when an interface is de-activated
|
||||
* by the OS. The hardware is still under the drivers control, but
|
||||
* needs to be disabled. A global MAC reset is issued to stop the
|
||||
* hardware, and all transmit and receive resources are freed.
|
||||
**/
|
||||
static void igbvf_close ( struct net_device *netdev )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t rxdctl;
|
||||
uint32_t icr;
|
||||
|
||||
DBG ( "igbvf_close\n" );
|
||||
icr = er32(EICR);
|
||||
|
||||
igbvf_irq_disable ( adapter );
|
||||
|
||||
/* disable receives */
|
||||
rxdctl = er32 ( RXDCTL(0) );
|
||||
ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
|
||||
mdelay ( 10 );
|
||||
|
||||
igbvf_reset ( adapter );
|
||||
|
||||
igbvf_free_tx_resources( adapter );
|
||||
igbvf_free_rx_resources( adapter );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_transmit - Transmit a packet
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v iobuf I/O buffer
|
||||
*
|
||||
* @ret rc Returns 0 on success, negative on failure
|
||||
*/
|
||||
static int igbvf_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
uint32_t tx_curr = adapter->tx_tail;
|
||||
union e1000_adv_tx_desc *tx_curr_desc;
|
||||
|
||||
DBGP ("igbvf_transmit\n");
|
||||
|
||||
if ( adapter->tx_fill_ctr == NUM_TX_DESC ) {
|
||||
DBG ("TX overflow\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/* Save pointer to iobuf we have been given to transmit,
|
||||
netdev_tx_complete() will need it later
|
||||
*/
|
||||
adapter->tx_iobuf[tx_curr] = iobuf;
|
||||
|
||||
tx_curr_desc = ( void * ) ( adapter->tx_base ) +
|
||||
( tx_curr * sizeof ( *adapter->tx_base ) );
|
||||
|
||||
DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
|
||||
DBG ( "tx_curr_desc + 16 = %#08lx\n", virt_to_bus ( tx_curr_desc ) + 16 );
|
||||
DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) );
|
||||
|
||||
/* Add the packet to TX ring
|
||||
*/
|
||||
tx_curr_desc->read.buffer_addr = virt_to_bus ( iobuf->data );
|
||||
tx_curr_desc->read.cmd_type_len = adapter->txd_cmd |(iob_len ( iobuf )) ;
|
||||
// minus hdr_len ????
|
||||
tx_curr_desc->read.olinfo_status = ((iob_len ( iobuf )) << E1000_ADVTXD_PAYLEN_SHIFT);
|
||||
|
||||
DBG ( "TX fill: %d tx_curr: %d addr: %#08lx len: %zd\n", adapter->tx_fill_ctr,
|
||||
tx_curr, virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
|
||||
|
||||
/* Point to next free descriptor */
|
||||
adapter->tx_tail = ( adapter->tx_tail + 1 ) % NUM_TX_DESC;
|
||||
adapter->tx_fill_ctr++;
|
||||
|
||||
/* Write new tail to NIC, making packet available for transmit
|
||||
*/
|
||||
ew32 ( TDT(0), adapter->tx_tail );
|
||||
e1e_flush ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** igbvf net device operations */
|
||||
static struct net_device_operations igbvf_operations = {
|
||||
.open = igbvf_open,
|
||||
.close = igbvf_close,
|
||||
.transmit = igbvf_transmit,
|
||||
.poll = igbvf_poll,
|
||||
.irq = igbvf_irq,
|
||||
};
|
||||
|
||||
/**
|
||||
* igbvf_get_hw_control - get control of the h/w from f/w
|
||||
* @adapter: address of board private structure
|
||||
*
|
||||
* igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit.
|
||||
* For ASF and Pass Through versions of f/w this means that
|
||||
* the driver is loaded.
|
||||
*
|
||||
**/
|
||||
void igbvf_get_hw_control ( struct igbvf_adapter *adapter )
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 ctrl_ext;
|
||||
|
||||
/* Let firmware know the driver has taken over */
|
||||
ctrl_ext = er32 ( CTRL_EXT );
|
||||
ew32 ( CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD );
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_probe - Device Initialization Routine
|
||||
* @pdev: PCI device information struct
|
||||
* @ent: entry in igbvf_pci_tbl
|
||||
*
|
||||
* Returns 0 on success, negative on failure
|
||||
*
|
||||
* igbvf_probe initializes an adapter identified by a pci_dev structure.
|
||||
* The OS initialization, configuring of the adapter private structure,
|
||||
* and a hardware reset occur.
|
||||
**/
|
||||
int igbvf_probe ( struct pci_device *pdev,
|
||||
const struct pci_device_id *ent __unused )
|
||||
{
|
||||
int err;
|
||||
struct net_device *netdev;
|
||||
struct igbvf_adapter *adapter;
|
||||
unsigned long mmio_start, mmio_len;
|
||||
struct e1000_hw *hw;
|
||||
|
||||
DBG ( "igbvf_probe\n" );
|
||||
|
||||
err = -ENOMEM;
|
||||
|
||||
/* Allocate net device ( also allocates memory for netdev->priv
|
||||
and makes netdev-priv point to it ) */
|
||||
netdev = alloc_etherdev ( sizeof ( struct igbvf_adapter ) );
|
||||
if ( ! netdev )
|
||||
goto err_alloc_etherdev;
|
||||
|
||||
/* Associate igbvf-specific network operations operations with
|
||||
* generic network device layer */
|
||||
netdev_init ( netdev, &igbvf_operations );
|
||||
|
||||
/* Associate this network device with given PCI device */
|
||||
pci_set_drvdata ( pdev, netdev );
|
||||
netdev->dev = &pdev->dev;
|
||||
|
||||
/* Initialize driver private storage */
|
||||
adapter = netdev_priv ( netdev );
|
||||
memset ( adapter, 0, ( sizeof ( *adapter ) ) );
|
||||
|
||||
adapter->pdev = pdev;
|
||||
|
||||
adapter->ioaddr = pdev->ioaddr;
|
||||
adapter->hw.io_base = pdev->ioaddr;
|
||||
|
||||
hw = &adapter->hw;
|
||||
hw->vendor_id = pdev->vendor;
|
||||
hw->device_id = pdev->device;
|
||||
|
||||
adapter->irqno = pdev->irq;
|
||||
adapter->netdev = netdev;
|
||||
adapter->hw.back = adapter;
|
||||
|
||||
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
|
||||
adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
|
||||
|
||||
adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC;
|
||||
adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC;
|
||||
|
||||
/* Fix up PCI device */
|
||||
adjust_pci_device ( pdev );
|
||||
|
||||
err = -EIO;
|
||||
|
||||
mmio_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_0 );
|
||||
mmio_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_0 );
|
||||
|
||||
DBG ( "mmio_start: %#08lx\n", mmio_start );
|
||||
DBG ( "mmio_len: %#08lx\n", mmio_len );
|
||||
|
||||
adapter->hw.hw_addr = ioremap ( mmio_start, mmio_len );
|
||||
DBG ( "adapter->hw.hw_addr: %p\n", adapter->hw.hw_addr );
|
||||
|
||||
if ( ! adapter->hw.hw_addr ) {
|
||||
DBG ( "err_ioremap\n" );
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
/* setup adapter struct */
|
||||
err = igbvf_sw_init ( adapter );
|
||||
if (err) {
|
||||
DBG ( "err_sw_init\n" );
|
||||
goto err_sw_init;
|
||||
}
|
||||
|
||||
/* reset the controller to put the device in a known good state */
|
||||
err = hw->mac.ops.reset_hw ( hw );
|
||||
if ( err ) {
|
||||
DBG ("PF still in reset state, assigning new address\n");
|
||||
netdev->hw_addr[0] = 0x21;
|
||||
netdev->hw_addr[1] = 0x21;
|
||||
netdev->hw_addr[2] = 0x21;
|
||||
netdev->hw_addr[3] = 0x21;
|
||||
netdev->hw_addr[4] = 0x21;
|
||||
netdev->hw_addr[5] = 0x21;
|
||||
netdev->hw_addr[6] = 0x21;
|
||||
} else {
|
||||
err = hw->mac.ops.read_mac_addr(hw);
|
||||
if (err) {
|
||||
DBG ("Error reading MAC address\n");
|
||||
goto err_hw_init;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
|
||||
|
||||
if ( ! is_valid_ether_addr( netdev->hw_addr ) ) {
|
||||
DBG ("Invalid MAC Address: "
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
netdev->hw_addr[0], netdev->hw_addr[1],
|
||||
netdev->hw_addr[2], netdev->hw_addr[3],
|
||||
netdev->hw_addr[4], netdev->hw_addr[5]);
|
||||
err = -EIO;
|
||||
goto err_hw_init;
|
||||
}
|
||||
|
||||
/* reset the hardware with the new settings */
|
||||
igbvf_reset ( adapter );
|
||||
|
||||
/* let the f/w know that the h/w is now under the control of the
|
||||
* driver. */
|
||||
igbvf_get_hw_control ( adapter );
|
||||
|
||||
/* Mark as link up; we don't yet handle link state */
|
||||
netdev_link_up ( netdev );
|
||||
|
||||
if ( ( err = register_netdev ( netdev ) ) != 0) {
|
||||
DBG ( "err_register\n" );
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
DBG ("igbvf_probe_succeeded\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
err_hw_init:
|
||||
err_sw_init:
|
||||
iounmap ( adapter->hw.hw_addr );
|
||||
err_ioremap:
|
||||
netdev_put ( netdev );
|
||||
err_alloc_etherdev:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_remove - Device Removal Routine
|
||||
* @pdev: PCI device information struct
|
||||
*
|
||||
* igbvf_remove is called by the PCI subsystem to alert the driver
|
||||
* that it should release a PCI device. The could be caused by a
|
||||
* Hot-Plug event, or because the driver is going to be removed from
|
||||
* memory.
|
||||
**/
|
||||
void igbvf_remove ( struct pci_device *pdev )
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata ( pdev );
|
||||
struct igbvf_adapter *adapter = netdev_priv ( netdev );
|
||||
|
||||
DBG ( "igbvf_remove\n" );
|
||||
|
||||
if ( adapter->hw.flash_address )
|
||||
iounmap ( adapter->hw.flash_address );
|
||||
if ( adapter->hw.hw_addr )
|
||||
iounmap ( adapter->hw.hw_addr );
|
||||
|
||||
unregister_netdev ( netdev );
|
||||
igbvf_reset ( adapter );
|
||||
netdev_nullify ( netdev );
|
||||
netdev_put ( netdev );
|
||||
}
|
||||
|
||||
static struct pci_device_id igbvf_pci_tbl[] = {
|
||||
PCI_ROM(0x8086, 0x10CA, "igbvf", "E1000_DEV_ID_82576_VF", 0)
|
||||
};
|
||||
|
||||
|
||||
struct pci_driver igbvf_driver __pci_driver = {
|
||||
.ids = igbvf_pci_tbl,
|
||||
.id_count = (sizeof(igbvf_pci_tbl) / sizeof(igbvf_pci_tbl[0])),
|
||||
.probe = igbvf_probe,
|
||||
.remove = igbvf_remove,
|
||||
};
|
||||
@@ -0,0 +1,404 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#include "igbvf_mbx.h"
|
||||
|
||||
/**
|
||||
* igbvf_poll_for_msg - Wait for message notification
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification
|
||||
**/
|
||||
static s32 igbvf_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
DEBUGFUNC("igbvf_poll_for_msg");
|
||||
|
||||
if (!countdown || !mbx->ops.check_for_msg)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
|
||||
countdown--;
|
||||
if (!countdown)
|
||||
break;
|
||||
usec_delay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_poll_for_ack - Wait for message acknowledgement
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message acknowledgement
|
||||
**/
|
||||
static s32 igbvf_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
DEBUGFUNC("igbvf_poll_for_ack");
|
||||
|
||||
if (!countdown || !mbx->ops.check_for_ack)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
|
||||
countdown--;
|
||||
if (!countdown)
|
||||
break;
|
||||
usec_delay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_read_posted_mbx - Wait for message notification and receive message
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification and
|
||||
* copied it into the receive buffer.
|
||||
**/
|
||||
static s32 igbvf_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
DEBUGFUNC("igbvf_read_posted_mbx");
|
||||
|
||||
if (!mbx->ops.read)
|
||||
goto out;
|
||||
|
||||
ret_val = igbvf_poll_for_msg(hw, mbx_id);
|
||||
|
||||
/* if ack received read message, otherwise we timed out */
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read(hw, msg, size, mbx_id);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_write_posted_mbx - Write a message to the mailbox, wait for ack
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer and
|
||||
* received an ack to that message within delay * timeout period
|
||||
**/
|
||||
static s32 igbvf_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
DEBUGFUNC("igbvf_write_posted_mbx");
|
||||
|
||||
/* exit if either we can't write or there isn't a defined timeout */
|
||||
if (!mbx->ops.write || !mbx->timeout)
|
||||
goto out;
|
||||
|
||||
/* send msg */
|
||||
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
|
||||
|
||||
/* if msg sent wait until we receive an ack */
|
||||
if (!ret_val)
|
||||
ret_val = igbvf_poll_for_ack(hw, mbx_id);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_init_mbx_ops_generic - Initialize NVM function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups up the function pointers to no-op functions
|
||||
**/
|
||||
void igbvf_init_mbx_ops_generic(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
mbx->ops.read_posted = igbvf_read_posted_mbx;
|
||||
mbx->ops.write_posted = igbvf_write_posted_mbx;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_read_v2p_mailbox - read v2p mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function is used to read the v2p mailbox without losing the read to
|
||||
* clear status bits.
|
||||
**/
|
||||
static u32 igbvf_read_v2p_mailbox(struct e1000_hw *hw)
|
||||
{
|
||||
u32 v2p_mailbox = E1000_READ_REG(hw, E1000_V2PMAILBOX(0));
|
||||
|
||||
v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
|
||||
hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
|
||||
|
||||
return v2p_mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_check_for_bit_vf - Determine if a status bit was set
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: bitmask for bits to be tested and cleared
|
||||
*
|
||||
* This function is used to check for the read to clear bits within
|
||||
* the V2P mailbox.
|
||||
**/
|
||||
static s32 igbvf_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
|
||||
{
|
||||
u32 v2p_mailbox = igbvf_read_v2p_mailbox(hw);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (v2p_mailbox & mask)
|
||||
ret_val = E1000_SUCCESS;
|
||||
|
||||
hw->dev_spec.vf.v2p_mailbox &= ~mask;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_check_for_msg_vf - checks to see if the PF has sent mail
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the PF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igbvf_check_for_msg_vf(struct e1000_hw *hw, u16 mbx_id __unused)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
DEBUGFUNC("igbvf_check_for_msg_vf");
|
||||
|
||||
if (!igbvf_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.reqs++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_check_for_ack_vf - checks to see if the PF has ACK'd
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igbvf_check_for_ack_vf(struct e1000_hw *hw, u16 mbx_id __unused)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
DEBUGFUNC("igbvf_check_for_ack_vf");
|
||||
|
||||
if (!igbvf_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.acks++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_check_for_rst_vf - checks to see if the PF has reset
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns true if the PF has set the reset done bit or else false
|
||||
**/
|
||||
static s32 igbvf_check_for_rst_vf(struct e1000_hw *hw, u16 mbx_id __unused)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
DEBUGFUNC("igbvf_check_for_rst_vf");
|
||||
|
||||
if (!igbvf_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
|
||||
E1000_V2PMAILBOX_RSTI))) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.rsts++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_obtain_mbx_lock_vf - obtain mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* return SUCCESS if we obtained the mailbox lock
|
||||
**/
|
||||
static s32 igbvf_obtain_mbx_lock_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
DEBUGFUNC("igbvf_obtain_mbx_lock_vf");
|
||||
|
||||
/* Take ownership of the buffer */
|
||||
E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
|
||||
|
||||
/* reserve mailbox for vf use */
|
||||
if (igbvf_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
|
||||
ret_val = E1000_SUCCESS;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_write_mbx_vf - Write a message to the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
static s32 igbvf_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id __unused)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 i;
|
||||
|
||||
|
||||
DEBUGFUNC("igbvf_write_mbx_vf");
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
ret_val = igbvf_obtain_mbx_lock_vf(hw);
|
||||
if (ret_val)
|
||||
goto out_no_write;
|
||||
|
||||
/* flush msg and acks as we are overwriting the message buffer */
|
||||
igbvf_check_for_msg_vf(hw, 0);
|
||||
igbvf_check_for_ack_vf(hw, 0);
|
||||
|
||||
/* copy the caller specified message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(0), i, msg[i]);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_tx++;
|
||||
|
||||
/* Drop VFU and interrupt the PF to tell it a message has been sent */
|
||||
E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
|
||||
|
||||
out_no_write:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_read_mbx_vf - Reads a message from the inbox intended for vf
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to read
|
||||
*
|
||||
* returns SUCCESS if it successfuly read message from buffer
|
||||
**/
|
||||
static s32 igbvf_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id __unused)
|
||||
{
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u16 i;
|
||||
|
||||
DEBUGFUNC("igbvf_read_mbx_vf");
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
ret_val = igbvf_obtain_mbx_lock_vf(hw);
|
||||
if (ret_val)
|
||||
goto out_no_read;
|
||||
|
||||
/* copy the message from the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(0), i);
|
||||
|
||||
/* Acknowledge receipt and release mailbox, then we're done */
|
||||
E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_rx++;
|
||||
|
||||
out_no_read:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_init_mbx_params_vf - set initial values for vf mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Initializes the hw->mbx struct to correct values for vf mailbox
|
||||
*/
|
||||
s32 igbvf_init_mbx_params_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
|
||||
/* start mailbox as timed out and let the reset_hw call set the timeout
|
||||
* value to begin communications */
|
||||
mbx->timeout = 0;
|
||||
mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
|
||||
|
||||
mbx->size = E1000_VFMAILBOX_SIZE;
|
||||
|
||||
mbx->ops.read = igbvf_read_mbx_vf;
|
||||
mbx->ops.write = igbvf_write_mbx_vf;
|
||||
mbx->ops.read_posted = igbvf_read_posted_mbx;
|
||||
mbx->ops.write_posted = igbvf_write_posted_mbx;
|
||||
mbx->ops.check_for_msg = igbvf_check_for_msg_vf;
|
||||
mbx->ops.check_for_ack = igbvf_check_for_ack_vf;
|
||||
mbx->ops.check_for_rst = igbvf_check_for_rst_vf;
|
||||
|
||||
mbx->stats.msgs_tx = 0;
|
||||
mbx->stats.msgs_rx = 0;
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#ifndef _IGBVF_MBX_H_
|
||||
#define _IGBVF_MBX_H_
|
||||
|
||||
#include "igbvf_vf.h"
|
||||
|
||||
/* Define mailbox specific registers */
|
||||
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
|
||||
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
|
||||
|
||||
/* Define mailbox register bits */
|
||||
#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
|
||||
#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
|
||||
#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
|
||||
#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
|
||||
#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
|
||||
#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
|
||||
#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
|
||||
#define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
|
||||
#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
|
||||
|
||||
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
|
||||
|
||||
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
|
||||
* PF. The reverse is true if it is E1000_PF_*.
|
||||
* Message ACK's are the value or'd with 0xF0000000
|
||||
*/
|
||||
#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
|
||||
* this are the ACK */
|
||||
#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
|
||||
* this are the NACK */
|
||||
#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
|
||||
clear to send requests */
|
||||
#define E1000_VT_MSGINFO_SHIFT 16
|
||||
/* bits 23:16 are used for exra info for certain messages */
|
||||
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_VF_RESET 0x01 /* VF requests reset */
|
||||
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */
|
||||
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */
|
||||
#define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT)
|
||||
#define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT)
|
||||
#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */
|
||||
#define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT)
|
||||
#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */
|
||||
#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
|
||||
#define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT)
|
||||
#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
|
||||
|
||||
#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
|
||||
#define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
|
||||
|
||||
void igbvf_init_mbx_ops_generic(struct e1000_hw *hw);
|
||||
s32 igbvf_init_mbx_params_vf(struct e1000_hw *);
|
||||
|
||||
#endif /* _IGBVF_MBX_H_ */
|
||||
@@ -0,0 +1,121 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
/* glue for the OS-dependent part of igbvf
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _IGBVF_OSDEP_H_
|
||||
#define _IGBVF_OSDEP_H_
|
||||
|
||||
#define u8 unsigned char
|
||||
#define bool boolean_t
|
||||
#define dma_addr_t unsigned long
|
||||
#define __le16 uint16_t
|
||||
#define __le32 uint32_t
|
||||
#define __le64 uint64_t
|
||||
|
||||
#define __iomem
|
||||
#define __devinit
|
||||
#define ____cacheline_aligned_in_smp
|
||||
|
||||
#define msleep(x) mdelay(x)
|
||||
|
||||
#define ETH_FCS_LEN 4
|
||||
|
||||
typedef int spinlock_t;
|
||||
typedef enum {
|
||||
false = 0,
|
||||
true = 1
|
||||
} boolean_t;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define usec_delay(x) udelay(x)
|
||||
#define msec_delay(x) mdelay(x)
|
||||
#define msec_delay_irq(x) mdelay(x)
|
||||
|
||||
#define PCI_COMMAND_REGISTER PCI_COMMAND
|
||||
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
|
||||
#define ETH_ADDR_LEN ETH_ALEN
|
||||
|
||||
|
||||
#define DEBUGOUT(S) if (0) { printf(S); }
|
||||
#define DEBUGOUT1(S, A...) if (0) { printf(S, A); }
|
||||
|
||||
#define DEBUGFUNC(F) DEBUGOUT(F "\n")
|
||||
#define DEBUGOUT2 DEBUGOUT1
|
||||
#define DEBUGOUT3 DEBUGOUT2
|
||||
#define DEBUGOUT7 DEBUGOUT3
|
||||
|
||||
#define E1000_WRITE_REG(a, reg, value) do { \
|
||||
writel((value), ((a)->hw_addr + reg)); } while (0)
|
||||
|
||||
#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) do { \
|
||||
writel((value), ((a)->hw_addr + reg + ((offset) << 2))); } while (0)
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + reg + ((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + reg + ((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + reg + ((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + reg + (offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + reg + (offset)))
|
||||
|
||||
#define E1000_WRITE_REG_IO(a, reg, offset) do { \
|
||||
outl(reg, ((a)->io_base)); \
|
||||
outl(offset, ((a)->io_base + 4)); } while(0)
|
||||
|
||||
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)
|
||||
|
||||
#define E1000_WRITE_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _IGBVF_OSDEP_H_ */
|
||||
@@ -0,0 +1,338 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#ifndef _IGBVF_REGS_H_
|
||||
#define _IGBVF_REGS_H_
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
|
||||
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
|
||||
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
|
||||
#define E1000_FLA 0x0001C /* Flash Access - RW */
|
||||
#define E1000_MDIC 0x00020 /* MDI Control - RW */
|
||||
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
|
||||
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
|
||||
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
|
||||
#define E1000_FEXT 0x0002C /* Future Extended - RW */
|
||||
#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
|
||||
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
|
||||
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
|
||||
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
|
||||
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
|
||||
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
|
||||
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
|
||||
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
|
||||
#define E1000_RCTL 0x00100 /* Rx Control - RW */
|
||||
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
|
||||
#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
|
||||
#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
|
||||
#define E1000_TCTL 0x00400 /* Tx Control - RW */
|
||||
#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
|
||||
#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
|
||||
#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
|
||||
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
|
||||
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
|
||||
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
|
||||
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
|
||||
#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
|
||||
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
|
||||
#define E1000_PBS 0x01008 /* Packet Buffer Size */
|
||||
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
|
||||
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
|
||||
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
|
||||
#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
|
||||
#define E1000_FLSWCTL 0x01030 /* FLASH control register */
|
||||
#define E1000_FLSWDATA 0x01034 /* FLASH data register */
|
||||
#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
|
||||
#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
|
||||
#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
|
||||
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
|
||||
#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
|
||||
#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
|
||||
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
|
||||
#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
|
||||
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
|
||||
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
|
||||
#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
|
||||
#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
|
||||
#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
|
||||
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
|
||||
/* Split and Replication Rx Control - RW */
|
||||
#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
|
||||
#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
|
||||
#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
|
||||
#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
|
||||
#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
|
||||
#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n)))
|
||||
#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n)))
|
||||
#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
|
||||
#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
|
||||
/*
|
||||
* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* E1000_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
|
||||
(0x0C000 + ((_n) * 0x40)))
|
||||
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
|
||||
(0x0C004 + ((_n) * 0x40)))
|
||||
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
|
||||
(0x0C008 + ((_n) * 0x40)))
|
||||
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
|
||||
(0x0C00C + ((_n) * 0x40)))
|
||||
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
|
||||
(0x0C010 + ((_n) * 0x40)))
|
||||
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
|
||||
(0x0C018 + ((_n) * 0x40)))
|
||||
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
|
||||
(0x0C028 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
|
||||
(0x0E000 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
|
||||
(0x0E004 + ((_n) * 0x40)))
|
||||
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
|
||||
(0x0E008 + ((_n) * 0x40)))
|
||||
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
|
||||
(0x0E010 + ((_n) * 0x40)))
|
||||
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
|
||||
(0x0E018 + ((_n) * 0x40)))
|
||||
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
|
||||
(0x0E028 + ((_n) * 0x40)))
|
||||
#define E1000_TARC(_n) (0x03840 + (_n << 8))
|
||||
#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
|
||||
#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
|
||||
#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
|
||||
(0x0E038 + ((_n) * 0x40)))
|
||||
#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
|
||||
(0x0E03C + ((_n) * 0x40)))
|
||||
#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
|
||||
#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
|
||||
#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
|
||||
#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
|
||||
#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
|
||||
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
|
||||
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
|
||||
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
|
||||
#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
|
||||
#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
|
||||
#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
|
||||
#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
|
||||
#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
|
||||
#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
|
||||
#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
|
||||
#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
|
||||
#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */
|
||||
#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */
|
||||
#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */
|
||||
#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */
|
||||
#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */
|
||||
#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
|
||||
#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
|
||||
#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
|
||||
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
|
||||
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
|
||||
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
|
||||
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
|
||||
#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
|
||||
#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
|
||||
#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
|
||||
#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
|
||||
#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
|
||||
#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
|
||||
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
|
||||
#define E1000_DC 0x04030 /* Defer Count - R/clr */
|
||||
#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
|
||||
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
|
||||
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
|
||||
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
|
||||
#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
|
||||
#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
|
||||
#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
|
||||
#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
|
||||
#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
|
||||
#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
|
||||
#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
|
||||
#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
|
||||
#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
|
||||
#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
|
||||
#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
|
||||
#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
|
||||
#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
|
||||
#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
|
||||
#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
|
||||
#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
|
||||
#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
|
||||
#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
|
||||
#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
|
||||
#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
|
||||
#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
|
||||
#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
|
||||
#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
|
||||
#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
|
||||
#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
|
||||
#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
|
||||
#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
|
||||
#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
|
||||
#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
|
||||
#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
|
||||
#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
|
||||
#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
|
||||
#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
|
||||
#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
|
||||
#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
|
||||
#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
|
||||
#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
|
||||
#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
|
||||
#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
|
||||
#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
|
||||
#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
|
||||
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
|
||||
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
|
||||
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
|
||||
#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
|
||||
#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
|
||||
#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
|
||||
#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
|
||||
#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
|
||||
#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
|
||||
#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
|
||||
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
|
||||
|
||||
#define E1000_VFGPRC 0x00F10
|
||||
#define E1000_VFGORC 0x00F18
|
||||
#define E1000_VFMPRC 0x00F3C
|
||||
#define E1000_VFGPTC 0x00F14
|
||||
#define E1000_VFGOTC 0x00F34
|
||||
#define E1000_VFGOTLBC 0x00F50
|
||||
#define E1000_VFGPTLBC 0x00F44
|
||||
#define E1000_VFGORLBC 0x00F48
|
||||
#define E1000_VFGPRLBC 0x00F40
|
||||
#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
|
||||
#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
|
||||
#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
|
||||
#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
|
||||
#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
|
||||
#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
|
||||
#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
|
||||
#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
|
||||
#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
|
||||
#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
|
||||
#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
|
||||
#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
|
||||
#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
|
||||
#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
|
||||
#define E1000_LENERRS 0x04138 /* Length Errors Count */
|
||||
#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
|
||||
#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
|
||||
#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
|
||||
#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
|
||||
#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
|
||||
#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
|
||||
#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */
|
||||
#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
|
||||
#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
|
||||
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
|
||||
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
#define E1000_RA 0x05400 /* Receive Address - RW Array */
|
||||
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
|
||||
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
|
||||
#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
|
||||
#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
|
||||
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
|
||||
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
|
||||
#define E1000_WUS 0x05810 /* Wakeup Status - RO */
|
||||
#define E1000_MANC 0x05820 /* Management Control - RW */
|
||||
#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
|
||||
#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
|
||||
#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
|
||||
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
|
||||
#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
|
||||
#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
|
||||
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
|
||||
#define E1000_HOST_IF 0x08800 /* Host Interface */
|
||||
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
|
||||
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
|
||||
|
||||
#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
|
||||
#define E1000_MDPHYA 0x0003C /* PHY address - RW */
|
||||
#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
|
||||
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
|
||||
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
|
||||
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
|
||||
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
|
||||
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
|
||||
#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
|
||||
#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
|
||||
#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
|
||||
#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
|
||||
#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
|
||||
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
|
||||
#define E1000_SWSM 0x05B50 /* SW Semaphore */
|
||||
#define E1000_FWSM 0x05B54 /* FW Semaphore */
|
||||
#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */
|
||||
#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
|
||||
#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
|
||||
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
|
||||
#define E1000_HICR 0x08F00 /* Host Interface Control */
|
||||
|
||||
/* RSS registers */
|
||||
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
|
||||
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
|
||||
#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
|
||||
#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
|
||||
#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
|
||||
#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
|
||||
* (_i) - RW */
|
||||
#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
|
||||
* low reg - RW */
|
||||
#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
|
||||
* upper reg - RW */
|
||||
#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
|
||||
* message reg - RW */
|
||||
#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
|
||||
* vector ctrl reg - RW */
|
||||
#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
|
||||
#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
|
||||
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
|
||||
#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
|
||||
#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
|
||||
|
||||
#endif /* _IGBVF_REGS_H_ */
|
||||
@@ -0,0 +1,455 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#include "igbvf_vf.h"
|
||||
|
||||
|
||||
static s32 igbvf_init_mac_params_vf(struct e1000_hw *hw);
|
||||
static s32 igbvf_check_for_link_vf(struct e1000_hw *hw);
|
||||
static s32 igbvf_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
static s32 igbvf_init_hw_vf(struct e1000_hw *hw);
|
||||
static s32 igbvf_reset_hw_vf(struct e1000_hw *hw);
|
||||
static void igbvf_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32);
|
||||
static void igbvf_rar_set_vf(struct e1000_hw *, u8 *, u32);
|
||||
static s32 igbvf_read_mac_addr_vf(struct e1000_hw *);
|
||||
|
||||
/**
|
||||
* igbvf_init_mac_params_vf - Inits MAC params
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 igbvf_init_mac_params_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
|
||||
DEBUGFUNC("igbvf_init_mac_params_vf");
|
||||
|
||||
/* VF's have no MTA Registers - PF feature only */
|
||||
mac->mta_reg_count = 128;
|
||||
/* VF's have no access to RAR entries */
|
||||
mac->rar_entry_count = 1;
|
||||
|
||||
/* Function pointers */
|
||||
/* reset */
|
||||
mac->ops.reset_hw = igbvf_reset_hw_vf;
|
||||
/* hw initialization */
|
||||
mac->ops.init_hw = igbvf_init_hw_vf;
|
||||
/* check for link */
|
||||
mac->ops.check_for_link = igbvf_check_for_link_vf;
|
||||
/* link info */
|
||||
mac->ops.get_link_up_info = igbvf_get_link_up_info_vf;
|
||||
/* multicast address update */
|
||||
mac->ops.update_mc_addr_list = igbvf_update_mc_addr_list_vf;
|
||||
/* set mac address */
|
||||
mac->ops.rar_set = igbvf_rar_set_vf;
|
||||
/* read mac address */
|
||||
mac->ops.read_mac_addr = igbvf_read_mac_addr_vf;
|
||||
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_init_function_pointers_vf - Inits function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
void igbvf_init_function_pointers_vf(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("igbvf_init_function_pointers_vf");
|
||||
|
||||
hw->mac.ops.init_params = igbvf_init_mac_params_vf;
|
||||
hw->mbx.ops.init_params = igbvf_init_mbx_params_vf;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_get_link_up_info_vf - Gets link info.
|
||||
* @hw: pointer to the HW structure
|
||||
* @speed: pointer to 16 bit value to store link speed.
|
||||
* @duplex: pointer to 16 bit value to store duplex.
|
||||
*
|
||||
* Since we cannot read the PHY and get accurate link info, we must rely upon
|
||||
* the status register's data which is often stale and inaccurate.
|
||||
**/
|
||||
static s32 igbvf_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex)
|
||||
{
|
||||
s32 status;
|
||||
|
||||
DEBUGFUNC("igbvf_get_link_up_info_vf");
|
||||
|
||||
status = E1000_READ_REG(hw, E1000_STATUS);
|
||||
if (status & E1000_STATUS_SPEED_1000) {
|
||||
*speed = SPEED_1000;
|
||||
DEBUGOUT("1000 Mbs, ");
|
||||
} else if (status & E1000_STATUS_SPEED_100) {
|
||||
*speed = SPEED_100;
|
||||
DEBUGOUT("100 Mbs, ");
|
||||
} else {
|
||||
*speed = SPEED_10;
|
||||
DEBUGOUT("10 Mbs, ");
|
||||
}
|
||||
|
||||
if (status & E1000_STATUS_FD) {
|
||||
*duplex = FULL_DUPLEX;
|
||||
DEBUGOUT("Full Duplex\n");
|
||||
} else {
|
||||
*duplex = HALF_DUPLEX;
|
||||
DEBUGOUT("Half Duplex\n");
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_reset_hw_vf - Resets the HW
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
|
||||
* This is all the reset we can perform on a VF.
|
||||
**/
|
||||
static s32 igbvf_reset_hw_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 timeout = E1000_VF_INIT_TIMEOUT;
|
||||
s32 ret_val = -E1000_ERR_MAC_INIT;
|
||||
u32 ctrl, msgbuf[3];
|
||||
u8 *addr = (u8 *)(&msgbuf[1]);
|
||||
|
||||
DEBUGFUNC("igbvf_reset_hw_vf");
|
||||
|
||||
DEBUGOUT("Issuing a function level reset to MAC\n");
|
||||
ctrl = E1000_READ_REG(hw, E1000_CTRL);
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
|
||||
|
||||
/* we cannot reset while the RSTI / RSTD bits are asserted */
|
||||
while (!mbx->ops.check_for_rst(hw, 0) && timeout) {
|
||||
timeout--;
|
||||
usec_delay(5);
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
/* mailbox timeout can now become active */
|
||||
mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
|
||||
|
||||
msgbuf[0] = E1000_VF_RESET;
|
||||
mbx->ops.write_posted(hw, msgbuf, 1, 0);
|
||||
|
||||
msec_delay(10);
|
||||
|
||||
/* set our "perm_addr" based on info provided by PF */
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
|
||||
if (!ret_val) {
|
||||
if (msgbuf[0] == (E1000_VF_RESET |
|
||||
E1000_VT_MSGTYPE_ACK))
|
||||
memcpy(hw->mac.perm_addr, addr, 6);
|
||||
else
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_init_hw_vf - Inits the HW
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Not much to do here except clear the PF Reset indication if there is one.
|
||||
**/
|
||||
static s32 igbvf_init_hw_vf(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("igbvf_init_hw_vf");
|
||||
|
||||
/* attempt to set and restore our mac address */
|
||||
igbvf_rar_set_vf(hw, hw->mac.addr, 0);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_rar_set_vf - set device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: pointer to the receive address
|
||||
* @index receive address array register
|
||||
**/
|
||||
static void igbvf_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index __unused)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[3];
|
||||
u8 *msg_addr = (u8 *)(&msgbuf[1]);
|
||||
s32 ret_val;
|
||||
|
||||
memset(msgbuf, 0, 12);
|
||||
msgbuf[0] = E1000_VF_SET_MAC_ADDR;
|
||||
memcpy(msg_addr, addr, 6);
|
||||
ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
|
||||
|
||||
msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
|
||||
|
||||
/* if nacked the address was rejected, use "perm_addr" */
|
||||
if (!ret_val &&
|
||||
(msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
|
||||
igbvf_read_mac_addr_vf(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_hash_mc_addr_vf - Generate a multicast hash value
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr: pointer to a multicast address
|
||||
*
|
||||
* Generates a multicast address hash value which is used to determine
|
||||
* the multicast filter table array address and new table value. See
|
||||
* igbvf_mta_set_generic()
|
||||
**/
|
||||
static u32 igbvf_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
|
||||
{
|
||||
u32 hash_value, hash_mask;
|
||||
u8 bit_shift = 0;
|
||||
|
||||
DEBUGFUNC("igbvf_hash_mc_addr_generic");
|
||||
|
||||
/* Register count multiplied by bits per register */
|
||||
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
|
||||
|
||||
/*
|
||||
* The bit_shift is the number of left-shifts
|
||||
* where 0xFF would still fall within the hash mask.
|
||||
*/
|
||||
while (hash_mask >> bit_shift != 0xFF)
|
||||
bit_shift++;
|
||||
|
||||
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
|
||||
(((u16) mc_addr[5]) << bit_shift)));
|
||||
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_update_mc_addr_list_vf - Update Multicast addresses
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr_list: array of multicast addresses to program
|
||||
* @mc_addr_count: number of multicast addresses to program
|
||||
*
|
||||
* Updates the Multicast Table Array.
|
||||
* The caller must have a packed mc_addr_list of multicast addresses.
|
||||
**/
|
||||
void igbvf_update_mc_addr_list_vf(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[E1000_VFMAILBOX_SIZE];
|
||||
u16 *hash_list = (u16 *)&msgbuf[1];
|
||||
u32 hash_value;
|
||||
u32 i;
|
||||
|
||||
DEBUGFUNC("igbvf_update_mc_addr_list_vf");
|
||||
|
||||
/* Each entry in the list uses 1 16 bit word. We have 30
|
||||
* 16 bit words available in our HW msg buffer (minus 1 for the
|
||||
* msg type). That's 30 hash values if we pack 'em right. If
|
||||
* there are more than 30 MC addresses to add then punt the
|
||||
* extras for now and then add code to handle more than 30 later.
|
||||
* It would be unusual for a server to request that many multi-cast
|
||||
* addresses except for in large enterprise network environments.
|
||||
*/
|
||||
|
||||
DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count);
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_MULTICAST;
|
||||
|
||||
if (mc_addr_count > 30) {
|
||||
msgbuf[0] |= E1000_VF_SET_MULTICAST_OVERFLOW;
|
||||
mc_addr_count = 30;
|
||||
}
|
||||
|
||||
msgbuf[0] |= mc_addr_count << E1000_VT_MSGINFO_SHIFT;
|
||||
|
||||
for (i = 0; i < mc_addr_count; i++) {
|
||||
hash_value = igbvf_hash_mc_addr_vf(hw, mc_addr_list);
|
||||
DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
|
||||
hash_list[i] = hash_value & 0x0FFF;
|
||||
mc_addr_list += ETH_ADDR_LEN;
|
||||
}
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_vfta_set_vf - Set/Unset vlan filter table address
|
||||
* @hw: pointer to the HW structure
|
||||
* @vid: determines the vfta register and bit to set/unset
|
||||
* @set: if true then set bit, else clear bit
|
||||
**/
|
||||
void igbvf_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[2];
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_VLAN;
|
||||
msgbuf[1] = vid;
|
||||
/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
|
||||
if (set)
|
||||
msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, 2, 0);
|
||||
}
|
||||
|
||||
/** igbvf_rlpml_set_vf - Set the maximum receive packet length
|
||||
* @hw: pointer to the HW structure
|
||||
* @max_size: value to assign to max frame size
|
||||
**/
|
||||
void igbvf_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[2];
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_LPE;
|
||||
msgbuf[1] = max_size;
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, 2, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_promisc_set_vf - Set flags for Unicast or Multicast promisc
|
||||
* @hw: pointer to the HW structure
|
||||
* @uni: boolean indicating unicast promisc status
|
||||
* @multi: boolean indicating multicast promisc status
|
||||
**/
|
||||
s32 igbvf_promisc_set_vf(struct e1000_hw *hw, enum e1000_promisc_type type)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf = E1000_VF_SET_PROMISC;
|
||||
s32 ret_val;
|
||||
|
||||
switch (type) {
|
||||
case e1000_promisc_multicast:
|
||||
msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
|
||||
break;
|
||||
case e1000_promisc_enabled:
|
||||
msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
|
||||
case e1000_promisc_unicast:
|
||||
msgbuf |= E1000_VF_SET_PROMISC_UNICAST;
|
||||
case e1000_promisc_disabled:
|
||||
break;
|
||||
default:
|
||||
return -E1000_ERR_MAC_INIT;
|
||||
}
|
||||
|
||||
ret_val = mbx->ops.write_posted(hw, &msgbuf, 1, 0);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read_posted(hw, &msgbuf, 1, 0);
|
||||
|
||||
if (!ret_val && !(msgbuf & E1000_VT_MSGTYPE_ACK))
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_read_mac_addr_vf - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 igbvf_read_mac_addr_vf(struct e1000_hw *hw)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igbvf_check_for_link_vf - Check for link for a virtual interface
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Checks to see if the underlying PF is still talking to the VF and
|
||||
* if it is then it reports the link state to the hardware, otherwise
|
||||
* it reports link down and returns an error.
|
||||
**/
|
||||
static s32 igbvf_check_for_link_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u32 in_msg = 0;
|
||||
|
||||
DEBUGFUNC("igbvf_check_for_link_vf");
|
||||
|
||||
/*
|
||||
* We only want to run this if there has been a rst asserted.
|
||||
* in this case that could mean a link change, device reset,
|
||||
* or a virtual function reset
|
||||
*/
|
||||
|
||||
/* If we were hit with a reset drop the link */
|
||||
if (!mbx->ops.check_for_rst(hw, 0))
|
||||
mac->get_link_status = true;
|
||||
|
||||
if (!mac->get_link_status)
|
||||
goto out;
|
||||
|
||||
/* if link status is down no point in checking to see if pf is up */
|
||||
if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU))
|
||||
goto out;
|
||||
|
||||
/* if the read failed it could just be a mailbox collision, best wait
|
||||
* until we are called again and don't report an error */
|
||||
if (mbx->ops.read(hw, &in_msg, 1, 0))
|
||||
goto out;
|
||||
|
||||
/* if incoming message isn't clear to send we are waiting on response */
|
||||
if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
|
||||
/* message is not CTS and is NACK we have lost CTS status */
|
||||
if (in_msg & E1000_VT_MSGTYPE_NACK)
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* at this point we know the PF is talking to us, check and see if
|
||||
* we are still accepting timeout or if we had a timeout failure.
|
||||
* if we failed then we will need to reinit */
|
||||
if (!mbx->timeout) {
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if we passed all the tests above then the link is up and we no
|
||||
* longer need to check for link */
|
||||
mac->get_link_status = false;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2008 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope 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.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
Linux NICS <linux.nics@intel.com>
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#ifndef _IGBVF_VF_H_
|
||||
#define _IGBVF_VF_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <byteswap.h>
|
||||
#include <errno.h>
|
||||
#include <ipxe/pci.h>
|
||||
#include <ipxe/malloc.h>
|
||||
#include <ipxe/if_ether.h>
|
||||
#include <ipxe/io.h>
|
||||
#include <ipxe/ethernet.h>
|
||||
#include <ipxe/iobuf.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
|
||||
#include "igbvf_osdep.h"
|
||||
#include "igbvf_regs.h"
|
||||
#include "igbvf_defines.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82576_VF 0x10CA
|
||||
|
||||
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
|
||||
|
||||
/* Additional Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
|
||||
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
|
||||
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
|
||||
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
|
||||
|
||||
/* Interrupt Defines */
|
||||
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
|
||||
#define E1000_EITR(_n) (0x01680 + ((_n) << 2))
|
||||
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
|
||||
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
|
||||
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
|
||||
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
|
||||
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
|
||||
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
|
||||
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
|
||||
#define E1000_IVAR_VALID 0x80
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
u64 pkt_addr; /* Packet buffer address */
|
||||
u64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u16 pkt_info; /* RSS type, Packet type */
|
||||
u16 hdr_info; /* Split Header,
|
||||
* header buffer length */
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length; /* Packet length */
|
||||
u16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
u64 buffer_addr; /* Address of descriptor's data buf */
|
||||
u32 cmd_type_len;
|
||||
u32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
u64 rsvd; /* Reserved */
|
||||
u32 nxtseq_seed;
|
||||
u32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
u32 vlan_macip_lens;
|
||||
u32 seqnum_seed;
|
||||
u32 type_tucmd_mlhl;
|
||||
u32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_vfadapt,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
struct e1000_vf_stats {
|
||||
u64 base_gprc;
|
||||
u64 base_gptc;
|
||||
u64 base_gorc;
|
||||
u64 base_gotc;
|
||||
u64 base_mprc;
|
||||
u64 base_gotlbc;
|
||||
u64 base_gptlbc;
|
||||
u64 base_gorlbc;
|
||||
u64 base_gprlbc;
|
||||
|
||||
u32 last_gprc;
|
||||
u32 last_gptc;
|
||||
u32 last_gorc;
|
||||
u32 last_gotc;
|
||||
u32 last_mprc;
|
||||
u32 last_gotlbc;
|
||||
u32 last_gptlbc;
|
||||
u32 last_gorlbc;
|
||||
u32 last_gprlbc;
|
||||
|
||||
u64 gprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 mprc;
|
||||
u64 gotlbc;
|
||||
u64 gptlbc;
|
||||
u64 gorlbc;
|
||||
u64 gprlbc;
|
||||
};
|
||||
|
||||
#include "igbvf_mbx.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
/* Function pointers for the MAC. */
|
||||
s32 (*init_params)(struct e1000_hw *);
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
void (*clear_vfta)(struct e1000_hw *);
|
||||
s32 (*get_bus_info)(struct e1000_hw *);
|
||||
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
|
||||
void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
s32 (*setup_link)(struct e1000_hw *);
|
||||
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||
void (*mta_set)(struct e1000_hw *, u32);
|
||||
void (*rar_set)(struct e1000_hw *, u8*, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
};
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 rar_entry_count;
|
||||
|
||||
bool get_link_status;
|
||||
};
|
||||
|
||||
enum e1000_bus_type {
|
||||
e1000_bus_type_unknown = 0,
|
||||
e1000_bus_type_pci,
|
||||
e1000_bus_type_pcix,
|
||||
e1000_bus_type_pci_express,
|
||||
e1000_bus_type_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_speed {
|
||||
e1000_bus_speed_unknown = 0,
|
||||
e1000_bus_speed_33,
|
||||
e1000_bus_speed_66,
|
||||
e1000_bus_speed_100,
|
||||
e1000_bus_speed_120,
|
||||
e1000_bus_speed_133,
|
||||
e1000_bus_speed_2500,
|
||||
e1000_bus_speed_5000,
|
||||
e1000_bus_speed_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_width {
|
||||
e1000_bus_width_unknown = 0,
|
||||
e1000_bus_width_pcie_x1,
|
||||
e1000_bus_width_pcie_x2,
|
||||
e1000_bus_width_pcie_x4 = 4,
|
||||
e1000_bus_width_pcie_x8 = 8,
|
||||
e1000_bus_width_32,
|
||||
e1000_bus_width_64,
|
||||
e1000_bus_width_reserved
|
||||
};
|
||||
|
||||
struct e1000_bus_info {
|
||||
enum e1000_bus_type type;
|
||||
enum e1000_bus_speed speed;
|
||||
enum e1000_bus_width width;
|
||||
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*check_for_msg)(struct e1000_hw *, u16);
|
||||
s32 (*check_for_ack)(struct e1000_hw *, u16);
|
||||
s32 (*check_for_rst)(struct e1000_hw *, u16);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_vf {
|
||||
u32 vf_number;
|
||||
u32 v2p_mailbox;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_bus_info bus;
|
||||
struct e1000_mbx_info mbx;
|
||||
|
||||
union {
|
||||
struct e1000_dev_spec_vf vf;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
enum e1000_promisc_type {
|
||||
e1000_promisc_disabled = 0, /* all promisc modes disabled */
|
||||
e1000_promisc_unicast = 1, /* unicast promiscuous enabled */
|
||||
e1000_promisc_multicast = 2, /* multicast promiscuous enabled */
|
||||
e1000_promisc_enabled = 3, /* both uni and multicast promisc */
|
||||
e1000_num_promisc_types
|
||||
};
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
s32 igbvf_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
void igbvf_vfta_set_vf(struct e1000_hw *, u16, bool);
|
||||
void igbvf_rlpml_set_vf(struct e1000_hw *, u16);
|
||||
s32 igbvf_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type);
|
||||
#endif /* _IGBVF_VF_H_ */
|
||||
@@ -2061,7 +2061,7 @@ static int phantom_probe ( struct pci_device *pci,
|
||||
assert ( phantom->port < PHN_MAX_NUM_PORTS );
|
||||
settings_init ( &phantom->settings,
|
||||
&phantom_settings_operations,
|
||||
&netdev->refcnt, "clp", PHN_CLP_TAG_MAGIC );
|
||||
&netdev->refcnt, PHN_CLP_TAG_MAGIC );
|
||||
|
||||
/* Fix up PCI device */
|
||||
adjust_pci_device ( pci );
|
||||
@@ -2111,7 +2111,7 @@ static int phantom_probe ( struct pci_device *pci,
|
||||
/* Register settings blocks */
|
||||
parent_settings = netdev_settings ( netdev );
|
||||
if ( ( rc = register_settings ( &phantom->settings,
|
||||
parent_settings ) ) != 0 ) {
|
||||
parent_settings, "clp" ) ) != 0 ) {
|
||||
DBGC ( phantom, "Phantom %p could not register settings: "
|
||||
"%s\n", phantom, strerror ( rc ) );
|
||||
goto err_register_settings;
|
||||
|
||||
@@ -1832,7 +1832,7 @@ static void rtl8169_irq_disable ( struct rtl8169_private *tp )
|
||||
|
||||
DBGP ( "rtl8169_irq_disable\n" );
|
||||
|
||||
rtl8169_irq_mask_and_ack ( ioaddr );
|
||||
RTL_W16 ( IntrMask, 0x0000 );
|
||||
}
|
||||
|
||||
/*** iPXE Core API Routines ***/
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
* Indent Options: indent -kr -i8
|
||||
*************************************************************************/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include "etherboot.h"
|
||||
#include "nic.h"
|
||||
#include <ipxe/pci.h>
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
* Copyright (c) 2006 by Timothy Legge <tlegge@rogers.com>
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#ifndef VELOCITY_H
|
||||
#define VELOCITY_H
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ipxe/nvs.h>
|
||||
#include <ipxe/pci.h>
|
||||
#include <ipxe/pcivpd.h>
|
||||
#include <ipxe/nvsvpd.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Non-Volatile Storage using Vital Product Data
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Read from VPD
|
||||
*
|
||||
* @v nvs NVS device
|
||||
* @v address Starting address
|
||||
* @v buf Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int nvs_vpd_read ( struct nvs_device *nvs, unsigned int address,
|
||||
void *data, size_t len ) {
|
||||
struct nvs_vpd_device *nvsvpd =
|
||||
container_of ( nvs, struct nvs_vpd_device, nvs );
|
||||
int rc;
|
||||
|
||||
if ( ( rc = pci_vpd_read ( &nvsvpd->vpd, ( nvsvpd->address + address ),
|
||||
data, len ) ) != 0 ) {
|
||||
DBGC ( nvsvpd->vpd.pci, PCI_FMT " NVS could not read "
|
||||
"[%04x,%04zx): %s\n", PCI_ARGS ( nvsvpd->vpd.pci ),
|
||||
address, ( address + len ), strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to VPD
|
||||
*
|
||||
* @v nvs NVS device
|
||||
* @v address Starting address
|
||||
* @v buf Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int nvs_vpd_write ( struct nvs_device *nvs, unsigned int address,
|
||||
const void *data, size_t len ) {
|
||||
struct nvs_vpd_device *nvsvpd =
|
||||
container_of ( nvs, struct nvs_vpd_device, nvs );
|
||||
int rc;
|
||||
|
||||
if ( ( rc = pci_vpd_write ( &nvsvpd->vpd, ( nvsvpd->address + address ),
|
||||
data, len ) ) != 0 ) {
|
||||
DBGC ( nvsvpd->vpd.pci, PCI_FMT " NVS could not write "
|
||||
"[%04x,%04zx): %s\n", PCI_ARGS ( nvsvpd->vpd.pci ),
|
||||
address, ( address + len ), strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise NVS VPD device
|
||||
*
|
||||
* @v nvsvpd NVS VPD device
|
||||
* @v pci PCI device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci,
|
||||
unsigned int field ) {
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
/* Initialise VPD device */
|
||||
if ( ( rc = pci_vpd_init ( &nvsvpd->vpd, pci ) ) != 0 ) {
|
||||
DBGC ( pci, PCI_FMT " NVS could not initialise "
|
||||
"VPD: %s\n", PCI_ARGS ( pci ), strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Locate VPD field */
|
||||
if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &nvsvpd->address,
|
||||
&len ) ) != 0 ) {
|
||||
DBGC ( pci, PCI_FMT " NVS could not locate VPD field "
|
||||
PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
|
||||
PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Initialise NVS device */
|
||||
nvsvpd->nvs.block_size = 1;
|
||||
nvsvpd->nvs.size = len;
|
||||
nvsvpd->nvs.read = nvs_vpd_read;
|
||||
nvsvpd->nvs.write = nvs_vpd_write;
|
||||
|
||||
DBGC ( pci, PCI_FMT " NVS using VPD field " PCI_VPD_FIELD_FMT " at "
|
||||
"[%04x,%04x)\n", PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
|
||||
nvsvpd->address, ( nvsvpd->address + nvsvpd->nvs.size ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <hci/ifmgmt_cmd.h>
|
||||
#include <usr/autoboot.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Booting commands
|
||||
*
|
||||
*/
|
||||
|
||||
/** "autoboot" command descriptor */
|
||||
static struct command_descriptor autoboot_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>...]", "Attempt to boot the system" );
|
||||
|
||||
/**
|
||||
* "autoboot" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int autoboot_exec ( int argc, char **argv ) {
|
||||
|
||||
if ( argc != 1 ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s\n"
|
||||
"\n"
|
||||
"Attempts to boot the system\n",
|
||||
argv[0] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
autoboot();
|
||||
|
||||
/* Can never return success by definition */
|
||||
return 1;
|
||||
return ifcommon_exec ( argc, argv, &autoboot_cmd, netboot, 0 );
|
||||
}
|
||||
|
||||
struct command autoboot_command __command = {
|
||||
.name = "autoboot",
|
||||
.exec = autoboot_exec,
|
||||
/** Booting commands */
|
||||
struct command autoboot_commands[] __command = {
|
||||
{
|
||||
.name = "autoboot",
|
||||
.exec = autoboot_exec,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,38 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/settings.h>
|
||||
#include <ipxe/settings_ui.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
static int config_exec ( int argc, char **argv ) {
|
||||
char *settings_name;
|
||||
struct settings *settings;
|
||||
int rc;
|
||||
/** @file
|
||||
*
|
||||
* Configuration UI commands
|
||||
*
|
||||
*/
|
||||
|
||||
if ( argc > 2 ) {
|
||||
printf ( "Usage: %s [scope]\n"
|
||||
"Opens the option configuration console\n", argv[0] );
|
||||
return 1;
|
||||
}
|
||||
/** "config" options */
|
||||
struct config_options {};
|
||||
|
||||
settings_name = ( ( argc == 2 ) ? argv[1] : "" );
|
||||
settings = find_settings ( settings_name );
|
||||
if ( ! settings ) {
|
||||
printf ( "No such scope \"%s\"\n", settings_name );
|
||||
return 1;
|
||||
}
|
||||
/** "config" option list */
|
||||
static struct option_descriptor config_opts[] = {};
|
||||
|
||||
if ( ( rc = settings_ui ( settings ) ) != 0 ) {
|
||||
printf ( "Could not save settings: %s\n",
|
||||
strerror ( rc ) );
|
||||
return 1;
|
||||
/** "config" command descriptor */
|
||||
static struct command_descriptor config_cmd =
|
||||
COMMAND_DESC ( struct config_options, config_opts, 0, 1,
|
||||
"[<scope>]",
|
||||
"Open the option configuration console" );
|
||||
|
||||
/**
|
||||
* Parse settings scope name
|
||||
*
|
||||
* @v text Text
|
||||
* @ret value Integer value
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int parse_settings ( const char *text, struct settings **value ) {
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Parse scope name */
|
||||
*value = find_settings ( text );
|
||||
if ( ! *value ) {
|
||||
printf ( "\"%s\": no such scope\n", text );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* "config" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int config_exec ( int argc, char **argv ) {
|
||||
struct config_options opts;
|
||||
struct settings *settings;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &config_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse settings option, if present */
|
||||
if ( ( rc = parse_settings ( ( ( optind < argc ) ? argv[optind] : "" ),
|
||||
&settings ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Run settings UI */
|
||||
if ( ( rc = settings_ui ( settings ) ) != 0 ) {
|
||||
printf ( "Could not save settings: %s\n", strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Configuration UI commands */
|
||||
struct command config_command __command = {
|
||||
.name = "config",
|
||||
.exec = config_exec,
|
||||
|
||||
+35
-120
@@ -30,7 +30,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/in.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <usr/dhcpmgmt.h>
|
||||
#include <hci/ifmgmt_cmd.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -38,26 +40,19 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* "dhcp" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void dhcp_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s [<interface>] [<interface>...]\n"
|
||||
"\n"
|
||||
"Configure a network interface using DHCP\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "dhcp" command descriptor */
|
||||
static struct command_descriptor dhcp_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>] [<interface>...]",
|
||||
"Configure network interface(s) using DHCP" );
|
||||
|
||||
/**
|
||||
* Execute "dhcp" command for a network device
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int dhcp_exec_netdev ( struct net_device *netdev ) {
|
||||
static int dhcp_payload ( struct net_device *netdev ) {
|
||||
int rc;
|
||||
|
||||
if ( ( rc = dhcp ( netdev ) ) != 0 ) {
|
||||
@@ -67,145 +62,65 @@ static int dhcp_exec_netdev ( struct net_device *netdev ) {
|
||||
/* Close device on failure, to avoid memory exhaustion */
|
||||
netdev_close ( netdev );
|
||||
|
||||
return 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute "dhcp" command for a named network device
|
||||
*
|
||||
* @v netdev_name Network device name
|
||||
* @ret rc Exit code
|
||||
*/
|
||||
static int dhcp_exec_name ( const char *netdev_name ) {
|
||||
struct net_device *netdev;
|
||||
|
||||
netdev = find_netdev ( netdev_name );
|
||||
if ( ! netdev ) {
|
||||
printf ( "No such interface \"%s\"\n", netdev_name );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return dhcp_exec_netdev ( netdev );
|
||||
}
|
||||
|
||||
/**
|
||||
* The "dhcp" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int dhcp_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
const char *netdev_name;
|
||||
struct net_device *netdev;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
dhcp_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( optind != argc ) {
|
||||
/* Treat arguments as a list of interfaces to try */
|
||||
while ( optind != argc ) {
|
||||
netdev_name = argv[optind++];
|
||||
if ( ( rc = dhcp_exec_name ( netdev_name ) ) == 0 )
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Try all interfaces */
|
||||
for_each_netdev ( netdev ) {
|
||||
if ( ( rc = dhcp_exec_netdev ( netdev ) ) == 0 )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return ifcommon_exec ( argc, argv, &dhcp_cmd, dhcp_payload, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* "pxebs" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void pxebs_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <interface> <server_type>\n"
|
||||
"\n"
|
||||
"Perform PXE Boot Server discovery\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "pxebs" options */
|
||||
struct pxebs_options {};
|
||||
|
||||
/** "pxebs" option list */
|
||||
static struct option_descriptor pxebs_opts[] = {};
|
||||
|
||||
/** "pxebs" command descriptor */
|
||||
static struct command_descriptor pxebs_cmd =
|
||||
COMMAND_DESC ( struct pxebs_options, pxebs_opts, 2, 2,
|
||||
"<interface> <server_type>",
|
||||
"Perform PXE Boot Server discovery" );
|
||||
|
||||
/**
|
||||
* The "pxebs" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int pxebs_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
const char *netdev_txt;
|
||||
const char *pxe_type_txt;
|
||||
struct pxebs_options opts;
|
||||
struct net_device *netdev;
|
||||
unsigned int pxe_type;
|
||||
char *end;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
pxebs_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( optind != ( argc - 2 ) ) {
|
||||
pxebs_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
netdev_txt = argv[optind];
|
||||
pxe_type_txt = argv[ optind + 1 ];
|
||||
if ( ( rc = parse_options ( argc, argv, &pxebs_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse arguments */
|
||||
netdev = find_netdev ( netdev_txt );
|
||||
if ( ! netdev ) {
|
||||
printf ( "No such interface: %s\n", netdev_txt );
|
||||
return 1;
|
||||
}
|
||||
pxe_type = strtoul ( pxe_type_txt, &end, 0 );
|
||||
if ( *end ) {
|
||||
printf ( "Bad server type: %s\n", pxe_type_txt );
|
||||
return 1;
|
||||
}
|
||||
/* Parse net device name */
|
||||
if ( ( rc = parse_netdev ( argv[optind], &netdev ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse boot server type */
|
||||
if ( ( rc = parse_integer ( argv[ optind + 1 ], &pxe_type ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Perform Boot Server Discovery */
|
||||
if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 ) {
|
||||
printf ( "Could not discover boot server on %s: %s\n",
|
||||
netdev->name, strerror ( rc ) );
|
||||
return 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -16,28 +16,36 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/crypto.h>
|
||||
|
||||
#include <ipxe/md5.h>
|
||||
#include <ipxe/sha1.h>
|
||||
|
||||
/**
|
||||
* "digest" command syntax message
|
||||
/** @file
|
||||
*
|
||||
* Digest commands
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void digest_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <image name>\n"
|
||||
"\n"
|
||||
"Calculate the %s of an image\n",
|
||||
argv[0], argv[0] );
|
||||
}
|
||||
|
||||
/** "digest" options */
|
||||
struct digest_options {};
|
||||
|
||||
/** "digest" option list */
|
||||
static struct option_descriptor digest_opts[] = {};
|
||||
|
||||
/** "digest" command descriptor */
|
||||
static struct command_descriptor digest_cmd =
|
||||
COMMAND_DESC ( struct digest_options, digest_opts, 1, MAX_ARGUMENTS,
|
||||
"<image> [<image>...]",
|
||||
"Calculate the digest of an image" );
|
||||
|
||||
/**
|
||||
* The "digest" command
|
||||
@@ -45,11 +53,11 @@ static void digest_syntax ( char **argv ) {
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @v digest Digest algorithm
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int digest_exec ( int argc, char **argv,
|
||||
struct digest_algorithm *digest ) {
|
||||
const char *image_name;
|
||||
struct digest_options opts;
|
||||
struct image *image;
|
||||
uint8_t digest_ctx[digest->ctxsize];
|
||||
uint8_t digest_out[digest->digestsize];
|
||||
@@ -59,23 +67,17 @@ static int digest_exec ( int argc, char **argv,
|
||||
size_t frag_len;
|
||||
int i;
|
||||
unsigned j;
|
||||
int rc;
|
||||
|
||||
if ( argc < 2 ||
|
||||
!strcmp ( argv[1], "--help" ) ||
|
||||
!strcmp ( argv[1], "-h" ) ) {
|
||||
digest_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &digest_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
for ( i = 1 ; i < argc ; i++ ) {
|
||||
image_name = argv[i];
|
||||
for ( i = optind ; i < argc ; i++ ) {
|
||||
|
||||
/* find image */
|
||||
image = find_image ( image_name );
|
||||
if ( ! image ) {
|
||||
printf ( "No such image: %s\n", image_name );
|
||||
if ( ( rc = parse_image ( argv[i], &image ) ) != 0 )
|
||||
continue;
|
||||
}
|
||||
offset = 0;
|
||||
len = image->len;
|
||||
|
||||
|
||||
+136
-107
@@ -19,11 +19,13 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <strings.h>
|
||||
#include <ipxe/fc.h>
|
||||
#include <ipxe/fcels.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/tables.h>
|
||||
#include <usr/fcmgmt.h>
|
||||
|
||||
@@ -33,36 +35,96 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
static void fcstat_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n %s\n", argv[0] );
|
||||
/**
|
||||
* Parse Fibre Channel port name
|
||||
*
|
||||
* @v text Text
|
||||
* @ret port Fibre Channel port
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int parse_fc_port ( const char *text, struct fc_port **port ) {
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Find Fibre Channel port */
|
||||
*port = fc_port_find ( text );
|
||||
if ( ! *port ) {
|
||||
printf ( "\"%s\": no such port\n", text );
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Fibre Channel port ID
|
||||
*
|
||||
* @v text Text
|
||||
* @ret port_id Fibre Channel port ID
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int parse_fc_port_id ( const char *text, struct fc_port_id *port_id ) {
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Parse port ID */
|
||||
if ( ( rc = fc_id_aton ( text, port_id ) ) != 0 ) {
|
||||
printf ( "\"%s\": invalid port ID\n", text );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Fibre Channel ELS handler name
|
||||
*
|
||||
* @v text Text
|
||||
* @ret handler Fibre Channel ELS handler
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int parse_fc_els_handler ( const char *text,
|
||||
struct fc_els_handler **handler ) {
|
||||
|
||||
for_each_table_entry ( (*handler), FC_ELS_HANDLERS ) {
|
||||
if ( strcasecmp ( (*handler)->name, text ) == 0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf ( "\"%s\": unrecognised ELS\n", text );
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/** "fcstat" options */
|
||||
struct fcstat_options {};
|
||||
|
||||
/** "fcstat" option list */
|
||||
static struct option_descriptor fcstat_opts[] = {};
|
||||
|
||||
/** "fcstat" command descriptor */
|
||||
static struct command_descriptor fcstat_cmd =
|
||||
COMMAND_DESC ( struct fcstat_options, fcstat_opts, 0, 0,
|
||||
"", "" );
|
||||
|
||||
/**
|
||||
* The "fcstat" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int fcstat_exec ( int argc, char **argv ) {
|
||||
static struct option fcstat_opts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
struct fcstat_options opts;
|
||||
struct fc_port *port;
|
||||
struct fc_peer *peer;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", fcstat_opts,
|
||||
NULL ) ) >= 0 ) {
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
fcstat_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( optind != argc ) {
|
||||
fcstat_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &fcstat_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
list_for_each_entry ( port, &fc_ports, list )
|
||||
fcportstat ( port );
|
||||
@@ -72,105 +134,72 @@ static int fcstat_exec ( int argc, char **argv ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fcels_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n %s [--port <port>] [--id <peer port id>]"
|
||||
" <command>\n", argv[0] );
|
||||
}
|
||||
|
||||
static struct fc_els_handler * fcels_find_handler ( const char *name ) {
|
||||
struct fc_els_handler *handler;
|
||||
|
||||
for_each_table_entry ( handler, FC_ELS_HANDLERS ) {
|
||||
if ( strcasecmp ( handler->name, name ) == 0 )
|
||||
return handler;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int fcels_exec ( int argc, char **argv ) {
|
||||
static struct option fcels_opts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "id", required_argument, NULL, 'i' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
const char *handler_text;
|
||||
const char *port_text = NULL;
|
||||
const char *id_text = NULL;
|
||||
struct fc_els_handler *handler;
|
||||
/** "fcels" options */
|
||||
struct fcels_options {
|
||||
/** Fibre Channel port */
|
||||
struct fc_port *port;
|
||||
struct fc_port_id id_buf;
|
||||
/** Fibre Channel peer port ID */
|
||||
struct fc_port_id peer_port_id;
|
||||
};
|
||||
|
||||
/** "fcels" option list */
|
||||
static struct option_descriptor fcels_opts[] = {
|
||||
OPTION_DESC ( "port", 'p', required_argument,
|
||||
struct fcels_options, port, parse_fc_port ),
|
||||
OPTION_DESC ( "id", 'i', required_argument,
|
||||
struct fcels_options, peer_port_id, parse_fc_port_id ),
|
||||
};
|
||||
|
||||
/** "fcels" command descriptor */
|
||||
static struct command_descriptor fcels_cmd =
|
||||
COMMAND_DESC ( struct fcels_options, fcels_opts, 1, 1,
|
||||
"[--port <port>] [--id <peer_port_id>] <command>", "" );
|
||||
|
||||
/**
|
||||
* The "fcels" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int fcels_exec ( int argc, char **argv ) {
|
||||
struct fcels_options opts;
|
||||
struct fc_els_handler *handler;
|
||||
struct fc_port_id *id;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "hp:i:", fcels_opts,
|
||||
NULL ) ) >= 0 ) {
|
||||
switch ( c ) {
|
||||
case 'p':
|
||||
port_text = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
id_text = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
fcels_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &fcels_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Identify ELS */
|
||||
if ( optind != ( argc - 1 ) ) {
|
||||
fcels_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
handler_text = argv[optind];
|
||||
handler = fcels_find_handler ( handler_text );
|
||||
if ( ! handler ) {
|
||||
printf ( "%s: unrecognised ELS\n", handler_text );
|
||||
return 1;
|
||||
}
|
||||
/* Parse ELS handler */
|
||||
if ( ( rc = parse_fc_els_handler ( argv[optind], &handler ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Identify port */
|
||||
if ( port_text ) {
|
||||
/* Use specified port */
|
||||
port = fc_port_find ( port_text );
|
||||
if ( ! port ) {
|
||||
printf ( "%s: no such port\n", port_text );
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* Use first port */
|
||||
port = list_first_entry ( &fc_ports, struct fc_port, list );
|
||||
if ( ! port ) {
|
||||
/* Use first port if no port specified */
|
||||
if ( ! opts.port ) {
|
||||
opts.port = list_first_entry ( &fc_ports, struct fc_port,
|
||||
list );
|
||||
if ( ! opts.port ) {
|
||||
printf ( "No ports\n" );
|
||||
return 1;
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
assert ( port != NULL );
|
||||
|
||||
/* Identify port ID */
|
||||
if ( id_text ) {
|
||||
if ( fc_id_aton ( id_text, &id_buf ) != 0 ) {
|
||||
printf ( "%s: invalid port ID\n", id_text );
|
||||
return 1;
|
||||
}
|
||||
id = &id_buf;
|
||||
} else {
|
||||
if ( fc_link_ok ( &port->link ) &&
|
||||
! ( port->flags & FC_PORT_HAS_FABRIC ) ) {
|
||||
id = &port->ptp_link_port_id;
|
||||
/* Use link peer port ID if no peer port ID specified */
|
||||
id = &opts.peer_port_id;
|
||||
if ( memcmp ( id, &fc_empty_port_id, sizeof ( *id ) ) == 0 ) {
|
||||
if ( fc_link_ok ( &opts.port->link ) &&
|
||||
! ( opts.port->flags & FC_PORT_HAS_FABRIC ) ) {
|
||||
id = &opts.port->ptp_link_port_id;
|
||||
} else {
|
||||
id = &fc_f_port_id;
|
||||
}
|
||||
}
|
||||
assert ( id != NULL );
|
||||
|
||||
if ( fcels ( port, id, handler ) != 0 )
|
||||
return 1;
|
||||
/** Issue ELS */
|
||||
if ( ( rc = fcels ( opts.port, id, handler ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,14 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/gdbstub.h>
|
||||
|
||||
/** @file
|
||||
@@ -28,71 +33,76 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* "gdbstub" command syntax message
|
||||
* Parse GDB transport name
|
||||
*
|
||||
* @v argv Argument list
|
||||
* @v text Text
|
||||
* @ret trans GDB transport
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static void gdbstub_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <transport> [<options>...]\n"
|
||||
"\n"
|
||||
"Start remote debugging using one of the following transports:\n"
|
||||
" serial use serial port (if compiled in)\n"
|
||||
" udp <interface> use UDP over network interface (if compiled in)\n",
|
||||
argv[0] );
|
||||
static int parse_gdb_transport ( const char *text,
|
||||
struct gdb_transport **trans ) {
|
||||
|
||||
/* Sanity check */
|
||||
assert ( text != NULL );
|
||||
|
||||
/* Find transport */
|
||||
*trans = find_gdb_transport ( text );
|
||||
if ( ! *trans ) {
|
||||
printf ( "\"%s\": no such transport (is it compiled in?)\n",
|
||||
text );
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "gdbstub" options */
|
||||
struct gdbstub_options {};
|
||||
|
||||
/** "gdbstub" option list */
|
||||
static struct option_descriptor gdbstub_opts[] = {};
|
||||
|
||||
/** "gdbstub" command descriptor */
|
||||
static struct command_descriptor gdbstub_cmd =
|
||||
COMMAND_DESC ( struct gdbstub_options, gdbstub_opts, 1, MAX_ARGUMENTS,
|
||||
"<transport> [<options>...]",
|
||||
"Start remote debugging using one of the following "
|
||||
"transports:\n"
|
||||
" serial use serial port (if compiled in)\n"
|
||||
" udp <interface> use UDP over network interface "
|
||||
"(if compiled in)" );
|
||||
|
||||
/**
|
||||
* The "gdbstub" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int gdbstub_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
const char *trans_name;
|
||||
struct gdbstub_options opts;
|
||||
struct gdb_transport *trans;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
gdbstub_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &gdbstub_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* At least one argument */
|
||||
if ( optind == argc ) {
|
||||
gdbstub_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
|
||||
trans_name = argv[optind++];
|
||||
/* Parse transport name */
|
||||
if ( ( rc = parse_gdb_transport ( argv[optind++], &trans ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Initialise transport */
|
||||
trans = find_gdb_transport ( trans_name );
|
||||
if ( !trans ) {
|
||||
printf ( "%s: no such transport (is it compiled in?)\n", trans_name );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( trans->init ) {
|
||||
if ( trans->init ( argc - optind, &argv[optind] ) != 0 ) {
|
||||
return 1;
|
||||
if ( ( rc = trans->init ( argc - optind,
|
||||
&argv[optind] ) ) != 0 ) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter GDB stub */
|
||||
gdbstub_start ( trans );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <usr/ifmgmt.h>
|
||||
#include <hci/ifmgmt_cmd.h>
|
||||
|
||||
@@ -31,136 +33,138 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
/** Options shared by all if<xxx> commands */
|
||||
static struct option ifcommon_longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Print syntax of if<xxx> command
|
||||
*
|
||||
* @v argv Command arguments
|
||||
* @v verb Verb describing the action of the command
|
||||
*/
|
||||
static void ifcommon_syntax ( char **argv, const char *verb ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s [<interface>] [<interface>...]\n"
|
||||
"\n"
|
||||
"%s the specified network interfaces\n",
|
||||
argv[0], verb );
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute if<xxx> command over all network devices
|
||||
*
|
||||
* @v payload Command to execute
|
||||
* @ret rc Exit code
|
||||
*/
|
||||
static int ifcommon_do_all ( int ( * payload ) ( struct net_device * ) ) {
|
||||
struct net_device *netdev;
|
||||
int rc = 0;
|
||||
|
||||
/* Execute payload for each network device */
|
||||
for_each_netdev ( netdev ) {
|
||||
if ( payload ( netdev ) != 0 )
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute if<xxx> command over list of network devices
|
||||
*
|
||||
* @v payload Command to execute
|
||||
* @ret rc Exit code
|
||||
*/
|
||||
static int ifcommon_do_list ( int ( * payload ) ( struct net_device * ),
|
||||
char **list, unsigned int count ) {
|
||||
const char *netdev_name;
|
||||
struct net_device *netdev;
|
||||
int rc = 0;
|
||||
|
||||
while ( count-- ) {
|
||||
netdev_name = *(list++);
|
||||
netdev = find_netdev ( netdev_name );
|
||||
if ( ! netdev ) {
|
||||
printf ( "%s: no such interface\n", netdev_name );
|
||||
rc = 1;
|
||||
continue;
|
||||
}
|
||||
if ( payload ( netdev ) != 0 )
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/** "if<xxx>" command options */
|
||||
struct option_descriptor ifcommon_opts[0];
|
||||
|
||||
/**
|
||||
* Execute if<xxx> command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @v cmd Command descriptor
|
||||
* @v payload Command to execute
|
||||
* @v verb Verb describing the action of the command
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int ifcommon_exec ( int argc, char **argv,
|
||||
struct command_descriptor *cmd,
|
||||
int ( * payload ) ( struct net_device * ),
|
||||
const char *verb ) {
|
||||
int c;
|
||||
int stop_on_first_success ) {
|
||||
struct ifcommon_options opts;
|
||||
struct net_device *netdev;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", ifcommon_longopts,
|
||||
NULL ) ) >= 0 ) {
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
ifcommon_syntax ( argv, verb );
|
||||
return 1;
|
||||
if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
if ( optind != argc ) {
|
||||
/* Treat arguments as a list of interfaces to try */
|
||||
while ( optind != argc ) {
|
||||
if ( ( rc = parse_netdev ( argv[optind++],
|
||||
&netdev ) ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
if ( ( ( rc = payload ( netdev ) ) == 0 ) &&
|
||||
stop_on_first_success ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Try all interfaces */
|
||||
rc = -ENODEV;
|
||||
for_each_netdev ( netdev ) {
|
||||
if ( ( ( rc = payload ( netdev ) ) == 0 ) &&
|
||||
stop_on_first_success ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( optind == argc ) {
|
||||
return ifcommon_do_all ( payload );
|
||||
} else {
|
||||
return ifcommon_do_list ( payload, &argv[optind],
|
||||
( argc - optind ) );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* "ifopen" command */
|
||||
/** "ifopen" command descriptor */
|
||||
static struct command_descriptor ifopen_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>...]",
|
||||
"Open network interface(s)" );
|
||||
|
||||
/**
|
||||
* "ifopen" payload
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int ifopen_payload ( struct net_device *netdev ) {
|
||||
return ifopen ( netdev );
|
||||
}
|
||||
|
||||
/**
|
||||
* The "ifopen" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int ifopen_exec ( int argc, char **argv ) {
|
||||
return ifcommon_exec ( argc, argv, ifopen_payload, "Open" );
|
||||
return ifcommon_exec ( argc, argv, &ifopen_cmd, ifopen_payload, 0 );
|
||||
}
|
||||
|
||||
/* "ifclose" command */
|
||||
/** "ifclose" command descriptor */
|
||||
static struct command_descriptor ifclose_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>...]",
|
||||
"Close network interface(s)" );
|
||||
|
||||
/**
|
||||
* "ifclose" payload
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int ifclose_payload ( struct net_device *netdev ) {
|
||||
ifclose ( netdev );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "ifclose" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int ifclose_exec ( int argc, char **argv ) {
|
||||
return ifcommon_exec ( argc, argv, ifclose_payload, "Close" );
|
||||
return ifcommon_exec ( argc, argv, &ifclose_cmd, ifclose_payload, 0 );
|
||||
}
|
||||
|
||||
/* "ifstat" command */
|
||||
/** "ifstat" command descriptor */
|
||||
static struct command_descriptor ifstat_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>...]",
|
||||
"Show network interface(s)" );
|
||||
|
||||
/**
|
||||
* "ifstat" payload
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int ifstat_payload ( struct net_device *netdev ) {
|
||||
ifstat ( netdev );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "ifstat" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int ifstat_exec ( int argc, char **argv ) {
|
||||
return ifcommon_exec ( argc, argv,
|
||||
ifstat_payload, "Display status of" );
|
||||
return ifcommon_exec ( argc, argv, &ifstat_cmd, ifstat_payload, 0 );
|
||||
}
|
||||
|
||||
/** Interface management commands */
|
||||
|
||||
+157
-316
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <getopt.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <usr/imgmgmt.h>
|
||||
|
||||
/** @file
|
||||
@@ -34,12 +35,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
enum image_action {
|
||||
IMG_FETCH = 0,
|
||||
IMG_LOAD,
|
||||
IMG_EXEC,
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill in image command line
|
||||
*
|
||||
@@ -74,74 +69,61 @@ static int imgfill_cmdline ( struct image *image, unsigned int nargs,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "imgfetch"/"module"/"kernel" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void imgfetch_core_syntax ( char **argv, enum image_action action ) {
|
||||
static const char *actions[] = {
|
||||
[IMG_FETCH] = "Fetch",
|
||||
[IMG_LOAD] = "Fetch and load",
|
||||
[IMG_EXEC] = "Fetch and execute",
|
||||
};
|
||||
/** "imgfetch" options */
|
||||
struct imgfetch_options {
|
||||
/** Image name */
|
||||
const char *name;
|
||||
};
|
||||
|
||||
printf ( "Usage:\n"
|
||||
" %s [-n|--name <name>] filename [arguments...]\n"
|
||||
"\n"
|
||||
"%s executable/loadable image\n",
|
||||
argv[0], actions[action] );
|
||||
}
|
||||
/** "imgfetch" option list */
|
||||
static struct option_descriptor imgfetch_opts[] = {
|
||||
OPTION_DESC ( "name", 'n', required_argument,
|
||||
struct imgfetch_options, name, parse_string ),
|
||||
};
|
||||
|
||||
/** "imgfetch" command descriptor */
|
||||
static struct command_descriptor imgfetch_cmd =
|
||||
COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
|
||||
"[--name <name>] <image_url> [<arguments>...]",
|
||||
"Fetch image" );
|
||||
|
||||
/** "kernel" command descriptor */
|
||||
static struct command_descriptor kernel_cmd =
|
||||
COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
|
||||
"[--name <name>] <image_url> [<arguments>...]",
|
||||
"Fetch and load image" );
|
||||
|
||||
/** "chain" command descriptor */
|
||||
static struct command_descriptor chain_cmd =
|
||||
COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
|
||||
"[--name <name>] <image_url> [<arguments>...]",
|
||||
"Fetch and execute image" );
|
||||
|
||||
/**
|
||||
* The "imgfetch"/"module"/"kernel" command body
|
||||
* The "imgfetch" and friends command body
|
||||
*
|
||||
* @v image_type Image type to assign (or NULL)
|
||||
* @v load Image will be automatically loaded after fetching
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @v cmd Command descriptor
|
||||
* @v image_register Image registration action
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgfetch_core_exec ( struct image_type *image_type,
|
||||
enum image_action action,
|
||||
int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "name", required_argument, NULL, 'n' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
static int imgfetch_core_exec ( int argc, char **argv,
|
||||
struct command_descriptor *cmd,
|
||||
int ( * image_register ) ( struct image * ) ) {
|
||||
struct imgfetch_options opts;
|
||||
struct image *image;
|
||||
const char *name = NULL;
|
||||
char *filename;
|
||||
int ( * image_register ) ( struct image *image );
|
||||
int c;
|
||||
char *uri_string;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "hn:",
|
||||
longopts, NULL ) ) >= 0 ) {
|
||||
switch ( c ) {
|
||||
case 'n':
|
||||
/* Set image name */
|
||||
name = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
imgfetch_core_syntax ( argv, action );
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Need at least a filename remaining after the options */
|
||||
if ( optind == argc ) {
|
||||
imgfetch_core_syntax ( argv, action );
|
||||
return -EINVAL;
|
||||
}
|
||||
filename = argv[optind++];
|
||||
if ( ! name )
|
||||
name = basename ( filename );
|
||||
/* Parse URI string */
|
||||
uri_string = argv[optind];
|
||||
if ( ! opts.name )
|
||||
opts.name = basename ( uri_string );
|
||||
|
||||
/* Allocate image */
|
||||
image = alloc_image();
|
||||
@@ -151,37 +133,18 @@ static int imgfetch_core_exec ( struct image_type *image_type,
|
||||
}
|
||||
|
||||
/* Fill in image name */
|
||||
if ( name ) {
|
||||
if ( ( rc = image_set_name ( image, name ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Set image type (if specified) */
|
||||
image->type = image_type;
|
||||
if ( ( rc = image_set_name ( image, opts.name ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Fill in command line */
|
||||
if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
|
||||
&argv[optind] ) ) != 0 )
|
||||
if ( ( rc = imgfill_cmdline ( image, ( argc - optind - 1 ),
|
||||
&argv[ optind + 1 ] ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Fetch the image */
|
||||
switch ( action ) {
|
||||
case IMG_FETCH:
|
||||
image_register = register_image;
|
||||
break;
|
||||
case IMG_LOAD:
|
||||
image_register = register_and_autoload_image;
|
||||
break;
|
||||
case IMG_EXEC:
|
||||
image_register = register_and_autoexec_image;
|
||||
break;
|
||||
default:
|
||||
assert ( 0 );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( ( rc = imgfetch ( image, filename, image_register ) ) != 0 ) {
|
||||
if ( ( rc = imgfetch ( image, uri_string, image_register ) ) != 0 ) {
|
||||
printf ( "Could not fetch %s: %s\n",
|
||||
filename, strerror ( rc ) );
|
||||
uri_string, strerror ( rc ) );
|
||||
image_put ( image );
|
||||
return rc;
|
||||
}
|
||||
@@ -195,16 +158,12 @@ static int imgfetch_core_exec ( struct image_type *image_type,
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgfetch_exec ( int argc, char **argv ) {
|
||||
int rc;
|
||||
|
||||
if ( ( rc = imgfetch_core_exec ( NULL, IMG_FETCH,
|
||||
argc, argv ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
return imgfetch_core_exec ( argc, argv, &imgfetch_cmd,
|
||||
register_image );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,15 +171,12 @@ static int imgfetch_exec ( int argc, char **argv ) {
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int kernel_exec ( int argc, char **argv ) {
|
||||
int rc;
|
||||
|
||||
if ( ( rc = imgfetch_core_exec ( NULL, IMG_LOAD, argc, argv ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
return imgfetch_core_exec ( argc, argv, &kernel_cmd,
|
||||
register_and_autoload_image );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,327 +184,211 @@ static int kernel_exec ( int argc, char **argv ) {
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int chain_exec ( int argc, char **argv) {
|
||||
int rc;
|
||||
|
||||
if ( ( rc = imgfetch_core_exec ( NULL, IMG_EXEC, argc, argv ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
return imgfetch_core_exec ( argc, argv, &chain_cmd,
|
||||
register_and_autoexec_image );
|
||||
}
|
||||
|
||||
/**
|
||||
* "imgload" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void imgload_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <image name>\n"
|
||||
"\n"
|
||||
"Load executable/loadable image\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "imgload" options */
|
||||
struct imgload_options {};
|
||||
|
||||
/** "imgload" option list */
|
||||
static struct option_descriptor imgload_opts[] = {};
|
||||
|
||||
/** "imgload" command descriptor */
|
||||
static struct command_descriptor imgload_cmd =
|
||||
COMMAND_DESC ( struct imgload_options, imgload_opts, 1, 1,
|
||||
"<image>", "Load image" );
|
||||
|
||||
/**
|
||||
* The "imgload" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgload_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
struct imgload_options opts;
|
||||
struct image *image;
|
||||
const char *name;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
imgload_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &imgload_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Need exactly one image name remaining after the options */
|
||||
if ( optind != ( argc - 1 ) ) {
|
||||
imgload_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
name = argv[optind];
|
||||
/* Parse image name */
|
||||
if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Load all specified images */
|
||||
image = find_image ( name );
|
||||
if ( ! image ) {
|
||||
printf ( "No such image: %s\n", name );
|
||||
return 1;
|
||||
}
|
||||
/* Load image */
|
||||
if ( ( rc = imgload ( image ) ) != 0 ) {
|
||||
printf ( "Could not load %s: %s\n", name, strerror ( rc ) );
|
||||
printf ( "Could not load %s: %s\n",
|
||||
image->name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* "imgargs" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void imgargs_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <image name> [<arguments>...]\n"
|
||||
"\n"
|
||||
"Set arguments for executable/loadable image\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "imgargs" options */
|
||||
struct imgargs_options {};
|
||||
|
||||
/** "imgargs" option list */
|
||||
static struct option_descriptor imgargs_opts[] = {};
|
||||
|
||||
/** "imgargs" command descriptor */
|
||||
static struct command_descriptor imgargs_cmd =
|
||||
COMMAND_DESC ( struct imgargs_options, imgargs_opts, 1, MAX_ARGUMENTS,
|
||||
"<image> [<arguments>...]",
|
||||
"Set arguments for image" );
|
||||
|
||||
/**
|
||||
* The "imgargs" command body
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgargs_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
struct imgargs_options opts;
|
||||
struct image *image;
|
||||
const char *name;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
imgargs_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Need at least an image name remaining after the options */
|
||||
if ( optind == argc ) {
|
||||
imgargs_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
name = argv[optind++];
|
||||
|
||||
/* Fill in command line */
|
||||
image = find_image ( name );
|
||||
if ( ! image ) {
|
||||
printf ( "No such image: %s\n", name );
|
||||
return 1;
|
||||
}
|
||||
if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
|
||||
&argv[optind] ) ) != 0 )
|
||||
if ( ( rc = parse_options ( argc, argv, &imgargs_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse image name */
|
||||
if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Fill in command line */
|
||||
if ( ( rc = imgfill_cmdline ( image, ( argc - optind - 1 ),
|
||||
&argv[ optind + 1 ] ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* "imgexec" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void imgexec_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <image name>\n"
|
||||
"\n"
|
||||
"Execute executable/loadable image\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "imgexec" options */
|
||||
struct imgexec_options {};
|
||||
|
||||
/** "imgexec" option list */
|
||||
static struct option_descriptor imgexec_opts[] = {};
|
||||
|
||||
/** "imgexec" command descriptor */
|
||||
static struct command_descriptor imgexec_cmd =
|
||||
COMMAND_DESC ( struct imgexec_options, imgexec_opts, 0, 1,
|
||||
"[<image>]", "Execute image" );
|
||||
|
||||
/**
|
||||
* The "imgexec" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgexec_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
struct imgexec_options opts;
|
||||
struct image *image;
|
||||
const char *name = NULL;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
imgexec_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &imgexec_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Need no more than one image name */
|
||||
if ( optind != argc )
|
||||
name = argv[optind++];
|
||||
if ( optind != argc ) {
|
||||
imgexec_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Execute specified image */
|
||||
if ( name ) {
|
||||
image = find_image ( name );
|
||||
if ( ! image ) {
|
||||
printf ( "No such image: %s\n", name );
|
||||
return 1;
|
||||
}
|
||||
/* Parse image name */
|
||||
if ( optind < argc ) {
|
||||
if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
|
||||
return rc;
|
||||
} else {
|
||||
image = imgautoselect();
|
||||
if ( ! image ) {
|
||||
printf ( "No (unique) loaded image\n" );
|
||||
return 1;
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute image */
|
||||
if ( ( rc = imgexec ( image ) ) != 0 ) {
|
||||
printf ( "Could not execute %s: %s\n",
|
||||
image->name, strerror ( rc ) );
|
||||
return 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* "imgstat" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void imgstat_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s\n"
|
||||
"\n"
|
||||
"List executable/loadable images\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "imgstat" options */
|
||||
struct imgstat_options {};
|
||||
|
||||
/** "imgstat" option list */
|
||||
static struct option_descriptor imgstat_opts[] = {};
|
||||
|
||||
/** "imgstat" command descriptor */
|
||||
static struct command_descriptor imgstat_cmd =
|
||||
COMMAND_DESC ( struct imgstat_options, imgstat_opts, 0, 0,
|
||||
"", "List images" );
|
||||
|
||||
/**
|
||||
* The "imgstat" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgstat_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
struct imgstat_options opts;
|
||||
struct image *image;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
imgstat_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* No arguments */
|
||||
if ( optind != argc ) {
|
||||
imgstat_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &imgstat_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Show status of all images */
|
||||
for_each_image ( image ) {
|
||||
imgstat ( image );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* "imgstat" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void imgfree_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s [<image name>]\n"
|
||||
"\n"
|
||||
"Free one or all executable/loadable images\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "imgfree" options */
|
||||
struct imgfree_options {};
|
||||
|
||||
/** "imgfree" option list */
|
||||
static struct option_descriptor imgfree_opts[] = {};
|
||||
|
||||
/** "imgfree" command descriptor */
|
||||
static struct command_descriptor imgfree_cmd =
|
||||
COMMAND_DESC ( struct imgfree_options, imgfree_opts, 0, 1,
|
||||
"[<image>]", "Free image(s)" );
|
||||
|
||||
/**
|
||||
* The "imgfree" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgfree_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
struct imgfree_options opts;
|
||||
struct image *image;
|
||||
struct image *tmp;
|
||||
const char *name = NULL;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
imgfree_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &imgfree_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Need no more than one image name */
|
||||
if ( optind != argc )
|
||||
name = argv[optind++];
|
||||
if ( optind != argc ) {
|
||||
imgfree_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( name ) {
|
||||
/* Free specified image (may leak) */
|
||||
image = find_image ( name );
|
||||
if ( ! image ) {
|
||||
printf ( "No such image: %s\n", name );
|
||||
return 1;
|
||||
}
|
||||
if ( optind < argc ) {
|
||||
/* Free specified image */
|
||||
if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 )
|
||||
return rc;
|
||||
imgfree ( image );
|
||||
} else {
|
||||
/* Free all images */
|
||||
@@ -556,6 +396,7 @@ static int imgfree_exec ( int argc, char **argv ) {
|
||||
imgfree ( image );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,28 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/net80211.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <usr/iwmgmt.h>
|
||||
#include <hci/ifmgmt_cmd.h>
|
||||
|
||||
/* "iwstat" command */
|
||||
/** @file
|
||||
*
|
||||
* Wireless interface management commands
|
||||
*
|
||||
*/
|
||||
|
||||
/** "iwstat" command descriptor */
|
||||
static struct command_descriptor iwstat_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>...]",
|
||||
"Show wireless interface(s)" );
|
||||
|
||||
/**
|
||||
* "iwstat" payload
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int iwstat_payload ( struct net_device *netdev ) {
|
||||
struct net80211_device *dev = net80211_get ( netdev );
|
||||
|
||||
@@ -35,13 +52,29 @@ static int iwstat_payload ( struct net_device *netdev ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "iwstat" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int iwstat_exec ( int argc, char **argv ) {
|
||||
return ifcommon_exec ( argc, argv,
|
||||
iwstat_payload, "Display wireless status of" );
|
||||
return ifcommon_exec ( argc, argv, &iwstat_cmd, iwstat_payload, 0 );
|
||||
}
|
||||
|
||||
/* "iwlist" command */
|
||||
/** "iwlist" command descriptor */
|
||||
static struct command_descriptor iwlist_cmd =
|
||||
COMMAND_DESC ( struct ifcommon_options, ifcommon_opts, 0, MAX_ARGUMENTS,
|
||||
"[<interface>...]",
|
||||
"List wireless networks" );
|
||||
|
||||
/**
|
||||
* "iwlist" payload
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int iwlist_payload ( struct net_device *netdev ) {
|
||||
struct net80211_device *dev = net80211_get ( netdev );
|
||||
|
||||
@@ -51,9 +84,15 @@ static int iwlist_payload ( struct net_device *netdev ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "iwlist" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int iwlist_exec ( int argc, char **argv ) {
|
||||
return ifcommon_exec ( argc, argv, iwlist_payload,
|
||||
"List wireless networks available via" );
|
||||
return ifcommon_exec ( argc, argv, &iwlist_cmd, iwlist_payload, 0 );
|
||||
}
|
||||
|
||||
/** Wireless interface management commands */
|
||||
|
||||
@@ -1,28 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/login_ui.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Login commands
|
||||
*
|
||||
*/
|
||||
|
||||
/** "login" options */
|
||||
struct login_options {};
|
||||
|
||||
/** "login" option list */
|
||||
static struct option_descriptor login_opts[] = {};
|
||||
|
||||
/** "login" command descriptor */
|
||||
static struct command_descriptor login_cmd =
|
||||
COMMAND_DESC ( struct login_options, login_opts, 0, 0,
|
||||
"", "Prompt for login credentials" );
|
||||
|
||||
/**
|
||||
* "login" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int login_exec ( int argc, char **argv ) {
|
||||
struct login_options opts;
|
||||
int rc;
|
||||
|
||||
if ( argc > 1 ) {
|
||||
printf ( "Usage: %s\n"
|
||||
"Prompt for login credentials\n", argv[0] );
|
||||
return 1;
|
||||
}
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &login_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Show login UI */
|
||||
if ( ( rc = login_ui() ) != 0 ) {
|
||||
printf ( "Could not set credentials: %s\n",
|
||||
strerror ( rc ) );
|
||||
return 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Login commands */
|
||||
struct command login_command __command = {
|
||||
.name = "login",
|
||||
.exec = login_exec,
|
||||
|
||||
@@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <getopt.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/if_ether.h>
|
||||
#include <usr/lotest.h>
|
||||
|
||||
@@ -33,81 +34,63 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
static void lotest_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n %s <sending interface> <receiving interface>\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "lotest" options */
|
||||
struct lotest_options {
|
||||
/** MTU */
|
||||
unsigned int mtu;
|
||||
};
|
||||
|
||||
/** "lotest" option list */
|
||||
static struct option_descriptor lotest_opts[] = {
|
||||
OPTION_DESC ( "mtu", 'm', required_argument,
|
||||
struct lotest_options, mtu, parse_integer ),
|
||||
};
|
||||
|
||||
/** "lotest" command descriptor */
|
||||
static struct command_descriptor lotest_cmd =
|
||||
COMMAND_DESC ( struct lotest_options, lotest_opts, 2, 2,
|
||||
"[--mtu <mtu>] <sending_interface> "
|
||||
"<receiving_interface>", "" );
|
||||
|
||||
/**
|
||||
* "lotest" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lotest_exec ( int argc, char **argv ) {
|
||||
static struct option lotest_opts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "mtu", required_argument, NULL, 'm' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
const char *sender_name;
|
||||
const char *receiver_name;
|
||||
const char *mtu_text = NULL;
|
||||
struct lotest_options opts;
|
||||
struct net_device *sender;
|
||||
struct net_device *receiver;
|
||||
char *endp;
|
||||
size_t mtu;
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
/* Parse command line */
|
||||
while ( ( c = getopt_long ( argc, argv, "hm:", lotest_opts,
|
||||
NULL ) ) >= 0 ) {
|
||||
switch ( c ) {
|
||||
case 'm':
|
||||
mtu_text = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
lotest_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( optind != ( argc - 2 ) ) {
|
||||
lotest_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
sender_name = argv[optind];
|
||||
receiver_name = argv[optind + 1];
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &lotest_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Identify network devices */
|
||||
sender = find_netdev ( sender_name );
|
||||
if ( ! sender ) {
|
||||
printf ( "%s: no such interface\n", sender_name );
|
||||
return 1;
|
||||
}
|
||||
receiver = find_netdev ( receiver_name );
|
||||
if ( ! receiver ) {
|
||||
printf ( "%s: no such interface\n", receiver_name );
|
||||
return 1;
|
||||
}
|
||||
/* Parse sending interface name */
|
||||
if ( ( rc = parse_netdev ( argv[optind], &sender ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Identify MTU */
|
||||
if ( mtu_text ) {
|
||||
mtu = strtoul ( mtu_text, &endp, 10 );
|
||||
if ( *endp ) {
|
||||
printf ( "%s: invalid MTU\n", mtu_text );
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
mtu = ETH_MAX_MTU;
|
||||
}
|
||||
/* Parse receiving interface name */
|
||||
if ( ( rc = parse_netdev ( argv[ optind + 1 ], &receiver ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Use default MTU if none specified */
|
||||
if ( ! opts.mtu )
|
||||
opts.mtu = ETH_MAX_MTU;
|
||||
|
||||
/* Perform loopback test */
|
||||
if ( ( rc = loopback_test ( sender, receiver, mtu ) ) != 0 ) {
|
||||
if ( ( rc = loopback_test ( sender, receiver, opts.mtu ) ) != 0 ) {
|
||||
printf ( "Test failed: %s\n", strerror ( rc ) );
|
||||
return 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Loopback testing commands */
|
||||
struct command lotest_command __command = {
|
||||
.name = "lotest",
|
||||
.exec = lotest_exec,
|
||||
|
||||
+121
-25
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -6,42 +24,96 @@
|
||||
#include <getopt.h>
|
||||
#include <ipxe/settings.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Non-volatile option commands
|
||||
*
|
||||
*/
|
||||
|
||||
/** "show" options */
|
||||
struct show_options {};
|
||||
|
||||
/** "show" option list */
|
||||
static struct option_descriptor show_opts[] = {};
|
||||
|
||||
/** "show" command descriptor */
|
||||
static struct command_descriptor show_cmd =
|
||||
COMMAND_DESC ( struct show_options, show_opts, 1, 1,
|
||||
"<setting>", "" );
|
||||
|
||||
/**
|
||||
* "show" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int show_exec ( int argc, char **argv ) {
|
||||
struct show_options opts;
|
||||
const char *name;
|
||||
char buf[256];
|
||||
int rc;
|
||||
|
||||
if ( argc != 2 ) {
|
||||
printf ( "Syntax: %s <identifier>\n", argv[0] );
|
||||
return 1;
|
||||
}
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &show_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
if ( ( rc = fetchf_named_setting ( argv[1], buf,
|
||||
sizeof ( buf ) ) ) < 0 ){
|
||||
/* Parse setting name */
|
||||
name = argv[optind];
|
||||
|
||||
/* Fetch setting */
|
||||
if ( ( rc = fetchf_named_setting ( name, buf,
|
||||
sizeof ( buf ) ) ) < 0 ) {
|
||||
printf ( "Could not find \"%s\": %s\n",
|
||||
argv[1], strerror ( rc ) );
|
||||
return 1;
|
||||
name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
printf ( "%s = %s\n", argv[1], buf );
|
||||
/* Print setting value */
|
||||
printf ( "%s = %s\n", name, buf );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "set" options */
|
||||
struct set_options {};
|
||||
|
||||
/** "set" option list */
|
||||
static struct option_descriptor set_opts[] = {};
|
||||
|
||||
/** "set" command descriptor */
|
||||
static struct command_descriptor set_cmd =
|
||||
COMMAND_DESC ( struct set_options, set_opts, 1, MAX_ARGUMENTS,
|
||||
"<setting> <value>", "" );
|
||||
|
||||
/**
|
||||
* "set" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int set_exec ( int argc, char **argv ) {
|
||||
struct set_options opts;
|
||||
const char *name;
|
||||
size_t len;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
if ( argc < 3 ) {
|
||||
printf ( "Syntax: %s <identifier> <value>\n", argv[0] );
|
||||
return 1;
|
||||
}
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &set_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse setting name */
|
||||
name = argv[optind];
|
||||
|
||||
/* Determine total length of command line */
|
||||
len = 1; /* NUL */
|
||||
for ( i = 2 ; i < argc ; i++ )
|
||||
for ( i = optind + 1 ; i < argc ; i++ )
|
||||
len += ( 1 /* possible space */ + strlen ( argv[i] ) );
|
||||
|
||||
{
|
||||
@@ -50,39 +122,63 @@ static int set_exec ( int argc, char **argv ) {
|
||||
|
||||
/* Assemble command line */
|
||||
buf[0] = '\0';
|
||||
for ( i = 2 ; i < argc ; i++ ) {
|
||||
for ( i = optind + 1 ; i < argc ; i++ ) {
|
||||
ptr += sprintf ( ptr, "%s%s", ( buf[0] ? " " : "" ),
|
||||
argv[i] );
|
||||
}
|
||||
assert ( ptr < ( buf + len ) );
|
||||
|
||||
if ( ( rc = storef_named_setting ( argv[1], buf ) ) != 0 ) {
|
||||
if ( ( rc = storef_named_setting ( name, buf ) ) != 0 ) {
|
||||
printf ( "Could not set \"%s\"=\"%s\": %s\n",
|
||||
argv[1], buf, strerror ( rc ) );
|
||||
return 1;
|
||||
name, buf, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "clear" options */
|
||||
struct clear_options {};
|
||||
|
||||
/** "clear" option list */
|
||||
static struct option_descriptor clear_opts[] = {};
|
||||
|
||||
/** "clear" command descriptor */
|
||||
static struct command_descriptor clear_cmd =
|
||||
COMMAND_DESC ( struct clear_options, clear_opts, 1, 1,
|
||||
"<setting>", "" );
|
||||
|
||||
/**
|
||||
* "clear" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int clear_exec ( int argc, char **argv ) {
|
||||
struct clear_options opts;
|
||||
const char *name;
|
||||
int rc;
|
||||
|
||||
if ( argc != 2 ) {
|
||||
printf ( "Syntax: %s <identifier>\n", argv[0] );
|
||||
return 1;
|
||||
}
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &clear_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
if ( ( rc = delete_named_setting ( argv[1] ) ) != 0 ) {
|
||||
/* Parse setting name */
|
||||
name = argv[optind];
|
||||
|
||||
/* Clear setting */
|
||||
if ( ( rc = delete_named_setting ( name ) ) != 0 ) {
|
||||
printf ( "Could not clear \"%s\": %s\n",
|
||||
argv[1], strerror ( rc ) );
|
||||
return 1;
|
||||
name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Non-volatile option commands */
|
||||
struct command nvo_commands[] __command = {
|
||||
{
|
||||
.name = "show",
|
||||
|
||||
@@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <usr/route.h>
|
||||
|
||||
/** @file
|
||||
@@ -29,52 +30,34 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* "route" command syntax message
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void route_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s\n"
|
||||
"\n"
|
||||
"Displays the routing table\n",
|
||||
argv[0] );
|
||||
}
|
||||
/** "route" options */
|
||||
struct route_options {};
|
||||
|
||||
/** "route" option list */
|
||||
static struct option_descriptor route_opts[] = {};
|
||||
|
||||
/** "route" command descriptor */
|
||||
static struct command_descriptor route_cmd =
|
||||
COMMAND_DESC ( struct route_options, route_opts, 0, 0,
|
||||
"", "Display the routing table" );
|
||||
|
||||
/**
|
||||
* The "route" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int route_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
int c;
|
||||
struct route_options opts;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
route_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( optind != argc ) {
|
||||
route_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &route_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
route();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,69 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <usr/autoboot.h>
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/**
|
||||
* "sanboot" command syntax message
|
||||
/** @file
|
||||
*
|
||||
* SAN commands
|
||||
*
|
||||
* @v argv Argument list
|
||||
*/
|
||||
static void sanboot_syntax ( char **argv ) {
|
||||
printf ( "Usage:\n"
|
||||
" %s <root-path>\n"
|
||||
"\n"
|
||||
"Boot from SAN target\n",
|
||||
argv[0] );
|
||||
}
|
||||
|
||||
/** "sanboot" options */
|
||||
struct sanboot_options {};
|
||||
|
||||
/** "sanboot" option list */
|
||||
static struct option_descriptor sanboot_opts[] = {};
|
||||
|
||||
/** "sanboot" command descriptor */
|
||||
static struct command_descriptor sanboot_cmd =
|
||||
COMMAND_DESC ( struct sanboot_options, sanboot_opts, 1, 1,
|
||||
"<root-path>", "Boot from SAN target" );
|
||||
|
||||
/**
|
||||
* The "sanboot" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Exit code
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int sanboot_exec ( int argc, char **argv ) {
|
||||
static struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
const char *root_path = NULL;
|
||||
int c;
|
||||
struct sanboot_options opts;
|
||||
const char *root_path;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
|
||||
switch ( c ) {
|
||||
case 'h':
|
||||
/* Display help text */
|
||||
default:
|
||||
/* Unrecognised/invalid option */
|
||||
sanboot_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( ( rc = parse_options ( argc, argv, &sanboot_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Need exactly one image name remaining after the options */
|
||||
if ( optind != ( argc - 1 ) ) {
|
||||
sanboot_syntax ( argv );
|
||||
return 1;
|
||||
}
|
||||
/* Parse root path */
|
||||
root_path = argv[optind];
|
||||
|
||||
/* Boot from root path */
|
||||
if ( ( rc = boot_root_path ( root_path ) ) != 0 ) {
|
||||
printf ( "Could not boot from %s: %s\n",
|
||||
root_path, strerror ( rc ) );
|
||||
return 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** SAN commands */
|
||||
struct command sanboot_command __command = {
|
||||
.name = "sanboot",
|
||||
.exec = sanboot_exec,
|
||||
|
||||
+63
-27
@@ -19,29 +19,50 @@
|
||||
* Shao Miller <shao.miller@yrdsb.edu.on.ca>.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/nap.h>
|
||||
#include <ipxe/timer.h>
|
||||
|
||||
static int time_exec ( int argc, char **argv ) {
|
||||
unsigned long start;
|
||||
int rc, secs;
|
||||
/** @file
|
||||
*
|
||||
* Time commands
|
||||
*
|
||||
*/
|
||||
|
||||
if ( argc == 1 ||
|
||||
!strcmp ( argv[1], "--help" ) ||
|
||||
!strcmp ( argv[1], "-h" ) )
|
||||
{
|
||||
printf ( "Usage:\n"
|
||||
" %s <command>\n"
|
||||
"\n"
|
||||
"Time a command\n",
|
||||
argv[0] );
|
||||
return 1;
|
||||
}
|
||||
/** "time" options */
|
||||
struct time_options {};
|
||||
|
||||
/** "time" option list */
|
||||
static struct option_descriptor time_opts[] = {};
|
||||
|
||||
/** "time" command descriptor */
|
||||
static struct command_descriptor time_cmd =
|
||||
COMMAND_DESC ( struct time_options, time_opts, 1, MAX_ARGUMENTS,
|
||||
"<command>", "Time a command" );
|
||||
|
||||
/**
|
||||
* "time" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int time_exec ( int argc, char **argv ) {
|
||||
struct time_options opts;
|
||||
unsigned long start;
|
||||
int secs;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &time_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
start = currticks();
|
||||
rc = execv ( argv[1], argv + 1 );
|
||||
@@ -52,25 +73,39 @@ static int time_exec ( int argc, char **argv ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** "time" command */
|
||||
struct command time_command __command = {
|
||||
.name = "time",
|
||||
.exec = time_exec,
|
||||
};
|
||||
|
||||
static int sleep_exec ( int argc, char **argv ) {
|
||||
unsigned long start, delay;
|
||||
/** "sleep" options */
|
||||
struct sleep_options {};
|
||||
|
||||
/** "sleep" option list */
|
||||
static struct option_descriptor sleep_opts[] = {};
|
||||
|
||||
/** "sleep" command descriptor */
|
||||
static struct command_descriptor sleep_cmd =
|
||||
COMMAND_DESC ( struct sleep_options, sleep_opts, 1, 1,
|
||||
"<seconds>", "Sleep for <seconds> seconds" );
|
||||
|
||||
/**
|
||||
* "sleep" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int sleep_exec ( int argc, char **argv ) {
|
||||
struct sleep_options opts;
|
||||
unsigned long start, delay;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &sleep_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
if ( argc == 1 ||
|
||||
!strcmp ( argv[1], "--help" ) ||
|
||||
!strcmp ( argv[1], "-h" ))
|
||||
{
|
||||
printf ( "Usage:\n"
|
||||
" %s <seconds>\n"
|
||||
"\n"
|
||||
"Sleep for <seconds> seconds\n",
|
||||
argv[0] );
|
||||
return 1;
|
||||
}
|
||||
start = currticks();
|
||||
delay = strtoul ( argv[1], NULL, 0 ) * ticks_per_sec();
|
||||
while ( ( currticks() - start ) <= delay )
|
||||
@@ -78,6 +113,7 @@ static int sleep_exec ( int argc, char **argv ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "sleep" command */
|
||||
struct command sleep_command __command = {
|
||||
.name = "sleep",
|
||||
.exec = sleep_exec,
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/vlan.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* VLAN commands
|
||||
*
|
||||
*/
|
||||
|
||||
/** "vcreate" options */
|
||||
struct vcreate_options {
|
||||
/** VLAN tag */
|
||||
unsigned int tag;
|
||||
/** VLAN default priority */
|
||||
unsigned int priority;
|
||||
};
|
||||
|
||||
/** "vcreate" option list */
|
||||
static struct option_descriptor vcreate_opts[] = {
|
||||
OPTION_DESC ( "tag", 't', required_argument,
|
||||
struct vcreate_options, tag, parse_integer ),
|
||||
OPTION_DESC ( "priority", 'p', required_argument,
|
||||
struct vcreate_options, priority, parse_integer ),
|
||||
};
|
||||
|
||||
/** "vcreate" command descriptor */
|
||||
static struct command_descriptor vcreate_cmd =
|
||||
COMMAND_DESC ( struct vcreate_options, vcreate_opts, 1, 1,
|
||||
"--tag <tag> [--priority <priority>] "
|
||||
"<trunk interface>",
|
||||
"Create a VLAN interface" );
|
||||
|
||||
/**
|
||||
* "vcreate" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int vcreate_exec ( int argc, char **argv ) {
|
||||
struct vcreate_options opts;
|
||||
struct net_device *trunk;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &vcreate_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse trunk interface */
|
||||
if ( ( rc = parse_netdev ( argv[optind], &trunk ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Create VLAN device */
|
||||
if ( ( rc = vlan_create ( trunk, opts.tag, opts.priority ) ) != 0 ) {
|
||||
printf ( "Could not create VLAN device: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "vdestroy" options */
|
||||
struct vdestroy_options {};
|
||||
|
||||
/** "vdestroy" option list */
|
||||
static struct option_descriptor vdestroy_opts[] = {};
|
||||
|
||||
/** "vdestroy" command descriptor */
|
||||
static struct command_descriptor vdestroy_cmd =
|
||||
COMMAND_DESC ( struct vdestroy_options, vdestroy_opts, 1, 1,
|
||||
"<VLAN interface>",
|
||||
"Destroy a VLAN interface" );
|
||||
|
||||
/**
|
||||
* "vdestroy" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int vdestroy_exec ( int argc, char **argv ) {
|
||||
struct vdestroy_options opts;
|
||||
struct net_device *netdev;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &vdestroy_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse trunk interface */
|
||||
if ( ( rc = parse_netdev ( argv[optind], &netdev ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Destroy VLAN device */
|
||||
if ( ( rc = vlan_destroy ( netdev ) ) != 0 ) {
|
||||
printf ( "Could not destroy VLAN device: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** VLAN commands */
|
||||
struct command vlan_commands[] __command = {
|
||||
{
|
||||
.name = "vcreate",
|
||||
.exec = vcreate_exec,
|
||||
},
|
||||
{
|
||||
.name = "vdestroy",
|
||||
.exec = vdestroy_exec,
|
||||
},
|
||||
};
|
||||
+56
-29
@@ -21,8 +21,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <readline/readline.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/shell.h>
|
||||
|
||||
/** @file
|
||||
@@ -34,29 +36,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
/** The shell prompt string */
|
||||
static const char shell_prompt[] = "iPXE> ";
|
||||
|
||||
/** Flag set in order to exit shell */
|
||||
static int exit_flag = 0;
|
||||
|
||||
/** "exit" command body */
|
||||
static int exit_exec ( int argc, char **argv __unused ) {
|
||||
|
||||
if ( argc == 1 ) {
|
||||
exit_flag = 1;
|
||||
} else {
|
||||
printf ( "Usage: exit\n"
|
||||
"Exits the command shell\n" );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "exit" command definition */
|
||||
struct command exit_command __command = {
|
||||
.name = "exit",
|
||||
.exec = exit_exec,
|
||||
};
|
||||
|
||||
/** "help" command body */
|
||||
/**
|
||||
* "help" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int help_exec ( int argc __unused, char **argv __unused ) {
|
||||
struct command *command;
|
||||
unsigned int hpos = 0;
|
||||
@@ -78,7 +64,7 @@ static int help_exec ( int argc __unused, char **argv __unused ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "help" command definition */
|
||||
/** "help" command */
|
||||
struct command help_command __command = {
|
||||
.name = "help",
|
||||
.exec = help_exec,
|
||||
@@ -88,15 +74,56 @@ struct command help_command __command = {
|
||||
* Start command shell
|
||||
*
|
||||
*/
|
||||
void shell ( void ) {
|
||||
int shell ( void ) {
|
||||
char *line;
|
||||
int rc = 0;
|
||||
|
||||
exit_flag = 0;
|
||||
while ( ! exit_flag ) {
|
||||
do {
|
||||
line = readline ( shell_prompt );
|
||||
if ( line ) {
|
||||
system ( line );
|
||||
rc = system ( line );
|
||||
free ( line );
|
||||
}
|
||||
}
|
||||
} while ( ! shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** "shell" options */
|
||||
struct shell_options {};
|
||||
|
||||
/** "shell" option list */
|
||||
static struct option_descriptor shell_opts[] = {};
|
||||
|
||||
/** "shell" command descriptor */
|
||||
static struct command_descriptor shell_cmd =
|
||||
COMMAND_DESC ( struct shell_options, shell_opts, 0, 0,
|
||||
"", "" );
|
||||
|
||||
/**
|
||||
* "shell" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int shell_exec ( int argc, char **argv ) {
|
||||
struct shell_options opts;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &shell_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Start shell */
|
||||
if ( ( rc = shell() ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "shell" command */
|
||||
struct command shell_command __command = {
|
||||
.name = "shell",
|
||||
.exec = shell_exec,
|
||||
};
|
||||
|
||||
+198
-30
@@ -27,12 +27,110 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <ipxe/command.h>
|
||||
#include <ipxe/parseopt.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/shell.h>
|
||||
|
||||
struct image_type script_image_type __image_type ( PROBE_NORMAL );
|
||||
|
||||
/** Currently running script
|
||||
*
|
||||
* This is a global in order to allow goto_exec() to update the
|
||||
* offset.
|
||||
*/
|
||||
static struct image *script;
|
||||
|
||||
/** Offset within current script
|
||||
*
|
||||
* This is a global in order to allow goto_exec() to update the
|
||||
* offset.
|
||||
*/
|
||||
static size_t script_offset;
|
||||
|
||||
/**
|
||||
* Process script lines
|
||||
*
|
||||
* @v process_line Line processor
|
||||
* @v terminate Termination check
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int process_script ( int ( * process_line ) ( const char *line ),
|
||||
int ( * terminate ) ( int rc ) ) {
|
||||
off_t eol;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
script_offset = 0;
|
||||
|
||||
do {
|
||||
|
||||
/* Find length of next line, excluding any terminating '\n' */
|
||||
eol = memchr_user ( script->data, script_offset, '\n',
|
||||
( script->len - script_offset ) );
|
||||
if ( eol < 0 )
|
||||
eol = script->len;
|
||||
len = ( eol - script_offset );
|
||||
|
||||
/* Copy line, terminate with NUL, and execute command */
|
||||
{
|
||||
char cmdbuf[ len + 1 ];
|
||||
|
||||
copy_from_user ( cmdbuf, script->data,
|
||||
script_offset, len );
|
||||
cmdbuf[len] = '\0';
|
||||
DBG ( "$ %s\n", cmdbuf );
|
||||
|
||||
/* Move to next line */
|
||||
script_offset += ( len + 1 );
|
||||
|
||||
/* Process line */
|
||||
rc = process_line ( cmdbuf );
|
||||
if ( terminate ( rc ) )
|
||||
return rc;
|
||||
}
|
||||
|
||||
} while ( script_offset < script->len );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate script processing on shell exit or command failure
|
||||
*
|
||||
* @v rc Line processing status
|
||||
* @ret terminate Terminate script processing
|
||||
*/
|
||||
static int terminate_on_exit_or_failure ( int rc ) {
|
||||
|
||||
return ( shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) ||
|
||||
( rc != 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script line
|
||||
*
|
||||
* @v line Line of script
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int script_exec_line ( const char *line ) {
|
||||
int rc;
|
||||
|
||||
/* Skip label lines */
|
||||
if ( line[0] == ':' )
|
||||
return 0;
|
||||
|
||||
/* Execute command */
|
||||
if ( ( rc = system ( line ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script
|
||||
*
|
||||
@@ -40,9 +138,8 @@ struct image_type script_image_type __image_type ( PROBE_NORMAL );
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int script_exec ( struct image *image ) {
|
||||
size_t offset = 0;
|
||||
off_t eol;
|
||||
size_t len;
|
||||
struct image *saved_script;
|
||||
size_t saved_offset;
|
||||
int rc;
|
||||
|
||||
/* Temporarily de-register image, so that a "boot" command
|
||||
@@ -50,36 +147,19 @@ static int script_exec ( struct image *image ) {
|
||||
*/
|
||||
unregister_image ( image );
|
||||
|
||||
while ( offset < image->len ) {
|
||||
|
||||
/* Find length of next line, excluding any terminating '\n' */
|
||||
eol = memchr_user ( image->data, offset, '\n',
|
||||
( image->len - offset ) );
|
||||
if ( eol < 0 )
|
||||
eol = image->len;
|
||||
len = ( eol - offset );
|
||||
/* Preserve state of any currently-running script */
|
||||
saved_script = script;
|
||||
saved_offset = script_offset;
|
||||
|
||||
/* Copy line, terminate with NUL, and execute command */
|
||||
{
|
||||
char cmdbuf[ len + 1 ];
|
||||
/* Initialise state for this script */
|
||||
script = image;
|
||||
|
||||
copy_from_user ( cmdbuf, image->data, offset, len );
|
||||
cmdbuf[len] = '\0';
|
||||
DBG ( "$ %s\n", cmdbuf );
|
||||
if ( ( rc = system ( cmdbuf ) ) != 0 ) {
|
||||
DBG ( "Command \"%s\" failed: %s\n",
|
||||
cmdbuf, strerror ( rc ) );
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to next line */
|
||||
offset += ( len + 1 );
|
||||
}
|
||||
/* Process script */
|
||||
rc = process_script ( script_exec_line, terminate_on_exit_or_failure );
|
||||
|
||||
rc = 0;
|
||||
done:
|
||||
/* Re-register image and return */
|
||||
/* Restore saved state, re-register image, and return */
|
||||
script_offset = saved_offset;
|
||||
script = saved_script;
|
||||
register_image ( image );
|
||||
return rc;
|
||||
}
|
||||
@@ -129,3 +209,91 @@ struct image_type script_image_type __image_type ( PROBE_NORMAL ) = {
|
||||
.load = script_load,
|
||||
.exec = script_exec,
|
||||
};
|
||||
|
||||
/** "goto" options */
|
||||
struct goto_options {};
|
||||
|
||||
/** "goto" option list */
|
||||
static struct option_descriptor goto_opts[] = {};
|
||||
|
||||
/** "goto" command descriptor */
|
||||
static struct command_descriptor goto_cmd =
|
||||
COMMAND_DESC ( struct goto_options, goto_opts, 1, 1,
|
||||
"<label>", "" );
|
||||
|
||||
/**
|
||||
* Current "goto" label
|
||||
*
|
||||
* Valid only during goto_exec(). Consider this part of a closure.
|
||||
*/
|
||||
static const char *goto_label;
|
||||
|
||||
/**
|
||||
* Check for presence of label
|
||||
*
|
||||
* @v line Script line
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int goto_find_label ( const char *line ) {
|
||||
|
||||
if ( line[0] != ':' )
|
||||
return -ENOENT;
|
||||
if ( strcmp ( goto_label, &line[1] ) != 0 )
|
||||
return -ENOENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate script processing when label is found
|
||||
*
|
||||
* @v rc Line processing status
|
||||
* @ret terminate Terminate script processing
|
||||
*/
|
||||
static int terminate_on_label_found ( int rc ) {
|
||||
return ( rc == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* "goto" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int goto_exec ( int argc, char **argv ) {
|
||||
struct goto_options opts;
|
||||
size_t saved_offset;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &goto_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Sanity check */
|
||||
if ( ! script ) {
|
||||
printf ( "Not in a script\n" );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Parse label */
|
||||
goto_label = argv[optind];
|
||||
|
||||
/* Find label */
|
||||
saved_offset = script_offset;
|
||||
if ( ( rc = process_script ( goto_find_label,
|
||||
terminate_on_label_found ) ) != 0 ) {
|
||||
script_offset = saved_offset;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Terminate processing of current command */
|
||||
shell_stop ( SHELL_STOP_COMMAND );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** "goto" command */
|
||||
struct command goto_command __command = {
|
||||
.name = "goto",
|
||||
.exec = goto_exec,
|
||||
};
|
||||
|
||||
@@ -272,6 +272,8 @@ extern void dbg_autocolourise ( unsigned long id );
|
||||
extern void dbg_decolourise ( void );
|
||||
extern void dbg_hex_dump_da ( unsigned long dispaddr,
|
||||
const void *data, unsigned long len );
|
||||
extern void dbg_md5_da ( unsigned long dispaddr,
|
||||
const void *data, unsigned long len );
|
||||
extern void dbg_pause ( void );
|
||||
extern void dbg_more ( void );
|
||||
|
||||
@@ -349,6 +351,37 @@ int __debug_disable;
|
||||
DBG_HDA_IF ( level, _data, _data, len ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* Print an MD5 checksum if we are at a certain debug level
|
||||
*
|
||||
* @v level Debug level
|
||||
* @v dispaddr Display address
|
||||
* @v data Data to print
|
||||
* @v len Length of data
|
||||
*/
|
||||
#define DBG_MD5A_IF( level, dispaddr, data, len ) do { \
|
||||
if ( DBG_ ## level ) { \
|
||||
union { \
|
||||
unsigned long ul; \
|
||||
typeof ( dispaddr ) raw; \
|
||||
} da; \
|
||||
da.raw = dispaddr; \
|
||||
dbg_md5_da ( da.ul, data, len ); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* Print an MD5 checksum if we are at a certain debug level
|
||||
*
|
||||
* @v level Debug level
|
||||
* @v data Data to print
|
||||
* @v len Length of data
|
||||
*/
|
||||
#define DBG_MD5_IF( level, data, len ) do { \
|
||||
const void *_data = data; \
|
||||
DBG_MD5A_IF ( level, _data, _data, len ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* Prompt for key press if we are at a certain debug level
|
||||
*
|
||||
@@ -419,6 +452,18 @@ int __debug_disable;
|
||||
DBG_DC_IF ( level ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define DBGC_MD5A_IF( level, id, ... ) do { \
|
||||
DBG_AC_IF ( level, id ); \
|
||||
DBG_MD5A_IF ( level, __VA_ARGS__ ); \
|
||||
DBG_DC_IF ( level ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define DBGC_MD5_IF( level, id, ... ) do { \
|
||||
DBG_AC_IF ( level, id ); \
|
||||
DBG_MD5_IF ( level, __VA_ARGS__ ); \
|
||||
DBG_DC_IF ( level ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define DBGC_PAUSE_IF( level, id ) do { \
|
||||
DBG_AC_IF ( level, id ); \
|
||||
DBG_PAUSE_IF ( level ); \
|
||||
@@ -436,11 +481,15 @@ int __debug_disable;
|
||||
#define DBG( ... ) DBG_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBG_HDA( ... ) DBG_HDA_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBG_HD( ... ) DBG_HD_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBG_MD5A( ... ) DBG_MD5A_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBG_MD5( ... ) DBG_MD5_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBG_PAUSE( ... ) DBG_PAUSE_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBG_MORE( ... ) DBG_MORE_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC( ... ) DBGC_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC_HDA( ... ) DBGC_HDA_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC_HD( ... ) DBGC_HD_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC_MD5A( ... ) DBGC_MD5A_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC_MD5( ... ) DBGC_MD5_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC_PAUSE( ... ) DBGC_PAUSE_IF ( LOG, ##__VA_ARGS__ )
|
||||
#define DBGC_MORE( ... ) DBGC_MORE_IF ( LOG, ##__VA_ARGS__ )
|
||||
|
||||
@@ -449,11 +498,15 @@ int __debug_disable;
|
||||
#define DBG2( ... ) DBG_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBG2_HDA( ... ) DBG_HDA_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBG2_HD( ... ) DBG_HD_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBG2_MD5A( ... ) DBG_MD5A_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBG2_MD5( ... ) DBG_MD5_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBG2_PAUSE( ... ) DBG_PAUSE_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBG2_MORE( ... ) DBG_MORE_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2( ... ) DBGC_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2_HDA( ... ) DBGC_HDA_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2_HD( ... ) DBGC_HD_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2_MD5A( ... ) DBGC_MD5A_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2_MD5( ... ) DBGC_MD5_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2_PAUSE( ... ) DBGC_PAUSE_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
#define DBGC2_MORE( ... ) DBGC_MORE_IF ( EXTRA, ##__VA_ARGS__ )
|
||||
|
||||
@@ -462,11 +515,15 @@ int __debug_disable;
|
||||
#define DBGP( ... ) DBG_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGP_HDA( ... ) DBG_HDA_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGP_HD( ... ) DBG_HD_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGP_MD5A( ... ) DBG_MD5A_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGP_MD5( ... ) DBG_MD5_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGP_PAUSE( ... ) DBG_PAUSE_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGP_MORE( ... ) DBG_MORE_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP( ... ) DBGC_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP_HDA( ... ) DBGC_HDA_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP_HD( ... ) DBGC_HD_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP_MD5A( ... ) DBGC_MD5A_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP_MD5( ... ) DBGC_MD5_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP_PAUSE( ... ) DBGC_PAUSE_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
#define DBGCP_MORE( ... ) DBGC_MORE_IF ( PROFILE, ##__VA_ARGS__ )
|
||||
|
||||
@@ -475,11 +532,15 @@ int __debug_disable;
|
||||
#define DBGIO( ... ) DBG_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGIO_HDA( ... ) DBG_HDA_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGIO_HD( ... ) DBG_HD_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGIO_MD5A( ... ) DBG_MD5A_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGIO_MD5( ... ) DBG_MD5_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGIO_PAUSE( ... ) DBG_PAUSE_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGIO_MORE( ... ) DBG_MORE_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO( ... ) DBGC_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO_HDA( ... ) DBGC_HDA_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO_HD( ... ) DBGC_HD_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO_MD5A( ... ) DBGC_MD5A_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO_MD5( ... ) DBGC_MD5_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO_PAUSE( ... ) DBGC_PAUSE_IF ( IO, ##__VA_ARGS__ )
|
||||
#define DBGCIO_MORE( ... ) DBGC_MORE_IF ( IO, ##__VA_ARGS__ )
|
||||
|
||||
@@ -537,6 +598,19 @@ int __debug_disable;
|
||||
/** Declare a function to be always inline */
|
||||
#define __always_inline __attribute__ (( always_inline ))
|
||||
|
||||
/* Force all inline functions to not be instrumented
|
||||
*
|
||||
* This is required to cope with what seems to be a long-standing gcc
|
||||
* bug, in which -finstrument-functions will cause instances of
|
||||
* inlined functions to be reported as further calls to the
|
||||
* *containing* function. This makes instrumentation very difficult
|
||||
* to use.
|
||||
*
|
||||
* Work around this problem by adding the no_instrument_function
|
||||
* attribute to all inlined functions.
|
||||
*/
|
||||
#define inline inline __attribute__ (( no_instrument_function ))
|
||||
|
||||
/**
|
||||
* Shared data.
|
||||
*
|
||||
|
||||
@@ -21,10 +21,17 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <ipxe/parseopt.h>
|
||||
|
||||
struct net_device;
|
||||
|
||||
struct ifcommon_options {};
|
||||
|
||||
extern struct option_descriptor ifcommon_opts[0];
|
||||
|
||||
extern int ifcommon_exec ( int argc, char **argv,
|
||||
struct command_descriptor *cmd,
|
||||
int ( * payload ) ( struct net_device * ),
|
||||
const char *verb );
|
||||
int stop_on_first_success );
|
||||
|
||||
#endif /* _IFMGMT_CMD_H */
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_ONLY );
|
||||
|
||||
#ifndef _LINUX_I82365_H
|
||||
#define _LINUX_I82365_H
|
||||
|
||||
|
||||
@@ -620,8 +620,8 @@ struct dhcphdr {
|
||||
/** Setting block name used for BootServerDHCP responses */
|
||||
#define PXEBS_SETTINGS_NAME "pxebs"
|
||||
|
||||
extern void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen,
|
||||
uint16_t *flags );
|
||||
extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
|
||||
uint16_t *flags );
|
||||
extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
||||
struct net_device *netdev, uint8_t msgtype,
|
||||
const void *options, size_t options_len,
|
||||
|
||||
@@ -59,6 +59,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_acpi ( ERRFILE_CORE | 0x00130000 )
|
||||
#define ERRFILE_null_sanboot ( ERRFILE_CORE | 0x00140000 )
|
||||
#define ERRFILE_edd ( ERRFILE_CORE | 0x00150000 )
|
||||
#define ERRFILE_parseopt ( ERRFILE_CORE | 0x00160000 )
|
||||
|
||||
#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
|
||||
#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
|
||||
@@ -66,6 +67,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_mca ( ERRFILE_DRIVER | 0x00030000 )
|
||||
#define ERRFILE_pci ( ERRFILE_DRIVER | 0x00040000 )
|
||||
#define ERRFILE_linux ( ERRFILE_DRIVER | 0x00050000 )
|
||||
#define ERRFILE_pcivpd ( ERRFILE_DRIVER | 0x00060000 )
|
||||
|
||||
#define ERRFILE_nvs ( ERRFILE_DRIVER | 0x00100000 )
|
||||
#define ERRFILE_spi ( ERRFILE_DRIVER | 0x00110000 )
|
||||
@@ -133,6 +135,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_jme ( ERRFILE_DRIVER | 0x005b0000 )
|
||||
#define ERRFILE_virtio_net ( ERRFILE_DRIVER | 0x005c0000 )
|
||||
#define ERRFILE_tap ( ERRFILE_DRIVER | 0x005d0000 )
|
||||
#define ERRFILE_igbvf_main ( ERRFILE_DRIVER | 0x005e0000 )
|
||||
|
||||
#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
|
||||
#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
|
||||
@@ -190,6 +193,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_fcp ( ERRFILE_NET | 0x002d0000 )
|
||||
#define ERRFILE_fcoe ( ERRFILE_NET | 0x002e0000 )
|
||||
#define ERRFILE_fcns ( ERRFILE_NET | 0x002f0000 )
|
||||
#define ERRFILE_vlan ( ERRFILE_NET | 0x00300000 )
|
||||
|
||||
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
|
||||
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
|
||||
@@ -226,6 +230,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_iwmgmt ( ERRFILE_OTHER | 0x00190000 )
|
||||
#define ERRFILE_linux_smbios ( ERRFILE_OTHER | 0x001a0000 )
|
||||
#define ERRFILE_lotest ( ERRFILE_OTHER | 0x001b0000 )
|
||||
#define ERRFILE_config_cmd ( ERRFILE_OTHER | 0x001c0000 )
|
||||
#define ERRFILE_ifmgmt_cmd ( ERRFILE_OTHER | 0x001d0000 )
|
||||
#define ERRFILE_fcmgmt_cmd ( ERRFILE_OTHER | 0x001e0000 )
|
||||
#define ERRFILE_gdbstub_cmd ( ERRFILE_OTHER | 0x001f0000 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -325,7 +325,8 @@ extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
|
||||
extern void fc_port_logout ( struct fc_port *port, int rc );
|
||||
extern int fc_port_open ( struct interface *transport,
|
||||
const struct fc_name *node_wwn,
|
||||
const struct fc_name *port_wwn );
|
||||
const struct fc_name *port_wwn,
|
||||
const char *name );
|
||||
extern struct fc_port * fc_port_find ( const char *name );
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -86,4 +86,7 @@ enum fcoe_eof {
|
||||
FCOE_EOF_A = 0x50, /**< End of Frame Abort */
|
||||
};
|
||||
|
||||
/** FCoE VLAN priority */
|
||||
#define FCOE_VLAN_PRIORITY 3
|
||||
|
||||
#endif /* _IPXE_FCOE_H */
|
||||
|
||||
@@ -51,6 +51,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define DHCP_EB_FEATURE_COMBOOT 0x23 /**< COMBOOT format */
|
||||
#define DHCP_EB_FEATURE_EFI 0x24 /**< EFI format */
|
||||
#define DHCP_EB_FEATURE_FCOE 0x25 /**< FCoE protocol */
|
||||
#define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ETH_P_IP 0x0800 /* Internet Protocl Packet */
|
||||
#define ETH_P_ARP 0x0806 /* Address Resolution Protocol */
|
||||
#define ETH_P_RARP 0x8035 /* Reverse Address resolution Protocol */
|
||||
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
|
||||
#define ETH_P_IPV6 0x86DD /* IPv6 over blueblook */
|
||||
#define ETH_P_SLOW 0x8809 /* Ethernet slow protocols */
|
||||
#define ETH_P_EAPOL 0x888E /* 802.1X EAP over LANs */
|
||||
|
||||
@@ -89,6 +89,10 @@ struct ib_address_vector {
|
||||
unsigned int gid_present;
|
||||
/** GID, if present */
|
||||
union ib_gid gid;
|
||||
/** VLAN is present */
|
||||
unsigned int vlan_present;
|
||||
/** VLAN, if present */
|
||||
unsigned int vlan;
|
||||
};
|
||||
|
||||
/** An Infiniband Work Queue */
|
||||
|
||||
@@ -36,15 +36,26 @@ struct device;
|
||||
/** Maximum length of a link-layer header
|
||||
*
|
||||
* The longest currently-supported link-layer header is for 802.11: a
|
||||
* 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header. (The
|
||||
* IPoIB link-layer pseudo-header doesn't actually include link-layer
|
||||
* addresses; see ipoib.c for details).
|
||||
* 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header, plus a
|
||||
* possible 4-byte VLAN header. (The IPoIB link-layer pseudo-header
|
||||
* doesn't actually include link-layer addresses; see ipoib.c for
|
||||
* details.)
|
||||
*/
|
||||
#define MAX_LL_HEADER_LEN 32
|
||||
#define MAX_LL_HEADER_LEN 36
|
||||
|
||||
/** Maximum length of a network-layer address */
|
||||
#define MAX_NET_ADDR_LEN 4
|
||||
|
||||
/** Maximum length of a network-layer header
|
||||
*
|
||||
* The longest currently-supported network-layer header is for IPv6 at
|
||||
* 40 bytes.
|
||||
*/
|
||||
#define MAX_NET_HEADER_LEN 40
|
||||
|
||||
/** Maximum combined length of a link-layer and network-layer header */
|
||||
#define MAX_LL_NET_HEADER_LEN ( MAX_LL_HEADER_LEN + MAX_NET_HEADER_LEN )
|
||||
|
||||
/**
|
||||
* A network-layer protocol
|
||||
*
|
||||
@@ -268,7 +279,7 @@ struct net_device {
|
||||
/** List of open network devices */
|
||||
struct list_head open_list;
|
||||
/** Name of this network device */
|
||||
char name[8];
|
||||
char name[12];
|
||||
/** Underlying hardware device */
|
||||
struct device *dev;
|
||||
|
||||
@@ -333,6 +344,9 @@ struct net_device {
|
||||
/** Network device interrupts are enabled */
|
||||
#define NETDEV_IRQ_ENABLED 0x0002
|
||||
|
||||
/** Network device receive queue processing is frozen */
|
||||
#define NETDEV_RX_FROZEN 0x0004
|
||||
|
||||
/** Link-layer protocol table */
|
||||
#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
|
||||
|
||||
@@ -475,8 +489,7 @@ netdev_settings ( struct net_device *netdev ) {
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
netdev_settings_init ( struct net_device *netdev ) {
|
||||
generic_settings_init ( &netdev->settings,
|
||||
&netdev->refcnt, netdev->name );
|
||||
generic_settings_init ( &netdev->settings, &netdev->refcnt );
|
||||
netdev->settings.settings.op = &netdev_settings_operations;
|
||||
}
|
||||
|
||||
@@ -495,7 +508,7 @@ netdev_link_ok ( struct net_device *netdev ) {
|
||||
* Check whether or not network device is open
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v is_open Network device is open
|
||||
* @ret is_open Network device is open
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
netdev_is_open ( struct net_device *netdev ) {
|
||||
@@ -506,13 +519,24 @@ netdev_is_open ( struct net_device *netdev ) {
|
||||
* Check whether or not network device interrupts are currently enabled
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v irq_enabled Network device interrupts are enabled
|
||||
* @ret irq_enabled Network device interrupts are enabled
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
netdev_irq_enabled ( struct net_device *netdev ) {
|
||||
return ( netdev->state & NETDEV_IRQ_ENABLED );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not network device receive queue processing is frozen
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rx_frozen Network device receive queue processing is frozen
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
netdev_rx_frozen ( struct net_device *netdev ) {
|
||||
return ( netdev->state & NETDEV_RX_FROZEN );
|
||||
}
|
||||
|
||||
extern void netdev_link_err ( struct net_device *netdev, int rc );
|
||||
extern void netdev_link_down ( struct net_device *netdev );
|
||||
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
|
||||
@@ -540,6 +564,7 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
|
||||
extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
|
||||
uint16_t net_proto, const void *ll_dest,
|
||||
const void *ll_source );
|
||||
extern void net_poll ( void );
|
||||
|
||||
/**
|
||||
* Complete network transmission
|
||||
@@ -575,4 +600,24 @@ netdev_link_up ( struct net_device *netdev ) {
|
||||
netdev_link_err ( netdev, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze network device receive queue processing
|
||||
*
|
||||
* @v netdev Network device
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
netdev_rx_freeze ( struct net_device *netdev ) {
|
||||
netdev->state |= NETDEV_RX_FROZEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfreeze network device receive queue processing
|
||||
*
|
||||
* @v netdev Network device
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
netdev_rx_unfreeze ( struct net_device *netdev ) {
|
||||
netdev->state &= ~NETDEV_RX_FROZEN;
|
||||
}
|
||||
|
||||
#endif /* _IPXE_NETDEVICE_H */
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _IPXE_NVSVPD_H
|
||||
#define _IPXE_NVSVPD_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Non-Volatile Storage using Vital Product Data
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <ipxe/nvs.h>
|
||||
#include <ipxe/pcivpd.h>
|
||||
|
||||
/** An NVS VPD device */
|
||||
struct nvs_vpd_device {
|
||||
/** NVS device */
|
||||
struct nvs_device nvs;
|
||||
/** PCI VPD device */
|
||||
struct pci_vpd vpd;
|
||||
/** Starting address
|
||||
*
|
||||
* This address is added to the NVS address to form the VPD
|
||||
* address.
|
||||
*/
|
||||
unsigned int address;
|
||||
};
|
||||
|
||||
extern int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci,
|
||||
unsigned int field );
|
||||
|
||||
#endif /* IPXE_NVSVPD_H */
|
||||
@@ -0,0 +1,127 @@
|
||||
#ifndef _IPXE_PARSEOPT_H
|
||||
#define _IPXE_PARSEOPT_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Command line option parsing
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct net_device;
|
||||
struct image;
|
||||
|
||||
/** A command-line option descriptor */
|
||||
struct option_descriptor {
|
||||
/** Long option name, if any */
|
||||
const char *longopt;
|
||||
/** Short option name */
|
||||
char shortopt;
|
||||
/** Argument requirement (as for @c struct @c option) */
|
||||
uint8_t has_arg;
|
||||
/** Offset of field within options structure */
|
||||
uint16_t offset;
|
||||
/** Parse option
|
||||
*
|
||||
* @v text Option text
|
||||
* @v value Option value to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int ( * parse ) ( const char *text, void *value );
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct option parser
|
||||
*
|
||||
* @v _struct Options structure type
|
||||
* @v _field Field within options structure
|
||||
* @v _parse Field type-specific option parser
|
||||
* @ret _parse Generic option parser
|
||||
*/
|
||||
#define OPTION_PARSER( _struct, _field, _parse ) \
|
||||
( ( int ( * ) ( const char *text, void *value ) ) \
|
||||
( ( ( ( typeof ( _parse ) * ) NULL ) == \
|
||||
( ( int ( * ) ( const char *text, \
|
||||
typeof ( ( ( _struct * ) NULL )->_field ) * ) ) \
|
||||
NULL ) ) ? _parse : _parse ) )
|
||||
|
||||
/**
|
||||
* Construct option descriptor
|
||||
*
|
||||
* @v _longopt Long option name, if any
|
||||
* @v _shortopt Short option name, if any
|
||||
* @v _has_arg Argument requirement
|
||||
* @v _struct Options structure type
|
||||
* @v _field Field within options structure
|
||||
* @v _parse Field type-specific option parser
|
||||
* @ret _option Option descriptor
|
||||
*/
|
||||
#define OPTION_DESC( _longopt, _shortopt, _has_arg, _struct, _field, _parse ) \
|
||||
{ \
|
||||
.longopt = _longopt, \
|
||||
.shortopt = _shortopt, \
|
||||
.has_arg = _has_arg, \
|
||||
.offset = offsetof ( _struct, _field ), \
|
||||
.parse = OPTION_PARSER ( _struct, _field, _parse ), \
|
||||
}
|
||||
|
||||
/** A command descriptor */
|
||||
struct command_descriptor {
|
||||
/** Option descriptors */
|
||||
struct option_descriptor *options;
|
||||
/** Number of option descriptors */
|
||||
uint8_t num_options;
|
||||
/** Length of option structure */
|
||||
uint8_t len;
|
||||
/** Minimum number of non-option arguments */
|
||||
uint8_t min_args;
|
||||
/** Maximum number of non-option arguments */
|
||||
uint8_t max_args;
|
||||
/** Command usage and description
|
||||
*
|
||||
* This excludes the literal "Usage:" and the command name,
|
||||
* which will be prepended automatically.
|
||||
*/
|
||||
const char *usage_description;
|
||||
};
|
||||
|
||||
/** No maximum number of arguments */
|
||||
#define MAX_ARGUMENTS 0xff
|
||||
|
||||
/**
|
||||
* Construct command descriptor
|
||||
*
|
||||
* @v _struct Options structure type
|
||||
* @v _options Option descriptor array
|
||||
* @v _check_args Remaining argument checker
|
||||
* @v _usage Command usage
|
||||
* @v _description Command description
|
||||
* @ret _command Command descriptor
|
||||
*/
|
||||
#define COMMAND_DESC( _struct, _options, _min_args, _max_args, _usage, \
|
||||
_description ) \
|
||||
{ \
|
||||
.options = ( ( ( ( typeof ( _options[0] ) * ) NULL ) == \
|
||||
( ( struct option_descriptor * ) NULL ) ) ? \
|
||||
_options : _options ), \
|
||||
.num_options = ( sizeof ( _options ) / \
|
||||
sizeof ( _options[0] ) ), \
|
||||
.len = sizeof ( _struct ), \
|
||||
.min_args = _min_args, \
|
||||
.max_args = _max_args, \
|
||||
.usage_description = _usage "\n\n" _description, \
|
||||
}
|
||||
|
||||
extern int parse_string ( const char *text, const char **value );
|
||||
extern int parse_integer ( const char *text, unsigned int *value );
|
||||
extern int parse_netdev ( const char *text, struct net_device **netdev );
|
||||
extern int parse_image ( const char *text, struct image **image );
|
||||
extern void print_usage ( struct command_descriptor *cmd, char **argv );
|
||||
extern int parse_options ( int argc, char **argv,
|
||||
struct command_descriptor *cmd, void *opts );
|
||||
|
||||
#endif /* _IPXE_PARSEOPT_H */
|
||||
@@ -374,6 +374,13 @@ struct pci_driver {
|
||||
#define PCI_ROM( _vendor, _device, _name, _description, _data ) \
|
||||
PCI_ID( _vendor, _device, _name, _description, _data )
|
||||
|
||||
/** PCI device debug message format */
|
||||
#define PCI_FMT "PCI %02x:%02x.%x"
|
||||
|
||||
/** PCI device debug message arguments */
|
||||
#define PCI_ARGS( pci ) \
|
||||
(pci)->bus, PCI_SLOT ( (pci)->devfn ), PCI_FUNC ( (pci)->devfn )
|
||||
|
||||
extern void adjust_pci_device ( struct pci_device *pci );
|
||||
extern unsigned long pci_bar_start ( struct pci_device *pci,
|
||||
unsigned int reg );
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#ifndef _IPXE_PCIVPD_H
|
||||
#define _IPXE_PCIVPD_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* PCI Vital Product Data
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <byteswap.h>
|
||||
#include <ipxe/isapnp.h>
|
||||
#include <ipxe/pci.h>
|
||||
|
||||
/** PCI VPD address register */
|
||||
#define PCI_VPD_ADDRESS 0x02
|
||||
|
||||
/** PCI VPD write flag */
|
||||
#define PCI_VPD_FLAG 0x8000
|
||||
|
||||
/** PCI VPD data register */
|
||||
#define PCI_VPD_DATA 0x04
|
||||
|
||||
/** A PCI VPD field */
|
||||
struct pci_vpd_field {
|
||||
/** Keyword */
|
||||
uint16_t keyword;
|
||||
/** Length */
|
||||
uint8_t len;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Construct PCI VPD field descriptor
|
||||
*
|
||||
* @v tag ISAPnP tag
|
||||
* @v keyword1 First character of keyword
|
||||
* @v keyword2 Second character of keyword
|
||||
* @ret field VPD field descriptor
|
||||
*/
|
||||
#define PCI_VPD_FIELD( tag, keyword1, keyword2 ) \
|
||||
( ( (tag) << 16 ) | ( (keyword2) << 8 ) | ( (keyword1) << 0 ) )
|
||||
|
||||
/** Construct PCI VPD whole-tag field descriptor
|
||||
*
|
||||
* @v tag ISAPnP tag
|
||||
* @ret field VPD field descriptor
|
||||
*/
|
||||
#define PCI_VPD_WHOLE_TAG_FIELD( tag ) PCI_VPD_FIELD ( (tag), '\0', '\0' )
|
||||
|
||||
/** Extract PCI VPD ISAPnP tag
|
||||
*
|
||||
* @v field VPD field descriptor
|
||||
* @ret tag ISAPnP tag
|
||||
*/
|
||||
#define PCI_VPD_TAG( field ) ( (field) >> 16 )
|
||||
|
||||
/** Extract PCI VPD keyword
|
||||
*
|
||||
* @v field VPD field descriptor
|
||||
* @ret keyword Keyword
|
||||
*/
|
||||
#define PCI_VPD_KEYWORD( field ) ( cpu_to_le16 ( (field) & 0xffff ) )
|
||||
|
||||
/** PCI VPD field debug message format */
|
||||
#define PCI_VPD_FIELD_FMT "%c%c"
|
||||
|
||||
/** PCI VPD field debug message arguments */
|
||||
#define PCI_VPD_FIELD_ARGS( field ) \
|
||||
( (field) >> 0 ), ( (field) >> 8 )
|
||||
|
||||
/** PCI VPD Read-Only field tag */
|
||||
#define PCI_VPD_TAG_RO 0x90
|
||||
|
||||
/** PCI VPD Read-Write field tag */
|
||||
#define PCI_VPD_TAG_RW 0x91
|
||||
|
||||
/** PCI VPD Card Name field descriptor */
|
||||
#define PCI_VPD_FIELD_NAME PCI_VPD_WHOLE_TAG_FIELD ( ISAPNP_TAG_ANSISTR )
|
||||
|
||||
/** PCI VPD Part Number field descriptor */
|
||||
#define PCI_VPD_FIELD_PN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'N' )
|
||||
|
||||
/** PCI VPD Engineering Change Level field descriptor */
|
||||
#define PCI_VPD_FIELD_EC PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'E', 'C' )
|
||||
|
||||
/** PCI VPD Fabric Geography field descriptor */
|
||||
#define PCI_VPD_FIELD_FG PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'F', 'G' )
|
||||
|
||||
/** PCI VPD Location field descriptor */
|
||||
#define PCI_VPD_FIELD_LC PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'L', 'C' )
|
||||
|
||||
/** PCI VPD Manufacturer ID field descriptor */
|
||||
#define PCI_VPD_FIELD_MN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'M', 'N' )
|
||||
|
||||
/** PCI VPD PCI Geography field descriptor */
|
||||
#define PCI_VPD_FIELD_PG PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'G' )
|
||||
|
||||
/** PCI VPD Serial Number field descriptor */
|
||||
#define PCI_VPD_FIELD_SN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'S', 'N' )
|
||||
|
||||
/** PCI VPD Extended Capability field descriptor */
|
||||
#define PCI_VPD_FIELD_CP PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'C', 'P' )
|
||||
|
||||
/** PCI VPD Checksum and Reserved field descriptor */
|
||||
#define PCI_VPD_FIELD_RV PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'R', 'V' )
|
||||
|
||||
/** PCI VPD Asset Tag field descriptor */
|
||||
#define PCI_VPD_FIELD_YA PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'Y', 'A' )
|
||||
|
||||
/** PCI VPD Remaining Read/Write Area field descriptor */
|
||||
#define PCI_VPD_FIELD_RW PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'R', 'W' )
|
||||
|
||||
/** Maximum wait for PCI VPD (in ms) */
|
||||
#define PCI_VPD_MAX_WAIT_MS 100
|
||||
|
||||
/** PCI VPD cache */
|
||||
struct pci_vpd_cache {
|
||||
/** Address */
|
||||
int address;
|
||||
/** Data */
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
/** PCI VPD */
|
||||
struct pci_vpd {
|
||||
/** PCI device */
|
||||
struct pci_device *pci;
|
||||
/** VPD capability offset */
|
||||
int cap;
|
||||
/** Read cache */
|
||||
struct pci_vpd_cache cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if PCI VPD read cache is valid
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
* @ret is_valid Read cache is valid
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
pci_vpd_cache_is_valid ( struct pci_vpd *vpd ) {
|
||||
return ( vpd->cache.address >= 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate PCI VPD read cache
|
||||
*
|
||||
* @v vpd PCI VPD
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
pci_vpd_invalidate_cache ( struct pci_vpd *vpd ) {
|
||||
vpd->cache.address = -1;
|
||||
}
|
||||
|
||||
extern int pci_vpd_init ( struct pci_vpd *vpd, struct pci_device *pci );
|
||||
extern int pci_vpd_read ( struct pci_vpd *vpd, unsigned int address,
|
||||
void *buf, size_t len );
|
||||
extern int pci_vpd_write ( struct pci_vpd *vpd, unsigned int address,
|
||||
const void *buf, size_t len );
|
||||
extern int pci_vpd_find ( struct pci_vpd *vpd, unsigned int field,
|
||||
unsigned int *address, size_t *len );
|
||||
|
||||
#endif /* _IPXE_PCIVPD_H */
|
||||
@@ -178,7 +178,7 @@ extern int generic_settings_fetch ( struct settings *settings,
|
||||
extern void generic_settings_clear ( struct settings *settings );
|
||||
|
||||
extern int register_settings ( struct settings *settings,
|
||||
struct settings *parent );
|
||||
struct settings *parent, const char *name );
|
||||
extern void unregister_settings ( struct settings *settings );
|
||||
|
||||
extern int store_setting ( struct settings *settings, struct setting *setting,
|
||||
@@ -193,6 +193,10 @@ extern int fetch_string_setting ( struct settings *settings,
|
||||
extern int fetch_string_setting_copy ( struct settings *settings,
|
||||
struct setting *setting,
|
||||
char **data );
|
||||
extern int fetch_ipv4_array_setting ( struct settings *settings,
|
||||
struct setting *setting,
|
||||
struct in_addr *inp,
|
||||
unsigned int count );
|
||||
extern int fetch_ipv4_setting ( struct settings *settings,
|
||||
struct setting *setting, struct in_addr *inp );
|
||||
extern int fetch_int_setting ( struct settings *settings,
|
||||
@@ -252,19 +256,16 @@ extern struct setting user_class_setting __setting;
|
||||
* @v settings Settings block
|
||||
* @v op Settings block operations
|
||||
* @v refcnt Containing object reference counter, or NULL
|
||||
* @v name Settings block name
|
||||
* @v tag_magic Tag magic
|
||||
*/
|
||||
static inline void settings_init ( struct settings *settings,
|
||||
struct settings_operations *op,
|
||||
struct refcnt *refcnt,
|
||||
const char *name,
|
||||
unsigned int tag_magic ) {
|
||||
INIT_LIST_HEAD ( &settings->siblings );
|
||||
INIT_LIST_HEAD ( &settings->children );
|
||||
settings->op = op;
|
||||
settings->refcnt = refcnt;
|
||||
settings->name = name;
|
||||
settings->tag_magic = tag_magic;
|
||||
}
|
||||
|
||||
@@ -273,13 +274,11 @@ static inline void settings_init ( struct settings *settings,
|
||||
*
|
||||
* @v generics Generic settings block
|
||||
* @v refcnt Containing object reference counter, or NULL
|
||||
* @v name Settings block name
|
||||
*/
|
||||
static inline void generic_settings_init ( struct generic_settings *generics,
|
||||
struct refcnt *refcnt,
|
||||
const char *name ) {
|
||||
struct refcnt *refcnt ) {
|
||||
settings_init ( &generics->settings, &generic_settings_operations,
|
||||
refcnt, name, 0 );
|
||||
refcnt, 0 );
|
||||
INIT_LIST_HEAD ( &generics->list );
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,28 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
extern void shell ( void );
|
||||
/** Shell stop states */
|
||||
enum shell_stop_state {
|
||||
/** Continue processing */
|
||||
SHELL_CONTINUE = 0,
|
||||
/**
|
||||
* Stop processing current command line
|
||||
*
|
||||
* This is the stop state entered by commands that change the flow
|
||||
* of execution, such as "goto".
|
||||
*/
|
||||
SHELL_STOP_COMMAND = 1,
|
||||
/**
|
||||
* Stop processing commands
|
||||
*
|
||||
* This is the stop state entered by commands that terminate
|
||||
* the flow of execution, such as "exit".
|
||||
*/
|
||||
SHELL_STOP_COMMAND_SEQUENCE = 2,
|
||||
};
|
||||
|
||||
extern void shell_stop ( int stop );
|
||||
extern int shell_stopped ( int stop );
|
||||
extern int shell ( void );
|
||||
|
||||
#endif /* _IPXE_SHELL_H */
|
||||
|
||||
@@ -257,11 +257,6 @@ struct tcp_options {
|
||||
/** Smallest port number on which a TCP connection can listen */
|
||||
#define TCP_MIN_PORT 1
|
||||
|
||||
/* Some IOB constants */
|
||||
#define MAX_HDR_LEN 100
|
||||
#define MAX_IOB_LEN 1500
|
||||
#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
|
||||
|
||||
/**
|
||||
* Maxmimum advertised TCP window size
|
||||
*
|
||||
|
||||
@@ -23,10 +23,6 @@ struct sockaddr;
|
||||
* UDP constants
|
||||
*/
|
||||
|
||||
#define UDP_MAX_HLEN 72
|
||||
#define UDP_MAX_TXIOB ETH_MAX_MTU
|
||||
#define UDP_MIN_TXIOB ETH_ZLEN
|
||||
|
||||
/**
|
||||
* A UDP header
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef _IPXE_VLAN_H
|
||||
#define _IPXE_VLAN_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Virtual LANs
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
/** A VLAN header */
|
||||
struct vlan_header {
|
||||
/** Tag control information */
|
||||
uint16_t tci;
|
||||
/** Encapsulated protocol */
|
||||
uint16_t net_proto;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/**
|
||||
* Extract VLAN tag from tag control information
|
||||
*
|
||||
* @v tci Tag control information
|
||||
* @ret tag VLAN tag
|
||||
*/
|
||||
#define VLAN_TAG( tci ) ( (tci) & 0x0fff )
|
||||
|
||||
/**
|
||||
* Extract VLAN priority from tag control information
|
||||
*
|
||||
* @v tci Tag control information
|
||||
* @ret priority Priority
|
||||
*/
|
||||
#define VLAN_PRIORITY( tci ) ( (tci) >> 13 )
|
||||
|
||||
/**
|
||||
* Construct VLAN tag control information
|
||||
*
|
||||
* @v tag VLAN tag
|
||||
* @v priority Priority
|
||||
* @ret tci Tag control information
|
||||
*/
|
||||
#define VLAN_TCI( tag, priority ) ( ( (priority) << 13 ) | (tag) )
|
||||
|
||||
/**
|
||||
* Check VLAN tag is valid
|
||||
*
|
||||
* @v tag VLAN tag
|
||||
* @ret is_valid VLAN tag is valid
|
||||
*/
|
||||
#define VLAN_TAG_IS_VALID( tag ) ( (tag) < 0xfff )
|
||||
|
||||
/**
|
||||
* Check VLAN priority is valid
|
||||
*
|
||||
* @v priority VLAN priority
|
||||
* @ret is_valid VLAN priority is valid
|
||||
*/
|
||||
#define VLAN_PRIORITY_IS_VALID( priority ) ( (priority) <= 7 )
|
||||
|
||||
extern struct net_device * vlan_find ( struct net_device *trunk,
|
||||
unsigned int tag );
|
||||
extern int vlan_can_be_trunk ( struct net_device *trunk );
|
||||
extern int vlan_create ( struct net_device *trunk, unsigned int tag,
|
||||
unsigned int priority );
|
||||
extern int vlan_destroy ( struct net_device *netdev );
|
||||
|
||||
#endif /* _IPXE_VLAN_H */
|
||||
@@ -10,7 +10,11 @@ FILE_LICENCE ( GPL2_ONLY );
|
||||
#define NULL ((void *)0)
|
||||
|
||||
#undef offsetof
|
||||
#if ( defined ( __GNUC__ ) && ( __GNUC__ > 3 ) )
|
||||
#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
|
||||
#else
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
#undef container_of
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
|
||||
@@ -14,7 +14,8 @@ struct net_device;
|
||||
|
||||
extern int shutdown_exit_flags;
|
||||
|
||||
extern void autoboot ( void );
|
||||
extern int netboot ( struct net_device *netdev );
|
||||
extern int autoboot ( void );
|
||||
extern int boot_next_server_and_filename ( struct in_addr next_server,
|
||||
const char *filename );
|
||||
extern int boot_root_path ( const char *root_path );
|
||||
|
||||
@@ -530,6 +530,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
||||
container_of ( snp, struct efi_snp_device, snp );
|
||||
struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
|
||||
struct io_buffer *iobuf;
|
||||
size_t ll_headroom;
|
||||
int rc;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
@@ -582,13 +583,15 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
iobuf = alloc_iob ( len );
|
||||
ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len );
|
||||
iobuf = alloc_iob ( ll_headroom + len );
|
||||
if ( ! iobuf ) {
|
||||
DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
|
||||
"buffer\n", snpdev, ( ( unsigned long ) len ) );
|
||||
efirc = EFI_DEVICE_ERROR;
|
||||
goto err_alloc_iob;
|
||||
}
|
||||
iob_reserve ( iobuf, ll_headroom );
|
||||
memcpy ( iob_put ( iobuf, len ), data, len );
|
||||
|
||||
/* Create link-layer header, if specified */
|
||||
|
||||
@@ -125,7 +125,6 @@ static struct settings_operations smbios_settings_operations = {
|
||||
/** SMBIOS settings */
|
||||
static struct settings smbios_settings = {
|
||||
.refcnt = NULL,
|
||||
.name = "smbios",
|
||||
.tag_magic = SMBIOS_EMPTY_TAG,
|
||||
.siblings = LIST_HEAD_INIT ( smbios_settings.siblings ),
|
||||
.children = LIST_HEAD_INIT ( smbios_settings.children ),
|
||||
@@ -136,7 +135,8 @@ static struct settings smbios_settings = {
|
||||
static void smbios_init ( void ) {
|
||||
int rc;
|
||||
|
||||
if ( ( rc = register_settings ( &smbios_settings, NULL ) ) != 0 ) {
|
||||
if ( ( rc = register_settings ( &smbios_settings, NULL,
|
||||
"smbios" ) ) != 0 ) {
|
||||
DBG ( "SMBIOS could not register settings: %s\n",
|
||||
strerror ( rc ) );
|
||||
return;
|
||||
|
||||
+2
-1
@@ -66,7 +66,8 @@ void store_cached_dhcpack ( userptr_t data, size_t len ) {
|
||||
* device, which is usually what we want.
|
||||
*/
|
||||
parent = netdev_settings ( last_opened_netdev() );
|
||||
if ( ( rc = register_settings ( &dhcppkt->settings, parent ) ) != 0 )
|
||||
if ( ( rc = register_settings ( &dhcppkt->settings, parent,
|
||||
DHCP_SETTINGS_NAME ) ) != 0 )
|
||||
DBG ( "DHCP could not register cached settings: %s\n",
|
||||
strerror ( rc ) );
|
||||
|
||||
|
||||
+1
-2
@@ -279,6 +279,5 @@ void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct dhcphdr *data,
|
||||
dhcppkt->len = ( offsetof ( struct dhcphdr, options ) +
|
||||
dhcppkt->options.len );
|
||||
settings_init ( &dhcppkt->settings,
|
||||
&dhcppkt_settings_operations, &dhcppkt->refcnt,
|
||||
DHCP_SETTINGS_NAME, 0 );
|
||||
&dhcppkt_settings_operations, &dhcppkt->refcnt, 0 );
|
||||
}
|
||||
|
||||
+12
-12
@@ -111,25 +111,25 @@ static void eth_slow_lacp_dump ( struct io_buffer *iobuf,
|
||||
struct eth_slow_lacp *lacp = ð_slow->lacp;
|
||||
|
||||
DBGC ( netdev,
|
||||
"SLOW %p %s LACP actor (%04x,%s,%04x,%02x,%04x) [%s]\n",
|
||||
netdev, label, ntohs ( lacp->actor.system_priority ),
|
||||
"SLOW %s %s LACP actor (%04x,%s,%04x,%02x,%04x) [%s]\n",
|
||||
netdev->name, label, ntohs ( lacp->actor.system_priority ),
|
||||
eth_ntoa ( lacp->actor.system ),
|
||||
ntohs ( lacp->actor.key ),
|
||||
ntohs ( lacp->actor.port_priority ),
|
||||
ntohs ( lacp->actor.port ),
|
||||
eth_slow_lacp_state_name ( lacp->actor.state ) );
|
||||
DBGC ( netdev,
|
||||
"SLOW %p %s LACP partner (%04x,%s,%04x,%02x,%04x) [%s]\n",
|
||||
netdev, label, ntohs ( lacp->partner.system_priority ),
|
||||
"SLOW %s %s LACP partner (%04x,%s,%04x,%02x,%04x) [%s]\n",
|
||||
netdev->name, label, ntohs ( lacp->partner.system_priority ),
|
||||
eth_ntoa ( lacp->partner.system ),
|
||||
ntohs ( lacp->partner.key ),
|
||||
ntohs ( lacp->partner.port_priority ),
|
||||
ntohs ( lacp->partner.port ),
|
||||
eth_slow_lacp_state_name ( lacp->partner.state ) );
|
||||
DBGC ( netdev, "SLOW %p %s LACP collector %04x (%d us)\n",
|
||||
netdev, label, ntohs ( lacp->collector.max_delay ),
|
||||
DBGC ( netdev, "SLOW %s %s LACP collector %04x (%d us)\n",
|
||||
netdev->name, label, ntohs ( lacp->collector.max_delay ),
|
||||
( ntohs ( lacp->collector.max_delay ) * 10 ) );
|
||||
DBGC2_HDA ( netdev, 0, iobuf, iob_len ( iobuf ) );
|
||||
DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,13 +191,13 @@ static void eth_slow_marker_dump ( struct io_buffer *iobuf,
|
||||
union eth_slow_packet *eth_slow = iobuf->data;
|
||||
struct eth_slow_marker *marker = ð_slow->marker;
|
||||
|
||||
DBGC ( netdev, "SLOW %p %s marker %s port %04x system %s xact %08x\n",
|
||||
netdev, label,
|
||||
DBGC ( netdev, "SLOW %s %s marker %s port %04x system %s xact %08x\n",
|
||||
netdev->name, label,
|
||||
eth_slow_marker_tlv_name ( marker->marker.tlv.type ),
|
||||
ntohs ( marker->marker.port ),
|
||||
eth_ntoa ( marker->marker.system ),
|
||||
ntohl ( marker->marker.xact ) );
|
||||
DBGC2_HDA ( netdev, 0, iobuf, iob_len ( iobuf ) );
|
||||
DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,8 +255,8 @@ static int eth_slow_rx ( struct io_buffer *iobuf,
|
||||
case ETH_SLOW_SUBTYPE_MARKER:
|
||||
return eth_slow_marker_rx ( iobuf, netdev );
|
||||
default:
|
||||
DBGC ( netdev, "SLOW %p RX unknown subtype %02x\n",
|
||||
netdev, eth_slow->header.subtype );
|
||||
DBGC ( netdev, "SLOW %s RX unknown subtype %02x\n",
|
||||
netdev->name, eth_slow->header.subtype );
|
||||
free_iob ( iobuf );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+3
-5
@@ -1178,11 +1178,11 @@ static struct interface_descriptor fc_port_ns_plogi_desc =
|
||||
* @v transport Transport interface
|
||||
* @v node Fibre Channel node name
|
||||
* @v port Fibre Channel port name
|
||||
* @v name Symbolic port name
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int fc_port_open ( struct interface *transport, const struct fc_name *node_wwn,
|
||||
const struct fc_name *port_wwn ) {
|
||||
static unsigned int portindex = 0;
|
||||
const struct fc_name *port_wwn, const char *name ) {
|
||||
struct fc_port *port;
|
||||
|
||||
/* Allocate and initialise structure */
|
||||
@@ -1198,9 +1198,7 @@ int fc_port_open ( struct interface *transport, const struct fc_name *node_wwn,
|
||||
INIT_LIST_HEAD ( &port->xchgs );
|
||||
memcpy ( &port->node_wwn, node_wwn, sizeof ( port->node_wwn ) );
|
||||
memcpy ( &port->port_wwn, port_wwn, sizeof ( port->port_wwn ) );
|
||||
|
||||
/* Create device name */
|
||||
snprintf ( port->name, sizeof ( port->name ), "fc%d", portindex++ );
|
||||
snprintf ( port->name, sizeof ( port->name ), "%s", name );
|
||||
|
||||
DBGC ( port, "FCPORT %s opened as %s",
|
||||
port->name, fc_ntoa ( &port->node_wwn ) );
|
||||
|
||||
+176
-18
@@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/xfer.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/ethernet.h>
|
||||
#include <ipxe/vlan.h>
|
||||
#include <ipxe/features.h>
|
||||
#include <ipxe/errortab.h>
|
||||
#include <ipxe/device.h>
|
||||
@@ -103,6 +104,10 @@ enum fcoe_flags {
|
||||
FCOE_HAVE_FIP_FCF = 0x0004,
|
||||
/** FCoE forwarder supports server-provided MAC addresses */
|
||||
FCOE_FCF_ALLOWS_SPMA = 0x0008,
|
||||
/** An alternative VLAN has been found */
|
||||
FCOE_VLAN_FOUND = 0x0010,
|
||||
/** VLAN discovery has timed out */
|
||||
FCOE_VLAN_TIMED_OUT = 0x0020,
|
||||
};
|
||||
|
||||
struct net_protocol fcoe_protocol __net_protocol;
|
||||
@@ -124,6 +129,15 @@ static uint8_t all_fcf_macs[ETH_ALEN] =
|
||||
static uint8_t default_fcf_mac[ETH_ALEN] =
|
||||
{ 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
|
||||
|
||||
/** Maximum number of VLAN requests before giving up on VLAN discovery */
|
||||
#define FCOE_MAX_VLAN_REQUESTS 2
|
||||
|
||||
/** Delay between retrying VLAN requests */
|
||||
#define FCOE_VLAN_RETRY_DELAY ( TICKS_PER_SEC )
|
||||
|
||||
/** Delay between retrying polling VLAN requests */
|
||||
#define FCOE_VLAN_POLL_DELAY ( 30 * TICKS_PER_SEC )
|
||||
|
||||
/** Maximum number of FIP solicitations before giving up on FIP */
|
||||
#define FCOE_MAX_FIP_SOLICITATIONS 2
|
||||
|
||||
@@ -166,6 +180,9 @@ static struct fcoe_port * fcoe_demux ( struct net_device *netdev ) {
|
||||
*/
|
||||
static void fcoe_reset ( struct fcoe_port *fcoe ) {
|
||||
|
||||
/* Detach FC port, if any */
|
||||
intf_restart ( &fcoe->transport, -ECANCELED );
|
||||
|
||||
/* Reset any FIP state */
|
||||
stop_timer ( &fcoe->timer );
|
||||
fcoe->timeouts = 0;
|
||||
@@ -182,8 +199,9 @@ static void fcoe_reset ( struct fcoe_port *fcoe ) {
|
||||
netdev_link_ok ( fcoe->netdev ) ) {
|
||||
fcoe->flags |= FCOE_HAVE_NETWORK;
|
||||
start_timer_nodelay ( &fcoe->timer );
|
||||
DBGC ( fcoe, "FCoE %s starting FIP solicitation\n",
|
||||
fcoe->netdev->name );
|
||||
DBGC ( fcoe, "FCoE %s starting %s\n", fcoe->netdev->name,
|
||||
( vlan_can_be_trunk ( fcoe->netdev ) ?
|
||||
"VLAN discovery" : "FIP solicitation" ) );
|
||||
}
|
||||
|
||||
/* Send notification of window change */
|
||||
@@ -515,7 +533,9 @@ static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
|
||||
/* Handle descriptors that we understand */
|
||||
if ( ( desc_type > FIP_RESERVED ) &&
|
||||
( desc_type < FIP_NUM_DESCRIPTOR_TYPES ) ) {
|
||||
descs->desc[desc_type] = desc;
|
||||
/* Use only the first instance of a descriptor */
|
||||
if ( descs->desc[desc_type] == NULL )
|
||||
descs->desc[desc_type] = desc;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -533,6 +553,100 @@ static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send FIP VLAN request
|
||||
*
|
||||
* @v fcoe FCoE port
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int fcoe_fip_tx_vlan ( struct fcoe_port *fcoe ) {
|
||||
struct io_buffer *iobuf;
|
||||
struct {
|
||||
struct fip_header hdr;
|
||||
struct fip_mac_address mac_address;
|
||||
} __attribute__ (( packed )) *request;
|
||||
int rc;
|
||||
|
||||
/* Allocate I/O buffer */
|
||||
iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *request ) );
|
||||
if ( ! iobuf )
|
||||
return -ENOMEM;
|
||||
iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
|
||||
|
||||
/* Construct VLAN request */
|
||||
request = iob_put ( iobuf, sizeof ( *request ) );
|
||||
memset ( request, 0, sizeof ( *request ) );
|
||||
request->hdr.version = FIP_VERSION;
|
||||
request->hdr.code = htons ( FIP_CODE_VLAN );
|
||||
request->hdr.subcode = FIP_VLAN_REQUEST;
|
||||
request->hdr.len = htons ( ( sizeof ( *request ) -
|
||||
sizeof ( request->hdr ) ) / 4 );
|
||||
request->mac_address.type = FIP_MAC_ADDRESS;
|
||||
request->mac_address.len =
|
||||
( sizeof ( request->mac_address ) / 4 );
|
||||
memcpy ( request->mac_address.mac, fcoe->netdev->ll_addr,
|
||||
sizeof ( request->mac_address.mac ) );
|
||||
|
||||
/* Send VLAN request */
|
||||
if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
|
||||
&fip_protocol, all_fcf_macs,
|
||||
fcoe->netdev->ll_addr ) ) != 0 ) {
|
||||
DBGC ( fcoe, "FCoE %s could not send VLAN request: "
|
||||
"%s\n", fcoe->netdev->name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle received FIP VLAN notification
|
||||
*
|
||||
* @v fcoe FCoE port
|
||||
* @v descs Descriptor list
|
||||
* @v flags Flags
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int fcoe_fip_rx_vlan ( struct fcoe_port *fcoe,
|
||||
struct fip_descriptors *descs,
|
||||
unsigned int flags __unused ) {
|
||||
struct fip_mac_address *mac_address = fip_mac_address ( descs );
|
||||
struct fip_vlan *vlan = fip_vlan ( descs );
|
||||
unsigned int tag;
|
||||
int rc;
|
||||
|
||||
/* Sanity checks */
|
||||
if ( ! mac_address ) {
|
||||
DBGC ( fcoe, "FCoE %s received VLAN notification missing MAC "
|
||||
"address\n", fcoe->netdev->name );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( ! vlan ) {
|
||||
DBGC ( fcoe, "FCoE %s received VLAN notification missing VLAN "
|
||||
"tag\n", fcoe->netdev->name );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Create VLAN */
|
||||
tag = ntohs ( vlan->vlan );
|
||||
DBGC ( fcoe, "FCoE %s creating VLAN %d for FCF %s\n",
|
||||
fcoe->netdev->name, tag, eth_ntoa ( mac_address->mac ) );
|
||||
if ( ( rc = vlan_create ( fcoe->netdev, tag,
|
||||
FCOE_VLAN_PRIORITY ) ) != 0 ) {
|
||||
DBGC ( fcoe, "FCoE %s could not create VLAN %d: %s\n",
|
||||
fcoe->netdev->name, tag, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Record that a VLAN was found. This FCoE port will play no
|
||||
* further active role; the real FCoE traffic will use the
|
||||
* port automatically created for the new VLAN device.
|
||||
*/
|
||||
fcoe->flags |= FCOE_VLAN_FOUND;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send FIP discovery solicitation
|
||||
*
|
||||
@@ -646,14 +760,12 @@ static int fcoe_fip_rx_advertisement ( struct fcoe_port *fcoe,
|
||||
fcoe->flags |= FCOE_FCF_ALLOWS_SPMA;
|
||||
memcpy ( fcoe->fcf_mac, mac_address->mac,
|
||||
sizeof ( fcoe->fcf_mac ) );
|
||||
DBGC ( fcoe, "FCoE %s selected FCF %s (priority %d, ",
|
||||
DBGC ( fcoe, "FCoE %s selected FCF %s (pri %d",
|
||||
fcoe->netdev->name, eth_ntoa ( fcoe->fcf_mac ),
|
||||
fcoe->priority );
|
||||
if ( fcoe->keepalive ) {
|
||||
DBGC ( fcoe, "keepalive %dms",
|
||||
DBGC ( fcoe, ", FKA ADV %dms",
|
||||
fcoe->keepalive );
|
||||
} else {
|
||||
DBGC ( fcoe, "no keepalive" );
|
||||
}
|
||||
DBGC ( fcoe, ", %cPMA)\n",
|
||||
( ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) ?
|
||||
@@ -797,6 +909,8 @@ struct fip_handler {
|
||||
|
||||
/** FIP handlers */
|
||||
static struct fip_handler fip_handlers[] = {
|
||||
{ FIP_CODE_VLAN, FIP_VLAN_NOTIFY,
|
||||
fcoe_fip_rx_vlan },
|
||||
{ FIP_CODE_DISCOVERY, FIP_DISCOVERY_ADVERTISE,
|
||||
fcoe_fip_rx_advertisement },
|
||||
{ FIP_CODE_ELS, FIP_ELS_RESPONSE,
|
||||
@@ -884,6 +998,7 @@ static int fcoe_fip_rx ( struct io_buffer *iobuf,
|
||||
static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
|
||||
struct fcoe_port *fcoe =
|
||||
container_of ( timer, struct fcoe_port, timer );
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
assert ( fcoe->flags & FCOE_HAVE_NETWORK );
|
||||
@@ -891,20 +1006,65 @@ static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
|
||||
/* Increment the timeout counter */
|
||||
fcoe->timeouts++;
|
||||
|
||||
if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
|
||||
if ( vlan_can_be_trunk ( fcoe->netdev ) &
|
||||
! ( fcoe->flags & FCOE_VLAN_TIMED_OUT ) ) {
|
||||
|
||||
/* If we have already found a VLAN, send infrequent
|
||||
* VLAN requests, in case VLAN information changes.
|
||||
*/
|
||||
if ( fcoe->flags & FCOE_VLAN_FOUND ) {
|
||||
fcoe->flags &= ~FCOE_VLAN_FOUND;
|
||||
fcoe->timeouts = 0;
|
||||
start_timer_fixed ( &fcoe->timer,
|
||||
FCOE_VLAN_POLL_DELAY );
|
||||
fcoe_fip_tx_vlan ( fcoe );
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we have not yet found a VLAN, and we have not
|
||||
* yet timed out and given up on finding one, then
|
||||
* send a VLAN request and wait.
|
||||
*/
|
||||
if ( fcoe->timeouts <= FCOE_MAX_VLAN_REQUESTS ) {
|
||||
start_timer_fixed ( &fcoe->timer,
|
||||
FCOE_VLAN_RETRY_DELAY );
|
||||
fcoe_fip_tx_vlan ( fcoe );
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have timed out waiting for a VLAN; proceed to
|
||||
* FIP discovery.
|
||||
*/
|
||||
fcoe->flags |= FCOE_VLAN_TIMED_OUT;
|
||||
fcoe->timeouts = 0;
|
||||
DBGC ( fcoe, "FCoE %s giving up on VLAN discovery\n",
|
||||
fcoe->netdev->name );
|
||||
start_timer_nodelay ( &fcoe->timer );
|
||||
|
||||
} else if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
|
||||
|
||||
/* If we have not yet found a FIP-capable forwarder,
|
||||
* and we have not yet timed out and given up on
|
||||
* finding one, then send a FIP solicitation and wait.
|
||||
*/
|
||||
start_timer_fixed ( &fcoe->timer, FCOE_FIP_RETRY_DELAY );
|
||||
if ( ( ! ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) &&
|
||||
( fcoe->timeouts <= FCOE_MAX_FIP_SOLICITATIONS ) ) {
|
||||
start_timer_fixed ( &fcoe->timer,
|
||||
FCOE_FIP_RETRY_DELAY );
|
||||
fcoe_fip_tx_solicitation ( fcoe );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attach Fibre Channel port */
|
||||
if ( ( rc = fc_port_open ( &fcoe->transport, &fcoe->node_wwn.fc,
|
||||
&fcoe->port_wwn.fc,
|
||||
fcoe->netdev->name ) ) != 0 ) {
|
||||
DBGC ( fcoe, "FCoE %s could not create FC port: %s\n",
|
||||
fcoe->netdev->name, strerror ( rc ) );
|
||||
/* We will try again on the next timer expiry */
|
||||
return;
|
||||
}
|
||||
stop_timer ( &fcoe->timer );
|
||||
|
||||
/* Either we have found a FIP-capable forwarder, or we
|
||||
* have timed out and will fall back to pre-FIP mode.
|
||||
*/
|
||||
@@ -979,16 +1139,10 @@ static int fcoe_probe ( struct net_device *netdev ) {
|
||||
fc_ntoa ( &fcoe->node_wwn.fc ) );
|
||||
DBGC ( fcoe, " port %s\n", fc_ntoa ( &fcoe->port_wwn.fc ) );
|
||||
|
||||
/* Attach Fibre Channel port */
|
||||
if ( ( rc = fc_port_open ( &fcoe->transport, &fcoe->node_wwn.fc,
|
||||
&fcoe->port_wwn.fc ) ) != 0 )
|
||||
goto err_fc_create;
|
||||
|
||||
/* Transfer reference to port list */
|
||||
list_add ( &fcoe->list, &fcoe_ports );
|
||||
return 0;
|
||||
|
||||
err_fc_create:
|
||||
netdev_put ( fcoe->netdev );
|
||||
err_zalloc:
|
||||
err_non_ethernet:
|
||||
@@ -1010,8 +1164,12 @@ static void fcoe_notify ( struct net_device *netdev ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the FCoE link */
|
||||
fcoe_reset ( fcoe );
|
||||
/* Reset the FCoE link if necessary */
|
||||
if ( ! ( netdev_is_open ( netdev ) &&
|
||||
netdev_link_ok ( netdev ) &&
|
||||
( fcoe->flags & FCOE_HAVE_NETWORK ) ) ) {
|
||||
fcoe_reset ( fcoe );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+55
-36
@@ -79,10 +79,10 @@ void netdev_link_err ( struct net_device *netdev, int rc ) {
|
||||
/* Record link state */
|
||||
netdev->link_rc = rc;
|
||||
if ( netdev->link_rc == 0 ) {
|
||||
DBGC ( netdev, "NETDEV %p link is up\n", netdev );
|
||||
DBGC ( netdev, "NETDEV %s link is up\n", netdev->name );
|
||||
} else {
|
||||
DBGC ( netdev, "NETDEV %p link is down: %s\n",
|
||||
netdev, strerror ( netdev->link_rc ) );
|
||||
DBGC ( netdev, "NETDEV %s link is down: %s\n",
|
||||
netdev->name, strerror ( netdev->link_rc ) );
|
||||
}
|
||||
|
||||
/* Notify drivers of link state change */
|
||||
@@ -157,8 +157,8 @@ static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
|
||||
int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
||||
int rc;
|
||||
|
||||
DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
|
||||
netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
|
||||
DBGC ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n",
|
||||
netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
|
||||
|
||||
/* Enqueue packet */
|
||||
list_add_tail ( &iobuf->list, &netdev->tx_queue );
|
||||
@@ -202,11 +202,11 @@ void netdev_tx_complete_err ( struct net_device *netdev,
|
||||
/* Update statistics counter */
|
||||
netdev_record_stat ( &netdev->tx_stats, rc );
|
||||
if ( rc == 0 ) {
|
||||
DBGC ( netdev, "NETDEV %p transmission %p complete\n",
|
||||
netdev, iobuf );
|
||||
DBGC ( netdev, "NETDEV %s transmission %p complete\n",
|
||||
netdev->name, iobuf );
|
||||
} else {
|
||||
DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
|
||||
netdev, iobuf, strerror ( rc ) );
|
||||
DBGC ( netdev, "NETDEV %s transmission %p failed: %s\n",
|
||||
netdev->name, iobuf, strerror ( rc ) );
|
||||
}
|
||||
|
||||
/* Catch data corruption as early as possible */
|
||||
@@ -259,8 +259,8 @@ static void netdev_tx_flush ( struct net_device *netdev ) {
|
||||
*/
|
||||
void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
||||
|
||||
DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
|
||||
netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
|
||||
DBGC ( netdev, "NETDEV %s received %p (%p+%zx)\n",
|
||||
netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
|
||||
|
||||
/* Discard packet (for test purposes) if applicable */
|
||||
if ( ( NETDEV_DISCARD_RATE > 0 ) &&
|
||||
@@ -291,8 +291,8 @@ void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
|
||||
void netdev_rx_err ( struct net_device *netdev,
|
||||
struct io_buffer *iobuf, int rc ) {
|
||||
|
||||
DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
|
||||
netdev, iobuf, strerror ( rc ) );
|
||||
DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
|
||||
netdev->name, iobuf, strerror ( rc ) );
|
||||
|
||||
/* Discard packet */
|
||||
free_iob ( iobuf );
|
||||
@@ -405,8 +405,10 @@ int register_netdev ( struct net_device *netdev ) {
|
||||
int rc;
|
||||
|
||||
/* Create device name */
|
||||
snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
|
||||
ifindex++ );
|
||||
if ( netdev->name[0] == '\0' ) {
|
||||
snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
|
||||
ifindex++ );
|
||||
}
|
||||
|
||||
/* Set initial link-layer address */
|
||||
netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
|
||||
@@ -414,23 +416,24 @@ int register_netdev ( struct net_device *netdev ) {
|
||||
/* Add to device list */
|
||||
netdev_get ( netdev );
|
||||
list_add_tail ( &netdev->list, &net_devices );
|
||||
DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
|
||||
netdev, netdev->name, netdev->dev->name,
|
||||
DBGC ( netdev, "NETDEV %s registered (phys %s hwaddr %s)\n",
|
||||
netdev->name, netdev->dev->name,
|
||||
netdev_addr ( netdev ) );
|
||||
|
||||
/* Register per-netdev configuration settings */
|
||||
if ( ( rc = register_settings ( netdev_settings ( netdev ),
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( netdev, "NETDEV %p could not register settings: %s\n",
|
||||
netdev, strerror ( rc ) );
|
||||
NULL, netdev->name ) ) != 0 ) {
|
||||
DBGC ( netdev, "NETDEV %s could not register settings: %s\n",
|
||||
netdev->name, strerror ( rc ) );
|
||||
goto err_register_settings;
|
||||
}
|
||||
|
||||
/* Probe device */
|
||||
for_each_table_entry ( driver, NET_DRIVERS ) {
|
||||
if ( ( rc = driver->probe ( netdev ) ) != 0 ) {
|
||||
DBGC ( netdev, "NETDEV %p could not add %s device: "
|
||||
"%s\n", netdev, driver->name, strerror ( rc ) );
|
||||
DBGC ( netdev, "NETDEV %s could not add %s device: "
|
||||
"%s\n", netdev->name, driver->name,
|
||||
strerror ( rc ) );
|
||||
goto err_probe;
|
||||
}
|
||||
}
|
||||
@@ -458,15 +461,15 @@ int netdev_open ( struct net_device *netdev ) {
|
||||
if ( netdev->state & NETDEV_OPEN )
|
||||
return 0;
|
||||
|
||||
DBGC ( netdev, "NETDEV %p opening\n", netdev );
|
||||
DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
|
||||
|
||||
/* Mark as opened */
|
||||
netdev->state |= NETDEV_OPEN;
|
||||
|
||||
/* Open the device */
|
||||
if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Mark as opened */
|
||||
netdev->state |= NETDEV_OPEN;
|
||||
|
||||
/* Add to head of open devices list */
|
||||
list_add ( &netdev->open_list, &open_net_devices );
|
||||
|
||||
@@ -487,7 +490,7 @@ void netdev_close ( struct net_device *netdev ) {
|
||||
if ( ! ( netdev->state & NETDEV_OPEN ) )
|
||||
return;
|
||||
|
||||
DBGC ( netdev, "NETDEV %p closing\n", netdev );
|
||||
DBGC ( netdev, "NETDEV %s closing\n", netdev->name );
|
||||
|
||||
/* Remove from open devices list */
|
||||
list_del ( &netdev->open_list );
|
||||
@@ -529,7 +532,7 @@ void unregister_netdev ( struct net_device *netdev ) {
|
||||
/* Remove from device list */
|
||||
list_del ( &netdev->list );
|
||||
netdev_put ( netdev );
|
||||
DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
|
||||
DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
|
||||
}
|
||||
|
||||
/** Enable or disable interrupts
|
||||
@@ -661,21 +664,19 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
|
||||
ll_source );
|
||||
}
|
||||
|
||||
DBGC ( netdev, "NETDEV %p unknown network protocol %04x\n",
|
||||
netdev, ntohs ( net_proto ) );
|
||||
DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
|
||||
netdev->name, ntohs ( net_proto ) );
|
||||
free_iob ( iobuf );
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Single-step the network stack
|
||||
*
|
||||
* @v process Network stack process
|
||||
* Poll the network stack
|
||||
*
|
||||
* This polls all interfaces for received packets, and processes
|
||||
* packets from the RX queue.
|
||||
*/
|
||||
static void net_step ( struct process *process __unused ) {
|
||||
void net_poll ( void ) {
|
||||
struct net_device *netdev;
|
||||
struct io_buffer *iobuf;
|
||||
struct ll_protocol *ll_protocol;
|
||||
@@ -690,6 +691,15 @@ static void net_step ( struct process *process __unused ) {
|
||||
/* Poll for new packets */
|
||||
netdev_poll ( netdev );
|
||||
|
||||
/* Leave received packets on the queue if receive
|
||||
* queue processing is currently frozen. This will
|
||||
* happen when the raw packets are to be manually
|
||||
* dequeued using netdev_rx_dequeue(), rather than
|
||||
* processed via the usual networking stack.
|
||||
*/
|
||||
if ( netdev_rx_frozen ( netdev ) )
|
||||
continue;
|
||||
|
||||
/* Process at most one received packet. Give priority
|
||||
* to getting packets out of the NIC over processing
|
||||
* the received packets, because we advertise a window
|
||||
@@ -698,8 +708,8 @@ static void net_step ( struct process *process __unused ) {
|
||||
*/
|
||||
if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
|
||||
|
||||
DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
|
||||
netdev, iobuf, iobuf->data,
|
||||
DBGC ( netdev, "NETDEV %s processing %p (%p+%zx)\n",
|
||||
netdev->name, iobuf, iobuf->data,
|
||||
iob_len ( iobuf ) );
|
||||
|
||||
/* Remove link-layer header */
|
||||
@@ -722,6 +732,15 @@ static void net_step ( struct process *process __unused ) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Single-step the network stack
|
||||
*
|
||||
* @v process Network stack process
|
||||
*/
|
||||
static void net_step ( struct process *process __unused ) {
|
||||
net_poll();
|
||||
}
|
||||
|
||||
/** Networking stack process */
|
||||
struct process net_process __permanent_process = {
|
||||
.list = LIST_HEAD_INIT ( net_process.list ),
|
||||
|
||||
+5
-4
@@ -12,6 +12,7 @@
|
||||
#include <ipxe/xfer.h>
|
||||
#include <ipxe/open.h>
|
||||
#include <ipxe/uri.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/tcpip.h>
|
||||
#include <ipxe/tcp.h>
|
||||
|
||||
@@ -483,14 +484,14 @@ static int tcp_xmit ( struct tcp_connection *tcp ) {
|
||||
start_timer ( &tcp->timer );
|
||||
|
||||
/* Allocate I/O buffer */
|
||||
iobuf = alloc_iob ( len + MAX_HDR_LEN );
|
||||
iobuf = alloc_iob ( len + MAX_LL_NET_HEADER_LEN );
|
||||
if ( ! iobuf ) {
|
||||
DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
|
||||
"%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
|
||||
tcp->rcv_ack );
|
||||
return -ENOMEM;
|
||||
}
|
||||
iob_reserve ( iobuf, MAX_HDR_LEN );
|
||||
iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
|
||||
|
||||
/* Fill data payload from transmit queue */
|
||||
tcp_process_tx_queue ( tcp, len, iobuf, 0 );
|
||||
@@ -627,14 +628,14 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
|
||||
int rc;
|
||||
|
||||
/* Allocate space for dataless TX buffer */
|
||||
iobuf = alloc_iob ( MAX_HDR_LEN );
|
||||
iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN );
|
||||
if ( ! iobuf ) {
|
||||
DBGC ( tcp, "TCP %p could not allocate iobuf for RST "
|
||||
"%08x..%08x %08x\n", tcp, ntohl ( in_tcphdr->ack ),
|
||||
ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ) );
|
||||
return -ENOMEM;
|
||||
}
|
||||
iob_reserve ( iobuf, MAX_HDR_LEN );
|
||||
iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
|
||||
|
||||
/* Construct RST response */
|
||||
tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
|
||||
|
||||
+20
-4
@@ -59,6 +59,22 @@ FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
|
||||
__einfo_error ( EINFO_EACCES_INCORRECT_TARGET_PASSWORD )
|
||||
#define EINFO_EACCES_INCORRECT_TARGET_PASSWORD \
|
||||
__einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect target password" )
|
||||
#define EINVAL_ROOT_PATH_TOO_SHORT \
|
||||
__einfo_error ( EINFO_EINVAL_ROOT_PATH_TOO_SHORT )
|
||||
#define EINFO_EINVAL_ROOT_PATH_TOO_SHORT \
|
||||
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Root path too short" )
|
||||
#define EINVAL_BAD_CREDENTIAL_MIX \
|
||||
__einfo_error ( EINFO_EINVAL_BAD_CREDENTIAL_MIX )
|
||||
#define EINFO_EINVAL_BAD_CREDENTIAL_MIX \
|
||||
__einfo_uniqify ( EINFO_EINVAL, 0x02, "Bad credential mix" )
|
||||
#define EINVAL_NO_ROOT_PATH \
|
||||
__einfo_error ( EINFO_EINVAL_NO_ROOT_PATH )
|
||||
#define EINFO_EINVAL_NO_ROOT_PATH \
|
||||
__einfo_uniqify ( EINFO_EINVAL, 0x03, "No root path" )
|
||||
#define EINVAL_NO_TARGET_IQN \
|
||||
__einfo_error ( EINFO_EINVAL_NO_TARGET_IQN )
|
||||
#define EINFO_EINVAL_NO_TARGET_IQN \
|
||||
__einfo_uniqify ( EINFO_EINVAL, 0x04, "No target IQN" )
|
||||
#define ENOTSUP_INITIATOR_STATUS \
|
||||
__einfo_error ( EINFO_ENOTSUP_INITIATOR_STATUS )
|
||||
#define EINFO_ENOTSUP_INITIATOR_STATUS \
|
||||
@@ -1787,7 +1803,7 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
|
||||
if ( ! *rp ) {
|
||||
DBGC ( iscsi, "iSCSI %p root path \"%s\" "
|
||||
"too short\n", iscsi, root_path );
|
||||
return -EINVAL;
|
||||
return -EINVAL_ROOT_PATH_TOO_SHORT;
|
||||
}
|
||||
}
|
||||
*(rp++) = '\0';
|
||||
@@ -1870,7 +1886,7 @@ static int iscsi_set_auth ( struct iscsi_session *iscsi,
|
||||
( initiator_password ? "" : "no " ),
|
||||
( target_username ? "" : "no " ),
|
||||
( target_password ? "" : "no " ) );
|
||||
return -EINVAL;
|
||||
return -EINVAL_BAD_CREDENTIAL_MIX;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1886,7 +1902,7 @@ static int iscsi_open ( struct interface *parent, struct uri *uri ) {
|
||||
|
||||
/* Sanity check */
|
||||
if ( ! uri->opaque ) {
|
||||
rc = -EINVAL;
|
||||
rc = -EINVAL_NO_ROOT_PATH;
|
||||
goto err_sanity_uri;
|
||||
}
|
||||
|
||||
@@ -1924,7 +1940,7 @@ static int iscsi_open ( struct interface *parent, struct uri *uri ) {
|
||||
if ( ! iscsi->target_iqn ) {
|
||||
DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
|
||||
iscsi, uri->opaque );
|
||||
rc = -EINVAL;
|
||||
rc = -EINVAL_NO_TARGET_IQN;
|
||||
goto err_sanity_iqn;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -9,6 +9,7 @@
|
||||
#include <ipxe/xfer.h>
|
||||
#include <ipxe/open.h>
|
||||
#include <ipxe/uri.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/udp.h>
|
||||
|
||||
/** @file
|
||||
@@ -197,7 +198,8 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
|
||||
int rc;
|
||||
|
||||
/* Check we can accommodate the header */
|
||||
if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
|
||||
if ( ( rc = iob_ensure_headroom ( iobuf,
|
||||
MAX_LL_NET_HEADER_LEN ) ) != 0 ) {
|
||||
free_iob ( iobuf );
|
||||
return rc;
|
||||
}
|
||||
@@ -361,13 +363,13 @@ static struct io_buffer * udp_xfer_alloc_iob ( struct udp_connection *udp,
|
||||
size_t len ) {
|
||||
struct io_buffer *iobuf;
|
||||
|
||||
iobuf = alloc_iob ( UDP_MAX_HLEN + len );
|
||||
iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len );
|
||||
if ( ! iobuf ) {
|
||||
DBGC ( udp, "UDP %p cannot allocate buffer of length %zd\n",
|
||||
udp, len );
|
||||
return NULL;
|
||||
}
|
||||
iob_reserve ( iobuf, UDP_MAX_HLEN );
|
||||
iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
|
||||
return iobuf;
|
||||
}
|
||||
|
||||
|
||||
+35
-29
@@ -553,7 +553,8 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
||||
/* Register settings */
|
||||
parent = netdev_settings ( dhcp->netdev );
|
||||
settings = &dhcppkt->settings;
|
||||
if ( ( rc = register_settings ( settings, parent ) ) != 0 ) {
|
||||
if ( ( rc = register_settings ( settings, parent,
|
||||
DHCP_SETTINGS_NAME ) ) != 0 ) {
|
||||
DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
|
||||
dhcp, strerror ( rc ) );
|
||||
dhcp_finished ( dhcp, rc );
|
||||
@@ -568,9 +569,8 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
||||
* without performing a ProxyDHCPREQUEST
|
||||
*/
|
||||
settings = &dhcp->proxy_offer->settings;
|
||||
settings->name = PROXYDHCP_SETTINGS_NAME;
|
||||
if ( ( rc = register_settings ( settings,
|
||||
NULL ) ) != 0 ) {
|
||||
if ( ( rc = register_settings ( settings, NULL,
|
||||
PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
|
||||
DBGC ( dhcp, "DHCP %p could not register "
|
||||
"proxy settings: %s\n",
|
||||
dhcp, strerror ( rc ) );
|
||||
@@ -670,8 +670,8 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
|
||||
return;
|
||||
|
||||
/* Register settings */
|
||||
settings->name = PROXYDHCP_SETTINGS_NAME;
|
||||
if ( ( rc = register_settings ( settings, NULL ) ) != 0 ) {
|
||||
if ( ( rc = register_settings ( settings, NULL,
|
||||
PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
|
||||
DBGC ( dhcp, "DHCP %p could not register proxy settings: %s\n",
|
||||
dhcp, strerror ( rc ) );
|
||||
dhcp_finished ( dhcp, rc );
|
||||
@@ -809,8 +809,8 @@ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
|
||||
return;
|
||||
|
||||
/* Register settings */
|
||||
dhcppkt->settings.name = PXEBS_SETTINGS_NAME;
|
||||
if ( ( rc = register_settings ( &dhcppkt->settings, NULL ) ) != 0 ) {
|
||||
if ( ( rc = register_settings ( &dhcppkt->settings, NULL,
|
||||
PXEBS_SETTINGS_NAME ) ) != 0 ) {
|
||||
DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
|
||||
dhcp, strerror ( rc ) );
|
||||
dhcp_finished ( dhcp, rc );
|
||||
@@ -867,20 +867,24 @@ static struct dhcp_session_state dhcp_state_pxebs = {
|
||||
* Construct DHCP client hardware address field and broadcast flag
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v hlen DHCP hardware address length to fill in
|
||||
* @v flags DHCP flags to fill in
|
||||
* @ret chaddr DHCP client hardware address
|
||||
* @v chaddr Hardware address buffer
|
||||
* @v flags Flags to set (or NULL)
|
||||
* @ret hlen Hardware address length
|
||||
*/
|
||||
void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen,
|
||||
uint16_t *flags ) {
|
||||
unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
|
||||
uint16_t *flags ) {
|
||||
struct ll_protocol *ll_protocol = netdev->ll_protocol;
|
||||
typeof ( ( ( struct dhcphdr * ) NULL )->chaddr ) chaddr;
|
||||
struct dhcphdr *dhcphdr;
|
||||
int rc;
|
||||
|
||||
/* If the link-layer address cannot fit into the chaddr field
|
||||
* (as is the case for IPoIB) then try using the hardware
|
||||
* address instead. If we do this, set the broadcast flag,
|
||||
* since chaddr then does not represent a valid link-layer
|
||||
* address for the return path.
|
||||
* (as is the case for IPoIB) then try using the Ethernet-
|
||||
* compatible link-layer address. If we do this, set the
|
||||
* broadcast flag, since chaddr then does not represent a
|
||||
* valid link-layer address for the return path.
|
||||
*
|
||||
* If we cannot produce an Ethernet-compatible link-layer
|
||||
* address, try using the hardware address.
|
||||
*
|
||||
* If even the hardware address is too large, use an empty
|
||||
* chaddr field and set the broadcast flag.
|
||||
@@ -891,16 +895,19 @@ void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen,
|
||||
* storage, or by eliminating the hardware address completely
|
||||
* from the DHCP packet, which seems unfriendly to users.
|
||||
*/
|
||||
if ( ( *hlen = ll_protocol->ll_addr_len ) <= sizeof ( chaddr ) ) {
|
||||
return netdev->ll_addr;
|
||||
if ( ll_protocol->ll_addr_len <= sizeof ( dhcphdr->chaddr ) ) {
|
||||
memcpy ( chaddr, netdev->ll_addr, ll_protocol->ll_addr_len );
|
||||
return ll_protocol->ll_addr_len;
|
||||
}
|
||||
*flags = htons ( BOOTP_FL_BROADCAST );
|
||||
if ( ( *hlen = ll_protocol->hw_addr_len ) <= sizeof ( chaddr ) ) {
|
||||
return netdev->hw_addr;
|
||||
} else {
|
||||
*hlen = 0;
|
||||
return NULL;
|
||||
if ( flags )
|
||||
*flags |= htons ( BOOTP_FL_BROADCAST );
|
||||
if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr, chaddr ) ) == 0 )
|
||||
return ETH_ALEN;
|
||||
if ( ll_protocol->hw_addr_len <= sizeof ( dhcphdr->chaddr ) ) {
|
||||
memcpy ( chaddr, netdev->hw_addr, ll_protocol->hw_addr_len );
|
||||
return ll_protocol->hw_addr_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -923,7 +930,6 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
||||
const void *options, size_t options_len,
|
||||
void *data, size_t max_len ) {
|
||||
struct dhcphdr *dhcphdr = data;
|
||||
void *chaddr;
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
@@ -936,8 +942,8 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
||||
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
|
||||
dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
|
||||
dhcphdr->op = dhcp_op[msgtype];
|
||||
chaddr = dhcp_chaddr ( netdev, &dhcphdr->hlen, &dhcphdr->flags );
|
||||
memcpy ( dhcphdr->chaddr, chaddr, dhcphdr->hlen );
|
||||
dhcphdr->hlen = dhcp_chaddr ( netdev, dhcphdr->chaddr,
|
||||
&dhcphdr->flags );
|
||||
memcpy ( dhcphdr->options, options, options_len );
|
||||
|
||||
/* Initialise DHCP packet structure */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user