diff options
author | Michael Brown | 2014-07-04 17:52:10 +0200 |
---|---|---|
committer | Michael Brown | 2014-07-08 15:01:55 +0200 |
commit | d0cfbd01f51661994a8e8379ddda6d592177a29b (patch) | |
tree | 0d215d4b9b43352229526262bab6250c905908c0 /src/drivers/net/efi/snp.c | |
parent | [efi] Attempt to start only drivers claiming support for a device (diff) | |
download | ipxe-d0cfbd01f51661994a8e8379ddda6d592177a29b.tar.gz ipxe-d0cfbd01f51661994a8e8379ddda6d592177a29b.tar.xz ipxe-d0cfbd01f51661994a8e8379ddda6d592177a29b.zip |
[efi] Rewrite SNP NIC driver
Rewrite the SNP NIC driver to use non-blocking and deferrable
transmissions, to provide link status detection, to provide
information about the underlying (PCI) hardware device, and to avoid
unnecessary I/O buffer allocations during receive polling.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/efi/snp.c')
-rw-r--r-- | src/drivers/net/efi/snp.c | 146 |
1 files changed, 2 insertions, 144 deletions
diff --git a/src/drivers/net/efi/snp.c b/src/drivers/net/efi/snp.c index 98619d66..958db712 100644 --- a/src/drivers/net/efi/snp.c +++ b/src/drivers/net/efi/snp.c @@ -19,17 +19,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); -#include <stdlib.h> -#include <stdio.h> -#include <string.h> #include <errno.h> #include <ipxe/efi/efi.h> #include <ipxe/efi/Protocol/SimpleNetwork.h> #include <ipxe/efi/efi_driver.h> #include <ipxe/efi/efi_snp.h> -#include <ipxe/efi/efi_pci.h> #include "snpnet.h" -#include "snp.h" /** @file * @@ -41,10 +36,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); static EFI_GUID efi_simple_network_protocol_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; -/** EFI PCI I/O protocol GUID */ -static EFI_GUID efi_pci_io_protocol_guid - = EFI_PCI_IO_PROTOCOL_GUID; - /** * Check to see if driver supports a device * @@ -77,143 +68,10 @@ static int snp_supported ( EFI_HANDLE device ) { return 0; } -/** - * Get underlying PCI device information - * - * @v snpdev SNP device - * @ret rc Return status code - */ -static int snp_pci_info ( struct snp_device *snpdev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct efi_device *efidev = snpdev->efidev; - EFI_DEVICE_PATH_PROTOCOL *devpath = efidev->path; - struct pci_device pci; - EFI_HANDLE device; - EFI_STATUS efirc; - int rc; - - /* Check for presence of PCI I/O protocol */ - if ( ( efirc = bs->LocateDevicePath ( &efi_pci_io_protocol_guid, - &devpath, &device ) ) != 0 ) { - DBGC ( efidev->device, "SNP %p %s is not a PCI device\n", - efidev->device, efi_devpath_text ( efidev->path ) ); - return -EEFI ( efirc ); - } - - /* Get PCI device information */ - if ( ( rc = efipci_info ( device, &pci ) ) != 0 ) { - DBGC ( efidev->device, "SNP %p %s could not get PCI " - "information: %s\n", efidev->device, - efi_devpath_text ( efidev->path ), strerror ( rc ) ); - return rc; - } - - /* Populate SNP device information */ - memcpy ( &snpdev->dev.desc, &pci.dev.desc, sizeof ( snpdev->dev.desc )); - snprintf ( snpdev->dev.name, sizeof ( snpdev->dev.name ), "SNP-%s", - pci.dev.name ); - - return 0; -} - -/** - * Attach driver to device - * - * @v efidev EFI device - * @ret rc Return status code - */ -static int snp_start ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE device = efidev->device; - struct snp_device *snpdev; - union { - EFI_SIMPLE_NETWORK_PROTOCOL *snp; - void *interface; - } snp; - EFI_STATUS efirc; - int rc; - - /* Check that this is not a device we are providing ourselves */ - if ( find_snpdev ( efidev->device ) != NULL ) { - DBGCP ( device, "SNP %p %s is provided by this binary\n", - device, efi_devpath_text ( efidev->path ) ); - rc = -ENOTTY; - goto err_own; - } - - /* Allocate and initialise structure */ - snpdev = zalloc ( sizeof ( *snpdev ) ); - if ( ! snpdev ) { - rc = -ENOMEM; - goto err_alloc; - } - snpdev->efidev = efidev; - snpdev->dev.driver_name = "SNP"; - INIT_LIST_HEAD ( &snpdev->dev.children ); - - /* See if device is an SNP device */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_simple_network_protocol_guid, - &snp.interface, efi_image_handle, - device, - ( EFI_OPEN_PROTOCOL_BY_DRIVER | - EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){ - rc = -EEFI ( efirc ); - DBGCP ( device, "SNP %p %s cannot open SNP protocol: %s\n", - device, efi_devpath_text ( efidev->path ), - strerror ( rc ) ); - goto err_open_protocol; - } - snpdev->snp = snp.snp; - - /* Get underlying device information */ - if ( ( rc = snp_pci_info ( snpdev ) ) != 0 ) - goto err_info; - - /* Mark SNP device as a child of the EFI device */ - snpdev->dev.parent = &efidev->dev; - list_add ( &snpdev->dev.siblings, &efidev->dev.children ); - - /* Create SNP network device */ - if ( ( rc = snpnet_probe ( snpdev ) ) != 0 ) - goto err_probe; - - efidev_set_drvdata ( efidev, snpdev ); - return 0; - - snpnet_remove ( snpdev ); - err_probe: - list_del ( &snpdev->dev.siblings ); - err_info: - bs->CloseProtocol ( device, &efi_simple_network_protocol_guid, - efi_image_handle, device ); - err_open_protocol: - free ( snpdev ); - err_alloc: - err_own: - return rc; -} - -/** - * Detach driver from device - * - * @v efidev EFI device - */ -static void snp_stop ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct snp_device *snpdev = efidev_get_drvdata ( efidev ); - - snpnet_remove ( snpdev ); - list_del ( &snpdev->dev.siblings ); - bs->CloseProtocol ( efidev->device, &efi_simple_network_protocol_guid, - efi_image_handle, efidev->device ); - free ( snpdev ); -} - /** EFI SNP driver */ struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { .name = "SNP", .supported = snp_supported, - .start = snp_start, - .stop = snp_stop, + .start = snpnet_start, + .stop = snpnet_stop, }; |