iPXE
Data Structures | Defines | Functions | Variables
nii.c File Reference

NII driver. More...

#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/umalloc.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_pci.h>
#include <ipxe/efi/efi_utils.h>
#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
#include <ipxe/efi/IndustryStandard/Acpi10.h>
#include "nii.h"

Go to the source code of this file.

Data Structures

struct  nii_mapping
 An NII memory mapping. More...
struct  nii_nic
 An NII NIC. More...

Defines

#define EIO_INVALID_CDB   __einfo_error ( EINFO_EIO_INVALID_CDB )
#define EINFO_EIO_INVALID_CDB
#define EIO_INVALID_CPB   __einfo_error ( EINFO_EIO_INVALID_CPB )
#define EINFO_EIO_INVALID_CPB
#define EIO_BUSY   __einfo_error ( EINFO_EIO_BUSY )
#define EINFO_EIO_BUSY
#define EIO_QUEUE_FULL   __einfo_error ( EINFO_EIO_QUEUE_FULL )
#define EINFO_EIO_QUEUE_FULL
#define EIO_ALREADY_STARTED   __einfo_error ( EINFO_EIO_ALREADY_STARTED )
#define EINFO_EIO_ALREADY_STARTED
#define EIO_NOT_STARTED   __einfo_error ( EINFO_EIO_NOT_STARTED )
#define EINFO_EIO_NOT_STARTED
#define EIO_NOT_SHUTDOWN   __einfo_error ( EINFO_EIO_NOT_SHUTDOWN )
#define EINFO_EIO_NOT_SHUTDOWN
#define EIO_ALREADY_INITIALIZED   __einfo_error ( EINFO_EIO_ALREADY_INITIALIZED )
#define EINFO_EIO_ALREADY_INITIALIZED
#define EIO_NOT_INITIALIZED   __einfo_error ( EINFO_EIO_NOT_INITIALIZED )
#define EINFO_EIO_NOT_INITIALIZED
#define EIO_DEVICE_FAILURE   __einfo_error ( EINFO_EIO_DEVICE_FAILURE )
#define EINFO_EIO_DEVICE_FAILURE
#define EIO_NVDATA_FAILURE   __einfo_error ( EINFO_EIO_NVDATA_FAILURE )
#define EINFO_EIO_NVDATA_FAILURE
#define EIO_UNSUPPORTED   __einfo_error ( EINFO_EIO_UNSUPPORTED )
#define EINFO_EIO_UNSUPPORTED
#define EIO_BUFFER_FULL   __einfo_error ( EINFO_EIO_BUFFER_FULL )
#define EINFO_EIO_BUFFER_FULL
#define EIO_INVALID_PARAMETER   __einfo_error ( EINFO_EIO_INVALID_PARAMETER )
#define EINFO_EIO_INVALID_PARAMETER
#define EIO_INVALID_UNDI   __einfo_error ( EINFO_EIO_INVALID_UNDI )
#define EINFO_EIO_INVALID_UNDI
#define EIO_IPV4_NOT_SUPPORTED   __einfo_error ( EINFO_EIO_IPV4_NOT_SUPPORTED )
#define EINFO_EIO_IPV4_NOT_SUPPORTED
#define EIO_IPV6_NOT_SUPPORTED   __einfo_error ( EINFO_EIO_IPV6_NOT_SUPPORTED )
#define EINFO_EIO_IPV6_NOT_SUPPORTED
#define EIO_NOT_ENOUGH_MEMORY   __einfo_error ( EINFO_EIO_NOT_ENOUGH_MEMORY )
#define EINFO_EIO_NOT_ENOUGH_MEMORY
#define EIO_NO_DATA   __einfo_error ( EINFO_EIO_NO_DATA )
#define EINFO_EIO_NO_DATA
#define EIO_STAT(stat)
#define PCI_MAX_BAR   6
 Maximum PCI BAR.
#define NII_RX_QUOTA   4
 Maximum number of received packets per poll.
#define NII_OP(opcode, opflags)   ( (opcode) | ( (opflags) << 16 ) )
 Construct operation from opcode and flags.
#define NII_OPCODE(op)   ( (op) & 0xffff )
 Extract opcode from operation.
#define NII_OPFLAGS(op)   ( (op) >> 16 )
 Extract flags from operation.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int nii_pci_open (struct nii_nic *nii)
 Open PCI I/O protocol and identify BARs.
static void nii_pci_close (struct nii_nic *nii)
 Close PCI I/O protocol.
static EFIAPI VOID nii_io (UINT64 unique_id, UINT8 op, UINT8 len, UINT64 addr, UINT64 data)
 I/O callback.
static EFIAPI VOID nii_map (UINT64 unique_id, UINT64 addr, UINT32 len, UINT32 dir, UINT64 mapped)
 Map callback.
