]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/UhciPei/DmaMem.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciPei / DmaMem.c
1 /** @file
2 The DMA memory help functions.
3
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UhcPeim.h"
11
12 /**
13 Provides the controller-specific addresses required to access system memory from a
14 DMA bus master.
15
16 @param IoMmu Pointer to IOMMU PPI.
17 @param Operation Indicates if the bus master is going to read or write to system memory.
18 @param HostAddress The system memory address to map to the PCI controller.
19 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
20 that were mapped.
21 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
22 access the hosts HostAddress.
23 @param Mapping A resulting value to pass to Unmap().
24
25 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
26 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
27 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
28 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
29 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
30
31 **/
32 EFI_STATUS
33 IoMmuMap (
34 IN EDKII_IOMMU_PPI *IoMmu,
35 IN EDKII_IOMMU_OPERATION Operation,
36 IN VOID *HostAddress,
37 IN OUT UINTN *NumberOfBytes,
38 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
39 OUT VOID **Mapping
40 )
41 {
42 EFI_STATUS Status;
43 UINT64 Attribute;
44
45 if (IoMmu != NULL) {
46 Status = IoMmu->Map (
47 IoMmu,
48 Operation,
49 HostAddress,
50 NumberOfBytes,
51 DeviceAddress,
52 Mapping
53 );
54 if (EFI_ERROR (Status)) {
55 return EFI_OUT_OF_RESOURCES;
56 }
57 switch (Operation) {
58 case EdkiiIoMmuOperationBusMasterRead:
59 case EdkiiIoMmuOperationBusMasterRead64:
60 Attribute = EDKII_IOMMU_ACCESS_READ;
61 break;
62 case EdkiiIoMmuOperationBusMasterWrite:
63 case EdkiiIoMmuOperationBusMasterWrite64:
64 Attribute = EDKII_IOMMU_ACCESS_WRITE;
65 break;
66 case EdkiiIoMmuOperationBusMasterCommonBuffer:
67 case EdkiiIoMmuOperationBusMasterCommonBuffer64:
68 Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
69 break;
70 default:
71 ASSERT(FALSE);
72 return EFI_INVALID_PARAMETER;
73 }
74 Status = IoMmu->SetAttribute (
75 IoMmu,
76 *Mapping,
77 Attribute
78 );
79 if (EFI_ERROR (Status)) {
80 IoMmu->Unmap (IoMmu, Mapping);
81 *Mapping = NULL;
82 return Status;
83 }
84 } else {
85 *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
86 *Mapping = NULL;
87 Status = EFI_SUCCESS;
88 }
89 return Status;
90 }
91
92 /**
93 Completes the Map() operation and releases any corresponding resources.
94
95 @param IoMmu Pointer to IOMMU PPI.
96 @param Mapping The mapping value returned from Map().
97
98 **/
99 VOID
100 IoMmuUnmap (
101 IN EDKII_IOMMU_PPI *IoMmu,
102 IN VOID *Mapping
103 )
104 {
105 if (IoMmu != NULL) {
106 IoMmu->SetAttribute (IoMmu, Mapping, 0);
107 IoMmu->Unmap (IoMmu, Mapping);
108 }
109 }
110
111 /**
112 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
113 OperationBusMasterCommonBuffer64 mapping.
114
115 @param IoMmu Pointer to IOMMU PPI.
116 @param Pages The number of pages to allocate.
117 @param HostAddress A pointer to store the base system memory address of the
118 allocated range.
119 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
120 access the hosts HostAddress.
121 @param Mapping A resulting value to pass to Unmap().
122
123 @retval EFI_SUCCESS The requested memory pages were allocated.
124 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
125 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
126 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
127 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
128
129 **/
130 EFI_STATUS
131 IoMmuAllocateBuffer (
132 IN EDKII_IOMMU_PPI *IoMmu,
133 IN UINTN Pages,
134 OUT VOID **HostAddress,
135 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
136 OUT VOID **Mapping
137 )
138 {
139 EFI_STATUS Status;
140 UINTN NumberOfBytes;
141 EFI_PHYSICAL_ADDRESS HostPhyAddress;
142
143 *HostAddress = NULL;
144 *DeviceAddress = 0;
145 *Mapping = NULL;
146
147 if (IoMmu != NULL) {
148 Status = IoMmu->AllocateBuffer (
149 IoMmu,
150 EfiBootServicesData,
151 Pages,
152 HostAddress,
153 0
154 );
155 if (EFI_ERROR (Status)) {
156 return EFI_OUT_OF_RESOURCES;
157 }
158
159 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
160 Status = IoMmu->Map (
161 IoMmu,
162 EdkiiIoMmuOperationBusMasterCommonBuffer,
163 *HostAddress,
164 &NumberOfBytes,
165 DeviceAddress,
166 Mapping
167 );
168 if (EFI_ERROR (Status)) {
169 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
170 *HostAddress = NULL;
171 return EFI_OUT_OF_RESOURCES;
172 }
173 Status = IoMmu->SetAttribute (
174 IoMmu,
175 *Mapping,
176 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
177 );
178 if (EFI_ERROR (Status)) {
179 IoMmu->Unmap (IoMmu, *Mapping);
180 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
181 *Mapping = NULL;
182 *HostAddress = NULL;
183 return Status;
184 }
185 } else {
186 Status = PeiServicesAllocatePages (
187 EfiBootServicesData,
188 Pages,
189 &HostPhyAddress
190 );
191 if (EFI_ERROR (Status)) {
192 return EFI_OUT_OF_RESOURCES;
193 }
194 *HostAddress = (VOID *) (UINTN) HostPhyAddress;
195 *DeviceAddress = HostPhyAddress;
196 *Mapping = NULL;
197 }
198 return Status;
199 }
200
201
202
203 /**
204 Initialize IOMMU.
205
206 @param IoMmu Pointer to pointer to IOMMU PPI.
207
208 **/
209 VOID
210 IoMmuInit (
211 OUT EDKII_IOMMU_PPI **IoMmu
212 )
213 {
214 *IoMmu = NULL;
215 PeiServicesLocatePpi (
216 &gEdkiiIoMmuPpiGuid,
217 0,
218 NULL,
219 (VOID **) IoMmu
220 );
221 }
222