Driver Binding code and its private helpers for the virtio-net driver.\r
\r
Copyright (C) 2013, Red Hat, Inc.\r
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials are licensed and made available\r
under the terms and conditions of the BSD License which accompanies this\r
\r
**/\r
\r
-#include <IndustryStandard/Pci.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
unused.\r
\r
@retval EFI_UNSUPPORTED The host doesn't supply a MAC address.\r
- @return Status codes from Dev->PciIo->Io.Read(),\r
- VIRTIO_CFG_READ() and VIRTIO_CFG_WRITE().\r
+ @return Status codes from VirtIo protocol members.\r
@retval EFI_SUCCESS Configuration values retrieved.\r
*/\r
STATIC\r
EFI_STATUS Status;\r
UINT8 NextDevStat;\r
UINT32 Features;\r
+ UINTN MacIdx;\r
UINT16 LinkStatus;\r
\r
//\r
// Initialization Sequence), but don't complete setting it up.\r
//\r
NextDevStat = 0; // step 1 -- reset device\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
\r
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
//\r
// step 4a -- retrieve and validate features\r
//\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
Status = EFI_UNSUPPORTED;\r
goto YieldDevice;\r
}\r
- Status = Dev->PciIo->Io.Read (Dev->PciIo, // PciIo\r
- EfiPciIoWidthUint8, // Width\r
- PCI_BAR_IDX0, // BarIndex\r
- OFFSET_OF_VNET (VhdrMac), // Offset\r
- SIZE_OF_VNET (VhdrMac), // Count\r
- MacAddress // Buffer\r
+ for (MacIdx = 0; MacIdx < SIZE_OF_VNET (Mac); ++MacIdx) {\r
+ Status = Dev->VirtIo->ReadDevice (Dev->VirtIo,\r
+ OFFSET_OF_VNET (Mac) + MacIdx, // Offset\r
+ 1, // FieldSize\r
+ 1, // BufferSize\r
+ &MacAddress->Addr[MacIdx] // Buffer\r
);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto YieldDevice;\r
+ if (EFI_ERROR (Status)) {\r
+ goto YieldDevice;\r
+ }\r
}\r
\r
//\r
}\r
else {\r
*MediaPresentSupported = TRUE;\r
- Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus);\r
+ Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
- *MediaPresent = !!(LinkStatus & VIRTIO_NET_S_LINK_UP);\r
+ *MediaPresent = (BOOLEAN) ((LinkStatus & VIRTIO_NET_S_LINK_UP) != 0);\r
}\r
\r
YieldDevice:\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus,\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo,\r
EFI_ERROR (Status) ? VSTAT_FAILED : 0);\r
\r
return Status;\r
Dev->Snp.Mode = &Dev->Snm;\r
\r
Dev->Snm.State = EfiSimpleNetworkStopped;\r
- Dev->Snm.HwAddressSize = SIZE_OF_VNET (VhdrMac);\r
- Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (VhdrMac) + // dst MAC\r
- SIZE_OF_VNET (VhdrMac) + // src MAC\r
+ Dev->Snm.HwAddressSize = SIZE_OF_VNET (Mac);\r
+ Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (Mac) + // dst MAC\r
+ SIZE_OF_VNET (Mac) + // src MAC\r
2; // Ethertype\r
Dev->Snm.MaxPacketSize = 1500;\r
Dev->Snm.NvRamSize = 0;\r
Dev->Snm.MacAddressChangeable = FALSE;\r
Dev->Snm.MultipleTxSupported = TRUE;\r
\r
- ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS));\r
+ ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));\r
\r
Status = VirtioNetGetFeatures (Dev, &Dev->Snm.CurrentAddress,\r
&Dev->Snm.MediaPresentSupported, &Dev->Snm.MediaPresent);\r
goto CloseWaitForPacket;\r
}\r
CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress,\r
- SIZE_OF_VNET (VhdrMac));\r
- SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (VhdrMac), 0xFF);\r
+ SIZE_OF_VNET (Mac));\r
+ SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (Mac), 0xFF);\r
\r
//\r
// VirtioNetExitBoot() is queued by ExitBootServices(); its purpose is to\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
-\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
+\r
+ //\r
+ // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open\r
+ // attempts (EFI_ALREADY_STARTED).\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle, // candidate device\r
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+ (VOID **)&VirtIo, // handle to instantiate\r
+ This->DriverBindingHandle, // requestor driver identity\r
+ DeviceHandle, // ControllerHandle, according to\r
+ // the UEFI Driver Model\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
+ // the device; to be released\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0,\r
- sizeof Pci / sizeof (UINT32), &Pci);\r
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
\r
//\r
- // virtio-0.9.5, 2.1 PCI Discovery:\r
- // the network device has Subsystem Device ID 1\r
+ // We needed VirtIo access only transitorily, to see whether we support the\r
+ // device or not.\r
//\r
- if (Status == EFI_SUCCESS) {\r
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
- Pci.Hdr.RevisionID == 0x00 &&\r
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_NETWORK_CARD) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
- }\r
-\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
return Status;\r
}\r
VNET_DEV *Dev;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
MAC_ADDR_DEVICE_PATH MacNode;\r
- VOID *ChildPciIo;\r
+ VOID *ChildVirtIo;\r
\r
//\r
// allocate space for the driver instance\r
}\r
Dev->Signature = VNET_SIG;\r
\r
- //\r
- // get PCI access to the device and keep it open\r
- //\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
if (EFI_ERROR (Status)) {\r
goto FreeVirtioNet;\r
}\r
\r
- //\r
- // save original PCI attributes and enable IO space access\r
- //\r
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
- 0, &Dev->OrigPciAttributes);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
- Status = Dev->PciIo->Attributes (Dev->PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
//\r
// now we can run a basic one-shot virtio-net initialization required to\r
// retrieve the MAC address\r
//\r
Status = VirtioNetSnpPopulate (Dev);\r
if (EFI_ERROR (Status)) {\r
- goto RestorePciAttributes;\r
+ goto CloseVirtIo;\r
}\r
\r
//\r
- // get the device path of the virtio-net PCI device -- one-shot open\r
+ // get the device path of the virtio-net device -- one-shot open\r
//\r
Status = gBS->OpenProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid,\r
(VOID **)&DevicePath, This->DriverBindingHandle,\r
}\r
\r
//\r
- // make a note that we keep this device open with PciIo for the sake of this\r
+ // make a note that we keep this device open with VirtIo for the sake of this\r
// child\r
//\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- &ChildPciIo, This->DriverBindingHandle,\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ &ChildVirtIo, This->DriverBindingHandle,\r
Dev->MacHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);\r
if (EFI_ERROR (Status)) {\r
goto UninstallMultiple;\r
Evacuate:\r
VirtioNetSnpEvacuate (Dev);\r
\r
-RestorePciAttributes:\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OrigPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
FreeVirtioNet:\r
Status = EFI_DEVICE_ERROR;\r
}\r
else {\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, Dev->MacHandle);\r
gBS->UninstallMultipleProtocolInterfaces (Dev->MacHandle,\r
&gEfiDevicePathProtocolGuid, Dev->MacDevicePath,\r
NULL);\r
FreePool (Dev->MacDevicePath);\r
VirtioNetSnpEvacuate (Dev);\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OrigPciAttributes, NULL);\r
FreePool (Dev);\r
}\r
\r
//\r
// release remaining resources, tied directly to the parent handle\r
//\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
return EFI_SUCCESS;\r