static EFIAPI VOID nii_unmap (UINT64 unique_id, UINT64 addr, UINT32 len, UINT32 dir __unused, UINT64 mapped)
 Unmap callback.
static EFIAPI VOID nii_sync (UINT64 unique_id __unused, UINT64 addr, UINT32 len, UINT32 dir, UINT64 mapped)
 Sync callback.
static EFIAPI VOID nii_delay (UINT64 unique_id __unused, UINTN microseconds)
 Delay callback.
static EFIAPI VOID nii_block (UINT64 unique_id, UINT32 acquire)
 Block callback.
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)
 Issue command with parameter block and data block.
static int nii_issue_cpb (struct nii_nic *nii, unsigned int op, void *cpb, size_t cpb_len)
 Issue command with parameter block.
static int nii_issue_db (struct nii_nic *nii, unsigned int op, void *db, size_t db_len)
 Issue command with data block.
static int nii_issue (struct nii_nic *nii, unsigned int op)
 Issue command.
static int nii_start_undi (struct nii_nic *nii)
 Start UNDI.
static void nii_stop_undi (struct nii_nic *nii)
 Stop UNDI.
static int nii_get_init_info (struct nii_nic *nii, struct net_device *netdev)
 Get initialisation information.
static int nii_initialise_flags (struct nii_nic *nii, unsigned int flags)
 Initialise UNDI.
static int nii_initialise (struct nii_nic *nii)
 Initialise UNDI.
static void nii_shutdown (struct nii_nic *nii)
 Shut down UNDI.
static int nii_get_station_address (struct nii_nic *nii, struct net_device *netdev)
 Get station addresses.
static int nii_set_station_address (struct nii_nic *nii, struct net_device *netdev)
 Set station address.
static int nii_set_rx_filters (struct nii_nic *nii)
 Set receive filters.
static int nii_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void nii_poll_tx (struct net_device *netdev, unsigned int stat)
 Poll for completed packets.
static void nii_poll_rx (struct net_device *netdev)
 Poll for received packets.
static void nii_poll_link (struct net_device *netdev, unsigned int stat)
 Check for link state changes.
static void nii_poll (struct net_device *netdev)
 Poll for completed packets.
static int nii_open (struct net_device *netdev)
 Open network device.
static void nii_close (struct net_device *netdev)
 Close network device.
int nii_start (struct efi_device *efidev)
 Attach driver to device.
void nii_stop (struct efi_device *efidev)
 Detach driver from device.

Variables

static struct net_device_operations nii_operations
 NII network device operations.

Detailed Description

NII driver.

Definition in file nii.c.


Define Documentation

Definition at line 49 of file nii.c.

Value:

Definition at line 50 of file nii.c.

Definition at line 53 of file nii.c.

Value:

Definition at line 54 of file nii.c.

Definition at line 57 of file nii.c.

#define EINFO_EIO_BUSY
Value:

Definition at line 58 of file nii.c.

Definition at line 61 of file nii.c.

Value:

Definition at line 62 of file nii.c.

Definition at line 65 of file nii.c.

Value:

Definition at line 66 of file nii.c.

Definition at line 69 of file nii.c.

Value:

Definition at line 70 of file nii.c.

Definition at line 73 of file nii.c.

Value:

Definition at line 74 of file nii.c.

Definition at line 77 of file nii.c.

Value:

Definition at line 78 of file nii.c.

Definition at line 81 of file nii.c.

Value:

Definition at line 82 of file nii.c.

Definition at line 85 of file nii.c.

Value:

Definition at line 86 of file nii.c.

Definition at line 89 of file nii.c.

Value:
__einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NVDATA_FAILURE,             \
                          "Non-volatile data failure" )

Definition at line 90 of file nii.c.

Definition at line 93 of file nii.c.

Value:

Definition at line 94 of file nii.c.

Definition at line 97 of file nii.c.

Value:

Definition at line 98 of file nii.c.

Definition at line 101 of file nii.c.

Value:

Definition at line 102 of file nii.c.

Definition at line 105 of file nii.c.

Value:

Definition at line 106 of file nii.c.

Definition at line 109 of file nii.c.

Value:

Definition at line 110 of file nii.c.

Definition at line 113 of file nii.c.

Value:

Definition at line 114 of file nii.c.

Definition at line 117 of file nii.c.

Value:

Definition at line 118 of file nii.c.

Definition at line 121 of file nii.c.

Value:

Definition at line 122 of file nii.c.

#define EIO_STAT (   stat)
#define PCI_MAX_BAR   6

Maximum PCI BAR.

This is defined in <ipxe/efi/IndustryStandard/Pci22.h>, but we can't #include that since it collides with <ipxe/pci.h>.

