add in DeviceIoToPciRootBridgeIoThunk.
[people/mcb30/edk2.git] / edk2 / EdkCompatibilityPkg / Compatibility / DeviceIoToPciRootBridgeIoThunk / DeviceIoToPciRootBridgeIoThunk.c
1 /** @file\r
2 Module Layer Device I/O on top of PCI Root Bridge I/O (Segment 0)\r
3 \r
4 Device I/O is on list of deprecated protocols for UEFI 2.0 and later.\r
5 This module module layers Device I/O on top of PCI Root Bridge I/O (Segment 0)\r
6  Use if:\r
7    There are no R8.x modules present that produces Device I/O\r
8    EFI drivers included that consume Device I/O\r
9    Platform required to support EFI drivers that consume Device I/O\r
10    Platform required to support EFI applications that consume Device I/O\r
11 \r
12 Copyright (c) 2008 Intel Corporation. <BR>\r
13 All rights reserved. This program and the accompanying materials\r
14 are licensed and made available under the terms and conditions of the BSD License\r
15 which accompanies this distribution.  The full text of the license may be found at\r
16 http://opensource.org/licenses/bsd-license.php\r
17 \r
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20 \r
21 **/\r
22 \r
23 #include <PiDxe.h>\r
24 #include <IndustryStandard/Pci22.h>\r
25 #include <Protocol/DeviceIo.h>\r
26 #include <Protocol/PciRootBridgeIo.h>\r
27 #include <Library/BaseLib.h>\r
28 #include <Library/BaseMemoryLib.h>\r
29 #include <Library/DebugLib.h>\r
30 #include <Library/UefiBootServicesTableLib.h>\r
31 #include <Library/UefiDriverEntryPoint.h>\r
32 #include <Library/UefiLib.h>\r
33 #include <Library/MemoryAllocationLib.h>\r
34 #include <Library/DevicePathLib.h>\r
35 \r
36 \r
37 /**\r
38   Perform reading memory mapped I/O space of device.\r
39 \r
40   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
41   @param  Width                  Width of I/O operations.\r
42   @param  Address                The base address of I/O operations.\r
43   @param  Count                  The number of I/O operations to perform.  Bytes\r
44                                  moves is Width size * Count, starting at Address.\r
45   @param  Buffer                 The destination buffer to store results.\r
46 \r
47   @retval EFI_SUCCESS            The data was read from the device.\r
48   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
49   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
50                                  resources.\r
51 \r
52 **/\r
53 EFI_STATUS\r
54 EFIAPI\r
55 DeviceIoMemRead (\r
56   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
57   IN     EFI_IO_WIDTH             Width,\r
58   IN     UINT64                   Address,\r
59   IN     UINTN                    Count,\r
60   IN OUT VOID                     *Buffer\r
61   )\r
62 ;\r
63 \r
64 \r
65 /**\r
66   Perform writing memory mapped I/O space of device.\r
67 \r
68   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
69   @param  Width                  Width of I/O operations.\r
70   @param  Address                The base address of I/O operations.\r
71   @param  Count                  The number of I/O operations to perform.  Bytes\r
72                                  moves is Width size * Count, starting at Address.\r
73   @param  Buffer                 The source buffer of data to be written.\r
74 \r
75   @retval EFI_SUCCESS            The data was written to the device.\r
76   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
77   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
78                                  resources.\r
79 \r
80 **/\r
81 EFI_STATUS\r
82 EFIAPI\r
83 DeviceIoMemWrite (\r
84   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
85   IN     EFI_IO_WIDTH              Width,\r
86   IN     UINT64                    Address,\r
87   IN     UINTN                     Count,\r
88   IN OUT VOID                      *Buffer\r
89   )\r
90 ;\r
91 \r
92 /**\r
93   Perform reading I/O space of device.\r
94 \r
95   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
96   @param  Width                  Width of I/O operations.\r
97   @param  Address                The base address of I/O operations.\r
98   @param  Count                  The number of I/O operations to perform.  Bytes\r
99                                  moves is Width size * Count, starting at Address.\r
100   @param  Buffer                 The destination buffer to store results.\r
101 \r
102   @retval EFI_SUCCESS            The data was read from the device.\r
103   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
104   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
105                                  resources.\r
106 \r
107 **/\r
108 EFI_STATUS\r
109 EFIAPI\r
110 DeviceIoIoRead (\r
111   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
112   IN     EFI_IO_WIDTH             Width,\r
113   IN     UINT64                   Address,\r
114   IN     UINTN                    Count,\r
115   IN OUT VOID                     *Buffer\r
116   )\r
117 ;\r
118 \r
119 /**\r
120   Perform writing I/O space of device.\r
121 \r
122   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
123   @param  Width                  Width of I/O operations.\r
124   @param  Address                The base address of I/O operations.\r
125   @param  Count                  The number of I/O operations to perform.  Bytes\r
126                                  moves is Width size * Count, starting at Address.\r
127   @param  Buffer                 The source buffer of data to be written.\r
128 \r
129   @retval EFI_SUCCESS            The data was written to the device.\r
130   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
131   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
132                                  resources.\r
133 \r
134 **/\r
135 EFI_STATUS\r
136 EFIAPI\r
137 DeviceIoIoWrite (\r
138   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
139   IN     EFI_IO_WIDTH              Width,\r
140   IN     UINT64                    Address,\r
141   IN     UINTN                     Count,\r
142   IN OUT VOID                      *Buffer\r
143   )\r
144 ;\r
145 \r
146 /**\r
147   Perform reading PCI configuration space of device\r
148 \r
149   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
150   @param  Width                  Width of I/O operations.\r
151   @param  Address                The base address of I/O operations.\r
152   @param  Count                  The number of I/O operations to perform.  Bytes\r
153                                  moves is Width size * Count, starting at Address.\r
154   @param  Buffer                 The destination buffer to store results.\r
155 \r
156   @retval EFI_SUCCESS            The data was read from the device.\r
157   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
158   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
159                                  resources.\r
160 \r
161 **/\r
162 EFI_STATUS\r
163 EFIAPI\r
164 DeviceIoPciRead (\r
165   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
166   IN     EFI_IO_WIDTH             Width,\r
167   IN     UINT64                   Address,\r
168   IN     UINTN                    Count,\r
169   IN OUT VOID                     *Buffer\r
170   )\r
171 ;\r
172 \r
173 /**\r
174   Perform writing PCI configuration space of device.\r
175 \r
176   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
177   @param  Width                  Width of I/O operations.\r
178   @param  Address                The base address of I/O operations.\r
179   @param  Count                  The number of I/O operations to perform.  Bytes\r
180                                  moves is Width size * Count, starting at Address.\r
181   @param  Buffer                 The source buffer of data to be written.\r
182 \r
183   @retval EFI_SUCCESS            The data was written to the device.\r
184   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
185   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
186                                  resources.\r
187 \r
188 **/\r
189 EFI_STATUS\r
190 EFIAPI\r
191 DeviceIoPciWrite (\r
192   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
193   IN     EFI_IO_WIDTH              Width,\r
194   IN     UINT64                    Address,\r
195   IN     UINTN                     Count,\r
196   IN OUT VOID                      *Buffer\r
197   )\r
198 ;\r
199 \r
200 /**\r
201   Provides an EFI Device Path for a PCI device with the given PCI configuration space address.\r
202 \r
203   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
204   @param  Address                The PCI configuration space address of the device\r
205                                  whose Device Path is going to be returned.\r
206   @param  PciDevicePath          A pointer to the pointer for the EFI Device Path\r
207                                  for PciAddress. Memory for the Device Path is\r
208                                  allocated from the pool.\r
209 \r
210   @retval EFI_SUCCESS            The PciDevicePath returns a pointer to a valid EFI\r
211                                  Device Path.\r
212   @retval EFI_UNSUPPORTED        The PciAddress does not map to a valid EFI Device\r
213                                  Path.\r
214   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack\r
215                                  of resources.\r
216 \r
217 **/\r
218 EFI_STATUS\r
219 EFIAPI\r
220 DeviceIoPciDevicePath (\r
221   IN     EFI_DEVICE_IO_PROTOCOL        *This,\r
222   IN     UINT64                        Address,\r
223   IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath\r
224   )\r
225 ;\r
226 \r
227 /**\r
228   Provides the device-specific addresses needed to access system memory.\r
229 \r
230   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
231   @param  Operation              Indicates if the bus master is going to read or\r
232                                  write to system memory.\r
233   @param  HostAddress            The system memory address to map to the device.\r
234   @param  NumberOfBytes          On input the number of bytes to map. On output the\r
235                                  number of bytes that were mapped.\r
236   @param  DeviceAddress          The resulting map address for the bus master\r
237                                  device to use to access the hosts HostAddress.\r
238   @param  Mapping                A resulting value to pass to Unmap().\r
239 \r
240   @retval EFI_SUCCESS            The range was mapped for the returned\r
241                                  NumberOfBytes.\r
242   @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.\r
243   @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common\r
244                                  buffer.\r
245   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested\r
246                                  address.\r
247   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack\r
248                                  of resources.\r
249 \r
250 **/\r
251 EFI_STATUS\r
252 EFIAPI\r
253 DeviceIoMap (\r
254   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
255   IN     EFI_IO_OPERATION_TYPE    Operation,\r
256   IN     EFI_PHYSICAL_ADDRESS     *HostAddress,\r
257   IN OUT UINTN                    *NumberOfBytes,\r
258   OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,\r
259   OUT    VOID                     **Mapping\r
260   )\r
261 ;\r
262 \r
263 /**\r
264   Completes the Map() operation and releases any corresponding resources.\r
265 \r
266   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
267   @param  Mapping                The mapping value returned from Map().\r
268 \r
269   @retval EFI_SUCCESS            The range was unmapped.\r
270   @retval EFI_DEVICE_ERROR       The data was not committed to the target system\r
271                                  memory.\r
272 \r
273 **/\r
274 EFI_STATUS\r
275 EFIAPI\r
276 DeviceIoUnmap (\r
277   IN EFI_DEVICE_IO_PROTOCOL   *This,\r
278   IN VOID                     *Mapping\r
279   )\r
280 ;\r
281 \r
282 /**\r
283   Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.\r
284 \r
285   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
286   @param  Type                   The type allocation to perform.\r
287   @param  MemoryType             The type of memory to allocate,\r
288                                  EfiBootServicesData or EfiRuntimeServicesData.\r
289   @param  Pages                  The number of pages to allocate.\r
290   @param  PhysicalAddress        A pointer to store the base address of the\r
291                                  allocated range.\r
292 \r
293   @retval EFI_SUCCESS            The requested memory pages were allocated.\r
294   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.\r
295   @retval EFI_INVALID_PARAMETER  The requested memory type is invalid.\r
296   @retval EFI_UNSUPPORTED        The requested PhysicalAddress is not supported on\r
297                                  this platform.\r
298 \r
299 **/\r
300 EFI_STATUS\r
301 EFIAPI\r
302 DeviceIoAllocateBuffer (\r
303   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
304   IN     EFI_ALLOCATE_TYPE         Type,\r
305   IN     EFI_MEMORY_TYPE           MemoryType,\r
306   IN     UINTN                     Pages,\r
307   IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress\r
308   )\r
309 ;\r
310 \r
311 /**\r
312   Flushes any posted write data to the device.\r
313 \r
314   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
315 \r
316   @retval EFI_SUCCESS            The buffers were flushed.\r
317   @retval EFI_DEVICE_ERROR       The buffers were not flushed due to a hardware\r
318                                  error.\r
319 \r
320 **/\r
321 EFI_STATUS\r
322 EFIAPI\r
323 DeviceIoFlush (\r
324   IN EFI_DEVICE_IO_PROTOCOL  *This\r
325   )\r
326 ;\r
327 \r
328 /**\r
329   Frees pages that were allocated with AllocateBuffer().\r
330 \r
331   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
332   @param  Pages                  The number of pages to free.\r
333   @param  HostAddress            The base address of the range to free.\r
334 \r
335   @retval EFI_SUCCESS            The requested memory pages were freed.\r
336   @retval EFI_NOT_FOUND          The requested memory pages were not allocated with\r
337                                  AllocateBuffer().\r
338   @retval EFI_INVALID_PARAMETER  HostAddress is not page aligned or Pages is\r
339                                  invalid.\r
340 \r
341 **/\r
342 EFI_STATUS\r
343 EFIAPI\r
344 DeviceIoFreeBuffer (\r
345   IN EFI_DEVICE_IO_PROTOCOL   *This,\r
346   IN UINTN                    Pages,\r
347   IN EFI_PHYSICAL_ADDRESS     HostAddress\r
348   )\r
349 ;\r
350 \r
351 \r
352 #define DEVICE_IO_PRIVATE_DATA_SIGNATURE  EFI_SIGNATURE_32 ('D', 'e', 'I', 'O')\r
353 \r
354 typedef struct {\r
355   UINTN                           Signature;\r
356   EFI_DEVICE_IO_PROTOCOL          DeviceIo;\r
357   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
358   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
359   UINT16                          PrimaryBus;\r
360   UINT16                          SubordinateBus;\r
361 } DEVICE_IO_PRIVATE_DATA;\r
362 \r
363 #define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)\r
364 \r
365 #define MAX_COMMON_BUFFER                 0x00000000FFFFFFFF\r
366 \r
367 \r
368 EFI_EVENT  mPciRootBridgeIoRegistration;\r
369 \r
370 //\r
371 // Device Io Volume Protocol template\r
372 //\r
373 DEVICE_IO_PRIVATE_DATA gDeviceIoPrivateDataTemplate = {\r
374   DEVICE_IO_PRIVATE_DATA_SIGNATURE,\r
375   {\r
376     {\r
377       DeviceIoMemRead,\r
378       DeviceIoMemWrite\r
379     },\r
380     {\r
381       DeviceIoIoRead,\r
382       DeviceIoIoWrite  \r
383     },\r
384     {\r
385       DeviceIoPciRead,\r
386       DeviceIoPciWrite,  \r
387     },\r
388     DeviceIoMap,\r
389     DeviceIoPciDevicePath,\r
390     DeviceIoUnmap,\r
391     DeviceIoAllocateBuffer,\r
392     DeviceIoFlush,\r
393     DeviceIoFreeBuffer\r
394   },\r
395   NULL, // PciRootBridgeIo\r
396   NULL, // DevicePath\r
397   0,    // PrimaryBus\r
398   255   // SubordinateBus\r
399 };\r
400 \r
401 VOID\r
402 EFIAPI\r
403 PciRootBridgeIoNotificationEvent (\r
404   IN  EFI_EVENT       Event,\r
405   IN  VOID            *Context\r
406   )\r
407 {\r
408   EFI_STATUS                     Status;\r
409   UINTN                          BufferSize;\r
410   EFI_HANDLE                     Handle;\r
411   DEVICE_IO_PRIVATE_DATA         *Private;\r
412   EFI_DEVICE_IO_PROTOCOL         *DeviceIo;\r
413   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
414 \r
415   while (TRUE) {\r
416     BufferSize = sizeof (Handle);\r
417     Status = gBS->LocateHandle (\r
418                     ByRegisterNotify,\r
419                     &gEfiPciRootBridgeIoProtocolGuid,\r
420                     mPciRootBridgeIoRegistration,\r
421                     &BufferSize,\r
422                     &Handle\r
423                     );\r
424     if (EFI_ERROR (Status)) {\r
425       //\r
426       // Exit Path of While Loop....\r
427       //\r
428       break;\r
429     }\r
430 \r
431     //\r
432     // Skip this handle if the Device Io Protocol is already installed\r
433     //\r
434     Status = gBS->HandleProtocol (\r
435                     Handle,\r
436                     &gEfiDeviceIoProtocolGuid,\r
437                     (VOID **)&DeviceIo\r
438                     );\r
439     if (!EFI_ERROR (Status)) {\r
440       continue;\r
441     }\r
442 \r
443     //\r
444     // Retrieve the Pci Root Bridge IO Protocol\r
445     //\r
446     Status = gBS->HandleProtocol (\r
447                     Handle,\r
448                     &gEfiPciRootBridgeIoProtocolGuid,\r
449                     (VOID **)&PciRootBridgeIo\r
450                     );\r
451     ASSERT_EFI_ERROR (Status);\r
452 \r
453     //\r
454     // We only install Device IO for PCI bus in Segment 0\r
455     //\r
456     if (PciRootBridgeIo->SegmentNumber != 0) {\r
457       continue;\r
458     }\r
459 \r
460     //\r
461     // Allocate private data structure\r
462     //\r
463     Private = AllocateCopyPool (sizeof (DEVICE_IO_PRIVATE_DATA), &gDeviceIoPrivateDataTemplate);\r
464     if (Private == NULL) {\r
465       continue;\r
466     }\r
467 \r
468     Status = gBS->HandleProtocol (\r
469                     Handle,\r
470                     &gEfiDevicePathProtocolGuid,\r
471                     (VOID **) &Private->DevicePath\r
472                     );\r
473 \r
474     //\r
475     // Install Device Io onto same handle\r
476     //\r
477     Status = gBS->InstallMultipleProtocolInterfaces (\r
478                     &Handle,\r
479                     &gEfiDeviceIoProtocolGuid,\r
480                     &Private->DeviceIo,\r
481                     NULL\r
482                     );\r
483     ASSERT_EFI_ERROR (Status);\r
484   }\r
485 }\r
486 \r
487 /**\r
488   The user Entry Point for DXE driver. The user code starts with this function\r
489   as the real entry point for the image goes into a library that calls this \r
490   function.\r
491 \r
492   @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
493   @param[in] SystemTable    A pointer to the EFI System Table.\r
494   \r
495   @retval EFI_SUCCESS       The entry point is executed successfully.\r
496   @retval other             Some error occurs when executing this entry point.\r
497 \r
498 **/\r
499 EFI_STATUS\r
500 EFIAPI\r
501 InitializeDeviceIo (\r
502   IN EFI_HANDLE        ImageHandle,\r
503   IN EFI_SYSTEM_TABLE  *SystemTable\r
504   )\r
505 {\r
506   EfiCreateProtocolNotifyEvent (\r
507     &gEfiPciRootBridgeIoProtocolGuid,\r
508     TPL_CALLBACK,\r
509     PciRootBridgeIoNotificationEvent,\r
510     NULL,\r
511     &mPciRootBridgeIoRegistration\r
512     );\r
513   return EFI_SUCCESS;\r
514 }\r
515 \r
516 \r
517 /**\r
518   Perform reading memory mapped I/O space of device.\r
519 \r
520   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
521   @param  Width                  Width of I/O operations.\r
522   @param  Address                The base address of I/O operations.\r
523   @param  Count                  The number of I/O operations to perform.  Bytes\r
524                                  moves is Width size * Count, starting at Address.\r
525   @param  Buffer                 The destination buffer to store results.\r
526 \r
527   @retval EFI_SUCCESS            The data was read from the device.\r
528   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
529   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
530                                  resources.\r
531 \r
532 **/\r
533 EFI_STATUS\r
534 EFIAPI\r
535 DeviceIoMemRead (\r
536   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
537   IN     EFI_IO_WIDTH             Width,\r
538   IN     UINT64                   Address,\r
539   IN     UINTN                    Count,\r
540   IN OUT VOID                     *Buffer\r
541   )\r
542 {\r
543   EFI_STATUS              Status;\r
544   DEVICE_IO_PRIVATE_DATA  *Private;\r
545 \r
546   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
547 \r
548   if (Width > MMIO_COPY_UINT64) {\r
549     return EFI_INVALID_PARAMETER;\r
550   }\r
551   if (Width >= MMIO_COPY_UINT8) {\r
552     Width = Width - MMIO_COPY_UINT8;\r
553     Status = Private->PciRootBridgeIo->CopyMem (\r
554                                          Private->PciRootBridgeIo,\r
555                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
556                                          (UINT64) (UINTN) Buffer,\r
557                                          Address,\r
558                                          Count\r
559                                          );\r
560   } else {\r
561     Status = Private->PciRootBridgeIo->Mem.Read (\r
562                                              Private->PciRootBridgeIo,\r
563                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
564                                              Address,\r
565                                              Count,\r
566                                              Buffer\r
567                                              );\r
568   }\r
569 \r
570   return Status;\r
571 }\r
572 \r
573 \r
574 \r
575 \r
576 /**\r
577   Perform writing memory mapped I/O space of device.\r
578 \r
579   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
580   @param  Width                  Width of I/O operations.\r
581   @param  Address                The base address of I/O operations.\r
582   @param  Count                  The number of I/O operations to perform.  Bytes\r
583                                  moves is Width size * Count, starting at Address.\r
584   @param  Buffer                 The source buffer of data to be written.\r
585 \r
586   @retval EFI_SUCCESS            The data was written to the device.\r
587   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
588   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
589                                  resources.\r
590 \r
591 **/\r
592 EFI_STATUS\r
593 EFIAPI\r
594 DeviceIoMemWrite (\r
595   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
596   IN     EFI_IO_WIDTH              Width,\r
597   IN     UINT64                    Address,\r
598   IN     UINTN                     Count,\r
599   IN OUT VOID                      *Buffer\r
600   )\r
601 {\r
602   EFI_STATUS              Status;\r
603   DEVICE_IO_PRIVATE_DATA  *Private;\r
604 \r
605   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
606 \r
607   if (Width > MMIO_COPY_UINT64) {\r
608     return EFI_INVALID_PARAMETER;\r
609   }\r
610   if (Width >= MMIO_COPY_UINT8) {\r
611     Width = Width - MMIO_COPY_UINT8;\r
612     Status = Private->PciRootBridgeIo->CopyMem (\r
613                                          Private->PciRootBridgeIo,\r
614                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
615                                          Address,\r
616                                          (UINT64) (UINTN) Buffer,\r
617                                          Count\r
618                                          );\r
619   } else {\r
620     Status = Private->PciRootBridgeIo->Mem.Write (\r
621                                              Private->PciRootBridgeIo,\r
622                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
623                                              Address,\r
624                                              Count,\r
625                                              Buffer\r
626                                              );\r
627   }\r
628 \r
629   return Status;\r
630 }\r
631 \r
632 \r
633 /**\r
634   Perform reading I/O space of device.\r
635 \r
636   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
637   @param  Width                  Width of I/O operations.\r
638   @param  Address                The base address of I/O operations.\r
639   @param  Count                  The number of I/O operations to perform.  Bytes\r
640                                  moves is Width size * Count, starting at Address.\r
641   @param  Buffer                 The destination buffer to store results.\r
642 \r
643   @retval EFI_SUCCESS            The data was read from the device.\r
644   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
645   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
646                                  resources.\r
647 \r
648 **/\r
649 EFI_STATUS\r
650 EFIAPI\r
651 DeviceIoIoRead (\r
652   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
653   IN     EFI_IO_WIDTH             Width,\r
654   IN     UINT64                   Address,\r
655   IN     UINTN                    Count,\r
656   IN OUT VOID                     *Buffer\r
657   )\r
658 {\r
659   EFI_STATUS              Status;\r
660   DEVICE_IO_PRIVATE_DATA  *Private;\r
661 \r
662   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
663 \r
664   if (Width >= MMIO_COPY_UINT8) {\r
665     return EFI_INVALID_PARAMETER;\r
666   }\r
667 \r
668   Status = Private->PciRootBridgeIo->Io.Read (\r
669                                           Private->PciRootBridgeIo,\r
670                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
671                                           Address,\r
672                                           Count,\r
673                                           Buffer\r
674                                           );\r
675 \r
676   return Status;\r
677 }\r
678 \r
679 \r
680 /**\r
681   Perform writing I/O space of device.\r
682 \r
683   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
684   @param  Width                  Width of I/O operations.\r
685   @param  Address                The base address of I/O operations.\r
686   @param  Count                  The number of I/O operations to perform.  Bytes\r
687                                  moves is Width size * Count, starting at Address.\r
688   @param  Buffer                 The source buffer of data to be written.\r
689 \r
690   @retval EFI_SUCCESS            The data was written to the device.\r
691   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
692   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
693                                  resources.\r
694 \r
695 **/\r
696 EFI_STATUS\r
697 EFIAPI\r
698 DeviceIoIoWrite (\r
699   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
700   IN     EFI_IO_WIDTH              Width,\r
701   IN     UINT64                    Address,\r
702   IN     UINTN                     Count,\r
703   IN OUT VOID                      *Buffer\r
704   )\r
705 {\r
706   EFI_STATUS              Status;\r
707   DEVICE_IO_PRIVATE_DATA  *Private;\r
708 \r
709   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
710 \r
711   if (Width >= MMIO_COPY_UINT8) {\r
712     return EFI_INVALID_PARAMETER;\r
713   }\r
714 \r
715   Status = Private->PciRootBridgeIo->Io.Write (\r
716                                           Private->PciRootBridgeIo,\r
717                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
718                                           Address,\r
719                                           Count,\r
720                                           Buffer\r
721                                           );\r
722 \r
723   return Status;\r
724 }\r
725 \r
726 \r
727 /**\r
728   Perform reading PCI configuration space of device\r
729 \r
730   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
731   @param  Width                  Width of I/O operations.\r
732   @param  Address                The base address of I/O operations.\r
733   @param  Count                  The number of I/O operations to perform.  Bytes\r
734                                  moves is Width size * Count, starting at Address.\r
735   @param  Buffer                 The destination buffer to store results.\r
736 \r
737   @retval EFI_SUCCESS            The data was read from the device.\r
738   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
739   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
740                                  resources.\r
741 \r
742 **/\r
743 EFI_STATUS\r
744 EFIAPI\r
745 DeviceIoPciRead (\r
746   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
747   IN     EFI_IO_WIDTH             Width,\r
748   IN     UINT64                   Address,\r
749   IN     UINTN                    Count,\r
750   IN OUT VOID                     *Buffer\r
751   )\r
752 {\r
753   EFI_STATUS              Status;\r
754   DEVICE_IO_PRIVATE_DATA  *Private;\r
755 \r
756   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
757 \r
758   if (Width < 0 || Width >= MMIO_COPY_UINT8) {\r
759     return EFI_INVALID_PARAMETER;\r
760   }\r
761 \r
762   Status = Private->PciRootBridgeIo->Pci.Read (\r
763                                            Private->PciRootBridgeIo,\r
764                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
765                                            Address,\r
766                                            Count,\r
767                                            Buffer\r
768                                            );\r
769 \r
770   return Status;\r
771 }\r
772 \r
773 \r
774 /**\r
775   Perform writing PCI configuration space of device.\r
776 \r
777   @param  This                   A pointer to EFI_DEVICE_IO protocol instance.\r
778   @param  Width                  Width of I/O operations.\r
779   @param  Address                The base address of I/O operations.\r
780   @param  Count                  The number of I/O operations to perform.  Bytes\r
781                                  moves is Width size * Count, starting at Address.\r
782   @param  Buffer                 The source buffer of data to be written.\r
783 \r
784   @retval EFI_SUCCESS            The data was written to the device.\r
785   @retval EFI_INVALID_PARAMETER  Width is invalid.\r
786   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to lack of\r
787                                  resources.\r
788 \r
789 **/\r
790 EFI_STATUS\r
791 EFIAPI\r
792 DeviceIoPciWrite (\r
793   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
794   IN     EFI_IO_WIDTH              Width,\r
795   IN     UINT64                    Address,\r
796   IN     UINTN                     Count,\r
797   IN OUT VOID                      *Buffer\r
798   )\r
799 {\r
800   EFI_STATUS              Status;\r
801   DEVICE_IO_PRIVATE_DATA  *Private;\r
802 \r
803   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
804 \r
805   if (Width < 0 || Width >= MMIO_COPY_UINT8) {\r
806     return EFI_INVALID_PARAMETER;\r
807   }\r
808 \r
809   Status = Private->PciRootBridgeIo->Pci.Write (\r
810                                            Private->PciRootBridgeIo,\r
811                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
812                                            Address,\r
813                                            Count,\r
814                                            Buffer\r
815                                            );\r
816 \r
817   return Status;\r
818 }\r
819 \r
820 \r
821 /**\r
822   Append a PCI device path node to another device path.\r
823 \r
824   @param  Private                A pointer to DEVICE_IO_PRIVATE_DATA instance.\r
825   @param  Bus                    PCI bus number of the device.\r
826   @param  Device                 PCI device number of the device.\r
827   @param  Function               PCI function number of the device.\r
828   @param  DevicePath             Original device path which will be appended a PCI\r
829                                  device path node.\r
830   @param  BridgePrimaryBus       Primary bus number of the bridge.\r
831   @param  BridgeSubordinateBus   Subordinate bus number of the bridge.\r
832 \r
833   @return Pointer to the appended PCI device path.\r
834 \r
835 **/\r
836 EFI_DEVICE_PATH_PROTOCOL *\r
837 AppendPciDevicePath (\r
838   IN     DEVICE_IO_PRIVATE_DATA    *Private,\r
839   IN     UINT8                     Bus,\r
840   IN     UINT8                     Device,\r
841   IN     UINT8                     Function,\r
842   IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
843   IN OUT UINT16                    *BridgePrimaryBus,\r
844   IN OUT UINT16                    *BridgeSubordinateBus\r
845   )\r
846 {\r
847   UINT16                    ThisBus;\r
848   UINT8                     ThisDevice;\r
849   UINT8                     ThisFunc;\r
850   UINT64                    Address;\r
851   PCI_TYPE01                PciBridge;\r
852   PCI_TYPE01                *PciPtr;\r
853   EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;\r
854   PCI_DEVICE_PATH           PciNode;\r
855 \r
856   PciPtr = &PciBridge;\r
857   for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {\r
858     for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {\r
859       for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {\r
860         Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);\r
861         ZeroMem (PciPtr, sizeof (PCI_TYPE01));\r
862         Private->DeviceIo.Pci.Read (\r
863                                 &Private->DeviceIo,\r
864                                 IO_UINT32,\r
865                                 Address,\r
866                                 1,\r
867                                 &(PciPtr->Hdr.VendorId)\r
868                                 );\r
869         if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {\r
870           break;\r
871         }\r
872         if (PciPtr->Hdr.VendorId == 0xffff) {\r
873           continue;\r
874         } else {\r
875           Private->DeviceIo.Pci.Read (\r
876                                   &Private->DeviceIo,\r
877                                   IO_UINT32,\r
878                                   Address,\r
879                                   sizeof (PCI_TYPE01) / sizeof (UINT32),\r
880                                   PciPtr\r
881                                   );\r
882           if (IS_PCI_BRIDGE (PciPtr)) {\r
883             if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {\r
884 \r
885               PciNode.Header.Type     = HARDWARE_DEVICE_PATH;\r
886               PciNode.Header.SubType  = HW_PCI_DP;\r
887               SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
888 \r
889               PciNode.Device        = ThisDevice;\r
890               PciNode.Function      = ThisFunc;\r
891               ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);\r
892 \r
893               *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;\r
894               *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;\r
895               return ReturnDevicePath;\r
896             }\r
897           }\r
898           if (ThisFunc == 0 && !(PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {\r
899             //\r
900             // Skip sub functions, this is not a multi function device\r
901             //\r
902             ThisFunc = 8;\r
903           }\r
904         }\r
905       }\r
906     }\r
907   }\r
908 \r
909   ZeroMem (&PciNode, sizeof (PciNode));\r
910   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;\r
911   PciNode.Header.SubType  = HW_PCI_DP;\r
912   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
913   PciNode.Device        = Device;\r
914   PciNode.Function      = Function;\r
915 \r
916   ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);\r
917 \r
918   *BridgePrimaryBus     = 0xffff;\r
919   *BridgeSubordinateBus = 0xffff;\r
920   return ReturnDevicePath;\r
921 }\r
922 \r
923 \r
924 /**\r
925   Provides an EFI Device Path for a PCI device with the given PCI configuration space address.\r
926 \r
927   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
928   @param  Address                The PCI configuration space address of the device\r
929                                  whose Device Path is going to be returned.\r
930   @param  PciDevicePath          A pointer to the pointer for the EFI Device Path\r
931                                  for PciAddress. Memory for the Device Path is\r
932                                  allocated from the pool.\r
933 \r
934   @retval EFI_SUCCESS            The PciDevicePath returns a pointer to a valid EFI\r
935                                  Device Path.\r
936   @retval EFI_UNSUPPORTED        The PciAddress does not map to a valid EFI Device\r
937                                  Path.\r
938   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack\r
939                                  of resources.\r
940 \r
941 **/\r
942 EFI_STATUS\r
943 EFIAPI\r
944 DeviceIoPciDevicePath (\r
945   IN     EFI_DEVICE_IO_PROTOCOL        *This,\r
946   IN     UINT64                        Address,\r
947   IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath\r
948   )\r
949 {\r
950   DEVICE_IO_PRIVATE_DATA  *Private;\r
951   UINT16                  PrimaryBus;\r
952   UINT16                  SubordinateBus;\r
953   UINT8                   Bus;\r
954   UINT8                   Device;\r
955   UINT8                   Func;\r
956 \r
957   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
958 \r
959   Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);\r
960   Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);\r
961   Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);\r
962 \r
963   if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {\r
964     return EFI_UNSUPPORTED;\r
965   }\r
966 \r
967   *PciDevicePath  = Private->DevicePath;\r
968   PrimaryBus      = Private->PrimaryBus;\r
969   SubordinateBus  = Private->SubordinateBus;\r
970   do {\r
971     *PciDevicePath = AppendPciDevicePath (\r
972                        Private,\r
973                        Bus,\r
974                        Device,\r
975                        Func,\r
976                        *PciDevicePath,\r
977                        &PrimaryBus,\r
978                        &SubordinateBus\r
979                        );\r
980     if (*PciDevicePath == NULL) {\r
981       return EFI_OUT_OF_RESOURCES;\r
982     }\r
983   } while (PrimaryBus != 0xffff);\r
984 \r
985   return EFI_SUCCESS;\r
986 }\r
987 \r
988 \r
989 /**\r
990   Provides the device-specific addresses needed to access system memory.\r
991 \r
992   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
993   @param  Operation              Indicates if the bus master is going to read or\r
994                                  write to system memory.\r
995   @param  HostAddress            The system memory address to map to the device.\r
996   @param  NumberOfBytes          On input the number of bytes to map. On output the\r
997                                  number of bytes that were mapped.\r
998   @param  DeviceAddress          The resulting map address for the bus master\r
999                                  device to use to access the hosts HostAddress.\r
1000   @param  Mapping                A resulting value to pass to Unmap().\r
1001 \r
1002   @retval EFI_SUCCESS            The range was mapped for the returned\r
1003                                  NumberOfBytes.\r
1004   @retval EFI_INVALID_PARAMETER  The Operation or HostAddress is undefined.\r
1005   @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common\r
1006                                  buffer.\r
1007   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested\r
1008                                  address.\r
1009   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack\r
1010                                  of resources.\r
1011 \r
1012 **/\r
1013 EFI_STATUS\r
1014 EFIAPI\r
1015 DeviceIoMap (\r
1016   IN     EFI_DEVICE_IO_PROTOCOL   *This,\r
1017   IN     EFI_IO_OPERATION_TYPE    Operation,\r
1018   IN     EFI_PHYSICAL_ADDRESS     *HostAddress,\r
1019   IN OUT UINTN                    *NumberOfBytes,\r
1020   OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,\r
1021   OUT    VOID                     **Mapping\r
1022   )\r
1023 {\r
1024   EFI_STATUS              Status;\r
1025   DEVICE_IO_PRIVATE_DATA  *Private;\r
1026 \r
1027   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
1028 \r
1029   if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {\r
1030     return EFI_INVALID_PARAMETER;\r
1031   }\r
1032 \r
1033   if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {\r
1034     return EFI_UNSUPPORTED;\r
1035   }\r
1036 \r
1037   Status = Private->PciRootBridgeIo->Map (\r
1038                                        Private->PciRootBridgeIo,\r
1039                                        (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
1040                                        (VOID *) (UINTN) (*HostAddress),\r
1041                                        NumberOfBytes,\r
1042                                        DeviceAddress,\r
1043                                        Mapping\r
1044                                        );\r
1045 \r
1046   return Status;\r
1047 }\r
1048 \r
1049 \r
1050 /**\r
1051   Completes the Map() operation and releases any corresponding resources.\r
1052 \r
1053   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1054   @param  Mapping                The mapping value returned from Map().\r
1055 \r
1056   @retval EFI_SUCCESS            The range was unmapped.\r
1057   @retval EFI_DEVICE_ERROR       The data was not committed to the target system\r
1058                                  memory.\r
1059 \r
1060 **/\r
1061 EFI_STATUS\r
1062 EFIAPI\r
1063 DeviceIoUnmap (\r
1064   IN EFI_DEVICE_IO_PROTOCOL   *This,\r
1065   IN VOID                     *Mapping\r
1066   )\r
1067 {\r
1068   EFI_STATUS              Status;\r
1069   DEVICE_IO_PRIVATE_DATA  *Private;\r
1070 \r
1071   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
1072 \r
1073   Status = Private->PciRootBridgeIo->Unmap (\r
1074                                        Private->PciRootBridgeIo,\r
1075                                        Mapping\r
1076                                        );\r
1077 \r
1078   return Status;\r
1079 }\r
1080 \r
1081 \r
1082 /**\r
1083   Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.\r
1084 \r
1085   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1086   @param  Type                   The type allocation to perform.\r
1087   @param  MemoryType             The type of memory to allocate,\r
1088                                  EfiBootServicesData or EfiRuntimeServicesData.\r
1089   @param  Pages                  The number of pages to allocate.\r
1090   @param  PhysicalAddress        A pointer to store the base address of the\r
1091                                  allocated range.\r
1092 \r
1093   @retval EFI_SUCCESS            The requested memory pages were allocated.\r
1094   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.\r
1095   @retval EFI_INVALID_PARAMETER  The requested memory type is invalid.\r
1096   @retval EFI_UNSUPPORTED        The requested PhysicalAddress is not supported on\r
1097                                  this platform.\r
1098 \r
1099 **/\r
1100 EFI_STATUS\r
1101 EFIAPI\r
1102 DeviceIoAllocateBuffer (\r
1103   IN     EFI_DEVICE_IO_PROTOCOL    *This,\r
1104   IN     EFI_ALLOCATE_TYPE         Type,\r
1105   IN     EFI_MEMORY_TYPE           MemoryType,\r
1106   IN     UINTN                     Pages,\r
1107   IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress\r
1108   )\r
1109 {\r
1110   EFI_STATUS            Status;\r
1111   EFI_PHYSICAL_ADDRESS  HostAddress;\r
1112 \r
1113   HostAddress = *PhysicalAddress;\r
1114 \r
1115   if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {\r
1116     return EFI_INVALID_PARAMETER;\r
1117   }\r
1118 \r
1119   if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {\r
1120     return EFI_INVALID_PARAMETER;\r
1121   }\r
1122 \r
1123   if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {\r
1124     return EFI_UNSUPPORTED;\r
1125   }\r
1126 \r
1127   if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {\r
1128     Type        = AllocateMaxAddress;\r
1129     HostAddress = MAX_COMMON_BUFFER;\r
1130   }\r
1131 \r
1132   Status = gBS->AllocatePages (\r
1133                   Type,\r
1134                   MemoryType,\r
1135                   Pages,\r
1136                   &HostAddress\r
1137                   );\r
1138   if (EFI_ERROR (Status)) {\r
1139     return Status;\r
1140   }\r
1141 \r
1142 \r
1143   *PhysicalAddress = HostAddress;\r
1144 \r
1145   return EFI_SUCCESS;\r
1146 }\r
1147 \r
1148 \r
1149 /**\r
1150   Flushes any posted write data to the device.\r
1151 \r
1152   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1153 \r
1154   @retval EFI_SUCCESS            The buffers were flushed.\r
1155   @retval EFI_DEVICE_ERROR       The buffers were not flushed due to a hardware\r
1156                                  error.\r
1157 \r
1158 **/\r
1159 EFI_STATUS\r
1160 EFIAPI\r
1161 DeviceIoFlush (\r
1162   IN EFI_DEVICE_IO_PROTOCOL  *This\r
1163   )\r
1164 {\r
1165   EFI_STATUS              Status;\r
1166   DEVICE_IO_PRIVATE_DATA  *Private;\r
1167 \r
1168   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
1169 \r
1170   Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);\r
1171 \r
1172   return Status;\r
1173 }\r
1174 \r
1175 \r
1176 /**\r
1177   Frees pages that were allocated with AllocateBuffer().\r
1178 \r
1179   @param  This                   A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1180   @param  Pages                  The number of pages to free.\r
1181   @param  HostAddress            The base address of the range to free.\r
1182 \r
1183   @retval EFI_SUCCESS            The requested memory pages were freed.\r
1184   @retval EFI_NOT_FOUND          The requested memory pages were not allocated with\r
1185                                  AllocateBuffer().\r
1186   @retval EFI_INVALID_PARAMETER  HostAddress is not page aligned or Pages is\r
1187                                  invalid.\r
1188 \r
1189 **/\r
1190 EFI_STATUS\r
1191 EFIAPI\r
1192 DeviceIoFreeBuffer (\r
1193   IN EFI_DEVICE_IO_PROTOCOL   *This,\r
1194   IN UINTN                    Pages,\r
1195   IN EFI_PHYSICAL_ADDRESS     HostAddress\r
1196   )\r
1197 {\r
1198   if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {\r
1199     return EFI_INVALID_PARAMETER;\r
1200   }\r
1201 \r
1202   return gBS->FreePages (HostAddress, Pages);\r
1203 }\r
1204 \r