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