16#include <IndustryStandard/Xen/io/protocols.h>
17#include <IndustryStandard/Xen/io/xenbus.h>
39 IN BOOLEAN FromBackend,
43 XENSTORE_STATUS Status;
47 Status = This->XsRead (This, XST_NIL, Node, (VOID **)&Ptr);
49 Status = This->XsBackendRead (This, XST_NIL, Node, (VOID **)&Ptr);
52 if (Status != XENSTORE_STATUS_SUCCESS) {
75 if (Dev->RingRef != 0) {
76 XenBusIo->GrantEndAccess (XenBusIo, Dev->RingRef);
79 if (Dev->Ring.sring !=
NULL) {
83 if (Dev->EventChannel != 0) {
84 XenBusIo->EventChannelClose (XenBusIo, Dev->EventChannel);
104 IN XenbusState ExpectedState,
105 OUT XenbusState *LastStatePtr OPTIONAL
111 XENSTORE_STATUS Status = XENSTORE_STATUS_SUCCESS;
115 if (Status != XENSTORE_STATUS_SUCCESS) {
119 if (Value > XenbusStateReconfigured) {
123 return XENSTORE_STATUS_EIO;
127 if (State == ExpectedState) {
129 }
else if (State > ExpectedState) {
130 Status = XENSTORE_STATUS_FAIL;
136 "XenPvBlk: waiting backend state %d, current: %d\n",
140 XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
143 if (LastStatePtr !=
NULL) {
144 *LastStatePtr = State;
151XenPvBlockFrontInitialization (
159 blkif_sring_t *SharedRing;
160 XENSTORE_STATUS Status;
166 ASSERT (NodeName !=
NULL);
170 return EFI_OUT_OF_RESOURCES;
173 Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE;
174 Dev->NodeName = NodeName;
175 Dev->XenBusIo = XenBusIo;
176 Dev->DeviceId = XenBusIo->DeviceId;
178 XenBusIo->XsRead (XenBusIo, XST_NIL,
"device-type", (VOID **)&DeviceType);
180 Dev->MediaInfo.CdRom =
TRUE;
182 Dev->MediaInfo.CdRom =
FALSE;
187 if (Dev->MediaInfo.CdRom) {
188 Status = XenBusIo->XsBackendRead (XenBusIo, XST_NIL,
"params", (VOID **)&Params);
189 if (Status != XENSTORE_STATUS_SUCCESS) {
190 DEBUG ((DEBUG_ERROR,
"%a: Failed to read params (%d)\n", __func__, Status));
196 DEBUG ((DEBUG_INFO,
"%a: Empty cdrom\n", __func__));
204 if ((Status != XENSTORE_STATUS_SUCCESS) || (Value > MAX_UINT16)) {
207 "XenPvBlk: Failed to get backend-id (%d)\n",
213 Dev->DomainId = (domid_t)Value;
214 XenBusIo->EventChannelAllocate (XenBusIo, Dev->DomainId, &Dev->EventChannel);
217 SHARED_RING_INIT (SharedRing);
218 FRONT_RING_INIT (&Dev->Ring, SharedRing, EFI_PAGE_SIZE);
219 XenBusIo->GrantAccess (
222 (
INTN)SharedRing >> EFI_PAGE_SHIFT,
228 Status = XenBusIo->XsTransactionStart (XenBusIo, &
Transaction);
229 if (Status != XENSTORE_STATUS_SUCCESS) {
230 DEBUG ((DEBUG_WARN,
"XenPvBlk: Failed to start transaction, %d\n", Status));
234 Status = XenBusIo->XsPrintf (
242 if (Status != XENSTORE_STATUS_SUCCESS) {
243 DEBUG ((DEBUG_ERROR,
"XenPvBlk: Failed to write ring-ref.\n"));
244 goto AbortTransaction;
247 Status = XenBusIo->XsPrintf (
255 if (Status != XENSTORE_STATUS_SUCCESS) {
256 DEBUG ((DEBUG_ERROR,
"XenPvBlk: Failed to write event-channel.\n"));
257 goto AbortTransaction;
260 Status = XenBusIo->XsPrintf (
266 XEN_IO_PROTO_ABI_NATIVE
268 if (Status != XENSTORE_STATUS_SUCCESS) {
269 DEBUG ((DEBUG_ERROR,
"XenPvBlk: Failed to write protocol.\n"));
270 goto AbortTransaction;
273 Status = XenBusIo->SetState (XenBusIo, &
Transaction, XenbusStateConnected);
274 if (Status != XENSTORE_STATUS_SUCCESS) {
275 DEBUG ((DEBUG_ERROR,
"XenPvBlk: Failed to switch state.\n"));
276 goto AbortTransaction;
280 if (Status == XENSTORE_STATUS_EAGAIN) {
284 XenBusIo->RegisterWatchBackend (XenBusIo,
"state", &Dev->StateWatchToken);
290 if (Status != XENSTORE_STATUS_SUCCESS) {
293 "XenPvBlk: backend for %a/%d not available, rc=%d state=%d\n",
303 if ((Status != XENSTORE_STATUS_SUCCESS) || (Value > MAX_UINT32)) {
307 Dev->MediaInfo.VDiskInfo = (UINT32)Value;
308 if (Dev->MediaInfo.VDiskInfo & VDISK_READONLY) {
309 Dev->MediaInfo.ReadWrite =
FALSE;
311 Dev->MediaInfo.ReadWrite =
TRUE;
315 if (Status != XENSTORE_STATUS_SUCCESS) {
320 if ((Status != XENSTORE_STATUS_SUCCESS) || (Value > MAX_UINT32)) {
324 if ((UINT32)Value % 512 != 0) {
330 "XenPvBlk: Unsupported sector-size value %Lu, "
331 "it must be a multiple of 512\n",
337 Dev->MediaInfo.SectorSize = (UINT32)Value;
343 Dev->MediaInfo.FeatureBarrier =
TRUE;
345 Dev->MediaInfo.FeatureBarrier =
FALSE;
352 Dev->MediaInfo.FeatureFlushCache =
TRUE;
354 Dev->MediaInfo.FeatureFlushCache =
FALSE;
359 "XenPvBlk: New disk with %ld sectors of %d bytes\n",
360 Dev->MediaInfo.Sectors,
361 Dev->MediaInfo.SectorSize
368 XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
369 XenBusIo->XsRemove (XenBusIo, XST_NIL,
"ring-ref");
370 XenBusIo->XsRemove (XenBusIo, XST_NIL,
"event-channel");
371 XenBusIo->XsRemove (XenBusIo, XST_NIL,
"protocol");
377 return EFI_DEVICE_ERROR;
381XenPvBlockFrontShutdown (
386 XENSTORE_STATUS Status;
389 XenPvBlockSync (Dev);
391 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosing);
392 if (Status != XENSTORE_STATUS_SUCCESS) {
395 "XenPvBlk: error while changing state to Closing: %d\n",
402 if (Status != XENSTORE_STATUS_SUCCESS) {
405 "XenPvBlk: error while waiting for closing backend state: %d\n",
411 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosed);
412 if (Status != XENSTORE_STATUS_SUCCESS) {
415 "XenPvBlk: error while changing state to Closed: %d\n",
422 if (Status != XENSTORE_STATUS_SUCCESS) {
425 "XenPvBlk: error while waiting for closed backend state: %d\n",
431 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateInitialising);
432 if (Status != XENSTORE_STATUS_SUCCESS) {
435 "XenPvBlk: error while changing state to initialising: %d\n",
443 if (Status != XENSTORE_STATUS_SUCCESS) {
446 "XenPvBlk: error while waiting for new backend state: %d\n",
452 if ((Value <= XenbusStateInitWait) || (Value >= XenbusStateClosed)) {
458 "XenPvBlk: waiting backend state %d, current: %Lu\n",
462 XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
466 XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
467 XenBusIo->XsRemove (XenBusIo, XST_NIL,
"ring-ref");
468 XenBusIo->XsRemove (XenBusIo, XST_NIL,
"event-channel");
469 XenBusIo->XsRemove (XenBusIo, XST_NIL,
"protocol");
481 if (RING_FULL (&Dev->Ring)) {
483 XenPvBlockAsyncIoPoll (Dev);
484 if (!RING_FULL (&Dev->Ring)) {
504 INT32 NumSegments, Index;
508 ASSERT (!(IoData->Sector & ((Dev->MediaInfo.SectorSize / 512) - 1)));
510 ASSERT (!(IoData->Size & (Dev->MediaInfo.SectorSize - 1)));
512 ASSERT (!((
UINTN)IoData->Buffer & (Dev->MediaInfo.SectorSize - 1)));
514 Start = (
UINTN)IoData->Buffer & ~EFI_PAGE_MASK;
515 End = ((
UINTN)IoData->Buffer + IoData->Size + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK;
516 IoData->NumRef = NumSegments = (INT32)((End - Start) / EFI_PAGE_SIZE);
518 ASSERT (NumSegments <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
520 XenPvBlockWaitSlot (Dev);
521 RingIndex = Dev->Ring.req_prod_pvt;
522 Request = RING_GET_REQUEST (&Dev->Ring, RingIndex);
524 Request->operation = IsWrite ? BLKIF_OP_WRITE : BLKIF_OP_READ;
525 Request->nr_segments = (UINT8)NumSegments;
526 Request->handle = Dev->DeviceId;
527 Request->id = (
UINTN)IoData;
528 Request->sector_number = IoData->Sector;
530 for (Index = 0; Index < NumSegments; Index++) {
531 Request->seg[Index].first_sect = 0;
532 Request->seg[Index].last_sect = EFI_PAGE_SIZE / 512 - 1;
535 Request->seg[0].first_sect = (UINT8)(((
UINTN)IoData->Buffer & EFI_PAGE_MASK) / 512);
536 Request->seg[NumSegments - 1].last_sect =
537 (UINT8)((((
UINTN)IoData->Buffer + IoData->Size - 1) & EFI_PAGE_MASK) / 512);
538 for (Index = 0; Index < NumSegments; Index++) {
539 UINTN Data = Start + Index * EFI_PAGE_SIZE;
540 XenBusIo->GrantAccess (
543 Data >> EFI_PAGE_SHIFT,
545 &Request->seg[Index].gref
547 IoData->GrantRef[Index] = Request->seg[Index].gref;
550 Dev->Ring.req_prod_pvt = RingIndex + 1;
553 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
557 ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
558 if (ReturnCode != 0) {
561 "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
577 IoData->Status = EFI_ALREADY_STARTED;
578 XenPvBlockAsyncIo (IoData, IsWrite);
580 while (IoData->Status == EFI_ALREADY_STARTED) {
581 XenPvBlockAsyncIoPoll (IoData->Dev);
584 return IoData->Status;
589XenPvBlockPushOperation (
599 XenPvBlockWaitSlot (Dev);
600 Index = Dev->Ring.req_prod_pvt;
601 Request = RING_GET_REQUEST (&Dev->Ring, Index);
602 Request->operation = Operation;
603 Request->nr_segments = 0;
604 Request->handle = Dev->DeviceId;
607 Request->sector_number = 0;
608 Dev->Ring.req_prod_pvt = Index + 1;
610 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
614 ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
615 if (ReturnCode != 0) {
618 "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
630 if (Dev->MediaInfo.ReadWrite) {
631 if (Dev->MediaInfo.FeatureBarrier) {
632 XenPvBlockPushOperation (Dev, BLKIF_OP_WRITE_BARRIER, 0);
635 if (Dev->MediaInfo.FeatureFlushCache) {
636 XenPvBlockPushOperation (Dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
642 XenPvBlockAsyncIoPoll (Dev);
643 if (RING_FREE_REQUESTS (&Dev->Ring) == RING_SIZE (&Dev->Ring)) {
650XenPvBlockAsyncIoPoll (
654 RING_IDX ProducerIndex, ConsumerIndex;
659 ProducerIndex = Dev->Ring.sring->rsp_prod;
662 ConsumerIndex = Dev->Ring.rsp_cons;
664 while (ConsumerIndex != ProducerIndex) {
668 Response = RING_GET_RESPONSE (&Dev->Ring, ConsumerIndex);
670 IoData = (VOID *)(
UINTN)Response->id;
671 Status = Response->status;
673 switch (Response->operation) {
679 if (Status != BLKIF_RSP_OKAY) {
683 "%a error %d on %a at sector %Lx, num bytes %Lx\n",
684 Response->operation == BLKIF_OP_READ ?
"read" :
"write",
686 IoData->Dev->NodeName,
692 for (Index = 0; Index < IoData->NumRef; Index++) {
693 Dev->XenBusIo->GrantEndAccess (Dev->XenBusIo, IoData->GrantRef[Index]);
699 case BLKIF_OP_WRITE_BARRIER:
700 if (Status != BLKIF_RSP_OKAY) {
701 DEBUG ((DEBUG_ERROR,
"XenPvBlk: write barrier error %d\n", Status));
705 case BLKIF_OP_FLUSH_DISKCACHE:
706 if (Status != BLKIF_RSP_OKAY) {
707 DEBUG ((DEBUG_ERROR,
"XenPvBlk: flush error %d\n", Status));
715 "XenPvBlk: unrecognized block operation %d response (status %d)\n",
722 Dev->Ring.rsp_cons = ++ConsumerIndex;
723 if (IoData !=
NULL) {
724 IoData->Status = Status ? EFI_DEVICE_ERROR :
EFI_SUCCESS;
727 if (Dev->Ring.rsp_cons != ConsumerIndex) {
733 RING_FINAL_CHECK_FOR_RESPONSES (&Dev->Ring, More);
EFI_STATUS EFIAPI Close(IN EFI_ACPI_HANDLE Handle)
UINT64 EFIAPI AsciiStrDecimalToUint64(IN CONST CHAR8 *String)
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
VOID EFIAPI MemoryFence(VOID)
STATIC VOID XenPvBlockFree(IN XEN_BLOCK_FRONT_DEVICE *Dev)
STATIC XENSTORE_STATUS XenBusReadUint64(IN XENBUS_PROTOCOL *This, IN CONST CHAR8 *Node, IN BOOLEAN FromBackend, OUT UINT64 *ValuePtr)
STATIC XENSTORE_STATUS XenPvBlkWaitForBackendState(IN XEN_BLOCK_FRONT_DEVICE *Dev, IN XenbusState ExpectedState, OUT XenbusState *LastStatePtr OPTIONAL)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define DEBUG(Expression)
VOID *EFIAPI AllocatePages(IN UINTN Pages)
EFI_STATUS EFIAPI Transaction(IN CONST EFI_SPI_IO_PROTOCOL *This, IN EFI_SPI_TRANSACTION_TYPE TransactionType, IN BOOLEAN DebugTransaction, IN UINT32 ClockHz OPTIONAL, IN UINT32 BusWidth, IN UINT32 FrameSize, IN UINT32 WriteBytes, IN UINT8 *WriteBuffer, IN UINT32 ReadBytes, OUT UINT8 *ReadBuffer)
UINTN Sector
512 bytes sector.