1 /*++
2 
3 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14     DeviceIo.c
15 
16 Abstract:
17 
18     EFI PC-AT PCI Device IO driver
19 
20 --*/
21 #include "PcatPciRootBridge.h"
22 #include "DeviceIo.h"
23 
24 EFI_STATUS
DeviceIoConstructor(IN EFI_HANDLE Handle,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * PciRootBridgeIo,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN UINT16 PrimaryBus,IN UINT16 SubordinateBus)25 DeviceIoConstructor (
26   IN EFI_HANDLE                      Handle,
27   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
28   IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
29   IN UINT16                          PrimaryBus,
30   IN UINT16                          SubordinateBus
31   )
32 /*++
33 
34 Routine Description:
35 
36   Initialize and install a Device IO protocol on a empty device path handle.
37 
38 Arguments:
39 
40   Handle               - Handle of PCI RootBridge IO instance
41   PciRootBridgeIo      - PCI RootBridge IO instance
42   DevicePath           - Device Path of PCI RootBridge IO instance
43   PrimaryBus           - Primary Bus
44   SubordinateBus       - Subordinate Bus
45 
46 Returns:
47 
48   EFI_SUCCESS          -  This driver is added to ControllerHandle.
49   EFI_ALREADY_STARTED  -  This driver is already running on ControllerHandle.
50   Others               -  This driver does not support this device.
51 
52 --*/
53 {
54   EFI_STATUS                      Status;
55   DEVICE_IO_PRIVATE_DATA          *Private;
56 
57   //
58   // Initialize the Device IO device instance.
59   //
60   Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
61   if (Private == NULL) {
62     return EFI_OUT_OF_RESOURCES;
63   }
64 
65   Private->Signature                = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
66   Private->Handle                   = Handle;
67   Private->PciRootBridgeIo          = PciRootBridgeIo;
68   Private->DevicePath               = DevicePath;
69   Private->PrimaryBus               = PrimaryBus;
70   Private->SubordinateBus           = SubordinateBus;
71 
72   Private->DeviceIo.Mem.Read        = DeviceIoMemRead;
73   Private->DeviceIo.Mem.Write       = DeviceIoMemWrite;
74   Private->DeviceIo.Io.Read         = DeviceIoIoRead;
75   Private->DeviceIo.Io.Write        = DeviceIoIoWrite;
76   Private->DeviceIo.Pci.Read        = DeviceIoPciRead;
77   Private->DeviceIo.Pci.Write       = DeviceIoPciWrite;
78   Private->DeviceIo.PciDevicePath   = DeviceIoPciDevicePath;
79   Private->DeviceIo.Map             = DeviceIoMap;
80   Private->DeviceIo.Unmap           = DeviceIoUnmap;
81   Private->DeviceIo.AllocateBuffer  = DeviceIoAllocateBuffer;
82   Private->DeviceIo.Flush           = DeviceIoFlush;
83   Private->DeviceIo.FreeBuffer      = DeviceIoFreeBuffer;
84 
85   //
86   // Install protocol interfaces for the Device IO device.
87   //
88   Status = gBS->InstallMultipleProtocolInterfaces (
89                   &Private->Handle,
90                   &gEfiDeviceIoProtocolGuid,
91                   &Private->DeviceIo,
92                   NULL
93                   );
94   ASSERT_EFI_ERROR (Status);
95 
96   return Status;
97 }
98 
99 EFI_STATUS
100 EFIAPI
DeviceIoMemRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)101 DeviceIoMemRead (
102   IN     EFI_DEVICE_IO_PROTOCOL   *This,
103   IN     EFI_IO_WIDTH             Width,
104   IN     UINT64                   Address,
105   IN     UINTN                    Count,
106   IN OUT VOID                     *Buffer
107   )
108 /*++
109 
110 Routine Description:
111 
112   Perform reading memory mapped I/O space of device.
113 
114 Arguments:
115 
116   This     -  A pointer to EFI_DEVICE_IO protocol instance.
117   Width    -  Width of I/O operations.
118   Address  -  The base address of I/O operations.
119   Count    -  The number of I/O operations to perform.
120               Bytes moves is Width size * Count, starting at Address.
121   Buffer   -  The destination buffer to store results.
122 
123 Returns:
124 
125   EFI_SUCCESS            -  The data was read from the device.
126   EFI_INVALID_PARAMETER  -  Width is invalid.
127   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
128 
129 --*/
130 {
131   EFI_STATUS              Status;
132   DEVICE_IO_PRIVATE_DATA  *Private;
133 
134   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
135 
136   if (Width > MMIO_COPY_UINT64) {
137     return EFI_INVALID_PARAMETER;
138   }
139   if (Width >= MMIO_COPY_UINT8) {
140     Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
141     Status = Private->PciRootBridgeIo->CopyMem (
142                                          Private->PciRootBridgeIo,
143                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
144                                          (UINT64)(UINTN) Buffer,
145                                          Address,
146                                          Count
147                                          );
148   } else {
149     Status = Private->PciRootBridgeIo->Mem.Read (
150                                              Private->PciRootBridgeIo,
151                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
152                                              Address,
153                                              Count,
154                                              Buffer
155                                              );
156   }
157 
158   return Status;
159 }
160 
161 
162 
163 EFI_STATUS
164 EFIAPI
DeviceIoMemWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)165 DeviceIoMemWrite (
166   IN     EFI_DEVICE_IO_PROTOCOL    *This,
167   IN     EFI_IO_WIDTH              Width,
168   IN     UINT64                    Address,
169   IN     UINTN                     Count,
170   IN OUT VOID                      *Buffer
171   )
172 /*++
173 
174 Routine Description:
175 
176   Perform writing memory mapped I/O space of device.
177 
178 Arguments:
179 
180   This     -  A pointer to EFI_DEVICE_IO protocol instance.
181   Width    -  Width of I/O operations.
182   Address  -  The base address of I/O operations.
183   Count    -  The number of I/O operations to perform.
184               Bytes moves is Width size * Count, starting at Address.
185   Buffer   -  The source buffer of data to be written.
186 
187 Returns:
188 
189   EFI_SUCCESS            -  The data was written to the device.
190   EFI_INVALID_PARAMETER  -  Width is invalid.
191   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
192 
193 --*/
194 {
195   EFI_STATUS              Status;
196   DEVICE_IO_PRIVATE_DATA  *Private;
197 
198   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
199 
200   if (Width > MMIO_COPY_UINT64) {
201     return EFI_INVALID_PARAMETER;
202   }
203   if (Width >= MMIO_COPY_UINT8) {
204     Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
205     Status = Private->PciRootBridgeIo->CopyMem (
206                                          Private->PciRootBridgeIo,
207                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
208                                          Address,
209                                          (UINT64)(UINTN) Buffer,
210                                          Count
211                                          );
212   } else {
213     Status = Private->PciRootBridgeIo->Mem.Write (
214                                              Private->PciRootBridgeIo,
215                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
216                                              Address,
217                                              Count,
218                                              Buffer
219                                              );
220   }
221 
222   return Status;
223 }
224 
225 EFI_STATUS
226 EFIAPI
DeviceIoIoRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)227 DeviceIoIoRead (
228   IN     EFI_DEVICE_IO_PROTOCOL   *This,
229   IN     EFI_IO_WIDTH             Width,
230   IN     UINT64                   Address,
231   IN     UINTN                    Count,
232   IN OUT VOID                     *Buffer
233   )
234 /*++
235 
236 Routine Description:
237 
238   Perform reading I/O space of device.
239 
240 Arguments:
241 
242   This     -  A pointer to EFI_DEVICE_IO protocol instance.
243   Width    -  Width of I/O operations.
244   Address  -  The base address of I/O operations.
245   Count    -  The number of I/O operations to perform.
246               Bytes moves is Width size * Count, starting at Address.
247   Buffer   -  The destination buffer to store results.
248 
249 Returns:
250 
251   EFI_SUCCESS            -  The data was read from the device.
252   EFI_INVALID_PARAMETER  -  Width is invalid.
253   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
254 
255 --*/
256 {
257   EFI_STATUS              Status;
258   DEVICE_IO_PRIVATE_DATA  *Private;
259 
260   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
261 
262   if (Width >= MMIO_COPY_UINT8) {
263     return EFI_INVALID_PARAMETER;
264   }
265 
266   Status = Private->PciRootBridgeIo->Io.Read (
267                                           Private->PciRootBridgeIo,
268                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
269                                           Address,
270                                           Count,
271                                           Buffer
272                                           );
273 
274   return Status;
275 }
276 
277 EFI_STATUS
278 EFIAPI
DeviceIoIoWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)279 DeviceIoIoWrite (
280   IN     EFI_DEVICE_IO_PROTOCOL    *This,
281   IN     EFI_IO_WIDTH              Width,
282   IN     UINT64                    Address,
283   IN     UINTN                     Count,
284   IN OUT VOID                      *Buffer
285   )
286 /*++
287 
288 Routine Description:
289 
290   Perform writing I/O space of device.
291 
292 Arguments:
293 
294   This     -  A pointer to EFI_DEVICE_IO protocol instance.
295   Width    -  Width of I/O operations.
296   Address  -  The base address of I/O operations.
297   Count    -  The number of I/O operations to perform.
298               Bytes moves is Width size * Count, starting at Address.
299   Buffer   -  The source buffer of data to be written.
300 
301 Returns:
302 
303   EFI_SUCCESS            -  The data was written to the device.
304   EFI_INVALID_PARAMETER  -  Width is invalid.
305   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
306 
307 --*/
308 {
309   EFI_STATUS              Status;
310   DEVICE_IO_PRIVATE_DATA  *Private;
311 
312   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
313 
314   if (Width >= MMIO_COPY_UINT8) {
315     return EFI_INVALID_PARAMETER;
316   }
317 
318   Status = Private->PciRootBridgeIo->Io.Write (
319                                           Private->PciRootBridgeIo,
320                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
321                                           Address,
322                                           Count,
323                                           Buffer
324                                           );
325 
326   return Status;
327 }
328 
329 EFI_STATUS
330 EFIAPI
DeviceIoPciRead(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)331 DeviceIoPciRead (
332   IN     EFI_DEVICE_IO_PROTOCOL   *This,
333   IN     EFI_IO_WIDTH             Width,
334   IN     UINT64                   Address,
335   IN     UINTN                    Count,
336   IN OUT VOID                     *Buffer
337   )
338 /*++
339 
340 Routine Description:
341 
342   Perform reading PCI configuration space of device
343 
344 Arguments:
345 
346   This     -  A pointer to EFI_DEVICE_IO protocol instance.
347   Width    -  Width of I/O operations.
348   Address  -  The base address of I/O operations.
349   Count    -  The number of I/O operations to perform.
350               Bytes moves is Width size * Count, starting at Address.
351   Buffer   -  The destination buffer to store results.
352 
353 Returns:
354 
355   EFI_SUCCESS            -  The data was read from the device.
356   EFI_INVALID_PARAMETER  -  Width is invalid.
357   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
358 
359 --*/
360 {
361   EFI_STATUS              Status;
362   DEVICE_IO_PRIVATE_DATA  *Private;
363 
364   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
365 
366   if ((UINT32)Width >= MMIO_COPY_UINT8) {
367     return EFI_INVALID_PARAMETER;
368   }
369 
370   Status = Private->PciRootBridgeIo->Pci.Read (
371                                            Private->PciRootBridgeIo,
372                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
373                                            Address,
374                                            Count,
375                                            Buffer
376                                            );
377 
378   return Status;
379 }
380 
381 EFI_STATUS
382 EFIAPI
DeviceIoPciWrite(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)383 DeviceIoPciWrite (
384   IN     EFI_DEVICE_IO_PROTOCOL    *This,
385   IN     EFI_IO_WIDTH              Width,
386   IN     UINT64                    Address,
387   IN     UINTN                     Count,
388   IN OUT VOID                      *Buffer
389   )
390 /*++
391 
392 Routine Description:
393 
394   Perform writing PCI configuration space of device.
395 
396 Arguments:
397 
398   This     -  A pointer to EFI_DEVICE_IO protocol instance.
399   Width    -  Width of I/O operations.
400   Address  -  The base address of I/O operations.
401   Count    -  The number of I/O operations to perform.
402               Bytes moves is Width size * Count, starting at Address.
403   Buffer   -  The source buffer of data to be written.
404 
405 Returns:
406 
407   EFI_SUCCESS            -  The data was written to the device.
408   EFI_INVALID_PARAMETER  -  Width is invalid.
409   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
410 
411 --*/
412 {
413   EFI_STATUS              Status;
414   DEVICE_IO_PRIVATE_DATA  *Private;
415 
416   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
417 
418   if ((UINT32)Width >= MMIO_COPY_UINT8) {
419     return EFI_INVALID_PARAMETER;
420   }
421 
422   Status = Private->PciRootBridgeIo->Pci.Write (
423                                            Private->PciRootBridgeIo,
424                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
425                                            Address,
426                                            Count,
427                                            Buffer
428                                            );
429 
430   return Status;
431 }
432 
433 EFI_DEVICE_PATH_PROTOCOL *
AppendPciDevicePath(IN DEVICE_IO_PRIVATE_DATA * Private,IN UINT8 Bus,IN UINT8 Device,IN UINT8 Function,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN OUT UINT16 * BridgePrimaryBus,IN OUT UINT16 * BridgeSubordinateBus)434 AppendPciDevicePath (
435   IN     DEVICE_IO_PRIVATE_DATA    *Private,
436   IN     UINT8                     Bus,
437   IN     UINT8                     Device,
438   IN     UINT8                     Function,
439   IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
440   IN OUT UINT16                    *BridgePrimaryBus,
441   IN OUT UINT16                    *BridgeSubordinateBus
442   )
443 /*++
444 
445 Routine Description:
446 
447   Append a PCI device path node to another device path.
448 
449 Arguments:
450 
451   Private               -  A pointer to DEVICE_IO_PRIVATE_DATA instance.
452   Bus                   -  PCI bus number of the device.
453   Device                -  PCI device number of the device.
454   Function              -  PCI function number of the device.
455   DevicePath            -  Original device path which will be appended a PCI device path node.
456   BridgePrimaryBus      -  Primary bus number of the bridge.
457   BridgeSubordinateBus  -  Subordinate bus number of the bridge.
458 
459 Returns:
460 
461   Pointer to the appended PCI device path.
462 
463 --*/
464 {
465   UINT16                    ThisBus;
466   UINT8                     ThisDevice;
467   UINT8                     ThisFunc;
468   UINT64                    Address;
469   PCI_TYPE01                PciBridge;
470   PCI_TYPE01                *PciPtr;
471   EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;
472   PCI_DEVICE_PATH           PciNode;
473 
474   PciPtr = &PciBridge;
475   for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
476     for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
477       for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
478         Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
479         ZeroMem (PciPtr, sizeof (PCI_TYPE01));
480         Private->DeviceIo.Pci.Read (
481                                 &Private->DeviceIo,
482                                 IO_UINT32,
483                                 Address,
484                                 1,
485                                 &(PciPtr->Hdr.VendorId)
486                                 );
487         if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
488           break;
489         }
490         if (PciPtr->Hdr.VendorId == 0xffff) {
491           continue;
492         }
493 
494         Private->DeviceIo.Pci.Read (
495                                 &Private->DeviceIo,
496                                 IO_UINT32,
497                                 Address,
498                                 sizeof (PCI_TYPE01) / sizeof (UINT32),
499                                 PciPtr
500                                 );
501         if (IS_PCI_BRIDGE (PciPtr)) {
502           if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
503 
504             PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
505             PciNode.Header.SubType  = HW_PCI_DP;
506             SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
507 
508             PciNode.Device        = ThisDevice;
509             PciNode.Function      = ThisFunc;
510             ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
511 
512             *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;
513             *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
514             return ReturnDevicePath;
515           }
516         }
517 
518         if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
519           //
520           // Skip sub functions, this is not a multi function device
521           //
522           break;
523         }
524       }
525     }
526   }
527 
528   ZeroMem (&PciNode, sizeof (PciNode));
529   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
530   PciNode.Header.SubType  = HW_PCI_DP;
531   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
532   PciNode.Device        = Device;
533   PciNode.Function      = Function;
534 
535   ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
536 
537   *BridgePrimaryBus     = 0xffff;
538   *BridgeSubordinateBus = 0xffff;
539   return ReturnDevicePath;
540 }
541 
542 EFI_STATUS
543 EFIAPI
DeviceIoPciDevicePath(IN EFI_DEVICE_IO_PROTOCOL * This,IN UINT64 Address,IN OUT EFI_DEVICE_PATH_PROTOCOL ** PciDevicePath)544 DeviceIoPciDevicePath (
545   IN     EFI_DEVICE_IO_PROTOCOL        *This,
546   IN     UINT64                        Address,
547   IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
548   )
549 /*++
550 
551 Routine Description:
552 
553   Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
554 
555 Arguments:
556 
557   This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
558   Address        -  The PCI configuration space address of the device whose Device Path
559                     is going to be returned.
560   PciDevicePath  -  A pointer to the pointer for the EFI Device Path for PciAddress.
561                     Memory for the Device Path is allocated from the pool.
562 
563 Returns:
564 
565   EFI_SUCCESS           -  The PciDevicePath returns a pointer to a valid EFI Device Path.
566   EFI_UNSUPPORTED       -  The PciAddress does not map to a valid EFI Device Path.
567   EFI_OUT_OF_RESOURCES  -  The request could not be completed due to a lack of resources.
568 
569 --*/
570 {
571   DEVICE_IO_PRIVATE_DATA  *Private;
572   UINT16                  PrimaryBus;
573   UINT16                  SubordinateBus;
574   UINT8                   Bus;
575   UINT8                   Device;
576   UINT8                   Func;
577 
578   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
579 
580   Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);
581   Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);
582   Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);
583 
584   if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
585     return EFI_UNSUPPORTED;
586   }
587 
588   *PciDevicePath  = Private->DevicePath;
589   PrimaryBus      = Private->PrimaryBus;
590   SubordinateBus  = Private->SubordinateBus;
591   do {
592     *PciDevicePath = AppendPciDevicePath (
593                        Private,
594                        Bus,
595                        Device,
596                        Func,
597                        *PciDevicePath,
598                        &PrimaryBus,
599                        &SubordinateBus
600                        );
601     if (*PciDevicePath == NULL) {
602       return EFI_OUT_OF_RESOURCES;
603     }
604   } while (PrimaryBus != 0xffff);
605 
606   return EFI_SUCCESS;
607 }
608 
609 EFI_STATUS
610 EFIAPI
DeviceIoMap(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_IO_OPERATION_TYPE Operation,IN EFI_PHYSICAL_ADDRESS * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)611 DeviceIoMap (
612   IN     EFI_DEVICE_IO_PROTOCOL   *This,
613   IN     EFI_IO_OPERATION_TYPE    Operation,
614   IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
615   IN OUT UINTN                    *NumberOfBytes,
616   OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
617   OUT    VOID                     **Mapping
618   )
619 /*++
620 
621 Routine Description:
622 
623   Provides the device-specific addresses needed to access system memory.
624 
625 Arguments:
626 
627   This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
628   Operation      -  Indicates if the bus master is going to read or write to system memory.
629   HostAddress    -  The system memory address to map to the device.
630   NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes
631                     that were mapped.
632   DeviceAddress  -  The resulting map address for the bus master device to use to access the
633                     hosts HostAddress.
634   Mapping        -  A resulting value to pass to Unmap().
635 
636 Returns:
637 
638   EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes.
639   EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined.
640   EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.
641   EFI_DEVICE_ERROR       -  The system hardware could not map the requested address.
642   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.
643 
644 --*/
645 {
646   EFI_STATUS              Status;
647   DEVICE_IO_PRIVATE_DATA  *Private;
648 
649   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
650 
651   if ((UINT32)Operation > EfiBusMasterCommonBuffer) {
652     return EFI_INVALID_PARAMETER;
653   }
654 
655   if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
656     return EFI_UNSUPPORTED;
657   }
658 
659   Status = Private->PciRootBridgeIo->Map (
660                                        Private->PciRootBridgeIo,
661                                        (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
662                                        (VOID *) (UINTN) (*HostAddress),
663                                        NumberOfBytes,
664                                        DeviceAddress,
665                                        Mapping
666                                        );
667 
668   return Status;
669 }
670 
671 EFI_STATUS
672 EFIAPI
DeviceIoUnmap(IN EFI_DEVICE_IO_PROTOCOL * This,IN VOID * Mapping)673 DeviceIoUnmap (
674   IN EFI_DEVICE_IO_PROTOCOL   *This,
675   IN VOID                     *Mapping
676   )
677 /*++
678 
679 Routine Description:
680 
681   Completes the Map() operation and releases any corresponding resources.
682 
683 Arguments:
684 
685   This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
686   Mapping  -  The mapping value returned from Map().
687 
688 Returns:
689 
690   EFI_SUCCESS       -  The range was unmapped.
691   EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.
692 
693 --*/
694 {
695   EFI_STATUS              Status;
696   DEVICE_IO_PRIVATE_DATA  *Private;
697 
698   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
699 
700   Status = Private->PciRootBridgeIo->Unmap (
701                                        Private->PciRootBridgeIo,
702                                        Mapping
703                                        );
704 
705   return Status;
706 }
707 
708 EFI_STATUS
709 EFIAPI
DeviceIoAllocateBuffer(IN EFI_DEVICE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN OUT EFI_PHYSICAL_ADDRESS * PhysicalAddress)710 DeviceIoAllocateBuffer (
711   IN     EFI_DEVICE_IO_PROTOCOL    *This,
712   IN     EFI_ALLOCATE_TYPE         Type,
713   IN     EFI_MEMORY_TYPE           MemoryType,
714   IN     UINTN                     Pages,
715   IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress
716   )
717 /*++
718 
719 Routine Description:
720 
721   Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
722 
723 Arguments:
724 
725   This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
726   Type             -  The type allocation to perform.
727   MemoryType       -  The type of memory to allocate, EfiBootServicesData or
728                       EfiRuntimeServicesData.
729   Pages            -  The number of pages to allocate.
730   PhysicalAddress  -  A pointer to store the base address of the allocated range.
731 
732 Returns:
733 
734   EFI_SUCCESS            -  The requested memory pages were allocated.
735   EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.
736   EFI_INVALID_PARAMETER  -  The requested memory type is invalid.
737   EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on
738                             this platform.
739 
740 --*/
741 {
742   EFI_STATUS            Status;
743   EFI_PHYSICAL_ADDRESS  HostAddress;
744 
745   HostAddress = *PhysicalAddress;
746 
747   if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
748     return EFI_INVALID_PARAMETER;
749   }
750 
751   if ((UINT32)Type >= MaxAllocateType) {
752     return EFI_INVALID_PARAMETER;
753   }
754 
755   if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
756     return EFI_UNSUPPORTED;
757   }
758 
759   if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
760     Type        = AllocateMaxAddress;
761     HostAddress = MAX_COMMON_BUFFER;
762   }
763 
764   Status = gBS->AllocatePages (
765                   Type,
766                   MemoryType,
767                   Pages,
768                   &HostAddress
769                   );
770   if (EFI_ERROR (Status)) {
771     return Status;
772   }
773 
774 
775   *PhysicalAddress = HostAddress;
776 
777   return EFI_SUCCESS;
778 }
779 
780 EFI_STATUS
781 EFIAPI
DeviceIoFlush(IN EFI_DEVICE_IO_PROTOCOL * This)782 DeviceIoFlush (
783   IN EFI_DEVICE_IO_PROTOCOL  *This
784   )
785 /*++
786 
787 Routine Description:
788 
789   Flushes any posted write data to the device.
790 
791 Arguments:
792 
793   This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
794 
795 Returns:
796 
797   EFI_SUCCESS       -  The buffers were flushed.
798   EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.
799 
800 --*/
801 {
802   EFI_STATUS              Status;
803   DEVICE_IO_PRIVATE_DATA  *Private;
804 
805   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
806 
807   Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
808 
809   return Status;
810 }
811 
812 EFI_STATUS
813 EFIAPI
DeviceIoFreeBuffer(IN EFI_DEVICE_IO_PROTOCOL * This,IN UINTN Pages,IN EFI_PHYSICAL_ADDRESS HostAddress)814 DeviceIoFreeBuffer (
815   IN EFI_DEVICE_IO_PROTOCOL   *This,
816   IN UINTN                    Pages,
817   IN EFI_PHYSICAL_ADDRESS     HostAddress
818   )
819 /*++
820 
821 Routine Description:
822 
823   Frees pages that were allocated with AllocateBuffer().
824 
825 Arguments:
826 
827   This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
828   Pages        -  The number of pages to free.
829   HostAddress  -  The base address of the range to free.
830 
831 Returns:
832 
833   EFI_SUCCESS            -  The requested memory pages were freed.
834   EFI_NOT_FOUND          -  The requested memory pages were not allocated with
835                             AllocateBuffer().
836   EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.
837 
838 --*/
839 {
840   if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
841     return EFI_INVALID_PARAMETER;
842   }
843 
844   return gBS->FreePages (HostAddress, Pages);
845 }
846