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