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