2 Usb Hub Request Support In PEI Phase
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "PeiUsbLib.h"
15 Get a given hub port status.
17 @param PeiServices General-purpose services that are available to every PEIM.
18 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
19 @param Port Usb hub port number (starting from 1).
20 @param PortStatus Current Hub port status and change status.
22 @retval EFI_SUCCESS Port status is obtained successfully.
23 @retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
24 @retval Others Other failure occurs.
29 IN EFI_PEI_SERVICES
**PeiServices
,
30 IN PEI_USB_IO_PPI
*UsbIoPpi
,
32 OUT UINT32
*PortStatus
35 EFI_USB_DEVICE_REQUEST DeviceRequest
;
37 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
40 // Fill Device request packet
42 DeviceRequest
.RequestType
= USB_HUB_GET_PORT_STATUS_REQ_TYPE
;
43 DeviceRequest
.Request
= USB_HUB_GET_PORT_STATUS
;
44 DeviceRequest
.Index
= Port
;
45 DeviceRequest
.Length
= (UINT16
) sizeof (UINT32
);
48 return UsbIoPpi
->UsbControlTransfer (
53 PcdGet32 (PcdUsbTransferTimeoutValue
),
61 Set specified feature to a given hub port.
63 @param PeiServices General-purpose services that are available to every PEIM.
64 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
65 @param Port Usb hub port number (starting from 1).
66 @param Value New feature value.
68 @retval EFI_SUCCESS Port feature is set successfully.
69 @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
70 @retval Others Other failure occurs.
74 PeiHubSetPortFeature (
75 IN EFI_PEI_SERVICES
**PeiServices
,
76 IN PEI_USB_IO_PPI
*UsbIoPpi
,
81 EFI_USB_DEVICE_REQUEST DeviceRequest
;
83 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
86 // Fill Device request packet
88 DeviceRequest
.RequestType
= USB_HUB_SET_PORT_FEATURE_REQ_TYPE
;
89 DeviceRequest
.Request
= USB_HUB_SET_PORT_FEATURE
;
90 DeviceRequest
.Value
= Value
;
91 DeviceRequest
.Index
= Port
;
93 return UsbIoPpi
->UsbControlTransfer (
98 PcdGet32 (PcdUsbTransferTimeoutValue
),
105 Clear specified feature on a given hub port.
107 @param PeiServices General-purpose services that are available to every PEIM.
108 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
109 @param Port Usb hub port number (starting from 1).
110 @param Value Feature value that will be cleared from the hub port.
112 @retval EFI_SUCCESS Port feature is cleared successfully.
113 @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
114 @retval Others Other failure occurs.
118 PeiHubClearPortFeature (
119 IN EFI_PEI_SERVICES
**PeiServices
,
120 IN PEI_USB_IO_PPI
*UsbIoPpi
,
125 EFI_USB_DEVICE_REQUEST DeviceRequest
;
127 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
130 // Fill Device request packet
132 DeviceRequest
.RequestType
= USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE
;
133 DeviceRequest
.Request
= USB_HUB_CLEAR_FEATURE_PORT
;
134 DeviceRequest
.Value
= Value
;
135 DeviceRequest
.Index
= Port
;
137 return UsbIoPpi
->UsbControlTransfer (
142 PcdGet32 (PcdUsbTransferTimeoutValue
),
149 Get a given hub status.
151 @param PeiServices General-purpose services that are available to every PEIM.
152 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
153 @param HubStatus Current Hub status and change status.
155 @retval EFI_SUCCESS Hub status is obtained successfully.
156 @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
157 @retval Others Other failure occurs.
162 IN EFI_PEI_SERVICES
**PeiServices
,
163 IN PEI_USB_IO_PPI
*UsbIoPpi
,
164 OUT UINT32
*HubStatus
167 EFI_USB_DEVICE_REQUEST DeviceRequest
;
169 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
172 // Fill Device request packet
174 DeviceRequest
.RequestType
= USB_HUB_GET_HUB_STATUS_REQ_TYPE
;
175 DeviceRequest
.Request
= USB_HUB_GET_HUB_STATUS
;
176 DeviceRequest
.Length
= (UINT16
) sizeof (UINT32
);
178 return UsbIoPpi
->UsbControlTransfer (
183 PcdGet32 (PcdUsbTransferTimeoutValue
),
192 Clear specified feature on a given hub.
194 @param PeiServices General-purpose services that are available to every PEIM.
195 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
196 @param Value Feature value that will be cleared from the hub port.
198 @retval EFI_SUCCESS Hub feature is cleared successfully.
199 @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
200 @retval Others Other failure occurs.
204 PeiHubClearHubFeature (
205 IN EFI_PEI_SERVICES
**PeiServices
,
206 IN PEI_USB_IO_PPI
*UsbIoPpi
,
210 EFI_USB_DEVICE_REQUEST DeviceRequest
;
212 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
215 // Fill Device request packet
217 DeviceRequest
.RequestType
= USB_HUB_CLEAR_FEATURE_REQ_TYPE
;
218 DeviceRequest
.Request
= USB_HUB_CLEAR_FEATURE
;
219 DeviceRequest
.Value
= Value
;
221 return UsbIoPpi
->UsbControlTransfer (
226 PcdGet32 (PcdUsbTransferTimeoutValue
),
233 Get a given (SuperSpeed) hub descriptor.
235 @param PeiServices General-purpose services that are available to every PEIM.
236 @param PeiUsbDevice Indicates the hub controller device.
237 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
238 @param DescriptorSize The length of Hub Descriptor buffer.
239 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
240 successfully returned.
242 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
243 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
244 @retval Others Other failure occurs.
248 PeiGetHubDescriptor (
249 IN EFI_PEI_SERVICES
**PeiServices
,
250 IN PEI_USB_DEVICE
*PeiUsbDevice
,
251 IN PEI_USB_IO_PPI
*UsbIoPpi
,
252 IN UINTN DescriptorSize
,
253 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
256 EFI_USB_DEVICE_REQUEST DevReq
;
259 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
261 DescType
= (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) ?
262 USB_DT_SUPERSPEED_HUB
:
266 // Fill Device request packet
268 DevReq
.RequestType
= USB_RT_HUB
| 0x80;
269 DevReq
.Request
= USB_HUB_GET_DESCRIPTOR
;
270 DevReq
.Value
= (UINT16
) (DescType
<< 8);
271 DevReq
.Length
= (UINT16
) DescriptorSize
;
273 return UsbIoPpi
->UsbControlTransfer (
278 PcdGet32 (PcdUsbTransferTimeoutValue
),
280 (UINT16
)DescriptorSize
285 Read the whole usb hub descriptor. It is necessary
286 to do it in two steps because hub descriptor is of
289 @param PeiServices General-purpose services that are available to every PEIM.
290 @param PeiUsbDevice Indicates the hub controller device.
291 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
292 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
293 successfully returned.
295 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
296 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
297 @retval Others Other failure occurs.
302 IN EFI_PEI_SERVICES
**PeiServices
,
303 IN PEI_USB_DEVICE
*PeiUsbDevice
,
304 IN PEI_USB_IO_PPI
*UsbIoPpi
,
305 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
311 // First get the hub descriptor length
313 Status
= PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, 2, HubDescriptor
);
315 if (EFI_ERROR (Status
)) {
320 // Get the whole hub descriptor
322 return PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, HubDescriptor
->Length
, HubDescriptor
);
326 USB hub control transfer to set the hub depth.
328 @param PeiServices General-purpose services that are available to every PEIM.
329 @param PeiUsbDevice Indicates the hub controller device.
330 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
332 @retval EFI_SUCCESS Depth of the hub is set.
333 @retval Others Failed to set the depth.
337 PeiUsbHubCtrlSetHubDepth (
338 IN EFI_PEI_SERVICES
**PeiServices
,
339 IN PEI_USB_DEVICE
*PeiUsbDevice
,
340 IN PEI_USB_IO_PPI
*UsbIoPpi
343 EFI_USB_DEVICE_REQUEST DevReq
;
344 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
347 // Fill Device request packet
349 DevReq
.RequestType
= USB_RT_HUB
;
350 DevReq
.Request
= USB_HUB_REQ_SET_DEPTH
;
351 DevReq
.Value
= PeiUsbDevice
->Tier
;
354 return UsbIoPpi
->UsbControlTransfer (
359 PcdGet32 (PcdUsbTransferTimeoutValue
),
366 Configure a given hub.
368 @param PeiServices General-purpose services that are available to every PEIM.
369 @param PeiUsbDevice Indicating the hub controller device that will be configured
371 @retval EFI_SUCCESS Hub configuration is done successfully.
372 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
377 IN EFI_PEI_SERVICES
**PeiServices
,
378 IN PEI_USB_DEVICE
*PeiUsbDevice
381 UINT8 HubDescBuffer
[256];
382 EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
;
384 EFI_USB_HUB_STATUS HubStatus
;
386 PEI_USB_IO_PPI
*UsbIoPpi
;
388 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
391 // The length field of descriptor is UINT8 type, so the buffer
392 // with 256 bytes is enough to hold the descriptor data.
394 HubDescriptor
= (EFI_USB_HUB_DESCRIPTOR
*) HubDescBuffer
;
397 // Get the hub descriptor
399 Status
= PeiUsbHubReadDesc (
405 if (EFI_ERROR (Status
)) {
406 return EFI_DEVICE_ERROR
;
409 PeiUsbDevice
->DownStreamPortNo
= HubDescriptor
->NbrPorts
;
411 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) {
412 DEBUG ((DEBUG_INFO
, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice
->Tier
));
413 PeiUsbHubCtrlSetHubDepth (
420 // Power all the hub ports
422 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
423 Status
= PeiHubSetPortFeature (
429 if (EFI_ERROR (Status
)) {
430 DEBUG (( DEBUG_ERROR
, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index
));
435 DEBUG (( DEBUG_INFO
, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor
->PwrOn2PwrGood
));
436 if (HubDescriptor
->PwrOn2PwrGood
> 0) {
437 MicroSecondDelay (HubDescriptor
->PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
441 // Clear Hub Status Change
443 Status
= PeiHubGetHubStatus (
446 (UINT32
*) &HubStatus
448 if (EFI_ERROR (Status
)) {
449 return EFI_DEVICE_ERROR
;
452 // Hub power supply change happens
454 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_LOCAL_POWER
) != 0) {
455 PeiHubClearHubFeature (
462 // Hub change overcurrent happens
464 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_OVERCURRENT
) != 0) {
465 PeiHubClearHubFeature (
478 Send reset signal over the given root hub port.
480 @param PeiServices General-purpose services that are available to every PEIM.
481 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
482 @param PortNum Usb hub port number (starting from 1).
487 IN EFI_PEI_SERVICES
**PeiServices
,
488 IN PEI_USB_IO_PPI
*UsbIoPpi
,
494 EFI_USB_PORT_STATUS HubPortStatus
;
496 MicroSecondDelay (100 * 1000);
501 PeiHubSetPortFeature (
509 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
510 // section 7.1.7.5 for timing requirements.
512 MicroSecondDelay (USB_SET_PORT_RESET_STALL
);
515 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
517 ZeroMem (&HubPortStatus
, sizeof (EFI_USB_PORT_STATUS
));
519 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
520 Status
= PeiHubGetPortStatus (
524 (UINT32
*) &HubPortStatus
527 if (EFI_ERROR (Status
)) {
531 if (USB_BIT_IS_SET (HubPortStatus
.PortChangeStatus
, USB_PORT_STAT_C_RESET
)) {
535 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
538 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
539 DEBUG ((DEBUG_ERROR
, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum
));
544 // clear reset change root port
546 PeiHubClearPortFeature (
550 EfiUsbPortResetChange
553 MicroSecondDelay (1 * 1000);
555 PeiHubClearPortFeature (
559 EfiUsbPortConnectChange
565 PeiHubSetPortFeature (
573 // Clear any change status
576 PeiHubClearPortFeature (
580 EfiUsbPortEnableChange
583 MicroSecondDelay (10 * 1000);