]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenPvBlkDxe/BlockFront.c
OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.GetInfo()
[mirror_edk2.git] / OvmfPkg / XenPvBlkDxe / BlockFront.c
1 /** @file
2 Minimal block driver for Mini-OS.
3
4 Copyright (c) 2007-2008 Samuel Thibault.
5 Copyright (C) 2014, Citrix Ltd.
6 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9 **/
10
11 #include <Library/PrintLib.h>
12 #include <Library/DebugLib.h>
13
14 #include "BlockFront.h"
15
16 #include <IndustryStandard/Xen/io/protocols.h>
17 #include <IndustryStandard/Xen/io/xenbus.h>
18
19 /**
20 Helper to read an integer from XenStore.
21
22 If the number overflows according to the range defined by UINT64,
23 then ASSERT().
24
25 @param This A pointer to a XENBUS_PROTOCOL instance.
26 @param Node The XenStore node to read from.
27 @param FromBackend Read frontend or backend value.
28 @param ValuePtr Where to put the value.
29
30 @retval XENSTORE_STATUS_SUCCESS If successful, will update ValuePtr.
31 @return Any other return value indicate the error,
32 ValuePtr is not updated in this case.
33 **/
34 STATIC
35 XENSTORE_STATUS
36 XenBusReadUint64 (
37 IN XENBUS_PROTOCOL *This,
38 IN CONST CHAR8 *Node,
39 IN BOOLEAN FromBackend,
40 OUT UINT64 *ValuePtr
41 )
42 {
43 XENSTORE_STATUS Status;
44 CHAR8 *Ptr;
45
46 if (!FromBackend) {
47 Status = This->XsRead (This, XST_NIL, Node, (VOID**)&Ptr);
48 } else {
49 Status = This->XsBackendRead (This, XST_NIL, Node, (VOID**)&Ptr);
50 }
51 if (Status != XENSTORE_STATUS_SUCCESS) {
52 return Status;
53 }
54 // AsciiStrDecimalToUint64 will ASSERT if Ptr overflow UINT64.
55 *ValuePtr = AsciiStrDecimalToUint64 (Ptr);
56 FreePool (Ptr);
57 return Status;
58 }
59
60 /**
61 Free an instance of XEN_BLOCK_FRONT_DEVICE.
62
63 @param Dev The instance to free.
64 **/
65 STATIC
66 VOID
67 XenPvBlockFree (
68 IN XEN_BLOCK_FRONT_DEVICE *Dev
69 )
70 {
71 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
72
73 if (Dev->RingRef != 0) {
74 XenBusIo->GrantEndAccess (XenBusIo, Dev->RingRef);
75 }
76 if (Dev->Ring.sring != NULL) {
77 FreePages (Dev->Ring.sring, 1);
78 }
79 if (Dev->EventChannel != 0) {
80 XenBusIo->EventChannelClose (XenBusIo, Dev->EventChannel);
81 }
82 FreePool (Dev);
83 }
84
85 /**
86 Wait until until the backend has reached the ExpectedState.
87
88 @param Dev A XEN_BLOCK_FRONT_DEVICE instance.
89 @param ExpectedState The backend state expected.
90 @param LastStatePtr An optional pointer where to right the final state.
91
92 @return Return XENSTORE_STATUS_SUCCESS if the new backend state is ExpectedState
93 or return an error otherwise.
94 **/
95 STATIC
96 XENSTORE_STATUS
97 XenPvBlkWaitForBackendState (
98 IN XEN_BLOCK_FRONT_DEVICE *Dev,
99 IN XenbusState ExpectedState,
100 OUT XenbusState *LastStatePtr OPTIONAL
101 )
102 {
103 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
104 XenbusState State;
105 UINT64 Value;
106 XENSTORE_STATUS Status = XENSTORE_STATUS_SUCCESS;
107
108 while (TRUE) {
109 Status = XenBusReadUint64 (XenBusIo, "state", TRUE, &Value);
110 if (Status != XENSTORE_STATUS_SUCCESS) {
111 return Status;
112 }
113 if (Value > XenbusStateReconfigured) {
114 //
115 // Value is not a State value.
116 //
117 return XENSTORE_STATUS_EIO;
118 }
119 State = Value;
120 if (State == ExpectedState) {
121 break;
122 } else if (State > ExpectedState) {
123 Status = XENSTORE_STATUS_FAIL;
124 break;
125 }
126 DEBUG ((DEBUG_INFO,
127 "XenPvBlk: waiting backend state %d, current: %d\n",
128 ExpectedState, State));
129 XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
130 }
131
132 if (LastStatePtr != NULL) {
133 *LastStatePtr = State;
134 }
135
136 return Status;
137 }
138
139 EFI_STATUS
140 XenPvBlockFrontInitialization (
141 IN XENBUS_PROTOCOL *XenBusIo,
142 IN CONST CHAR8 *NodeName,
143 OUT XEN_BLOCK_FRONT_DEVICE **DevPtr
144 )
145 {
146 XENSTORE_TRANSACTION Transaction;
147 CHAR8 *DeviceType;
148 blkif_sring_t *SharedRing;
149 XENSTORE_STATUS Status;
150 XEN_BLOCK_FRONT_DEVICE *Dev;
151 XenbusState State;
152 UINT64 Value;
153 CHAR8 *Params;
154
155 ASSERT (NodeName != NULL);
156
157 Dev = AllocateZeroPool (sizeof (XEN_BLOCK_FRONT_DEVICE));
158 if (Dev == NULL) {
159 return EFI_OUT_OF_RESOURCES;
160 }
161
162 Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE;
163 Dev->NodeName = NodeName;
164 Dev->XenBusIo = XenBusIo;
165 Dev->DeviceId = XenBusIo->DeviceId;
166
167 XenBusIo->XsRead (XenBusIo, XST_NIL, "device-type", (VOID**)&DeviceType);
168 if (AsciiStrCmp (DeviceType, "cdrom") == 0) {
169 Dev->MediaInfo.CdRom = TRUE;
170 } else {
171 Dev->MediaInfo.CdRom = FALSE;
172 }
173 FreePool (DeviceType);
174
175 if (Dev->MediaInfo.CdRom) {
176 Status = XenBusIo->XsBackendRead (XenBusIo, XST_NIL, "params", (VOID**)&Params);
177 if (Status != XENSTORE_STATUS_SUCCESS) {
178 DEBUG ((DEBUG_ERROR, "%a: Failed to read params (%d)\n", __FUNCTION__, Status));
179 goto Error;
180 }
181 if (AsciiStrLen (Params) == 0 || AsciiStrCmp (Params, "aio:") == 0) {
182 FreePool (Params);
183 DEBUG ((DEBUG_INFO, "%a: Empty cdrom\n", __FUNCTION__));
184 goto Error;
185 }
186 FreePool (Params);
187 }
188
189 Status = XenBusReadUint64 (XenBusIo, "backend-id", FALSE, &Value);
190 if (Status != XENSTORE_STATUS_SUCCESS || Value > MAX_UINT16) {
191 DEBUG ((DEBUG_ERROR, "XenPvBlk: Failed to get backend-id (%d)\n",
192 Status));
193 goto Error;
194 }
195 Dev->DomainId = (domid_t)Value;
196 XenBusIo->EventChannelAllocate (XenBusIo, Dev->DomainId, &Dev->EventChannel);
197
198 SharedRing = (blkif_sring_t*) AllocatePages (1);
199 SHARED_RING_INIT (SharedRing);
200 FRONT_RING_INIT (&Dev->Ring, SharedRing, EFI_PAGE_SIZE);
201 XenBusIo->GrantAccess (XenBusIo,
202 Dev->DomainId,
203 (INTN) SharedRing >> EFI_PAGE_SHIFT,
204 FALSE,
205 &Dev->RingRef);
206
207 Again:
208 Status = XenBusIo->XsTransactionStart (XenBusIo, &Transaction);
209 if (Status != XENSTORE_STATUS_SUCCESS) {
210 DEBUG ((DEBUG_WARN, "XenPvBlk: Failed to start transaction, %d\n", Status));
211 goto Error;
212 }
213
214 Status = XenBusIo->XsPrintf (XenBusIo, &Transaction, NodeName, "ring-ref", "%d",
215 Dev->RingRef);
216 if (Status != XENSTORE_STATUS_SUCCESS) {
217 DEBUG ((DEBUG_ERROR, "XenPvBlk: Failed to write ring-ref.\n"));
218 goto AbortTransaction;
219 }
220 Status = XenBusIo->XsPrintf (XenBusIo, &Transaction, NodeName,
221 "event-channel", "%d", Dev->EventChannel);
222 if (Status != XENSTORE_STATUS_SUCCESS) {
223 DEBUG ((DEBUG_ERROR, "XenPvBlk: Failed to write event-channel.\n"));
224 goto AbortTransaction;
225 }
226 Status = XenBusIo->XsPrintf (XenBusIo, &Transaction, NodeName,
227 "protocol", "%a", XEN_IO_PROTO_ABI_NATIVE);
228 if (Status != XENSTORE_STATUS_SUCCESS) {
229 DEBUG ((DEBUG_ERROR, "XenPvBlk: Failed to write protocol.\n"));
230 goto AbortTransaction;
231 }
232
233 Status = XenBusIo->SetState (XenBusIo, &Transaction, XenbusStateConnected);
234 if (Status != XENSTORE_STATUS_SUCCESS) {
235 DEBUG ((DEBUG_ERROR, "XenPvBlk: Failed to switch state.\n"));
236 goto AbortTransaction;
237 }
238
239 Status = XenBusIo->XsTransactionEnd (XenBusIo, &Transaction, FALSE);
240 if (Status == XENSTORE_STATUS_EAGAIN) {
241 goto Again;
242 }
243
244 XenBusIo->RegisterWatchBackend (XenBusIo, "state", &Dev->StateWatchToken);
245
246 //
247 // Waiting for backend
248 //
249 Status = XenPvBlkWaitForBackendState (Dev, XenbusStateConnected, &State);
250 if (Status != XENSTORE_STATUS_SUCCESS) {
251 DEBUG ((DEBUG_ERROR,
252 "XenPvBlk: backend for %a/%d not available, rc=%d state=%d\n",
253 XenBusIo->Type, XenBusIo->DeviceId, Status, State));
254 goto Error2;
255 }
256
257 Status = XenBusReadUint64 (XenBusIo, "info", TRUE, &Value);
258 if (Status != XENSTORE_STATUS_SUCCESS || Value > MAX_UINT32) {
259 goto Error2;
260 }
261 Dev->MediaInfo.VDiskInfo = (UINT32)Value;
262 if (Dev->MediaInfo.VDiskInfo & VDISK_READONLY) {
263 Dev->MediaInfo.ReadWrite = FALSE;
264 } else {
265 Dev->MediaInfo.ReadWrite = TRUE;
266 }
267
268 Status = XenBusReadUint64 (XenBusIo, "sectors", TRUE, &Dev->MediaInfo.Sectors);
269 if (Status != XENSTORE_STATUS_SUCCESS) {
270 goto Error2;
271 }
272
273 Status = XenBusReadUint64 (XenBusIo, "sector-size", TRUE, &Value);
274 if (Status != XENSTORE_STATUS_SUCCESS || Value > MAX_UINT32) {
275 goto Error2;
276 }
277 if ((UINT32)Value % 512 != 0) {
278 //
279 // This is not supported by the driver.
280 //
281 DEBUG ((DEBUG_ERROR, "XenPvBlk: Unsupported sector-size value %Lu, "
282 "it must be a multiple of 512\n", Value));
283 goto Error2;
284 }
285 Dev->MediaInfo.SectorSize = (UINT32)Value;
286
287 // Default value
288 Value = 0;
289 XenBusReadUint64 (XenBusIo, "feature-barrier", TRUE, &Value);
290 if (Value == 1) {
291 Dev->MediaInfo.FeatureBarrier = TRUE;
292 } else {
293 Dev->MediaInfo.FeatureBarrier = FALSE;
294 }
295
296 // Default value
297 Value = 0;
298 XenBusReadUint64 (XenBusIo, "feature-flush-cache", TRUE, &Value);
299 if (Value == 1) {
300 Dev->MediaInfo.FeatureFlushCache = TRUE;
301 } else {
302 Dev->MediaInfo.FeatureFlushCache = FALSE;
303 }
304
305 DEBUG ((DEBUG_INFO, "XenPvBlk: New disk with %ld sectors of %d bytes\n",
306 Dev->MediaInfo.Sectors, Dev->MediaInfo.SectorSize));
307
308 *DevPtr = Dev;
309 return EFI_SUCCESS;
310
311 Error2:
312 XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
313 XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
314 XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
315 XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
316 goto Error;
317 AbortTransaction:
318 XenBusIo->XsTransactionEnd (XenBusIo, &Transaction, TRUE);
319 Error:
320 XenPvBlockFree (Dev);
321 return EFI_DEVICE_ERROR;
322 }
323
324 VOID
325 XenPvBlockFrontShutdown (
326 IN XEN_BLOCK_FRONT_DEVICE *Dev
327 )
328 {
329 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
330 XENSTORE_STATUS Status;
331 UINT64 Value;
332
333 XenPvBlockSync (Dev);
334
335 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosing);
336 if (Status != XENSTORE_STATUS_SUCCESS) {
337 DEBUG ((DEBUG_ERROR,
338 "XenPvBlk: error while changing state to Closing: %d\n",
339 Status));
340 goto Close;
341 }
342
343 Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosing, NULL);
344 if (Status != XENSTORE_STATUS_SUCCESS) {
345 DEBUG ((DEBUG_ERROR,
346 "XenPvBlk: error while waiting for closing backend state: %d\n",
347 Status));
348 goto Close;
349 }
350
351 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosed);
352 if (Status != XENSTORE_STATUS_SUCCESS) {
353 DEBUG ((DEBUG_ERROR,
354 "XenPvBlk: error while changing state to Closed: %d\n",
355 Status));
356 goto Close;
357 }
358
359 Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosed, NULL);
360 if (Status != XENSTORE_STATUS_SUCCESS) {
361 DEBUG ((DEBUG_ERROR,
362 "XenPvBlk: error while waiting for closed backend state: %d\n",
363 Status));
364 goto Close;
365 }
366
367 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateInitialising);
368 if (Status != XENSTORE_STATUS_SUCCESS) {
369 DEBUG ((DEBUG_ERROR,
370 "XenPvBlk: error while changing state to initialising: %d\n",
371 Status));
372 goto Close;
373 }
374
375 while (TRUE) {
376 Status = XenBusReadUint64 (XenBusIo, "state", TRUE, &Value);
377 if (Status != XENSTORE_STATUS_SUCCESS) {
378 DEBUG ((DEBUG_ERROR,
379 "XenPvBlk: error while waiting for new backend state: %d\n",
380 Status));
381 goto Close;
382 }
383 if (Value <= XenbusStateInitWait || Value >= XenbusStateClosed) {
384 break;
385 }
386 DEBUG ((DEBUG_INFO,
387 "XenPvBlk: waiting backend state %d, current: %Lu\n",
388 XenbusStateInitWait, Value));
389 XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
390 }
391
392 Close:
393 XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
394 XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
395 XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
396 XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
397
398 XenPvBlockFree (Dev);
399 }
400
401 STATIC
402 VOID
403 XenPvBlockWaitSlot (
404 IN XEN_BLOCK_FRONT_DEVICE *Dev
405 )
406 {
407 /* Wait for a slot */
408 if (RING_FULL (&Dev->Ring)) {
409 while (TRUE) {
410 XenPvBlockAsyncIoPoll (Dev);
411 if (!RING_FULL (&Dev->Ring)) {
412 break;
413 }
414 /* Really no slot, could wait for an event on Dev->EventChannel. */
415 }
416 }
417 }
418
419 VOID
420 XenPvBlockAsyncIo (
421 IN OUT XEN_BLOCK_FRONT_IO *IoData,
422 IN BOOLEAN IsWrite
423 )
424 {
425 XEN_BLOCK_FRONT_DEVICE *Dev = IoData->Dev;
426 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
427 blkif_request_t *Request;
428 RING_IDX RingIndex;
429 BOOLEAN Notify;
430 INT32 NumSegments, Index;
431 UINTN Start, End;
432
433 // Can't io at non-sector-aligned location
434 ASSERT(!(IoData->Sector & ((Dev->MediaInfo.SectorSize / 512) - 1)));
435 // Can't io non-sector-sized amounts
436 ASSERT(!(IoData->Size & (Dev->MediaInfo.SectorSize - 1)));
437 // Can't io non-sector-aligned buffer
438 ASSERT(!((UINTN) IoData->Buffer & (Dev->MediaInfo.SectorSize - 1)));
439
440 Start = (UINTN) IoData->Buffer & ~EFI_PAGE_MASK;
441 End = ((UINTN) IoData->Buffer + IoData->Size + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK;
442 IoData->NumRef = NumSegments = (INT32)((End - Start) / EFI_PAGE_SIZE);
443
444 ASSERT (NumSegments <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
445
446 XenPvBlockWaitSlot (Dev);
447 RingIndex = Dev->Ring.req_prod_pvt;
448 Request = RING_GET_REQUEST (&Dev->Ring, RingIndex);
449
450 Request->operation = IsWrite ? BLKIF_OP_WRITE : BLKIF_OP_READ;
451 Request->nr_segments = (UINT8)NumSegments;
452 Request->handle = Dev->DeviceId;
453 Request->id = (UINTN) IoData;
454 Request->sector_number = IoData->Sector;
455
456 for (Index = 0; Index < NumSegments; Index++) {
457 Request->seg[Index].first_sect = 0;
458 Request->seg[Index].last_sect = EFI_PAGE_SIZE / 512 - 1;
459 }
460 Request->seg[0].first_sect = (UINT8)(((UINTN) IoData->Buffer & EFI_PAGE_MASK) / 512);
461 Request->seg[NumSegments - 1].last_sect =
462 (UINT8)((((UINTN) IoData->Buffer + IoData->Size - 1) & EFI_PAGE_MASK) / 512);
463 for (Index = 0; Index < NumSegments; Index++) {
464 UINTN Data = Start + Index * EFI_PAGE_SIZE;
465 XenBusIo->GrantAccess (XenBusIo, Dev->DomainId,
466 Data >> EFI_PAGE_SHIFT, IsWrite,
467 &Request->seg[Index].gref);
468 IoData->GrantRef[Index] = Request->seg[Index].gref;
469 }
470
471 Dev->Ring.req_prod_pvt = RingIndex + 1;
472
473 MemoryFence ();
474 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
475
476 if (Notify) {
477 UINT32 ReturnCode;
478 ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
479 if (ReturnCode != 0) {
480 DEBUG ((DEBUG_ERROR,
481 "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
482 ReturnCode));
483 }
484 }
485 }
486
487 EFI_STATUS
488 XenPvBlockIo (
489 IN OUT XEN_BLOCK_FRONT_IO *IoData,
490 IN BOOLEAN IsWrite
491 )
492 {
493 //
494 // Status value that correspond to an IO in progress.
495 //
496 IoData->Status = EFI_ALREADY_STARTED;
497 XenPvBlockAsyncIo (IoData, IsWrite);
498
499 while (IoData->Status == EFI_ALREADY_STARTED) {
500 XenPvBlockAsyncIoPoll (IoData->Dev);
501 }
502
503 return IoData->Status;
504 }
505
506 STATIC
507 VOID
508 XenPvBlockPushOperation (
509 IN XEN_BLOCK_FRONT_DEVICE *Dev,
510 IN UINT8 Operation,
511 IN UINT64 Id
512 )
513 {
514 INT32 Index;
515 blkif_request_t *Request;
516 BOOLEAN Notify;
517
518 XenPvBlockWaitSlot (Dev);
519 Index = Dev->Ring.req_prod_pvt;
520 Request = RING_GET_REQUEST(&Dev->Ring, Index);
521 Request->operation = Operation;
522 Request->nr_segments = 0;
523 Request->handle = Dev->DeviceId;
524 Request->id = Id;
525 /* Not needed anyway, but the backend will check it */
526 Request->sector_number = 0;
527 Dev->Ring.req_prod_pvt = Index + 1;
528 MemoryFence ();
529 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
530 if (Notify) {
531 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
532 UINT32 ReturnCode;
533 ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
534 if (ReturnCode != 0) {
535 DEBUG ((DEBUG_ERROR,
536 "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
537 ReturnCode));
538 }
539 }
540 }
541
542 VOID
543 XenPvBlockSync (
544 IN XEN_BLOCK_FRONT_DEVICE *Dev
545 )
546 {
547 if (Dev->MediaInfo.ReadWrite) {
548 if (Dev->MediaInfo.FeatureBarrier) {
549 XenPvBlockPushOperation (Dev, BLKIF_OP_WRITE_BARRIER, 0);
550 }
551
552 if (Dev->MediaInfo.FeatureFlushCache) {
553 XenPvBlockPushOperation (Dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
554 }
555 }
556
557 /* Note: This won't finish if another thread enqueues requests. */
558 while (TRUE) {
559 XenPvBlockAsyncIoPoll (Dev);
560 if (RING_FREE_REQUESTS (&Dev->Ring) == RING_SIZE (&Dev->Ring)) {
561 break;
562 }
563 }
564 }
565
566 VOID
567 XenPvBlockAsyncIoPoll (
568 IN XEN_BLOCK_FRONT_DEVICE *Dev
569 )
570 {
571 RING_IDX ProducerIndex, ConsumerIndex;
572 blkif_response_t *Response;
573 INT32 More;
574
575 do {
576 ProducerIndex = Dev->Ring.sring->rsp_prod;
577 /* Ensure we see queued responses up to 'ProducerIndex'. */
578 MemoryFence ();
579 ConsumerIndex = Dev->Ring.rsp_cons;
580
581 while (ConsumerIndex != ProducerIndex) {
582 XEN_BLOCK_FRONT_IO *IoData = NULL;
583 INT16 Status;
584
585 Response = RING_GET_RESPONSE (&Dev->Ring, ConsumerIndex);
586
587 IoData = (VOID *) (UINTN) Response->id;
588 Status = Response->status;
589
590 switch (Response->operation) {
591 case BLKIF_OP_READ:
592 case BLKIF_OP_WRITE:
593 {
594 INT32 Index;
595
596 if (Status != BLKIF_RSP_OKAY) {
597 DEBUG ((DEBUG_ERROR,
598 "XenPvBlk: "
599 "%a error %d on %a at sector %Lx, num bytes %Lx\n",
600 Response->operation == BLKIF_OP_READ ? "read" : "write",
601 Status, IoData->Dev->NodeName,
602 (UINT64)IoData->Sector,
603 (UINT64)IoData->Size));
604 }
605
606 for (Index = 0; Index < IoData->NumRef; Index++) {
607 Dev->XenBusIo->GrantEndAccess (Dev->XenBusIo, IoData->GrantRef[Index]);
608 }
609
610 break;
611 }
612
613 case BLKIF_OP_WRITE_BARRIER:
614 if (Status != BLKIF_RSP_OKAY) {
615 DEBUG ((DEBUG_ERROR, "XenPvBlk: write barrier error %d\n", Status));
616 }
617 break;
618 case BLKIF_OP_FLUSH_DISKCACHE:
619 if (Status != BLKIF_RSP_OKAY) {
620 DEBUG ((DEBUG_ERROR, "XenPvBlk: flush error %d\n", Status));
621 }
622 break;
623
624 default:
625 DEBUG ((DEBUG_ERROR,
626 "XenPvBlk: unrecognized block operation %d response (status %d)\n",
627 Response->operation, Status));
628 break;
629 }
630
631 Dev->Ring.rsp_cons = ++ConsumerIndex;
632 if (IoData != NULL) {
633 IoData->Status = Status ? EFI_DEVICE_ERROR : EFI_SUCCESS;
634 }
635 if (Dev->Ring.rsp_cons != ConsumerIndex) {
636 /* We reentered, we must not continue here */
637 break;
638 }
639 }
640
641 RING_FINAL_CHECK_FOR_RESPONSES (&Dev->Ring, More);
642 } while (More != 0);
643 }