]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbIoPeim.c
1 /** @file
2 The module is used to implement Usb Io PPI interfaces.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UsbPeim.h"
11 #include "PeiUsbLib.h"
12
13 /**
14 Submits control transfer to a target USB device.
15
16 @param PeiServices The pointer of EFI_PEI_SERVICES.
17 @param This The pointer of PEI_USB_IO_PPI.
18 @param Request USB device request to send.
19 @param Direction Specifies the data direction for the data stage.
20 @param Timeout Indicates the maximum timeout, in millisecond. If Timeout
21 is 0, then the caller must wait for the function to be
22 completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
23 @param Data Data buffer to be transmitted or received from USB device.
24 @param DataLength The size (in bytes) of the data buffer.
25
26 @retval EFI_SUCCESS Transfer was completed successfully.
27 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
28 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
29 @retval EFI_TIMEOUT Transfer failed due to timeout.
30 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
31
32 **/
33 EFI_STATUS
34 EFIAPI
35 PeiUsbControlTransfer (
36 IN EFI_PEI_SERVICES **PeiServices,
37 IN PEI_USB_IO_PPI *This,
38 IN EFI_USB_DEVICE_REQUEST *Request,
39 IN EFI_USB_DATA_DIRECTION Direction,
40 IN UINT32 Timeout,
41 IN OUT VOID *Data OPTIONAL,
42 IN UINTN DataLength OPTIONAL
43 )
44 {
45 EFI_STATUS Status;
46 PEI_USB_DEVICE *PeiUsbDev;
47 UINT32 TransferResult;
48 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
49 UINT8 EndpointIndex;
50
51 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
52
53 EndpointDescriptor = NULL;
54 EndpointIndex = 0;
55
56 if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&
57 (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
58 (Request->Value == USB_FEATURE_ENDPOINT_HALT))
59 {
60 //
61 // Request->Index is the Endpoint Address, use it to get the Endpoint Index.
62 //
63 while (EndpointIndex < MAX_ENDPOINT) {
64 Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
65 if (EFI_ERROR (Status)) {
66 return EFI_INVALID_PARAMETER;
67 }
68
69 if (EndpointDescriptor->EndpointAddress == Request->Index) {
70 break;
71 }
72
73 EndpointIndex++;
74 }
75
76 if (EndpointIndex == MAX_ENDPOINT) {
77 return EFI_INVALID_PARAMETER;
78 }
79 }
80
81 if (PeiUsbDev->Usb2HcPpi != NULL) {
82 Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (
83 PeiServices,
84 PeiUsbDev->Usb2HcPpi,
85 PeiUsbDev->DeviceAddress,
86 PeiUsbDev->DeviceSpeed,
87 PeiUsbDev->MaxPacketSize0,
88 Request,
89 Direction,
90 Data,
91 &DataLength,
92 Timeout,
93 &(PeiUsbDev->Translator),
94 &TransferResult
95 );
96 } else {
97 Status = PeiUsbDev->UsbHcPpi->ControlTransfer (
98 PeiServices,
99 PeiUsbDev->UsbHcPpi,
100 PeiUsbDev->DeviceAddress,
101 PeiUsbDev->DeviceSpeed,
102 (UINT8)PeiUsbDev->MaxPacketSize0,
103 Request,
104 Direction,
105 Data,
106 &DataLength,
107 Timeout,
108 &TransferResult
109 );
110 }
111
112 //
113 // Reset the endpoint toggle when endpoint stall is cleared
114 //
115 if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&
116 (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
117 (Request->Value == USB_FEATURE_ENDPOINT_HALT))
118 {
119 if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
120 PeiUsbDev->DataToggle = (UINT16)(PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
121 }
122 }
123
124 DEBUG ((DEBUG_INFO, "PeiUsbControlTransfer: %r\n", Status));
125 return Status;
126 }
127
128 /**
129 Submits bulk transfer to a bulk endpoint of a USB device.
130
131 @param PeiServices The pointer of EFI_PEI_SERVICES.
132 @param This The pointer of PEI_USB_IO_PPI.
133 @param DeviceEndpoint Endpoint number and its direction in bit 7.
134 @param Data A pointer to the buffer of data to transmit
135 from or receive into.
136 @param DataLength The length of the data buffer.
137 @param Timeout Indicates the maximum time, in millisecond, which the
138 transfer is allowed to complete. If Timeout is 0, then
139 the caller must wait for the function to be completed
140 until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
141
142 @retval EFI_SUCCESS The transfer was completed successfully.
143 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
144 @retval EFI_INVALID_PARAMETER Parameters are invalid.
145 @retval EFI_TIMEOUT The transfer failed due to timeout.
146 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
147
148 **/
149 EFI_STATUS
150 EFIAPI
151 PeiUsbBulkTransfer (
152 IN EFI_PEI_SERVICES **PeiServices,
153 IN PEI_USB_IO_PPI *This,
154 IN UINT8 DeviceEndpoint,
155 IN OUT VOID *Data,
156 IN OUT UINTN *DataLength,
157 IN UINTN Timeout
158 )
159 {
160 EFI_STATUS Status;
161 PEI_USB_DEVICE *PeiUsbDev;
162 UINT32 TransferResult;
163 UINTN MaxPacketLength;
164 UINT8 DataToggle;
165 UINT8 OldToggle;
166 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
167 UINT8 EndpointIndex;
168 VOID *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];
169
170 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
171
172 EndpointDescriptor = NULL;
173 EndpointIndex = 0;
174 Data2[0] = Data;
175 Data2[1] = NULL;
176
177 while (EndpointIndex < MAX_ENDPOINT) {
178 Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
179 if (EFI_ERROR (Status)) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
184 break;
185 }
186
187 EndpointIndex++;
188 }
189
190 if (EndpointIndex == MAX_ENDPOINT) {
191 return EFI_INVALID_PARAMETER;
192 }
193
194 MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
195 if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
196 DataToggle = 1;
197 } else {
198 DataToggle = 0;
199 }
200
201 OldToggle = DataToggle;
202
203 if (PeiUsbDev->Usb2HcPpi != NULL) {
204 Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (
205 PeiServices,
206 PeiUsbDev->Usb2HcPpi,
207 PeiUsbDev->DeviceAddress,
208 DeviceEndpoint,
209 PeiUsbDev->DeviceSpeed,
210 MaxPacketLength,
211 Data2,
212 DataLength,
213 &DataToggle,
214 Timeout,
215 &(PeiUsbDev->Translator),
216 &TransferResult
217 );
218 } else {
219 Status = PeiUsbDev->UsbHcPpi->BulkTransfer (
220 PeiServices,
221 PeiUsbDev->UsbHcPpi,
222 PeiUsbDev->DeviceAddress,
223 DeviceEndpoint,
224 (UINT8)MaxPacketLength,
225 Data,
226 DataLength,
227 &DataToggle,
228 Timeout,
229 &TransferResult
230 );
231 }
232
233 if (OldToggle != DataToggle) {
234 PeiUsbDev->DataToggle = (UINT16)(PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
235 }
236
237 DEBUG ((DEBUG_INFO, "PeiUsbBulkTransfer: %r\n", Status));
238 return Status;
239 }
240
241 /**
242 Get the usb interface descriptor.
243
244 @param PeiServices General-purpose services that are available to every PEIM.
245 @param This Indicates the PEI_USB_IO_PPI instance.
246 @param InterfaceDescriptor Request interface descriptor.
247
248
249 @retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
250
251 **/
252 EFI_STATUS
253 EFIAPI
254 PeiUsbGetInterfaceDescriptor (
255 IN EFI_PEI_SERVICES **PeiServices,
256 IN PEI_USB_IO_PPI *This,
257 OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
258 )
259 {
260 PEI_USB_DEVICE *PeiUsbDev;
261
262 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
263 *InterfaceDescriptor = PeiUsbDev->InterfaceDesc;
264 return EFI_SUCCESS;
265 }
266
267 /**
268 Get the usb endpoint descriptor.
269
270 @param PeiServices General-purpose services that are available to every PEIM.
271 @param This Indicates the PEI_USB_IO_PPI instance.
272 @param EndpointIndex The valid index of the specified endpoint.
273 @param EndpointDescriptor Request endpoint descriptor.
274
275 @retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
276 @retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
277
278 **/
279 EFI_STATUS
280 EFIAPI
281 PeiUsbGetEndpointDescriptor (
282 IN EFI_PEI_SERVICES **PeiServices,
283 IN PEI_USB_IO_PPI *This,
284 IN UINT8 EndpointIndex,
285 OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
286 )
287 {
288 PEI_USB_DEVICE *PeiUsbDev;
289
290 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
291
292 ASSERT (EndpointDescriptor != NULL);
293
294 //
295 // The valid range of EndpointIndex is 0..15
296 // If EndpointIndex is lesser than 15 but larger than the number of interfaces,
297 // a EFI_NOT_FOUND should be returned
298 //
299 ASSERT (EndpointIndex <= 15);
300
301 if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
302 return EFI_NOT_FOUND;
303 }
304
305 *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
306
307 return EFI_SUCCESS;
308 }
309
310 /**
311 Reset the port and re-configure the usb device.
312
313 @param PeiServices General-purpose services that are available to every PEIM.
314 @param This Indicates the PEI_USB_IO_PPI instance.
315
316 @retval EFI_SUCCESS Usb device is reset and configured successfully.
317 @retval Others Other failure occurs.
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 PeiUsbPortReset (
323 IN EFI_PEI_SERVICES **PeiServices,
324 IN PEI_USB_IO_PPI *This
325 )
326 {
327 PEI_USB_DEVICE *PeiUsbDev;
328 EFI_STATUS Status;
329 UINT8 Address;
330
331 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
332
333 ResetRootPort (
334 PeiServices,
335 PeiUsbDev->UsbHcPpi,
336 PeiUsbDev->Usb2HcPpi,
337 PeiUsbDev->DeviceAddress,
338 0
339 );
340
341 //
342 // Set address
343 //
344 Address = PeiUsbDev->DeviceAddress;
345 PeiUsbDev->DeviceAddress = 0;
346
347 Status = PeiUsbSetDeviceAddress (
348 PeiServices,
349 This,
350 Address
351 );
352
353 if (EFI_ERROR (Status)) {
354 return Status;
355 }
356
357 PeiUsbDev->DeviceAddress = Address;
358
359 //
360 // Set default configuration
361 //
362 Status = PeiUsbSetConfiguration (
363 PeiServices,
364 This
365 );
366
367 return Status;
368 }