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