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