iPXE
Functions
snpnet.h File Reference

SNP NIC driver. More...

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
int snpnet_start (struct efi_device *efidev)
 Attach driver to device.
void snpnet_stop (struct efi_device *efidev)
 Detach driver from device.

Detailed Description

SNP NIC driver.

Definition in file snpnet.h.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
int snpnet_start ( struct efi_device efidev)

Attach driver to device.

Parameters:
efidevEFI device
Return values:
rcReturn status code

Definition at line 418 of file snpnet.c.

References alloc_etherdev(), EFI_SYSTEM_TABLE::BootServices, device::children, EFI_BOOT_SERVICES::CloseProtocol, EFI_SIMPLE_NETWORK_MODE::CurrentAddress, DBGC, DBGC_EFI_OPENERS, efi_device::dev, snp_nic::dev, net_device::dev, efi_device::device, device::driver_name, EEFI, efi_device_info(), efi_handle_name(), efi_image_handle, EFI_OPEN_PROTOCOL_BY_DRIVER, EFI_OPEN_PROTOCOL_EXCLUSIVE, efi_simple_network_protocol_guid, efi_systab, snp_nic::efidev, efidev_set_drvdata(), EfiSimpleNetworkInitialized, EfiSimpleNetworkStopped, ENOMEM, ENOTSUP, net_device::hw_addr, ll_protocol::hw_addr_len, EFI_SIMPLE_NETWORK_MODE::HwAddressSize, INIT_LIST_HEAD, list_add, list_del, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, EFI_SIMPLE_NETWORK_MODE::MaxPacketSize, EFI_SIMPLE_NETWORK_MODE::MediaHeaderSize, EFI_SIMPLE_NETWORK_MODE::MediaPresentSupported, memcpy(), _EFI_SIMPLE_NETWORK_PROTOCOL::Mode, snp_nic::mtu, net_device::name, netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), EFI_BOOT_SERVICES::OpenProtocol, device::parent, EFI_SIMPLE_NETWORK_MODE::PermanentAddress, net_device::priv, rc, register_netdev(), _EFI_SIMPLE_NETWORK_PROTOCOL::Shutdown, device::siblings, snp_nic::snp, snpnet_check_link(), _EFI_SIMPLE_NETWORK_PROTOCOL::Start, EFI_SIMPLE_NETWORK_MODE::State, strerror(), and unregister_netdev().

                                               {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        EFI_HANDLE device = efidev->device;
        EFI_SIMPLE_NETWORK_MODE *mode;
        struct net_device *netdev;
        struct snp_nic *snp;
        void *interface;
        EFI_STATUS efirc;
        int rc;

        /* Open SNP protocol */
        if ( ( efirc = bs->OpenProtocol ( device,
                                          &efi_simple_network_protocol_guid,
                                          &interface, efi_image_handle, device,
                                          ( EFI_OPEN_PROTOCOL_BY_DRIVER |
                                            EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s cannot open SNP protocol: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                DBGC_EFI_OPENERS ( device, device,
                                   &efi_simple_network_protocol_guid );
                goto err_open_protocol;
        }

        /* Allocate and initialise structure */
        netdev = alloc_etherdev ( sizeof ( *snp ) );
        if ( ! netdev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        netdev_init ( netdev, &snpnet_operations );
        snp = netdev->priv;
        snp->efidev = efidev;
        snp->snp = interface;
        mode = snp->snp->Mode;
        efidev_set_drvdata ( efidev, netdev );

        /* Populate underlying device information */
        efi_device_info ( device, "SNP", &snp->dev );
        snp->dev.driver_name = "SNP";
        snp->dev.parent = &efidev->dev;
        list_add ( &snp->dev.siblings, &efidev->dev.children );
        INIT_LIST_HEAD ( &snp->dev.children );
        netdev->dev = &snp->dev;

        /* Bring to the Started state */
        if ( ( mode->State == EfiSimpleNetworkStopped ) &&
             ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) {
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s could not start: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                goto err_start;
        }
        if ( ( mode->State == EfiSimpleNetworkInitialized ) &&
             ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s could not shut down: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                goto err_shutdown;
        }

        /* Populate network device parameters */
        if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) {
                DBGC ( device, "SNP %s has invalid hardware address length "
                       "%d\n", efi_handle_name ( device ), mode->HwAddressSize);
                rc = -ENOTSUP;
                goto err_hw_addr_len;
        }
        memcpy ( netdev->hw_addr, &mode->PermanentAddress,
                 netdev->ll_protocol->hw_addr_len );
        if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) {
                DBGC ( device, "SNP %s has invalid link-layer address length "
                       "%d\n", efi_handle_name ( device ), mode->HwAddressSize);
                rc = -ENOTSUP;
                goto err_ll_addr_len;
        }
        memcpy ( netdev->ll_addr, &mode->CurrentAddress,
                 netdev->ll_protocol->ll_addr_len );
        snp->mtu = ( snp->snp->Mode->MaxPacketSize +
                     snp->snp->Mode->MediaHeaderSize );

        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                goto err_register_netdev;
        DBGC ( device, "SNP %s registered as %s\n",
               efi_handle_name ( device ), netdev->name );

        /* Set initial link state */
        if ( snp->snp->Mode->MediaPresentSupported ) {
                snpnet_check_link ( netdev );
        } else {
                netdev_link_up ( netdev );
        }

        return 0;

        unregister_netdev ( netdev );
 err_register_netdev:
 err_ll_addr_len:
 err_hw_addr_len:
 err_shutdown:
 err_start:
        list_del ( &snp->dev.siblings );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
 err_alloc:
        bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
                            efi_image_handle, device );
 err_open_protocol:
        return rc;
}
void snpnet_stop ( struct efi_device efidev)

Detach driver from device.

Parameters:
efidevEFI device

Definition at line 535 of file snpnet.c.

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseProtocol, DBGC, snp_nic::dev, efi_device::device, EEFI, efi_handle_name(), efi_image_handle, efi_simple_network_protocol_guid, efi_systab, efidev_get_drvdata(), list_del, netdev_nullify(), netdev_put(), net_device::priv, rc, device::siblings, snp_nic::snp, _EFI_SIMPLE_NETWORK_PROTOCOL::Stop, strerror(), and unregister_netdev().

                                               {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        struct net_device *netdev = efidev_get_drvdata ( efidev );
        struct snp_nic *snp = netdev->priv;
        EFI_HANDLE device = efidev->device;
        EFI_STATUS efirc;
        int rc;

        /* Unregister network device */
        unregister_netdev ( netdev );

        /* Stop SNP protocol */
        if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( device, "SNP %s could not stop: %s\n",
                       efi_handle_name ( device ), strerror ( rc ) );
                /* Nothing we can do about this */
        }

        /* Free network device */
        list_del ( &snp->dev.siblings );
        netdev_nullify ( netdev );
        netdev_put ( netdev );

        /* Close SNP protocol */
        bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
                            efi_image_handle, device );
}