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
);
47 return UsbIoPpi
->UsbControlTransfer (
52 PcdGet32 (PcdUsbTransferTimeoutValue
),
59 Set specified feature to a given hub port.
61 @param PeiServices General-purpose services that are available to every PEIM.
62 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
63 @param Port Usb hub port number (starting from 1).
64 @param Value New feature value.
66 @retval EFI_SUCCESS Port feature is set successfully.
67 @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
68 @retval Others Other failure occurs.
72 PeiHubSetPortFeature (
73 IN EFI_PEI_SERVICES
**PeiServices
,
74 IN PEI_USB_IO_PPI
*UsbIoPpi
,
79 EFI_USB_DEVICE_REQUEST DeviceRequest
;
81 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
84 // Fill Device request packet
86 DeviceRequest
.RequestType
= USB_HUB_SET_PORT_FEATURE_REQ_TYPE
;
87 DeviceRequest
.Request
= USB_HUB_SET_PORT_FEATURE
;
88 DeviceRequest
.Value
= Value
;
89 DeviceRequest
.Index
= Port
;
91 return UsbIoPpi
->UsbControlTransfer (
96 PcdGet32 (PcdUsbTransferTimeoutValue
),
103 Clear specified feature on a given hub port.
105 @param PeiServices General-purpose services that are available to every PEIM.
106 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
107 @param Port Usb hub port number (starting from 1).
108 @param Value Feature value that will be cleared from the hub port.
110 @retval EFI_SUCCESS Port feature is cleared successfully.
111 @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
112 @retval Others Other failure occurs.
116 PeiHubClearPortFeature (
117 IN EFI_PEI_SERVICES
**PeiServices
,
118 IN PEI_USB_IO_PPI
*UsbIoPpi
,
123 EFI_USB_DEVICE_REQUEST DeviceRequest
;
125 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
128 // Fill Device request packet
130 DeviceRequest
.RequestType
= USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE
;
131 DeviceRequest
.Request
= USB_HUB_CLEAR_FEATURE_PORT
;
132 DeviceRequest
.Value
= Value
;
133 DeviceRequest
.Index
= Port
;
135 return UsbIoPpi
->UsbControlTransfer (
140 PcdGet32 (PcdUsbTransferTimeoutValue
),
147 Get a given hub status.
149 @param PeiServices General-purpose services that are available to every PEIM.
150 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
151 @param HubStatus Current Hub status and change status.
153 @retval EFI_SUCCESS Hub status is obtained successfully.
154 @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
155 @retval Others Other failure occurs.
160 IN EFI_PEI_SERVICES
**PeiServices
,
161 IN PEI_USB_IO_PPI
*UsbIoPpi
,
162 OUT UINT32
*HubStatus
165 EFI_USB_DEVICE_REQUEST DeviceRequest
;
167 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
170 // Fill Device request packet
172 DeviceRequest
.RequestType
= USB_HUB_GET_HUB_STATUS_REQ_TYPE
;
173 DeviceRequest
.Request
= USB_HUB_GET_HUB_STATUS
;
174 DeviceRequest
.Length
= (UINT16
)sizeof (UINT32
);
176 return UsbIoPpi
->UsbControlTransfer (
181 PcdGet32 (PcdUsbTransferTimeoutValue
),
188 Clear specified feature on a given hub.
190 @param PeiServices General-purpose services that are available to every PEIM.
191 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
192 @param Value Feature value that will be cleared from the hub port.
194 @retval EFI_SUCCESS Hub feature is cleared successfully.
195 @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
196 @retval Others Other failure occurs.
200 PeiHubClearHubFeature (
201 IN EFI_PEI_SERVICES
**PeiServices
,
202 IN PEI_USB_IO_PPI
*UsbIoPpi
,
206 EFI_USB_DEVICE_REQUEST DeviceRequest
;
208 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
211 // Fill Device request packet
213 DeviceRequest
.RequestType
= USB_HUB_CLEAR_FEATURE_REQ_TYPE
;
214 DeviceRequest
.Request
= USB_HUB_CLEAR_FEATURE
;
215 DeviceRequest
.Value
= Value
;
217 return UsbIoPpi
->UsbControlTransfer (
222 PcdGet32 (PcdUsbTransferTimeoutValue
),
229 Get a given (SuperSpeed) hub descriptor.
231 @param PeiServices General-purpose services that are available to every PEIM.
232 @param PeiUsbDevice Indicates the hub controller device.
233 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
234 @param DescriptorSize The length of Hub Descriptor buffer.
235 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
236 successfully returned.
238 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
239 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
240 @retval Others Other failure occurs.
244 PeiGetHubDescriptor (
245 IN EFI_PEI_SERVICES
**PeiServices
,
246 IN PEI_USB_DEVICE
*PeiUsbDevice
,
247 IN PEI_USB_IO_PPI
*UsbIoPpi
,
248 IN UINTN DescriptorSize
,
249 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
252 EFI_USB_DEVICE_REQUEST DevReq
;
255 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
257 DescType
= (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) ?
258 USB_DT_SUPERSPEED_HUB
:
262 // Fill Device request packet
264 DevReq
.RequestType
= USB_RT_HUB
| 0x80;
265 DevReq
.Request
= USB_HUB_GET_DESCRIPTOR
;
266 DevReq
.Value
= (UINT16
)(DescType
<< 8);
267 DevReq
.Length
= (UINT16
)DescriptorSize
;
269 return UsbIoPpi
->UsbControlTransfer (
274 PcdGet32 (PcdUsbTransferTimeoutValue
),
276 (UINT16
)DescriptorSize
281 Read the whole usb hub descriptor. It is necessary
282 to do it in two steps because hub descriptor is of
285 @param PeiServices General-purpose services that are available to every PEIM.
286 @param PeiUsbDevice Indicates the hub controller device.
287 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
288 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
289 successfully returned.
291 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
292 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
293 @retval Others Other failure occurs.
298 IN EFI_PEI_SERVICES
**PeiServices
,
299 IN PEI_USB_DEVICE
*PeiUsbDevice
,
300 IN PEI_USB_IO_PPI
*UsbIoPpi
,
301 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
307 // First get the hub descriptor length
309 Status
= PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, 2, HubDescriptor
);
311 if (EFI_ERROR (Status
)) {
316 // Get the whole hub descriptor
318 return PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, HubDescriptor
->Length
, HubDescriptor
);
322 USB hub control transfer to set the hub depth.
324 @param PeiServices General-purpose services that are available to every PEIM.
325 @param PeiUsbDevice Indicates the hub controller device.
326 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
328 @retval EFI_SUCCESS Depth of the hub is set.
329 @retval Others Failed to set the depth.
333 PeiUsbHubCtrlSetHubDepth (
334 IN EFI_PEI_SERVICES
**PeiServices
,
335 IN PEI_USB_DEVICE
*PeiUsbDevice
,
336 IN PEI_USB_IO_PPI
*UsbIoPpi
339 EFI_USB_DEVICE_REQUEST DevReq
;
341 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
344 // Fill Device request packet
346 DevReq
.RequestType
= USB_RT_HUB
;
347 DevReq
.Request
= USB_HUB_REQ_SET_DEPTH
;
348 DevReq
.Value
= PeiUsbDevice
->Tier
;
351 return UsbIoPpi
->UsbControlTransfer (
356 PcdGet32 (PcdUsbTransferTimeoutValue
),
363 Configure a given hub.
365 @param PeiServices General-purpose services that are available to every PEIM.
366 @param PeiUsbDevice Indicating the hub controller device that will be configured
368 @retval EFI_SUCCESS Hub configuration is done successfully.
369 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
374 IN EFI_PEI_SERVICES
**PeiServices
,
375 IN PEI_USB_DEVICE
*PeiUsbDevice
378 UINT8 HubDescBuffer
[256];
379 EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
;
381 EFI_USB_HUB_STATUS HubStatus
;
383 PEI_USB_IO_PPI
*UsbIoPpi
;
385 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
388 // The length field of descriptor is UINT8 type, so the buffer
389 // with 256 bytes is enough to hold the descriptor data.
391 HubDescriptor
= (EFI_USB_HUB_DESCRIPTOR
*)HubDescBuffer
;
394 // Get the hub descriptor
396 Status
= PeiUsbHubReadDesc (
402 if (EFI_ERROR (Status
)) {
403 return EFI_DEVICE_ERROR
;
406 PeiUsbDevice
->DownStreamPortNo
= HubDescriptor
->NbrPorts
;
408 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) {
409 DEBUG ((DEBUG_INFO
, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice
->Tier
));
410 PeiUsbHubCtrlSetHubDepth (
417 // Power all the hub ports
419 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
420 Status
= PeiHubSetPortFeature (
426 if (EFI_ERROR (Status
)) {
427 DEBUG ((DEBUG_ERROR
, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index
));
432 DEBUG ((DEBUG_INFO
, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor
->PwrOn2PwrGood
));
433 if (HubDescriptor
->PwrOn2PwrGood
> 0) {
434 MicroSecondDelay (HubDescriptor
->PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
438 // Clear Hub Status Change
440 Status
= PeiHubGetHubStatus (
445 if (EFI_ERROR (Status
)) {
446 return EFI_DEVICE_ERROR
;
449 // Hub power supply change happens
451 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_LOCAL_POWER
) != 0) {
452 PeiHubClearHubFeature (
460 // Hub change overcurrent happens
462 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_OVERCURRENT
) != 0) {
463 PeiHubClearHubFeature (
476 Send reset signal over the given root hub port.
478 @param PeiServices General-purpose services that are available to every PEIM.
479 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
480 @param PortNum Usb hub port number (starting from 1).
485 IN EFI_PEI_SERVICES
**PeiServices
,
486 IN PEI_USB_IO_PPI
*UsbIoPpi
,
492 EFI_USB_PORT_STATUS HubPortStatus
;
494 MicroSecondDelay (100 * 1000);
499 PeiHubSetPortFeature (
507 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
508 // section 7.1.7.5 for timing requirements.
510 MicroSecondDelay (USB_SET_PORT_RESET_STALL
);
513 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
515 ZeroMem (&HubPortStatus
, sizeof (EFI_USB_PORT_STATUS
));
517 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
518 Status
= PeiHubGetPortStatus (
522 (UINT32
*)&HubPortStatus
525 if (EFI_ERROR (Status
)) {
529 if (USB_BIT_IS_SET (HubPortStatus
.PortChangeStatus
, USB_PORT_STAT_C_RESET
)) {
533 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
536 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
537 DEBUG ((DEBUG_ERROR
, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum
));
542 // clear reset change root port
544 PeiHubClearPortFeature (
548 EfiUsbPortResetChange
551 MicroSecondDelay (1 * 1000);
553 PeiHubClearPortFeature (
557 EfiUsbPortConnectChange
563 PeiHubSetPortFeature (
571 // Clear any change status
574 PeiHubClearPortFeature (
578 EfiUsbPortEnableChange
581 MicroSecondDelay (10 * 1000);