Definition at line 139 of file nii.c.

Referenced by nii_pci_open().

#define NII_RX_QUOTA   4

Maximum number of received packets per poll.

Definition at line 199 of file nii.c.

Referenced by nii_poll_rx().

#define NII_OP (   opcode,
  opflags 
)    ( (opcode) | ( (opflags) << 16 ) )

Construct operation from opcode and flags.

Parameters:
opcodeOpcode
opflagsFlags
Return values:
opOperation

Definition at line 533 of file nii.c.

Referenced by nii_get_station_address(), nii_initialise_flags(), nii_poll(), nii_set_rx_filters(), nii_set_station_address(), and nii_transmit().

#define NII_OPCODE (   op)    ( (op) & 0xffff )

Extract opcode from operation.

Parameters:
opOperation
Return values:
opcodeOpcode

Definition at line 541 of file nii.c.

Referenced by nii_issue_cpb_db().

#define NII_OPFLAGS (   op)    ( (op) >> 16 )

Extract flags from operation.

Parameters:
opOperation
Return values:
opflagsFlags

Definition at line 549 of file nii.c.

Referenced by nii_issue_cpb_db().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int nii_pci_open ( struct nii_nic nii) [static]

Open PCI I/O protocol and identify BARs.

Parameters:
niiNII NIC
Return values:
rcReturn status code

Definition at line 207 of file nii.c.

References acpi, ACPI_ADDRESS_SPACE_TYPE_IO, ACPI_ADDRESS_SPACE_TYPE_MEM, EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, DBGC, nii_nic::dev, efi_device::device, EEFI, efi_image_handle, efi_locate_device(), EFI_OPEN_PROTOCOL_GET_PROTOCOL, efi_pci_io_protocol_guid, efi_systab, EFI_UNSUPPORTED, nii_nic::efidev, EFI_BOOT_SERVICES::FreePool, _EFI_PCI_IO_PROTOCOL::GetBarAttributes, nii_nic::io_bar, nii_nic::mem_bar, device::name, NULL, EFI_BOOT_SERVICES::OpenProtocol, nii_nic::pci_device, nii_nic::pci_io, PCI_MAX_BAR, rc, and strerror().

Referenced by nii_start().

                                                {
        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;
        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 = ( PCI_MAX_BAR - 1 ) ; bar >= 0 ; 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;
}
static void nii_pci_close ( struct nii_nic nii) [static]

Close PCI I/O protocol.

Parameters:
niiNII NIC
Return values:
rcReturn status code

Definition at line 295 of file nii.c.

References nii_mapping::addr, EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, DBGC, nii_nic::dev, efi_device::device, efi_image_handle, efi_pci_io_protocol_guid, efi_systab, nii_nic::efidev, free, nii_mapping::list, list_del, list_for_each_entry_safe, nii_mapping::mapping, nii_nic::mappings, device::name, nii_nic::pci_device, nii_nic::pci_io, and _EFI_PCI_IO_PROTOCOL::Unmap.

Referenced by nii_start(), and nii_stop().

                                                  {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct nii_mapping *map;
        struct nii_mapping *tmp;

        /* Remove any stale mappings */
        list_for_each_entry_safe ( map, tmp, &nii->mappings, list ) {
                DBGC ( nii, "NII %s removing stale mapping %#llx\n",
                       nii->dev.name, ( ( unsigned long long ) map->addr ) );
                nii->pci_io->Unmap ( nii->pci_io, map->mapping );
                list_del ( &map->list );
                free ( map );
        }

        /* Close protocols */
        bs->CloseProtocol ( nii->pci_device, &efi_pci_io_protocol_guid,
                            efi_image_handle, nii->efidev->device );
}
static EFIAPI VOID nii_io ( UINT64  unique_id,
UINT8  op,
UINT8  len,
UINT64  addr,
UINT64  data 
) [static]

I/O callback.

Parameters:
unique_idNII NIC
opOperations
lenLength of data
addrAddress
dataData buffer

Definition at line 323 of file nii.c.

References DBGC, nii_nic::dev, EEFI, fls, _EFI_PCI_IO_PROTOCOL::Io, nii_nic::io_bar, _EFI_PCI_IO_PROTOCOL::Mem, nii_nic::mem_bar, device::name, nii_nic::nii, nii_nic::pci_io, PXE_IO_WRITE, PXE_MEM_READ, PXE_MEM_WRITE, rc, EFI_PCI_IO_PROTOCOL_ACCESS::Read, strerror(), and EFI_PCI_IO_PROTOCOL_ACCESS::Write.

Referenced by nii_start_undi().

                                          {
        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;
        }
}
static EFIAPI VOID nii_map ( UINT64  unique_id,
UINT64  addr,
UINT32  len,
UINT32  dir,
UINT64  mapped 
) [static]

