]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
5b7ebfad909688353a9fe4184e082db1bf99e4d4
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / HubPeim.c
1 /** @file
2 Usb Hub Request Support In PEI Phase
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 "HubPeim.h"
19 #include "PeiUsbLib.h"
20
21 /**
22 Get a given hub port status.
23
24 @param PeiServices General-purpose services that are available to every PEIM.
25 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
26 @param Port Usb hub port number (starting from 1).
27 @param PortStatus Current Hub port status and change status.
28
29 @retval EFI_SUCCESS Port status is obtained successfully.
30 @retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
31 @retval Others Other failure occurs.
32
33 **/
34 EFI_STATUS
35 PeiHubGetPortStatus (
36 IN EFI_PEI_SERVICES **PeiServices,
37 IN PEI_USB_IO_PPI *UsbIoPpi,
38 IN UINT8 Port,
39 OUT UINT32 *PortStatus
40 )
41 {
42 EFI_USB_DEVICE_REQUEST DeviceRequest;
43
44 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
45
46 //
47 // Fill Device request packet
48 //
49 DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;
50 DeviceRequest.Request = USB_HUB_GET_PORT_STATUS;
51 DeviceRequest.Index = Port;
52 DeviceRequest.Length = (UINT16) sizeof (UINT32);
53
54
55 return UsbIoPpi->UsbControlTransfer (
56 PeiServices,
57 UsbIoPpi,
58 &DeviceRequest,
59 EfiUsbDataIn,
60 PcdGet32 (PcdUsbTransferTimeoutValue),
61 PortStatus,
62 sizeof (UINT32)
63 );
64
65 }
66
67 /**
68 Set specified feature to a given hub port.
69
70 @param PeiServices General-purpose services that are available to every PEIM.
71 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
72 @param Port Usb hub port number (starting from 1).
73 @param Value New feature value.
74
75 @retval EFI_SUCCESS Port feature is set successfully.
76 @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
77 @retval Others Other failure occurs.
78
79 **/
80 EFI_STATUS
81 PeiHubSetPortFeature (
82 IN EFI_PEI_SERVICES **PeiServices,
83 IN PEI_USB_IO_PPI *UsbIoPpi,
84 IN UINT8 Port,
85 IN UINT8 Value
86 )
87 {
88 EFI_USB_DEVICE_REQUEST DeviceRequest;
89
90 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
91
92 //
93 // Fill Device request packet
94 //
95 DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;
96 DeviceRequest.Request = USB_HUB_SET_PORT_FEATURE;
97 DeviceRequest.Value = Value;
98 DeviceRequest.Index = Port;
99
100 return UsbIoPpi->UsbControlTransfer (
101 PeiServices,
102 UsbIoPpi,
103 &DeviceRequest,
104 EfiUsbNoData,
105 PcdGet32 (PcdUsbTransferTimeoutValue),
106 NULL,
107 0
108 );
109 }
110
111 /**
112 Clear specified feature on a given hub port.
113
114 @param PeiServices General-purpose services that are available to every PEIM.
115 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
116 @param Port Usb hub port number (starting from 1).
117 @param Value Feature value that will be cleared from the hub port.
118
119 @retval EFI_SUCCESS Port feature is cleared successfully.
120 @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
121 @retval Others Other failure occurs.
122
123 **/
124 EFI_STATUS
125 PeiHubClearPortFeature (
126 IN EFI_PEI_SERVICES **PeiServices,
127 IN PEI_USB_IO_PPI *UsbIoPpi,
128 IN UINT8 Port,
129 IN UINT8 Value
130 )
131 {
132 EFI_USB_DEVICE_REQUEST DeviceRequest;
133
134 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
135
136 //
137 // Fill Device request packet
138 //
139 DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
140 DeviceRequest.Request = USB_HUB_CLEAR_FEATURE_PORT;
141 DeviceRequest.Value = Value;
142 DeviceRequest.Index = Port;
143
144 return UsbIoPpi->UsbControlTransfer (
145 PeiServices,
146 UsbIoPpi,
147 &DeviceRequest,
148 EfiUsbNoData,
149 PcdGet32 (PcdUsbTransferTimeoutValue),
150 NULL,
151 0
152 );
153 }
154
155 /**
156 Get a given hub status.
157
158 @param PeiServices General-purpose services that are available to every PEIM.
159 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
160 @param HubStatus Current Hub status and change status.
161
162 @retval EFI_SUCCESS Hub status is obtained successfully.
163 @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
164 @retval Others Other failure occurs.
165
166 **/
167 EFI_STATUS
168 PeiHubGetHubStatus (
169 IN EFI_PEI_SERVICES **PeiServices,
170 IN PEI_USB_IO_PPI *UsbIoPpi,
171 OUT UINT32 *HubStatus
172 )
173 {
174 EFI_USB_DEVICE_REQUEST DeviceRequest;
175
176 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
177
178 //
179 // Fill Device request packet
180 //
181 DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;
182 DeviceRequest.Request = USB_HUB_GET_HUB_STATUS;
183 DeviceRequest.Length = (UINT16) sizeof (UINT32);
184
185 return UsbIoPpi->UsbControlTransfer (
186 PeiServices,
187 UsbIoPpi,
188 &DeviceRequest,
189 EfiUsbDataIn,
190 PcdGet32 (PcdUsbTransferTimeoutValue),
191 HubStatus,
192 sizeof (UINT32)
193 );
194 }
195
196 /**
197 Set specified feature to a given hub.
198
199 @param PeiServices General-purpose services that are available to every PEIM.
200 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
201 @param Value New feature value.
202
203 @retval EFI_SUCCESS Port feature is set successfully.
204 @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
205 @retval Others Other failure occurs.
206
207 **/
208 EFI_STATUS
209 PeiHubSetHubFeature (
210 IN EFI_PEI_SERVICES **PeiServices,
211 IN PEI_USB_IO_PPI *UsbIoPpi,
212 IN UINT8 Value
213 )
214 {
215 EFI_USB_DEVICE_REQUEST DeviceRequest;
216
217 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
218
219 //
220 // Fill Device request packet
221 //
222 DeviceRequest.RequestType = USB_HUB_SET_HUB_FEATURE_REQ_TYPE;
223 DeviceRequest.Request = USB_HUB_SET_HUB_FEATURE;
224 DeviceRequest.Value = Value;
225
226 return UsbIoPpi->UsbControlTransfer (
227 PeiServices,
228 UsbIoPpi,
229 &DeviceRequest,
230 EfiUsbNoData,
231 PcdGet32 (PcdUsbTransferTimeoutValue),
232 NULL,
233 0
234 );
235 }
236
237 /**
238 Clear specified feature on a given hub.
239
240 @param PeiServices General-purpose services that are available to every PEIM.
241 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
242 @param Value Feature value that will be cleared from the hub port.
243
244 @retval EFI_SUCCESS Hub feature is cleared successfully.
245 @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
246 @retval Others Other failure occurs.
247
248 **/
249 EFI_STATUS
250 PeiHubClearHubFeature (
251 IN EFI_PEI_SERVICES **PeiServices,
252 IN PEI_USB_IO_PPI *UsbIoPpi,
253 IN UINT8 Value
254 )
255 {
256 EFI_USB_DEVICE_REQUEST DeviceRequest;
257
258 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
259
260 //
261 // Fill Device request packet
262 //
263 DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;
264 DeviceRequest.Request = USB_HUB_CLEAR_FEATURE;
265 DeviceRequest.Value = Value;
266
267 return UsbIoPpi->UsbControlTransfer (
268 PeiServices,
269 UsbIoPpi,
270 &DeviceRequest,
271 EfiUsbNoData,
272 PcdGet32 (PcdUsbTransferTimeoutValue),
273 NULL,
274 0
275 );
276 }
277
278 /**
279 Get a given hub descriptor.
280
281 @param PeiServices General-purpose services that are available to every PEIM.
282 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
283 @param DescriptorSize The length of Hub Descriptor buffer.
284 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
285 successfully returned.
286
287 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
288 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
289 @retval Others Other failure occurs.
290
291 **/
292 EFI_STATUS
293 PeiGetHubDescriptor (
294 IN EFI_PEI_SERVICES **PeiServices,
295 IN PEI_USB_IO_PPI *UsbIoPpi,
296 IN UINTN DescriptorSize,
297 OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
298 )
299 {
300 EFI_USB_DEVICE_REQUEST DevReq;
301 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
302
303 //
304 // Fill Device request packet
305 //
306 DevReq.RequestType = USB_RT_HUB | 0x80;
307 DevReq.Request = USB_HUB_GET_DESCRIPTOR;
308 DevReq.Value = USB_DT_HUB << 8;
309 DevReq.Length = (UINT16)DescriptorSize;
310
311 return UsbIoPpi->UsbControlTransfer (
312 PeiServices,
313 UsbIoPpi,
314 &DevReq,
315 EfiUsbDataIn,
316 PcdGet32 (PcdUsbTransferTimeoutValue),
317 HubDescriptor,
318 (UINT16)DescriptorSize
319 );
320 }
321
322 /**
323 Configure a given hub.
324
325 @param PeiServices General-purpose services that are available to every PEIM.
326 @param PeiUsbDevice Indicating the hub controller device that will be configured
327
328 @retval EFI_SUCCESS Hub configuration is done successfully.
329 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
330
331 **/
332 EFI_STATUS
333 PeiDoHubConfig (
334 IN EFI_PEI_SERVICES **PeiServices,
335 IN PEI_USB_DEVICE *PeiUsbDevice
336 )
337 {
338 EFI_USB_HUB_DESCRIPTOR HubDescriptor;
339 EFI_STATUS Status;
340 EFI_USB_HUB_STATUS HubStatus;
341 UINTN Index;
342 UINT32 PortStatus;
343 PEI_USB_IO_PPI *UsbIoPpi;
344
345 ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
346 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
347
348 //
349 // First get the hub descriptor length
350 //
351 Status = PeiGetHubDescriptor (
352 PeiServices,
353 UsbIoPpi,
354 2,
355 &HubDescriptor
356 );
357 if (EFI_ERROR (Status)) {
358 return EFI_DEVICE_ERROR;
359 }
360 //
361 // First get the whole descriptor, then
362 // get the number of hub ports
363 //
364 Status = PeiGetHubDescriptor (
365 PeiServices,
366 UsbIoPpi,
367 HubDescriptor.Length,
368 &HubDescriptor
369 );
370 if (EFI_ERROR (Status)) {
371 return EFI_DEVICE_ERROR;
372 }
373
374 PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
375
376 Status = PeiHubGetHubStatus (
377 PeiServices,
378 UsbIoPpi,
379 (UINT32 *) &HubStatus
380 );
381
382 if (EFI_ERROR (Status)) {
383 return EFI_DEVICE_ERROR;
384 }
385 //
386 // Get all hub ports status
387 //
388 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
389
390 Status = PeiHubGetPortStatus (
391 PeiServices,
392 UsbIoPpi,
393 (UINT8) (Index + 1),
394 &PortStatus
395 );
396 if (EFI_ERROR (Status)) {
397 continue;
398 }
399 }
400 //
401 // Power all the hub ports
402 //
403 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
404 Status = PeiHubSetPortFeature (
405 PeiServices,
406 UsbIoPpi,
407 (UINT8) (Index + 1),
408 EfiUsbPortPower
409 );
410 if (EFI_ERROR (Status)) {
411 continue;
412 }
413 }
414 //
415 // Clear Hub Status Change
416 //
417 Status = PeiHubGetHubStatus (
418 PeiServices,
419 UsbIoPpi,
420 (UINT32 *) &HubStatus
421 );
422 if (EFI_ERROR (Status)) {
423 return EFI_DEVICE_ERROR;
424 } else {
425 //
426 // Hub power supply change happens
427 //
428 if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
429 PeiHubClearHubFeature (
430 PeiServices,
431 UsbIoPpi,
432 C_HUB_LOCAL_POWER
433 );
434 }
435 //
436 // Hub change overcurrent happens
437 //
438 if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
439 PeiHubClearHubFeature (
440 PeiServices,
441 UsbIoPpi,
442 C_HUB_OVER_CURRENT
443 );
444 }
445 }
446
447 return EFI_SUCCESS;
448 }
449
450 /**
451 Send reset signal over the given root hub port.
452
453 @param PeiServices General-purpose services that are available to every PEIM.
454 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
455 @param PortNum Usb hub port number (starting from 1).
456
457 **/
458 VOID
459 PeiResetHubPort (
460 IN EFI_PEI_SERVICES **PeiServices,
461 IN PEI_USB_IO_PPI *UsbIoPpi,
462 IN UINT8 PortNum
463 )
464 {
465 UINT8 Try;
466 EFI_USB_PORT_STATUS HubPortStatus;
467
468
469 MicroSecondDelay (100 * 1000);
470
471 //
472 // reset root port
473 //
474 PeiHubSetPortFeature (
475 PeiServices,
476 UsbIoPpi,
477 PortNum,
478 EfiUsbPortReset
479 );
480
481 Try = 10;
482 do {
483 PeiHubGetPortStatus (
484 PeiServices,
485 UsbIoPpi,
486 PortNum,
487 (UINT32 *) &HubPortStatus
488 );
489
490 MicroSecondDelay (2 * 1000);
491 Try -= 1;
492 } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Try > 0);
493
494 //
495 // clear reset root port
496 //
497 PeiHubClearPortFeature (
498 PeiServices,
499 UsbIoPpi,
500 PortNum,
501 EfiUsbPortReset
502 );
503
504 MicroSecondDelay (1 * 1000);
505
506 PeiHubClearPortFeature (
507 PeiServices,
508 UsbIoPpi,
509 PortNum,
510 EfiUsbPortConnectChange
511 );
512
513 //
514 // Set port enable
515 //
516 PeiHubSetPortFeature (
517 PeiServices,
518 UsbIoPpi,
519 PortNum,
520 EfiUsbPortEnable
521 );
522
523 //
524 // Clear any change status
525 //
526
527 PeiHubClearPortFeature (
528 PeiServices,
529 UsbIoPpi,
530 PortNum,
531 EfiUsbPortEnableChange
532 );
533
534 MicroSecondDelay (10 * 1000);
535
536 return;
537 }