\r
#include <IndustryStandard/Pci.h>\r
#include <IndustryStandard/PvScsi.h>\r
+#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiLib.h>\r
#include <Protocol/PciIo.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
#include <Uefi/UefiSpec.h>\r
\r
#include "PvScsi.h"\r
);\r
}\r
\r
+STATIC\r
+EFI_STATUS\r
+PvScsiAllocateSharedPages (\r
+ IN PVSCSI_DEV *Dev,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ OUT PVSCSI_DMA_DESC *DmaDesc\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN NumberOfBytes;\r
+\r
+ Status = Dev->PciIo->AllocateBuffer (\r
+ Dev->PciIo,\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ Pages,\r
+ HostAddress,\r
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);\r
+ Status = Dev->PciIo->Map (\r
+ Dev->PciIo,\r
+ EfiPciIoOperationBusMasterCommonBuffer,\r
+ *HostAddress,\r
+ &NumberOfBytes,\r
+ &DmaDesc->DeviceAddress,\r
+ &DmaDesc->Mapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeBuffer;\r
+ }\r
+\r
+ if (NumberOfBytes != EFI_PAGES_TO_SIZE (Pages)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Unmap;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Unmap:\r
+ Dev->PciIo->Unmap (Dev->PciIo, DmaDesc->Mapping);\r
+\r
+FreeBuffer:\r
+ Dev->PciIo->FreeBuffer (Dev->PciIo, Pages, *HostAddress);\r
+\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+VOID\r
+PvScsiFreeSharedPages (\r
+ IN PVSCSI_DEV *Dev,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress,\r
+ IN PVSCSI_DMA_DESC *DmaDesc\r
+ )\r
+{\r
+ Dev->PciIo->Unmap (Dev->PciIo, DmaDesc->Mapping);\r
+ Dev->PciIo->FreeBuffer (Dev->PciIo, Pages, HostAddress);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+PvScsiInitRings (\r
+ IN OUT PVSCSI_DEV *Dev\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ union {\r
+ PVSCSI_CMD_DESC_SETUP_RINGS Cmd;\r
+ UINT32 Uint32;\r
+ } AlignedCmd;\r
+ PVSCSI_CMD_DESC_SETUP_RINGS *Cmd;\r
+\r
+ Cmd = &AlignedCmd.Cmd;\r
+\r
+ Status = PvScsiAllocateSharedPages (\r
+ Dev,\r
+ 1,\r
+ (VOID **)&Dev->RingDesc.RingState,\r
+ &Dev->RingDesc.RingStateDmaDesc\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ZeroMem (Dev->RingDesc.RingState, EFI_PAGE_SIZE);\r
+\r
+ Status = PvScsiAllocateSharedPages (\r
+ Dev,\r
+ 1,\r
+ (VOID **)&Dev->RingDesc.RingReqs,\r
+ &Dev->RingDesc.RingReqsDmaDesc\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeRingState;\r
+ }\r
+ ZeroMem (Dev->RingDesc.RingReqs, EFI_PAGE_SIZE);\r
+\r
+ Status = PvScsiAllocateSharedPages (\r
+ Dev,\r
+ 1,\r
+ (VOID **)&Dev->RingDesc.RingCmps,\r
+ &Dev->RingDesc.RingCmpsDmaDesc\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeRingReqs;\r
+ }\r
+ ZeroMem (Dev->RingDesc.RingCmps, EFI_PAGE_SIZE);\r
+\r
+ ZeroMem (Cmd, sizeof (*Cmd));\r
+ Cmd->ReqRingNumPages = 1;\r
+ Cmd->CmpRingNumPages = 1;\r
+ Cmd->RingsStatePPN = RShiftU64 (\r
+ Dev->RingDesc.RingStateDmaDesc.DeviceAddress,\r
+ EFI_PAGE_SHIFT\r
+ );\r
+ Cmd->ReqRingPPNs[0] = RShiftU64 (\r
+ Dev->RingDesc.RingReqsDmaDesc.DeviceAddress,\r
+ EFI_PAGE_SHIFT\r
+ );\r
+ Cmd->CmpRingPPNs[0] = RShiftU64 (\r
+ Dev->RingDesc.RingCmpsDmaDesc.DeviceAddress,\r
+ EFI_PAGE_SHIFT\r
+ );\r
+\r
+ STATIC_ASSERT (\r
+ sizeof (*Cmd) % sizeof (UINT32) == 0,\r
+ "Cmd must be multiple of 32-bit words"\r
+ );\r
+ Status = PvScsiWriteCmdDesc (\r
+ Dev,\r
+ PvScsiCmdSetupRings,\r
+ (UINT32 *)Cmd,\r
+ sizeof (*Cmd) / sizeof (UINT32)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeRingCmps;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+FreeRingCmps:\r
+ PvScsiFreeSharedPages (\r
+ Dev,\r
+ 1,\r
+ Dev->RingDesc.RingCmps,\r
+ &Dev->RingDesc.RingCmpsDmaDesc\r
+ );\r
+\r
+FreeRingReqs:\r
+ PvScsiFreeSharedPages (\r
+ Dev,\r
+ 1,\r
+ Dev->RingDesc.RingReqs,\r
+ &Dev->RingDesc.RingReqsDmaDesc\r
+ );\r
+\r
+FreeRingState:\r
+ PvScsiFreeSharedPages (\r
+ Dev,\r
+ 1,\r
+ Dev->RingDesc.RingState,\r
+ &Dev->RingDesc.RingStateDmaDesc\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+VOID\r
+PvScsiFreeRings (\r
+ IN OUT PVSCSI_DEV *Dev\r
+ )\r
+{\r
+ PvScsiFreeSharedPages (\r
+ Dev,\r
+ 1,\r
+ Dev->RingDesc.RingCmps,\r
+ &Dev->RingDesc.RingCmpsDmaDesc\r
+ );\r
+\r
+ PvScsiFreeSharedPages (\r
+ Dev,\r
+ 1,\r
+ Dev->RingDesc.RingReqs,\r
+ &Dev->RingDesc.RingReqsDmaDesc\r
+ );\r
+\r
+ PvScsiFreeSharedPages (\r
+ Dev,\r
+ 1,\r
+ Dev->RingDesc.RingState,\r
+ &Dev->RingDesc.RingStateDmaDesc\r
+ );\r
+}\r
+\r
STATIC\r
EFI_STATUS\r
PvScsiInit (\r
goto RestorePciAttributes;\r
}\r
\r
+ //\r
+ // Init PVSCSI rings\r
+ //\r
+ Status = PvScsiInitRings (Dev);\r
+ if (EFI_ERROR (Status)) {\r
+ goto RestorePciAttributes;\r
+ }\r
+\r
//\r
// Populate the exported interface's attributes\r
//\r
IN OUT PVSCSI_DEV *Dev\r
)\r
{\r
+ //\r
+ // Reset device to stop device usage of the rings.\r
+ // This is required to safely free the rings.\r
+ //\r
+ PvScsiResetAdapter (Dev);\r
+\r
+ PvScsiFreeRings (Dev);\r
+\r
PvScsiRestorePciAttributes (Dev);\r
}\r
\r