Map callback.

Parameters:
unique_idNII NIC
addrAddress of memory to be mapped
lenLength of memory to be mapped
dirDirection of data flow
mappedDevice mapped address to fill in

Definition at line 369 of file nii.c.

References nii_mapping::addr, addr, count, DBGC, DBGC2, nii_nic::dev, EEFI, EfiPciIoOperationBusMasterCommonBuffer, EfiPciIoOperationBusMasterRead, EfiPciIoOperationBusMasterWrite, free, FROM_DEVICE, len, nii_mapping::list, list_add, list_del, _EFI_PCI_IO_PROTOCOL::Map, nii_mapping::mapping, nii_nic::mappings, device::name, nii_nic::nii, op, nii_nic::pci_io, phys, rc, strerror(), TO_AND_FROM_DEVICE, TO_DEVICE, and zalloc().

Referenced by nii_start_undi().

                                                         {
        struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
        EFI_PHYSICAL_ADDRESS *phys = ( ( void * ) ( intptr_t ) mapped );
        EFI_PCI_IO_PROTOCOL_OPERATION op;
        struct nii_mapping *map;
        UINTN count = len;
        EFI_STATUS efirc;
        int rc;

        /* Return a zero mapped address on failure */
        *phys = 0;

        /* Determine PCI mapping operation */
        switch ( dir ) {
        case TO_AND_FROM_DEVICE:
                op = EfiPciIoOperationBusMasterCommonBuffer;
                break;
        case FROM_DEVICE:
                op = EfiPciIoOperationBusMasterWrite;
                break;
        case TO_DEVICE:
                op = EfiPciIoOperationBusMasterRead;
                break;
        default:
                DBGC ( nii, "NII %s unsupported mapping direction %d\n",
                       nii->dev.name, dir );
                goto err_dir;
        }

        /* Allocate a mapping record */
        map = zalloc ( sizeof ( *map ) );
        if ( ! map )
                goto err_alloc;
        map->addr = addr;

        /* Create map */
        if ( ( efirc = nii->pci_io->Map ( nii->pci_io, op,
                                          ( ( void * ) ( intptr_t ) addr ),
                                          &count, phys, &map->mapping ) ) != 0){
                rc = -EEFI ( efirc );
                DBGC ( nii, "NII %s map operation failed: %s\n",
                       nii->dev.name, strerror ( rc ) );
                goto err_map;
        }

        /* Add to list of mappings */
        list_add ( &map->list, &nii->mappings );
        DBGC2 ( nii, "NII %s mapped %#llx+%#x->%#llx\n",
                nii->dev.name, ( ( unsigned long long ) addr ),
                len, ( ( unsigned long long ) *phys ) );
        return;

        list_del ( &map->list );
 err_map:
        free ( map );
 err_alloc:
 err_dir:
        return;
}
static EFIAPI VOID nii_unmap ( UINT64  unique_id,
UINT64  addr,
UINT32  len,
UINT32 dir  __unused,
UINT64  mapped 
) [static]

Unmap callback.

Parameters:
unique_idNII NIC
addrAddress of mapped memory
lenLength of mapped memory
dirDirection of data flow
mappedDevice mapped address

Definition at line 439 of file nii.c.

References nii_mapping::addr, DBGC, DBGC2, nii_nic::dev, free, nii_mapping::list, list_del, list_for_each_entry, nii_mapping::mapping, nii_nic::mappings, device::name, nii_nic::nii, nii_nic::pci_io, and _EFI_PCI_IO_PROTOCOL::Unmap.

Referenced by nii_start_undi().

                                                                    {
        struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
        struct nii_mapping *map;

        /* Locate mapping record */
        list_for_each_entry ( map, &nii->mappings, list ) {
                if ( map->addr == addr ) {
                        nii->pci_io->Unmap ( nii->pci_io, map->mapping );
                        list_del ( &map->list );
                        free ( map );
                        DBGC2 ( nii, "NII %s unmapped %#llx+%#x->%#llx\n",
                                nii->dev.name, ( ( unsigned long long ) addr ),
                                len, ( ( unsigned long long ) mapped ) );
                        return;
                }
        }

        DBGC ( nii, "NII %s non-existent mapping %#llx+%#x->%#llx\n",
               nii->dev.name, ( ( unsigned long long ) addr ),
               len, ( ( unsigned long long ) mapped ) );
}
static EFIAPI VOID nii_sync ( UINT64 unique_id  __unused,
UINT64  addr,
UINT32  len,
UINT32  dir,
UINT64  mapped 
) [static]

Sync callback.

Parameters:
unique_idNII NIC
addrAddress of mapped memory
lenLength of mapped memory
dirDirection of data flow
mappedDevice mapped address

Definition at line 471 of file nii.c.

