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