2 Usb Hub Request Support In PEI Phase
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
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
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.
19 #include "PeiUsbLib.h"
22 Get a given hub port status.
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.
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.
36 IN EFI_PEI_SERVICES
**PeiServices
,
37 IN PEI_USB_IO_PPI
*UsbIoPpi
,
39 OUT UINT32
*PortStatus
42 EFI_USB_DEVICE_REQUEST DeviceRequest
;
44 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
47 // Fill Device request packet
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
);
55 return UsbIoPpi
->UsbControlTransfer (
60 PcdGet32 (PcdUsbTransferTimeoutValue
),
68 Set specified feature to a given hub port.
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.
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.
81 PeiHubSetPortFeature (
82 IN EFI_PEI_SERVICES
**PeiServices
,
83 IN PEI_USB_IO_PPI
*UsbIoPpi
,
88 EFI_USB_DEVICE_REQUEST DeviceRequest
;
90 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
93 // Fill Device request packet
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
;
100 return UsbIoPpi
->UsbControlTransfer (
105 PcdGet32 (PcdUsbTransferTimeoutValue
),
112 Clear specified feature on a given hub port.
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.
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.
125 PeiHubClearPortFeature (
126 IN EFI_PEI_SERVICES
**PeiServices
,
127 IN PEI_USB_IO_PPI
*UsbIoPpi
,
132 EFI_USB_DEVICE_REQUEST DeviceRequest
;
134 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
137 // Fill Device request packet
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
;
144 return UsbIoPpi
->UsbControlTransfer (
149 PcdGet32 (PcdUsbTransferTimeoutValue
),
156 Get a given hub status.
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.
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.
169 IN EFI_PEI_SERVICES
**PeiServices
,
170 IN PEI_USB_IO_PPI
*UsbIoPpi
,
171 OUT UINT32
*HubStatus
174 EFI_USB_DEVICE_REQUEST DeviceRequest
;
176 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
179 // Fill Device request packet
181 DeviceRequest
.RequestType
= USB_HUB_GET_HUB_STATUS_REQ_TYPE
;
182 DeviceRequest
.Request
= USB_HUB_GET_HUB_STATUS
;
183 DeviceRequest
.Length
= (UINT16
) sizeof (UINT32
);
185 return UsbIoPpi
->UsbControlTransfer (
190 PcdGet32 (PcdUsbTransferTimeoutValue
),
197 Set specified feature to a given hub.
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.
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.
209 PeiHubSetHubFeature (
210 IN EFI_PEI_SERVICES
**PeiServices
,
211 IN PEI_USB_IO_PPI
*UsbIoPpi
,
215 EFI_USB_DEVICE_REQUEST DeviceRequest
;
217 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
220 // Fill Device request packet
222 DeviceRequest
.RequestType
= USB_HUB_SET_HUB_FEATURE_REQ_TYPE
;
223 DeviceRequest
.Request
= USB_HUB_SET_HUB_FEATURE
;
224 DeviceRequest
.Value
= Value
;
226 return UsbIoPpi
->UsbControlTransfer (
231 PcdGet32 (PcdUsbTransferTimeoutValue
),
238 Clear specified feature on a given hub.
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.
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.
250 PeiHubClearHubFeature (
251 IN EFI_PEI_SERVICES
**PeiServices
,
252 IN PEI_USB_IO_PPI
*UsbIoPpi
,
256 EFI_USB_DEVICE_REQUEST DeviceRequest
;
258 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
261 // Fill Device request packet
263 DeviceRequest
.RequestType
= USB_HUB_CLEAR_FEATURE_REQ_TYPE
;
264 DeviceRequest
.Request
= USB_HUB_CLEAR_FEATURE
;
265 DeviceRequest
.Value
= Value
;
267 return UsbIoPpi
->UsbControlTransfer (
272 PcdGet32 (PcdUsbTransferTimeoutValue
),
279 Get a given (SuperSpeed) hub descriptor.
281 @param PeiServices General-purpose services that are available to every PEIM.
282 @param PeiUsbDevice Indicates the hub controller device.
283 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
284 @param DescriptorSize The length of Hub Descriptor buffer.
285 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
286 successfully returned.
288 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
289 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
290 @retval Others Other failure occurs.
294 PeiGetHubDescriptor (
295 IN EFI_PEI_SERVICES
**PeiServices
,
296 IN PEI_USB_DEVICE
*PeiUsbDevice
,
297 IN PEI_USB_IO_PPI
*UsbIoPpi
,
298 IN UINTN DescriptorSize
,
299 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
302 EFI_USB_DEVICE_REQUEST DevReq
;
305 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
307 DescType
= (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) ?
308 USB_DT_SUPERSPEED_HUB
:
312 // Fill Device request packet
314 DevReq
.RequestType
= USB_RT_HUB
| 0x80;
315 DevReq
.Request
= USB_HUB_GET_DESCRIPTOR
;
316 DevReq
.Value
= (UINT16
) (DescType
<< 8);
317 DevReq
.Length
= (UINT16
) DescriptorSize
;
319 return UsbIoPpi
->UsbControlTransfer (
324 PcdGet32 (PcdUsbTransferTimeoutValue
),
326 (UINT16
)DescriptorSize
331 Read the whole usb hub descriptor. It is necessary
332 to do it in two steps because hub descriptor is of
335 @param PeiServices General-purpose services that are available to every PEIM.
336 @param PeiUsbDevice Indicates the hub controller device.
337 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
338 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
339 successfully returned.
341 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
342 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
343 @retval Others Other failure occurs.
348 IN EFI_PEI_SERVICES
**PeiServices
,
349 IN PEI_USB_DEVICE
*PeiUsbDevice
,
350 IN PEI_USB_IO_PPI
*UsbIoPpi
,
351 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
357 // First get the hub descriptor length
359 Status
= PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, 2, HubDescriptor
);
361 if (EFI_ERROR (Status
)) {
366 // Get the whole hub descriptor
368 return PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, HubDescriptor
->Length
, HubDescriptor
);
372 USB hub control transfer to set the hub depth.
374 @param PeiServices General-purpose services that are available to every PEIM.
375 @param PeiUsbDevice Indicates the hub controller device.
376 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
378 @retval EFI_SUCCESS Depth of the hub is set.
379 @retval Others Failed to set the depth.
383 PeiUsbHubCtrlSetHubDepth (
384 IN EFI_PEI_SERVICES
**PeiServices
,
385 IN PEI_USB_DEVICE
*PeiUsbDevice
,
386 IN PEI_USB_IO_PPI
*UsbIoPpi
389 EFI_USB_DEVICE_REQUEST DevReq
;
390 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
393 // Fill Device request packet
395 DevReq
.RequestType
= USB_RT_HUB
;
396 DevReq
.Request
= USB_HUB_REQ_SET_DEPTH
;
397 DevReq
.Value
= PeiUsbDevice
->Tier
;
400 return UsbIoPpi
->UsbControlTransfer (
405 PcdGet32 (PcdUsbTransferTimeoutValue
),
412 Configure a given hub.
414 @param PeiServices General-purpose services that are available to every PEIM.
415 @param PeiUsbDevice Indicating the hub controller device that will be configured
417 @retval EFI_SUCCESS Hub configuration is done successfully.
418 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
423 IN EFI_PEI_SERVICES
**PeiServices
,
424 IN PEI_USB_DEVICE
*PeiUsbDevice
427 UINT8 HubDescBuffer
[256];
428 EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
;
430 EFI_USB_HUB_STATUS HubStatus
;
432 PEI_USB_IO_PPI
*UsbIoPpi
;
434 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
437 // The length field of descriptor is UINT8 type, so the buffer
438 // with 256 bytes is enough to hold the descriptor data.
440 HubDescriptor
= (EFI_USB_HUB_DESCRIPTOR
*) HubDescBuffer
;
443 // Get the hub descriptor
445 Status
= PeiUsbHubReadDesc (
451 if (EFI_ERROR (Status
)) {
452 return EFI_DEVICE_ERROR
;
455 PeiUsbDevice
->DownStreamPortNo
= HubDescriptor
->NbrPorts
;
457 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) {
458 DEBUG ((EFI_D_INFO
, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice
->Tier
));
459 PeiUsbHubCtrlSetHubDepth (
466 // Power all the hub ports
468 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
469 Status
= PeiHubSetPortFeature (
475 if (EFI_ERROR (Status
)) {
476 DEBUG (( EFI_D_ERROR
, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index
));
481 DEBUG (( EFI_D_INFO
, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor
->PwrOn2PwrGood
));
482 if (HubDescriptor
->PwrOn2PwrGood
> 0) {
483 MicroSecondDelay (HubDescriptor
->PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
487 // Clear Hub Status Change
489 Status
= PeiHubGetHubStatus (
492 (UINT32
*) &HubStatus
494 if (EFI_ERROR (Status
)) {
495 return EFI_DEVICE_ERROR
;
498 // Hub power supply change happens
500 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_LOCAL_POWER
) != 0) {
501 PeiHubClearHubFeature (
508 // Hub change overcurrent happens
510 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_OVERCURRENT
) != 0) {
511 PeiHubClearHubFeature (
524 Send reset signal over the given root hub port.
526 @param PeiServices General-purpose services that are available to every PEIM.
527 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
528 @param PortNum Usb hub port number (starting from 1).
533 IN EFI_PEI_SERVICES
**PeiServices
,
534 IN PEI_USB_IO_PPI
*UsbIoPpi
,
540 EFI_USB_PORT_STATUS HubPortStatus
;
542 MicroSecondDelay (100 * 1000);
547 PeiHubSetPortFeature (
555 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
556 // section 7.1.7.5 for timing requirements.
558 MicroSecondDelay (USB_SET_PORT_RESET_STALL
);
561 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
563 ZeroMem (&HubPortStatus
, sizeof (EFI_USB_PORT_STATUS
));
565 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
566 Status
= PeiHubGetPortStatus (
570 (UINT32
*) &HubPortStatus
573 if (EFI_ERROR (Status
)) {
577 if (USB_BIT_IS_SET (HubPortStatus
.PortChangeStatus
, USB_PORT_STAT_C_RESET
)) {
581 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
584 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
585 DEBUG ((EFI_D_ERROR
, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum
));
590 // clear reset change root port
592 PeiHubClearPortFeature (
596 EfiUsbPortResetChange
599 MicroSecondDelay (1 * 1000);
601 PeiHubClearPortFeature (
605 EfiUsbPortConnectChange
611 PeiHubSetPortFeature (
619 // Clear any change status
622 PeiHubClearPortFeature (
626 EfiUsbPortEnableChange
629 MicroSecondDelay (10 * 1000);