References addr, FROM_DEVICE, memcpy(), and src.

Referenced by nii_start_undi().

                                                                      {
        const void *src;
        void *dst;

        /* Do nothing if this is an identity mapping */
        if ( addr == mapped )
                return;

        /* Determine direction */
        if ( dir == FROM_DEVICE ) {
                src = ( ( void * ) ( intptr_t ) mapped );
                dst = ( ( void * ) ( intptr_t ) addr );
        } else {
                src = ( ( void * ) ( intptr_t ) addr );
                dst = ( ( void * ) ( intptr_t ) mapped );
        }

        /* Copy data */
        memcpy ( dst, src, len );
}
static EFIAPI VOID nii_delay ( UINT64 unique_id  __unused,
UINTN  microseconds 
) [static]

Delay callback.

Parameters:
unique_idNII NIC
microsecondsDelay in microseconds

Definition at line 499 of file nii.c.

References udelay().

Referenced by nii_start_undi().

                                                                               {

        udelay ( microseconds );
}
static EFIAPI VOID nii_block ( UINT64  unique_id,
UINT32  acquire 
) [static]

Block callback.

Parameters:
unique_idNII NIC
acquireAcquire lock

Definition at line 510 of file nii.c.

References EFI_SYSTEM_TABLE::BootServices, efi_systab, nii_nic::nii, EFI_BOOT_SERVICES::RaiseTPL, EFI_BOOT_SERVICES::RestoreTPL, nii_nic::saved_tpl, and TPL_NOTIFY.

Referenced by nii_start_undi().

                                                                  {
        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 );
        }
}
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 
) [static]

Issue command with parameter block and data block.

Parameters:
niiNII NIC
opOperation
cpbCommand parameter block, or NULL
cpb_lenCommand parameter block length
dbData block, or NULL
db_lenData block length
Return values:
statStatus flags, or negative status code

Definition at line 562 of file nii.c.

References EFI_SYSTEM_TABLE::BootServices, s_pxe_cdb::CPBaddr, s_pxe_cdb::CPBsize, s_pxe_cdb::DBaddr, DBGC2, DBGC2_HD, s_pxe_cdb::DBsize, nii_nic::dev, efi_systab, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::IfNum, s_pxe_cdb::IFnum, nii_nic::issue, memset(), device::name, nii_nic::nii, NII_OPCODE, NII_OPFLAGS, s_pxe_cdb::OpCode, s_pxe_cdb::OpFlags, PXE_STATCODE_SUCCESS, PXE_STATFLAGS_STATUS_MASK, EFI_BOOT_SERVICES::RaiseTPL, EFI_BOOT_SERVICES::RestoreTPL, and TPL_CALLBACK.

Referenced by nii_initialise_flags(), nii_issue(), nii_issue_cpb(), nii_issue_db(), and nii_poll_rx().

                                                                        {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        PXE_CDB cdb;
        UINTN tpl;

        /* 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;

        /* Raise task priority level */
        tpl = bs->RaiseTPL ( TPL_CALLBACK );

        /* 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 );

        /* Restore task priority level */
        bs->RestoreTPL ( tpl );

        /* Check completion status */
        if ( cdb.StatCode != PXE_STATCODE_SUCCESS )
                return -cdb.StatCode;

        /* Return command-specific status flags */
        return ( cdb.StatFlags & ~PXE_STATFLAGS_STATUS_MASK );
}
static int nii_issue_cpb ( struct nii_nic nii,
unsigned int  op,
void *  cpb,
size_t  cpb_len 
) [static]

Issue command with parameter block.

Parameters:
niiNII NIC
opOperation
cpbCommand parameter block, or NULL
cpb_lenCommand parameter block length
Return values:
statStatus flags, or negative status code

Definition at line 611 of file nii.c.

References nii_issue_cpb_db(), and NULL.

Referenced by nii_set_station_address(), nii_start_undi(), and nii_transmit().

                                            {

        return nii_issue_cpb_db ( nii, op, cpb, cpb_len, NULL, 0 );
}
static int nii_issue_db ( struct nii_nic nii,
unsigned int  op,
void *  db,
size_t  db_len 
) [static]

Issue command with data block.

Parameters:
niiNII NIC
opOperation
dbData block, or NULL
db_lenData block length
Return values:
statStatus flags, or negative status code

Definition at line 626 of file nii.c.

References nii_issue_cpb_db(), and NULL.

Referenced by nii_get_init_info(), nii_get_station_address(), and nii_poll().

                                          {

        return nii_issue_cpb_db ( nii, op, NULL, 0, db, db_len );
}
static int nii_issue ( struct nii_nic nii,
unsigned int  op 
) [static]

Issue command.

Parameters:
niiNII NIC
opOperation
Return values:
statStatus flags, or negative status code

