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