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
),
199 Clear specified feature on a given hub.
201 @param PeiServices General-purpose services that are available to every PEIM.
202 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
203 @param Value Feature value that will be cleared from the hub port.
205 @retval EFI_SUCCESS Hub feature is cleared successfully.
206 @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
207 @retval Others Other failure occurs.
211 PeiHubClearHubFeature (
212 IN EFI_PEI_SERVICES
**PeiServices
,
213 IN PEI_USB_IO_PPI
*UsbIoPpi
,
217 EFI_USB_DEVICE_REQUEST DeviceRequest
;
219 ZeroMem (&DeviceRequest
, sizeof (EFI_USB_DEVICE_REQUEST
));
222 // Fill Device request packet
224 DeviceRequest
.RequestType
= USB_HUB_CLEAR_FEATURE_REQ_TYPE
;
225 DeviceRequest
.Request
= USB_HUB_CLEAR_FEATURE
;
226 DeviceRequest
.Value
= Value
;
228 return UsbIoPpi
->UsbControlTransfer (
233 PcdGet32 (PcdUsbTransferTimeoutValue
),
240 Get a given (SuperSpeed) hub descriptor.
242 @param PeiServices General-purpose services that are available to every PEIM.
243 @param PeiUsbDevice Indicates the hub controller device.
244 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
245 @param DescriptorSize The length of Hub Descriptor buffer.
246 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
247 successfully returned.
249 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
250 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
251 @retval Others Other failure occurs.
255 PeiGetHubDescriptor (
256 IN EFI_PEI_SERVICES
**PeiServices
,
257 IN PEI_USB_DEVICE
*PeiUsbDevice
,
258 IN PEI_USB_IO_PPI
*UsbIoPpi
,
259 IN UINTN DescriptorSize
,
260 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
263 EFI_USB_DEVICE_REQUEST DevReq
;
266 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
268 DescType
= (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) ?
269 USB_DT_SUPERSPEED_HUB
:
273 // Fill Device request packet
275 DevReq
.RequestType
= USB_RT_HUB
| 0x80;
276 DevReq
.Request
= USB_HUB_GET_DESCRIPTOR
;
277 DevReq
.Value
= (UINT16
) (DescType
<< 8);
278 DevReq
.Length
= (UINT16
) DescriptorSize
;
280 return UsbIoPpi
->UsbControlTransfer (
285 PcdGet32 (PcdUsbTransferTimeoutValue
),
287 (UINT16
)DescriptorSize
292 Read the whole usb hub descriptor. It is necessary
293 to do it in two steps because hub descriptor is of
296 @param PeiServices General-purpose services that are available to every PEIM.
297 @param PeiUsbDevice Indicates the hub controller device.
298 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
299 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
300 successfully returned.
302 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
303 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
304 @retval Others Other failure occurs.
309 IN EFI_PEI_SERVICES
**PeiServices
,
310 IN PEI_USB_DEVICE
*PeiUsbDevice
,
311 IN PEI_USB_IO_PPI
*UsbIoPpi
,
312 OUT EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
318 // First get the hub descriptor length
320 Status
= PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, 2, HubDescriptor
);
322 if (EFI_ERROR (Status
)) {
327 // Get the whole hub descriptor
329 return PeiGetHubDescriptor (PeiServices
, PeiUsbDevice
, UsbIoPpi
, HubDescriptor
->Length
, HubDescriptor
);
333 USB hub control transfer to set the hub depth.
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.
339 @retval EFI_SUCCESS Depth of the hub is set.
340 @retval Others Failed to set the depth.
344 PeiUsbHubCtrlSetHubDepth (
345 IN EFI_PEI_SERVICES
**PeiServices
,
346 IN PEI_USB_DEVICE
*PeiUsbDevice
,
347 IN PEI_USB_IO_PPI
*UsbIoPpi
350 EFI_USB_DEVICE_REQUEST DevReq
;
351 ZeroMem (&DevReq
, sizeof (EFI_USB_DEVICE_REQUEST
));
354 // Fill Device request packet
356 DevReq
.RequestType
= USB_RT_HUB
;
357 DevReq
.Request
= USB_HUB_REQ_SET_DEPTH
;
358 DevReq
.Value
= PeiUsbDevice
->Tier
;
361 return UsbIoPpi
->UsbControlTransfer (
366 PcdGet32 (PcdUsbTransferTimeoutValue
),
373 Configure a given hub.
375 @param PeiServices General-purpose services that are available to every PEIM.
376 @param PeiUsbDevice Indicating the hub controller device that will be configured
378 @retval EFI_SUCCESS Hub configuration is done successfully.
379 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
384 IN EFI_PEI_SERVICES
**PeiServices
,
385 IN PEI_USB_DEVICE
*PeiUsbDevice
388 UINT8 HubDescBuffer
[256];
389 EFI_USB_HUB_DESCRIPTOR
*HubDescriptor
;
391 EFI_USB_HUB_STATUS HubStatus
;
393 PEI_USB_IO_PPI
*UsbIoPpi
;
395 UsbIoPpi
= &PeiUsbDevice
->UsbIoPpi
;
398 // The length field of descriptor is UINT8 type, so the buffer
399 // with 256 bytes is enough to hold the descriptor data.
401 HubDescriptor
= (EFI_USB_HUB_DESCRIPTOR
*) HubDescBuffer
;
404 // Get the hub descriptor
406 Status
= PeiUsbHubReadDesc (
412 if (EFI_ERROR (Status
)) {
413 return EFI_DEVICE_ERROR
;
416 PeiUsbDevice
->DownStreamPortNo
= HubDescriptor
->NbrPorts
;
418 if (PeiUsbDevice
->DeviceSpeed
== EFI_USB_SPEED_SUPER
) {
419 DEBUG ((EFI_D_INFO
, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice
->Tier
));
420 PeiUsbHubCtrlSetHubDepth (
427 // Power all the hub ports
429 for (Index
= 0; Index
< PeiUsbDevice
->DownStreamPortNo
; Index
++) {
430 Status
= PeiHubSetPortFeature (
436 if (EFI_ERROR (Status
)) {
437 DEBUG (( EFI_D_ERROR
, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index
));
442 DEBUG (( EFI_D_INFO
, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor
->PwrOn2PwrGood
));
443 if (HubDescriptor
->PwrOn2PwrGood
> 0) {
444 MicroSecondDelay (HubDescriptor
->PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
448 // Clear Hub Status Change
450 Status
= PeiHubGetHubStatus (
453 (UINT32
*) &HubStatus
455 if (EFI_ERROR (Status
)) {
456 return EFI_DEVICE_ERROR
;
459 // Hub power supply change happens
461 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_LOCAL_POWER
) != 0) {
462 PeiHubClearHubFeature (
469 // Hub change overcurrent happens
471 if ((HubStatus
.HubChangeStatus
& HUB_CHANGE_OVERCURRENT
) != 0) {
472 PeiHubClearHubFeature (
485 Send reset signal over the given root hub port.
487 @param PeiServices General-purpose services that are available to every PEIM.
488 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
489 @param PortNum Usb hub port number (starting from 1).
494 IN EFI_PEI_SERVICES
**PeiServices
,
495 IN PEI_USB_IO_PPI
*UsbIoPpi
,
501 EFI_USB_PORT_STATUS HubPortStatus
;
503 MicroSecondDelay (100 * 1000);
508 PeiHubSetPortFeature (
516 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
517 // section 7.1.7.5 for timing requirements.
519 MicroSecondDelay (USB_SET_PORT_RESET_STALL
);
522 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
524 ZeroMem (&HubPortStatus
, sizeof (EFI_USB_PORT_STATUS
));
526 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
527 Status
= PeiHubGetPortStatus (
531 (UINT32
*) &HubPortStatus
534 if (EFI_ERROR (Status
)) {
538 if (USB_BIT_IS_SET (HubPortStatus
.PortChangeStatus
, USB_PORT_STAT_C_RESET
)) {
542 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL
);
545 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
546 DEBUG ((EFI_D_ERROR
, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum
));
551 // clear reset change root port
553 PeiHubClearPortFeature (
557 EfiUsbPortResetChange
560 MicroSecondDelay (1 * 1000);
562 PeiHubClearPortFeature (
566 EfiUsbPortConnectChange
572 PeiHubSetPortFeature (
580 // Clear any change status
583 PeiHubClearPortFeature (
587 EfiUsbPortEnableChange
590 MicroSecondDelay (10 * 1000);