synchronous requests and EFI_BLOCK_IO_PROTOCOL for now.\r
\r
Copyright (C) 2012, Red Hat, Inc.\r
+ Copyright (c) 2012, 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
UINT32 BlockSize;\r
volatile VIRTIO_BLK_REQ Request;\r
volatile UINT8 HostStatus;\r
- UINT16 FirstAvailIdx;\r
- UINT16 NextAvailIdx;\r
- UINTN PollPeriodUsecs;\r
+ DESC_INDICES Indices;\r
\r
BlockSize = Dev->BlockIoMedia.BlockSize;\r
\r
(BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) :\r
VIRTIO_BLK_T_IN;\r
Request.IoPrio = 0;\r
- Request.Sector = Lba * (BlockSize / 512);\r
+ Request.Sector = MultU64x32(Lba, BlockSize / 512);\r
\r
- //\r
- // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.\r
- // We're going to poll the answer, the host should not send an interrupt.\r
- //\r
- *Dev->Ring.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;\r
+ VirtioPrepare (&Dev->Ring, &Indices);\r
\r
//\r
// preset a host status for ourselves that we do not accept as success\r
//\r
ASSERT (Dev->Ring.QueueSize >= 3);\r
\r
- //\r
- // Implement virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.\r
- //\r
- FirstAvailIdx = *Dev->Ring.Avail.Idx;\r
- NextAvailIdx = FirstAvailIdx;\r
-\r
//\r
// virtio-blk header in first desc\r
//\r
- AppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request, VRING_DESC_F_NEXT,\r
- FirstAvailIdx, &NextAvailIdx);\r
+ VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,\r
+ VRING_DESC_F_NEXT, &Indices);\r
\r
//\r
// data buffer for read/write in second desc\r
//\r
// VRING_DESC_F_WRITE is interpreted from the host's point of view.\r
//\r
- AppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,\r
+ VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,\r
VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),\r
- FirstAvailIdx, &NextAvailIdx);\r
+ &Indices);\r
}\r
\r
//\r
// host status in last (second or third) desc\r
//\r
- AppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\r
- VRING_DESC_F_WRITE, FirstAvailIdx, &NextAvailIdx);\r
+ VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\r
+ VRING_DESC_F_WRITE, &Indices);\r
\r
//\r
- // virtio-0.9.5, 2.4.1.3 Updating the Index Field\r
+ // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
//\r
- MemoryFence();\r
- *Dev->Ring.Avail.Idx = NextAvailIdx;\r
-\r
- //\r
- // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are\r
- // OK. virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
- //\r
- MemoryFence();\r
- if (EFI_ERROR (VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, 0))) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
- // Wait until the host processes and acknowledges our 3-part descriptor\r
- // chain. The condition we use for polling is greatly simplified and relies\r
- // on synchronous, the lock-step progress.\r
- //\r
- // Keep slowing down until we reach a poll period of slightly above 1 ms.\r
- //\r
- PollPeriodUsecs = 1;\r
- MemoryFence();\r
- while (*Dev->Ring.Used.Idx != NextAvailIdx) {\r
- gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay\r
-\r
- if (PollPeriodUsecs < 1024) {\r
- PollPeriodUsecs *= 2;\r
- }\r
- MemoryFence();\r
- }\r
-\r
- if (HostStatus == VIRTIO_BLK_S_OK) {\r
+ if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
+ HostStatus == VIRTIO_BLK_S_OK) {\r
return EFI_SUCCESS;\r
}\r
\r
Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
Pci.Hdr.RevisionID == 0x00 &&\r
- Pci.Device.SubsystemID == 0x02) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+ Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
}\r
\r
//\r
goto Failed;\r
}\r
if (BlockSize == 0 || BlockSize % 512 != 0 ||\r
- NumSectors % (BlockSize / 512) != 0) {\r
+ ModU64x32 (NumSectors, BlockSize / 512) != 0) {\r
//\r
// We can only handle a logical block consisting of whole sectors,\r
// and only a disk composed of whole logical blocks.\r
Dev->BlockIoMedia.WriteCaching = !!(Features & VIRTIO_BLK_F_FLUSH);\r
Dev->BlockIoMedia.BlockSize = BlockSize;\r
Dev->BlockIoMedia.IoAlign = 0;\r
- Dev->BlockIoMedia.LastBlock = NumSectors / (BlockSize / 512) - 1;\r
+ Dev->BlockIoMedia.LastBlock = DivU64x32 (NumSectors,\r
+ BlockSize / 512) - 1;\r
return EFI_SUCCESS;\r
\r
ReleaseQueue:\r
IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
- VBLK_DEV *Dev;\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ VBLK_DEV *Dev;\r
\r
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle, // candidate device\r
+ &gEfiBlockIoProtocolGuid, // retrieve the BlockIo iface\r
+ (VOID **)&BlockIo, // target pointer\r
+ This->DriverBindingHandle, // requestor driver identity\r
+ DeviceHandle, // requesting lookup for dev.\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Dev = VIRTIO_BLK_FROM_BLOCK_IO (BlockIo);\r
\r
//\r
- // If DriverBindingStop() is called with the driver instance still in use,\r
- // or any of the parameters are invalid, we've caught a bug.\r
+ // Handle Stop() requests for in-use driver instances gracefully.\r
//\r
Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
&gEfiBlockIoProtocolGuid, &Dev->BlockIo);\r
- ASSERT (Status == EFI_SUCCESS);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
VirtioBlkUninit (Dev);\r
\r
// for unambiguous identification.\r
//\r
\r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
{ "eng;en", L"Virtio Block Driver" },\r
{ NULL, NULL }\r
};\r
\r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
\r
EFI_STATUS\r
return EFI_UNSUPPORTED;\r
}\r
\r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
&VirtioBlkGetDriverName,\r
&VirtioBlkGetDeviceName,\r
"eng" // SupportedLanguages, ISO 639-2 language codes\r
};\r
\r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioBlkGetDriverName,\r
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioBlkGetDeviceName,\r