diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c')
-rw-r--r-- | qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c | 1084 |
1 files changed, 0 insertions, 1084 deletions
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c deleted file mode 100644 index 2eb68178a..000000000 --- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c +++ /dev/null @@ -1,1084 +0,0 @@ -/** @file - * - * PXE UNDI API - * - */ - -/* - * Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <byteswap.h> -#include <basemem_packet.h> -#include <ipxe/netdevice.h> -#include <ipxe/iobuf.h> -#include <ipxe/device.h> -#include <ipxe/pci.h> -#include <ipxe/if_ether.h> -#include <ipxe/ip.h> -#include <ipxe/arp.h> -#include <ipxe/rarp.h> -#include <ipxe/profile.h> -#include "pxe.h" - -/** - * Count of outstanding transmitted packets - * - * This is incremented each time PXENV_UNDI_TRANSMIT is called, and - * decremented each time that PXENV_UNDI_ISR is called with the TX - * queue empty, stopping when the count reaches zero. This allows us - * to provide a pessimistic approximation of TX completion events to - * the PXE NBP simply by monitoring the netdev's TX queue. - */ -static int undi_tx_count = 0; - -struct net_device *pxe_netdev = NULL; - -/** Transmit profiler */ -static struct profiler undi_tx_profiler __profiler = { .name = "undi.tx" }; - -/** - * Set network device as current PXE network device - * - * @v netdev Network device, or NULL - */ -void pxe_set_netdev ( struct net_device *netdev ) { - - if ( pxe_netdev ) { - netdev_rx_unfreeze ( pxe_netdev ); - netdev_put ( pxe_netdev ); - } - - pxe_netdev = NULL; - - if ( netdev ) - pxe_netdev = netdev_get ( netdev ); -} - -/** - * Open PXE network device - * - * @ret rc Return status code - */ -static int pxe_netdev_open ( void ) { - int rc; - - assert ( pxe_netdev != NULL ); - - if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 ) - return rc; - - netdev_rx_freeze ( pxe_netdev ); - netdev_irq ( pxe_netdev, 1 ); - - return 0; -} - -/** - * Close PXE network device - * - */ -static void pxe_netdev_close ( void ) { - - assert ( pxe_netdev != NULL ); - netdev_rx_unfreeze ( pxe_netdev ); - netdev_irq ( pxe_netdev, 0 ); - netdev_close ( pxe_netdev ); - undi_tx_count = 0; -} - -/** - * Dump multicast address list - * - * @v mcast PXE multicast address list - */ -static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) { - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - unsigned int i; - - for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) { - DBGC ( &pxe_netdev, " %s", - ll_protocol->ntoa ( mcast->McastAddr[i] ) ); - } -} - -/* PXENV_UNDI_STARTUP - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP called with no " - "network device\n" ); - undi_startup->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - undi_startup->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_CLEANUP - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP called with no " - "network device\n" ); - undi_cleanup->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Close network device */ - pxe_netdev_close(); - - undi_cleanup->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_INITIALIZE - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE *undi_initialize ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE protocolini %08x\n", - undi_initialize->ProtocolIni ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE called with no " - "network device\n" ); - undi_initialize->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - undi_initialize->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_RESET_ADAPTER - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET *undi_reset_adapter ) { - int rc; - - DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER" ); - pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf ); - DBGC ( &pxe_netdev, "\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER called with no " - "network device\n" ); - undi_reset_adapter->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Close and reopen network device */ - pxe_netdev_close(); - if ( ( rc = pxe_netdev_open() ) != 0 ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER could not " - "reopen %s: %s\n", pxe_netdev->name, strerror ( rc ) ); - undi_reset_adapter->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - undi_reset_adapter->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SHUTDOWN - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN *undi_shutdown ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN called with no " - "network device\n" ); - undi_shutdown->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Close network device */ - pxe_netdev_close(); - - undi_shutdown->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_OPEN - * - * Status: working - */ -static PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) { - int rc; - - DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN flag %04x filter %04x", - undi_open->OpenFlag, undi_open->PktFilter ); - pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf ); - DBGC ( &pxe_netdev, "\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN called with no " - "network device\n" ); - undi_open->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Open network device */ - if ( ( rc = pxe_netdev_open() ) != 0 ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN could not open %s: %s\n", - pxe_netdev->name, strerror ( rc ) ); - undi_open->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - undi_open->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_CLOSE - * - * Status: working - */ -static PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE called with no " - "network device\n" ); - undi_close->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Close network device */ - pxe_netdev_close(); - - undi_close->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_TRANSMIT - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT *undi_transmit ) { - struct s_PXENV_UNDI_TBD tbd; - struct DataBlk *datablk; - struct io_buffer *iobuf; - struct net_protocol *net_protocol; - struct ll_protocol *ll_protocol; - char destaddr[MAX_LL_ADDR_LEN]; - const void *ll_dest; - size_t len; - unsigned int i; - int rc; - - /* Start profiling */ - profile_start ( &undi_tx_profiler ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_TRANSMIT called with no " - "network device\n" ); - undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT" ); - - /* 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. - */ - if ( ! netdev_rx_frozen ( pxe_netdev ) ) { - netdev_rx_freeze ( pxe_netdev ); - netdev_irq ( pxe_netdev, 1 ); - } - - /* Identify network-layer protocol */ - switch ( undi_transmit->Protocol ) { - case P_IP: net_protocol = &ipv4_protocol; break; - case P_ARP: net_protocol = &arp_protocol; break; - case P_RARP: net_protocol = &rarp_protocol; break; - case P_UNKNOWN: - net_protocol = NULL; - break; - default: - DBGC2 ( &pxe_netdev, " %02x invalid protocol\n", - undi_transmit->Protocol ); - undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; - return PXENV_EXIT_FAILURE; - } - DBGC2 ( &pxe_netdev, " %s", - ( net_protocol ? net_protocol->name : "RAW" ) ); - - /* Calculate total packet length */ - copy_from_real ( &tbd, undi_transmit->TBD.segment, - undi_transmit->TBD.offset, sizeof ( tbd ) ); - len = tbd.ImmedLength; - DBGC2 ( &pxe_netdev, " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset, - tbd.ImmedLength ); - for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) { - datablk = &tbd.DataBlock[i]; - len += datablk->TDDataLen; - DBGC2 ( &pxe_netdev, " %04x:%04x+%x", - datablk->TDDataPtr.segment, datablk->TDDataPtr.offset, - datablk->TDDataLen ); - } - - /* Allocate and fill I/O buffer */ - iobuf = alloc_iob ( MAX_LL_HEADER_LEN + - ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) ); - if ( ! iobuf ) { - DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" ); - undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES; - return PXENV_EXIT_FAILURE; - } - 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++ ) { - datablk = &tbd.DataBlock[i]; - copy_from_real ( iob_put ( iobuf, datablk->TDDataLen ), - datablk->TDDataPtr.segment, - datablk->TDDataPtr.offset, - datablk->TDDataLen ); - } - - /* Add link-layer header, if required to do so */ - if ( net_protocol != NULL ) { - - /* Calculate destination address */ - ll_protocol = pxe_netdev->ll_protocol; - if ( undi_transmit->XmitFlag == XMT_DESTADDR ) { - copy_from_real ( destaddr, - undi_transmit->DestAddr.segment, - undi_transmit->DestAddr.offset, - ll_protocol->ll_addr_len ); - ll_dest = destaddr; - DBGC2 ( &pxe_netdev, " DEST %s", - ll_protocol->ntoa ( ll_dest ) ); - } else { - ll_dest = pxe_netdev->ll_broadcast; - DBGC2 ( &pxe_netdev, " BCAST" ); - } - - /* Add link-layer header */ - if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest, - pxe_netdev->ll_addr, - net_protocol->net_proto ))!=0){ - DBGC2 ( &pxe_netdev, " could not add link-layer " - "header: %s\n", strerror ( rc ) ); - free_iob ( iobuf ); - undi_transmit->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - } - - /* Flag transmission as in-progress. Do this before starting - * to transmit the packet, because the ISR may trigger before - * we return from netdev_tx(). - */ - undi_tx_count++; - - /* Transmit packet */ - DBGC2 ( &pxe_netdev, "\n" ); - if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) { - DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT could not transmit: " - "%s\n", strerror ( rc ) ); - undi_tx_count--; - undi_transmit->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - - profile_stop ( &undi_tx_profiler ); - undi_transmit->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SET_MCAST_ADDRESS - * - * Status: working (for NICs that support receive-all-multicast) - */ -static PXENV_EXIT_t -pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS - *undi_set_mcast_address ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS" ); - pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf ); - DBGC ( &pxe_netdev, "\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS called with " - "no network device\n" ); - undi_set_mcast_address->Status = - PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SET_STATION_ADDRESS - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS - *undi_set_station_address ) { - struct ll_protocol *ll_protocol; - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS called " - "with no network device\n" ); - undi_set_station_address->Status = - PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - ll_protocol = pxe_netdev->ll_protocol; - DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS %s", - ll_protocol->ntoa ( undi_set_station_address->StationAddress ) ); - - /* If adapter is open, the change will have no effect; return - * an error - */ - if ( netdev_is_open ( pxe_netdev ) ) { - DBGC ( &pxe_netdev, " failed: netdev is open\n" ); - undi_set_station_address->Status = - PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Update MAC address */ - memcpy ( pxe_netdev->ll_addr, - &undi_set_station_address->StationAddress, - ll_protocol->ll_addr_len ); - - DBGC ( &pxe_netdev, "\n" ); - undi_set_station_address->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_SET_PACKET_FILTER - * - * Status: won't implement (would require driver API changes for no - * real benefit) - */ -static PXENV_EXIT_t -pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER - *undi_set_packet_filter ) { - - DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER %02x\n", - undi_set_packet_filter->filter ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER called with " - "no network device\n" ); - undi_set_packet_filter->Status = - PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Pretend that we succeeded, otherwise the 3Com DOS UNDI - * driver refuses to load. (We ignore the filter value in the - * PXENV_UNDI_OPEN call anyway.) - */ - undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS; - - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_INFORMATION - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION - *undi_get_information ) { - struct device *dev; - struct ll_protocol *ll_protocol; - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION called with no " - "network device\n" ); - undi_get_information->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION" ); - - /* Fill in information */ - dev = pxe_netdev->dev; - ll_protocol = pxe_netdev->ll_protocol; - undi_get_information->BaseIo = dev->desc.ioaddr; - undi_get_information->IntNumber = - ( netdev_irq_supported ( pxe_netdev ) ? dev->desc.irq : 0 ); - /* Cheat: assume all cards can cope with this */ - undi_get_information->MaxTranUnit = ETH_MAX_MTU; - undi_get_information->HwType = ntohs ( ll_protocol->ll_proto ); - undi_get_information->HwAddrLen = ll_protocol->ll_addr_len; - assert ( ll_protocol->ll_addr_len <= - sizeof ( undi_get_information->CurrentNodeAddress ) ); - memcpy ( &undi_get_information->CurrentNodeAddress, - pxe_netdev->ll_addr, - sizeof ( undi_get_information->CurrentNodeAddress ) ); - ll_protocol->init_addr ( pxe_netdev->hw_addr, - &undi_get_information->PermNodeAddress ); - undi_get_information->ROMAddress = 0; - /* nic.rom_info->rom_segment; */ - /* We only provide the ability to receive or transmit a single - * packet at a time. This is a bootloader, not an OS. - */ - undi_get_information->RxBufCt = 1; - undi_get_information->TxBufCt = 1; - - DBGC ( &pxe_netdev, " io %04x irq %d mtu %d %s %s\n", - undi_get_information->BaseIo, undi_get_information->IntNumber, - undi_get_information->MaxTranUnit, ll_protocol->name, - ll_protocol->ntoa ( &undi_get_information->CurrentNodeAddress )); - undi_get_information->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_STATISTICS - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS - *undi_get_statistics ) { - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS called with no " - "network device\n" ); - undi_get_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS" ); - - /* Report statistics */ - undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good; - undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good; - undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad; - undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad; - DBGC ( &pxe_netdev, " txok %d rxok %d rxcrc %d rxrsrc %d\n", - undi_get_statistics->XmtGoodFrames, - undi_get_statistics->RcvGoodFrames, - undi_get_statistics->RcvCRCErrors, - undi_get_statistics->RcvResourceErrors ); - - undi_get_statistics->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_CLEAR_STATISTICS - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS - *undi_clear_statistics ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS called with " - "no network device\n" ); - undi_clear_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - /* Clear statistics */ - memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) ); - memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) ); - - undi_clear_statistics->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_INITIATE_DIAGS - * - * Status: won't implement (would require driver API changes for no - * real benefit) - */ -static PXENV_EXIT_t -pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS - *undi_initiate_diags ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS called with no " - "network device\n" ); - undi_initiate_diags->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - -/* PXENV_UNDI_FORCE_INTERRUPT - * - * Status: won't implement (would require driver API changes for no - * perceptible benefit) - */ -static PXENV_EXIT_t -pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT - *undi_force_interrupt ) { - DBGC ( &pxe_netdev, - "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" ); - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_FORCE_INTERRUPT called with no " - "network device\n" ); - undi_force_interrupt->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -} - -/* PXENV_UNDI_GET_MCAST_ADDRESS - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS - *undi_get_mcast_address ) { - struct ll_protocol *ll_protocol; - struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr }; - int rc; - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS called with " - "no network device\n" ); - undi_get_mcast_address->Status = - PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS %s", - inet_ntoa ( ip ) ); - - /* Hash address using the network device's link-layer protocol */ - ll_protocol = pxe_netdev->ll_protocol; - if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip, - undi_get_mcast_address->MediaAddr ))!=0){ - DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) ); - undi_get_mcast_address->Status = PXENV_STATUS ( rc ); - return PXENV_EXIT_FAILURE; - } - DBGC ( &pxe_netdev, "=>%s\n", - ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) ); - - undi_get_mcast_address->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_NIC_TYPE - * - * Status: working - */ -static PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE - *undi_get_nic_type ) { - struct device *dev; - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE called with " - "no network device\n" ); - undi_get_nic_type->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE" ); - - /* Fill in information */ - memset ( &undi_get_nic_type->info, 0, - sizeof ( undi_get_nic_type->info ) ); - dev = pxe_netdev->dev; - switch ( dev->desc.bus_type ) { - case BUS_TYPE_PCI: { - struct pci_nic_info *info = &undi_get_nic_type->info.pci; - - undi_get_nic_type->NicType = PCI_NIC; - info->Vendor_ID = dev->desc.vendor; - info->Dev_ID = dev->desc.device; - info->Base_Class = PCI_BASE_CLASS ( dev->desc.class ); - info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class ); - info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class ); - info->BusDevFunc = dev->desc.location; - /* 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. - */ - DBGC ( &pxe_netdev, " 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, - info->Dev_ID, info->SubVendor_ID, info->SubDevice_ID, - info->Base_Class, info->Sub_Class, info->Prog_Intf, - info->Rev ); - break; } - case BUS_TYPE_ISAPNP: { - struct pnp_nic_info *info = &undi_get_nic_type->info.pnp; - - undi_get_nic_type->NicType = PnP_NIC; - info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) | - dev->desc.device ); - info->CardSelNum = dev->desc.location; - /* Cheat: remaining fields are probably unnecessary, - * and would require adding extra code to isapnp.c. - */ - DBGC ( &pxe_netdev, " ISAPnP CSN %04x %08x %02x%02x%02x\n", - info->CardSelNum, info->EISA_Dev_ID, - info->Base_Class, info->Sub_Class, info->Prog_Intf ); - break; } - default: - DBGC ( &pxe_netdev, " failed: unknown bus type\n" ); - undi_get_nic_type->Status = PXENV_STATUS_FAILURE; - return PXENV_EXIT_FAILURE; - } - - undi_get_nic_type->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_IFACE_INFO - * - * Status: working - */ -static PXENV_EXIT_t -pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO - *undi_get_iface_info ) { - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO called with " - "no network device\n" ); - undi_get_iface_info->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO" ); - - /* Just hand back some info, doesn't really matter what it is. - * Most PXE stacks seem to take this approach. - */ - snprintf ( ( char * ) undi_get_iface_info->IfaceType, - sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" ); - undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */ - undi_get_iface_info->ServiceFlags = - ( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST | - SUPPORTED_SET_STATION_ADDRESS | SUPPORTED_RESET | - SUPPORTED_OPEN_CLOSE ); - if ( netdev_irq_supported ( pxe_netdev ) ) - undi_get_iface_info->ServiceFlags |= SUPPORTED_IRQ; - memset ( undi_get_iface_info->Reserved, 0, - sizeof(undi_get_iface_info->Reserved) ); - - DBGC ( &pxe_netdev, " %s %dbps flags %08x\n", - undi_get_iface_info->IfaceType, undi_get_iface_info->LinkSpeed, - undi_get_iface_info->ServiceFlags ); - undi_get_iface_info->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/* PXENV_UNDI_GET_STATE - * - * Status: impossible due to opcode collision - */ - -/* PXENV_UNDI_ISR - * - * Status: working - */ -static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { - struct io_buffer *iobuf; - size_t len; - struct ll_protocol *ll_protocol; - const void *ll_dest; - const void *ll_source; - uint16_t net_proto; - unsigned int flags; - size_t ll_hlen; - struct net_protocol *net_protocol; - unsigned int prottype; - int rc; - - /* Use a different debug colour, since UNDI ISR messages are - * likely to be interspersed amongst other UNDI messages. - */ - - /* Sanity check */ - if ( ! pxe_netdev ) { - DBGC ( &pxenv_undi_isr, "PXENV_UNDI_ISR called with " - "no network device\n" ); - undi_isr->Status = PXENV_STATUS_UNDI_INVALID_STATE; - return PXENV_EXIT_FAILURE; - } - - DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" ); - - /* Just in case some idiot actually looks at these fields when - * we weren't meant to fill them in... - */ - undi_isr->BufferLength = 0; - undi_isr->FrameLength = 0; - undi_isr->FrameHeaderLength = 0; - undi_isr->ProtType = 0; - undi_isr->PktType = 0; - - switch ( undi_isr->FuncFlag ) { - case PXENV_UNDI_ISR_IN_START : - DBGC2 ( &pxenv_undi_isr, " START" ); - - /* Call poll(). This should acknowledge the device - * interrupt and queue up any received packet. - */ - net_poll(); - - /* A 100% accurate determination of "OURS" vs "NOT - * OURS" is difficult to achieve without invasive and - * unpleasant changes to the driver model. We settle - * for always returning "OURS" if interrupts are - * currently enabled. - * - * Returning "NOT OURS" when interrupts are disabled - * allows us to avoid a potential interrupt storm when - * we are on a shared interrupt line; if we were to - * always return "OURS" then the other device's ISR - * may never be called. - */ - if ( netdev_irq_enabled ( pxe_netdev ) ) { - DBGC2 ( &pxenv_undi_isr, " OURS" ); - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS; - } else { - DBGC2 ( &pxenv_undi_isr, " NOT OURS" ); - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_NOT_OURS; - } - - /* Disable interrupts */ - netdev_irq ( pxe_netdev, 0 ); - - break; - case PXENV_UNDI_ISR_IN_PROCESS : - case PXENV_UNDI_ISR_IN_GET_NEXT : - DBGC2 ( &pxenv_undi_isr, " %s", - ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ? - "PROCESS" : "GET_NEXT" ) ); - - /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call - * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START; - * they just sit in a tight polling loop merrily - * violating the PXE spec with repeated calls to - * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to - * cope with these out-of-spec clients. - */ - net_poll(); - - /* If we have not yet marked a TX as complete, and the - * netdev TX queue is empty, report the TX completion. - */ - if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) { - DBGC2 ( &pxenv_undi_isr, " TXC" ); - undi_tx_count--; - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT; - break; - } - - /* Remove first packet from netdev RX queue */ - iobuf = netdev_rx_dequeue ( pxe_netdev ); - if ( ! iobuf ) { - DBGC2 ( &pxenv_undi_isr, " DONE" ); - /* No more packets remaining */ - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; - /* Re-enable interrupts */ - netdev_irq ( pxe_netdev, 1 ); - break; - } - - /* Copy packet to base memory buffer */ - len = iob_len ( iobuf ); - DBGC2 ( &pxenv_undi_isr, " RX" ); - if ( len > sizeof ( basemem_packet ) ) { - /* Should never happen */ - DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len ); - len = sizeof ( basemem_packet ); - } - memcpy ( basemem_packet, iobuf->data, len ); - - /* Strip link-layer header */ - ll_protocol = pxe_netdev->ll_protocol; - if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest, - &ll_source, &net_proto, - &flags ) ) != 0 ) { - /* Assume unknown net_proto and no ll_source */ - net_proto = 0; - ll_source = NULL; - } - ll_hlen = ( len - iob_len ( iobuf ) ); - - /* Determine network-layer protocol */ - switch ( net_proto ) { - case htons ( ETH_P_IP ): - net_protocol = &ipv4_protocol; - prottype = P_IP; - break; - case htons ( ETH_P_ARP ): - net_protocol = &arp_protocol; - prottype = P_ARP; - break; - case htons ( ETH_P_RARP ): - net_protocol = &rarp_protocol; - prottype = P_RARP; - break; - default: - net_protocol = NULL; - prottype = P_UNKNOWN; - break; - } - - /* Fill in UNDI_ISR structure */ - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE; - undi_isr->BufferLength = len; - undi_isr->FrameLength = len; - undi_isr->FrameHeaderLength = ll_hlen; - undi_isr->Frame.segment = rm_ds; - undi_isr->Frame.offset = __from_data16 ( basemem_packet ); - undi_isr->ProtType = prottype; - if ( flags & LL_BROADCAST ) { - undi_isr->PktType = P_BROADCAST; - } else if ( flags & LL_MULTICAST ) { - undi_isr->PktType = P_MULTICAST; - } else { - undi_isr->PktType = P_DIRECTED; - } - 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, - ( net_protocol ? net_protocol->name : "RAW" ), - undi_isr->FrameHeaderLength ); - - /* Free packet */ - free_iob ( iobuf ); - break; - default : - DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n", - undi_isr->FuncFlag ); - - /* Should never happen */ - undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; - undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; - return PXENV_EXIT_FAILURE; - } - - DBGC2 ( &pxenv_undi_isr, "\n" ); - undi_isr->Status = PXENV_STATUS_SUCCESS; - return PXENV_EXIT_SUCCESS; -} - -/** PXE UNDI API */ -struct pxe_api_call pxe_undi_api[] __pxe_api_call = { - PXE_API_CALL ( PXENV_UNDI_STARTUP, pxenv_undi_startup, - struct s_PXENV_UNDI_STARTUP ), - PXE_API_CALL ( PXENV_UNDI_CLEANUP, pxenv_undi_cleanup, - struct s_PXENV_UNDI_CLEANUP ), - PXE_API_CALL ( PXENV_UNDI_INITIALIZE, pxenv_undi_initialize, - struct s_PXENV_UNDI_INITIALIZE ), - PXE_API_CALL ( PXENV_UNDI_RESET_ADAPTER, pxenv_undi_reset_adapter, - struct s_PXENV_UNDI_RESET ), - PXE_API_CALL ( PXENV_UNDI_SHUTDOWN, pxenv_undi_shutdown, - struct s_PXENV_UNDI_SHUTDOWN ), - PXE_API_CALL ( PXENV_UNDI_OPEN, pxenv_undi_open, - struct s_PXENV_UNDI_OPEN ), - PXE_API_CALL ( PXENV_UNDI_CLOSE, pxenv_undi_close, - struct s_PXENV_UNDI_CLOSE ), - PXE_API_CALL ( PXENV_UNDI_TRANSMIT, pxenv_undi_transmit, - struct s_PXENV_UNDI_TRANSMIT ), - PXE_API_CALL ( PXENV_UNDI_SET_MCAST_ADDRESS, - pxenv_undi_set_mcast_address, - struct s_PXENV_UNDI_SET_MCAST_ADDRESS ), - PXE_API_CALL ( PXENV_UNDI_SET_STATION_ADDRESS, - pxenv_undi_set_station_address, - struct s_PXENV_UNDI_SET_STATION_ADDRESS ), - PXE_API_CALL ( PXENV_UNDI_SET_PACKET_FILTER, - pxenv_undi_set_packet_filter, - struct s_PXENV_UNDI_SET_PACKET_FILTER ), - PXE_API_CALL ( PXENV_UNDI_GET_INFORMATION, pxenv_undi_get_information, - struct s_PXENV_UNDI_GET_INFORMATION ), - PXE_API_CALL ( PXENV_UNDI_GET_STATISTICS, pxenv_undi_get_statistics, - struct s_PXENV_UNDI_GET_STATISTICS ), - PXE_API_CALL ( PXENV_UNDI_CLEAR_STATISTICS, pxenv_undi_clear_statistics, - struct s_PXENV_UNDI_CLEAR_STATISTICS ), - PXE_API_CALL ( PXENV_UNDI_INITIATE_DIAGS, pxenv_undi_initiate_diags, - struct s_PXENV_UNDI_INITIATE_DIAGS ), - PXE_API_CALL ( PXENV_UNDI_FORCE_INTERRUPT, pxenv_undi_force_interrupt, - struct s_PXENV_UNDI_FORCE_INTERRUPT ), - PXE_API_CALL ( PXENV_UNDI_GET_MCAST_ADDRESS, - pxenv_undi_get_mcast_address, - struct s_PXENV_UNDI_GET_MCAST_ADDRESS ), - PXE_API_CALL ( PXENV_UNDI_GET_NIC_TYPE, pxenv_undi_get_nic_type, - struct s_PXENV_UNDI_GET_NIC_TYPE ), - PXE_API_CALL ( PXENV_UNDI_GET_IFACE_INFO, pxenv_undi_get_iface_info, - struct s_PXENV_UNDI_GET_IFACE_INFO ), - PXE_API_CALL ( PXENV_UNDI_ISR, pxenv_undi_isr, - struct s_PXENV_UNDI_ISR ), -}; |