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