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