Definition at line 640 of file nii.c.

References nii_issue_cpb_db(), and NULL.

Referenced by nii_set_rx_filters(), nii_shutdown(), and nii_stop_undi().

                                                              {

        return nii_issue_cpb_db ( nii, op, NULL, 0, NULL, 0 );
}
static int nii_start_undi ( struct nii_nic nii) [static]

Start UNDI.

Parameters:
niiNII NIC
Return values:
rcReturn status code

Definition at line 651 of file nii.c.

References s_pxe_cpb_start_31::Block, DBGC, s_pxe_cpb_start_31::Delay, nii_nic::dev, EIO_STAT, s_pxe_cpb_start_31::Map_Mem, s_pxe_cpb_start_31::Mem_IO, memset(), device::name, nii_block(), nii_delay(), nii_io(), nii_issue_cpb(), nii_map(), nii_sync(), nii_unmap(), PXE_OPCODE_START, rc, strerror(), s_pxe_cpb_start_31::Sync_Mem, s_pxe_cpb_start_31::Unique_ID, and s_pxe_cpb_start_31::UnMap_Mem.

Referenced by nii_start().

                                                  {
        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.Map_Mem = ( ( intptr_t ) nii_map );
        cpb.UnMap_Mem = ( ( intptr_t ) nii_unmap );
        cpb.Sync_Mem = ( ( intptr_t ) nii_sync );
        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;
}
static void nii_stop_undi ( struct nii_nic nii) [static]

Stop UNDI.

Parameters:
niiNII NIC

Definition at line 683 of file nii.c.

References DBGC, nii_nic::dev, EIO_STAT, device::name, nii_issue(), PXE_OPCODE_STOP, rc, and strerror().

Referenced by nii_start(), and nii_stop().

                                                  {
        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;
        }
}
static int nii_get_init_info ( struct nii_nic nii,
struct net_device netdev 
) [static]

Get initialisation information.

Parameters:
niiNII NIC
netdevNetwork device to fill in
Return values:
rcReturn status code

Definition at line 704 of file nii.c.

References assert, nii_nic::buffer_len, db, DBGC, nii_nic::dev, EIO_STAT, ENOTSUP, s_pxe_db_get_init_info::FrameDataLen, ll_protocol::hw_addr_len, s_pxe_db_get_init_info::HWaddrLen, s_pxe_db_get_init_info::IFtype, ll_protocol::ll_addr_len, ll_protocol::ll_header_len, net_device::ll_protocol, net_device::max_pkt_len, nii_nic::media, s_pxe_db_get_init_info::MediaHeaderLen, s_pxe_db_get_init_info::MemoryRequired, nii_nic::mtu, device::name, nii_issue_db(), PXE_IFTYPE_ETHERNET, PXE_OPCODE_GET_INIT_INFO, PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED, rc, and strerror().

Referenced by nii_start().

                                                           {
        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 = &ethernet_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;
}
static int nii_initialise_flags ( struct nii_nic nii,
unsigned int  flags 
) [static]

Initialise UNDI.

Parameters:
niiNII NIC
flagsFlags
Return values:
rcReturn status code

Definition at line 751 of file nii.c.

References nii_nic::buffer, nii_nic::buffer_len, db, DBGC, nii_nic::dev, EIO_STAT, ENOMEM, s_pxe_cpb_initialize::MemoryAddr, s_pxe_cpb_initialize::MemoryLength, memset(), device::name, nii_issue_cpb_db(), NII_OP, op, PXE_OPCODE_INITIALIZE, rc, strerror(), ufree(), and umalloc().

Referenced by nii_initialise(), and nii_open().

                                                                            {
        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;
}
static int nii_initialise ( struct nii_nic nii) [static]

Initialise UNDI.

Parameters:
niiNII NIC
Return values:
rcReturn status code

Definition at line 797 of file nii.c.

References flags, nii_initialise_flags(), and PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE.

Referenced by nii_get_station_address().

                                                  {
        unsigned int flags;

        /* Initialise UNDI */
        flags = PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE;
        return nii_initialise_flags ( nii, flags );
}
static void nii_shutdown ( struct nii_nic nii) [static]

Shut down UNDI.

Parameters:
niiNII NIC

Definition at line 810 of file nii.c.

References nii_nic::buffer, DBGC, nii_nic::dev, EIO_STAT, device::name, nii_issue(), PXE_OPCODE_SHUTDOWN, rc, strerror(), and ufree().

Referenced by nii_close(), nii_get_station_address(), and nii_open().

                                                 {
        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 );
}
static int nii_get_station_address ( struct nii_nic nii,
struct net_device netdev 
) [static]

Get station addresses.

Parameters:
niiNII NIC
netdevNetwork device to fill in
Return values:
rcReturn status code

