+ //\r
+ // Map the virtio-scsi Request header buffer\r
+ //\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterRead,\r
+ (VOID *) &Request,\r
+ sizeof Request,\r
+ &RequestDeviceAddress,\r
+ &RequestMapping);\r
+ if (EFI_ERROR (Status)) {\r
+ return ReportHostAdapterError (Packet);\r
+ }\r
+\r
+ //\r
+ // Map the input buffer\r
+ //\r
+ if (Packet->InTransferLength > 0) {\r
+ //\r
+ // Allocate a intermediate input buffer. This is mainly to handle the\r
+ // following case:\r
+ // * caller submits a bi-directional request\r
+ // * we perform the request fine\r
+ // * but we fail to unmap the "InDataMapping"\r
+ //\r
+ // In that case simply returing the EFI_DEVICE_ERROR is not sufficient. In\r
+ // addition to the error code we also need to update Packet fields\r
+ // accordingly so that we report the full loss of the incoming transfer.\r
+ //\r
+ // We allocate a temporary buffer and map it with BusMasterCommonBuffer. If\r
+ // the Virtio request is successful then we copy the data from temporary\r
+ // buffer into Packet->InDataBuffer.\r
+ //\r
+ InDataNumPages = EFI_SIZE_TO_PAGES ((UINTN)Packet->InTransferLength);\r
+ Status = Dev->VirtIo->AllocateSharedPages (\r
+ Dev->VirtIo,\r
+ InDataNumPages,\r
+ &InDataBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapRequestBuffer;\r
+ }\r
+\r
+ ZeroMem (InDataBuffer, Packet->InTransferLength);\r
+\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterCommonBuffer,\r
+ InDataBuffer,\r
+ Packet->InTransferLength,\r
+ &InDataDeviceAddress,\r
+ &InDataMapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto FreeInDataBuffer;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Map the output buffer\r
+ //\r
+ if (Packet->OutTransferLength > 0) {\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterRead,\r
+ Packet->OutDataBuffer,\r
+ Packet->OutTransferLength,\r
+ &OutDataDeviceAddress,\r
+ &OutDataMapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapInDataBuffer;\r
+ }\r
+\r
+ OutDataBufferIsMapped = TRUE;\r
+ }\r
+\r
+ //\r
+ // Response header is bi-direction (we preset with host status and expect\r
+ // the device to update it). Allocate a response buffer which can be mapped\r
+ // to access equally by both processor and device.\r
+ //\r
+ Status = Dev->VirtIo->AllocateSharedPages (\r
+ Dev->VirtIo,\r
+ EFI_SIZE_TO_PAGES (sizeof *Response),\r
+ &ResponseBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapOutDataBuffer;\r
+ }\r
+\r
+ Response = ResponseBuffer;\r
+\r
+ ZeroMem ((VOID *)Response, sizeof (*Response));\r