]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenPvBlkDxe/BlockFront.c
OvmfPkg/Csm/LegacyBiosDxe: Fix Legacy16GetTableAddress call for E820 data
[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 succefull, 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 ((EFI_D_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 Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE;
159 Dev->NodeName = NodeName;
160 Dev->XenBusIo = XenBusIo;
161 Dev->DeviceId = XenBusIo->DeviceId;
162
163 XenBusIo->XsRead (XenBusIo, XST_NIL, "device-type", (VOID**)&DeviceType);
164 if (AsciiStrCmp (DeviceType, "cdrom") == 0) {
165 Dev->MediaInfo.CdRom = TRUE;
166 } else {
167 Dev->MediaInfo.CdRom = FALSE;
168 }
169 FreePool (DeviceType);
170
171 if (Dev->MediaInfo.CdRom) {
172 Status = XenBusIo->XsBackendRead (XenBusIo, XST_NIL, "params", (VOID**)&Params);
173 if (Status != XENSTORE_STATUS_SUCCESS) {
174 DEBUG ((EFI_D_ERROR, "%a: Failed to read params (%d)\n", __FUNCTION__, Status));
175 goto Error;
176 }
177 if (AsciiStrLen (Params) == 0 || AsciiStrCmp (Params, "aio:") == 0) {
178 FreePool (Params);
179 DEBUG ((EFI_D_INFO, "%a: Empty cdrom\n", __FUNCTION__));
180 goto Error;
181 }
182 FreePool (Params);
183 }
184
185 Status = XenBusReadUint64 (XenBusIo, "backend-id", FALSE, &Value);
186 if (Status != XENSTORE_STATUS_SUCCESS || Value > MAX_UINT16) {
187 DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to get backend-id (%d)\n",
188 Status));
189 goto Error;
190 }
191 Dev->DomainId = (domid_t)Value;
192 XenBusIo->EventChannelAllocate (XenBusIo, Dev->DomainId, &Dev->EventChannel);
193
194 SharedRing = (blkif_sring_t*) AllocatePages (1);
195 SHARED_RING_INIT (SharedRing);
196 FRONT_RING_INIT (&Dev->Ring, SharedRing, EFI_PAGE_SIZE);
197 XenBusIo->GrantAccess (XenBusIo,
198 Dev->DomainId,
199 (INTN) SharedRing >> EFI_PAGE_SHIFT,
200 FALSE,
201 &Dev->RingRef);
202
203 Again:
204 Status = XenBusIo->XsTransactionStart (XenBusIo, &Transaction);
205 if (Status != XENSTORE_STATUS_SUCCESS) {
206 DEBUG ((EFI_D_WARN, "XenPvBlk: Failed to start transaction, %d\n", Status));
207 goto Error;
208 }
209
210 Status = XenBusIo->XsPrintf (XenBusIo, &Transaction, NodeName, "ring-ref", "%d",
211 Dev->RingRef);
212 if (Status != XENSTORE_STATUS_SUCCESS) {
213 DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write ring-ref.\n"));
214 goto AbortTransaction;
215 }
216 Status = XenBusIo->XsPrintf (XenBusIo, &Transaction, NodeName,
217 "event-channel", "%d", Dev->EventChannel);
218 if (Status != XENSTORE_STATUS_SUCCESS) {
219 DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write event-channel.\n"));
220 goto AbortTransaction;
221 }
222 Status = XenBusIo->XsPrintf (XenBusIo, &Transaction, NodeName,
223 "protocol", "%a", XEN_IO_PROTO_ABI_NATIVE);
224 if (Status != XENSTORE_STATUS_SUCCESS) {
225 DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write protocol.\n"));
226 goto AbortTransaction;
227 }
228
229 Status = XenBusIo->SetState (XenBusIo, &Transaction, XenbusStateConnected);
230 if (Status != XENSTORE_STATUS_SUCCESS) {
231 DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to switch state.\n"));
232 goto AbortTransaction;
233 }
234
235 Status = XenBusIo->XsTransactionEnd (XenBusIo, &Transaction, FALSE);
236 if (Status == XENSTORE_STATUS_EAGAIN) {
237 goto Again;
238 }
239
240 XenBusIo->RegisterWatchBackend (XenBusIo, "state", &Dev->StateWatchToken);
241
242 //
243 // Waiting for backend
244 //
245 Status = XenPvBlkWaitForBackendState (Dev, XenbusStateConnected, &State);
246 if (Status != XENSTORE_STATUS_SUCCESS) {
247 DEBUG ((EFI_D_ERROR,
248 "XenPvBlk: backend for %a/%d not available, rc=%d state=%d\n",
249 XenBusIo->Type, XenBusIo->DeviceId, Status, State));
250 goto Error2;
251 }
252
253 Status = XenBusReadUint64 (XenBusIo, "info", TRUE, &Value);
254 if (Status != XENSTORE_STATUS_SUCCESS || Value > MAX_UINT32) {
255 goto Error2;
256 }
257 Dev->MediaInfo.VDiskInfo = (UINT32)Value;
258 if (Dev->MediaInfo.VDiskInfo & VDISK_READONLY) {
259 Dev->MediaInfo.ReadWrite = FALSE;
260 } else {
261 Dev->MediaInfo.ReadWrite = TRUE;
262 }
263
264 Status = XenBusReadUint64 (XenBusIo, "sectors", TRUE, &Dev->MediaInfo.Sectors);
265 if (Status != XENSTORE_STATUS_SUCCESS) {
266 goto Error2;
267 }
268
269 Status = XenBusReadUint64 (XenBusIo, "sector-size", TRUE, &Value);
270 if (Status != XENSTORE_STATUS_SUCCESS || Value > MAX_UINT32) {
271 goto Error2;
272 }
273 if ((UINT32)Value % 512 != 0) {
274 //
275 // This is not supported by the driver.
276 //
277 DEBUG ((EFI_D_ERROR, "XenPvBlk: Unsupported sector-size value %Lu, "
278 "it must be a multiple of 512\n", Value));
279 goto Error2;
280 }
281 Dev->MediaInfo.SectorSize = (UINT32)Value;
282
283 // Default value
284 Value = 0;
285 XenBusReadUint64 (XenBusIo, "feature-barrier", TRUE, &Value);
286 if (Value == 1) {
287 Dev->MediaInfo.FeatureBarrier = TRUE;
288 } else {
289 Dev->MediaInfo.FeatureBarrier = FALSE;
290 }
291
292 // Default value
293 Value = 0;
294 XenBusReadUint64 (XenBusIo, "feature-flush-cache", TRUE, &Value);
295 if (Value == 1) {
296 Dev->MediaInfo.FeatureFlushCache = TRUE;
297 } else {
298 Dev->MediaInfo.FeatureFlushCache = FALSE;
299 }
300
301 DEBUG ((EFI_D_INFO, "XenPvBlk: New disk with %ld sectors of %d bytes\n",
302 Dev->MediaInfo.Sectors, Dev->MediaInfo.SectorSize));
303
304 *DevPtr = Dev;
305 return EFI_SUCCESS;
306
307 Error2:
308 XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
309 XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
310 XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
311 XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
312 goto Error;
313 AbortTransaction:
314 XenBusIo->XsTransactionEnd (XenBusIo, &Transaction, TRUE);
315 Error:
316 XenPvBlockFree (Dev);
317 return EFI_DEVICE_ERROR;
318 }
319
320 VOID
321 XenPvBlockFrontShutdown (
322 IN XEN_BLOCK_FRONT_DEVICE *Dev
323 )
324 {
325 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
326 XENSTORE_STATUS Status;
327 UINT64 Value;
328
329 XenPvBlockSync (Dev);
330
331 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosing);
332 if (Status != XENSTORE_STATUS_SUCCESS) {
333 DEBUG ((EFI_D_ERROR,
334 "XenPvBlk: error while changing state to Closing: %d\n",
335 Status));
336 goto Close;
337 }
338
339 Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosing, NULL);
340 if (Status != XENSTORE_STATUS_SUCCESS) {
341 DEBUG ((EFI_D_ERROR,
342 "XenPvBlk: error while waiting for closing backend state: %d\n",
343 Status));
344 goto Close;
345 }
346
347 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosed);
348 if (Status != XENSTORE_STATUS_SUCCESS) {
349 DEBUG ((EFI_D_ERROR,
350 "XenPvBlk: error while changing state to Closed: %d\n",
351 Status));
352 goto Close;
353 }
354
355 Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosed, NULL);
356 if (Status != XENSTORE_STATUS_SUCCESS) {
357 DEBUG ((EFI_D_ERROR,
358 "XenPvBlk: error while waiting for closed backend state: %d\n",
359 Status));
360 goto Close;
361 }
362
363 Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateInitialising);
364 if (Status != XENSTORE_STATUS_SUCCESS) {
365 DEBUG ((EFI_D_ERROR,
366 "XenPvBlk: error while changing state to initialising: %d\n",
367 Status));
368 goto Close;
369 }
370
371 while (TRUE) {
372 Status = XenBusReadUint64 (XenBusIo, "state", TRUE, &Value);
373 if (Status != XENSTORE_STATUS_SUCCESS) {
374 DEBUG ((EFI_D_ERROR,
375 "XenPvBlk: error while waiting for new backend state: %d\n",
376 Status));
377 goto Close;
378 }
379 if (Value <= XenbusStateInitWait || Value >= XenbusStateClosed) {
380 break;
381 }
382 DEBUG ((EFI_D_INFO,
383 "XenPvBlk: waiting backend state %d, current: %Lu\n",
384 XenbusStateInitWait, Value));
385 XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
386 }
387
388 Close:
389 XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
390 XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
391 XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
392 XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
393
394 XenPvBlockFree (Dev);
395 }
396
397 STATIC
398 VOID
399 XenPvBlockWaitSlot (
400 IN XEN_BLOCK_FRONT_DEVICE *Dev
401 )
402 {
403 /* Wait for a slot */
404 if (RING_FULL (&Dev->Ring)) {
405 while (TRUE) {
406 XenPvBlockAsyncIoPoll (Dev);
407 if (!RING_FULL (&Dev->Ring)) {
408 break;
409 }
410 /* Really no slot, could wait for an event on Dev->EventChannel. */
411 }
412 }
413 }
414
415 VOID
416 XenPvBlockAsyncIo (
417 IN OUT XEN_BLOCK_FRONT_IO *IoData,
418 IN BOOLEAN IsWrite
419 )
420 {
421 XEN_BLOCK_FRONT_DEVICE *Dev = IoData->Dev;
422 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
423 blkif_request_t *Request;
424 RING_IDX RingIndex;
425 BOOLEAN Notify;
426 INT32 NumSegments, Index;
427 UINTN Start, End;
428
429 // Can't io at non-sector-aligned location
430 ASSERT(!(IoData->Sector & ((Dev->MediaInfo.SectorSize / 512) - 1)));
431 // Can't io non-sector-sized amounts
432 ASSERT(!(IoData->Size & (Dev->MediaInfo.SectorSize - 1)));
433 // Can't io non-sector-aligned buffer
434 ASSERT(!((UINTN) IoData->Buffer & (Dev->MediaInfo.SectorSize - 1)));
435
436 Start = (UINTN) IoData->Buffer & ~EFI_PAGE_MASK;
437 End = ((UINTN) IoData->Buffer + IoData->Size + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK;
438 IoData->NumRef = NumSegments = (INT32)((End - Start) / EFI_PAGE_SIZE);
439
440 ASSERT (NumSegments <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
441
442 XenPvBlockWaitSlot (Dev);
443 RingIndex = Dev->Ring.req_prod_pvt;
444 Request = RING_GET_REQUEST (&Dev->Ring, RingIndex);
445
446 Request->operation = IsWrite ? BLKIF_OP_WRITE : BLKIF_OP_READ;
447 Request->nr_segments = (UINT8)NumSegments;
448 Request->handle = Dev->DeviceId;
449 Request->id = (UINTN) IoData;
450 Request->sector_number = IoData->Sector;
451
452 for (Index = 0; Index < NumSegments; Index++) {
453 Request->seg[Index].first_sect = 0;
454 Request->seg[Index].last_sect = EFI_PAGE_SIZE / 512 - 1;
455 }
456 Request->seg[0].first_sect = (UINT8)(((UINTN) IoData->Buffer & EFI_PAGE_MASK) / 512);
457 Request->seg[NumSegments - 1].last_sect =
458 (UINT8)((((UINTN) IoData->Buffer + IoData->Size - 1) & EFI_PAGE_MASK) / 512);
459 for (Index = 0; Index < NumSegments; Index++) {
460 UINTN Data = Start + Index * EFI_PAGE_SIZE;
461 XenBusIo->GrantAccess (XenBusIo, Dev->DomainId,
462 Data >> EFI_PAGE_SHIFT, IsWrite,
463 &Request->seg[Index].gref);
464 IoData->GrantRef[Index] = Request->seg[Index].gref;
465 }
466
467 Dev->Ring.req_prod_pvt = RingIndex + 1;
468
469 MemoryFence ();
470 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
471
472 if (Notify) {
473 UINT32 ReturnCode;
474 ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
475 if (ReturnCode != 0) {
476 DEBUG ((EFI_D_ERROR,
477 "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
478 ReturnCode));
479 }
480 }
481 }
482
483 EFI_STATUS
484 XenPvBlockIo (
485 IN OUT XEN_BLOCK_FRONT_IO *IoData,
486 IN BOOLEAN IsWrite
487 )
488 {
489 //
490 // Status value that correspond to an IO in progress.
491 //
492 IoData->Status = EFI_ALREADY_STARTED;
493 XenPvBlockAsyncIo (IoData, IsWrite);
494
495 while (IoData->Status == EFI_ALREADY_STARTED) {
496 XenPvBlockAsyncIoPoll (IoData->Dev);
497 }
498
499 return IoData->Status;
500 }
501
502 STATIC
503 VOID
504 XenPvBlockPushOperation (
505 IN XEN_BLOCK_FRONT_DEVICE *Dev,
506 IN UINT8 Operation,
507 IN UINT64 Id
508 )
509 {
510 INT32 Index;
511 blkif_request_t *Request;
512 BOOLEAN Notify;
513
514 XenPvBlockWaitSlot (Dev);
515 Index = Dev->Ring.req_prod_pvt;
516 Request = RING_GET_REQUEST(&Dev->Ring, Index);
517 Request->operation = Operation;
518 Request->nr_segments = 0;
519 Request->handle = Dev->DeviceId;
520 Request->id = Id;
521 /* Not needed anyway, but the backend will check it */
522 Request->sector_number = 0;
523 Dev->Ring.req_prod_pvt = Index + 1;
524 MemoryFence ();
525 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
526 if (Notify) {
527 XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
528 UINT32 ReturnCode;
529 ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
530 if (ReturnCode != 0) {
531 DEBUG ((EFI_D_ERROR,
532 "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
533 ReturnCode));
534 }
535 }
536 }
537
538 VOID
539 XenPvBlockSync (
540 IN XEN_BLOCK_FRONT_DEVICE *Dev
541 )
542 {
543 if (Dev->MediaInfo.ReadWrite) {
544 if (Dev->MediaInfo.FeatureBarrier) {
545 XenPvBlockPushOperation (Dev, BLKIF_OP_WRITE_BARRIER, 0);
546 }
547
548 if (Dev->MediaInfo.FeatureFlushCache) {
549 XenPvBlockPushOperation (Dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
550 }
551 }
552
553 /* Note: This won't finish if another thread enqueues requests. */
554 while (TRUE) {
555 XenPvBlockAsyncIoPoll (Dev);
556 if (RING_FREE_REQUESTS (&Dev->Ring) == RING_SIZE (&Dev->Ring)) {
557 break;
558 }
559 }
560 }
561
562 VOID
563 XenPvBlockAsyncIoPoll (
564 IN XEN_BLOCK_FRONT_DEVICE *Dev
565 )
566 {
567 RING_IDX ProducerIndex, ConsumerIndex;
568 blkif_response_t *Response;
569 INT32 More;
570
571 do {
572 ProducerIndex = Dev->Ring.sring->rsp_prod;
573 /* Ensure we see queued responses up to 'ProducerIndex'. */
574 MemoryFence ();
575 ConsumerIndex = Dev->Ring.rsp_cons;
576
577 while (ConsumerIndex != ProducerIndex) {
578 XEN_BLOCK_FRONT_IO *IoData = NULL;
579 INT16 Status;
580
581 Response = RING_GET_RESPONSE (&Dev->Ring, ConsumerIndex);
582
583 IoData = (VOID *) (UINTN) Response->id;
584 Status = Response->status;
585
586 switch (Response->operation) {
587 case BLKIF_OP_READ:
588 case BLKIF_OP_WRITE:
589 {
590 INT32 Index;
591
592 if (Status != BLKIF_RSP_OKAY) {
593 DEBUG ((EFI_D_ERROR,
594 "XenPvBlk: "
595 "%a error %d on %a at sector %Lx, num bytes %Lx\n",
596 Response->operation == BLKIF_OP_READ ? "read" : "write",
597 Status, IoData->Dev->NodeName,
598 (UINT64)IoData->Sector,
599 (UINT64)IoData->Size));
600 }
601
602 for (Index = 0; Index < IoData->NumRef; Index++) {
603 Dev->XenBusIo->GrantEndAccess (Dev->XenBusIo, IoData->GrantRef[Index]);
604 }
605
606 break;
607 }
608
609 case BLKIF_OP_WRITE_BARRIER:
610 if (Status != BLKIF_RSP_OKAY) {
611 DEBUG ((EFI_D_ERROR, "XenPvBlk: write barrier error %d\n", Status));
612 }
613 break;
614 case BLKIF_OP_FLUSH_DISKCACHE:
615 if (Status != BLKIF_RSP_OKAY) {
616 DEBUG ((EFI_D_ERROR, "XenPvBlk: flush error %d\n", Status));
617 }
618 break;
619
620 default:
621 DEBUG ((EFI_D_ERROR,
622 "XenPvBlk: unrecognized block operation %d response (status %d)\n",
623 Response->operation, Status));
624 break;
625 }
626
627 Dev->Ring.rsp_cons = ++ConsumerIndex;
628 if (IoData != NULL) {
629 IoData->Status = Status ? EFI_DEVICE_ERROR : EFI_SUCCESS;
630 }
631 if (Dev->Ring.rsp_cons != ConsumerIndex) {
632 /* We reentered, we must not continue here */
633 break;
634 }
635 }
636
637 RING_FINAL_CHECK_FOR_RESPONSES (&Dev->Ring, More);
638 } while (More != 0);
639 }