Definition at line 834 of file nii.c.

References nii_nic::broadcast, s_pxe_dpb_station_address::BroadcastAddr, db, DBGC, nii_nic::dev, EIO_STAT, net_device::hw_addr, ll_protocol::hw_addr_len, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, memcpy(), device::name, nii_initialise(), nii_issue_db(), NII_OP, nii_shutdown(), op, s_pxe_dpb_station_address::PermanentAddr, PXE_OPCODE_STATION_ADDRESS, PXE_OPFLAGS_STATION_ADDRESS_READ, rc, s_pxe_dpb_station_address::StationAddr, and strerror().

Referenced by nii_start().

                                                                 {
        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;
}
static int nii_set_station_address ( struct nii_nic nii,
struct net_device netdev 
) [static]

Set station address.

Parameters:
niiNII NIC
netdevNetwork device
Return values:
rcReturn status code

Definition at line 876 of file nii.c.

References DBGC, nii_nic::dev, EIO_STAT, ENOTSUP, implementation, s_pxe_sw_undi::Implementation, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, memcpy(), memset(), device::name, nii_issue_cpb(), NII_OP, op, PXE_OPCODE_STATION_ADDRESS, PXE_OPFLAGS_STATION_ADDRESS_WRITE, PXE_ROMID_IMP_STATION_ADDR_SETTABLE, rc, s_pxe_cpb_station_address::StationAddr, strerror(), and nii_nic::undi.

Referenced by nii_open().

                                                                 {
        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;
}
static int nii_set_rx_filters ( struct nii_nic nii) [static]

Set receive filters.

Parameters:
niiNII NIC
Return values:
rcReturn status code

Definition at line 912 of file nii.c.

References DBGC, nii_nic::dev, EIO_STAT, flags, implementation, s_pxe_sw_undi::Implementation, device::name, nii_issue(), NII_OP, op, PXE_OPCODE_RECEIVE_FILTERS, PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, PXE_OPFLAGS_RECEIVE_FILTER_ENABLE, PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED, PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED, PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED, rc, strerror(), and nii_nic::undi.

Referenced by nii_open().

                                                      {
        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;
}
static int nii_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet.

Parameters:
netdevNetwork device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 948 of file nii.c.

References io_buffer::data, s_pxe_cpb_transmit::DataLen, DBGC, nii_nic::dev, EIO_STAT, s_pxe_cpb_transmit::FrameAddr, iob_len(), ll_protocol::ll_header_len, net_device::ll_protocol, s_pxe_cpb_transmit::MediaheaderLen, memset(), device::name, netdev_tx_defer(), nii_nic::nii, nii_issue_cpb(), NII_OP, op, net_device::priv, PXE_OPCODE_TRANSMIT, PXE_OPFLAGS_TRANSMIT_DONT_BLOCK, PXE_OPFLAGS_TRANSMIT_WHOLE, rc, strerror(), nii_nic::txbuf, and virt_to_bus().

                                                    {
        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;
}
static void nii_poll_tx ( struct net_device netdev,
unsigned int  stat 
) [static]

Poll for completed packets.

Parameters:
netdevNetwork device
statStatus flags

Definition at line 989 of file nii.c.

References assert, netdev_tx_complete(), nii_nic::nii, NULL, net_device::priv, PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN, and nii_nic::txbuf.

Referenced by nii_poll().

                                                                         {
        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 );
}
static void nii_poll_rx ( struct net_device netdev) [static]

Poll for received packets.

Parameters:
netdevNetwork device

Definition at line 1011 of file nii.c.

References alloc_iob(), s_pxe_cpb_receive::BufferAddr, s_pxe_cpb_receive::BufferLen, io_buffer::data, db, DBGC, nii_nic::dev, EIO_STAT, s_pxe_db_receive::FrameLen, iob_put, iob_tailroom(), memset(), nii_nic::mtu, device::name, netdev_rx(), netdev_rx_err(), nii_nic::nii, nii_issue_cpb_db(), NII_RX_QUOTA, NULL, net_device::priv, PXE_OPCODE_RECEIVE, PXE_STATCODE_NO_DATA, rc, nii_nic::rxbuf, strerror(), and virt_to_bus().

Referenced by nii_poll().

                                                      {
        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;
        }
}
static void nii_poll_link ( struct net_device netdev,
unsigned int  stat 
) [static]

Check for link state changes.

Parameters:
netdevNetwork device
statStatus flags

Definition at line 1068 of file nii.c.

References netdev_link_down(), netdev_link_ok(), netdev_link_up(), and PXE_STATFLAGS_GET_STATUS_NO_MEDIA.

Referenced by nii_poll().

                                                                           {
        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 );
        }
}
static void nii_poll ( struct net_device netdev) [static]

