From bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 Mon Sep 17 00:00:00 2001 From: RajithaY Date: Tue, 25 Apr 2017 03:31:15 -0700 Subject: 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 --- qemu/roms/ipxe/src/drivers/net/efi/nii.c | 1185 ------------------------------ 1 file changed, 1185 deletions(-) delete mode 100644 qemu/roms/ipxe/src/drivers/net/efi/nii.c (limited to 'qemu/roms/ipxe/src/drivers/net/efi/nii.c') diff --git a/qemu/roms/ipxe/src/drivers/net/efi/nii.c b/qemu/roms/ipxe/src/drivers/net/efi/nii.c deleted file mode 100644 index b91848f5c..000000000 --- a/qemu/roms/ipxe/src/drivers/net/efi/nii.c +++ /dev/null @@ -1,1185 +0,0 @@ -/* - * Copyright (C) 2014 Michael Brown . - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "nii.h" - -/** @file - * - * NII driver - * - */ - -/* Error numbers generated by NII */ -#define EIO_INVALID_CDB __einfo_error ( EINFO_EIO_INVALID_CDB ) -#define EINFO_EIO_INVALID_CDB \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_CDB, \ - "Invalid CDB" ) -#define EIO_INVALID_CPB __einfo_error ( EINFO_EIO_INVALID_CPB ) -#define EINFO_EIO_INVALID_CPB \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_CPB, \ - "Invalid CPB" ) -#define EIO_BUSY __einfo_error ( EINFO_EIO_BUSY ) -#define EINFO_EIO_BUSY \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_BUSY, \ - "Busy" ) -#define EIO_QUEUE_FULL __einfo_error ( EINFO_EIO_QUEUE_FULL ) -#define EINFO_EIO_QUEUE_FULL \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_QUEUE_FULL, \ - "Queue full" ) -#define EIO_ALREADY_STARTED __einfo_error ( EINFO_EIO_ALREADY_STARTED ) -#define EINFO_EIO_ALREADY_STARTED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_ALREADY_STARTED, \ - "Already started" ) -#define EIO_NOT_STARTED __einfo_error ( EINFO_EIO_NOT_STARTED ) -#define EINFO_EIO_NOT_STARTED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_STARTED, \ - "Not started" ) -#define EIO_NOT_SHUTDOWN __einfo_error ( EINFO_EIO_NOT_SHUTDOWN ) -#define EINFO_EIO_NOT_SHUTDOWN \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_SHUTDOWN, \ - "Not shutdown" ) -#define EIO_ALREADY_INITIALIZED __einfo_error ( EINFO_EIO_ALREADY_INITIALIZED ) -#define EINFO_EIO_ALREADY_INITIALIZED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_ALREADY_INITIALIZED, \ - "Already initialized" ) -#define EIO_NOT_INITIALIZED __einfo_error ( EINFO_EIO_NOT_INITIALIZED ) -#define EINFO_EIO_NOT_INITIALIZED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_INITIALIZED, \ - "Not initialized" ) -#define EIO_DEVICE_FAILURE __einfo_error ( EINFO_EIO_DEVICE_FAILURE ) -#define EINFO_EIO_DEVICE_FAILURE \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_DEVICE_FAILURE, \ - "Device failure" ) -#define EIO_NVDATA_FAILURE __einfo_error ( EINFO_EIO_NVDATA_FAILURE ) -#define EINFO_EIO_NVDATA_FAILURE \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NVDATA_FAILURE, \ - "Non-volatile data failure" ) -#define EIO_UNSUPPORTED __einfo_error ( EINFO_EIO_UNSUPPORTED ) -#define EINFO_EIO_UNSUPPORTED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_UNSUPPORTED, \ - "Unsupported" ) -#define EIO_BUFFER_FULL __einfo_error ( EINFO_EIO_BUFFER_FULL ) -#define EINFO_EIO_BUFFER_FULL \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_BUFFER_FULL, \ - "Buffer full" ) -#define EIO_INVALID_PARAMETER __einfo_error ( EINFO_EIO_INVALID_PARAMETER ) -#define EINFO_EIO_INVALID_PARAMETER \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_PARAMETER, \ - "Invalid parameter" ) -#define EIO_INVALID_UNDI __einfo_error ( EINFO_EIO_INVALID_UNDI ) -#define EINFO_EIO_INVALID_UNDI \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_UNDI, \ - "Invalid UNDI" ) -#define EIO_IPV4_NOT_SUPPORTED __einfo_error ( EINFO_EIO_IPV4_NOT_SUPPORTED ) -#define EINFO_EIO_IPV4_NOT_SUPPORTED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_IPV4_NOT_SUPPORTED, \ - "IPv4 not supported" ) -#define EIO_IPV6_NOT_SUPPORTED __einfo_error ( EINFO_EIO_IPV6_NOT_SUPPORTED ) -#define EINFO_EIO_IPV6_NOT_SUPPORTED \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_IPV6_NOT_SUPPORTED, \ - "IPv6 not supported" ) -#define EIO_NOT_ENOUGH_MEMORY __einfo_error ( EINFO_EIO_NOT_ENOUGH_MEMORY ) -#define EINFO_EIO_NOT_ENOUGH_MEMORY \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_ENOUGH_MEMORY, \ - "Not enough memory" ) -#define EIO_NO_DATA __einfo_error ( EINFO_EIO_NO_DATA ) -#define EINFO_EIO_NO_DATA \ - __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NO_DATA, \ - "No data" ) -#define EIO_STAT( stat ) \ - EUNIQ ( EINFO_EIO, -(stat), EIO_INVALID_CDB, EIO_INVALID_CPB, \ - EIO_BUSY, EIO_QUEUE_FULL, EIO_ALREADY_STARTED, \ - EIO_NOT_STARTED, EIO_NOT_SHUTDOWN, EIO_ALREADY_INITIALIZED, \ - EIO_NOT_INITIALIZED, EIO_DEVICE_FAILURE, EIO_NVDATA_FAILURE, \ - EIO_UNSUPPORTED, EIO_BUFFER_FULL, EIO_INVALID_PARAMETER, \ - EIO_INVALID_UNDI, EIO_IPV4_NOT_SUPPORTED, \ - EIO_IPV6_NOT_SUPPORTED, EIO_NOT_ENOUGH_MEMORY, EIO_NO_DATA ) - -/** Maximum PCI BAR - * - * This is defined in , but we - * can't #include that since it collides with . - */ -#define PCI_MAX_BAR 6 - -/** An NII NIC */ -struct nii_nic { - /** EFI device */ - struct efi_device *efidev; - /** Network interface identifier protocol */ - EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii; - /** !PXE structure */ - PXE_SW_UNDI *undi; - /** Entry point */ - EFIAPI VOID ( * issue ) ( UINT64 cdb ); - /** Generic device */ - struct device dev; - - /** PCI device */ - EFI_HANDLE pci_device; - /** PCI I/O protocol */ - EFI_PCI_IO_PROTOCOL *pci_io; - /** Memory BAR */ - unsigned int mem_bar; - /** I/O BAR */ - unsigned int io_bar; - - /** Broadcast address */ - PXE_MAC_ADDR broadcast; - /** Maximum packet length */ - size_t mtu; - - /** Hardware transmit/receive buffer */ - userptr_t buffer; - /** Hardware transmit/receive buffer length */ - size_t buffer_len; - - /** Saved task priority level */ - EFI_TPL saved_tpl; - - /** Media status is supported */ - int media; - - /** Current transmit buffer */ - struct io_buffer *txbuf; - /** Current receive buffer */ - struct io_buffer *rxbuf; -}; - -/** Maximum number of received packets per poll */ -#define NII_RX_QUOTA 4 - -/** - * Open PCI I/O protocol and identify BARs - * - * @v nii NII NIC - * @ret rc Return status code - */ -static int nii_pci_open ( struct nii_nic *nii ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE device = nii->efidev->device; - EFI_HANDLE pci_device; - union { - EFI_PCI_IO_PROTOCOL *pci_io; - void *interface; - } pci_io; - union { - EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *acpi; - void *resource; - } desc; - unsigned int bar; - EFI_STATUS efirc; - int rc; - - /* Locate PCI I/O protocol */ - if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid, - &pci_device ) ) != 0 ) { - DBGC ( nii, "NII %s could not locate PCI I/O protocol: %s\n", - nii->dev.name, strerror ( rc ) ); - goto err_locate; - } - nii->pci_device = pci_device; - - /* Open PCI I/O protocol */ - if ( ( efirc = bs->OpenProtocol ( pci_device, &efi_pci_io_protocol_guid, - &pci_io.interface, efi_image_handle, - device, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGC ( nii, "NII %s could not open PCI I/O protocol: %s\n", - nii->dev.name, strerror ( rc ) ); - goto err_open; - } - nii->pci_io = pci_io.pci_io; - - /* Identify memory and I/O BARs */ - nii->mem_bar = PCI_MAX_BAR; - nii->io_bar = PCI_MAX_BAR; - for ( bar = 0 ; bar < PCI_MAX_BAR ; bar++ ) { - efirc = nii->pci_io->GetBarAttributes ( nii->pci_io, bar, NULL, - &desc.resource ); - if ( efirc == EFI_UNSUPPORTED ) { - /* BAR not present; ignore */ - continue; - } - if ( efirc != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( nii, "NII %s could not get BAR %d attributes: " - "%s\n", nii->dev.name, bar, strerror ( rc ) ); - goto err_get_bar_attributes; - } - if ( desc.acpi->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM ) { - nii->mem_bar = bar; - } else if ( desc.acpi->ResType == ACPI_ADDRESS_SPACE_TYPE_IO ) { - nii->io_bar = bar; - } - bs->FreePool ( desc.resource ); - } - DBGC ( nii, "NII %s has ", nii->dev.name ); - if ( nii->mem_bar < PCI_MAX_BAR ) { - DBGC ( nii, "memory BAR %d and ", nii->mem_bar ); - } else { - DBGC ( nii, "no memory BAR and " ); - } - if ( nii->io_bar < PCI_MAX_BAR ) { - DBGC ( nii, "I/O BAR %d\n", nii->io_bar ); - } else { - DBGC ( nii, "no I/O BAR\n" ); - } - - return 0; - - err_get_bar_attributes: - bs->CloseProtocol ( pci_device, &efi_pci_io_protocol_guid, - efi_image_handle, device ); - err_open: - err_locate: - return rc; -} - -/** - * Close PCI I/O protocol - * - * @v nii NII NIC - * @ret rc Return status code - */ -static void nii_pci_close ( struct nii_nic *nii ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - bs->CloseProtocol ( nii->pci_device, &efi_pci_io_protocol_guid, - efi_image_handle, nii->efidev->device ); -} - -/** - * I/O callback - * - * @v unique_id NII NIC - * @v op Operations - * @v len Length of data - * @v addr Address - * @v data Data buffer - */ -static EFIAPI VOID nii_io ( UINT64 unique_id, UINT8 op, UINT8 len, UINT64 addr, - UINT64 data ) { - struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id ); - EFI_PCI_IO_PROTOCOL_ACCESS *access; - EFI_PCI_IO_PROTOCOL_IO_MEM io; - EFI_PCI_IO_PROTOCOL_WIDTH width; - unsigned int bar; - EFI_STATUS efirc; - int rc; - - /* Determine accessor and BAR */ - if ( op & ( PXE_MEM_READ | PXE_MEM_WRITE ) ) { - access = &nii->pci_io->Mem; - bar = nii->mem_bar; - } else { - access = &nii->pci_io->Io; - bar = nii->io_bar; - } - - /* Determine operaton */ - io = ( ( op & ( PXE_IO_WRITE | PXE_MEM_WRITE ) ) ? - access->Write : access->Read ); - - /* Determine width */ - width = ( fls ( len ) - 1 ); - - /* Issue operation */ - if ( ( efirc = io ( nii->pci_io, width, bar, addr, 1, - ( ( void * ) ( intptr_t ) data ) ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( nii, "NII %s I/O operation %#x failed: %s\n", - nii->dev.name, op, strerror ( rc ) ); - /* No way to report failure */ - return; - } -} - -/** - * Delay callback - * - * @v unique_id NII NIC - * @v microseconds Delay in microseconds - */ -static EFIAPI VOID nii_delay ( UINT64 unique_id __unused, UINTN microseconds ) { - - udelay ( microseconds ); -} - -/** - * Block callback - * - * @v unique_id NII NIC - * @v acquire Acquire lock - */ -static EFIAPI VOID nii_block ( UINT64 unique_id, UINT32 acquire ) { - struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id ); - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - /* This functionality (which is copied verbatim from the - * SnpDxe implementation of this function) appears to be - * totally brain-dead, since it produces no actual blocking - * behaviour. - */ - if ( acquire ) { - nii->saved_tpl = bs->RaiseTPL ( TPL_NOTIFY ); - } else { - bs->RestoreTPL ( nii->saved_tpl ); - } -} - -/** - * Construct operation from opcode and flags - * - * @v opcode Opcode - * @v opflags Flags - * @ret op Operation - */ -#define NII_OP( opcode, opflags ) ( (opcode) | ( (opflags) << 16 ) ) - -/** - * Extract opcode from operation - * - * @v op Operation - * @ret opcode Opcode - */ -#define NII_OPCODE( op ) ( (op) & 0xffff ) - -/** - * Extract flags from operation - * - * @v op Operation - * @ret opflags Flags - */ -#define NII_OPFLAGS( op ) ( (op) >> 16 ) - -/** - * Issue command with parameter block and data block - * - * @v nii NII NIC - * @v op Operation - * @v cpb Command parameter block, or NULL - * @v cpb_len Command parameter block length - * @v db Data block, or NULL - * @v db_len Data block length - * @ret stat Status flags, or negative status code - */ -static int nii_issue_cpb_db ( struct nii_nic *nii, unsigned int op, void *cpb, - size_t cpb_len, void *db, size_t db_len ) { - PXE_CDB cdb; - - /* Prepare command descriptor block */ - memset ( &cdb, 0, sizeof ( cdb ) ); - cdb.OpCode = NII_OPCODE ( op ); - cdb.OpFlags = NII_OPFLAGS ( op ); - cdb.CPBaddr = ( ( intptr_t ) cpb ); - cdb.CPBsize = cpb_len; - cdb.DBaddr = ( ( intptr_t ) db ); - cdb.DBsize = db_len; - cdb.IFnum = nii->nii->IfNum; - - /* Issue command */ - DBGC2 ( nii, "NII %s issuing %02x:%04x ifnum %d%s%s\n", - nii->dev.name, cdb.OpCode, cdb.OpFlags, cdb.IFnum, - ( cpb ? " cpb" : "" ), ( db ? " db" : "" ) ); - if ( cpb ) - DBGC2_HD ( nii, cpb, cpb_len ); - if ( db ) - DBGC2_HD ( nii, db, db_len ); - nii->issue ( ( intptr_t ) &cdb ); - - /* Check completion status */ - if ( cdb.StatCode != PXE_STATCODE_SUCCESS ) - return -cdb.StatCode; - - /* Return command-specific status flags */ - return ( cdb.StatFlags & ~PXE_STATFLAGS_STATUS_MASK ); -} - -/** - * Issue command with parameter block - * - * @v nii NII NIC - * @v op Operation - * @v cpb Command parameter block, or NULL - * @v cpb_len Command parameter block length - * @ret stat Status flags, or negative status code - */ -static int nii_issue_cpb ( struct nii_nic *nii, unsigned int op, void *cpb, - size_t cpb_len ) { - - return nii_issue_cpb_db ( nii, op, cpb, cpb_len, NULL, 0 ); -} - -/** - * Issue command with data block - * - * @v nii NII NIC - * @v op Operation - * @v db Data block, or NULL - * @v db_len Data block length - * @ret stat Status flags, or negative status code - */ -static int nii_issue_db ( struct nii_nic *nii, unsigned int op, void *db, - size_t db_len ) { - - return nii_issue_cpb_db ( nii, op, NULL, 0, db, db_len ); -} - -/** - * Issue command - * - * - * @v nii NII NIC - * @v op Operation - * @ret stat Status flags, or negative status code - */ -static int nii_issue ( struct nii_nic *nii, unsigned int op ) { - - return nii_issue_cpb_db ( nii, op, NULL, 0, NULL, 0 ); -} - -/** - * Start UNDI - * - * @v nii NII NIC - * @ret rc Return status code - */ -static int nii_start_undi ( struct nii_nic *nii ) { - PXE_CPB_START_31 cpb; - int stat; - int rc; - - /* Construct parameter block */ - memset ( &cpb, 0, sizeof ( cpb ) ); - cpb.Delay = ( ( intptr_t ) nii_delay ); - cpb.Block = ( ( intptr_t ) nii_block ); - cpb.Mem_IO = ( ( intptr_t ) nii_io ); - cpb.Unique_ID = ( ( intptr_t ) nii ); - - /* Issue command */ - if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_START, &cpb, - sizeof ( cpb ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not start: %s\n", - nii->dev.name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Stop UNDI - * - * @v nii NII NIC - */ -static void nii_stop_undi ( struct nii_nic *nii ) { - int stat; - int rc; - - /* Issue command */ - if ( ( stat = nii_issue ( nii, PXE_OPCODE_STOP ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not stop: %s\n", - nii->dev.name, strerror ( rc ) ); - /* Nothing we can do about it */ - return; - } -} - -/** - * Get initialisation information - * - * @v nii NII NIC - * @v netdev Network device to fill in - * @ret rc Return status code - */ -static int nii_get_init_info ( struct nii_nic *nii, - struct net_device *netdev ) { - PXE_DB_GET_INIT_INFO db; - int stat; - int rc; - - /* Issue command */ - if ( ( stat = nii_issue_db ( nii, PXE_OPCODE_GET_INIT_INFO, &db, - sizeof ( db ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not get initialisation info: %s\n", - nii->dev.name, strerror ( rc ) ); - return rc; - } - - /* Determine link layer protocol */ - switch ( db.IFtype ) { - case PXE_IFTYPE_ETHERNET : - netdev->ll_protocol = ðernet_protocol; - break; - default: - DBGC ( nii, "NII %s unknown interface type %#02x\n", - nii->dev.name, db.IFtype ); - return -ENOTSUP; - } - - /* Sanity checks */ - assert ( db.MediaHeaderLen == netdev->ll_protocol->ll_header_len ); - assert ( db.HWaddrLen == netdev->ll_protocol->hw_addr_len ); - assert ( db.HWaddrLen == netdev->ll_protocol->ll_addr_len ); - - /* Extract parameters */ - nii->buffer_len = db.MemoryRequired; - nii->mtu = ( db.FrameDataLen + db.MediaHeaderLen ); - netdev->max_pkt_len = nii->mtu; - nii->media = ( stat & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED ); - - return 0; -} - -/** - * Initialise UNDI - * - * @v nii NII NIC - * @v flags Flags - * @ret rc Return status code - */ -static int nii_initialise_flags ( struct nii_nic *nii, unsigned int flags ) { - PXE_CPB_INITIALIZE cpb; - PXE_DB_INITIALIZE db; - unsigned int op; - int stat; - int rc; - - /* Allocate memory buffer */ - nii->buffer = umalloc ( nii->buffer_len ); - if ( ! nii->buffer ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Construct parameter block */ - memset ( &cpb, 0, sizeof ( cpb ) ); - cpb.MemoryAddr = ( ( intptr_t ) nii->buffer ); - cpb.MemoryLength = nii->buffer_len; - - /* Construct data block */ - memset ( &db, 0, sizeof ( db ) ); - - /* Issue command */ - op = NII_OP ( PXE_OPCODE_INITIALIZE, flags ); - if ( ( stat = nii_issue_cpb_db ( nii, op, &cpb, sizeof ( cpb ), - &db, sizeof ( db ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not initialise: %s\n", - nii->dev.name, strerror ( rc ) ); - goto err_initialize; - } - - return 0; - - err_initialize: - ufree ( nii->buffer ); - err_alloc: - return rc; -} - -/** - * Initialise UNDI - * - * @v nii NII NIC - * @ret rc Return status code - */ -static int nii_initialise ( struct nii_nic *nii ) { - unsigned int flags; - - /* Initialise UNDI */ - flags = PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE; - return nii_initialise_flags ( nii, flags ); -} - -/** - * Initialise UNDI and detect cable - * - * @v nii NII NIC - * @ret rc Return status code - */ -static int nii_initialise_and_detect ( struct nii_nic *nii ) { - unsigned int flags; - - /* Initialise UNDI and detect cable. This is required to work - * around bugs in some Emulex NII drivers. - */ - flags = PXE_OPFLAGS_INITIALIZE_DETECT_CABLE; - return nii_initialise_flags ( nii, flags ); -} - -/** - * Shut down UNDI - * - * @v nii NII NIC - */ -static void nii_shutdown ( struct nii_nic *nii ) { - int stat; - int rc; - - /* Issue command */ - if ( ( stat = nii_issue ( nii, PXE_OPCODE_SHUTDOWN ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not shut down: %s\n", - nii->dev.name, strerror ( rc ) ); - /* Leak memory to avoid corruption */ - return; - } - - /* Free buffer */ - ufree ( nii->buffer ); -} - -/** - * Get station addresses - * - * @v nii NII NIC - * @v netdev Network device to fill in - * @ret rc Return status code - */ -static int nii_get_station_address ( struct nii_nic *nii, - struct net_device *netdev ) { - PXE_DB_STATION_ADDRESS db; - unsigned int op; - int stat; - int rc; - - /* Initialise UNDI */ - if ( ( rc = nii_initialise ( nii ) ) != 0 ) - goto err_initialise; - - /* Issue command */ - op = NII_OP ( PXE_OPCODE_STATION_ADDRESS, - PXE_OPFLAGS_STATION_ADDRESS_READ ); - if ( ( stat = nii_issue_db ( nii, op, &db, sizeof ( db ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not get station address: %s\n", - nii->dev.name, strerror ( rc ) ); - goto err_station_address; - } - - /* Copy MAC addresses */ - memcpy ( netdev->ll_addr, db.StationAddr, - netdev->ll_protocol->ll_addr_len ); - memcpy ( netdev->hw_addr, db.PermanentAddr, - netdev->ll_protocol->hw_addr_len ); - memcpy ( nii->broadcast, db.BroadcastAddr, - sizeof ( nii->broadcast ) ); - - err_station_address: - nii_shutdown ( nii ); - err_initialise: - return rc; -} - -/** - * Set station address - * - * @v nii NII NIC - * @v netdev Network device - * @ret rc Return status code - */ -static int nii_set_station_address ( struct nii_nic *nii, - struct net_device *netdev ) { - uint32_t implementation = nii->undi->Implementation; - PXE_CPB_STATION_ADDRESS cpb; - unsigned int op; - int stat; - int rc; - - /* Fail if setting station address is unsupported */ - if ( ! ( implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE ) ) - return -ENOTSUP; - - /* Construct parameter block */ - memset ( &cpb, 0, sizeof ( cpb ) ); - memcpy ( cpb.StationAddr, netdev->ll_addr, - netdev->ll_protocol->ll_addr_len ); - - /* Issue command */ - op = NII_OP ( PXE_OPCODE_STATION_ADDRESS, - PXE_OPFLAGS_STATION_ADDRESS_WRITE ); - if ( ( stat = nii_issue_cpb ( nii, op, &cpb, sizeof ( cpb ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not set station address: %s\n", - nii->dev.name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Set receive filters - * - * @v nii NII NIC - * @ret rc Return status code - */ -static int nii_set_rx_filters ( struct nii_nic *nii ) { - uint32_t implementation = nii->undi->Implementation; - unsigned int flags; - unsigned int op; - int stat; - int rc; - - /* Construct receive filter set */ - flags = ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE | - PXE_OPFLAGS_RECEIVE_FILTER_UNICAST ); - if ( implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED ) - flags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; - if ( implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED ) - flags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS; - if ( implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED ) - flags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; - - /* Issue command */ - op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS, flags ); - if ( ( stat = nii_issue ( nii, op ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not set receive filters %#04x: %s\n", - nii->dev.name, flags, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Transmit packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int nii_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct nii_nic *nii = netdev->priv; - PXE_CPB_TRANSMIT cpb; - unsigned int op; - int stat; - int rc; - - /* Defer the packet if there is already a transmission in progress */ - if ( nii->txbuf ) { - netdev_tx_defer ( netdev, iobuf ); - return 0; - } - - /* Construct parameter block */ - memset ( &cpb, 0, sizeof ( cpb ) ); - cpb.FrameAddr = virt_to_bus ( iobuf->data ); - cpb.DataLen = iob_len ( iobuf ); - cpb.MediaheaderLen = netdev->ll_protocol->ll_header_len; - - /* Transmit packet */ - op = NII_OP ( PXE_OPCODE_TRANSMIT, - ( PXE_OPFLAGS_TRANSMIT_WHOLE | - PXE_OPFLAGS_TRANSMIT_DONT_BLOCK ) ); - if ( ( stat = nii_issue_cpb ( nii, op, &cpb, sizeof ( cpb ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not transmit: %s\n", - nii->dev.name, strerror ( rc ) ); - return rc; - } - nii->txbuf = iobuf; - - return 0; -} - -/** - * Poll for completed packets - * - * @v netdev Network device - * @v stat Status flags - */ -static void nii_poll_tx ( struct net_device *netdev, unsigned int stat ) { - struct nii_nic *nii = netdev->priv; - struct io_buffer *iobuf; - - /* Do nothing unless we have a completion */ - if ( stat & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN ) - return; - - /* Sanity check */ - assert ( nii->txbuf != NULL ); - - /* Complete transmission */ - iobuf = nii->txbuf; - nii->txbuf = NULL; - netdev_tx_complete ( netdev, iobuf ); -} - -/** - * Poll for received packets - * - * @v netdev Network device - */ -static void nii_poll_rx ( struct net_device *netdev ) { - struct nii_nic *nii = netdev->priv; - PXE_CPB_RECEIVE cpb; - PXE_DB_RECEIVE db; - unsigned int quota; - int stat; - int rc; - - /* Retrieve up to NII_RX_QUOTA packets */ - for ( quota = NII_RX_QUOTA ; quota ; quota-- ) { - - /* Allocate buffer, if required */ - if ( ! nii->rxbuf ) { - nii->rxbuf = alloc_iob ( nii->mtu ); - if ( ! nii->rxbuf ) { - /* Leave for next poll */ - break; - } - } - - /* Construct parameter block */ - memset ( &cpb, 0, sizeof ( cpb ) ); - cpb.BufferAddr = virt_to_bus ( nii->rxbuf->data ); - cpb.BufferLen = iob_tailroom ( nii->rxbuf ); - - /* Issue command */ - if ( ( stat = nii_issue_cpb_db ( nii, PXE_OPCODE_RECEIVE, - &cpb, sizeof ( cpb ), - &db, sizeof ( db ) ) ) < 0 ) { - - /* PXE_STATCODE_NO_DATA is just the usual "no packet" - * status indicator; ignore it. - */ - if ( stat == -PXE_STATCODE_NO_DATA ) - break; - - /* Anything else is an error */ - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not receive: %s\n", - nii->dev.name, strerror ( rc ) ); - netdev_rx_err ( netdev, NULL, rc ); - break; - } - - /* Hand off to network stack */ - iob_put ( nii->rxbuf, db.FrameLen ); - netdev_rx ( netdev, nii->rxbuf ); - nii->rxbuf = NULL; - } -} - -/** - * Check for link state changes - * - * @v netdev Network device - * @v stat Status flags - */ -static void nii_poll_link ( struct net_device *netdev, unsigned int stat ) { - int no_media = ( stat & PXE_STATFLAGS_GET_STATUS_NO_MEDIA ); - - if ( no_media && netdev_link_ok ( netdev ) ) { - netdev_link_down ( netdev ); - } else if ( ( ! no_media ) && ( ! netdev_link_ok ( netdev ) ) ) { - netdev_link_up ( netdev ); - } -} - -/** - * Poll for completed packets - * - * @v netdev Network device - */ -static void nii_poll ( struct net_device *netdev ) { - struct nii_nic *nii = netdev->priv; - PXE_DB_GET_STATUS db; - unsigned int op; - int stat; - int rc; - - /* Construct data block */ - memset ( &db, 0, sizeof ( db ) ); - - /* Get status */ - op = NII_OP ( PXE_OPCODE_GET_STATUS, - ( PXE_OPFLAGS_GET_INTERRUPT_STATUS | - ( nii->txbuf ? PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS : 0)| - ( nii->media ? PXE_OPFLAGS_GET_MEDIA_STATUS : 0 ) ) ); - if ( ( stat = nii_issue_db ( nii, op, &db, sizeof ( db ) ) ) < 0 ) { - rc = -EIO_STAT ( stat ); - DBGC ( nii, "NII %s could not get status: %s\n", - nii->dev.name, strerror ( rc ) ); - return; - } - - /* Process any TX completions */ - if ( nii->txbuf ) - nii_poll_tx ( netdev, stat ); - - /* Process any RX completions */ - nii_poll_rx ( netdev ); - - /* Check for link state changes */ - if ( nii->media ) - nii_poll_link ( netdev, stat ); -} - -/** - * Open network device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int nii_open ( struct net_device *netdev ) { - struct nii_nic *nii = netdev->priv; - int rc; - - /* Initialise NIC - * - * Some Emulex NII drivers have a bug which prevents packets - * from being sent or received unless we specifically ask it - * to detect cable presence during initialisation. Work - * around these buggy drivers by requesting cable detection at - * this point, even though we don't care about link state here - * (and would prefer to have the NIC initialise even if no - * cable is present, to match the behaviour of all other iPXE - * drivers). - */ - if ( ( rc = nii_initialise_and_detect ( nii ) ) != 0 ) - goto err_initialise; - - /* Attempt to set station address */ - if ( ( rc = nii_set_station_address ( nii, netdev ) ) != 0 ) { - DBGC ( nii, "NII %s could not set station address: %s\n", - nii->dev.name, strerror ( rc ) ); - /* Treat as non-fatal */ - } - - /* Set receive filters */ - if ( ( rc = nii_set_rx_filters ( nii ) ) != 0 ) - goto err_set_rx_filters; - - return 0; - - err_set_rx_filters: - nii_shutdown ( nii ); - err_initialise: - return rc; -} - -/** - * Close network device - * - * @v netdev Network device - */ -static void nii_close ( struct net_device *netdev ) { - struct nii_nic *nii = netdev->priv; - - /* Shut down NIC */ - nii_shutdown ( nii ); - - /* Discard transmit buffer, if applicable */ - if ( nii->txbuf ) { - netdev_tx_complete_err ( netdev, nii->txbuf, -ECANCELED ); - nii->txbuf = NULL; - } - - /* Discard receive buffer, if applicable */ - if ( nii->rxbuf ) { - free_iob ( nii->rxbuf ); - nii->rxbuf = NULL; - } -} - -/** NII network device operations */ -static struct net_device_operations nii_operations = { - .open = nii_open, - .close = nii_close, - .transmit = nii_transmit, - .poll = nii_poll, -}; - -/** - * Attach driver to device - * - * @v efidev EFI device - * @ret rc Return status code - */ -int nii_start ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE device = efidev->device; - struct net_device *netdev; - struct nii_nic *nii; - void *interface; - EFI_STATUS efirc; - int rc; - - /* Allocate and initialise structure */ - netdev = alloc_netdev ( sizeof ( *nii ) ); - if ( ! netdev ) { - rc = -ENOMEM; - goto err_alloc; - } - netdev_init ( netdev, &nii_operations ); - nii = netdev->priv; - nii->efidev = efidev; - netdev->ll_broadcast = nii->broadcast; - efidev_set_drvdata ( efidev, netdev ); - - /* Populate underlying device information */ - efi_device_info ( device, "NII", &nii->dev ); - nii->dev.driver_name = "NII"; - nii->dev.parent = &efidev->dev; - list_add ( &nii->dev.siblings, &efidev->dev.children ); - INIT_LIST_HEAD ( &nii->dev.children ); - netdev->dev = &nii->dev; - - /* Open NII protocol */ - if ( ( efirc = bs->OpenProtocol ( device, &efi_nii31_protocol_guid, - &interface, efi_image_handle, device, - ( EFI_OPEN_PROTOCOL_BY_DRIVER | - EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){ - rc = -EEFI ( efirc ); - DBGC ( nii, "NII %s cannot open NII protocol: %s\n", - nii->dev.name, strerror ( rc ) ); - DBGC_EFI_OPENERS ( device, device, &efi_nii31_protocol_guid ); - goto err_open_protocol; - } - nii->nii = interface; - - /* Locate UNDI and entry point */ - nii->undi = ( ( void * ) ( intptr_t ) nii->nii->Id ); - if ( ! nii->undi ) { - DBGC ( nii, "NII %s has no UNDI\n", nii->dev.name ); - rc = -ENODEV; - goto err_no_undi; - } - if ( nii->undi->Implementation & PXE_ROMID_IMP_HW_UNDI ) { - DBGC ( nii, "NII %s is a mythical hardware UNDI\n", - nii->dev.name ); - rc = -ENOTSUP; - goto err_hw_undi; - } - if ( nii->undi->Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR ) { - nii->issue = ( ( void * ) ( intptr_t ) nii->undi->EntryPoint ); - } else { - nii->issue = ( ( ( void * ) nii->undi ) + - nii->undi->EntryPoint ); - } - DBGC ( nii, "NII %s using UNDI v%x.%x at %p entry %p impl %#08x\n", - nii->dev.name, nii->nii->MajorVer, nii->nii->MinorVer, - nii->undi, nii->issue, nii->undi->Implementation ); - - /* Open PCI I/O protocols and locate BARs */ - if ( ( rc = nii_pci_open ( nii ) ) != 0 ) - goto err_pci_open; - - /* Start UNDI */ - if ( ( rc = nii_start_undi ( nii ) ) != 0 ) - goto err_start_undi; - - /* Get initialisation information */ - if ( ( rc = nii_get_init_info ( nii, netdev ) ) != 0 ) - goto err_get_init_info; - - /* Get MAC addresses */ - if ( ( rc = nii_get_station_address ( nii, netdev ) ) != 0 ) - goto err_get_station_address; - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register_netdev; - DBGC ( nii, "NII %s registered as %s for %p %s\n", nii->dev.name, - netdev->name, device, efi_handle_name ( device ) ); - - /* Set initial link state (if media detection is not supported) */ - if ( ! nii->media ) - netdev_link_up ( netdev ); - - return 0; - - unregister_netdev ( netdev ); - err_register_netdev: - err_get_station_address: - err_get_init_info: - nii_stop_undi ( nii ); - err_start_undi: - nii_pci_close ( nii ); - err_pci_open: - err_hw_undi: - err_no_undi: - bs->CloseProtocol ( device, &efi_nii31_protocol_guid, - efi_image_handle, device ); - err_open_protocol: - list_del ( &nii->dev.siblings ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); - err_alloc: - return rc; -} - -/** - * Detach driver from device - * - * @v efidev EFI device - */ -void nii_stop ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct net_device *netdev = efidev_get_drvdata ( efidev ); - struct nii_nic *nii = netdev->priv; - EFI_HANDLE device = efidev->device; - - /* Unregister network device */ - unregister_netdev ( netdev ); - - /* Stop UNDI */ - nii_stop_undi ( nii ); - - /* Close PCI I/O protocols */ - nii_pci_close ( nii ); - - /* Close NII protocol */ - bs->CloseProtocol ( device, &efi_nii31_protocol_guid, - efi_image_handle, device ); - - /* Free network device */ - list_del ( &nii->dev.siblings ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} -- cgit 1.2.3-korg