Poll for completed packets.

Parameters:
netdevNetwork device

Definition at line 1083 of file nii.c.

References db, DBGC, nii_nic::dev, EIO_STAT, nii_nic::media, memset(), device::name, nii_nic::nii, nii_issue_db(), NII_OP, nii_poll_link(), nii_poll_rx(), nii_poll_tx(), op, net_device::priv, PXE_OPCODE_GET_STATUS, PXE_OPFLAGS_GET_INTERRUPT_STATUS, PXE_OPFLAGS_GET_MEDIA_STATUS, PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS, rc, strerror(), and nii_nic::txbuf.

                                                   {
        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 );
}
static int nii_open ( struct net_device netdev) [static]

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 1123 of file nii.c.

References DBGC, nii_nic::dev, flags, nii_nic::media, device::name, nii_nic::nii, nii_initialise_flags(), nii_set_rx_filters(), nii_set_station_address(), nii_shutdown(), net_device::priv, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE, rc, and strerror().

                                                  {
        struct nii_nic *nii = netdev->priv;
        unsigned int flags;
        int rc;

        /* Initialise NIC
         *
         * 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.
         *
         * 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.
         *
         * Unfortunately, some other NII drivers (e.g. Mellanox) may
         * time out and report failure if asked to detect cable
         * presence during initialisation on links that are physically
         * slow to reach link-up.
         *
         * Attempt to work around both of these problems by requesting
         * cable detection at this point if any only if the driver is
         * not capable of reporting link status changes at runtime via
         * PXE_OPCODE_GET_STATUS.
         */
        flags = ( nii->media ? PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
                  : PXE_OPFLAGS_INITIALIZE_DETECT_CABLE );
        if ( ( rc = nii_initialise_flags ( nii, flags ) ) != 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;
}
static void nii_close ( struct net_device netdev) [static]

Close network device.

Parameters:
netdevNetwork device

Definition at line 1177 of file nii.c.

References ECANCELED, free_iob(), netdev_tx_complete_err(), nii_nic::nii, nii_shutdown(), NULL, net_device::priv, nii_nic::rxbuf, and nii_nic::txbuf.

                                                    {
        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;
        }
}
int nii_start ( struct efi_device efidev)

Attach driver to device.

Parameters:
efidevEFI device
Return values:
rcReturn status code

Definition at line 1210 of file nii.c.

References alloc_netdev(), EFI_SYSTEM_TABLE::BootServices, nii_nic::broadcast, device::children, EFI_BOOT_SERVICES::CloseProtocol, DBGC, DBGC_EFI_OPENERS, efi_device::dev, nii_nic::dev, net_device::dev, efi_device::device, device::driver_name, EEFI, efi_device_info(), efi_handle_name(), efi_image_handle, efi_nii31_protocol_guid, EFI_OPEN_PROTOCOL_BY_DRIVER, EFI_OPEN_PROTOCOL_EXCLUSIVE, efi_systab, nii_nic::efidev, efidev_set_drvdata(), ENODEV, ENOMEM, ENOTSUP, s_pxe_sw_undi::EntryPoint, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::Id, s_pxe_sw_undi::Implementation, INIT_LIST_HEAD, nii_nic::issue, list_add, list_del, net_device::ll_broadcast, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::MajorVer, nii_nic::mappings, nii_nic::media, _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL::MinorVer, device::name, net_device::name, netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), nii_nic::nii, nii_get_init_info(), nii_get_station_address(), nii_pci_close(), nii_pci_open(), nii_start_undi(), nii_stop_undi(), EFI_BOOT_SERVICES::OpenProtocol, device::parent, net_device::priv, PXE_ROMID_IMP_HW_UNDI, PXE_ROMID_IMP_SW_VIRT_ADDR, rc, register_netdev(), device::siblings, strerror(), nii_nic::undi, and unregister_netdev().

                                            {
        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;
        INIT_LIST_HEAD ( &nii->mappings );
        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 %s\n", nii->dev.name,
               netdev->name, 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;
}
void nii_stop ( struct efi_device efidev)

Detach driver from device.

Parameters:
efidevEFI device

Definition at line 1329 of file nii.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, nii_nic::dev, efi_device::device, efi_image_handle, efi_nii31_protocol_guid, efi_systab, efidev_get_drvdata(), list_del, netdev, netdev_nullify(), netdev_put(), nii_nic::nii, nii_pci_close(), nii_stop_undi(), net_device::priv, device::siblings, and unregister_netdev().

                                            {
        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 );
}

Variable Documentation

Initial value:
 {
        .open = nii_open,
        .close = nii_close,
        .transmit = nii_transmit,
        .poll = nii_poll,
}

NII network device operations.

Definition at line 1197 of file nii.c.