summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Usb/UsbBusPei
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:30:55 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-06-27 23:30:55 +0000
commit4b1bf81c20d5523554a83f6604df7930396f7c21 (patch)
tree8764ce333f14a1e5722b9d0f75ac1e09f1e0df29 /MdeModulePkg/Bus/Usb/UsbBusPei
parent366f81a016c11a59669cdfb5adb714e6f036f65f (diff)
downloadedk2-4b1bf81c20d5523554a83f6604df7930396f7c21.zip
edk2-4b1bf81c20d5523554a83f6604df7930396f7c21.tar.gz
edk2-4b1bf81c20d5523554a83f6604df7930396f7c21.tar.bz2
MdeModulePkg: Add PEI USB drivers and related PPIs
Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11901 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Bus/Usb/UsbBusPei')
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c537
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h279
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c333
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h250
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf66
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c325
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c1041
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h203
8 files changed, 3034 insertions, 0 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c b/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
new file mode 100644
index 0000000..5b7ebfa
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
@@ -0,0 +1,537 @@
+/** @file
+Usb Hub Request Support In PEI Phase
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbPeim.h"
+#include "HubPeim.h"
+#include "PeiUsbLib.h"
+
+/**
+ Get a given hub port status.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Port Usb hub port number (starting from 1).
+ @param PortStatus Current Hub port status and change status.
+
+ @retval EFI_SUCCESS Port status is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ OUT UINT32 *PortStatus
+ )
+{
+ EFI_USB_DEVICE_REQUEST DeviceRequest;
+
+ ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;
+ DeviceRequest.Request = USB_HUB_GET_PORT_STATUS;
+ DeviceRequest.Index = Port;
+ DeviceRequest.Length = (UINT16) sizeof (UINT32);
+
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DeviceRequest,
+ EfiUsbDataIn,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ PortStatus,
+ sizeof (UINT32)
+ );
+
+}
+
+/**
+ Set specified feature to a given hub port.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Port Usb hub port number (starting from 1).
+ @param Value New feature value.
+
+ @retval EFI_SUCCESS Port feature is set successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubSetPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value
+ )
+{
+ EFI_USB_DEVICE_REQUEST DeviceRequest;
+
+ ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;
+ DeviceRequest.Request = USB_HUB_SET_PORT_FEATURE;
+ DeviceRequest.Value = Value;
+ DeviceRequest.Index = Port;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DeviceRequest,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Clear specified feature on a given hub port.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Port Usb hub port number (starting from 1).
+ @param Value Feature value that will be cleared from the hub port.
+
+ @retval EFI_SUCCESS Port feature is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value
+ )
+{
+ EFI_USB_DEVICE_REQUEST DeviceRequest;
+
+ ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
+ DeviceRequest.Request = USB_HUB_CLEAR_FEATURE_PORT;
+ DeviceRequest.Value = Value;
+ DeviceRequest.Index = Port;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DeviceRequest,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Get a given hub status.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param HubStatus Current Hub status and change status.
+
+ @retval EFI_SUCCESS Hub status is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetHubStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ OUT UINT32 *HubStatus
+ )
+{
+ EFI_USB_DEVICE_REQUEST DeviceRequest;
+
+ ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;
+ DeviceRequest.Request = USB_HUB_GET_HUB_STATUS;
+ DeviceRequest.Length = (UINT16) sizeof (UINT32);
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DeviceRequest,
+ EfiUsbDataIn,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ HubStatus,
+ sizeof (UINT32)
+ );
+}
+
+/**
+ Set specified feature to a given hub.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Value New feature value.
+
+ @retval EFI_SUCCESS Port feature is set successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubSetHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value
+ )
+{
+ EFI_USB_DEVICE_REQUEST DeviceRequest;
+
+ ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DeviceRequest.RequestType = USB_HUB_SET_HUB_FEATURE_REQ_TYPE;
+ DeviceRequest.Request = USB_HUB_SET_HUB_FEATURE;
+ DeviceRequest.Value = Value;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DeviceRequest,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Clear specified feature on a given hub.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Value Feature value that will be cleared from the hub port.
+
+ @retval EFI_SUCCESS Hub feature is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value
+ )
+{
+ EFI_USB_DEVICE_REQUEST DeviceRequest;
+
+ ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;
+ DeviceRequest.Request = USB_HUB_CLEAR_FEATURE;
+ DeviceRequest.Value = Value;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DeviceRequest,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Get a given hub descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param DescriptorSize The length of Hub Descriptor buffer.
+ @param HubDescriptor Caller allocated buffer to store the hub descriptor if
+ successfully returned.
+
+ @retval EFI_SUCCESS Hub descriptor is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiGetHubDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINTN DescriptorSize,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = USB_RT_HUB | 0x80;
+ DevReq.Request = USB_HUB_GET_DESCRIPTOR;
+ DevReq.Value = USB_DT_HUB << 8;
+ DevReq.Length = (UINT16)DescriptorSize;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbDataIn,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ HubDescriptor,
+ (UINT16)DescriptorSize
+ );
+}
+
+/**
+ Configure a given hub.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param PeiUsbDevice Indicating the hub controller device that will be configured
+
+ @retval EFI_SUCCESS Hub configuration is done successfully.
+ @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
+
+**/
+EFI_STATUS
+PeiDoHubConfig (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice
+ )
+{
+ EFI_USB_HUB_DESCRIPTOR HubDescriptor;
+ EFI_STATUS Status;
+ EFI_USB_HUB_STATUS HubStatus;
+ UINTN Index;
+ UINT32 PortStatus;
+ PEI_USB_IO_PPI *UsbIoPpi;
+
+ ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+ //
+ // First get the hub descriptor length
+ //
+ Status = PeiGetHubDescriptor (
+ PeiServices,
+ UsbIoPpi,
+ 2,
+ &HubDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // First get the whole descriptor, then
+ // get the number of hub ports
+ //
+ Status = PeiGetHubDescriptor (
+ PeiServices,
+ UsbIoPpi,
+ HubDescriptor.Length,
+ &HubDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
+
+ Status = PeiHubGetHubStatus (
+ PeiServices,
+ UsbIoPpi,
+ (UINT32 *) &HubStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get all hub ports status
+ //
+ for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
+
+ Status = PeiHubGetPortStatus (
+ PeiServices,
+ UsbIoPpi,
+ (UINT8) (Index + 1),
+ &PortStatus
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ }
+ //
+ // Power all the hub ports
+ //
+ for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
+ Status = PeiHubSetPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ (UINT8) (Index + 1),
+ EfiUsbPortPower
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ }
+ //
+ // Clear Hub Status Change
+ //
+ Status = PeiHubGetHubStatus (
+ PeiServices,
+ UsbIoPpi,
+ (UINT32 *) &HubStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // Hub power supply change happens
+ //
+ if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
+ PeiHubClearHubFeature (
+ PeiServices,
+ UsbIoPpi,
+ C_HUB_LOCAL_POWER
+ );
+ }
+ //
+ // Hub change overcurrent happens
+ //
+ if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
+ PeiHubClearHubFeature (
+ PeiServices,
+ UsbIoPpi,
+ C_HUB_OVER_CURRENT
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send reset signal over the given root hub port.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param PortNum Usb hub port number (starting from 1).
+
+**/
+VOID
+PeiResetHubPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 PortNum
+ )
+{
+ UINT8 Try;
+ EFI_USB_PORT_STATUS HubPortStatus;
+
+
+ MicroSecondDelay (100 * 1000);
+
+ //
+ // reset root port
+ //
+ PeiHubSetPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ Try = 10;
+ do {
+ PeiHubGetPortStatus (
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ (UINT32 *) &HubPortStatus
+ );
+
+ MicroSecondDelay (2 * 1000);
+ Try -= 1;
+ } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Try > 0);
+
+ //
+ // clear reset root port
+ //
+ PeiHubClearPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ MicroSecondDelay (1 * 1000);
+
+ PeiHubClearPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortConnectChange
+ );
+
+ //
+ // Set port enable
+ //
+ PeiHubSetPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortEnable
+ );
+
+ //
+ // Clear any change status
+ //
+
+ PeiHubClearPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ PortNum,
+ EfiUsbPortEnableChange
+ );
+
+ MicroSecondDelay (10 * 1000);
+
+ return;
+}
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h b/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h
new file mode 100644
index 0000000..273a26c
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h
@@ -0,0 +1,279 @@
+/** @file
+Constants definitions for Usb Hub Peim
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_HUB_PEIM_H_
+#define _PEI_HUB_PEIM_H_
+
+
+//
+// Hub feature numbers
+//
+#define C_HUB_LOCAL_POWER 0
+#define C_HUB_OVER_CURRENT 1
+
+//
+// Hub class code & sub class code
+//
+#define CLASS_CODE_HUB 0x09
+#define SUB_CLASS_CODE_HUB 0
+
+//
+// Hub Status & Hub Change bit masks
+//
+#define HUB_STATUS_LOCAL_POWER 0x0001
+#define HUB_STATUS_OVERCURRENT 0x0002
+
+#define HUB_CHANGE_LOCAL_POWER 0x0001
+#define HUB_CHANGE_OVERCURRENT 0x0002
+
+//
+// Hub Characteristics
+//
+#define HUB_CHAR_LPSM 0x0003
+#define HUB_CHAR_COMPOUND 0x0004
+#define HUB_CHAR_OCPM 0x0018
+
+//
+// Standard hub request and request type
+// By [Spec-USB20/Chapter-11.24]
+//
+#define USB_HUB_CLEAR_FEATURE 0x01
+#define USB_HUB_CLEAR_FEATURE_REQ_TYPE 0x20
+
+#define USB_HUB_CLEAR_FEATURE_PORT 0x01
+#define USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE 0x23
+
+#define USB_HUB_GET_BUS_STATE 0x02
+#define USB_HUB_GET_BUS_STATE_REQ_TYPE 0xA3
+
+#define USB_HUB_GET_DESCRIPTOR 0x06
+#define USB_HUB_GET_DESCRIPTOR_REQ_TYPE 0xA0
+
+#define USB_HUB_GET_HUB_STATUS 0x00
+#define USB_HUB_GET_HUB_STATUS_REQ_TYPE 0xA0
+
+#define USB_HUB_GET_PORT_STATUS 0x00
+#define USB_HUB_GET_PORT_STATUS_REQ_TYPE 0xA3
+
+#define USB_HUB_SET_DESCRIPTOR 0x07
+#define USB_HUB_SET_DESCRIPTOR_REQ_TYPE 0x20
+
+#define USB_HUB_SET_HUB_FEATURE 0x03
+#define USB_HUB_SET_HUB_FEATURE_REQ_TYPE 0x20
+
+#define USB_HUB_SET_PORT_FEATURE 0x03
+#define USB_HUB_SET_PORT_FEATURE_REQ_TYPE 0x23
+
+#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+#define MAXBYTES 8
+#pragma pack(1)
+//
+// Hub descriptor, the last two fields are of variable lenght.
+//
+typedef struct {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 NbrPorts;
+ UINT8 HubCharacteristics[2];
+ UINT8 PwrOn2PwrGood;
+ UINT8 HubContrCurrent;
+ UINT8 Filler[MAXBYTES];
+} EFI_USB_HUB_DESCRIPTOR;
+
+typedef struct {
+ UINT16 HubStatus;
+ UINT16 HubChangeStatus;
+} EFI_USB_HUB_STATUS;
+
+#pragma pack()
+/**
+ Get a given hub port status.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Port Usb hub port number (starting from 1).
+ @param PortStatus Current Hub port status and change status.
+
+ @retval EFI_SUCCESS Port status is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetPortStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ OUT UINT32 *PortStatus
+ );
+
+/**
+ Set specified feature to a given hub port.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Port Usb hub port number (starting from 1).
+ @param Value New feature value.
+
+ @retval EFI_SUCCESS Port feature is set successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubSetPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value
+ );
+
+/**
+ Set specified feature to a given hub.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Value New feature value.
+
+ @retval EFI_SUCCESS Port feature is set successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubSetHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value
+ );
+
+/**
+ Get a given hub status.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param HubStatus Current Hub status and change status.
+
+ @retval EFI_SUCCESS Hub status is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetHubStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ OUT UINT32 *HubStatus
+ );
+
+/**
+ Clear specified feature on a given hub port.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Port Usb hub port number (starting from 1).
+ @param Value Feature value that will be cleared from the hub port.
+
+ @retval EFI_SUCCESS Port feature is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearPortFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Port,
+ IN UINT8 Value
+ );
+
+/**
+ Clear specified feature on a given hub.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Value Feature value that will be cleared from the hub port.
+
+ @retval EFI_SUCCESS Hub feature is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearHubFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 Value
+ );
+
+/**
+ Get a given hub descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param DescriptorSize The length of Hub Descriptor buffer.
+ @param HubDescriptor Caller allocated buffer to store the hub descriptor if
+ successfully returned.
+
+ @retval EFI_SUCCESS Hub descriptor is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiGetHubDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINTN DescriptorSize,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
+ );
+
+/**
+ Configure a given hub.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param PeiUsbDevice Indicating the hub controller device that will be configured
+
+ @retval EFI_SUCCESS Hub configuration is done successfully.
+ @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
+
+**/
+EFI_STATUS
+PeiDoHubConfig (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice
+ );
+
+/**
+ Send reset signal over the given root hub port.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param PortNum Usb hub port number (starting from 1).
+
+**/
+VOID
+PeiResetHubPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 PortNum
+ );
+
+#endif
+
+
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c b/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c
new file mode 100644
index 0000000..2ac8d7b
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c
@@ -0,0 +1,333 @@
+/** @file
+Common Libarary for PEI USB
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+/**
+ Get a given usb descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Value Request Value.
+ @param Index Request Index.
+ @param DescriptorLength Request descriptor Length.
+ @param Descriptor Request descriptor.
+
+
+ @retval EFI_SUCCESS Usb descriptor is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 Value,
+ IN UINT16 Index,
+ IN UINT16 DescriptorLength,
+ OUT VOID *Descriptor
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+
+ ASSERT (UsbIoPpi != NULL);
+
+ DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
+ DevReq.Request = USB_DEV_GET_DESCRIPTOR;
+ DevReq.Value = Value;
+ DevReq.Index = Index;
+ DevReq.Length = DescriptorLength;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbDataIn,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ Descriptor,
+ DescriptorLength
+ );
+}
+
+/**
+ Set a usb device with a specified address.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param AddressValue The address to assign.
+
+ @retval EFI_SUCCESS Usb device address is set successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetDeviceAddress (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 AddressValue
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+
+ ASSERT (UsbIoPpi != NULL);
+
+ DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE;
+ DevReq.Request = USB_DEV_SET_ADDRESS;
+ DevReq.Value = AddressValue;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Clear a given usb feature.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
+ @param Value Request Value.
+ @param Target Request Index.
+
+ @retval EFI_SUCCESS Usb feature is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbClearDeviceFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN EFI_USB_RECIPIENT Recipient,
+ IN UINT16 Value,
+ IN UINT16 Target
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+
+ ASSERT (UsbIoPpi != NULL);
+
+ switch (Recipient) {
+ case EfiUsbDevice:
+ DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;
+ break;
+
+ case EfiUsbInterface:
+ DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;
+ break;
+
+ case EfiUsbEndpoint:
+ DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;
+ break;
+ }
+
+ DevReq.Request = USB_DEV_CLEAR_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = Target;
+ DevReq.Length = 0;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Configure a usb device to Configuration 1.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+
+ @retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi
+ )
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
+ DevReq.Request = USB_DEV_SET_CONFIGURATION;
+ DevReq.Value = 1;
+
+ return UsbIoPpi->UsbControlTransfer (
+ PeiServices,
+ UsbIoPpi,
+ &DevReq,
+ EfiUsbNoData,
+ PcdGet32 (PcdUsbTransferTimeoutValue),
+ NULL,
+ 0
+ );
+}
+
+/**
+ Clear Endpoint Halt.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param EndpointAddress The endpoint address.
+
+ @retval EFI_SUCCESS Endpoint halt is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbClearEndpointHalt (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 EndpointAddress
+ )
+{
+ EFI_STATUS Status;
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+ UINT8 EndpointIndex;
+
+ EndpointIndex = 0;
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (UsbIoPpi);
+
+ while (EndpointIndex < MAX_ENDPOINT) {
+ Status = UsbIoPpi->UsbGetEndpointDescriptor (PeiServices, UsbIoPpi, EndpointIndex, &EndpointDescriptor);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EndpointDescriptor->EndpointAddress == EndpointAddress) {
+ break;
+ }
+
+ EndpointIndex++;
+ }
+
+ if (EndpointIndex == MAX_ENDPOINT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PeiUsbClearDeviceFeature (
+ PeiServices,
+ UsbIoPpi,
+ EfiUsbEndpoint,
+ EfiUsbEndpointHalt,
+ EndpointAddress
+ );
+
+ //
+ // set data toggle to zero.
+ //
+ if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
+ PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
+ }
+
+ return Status;
+}
+
+/**
+ Judge if the port is connected with a usb device or not.
+
+ @param PortStatus The usb port status gotten.
+
+ @retval TRUE A usb device is connected with the port.
+ @retval FALSE No usb device is connected with the port.
+
+**/
+BOOLEAN
+IsPortConnect (
+ IN UINT16 PortStatus
+ )
+{
+ //
+ // return the bit 0 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Judge if the port is connected with a low-speed usb device or not.
+
+ @param PortStatus The usb port status gotten.
+
+ @retval TRUE A low-speed usb device is connected with the port.
+ @retval FALSE No low-speed usb device is connected with the port.
+
+**/
+UINTN
+IsPortLowSpeedDeviceAttached (
+ IN UINT16 PortStatus
+ )
+{
+ //
+ // return the bit 9 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
+ return EFI_USB_SPEED_LOW;
+ } else if ((PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0){
+ return EFI_USB_SPEED_HIGH;
+ } else {
+ return EFI_USB_SPEED_FULL;
+ }
+}
+
+/**
+ Judge if the port is in "connection change" status or not.
+
+ @param PortChangeStatus The usb port change status gotten.
+
+ @retval TRUE The port is in "connection change" status.
+ @retval FALSE The port is NOT in "connection change" status.
+
+**/
+BOOLEAN
+IsPortConnectChange (
+ IN UINT16 PortChangeStatus
+ )
+{
+ //
+ // return the bit 0 value of PortChangeStatus
+ //
+ if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h b/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h
new file mode 100644
index 0000000..dd4ce1b
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h
@@ -0,0 +1,250 @@
+/** @file
+Common Libarary for PEI USB
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_USB_LIB_H_
+#define _PEI_USB_LIB_H_
+
+
+//
+// Standard device request and request type
+// By [Spec-USB20/Chapter-9.4]
+//
+#define USB_DEV_GET_STATUS 0x00
+#define USB_DEV_GET_STATUS_REQ_TYPE_D 0x80 // Receiver : Device
+#define USB_DEV_GET_STATUS_REQ_TYPE_I 0x81 // Receiver : Interface
+#define USB_DEV_GET_STATUS_REQ_TYPE_E 0x82 // Receiver : Endpoint
+
+#define USB_DEV_CLEAR_FEATURE 0x01
+#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device
+#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface
+#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint
+
+#define USB_DEV_SET_FEATURE 0x03
+#define USB_DEV_SET_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device
+#define USB_DEV_SET_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface
+#define USB_DEV_SET_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint
+
+#define USB_DEV_SET_ADDRESS 0x05
+#define USB_DEV_SET_ADDRESS_REQ_TYPE 0x00
+
+#define USB_DEV_GET_DESCRIPTOR 0x06
+#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE 0x80
+
+#define USB_DEV_SET_DESCRIPTOR 0x07
+#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE 0x00
+
+#define USB_DEV_GET_CONFIGURATION 0x08
+#define USB_DEV_GET_CONFIGURATION_REQ_TYPE 0x80
+
+#define USB_DEV_SET_CONFIGURATION 0x09
+#define USB_DEV_SET_CONFIGURATION_REQ_TYPE 0x00
+
+#define USB_DEV_GET_INTERFACE 0x0A
+#define USB_DEV_GET_INTERFACE_REQ_TYPE 0x81
+
+#define USB_DEV_SET_INTERFACE 0x0B
+#define USB_DEV_SET_INTERFACE_REQ_TYPE 0x01
+
+#define USB_DEV_SYNCH_FRAME 0x0C
+#define USB_DEV_SYNCH_FRAME_REQ_TYPE 0x82
+
+//
+// USB Descriptor types
+//
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
+#define USB_DT_HUB 0x29
+#define USB_DT_HID 0x21
+
+//
+// USB request type
+//
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+//
+// USB request targer device
+//
+#define USB_RECIP_DEVICE 0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT 0x02
+#define USB_RECIP_OTHER 0x03
+
+typedef enum {
+ EfiUsbEndpointHalt,
+ EfiUsbDeviceRemoteWakeup
+} EFI_USB_STANDARD_FEATURE_SELECTOR;
+
+//
+// Usb Data recipient type
+//
+typedef enum {
+ EfiUsbDevice,
+ EfiUsbInterface,
+ EfiUsbEndpoint
+} EFI_USB_RECIPIENT;
+
+/**
+ Get a given usb descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Value Request Value.
+ @param Index Request Index.
+ @param DescriptorLength Request descriptor Length.
+ @param Descriptor Request descriptor.
+
+
+ @retval EFI_SUCCESS Usb descriptor is obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 Value,
+ IN UINT16 Index,
+ IN UINT16 DescriptorLength,
+ OUT VOID *Descriptor
+ );
+
+/**
+ Set a usb device with a specified address.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param AddressValue The address to assign.
+
+ @retval EFI_SUCCESS Usb device address is set successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetDeviceAddress (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT16 AddressValue
+ );
+
+/**
+ Clear a given usb feature.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
+ @param Value Request Value.
+ @param Target Request Index.
+
+ @retval EFI_SUCCESS Usb feature is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbClearDeviceFeature (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN EFI_USB_RECIPIENT Recipient,
+ IN UINT16 Value,
+ IN UINT16 Target
+ );
+
+/**
+ Configure a usb device to Configuration 1.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+
+ @retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.
+ @retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi
+ );
+
+/**
+ Clear Endpoint Halt.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
+ @param EndpointAddress The endpoint address.
+
+ @retval EFI_SUCCESS Endpoint halt is cleared successfully.
+ @retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbClearEndpointHalt (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *UsbIoPpi,
+ IN UINT8 EndpointAddress
+ );
+
+/**
+ Judge if the port is connected with a usb device or not.
+
+ @param PortStatus The usb port status gotten.
+
+ @retval TRUE A usb device is connected with the port.
+ @retval FALSE No usb device is connected with the port.
+
+**/
+BOOLEAN
+IsPortConnect (
+ IN UINT16 PortStatus
+ );
+
+/**
+ Judge if the port is connected with a low-speed usb device or not.
+
+ @param PortStatus The usb port status gotten.
+
+ @retval TRUE A low-speed usb device is connected with the port.
+ @retval FALSE No low-speed usb device is connected with the port.
+
+**/
+UINTN
+IsPortLowSpeedDeviceAttached (
+ IN UINT16 PortStatus
+ );
+
+/**
+ Judge if the port is in "connection change" status or not.
+
+ @param PortChangeStatus The usb port change status gotten.
+
+ @retval TRUE The port is in "connection change" status.
+ @retval FALSE The port is NOT in "connection change" status.
+
+**/
+BOOLEAN
+IsPortConnectChange (
+ IN UINT16 PortChangeStatus
+ );
+#endif
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
new file mode 100644
index 0000000..e4a2cb4
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
@@ -0,0 +1,66 @@
+## @file
+# Component description file for UsbPeim module.
+#
+# Usb Bus Peim driver to support recovery from usb device.
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions
+# of the BSD License which accompanies this distribution. The
+# full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UsbBusPei
+ FILE_GUID = 8401A045-6F70-4505-8471-7015B40355E3
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PeimInitializeUsb
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PeiUsbLib.c
+ HubPeim.c
+ UsbIoPeim.c
+ UsbPeim.c
+ UsbPeim.h
+ PeiUsbLib.h
+ HubPeim.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ TimerLib
+ BaseMemoryLib
+ PeiServicesLib
+ PeimEntryPoint
+ DebugLib
+ PcdLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue
+
+[Ppis]
+ gPeiUsbIoPpiGuid # PPI ALWAYS_PRODUCED
+ gPeiUsbHostControllerPpiGuid # PPI ALWAYS_CONSUMED
+ gPeiUsb2HostControllerPpiGuid # PPI ALWAYS_CONSUMED
+
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid AND gPeiUsb2HostControllerPpiGuid OR gPeiUsbHostControllerPpiGuid
+
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
new file mode 100644
index 0000000..897b228
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
@@ -0,0 +1,325 @@
+/** @file
+The module is used to implement Usb Io PPI interfaces.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+/**
+ Submits control transfer to a target USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_IO_PPI.
+ @param Request USB device request to send.
+ @param Direction Specifies the data direction for the data stage.
+ @param Timeout Indicates the maximum timeout, in millisecond.
+ @param Data Data buffer to be transmitted or received from USB device.
+ @param DataLength The size (in bytes) of the data buffer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data, OPTIONAL
+ IN UINTN DataLength OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ PEI_USB_DEVICE *PeiUsbDev;
+ UINT32 TransferResult;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+ if (PeiUsbDev->Usb2HcPpi != NULL) {
+ Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (
+ PeiServices,
+ PeiUsbDev->Usb2HcPpi,
+ PeiUsbDev->DeviceAddress,
+ PeiUsbDev->DeviceSpeed,
+ PeiUsbDev->MaxPacketSize0,
+ Request,
+ Direction,
+ Data,
+ &DataLength,
+ Timeout,
+ &(PeiUsbDev->Translator),
+ &TransferResult
+ );
+ } else {
+ Status = PeiUsbDev->UsbHcPpi->ControlTransfer (
+ PeiServices,
+ PeiUsbDev->UsbHcPpi,
+ PeiUsbDev->DeviceAddress,
+ PeiUsbDev->DeviceSpeed,
+ PeiUsbDev->MaxPacketSize0,
+ Request,
+ Direction,
+ Data,
+ &DataLength,
+ Timeout,
+ &TransferResult
+ );
+ }
+ return Status;
+}
+
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_IO_PPI.
+ @param DeviceEndpoint Endpoint number and its direction in bit 7.
+ @param Data A pointer to the buffer of data to transmit
+ from or receive into.
+ @param DataLength The lenght of the data buffer.
+ @param Timeout Indicates the maximum time, in millisecond, which the
+ transfer is allowed to complete.
+
+ @retval EFI_SUCCESS The transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Parameters are invalid.
+ @retval EFI_TIMEOUT The transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout
+ )
+{
+ EFI_STATUS Status;
+ PEI_USB_DEVICE *PeiUsbDev;
+ UINT32 TransferResult;
+ UINTN MaxPacketLength;
+ UINT8 DataToggle;
+ UINT8 OldToggle;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+ UINT8 EndpointIndex;
+ VOID *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+ EndpointDescriptor = NULL;
+ EndpointIndex = 0;
+ Data2[0] = Data;
+ Data2[1] = NULL;
+
+ while (EndpointIndex < MAX_ENDPOINT) {
+ Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
+ break;
+ }
+
+ EndpointIndex++;
+ }
+
+ if (EndpointIndex == MAX_ENDPOINT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
+ if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
+ DataToggle = 1;
+ } else {
+ DataToggle = 0;
+ }
+
+ OldToggle = DataToggle;
+
+ if (PeiUsbDev->Usb2HcPpi != NULL) {
+ Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (
+ PeiServices,
+ PeiUsbDev->Usb2HcPpi,
+ PeiUsbDev->DeviceAddress,
+ DeviceEndpoint,
+ PeiUsbDev->DeviceSpeed,
+ MaxPacketLength,
+ Data2,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ &(PeiUsbDev->Translator),
+ &TransferResult
+ );
+ } else {
+ Status = PeiUsbDev->UsbHcPpi->BulkTransfer (
+ PeiServices,
+ PeiUsbDev->UsbHcPpi,
+ PeiUsbDev->DeviceAddress,
+ DeviceEndpoint,
+ (UINT8) MaxPacketLength,
+ Data,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ &TransferResult
+ );
+ }
+
+ if (OldToggle != DataToggle) {
+ PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
+ }
+
+ return Status;
+}
+
+/**
+ Get the usb interface descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the PEI_USB_IO_PPI instance.
+ @param InterfaceDescriptor Request interface descriptor.
+
+
+ @retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetInterfaceDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
+ )
+{
+ PEI_USB_DEVICE *PeiUsbDev;
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+ *InterfaceDescriptor = PeiUsbDev->InterfaceDesc;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the usb endpoint descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the PEI_USB_IO_PPI instance.
+ @param EndpointIndex The valid index of the specified endpoint.
+ @param EndpointDescriptor Request endpoint descriptor.
+
+ @retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
+ @retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetEndpointDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 EndpointIndex,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
+ )
+{
+ PEI_USB_DEVICE *PeiUsbDev;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+ ASSERT (EndpointDescriptor != NULL);
+
+ //
+ // The valid range of EndpointIndex is 0..15
+ // If EndpointIndex is lesser than 15 but larger than the number of interfaces,
+ // a EFI_NOT_FOUND should be returned
+ //
+ ASSERT (EndpointIndex <= 15);
+
+ if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
+ return EFI_NOT_FOUND;
+ }
+
+ *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset the port and re-configure the usb device.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the PEI_USB_IO_PPI instance.
+
+ @retval EFI_SUCCESS Usb device is reset and configured successfully.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbPortReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This
+ )
+{
+ PEI_USB_DEVICE *PeiUsbDev;
+ EFI_STATUS Status;
+ UINT8 Address;
+
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+ ResetRootPort (
+ PeiServices,
+ PeiUsbDev->UsbHcPpi,
+ PeiUsbDev->Usb2HcPpi,
+ PeiUsbDev->DeviceAddress,
+ 0
+ );
+
+ //
+ // Set address
+ //
+ Address = PeiUsbDev->DeviceAddress;
+ PeiUsbDev->DeviceAddress = 0;
+
+ Status = PeiUsbSetDeviceAddress (
+ PeiServices,
+ This,
+ Address
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PeiUsbDev->DeviceAddress = Address;
+
+ //
+ // Set default configuration
+ //
+ Status = PeiUsbSetConfiguration (
+ PeiServices,
+ This
+ );
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
new file mode 100644
index 0000000..4a5d8e8
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
@@ -0,0 +1,1041 @@
+/** @file
+The module to produce Usb Bus PPI.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbPeim.h"
+#include "HubPeim.h"
+#include "PeiUsbLib.h"
+
+//
+// UsbIo PPI interface function
+//
+PEI_USB_IO_PPI mUsbIoPpi = {
+ PeiUsbControlTransfer,
+ PeiUsbBulkTransfer,
+ PeiUsbGetInterfaceDescriptor,
+ PeiUsbGetEndpointDescriptor,
+ PeiUsbPortReset
+};
+
+EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiUsbIoPpiGuid,
+ NULL
+};
+
+/**
+ The enumeration routine to detect device change.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+ @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+
+ @retval EFI_SUCCESS The usb is enumerated successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi
+ );
+
+/**
+ Configure new detected usb device.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
+ @param Port The port to be configured.
+ @param DeviceAddress The device address to be configured.
+
+ @retval EFI_SUCCESS The new detected usb device is configured successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiConfigureUsbDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 Port,
+ IN OUT UINT8 *DeviceAddress
+ );
+
+/**
+ Get all configurations from a detected usb device.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
+
+ @retval EFI_SUCCESS The new detected usb device is configured successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetAllConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice
+ );
+
+/**
+ Get the start position of next wanted descriptor.
+
+ @param Buffer Buffer containing data to parse.
+ @param Length Buffer length.
+ @param DescType Descriptor type.
+ @param DescLength Descriptor length.
+ @param ParsedBytes Bytes has been parsed.
+
+ @retval EFI_SUCCESS Get wanted descriptor successfully.
+ @retval EFI_DEVICE_ERROR Error occurred.
+
+**/
+EFI_STATUS
+GetExpectedDescriptor (
+ IN UINT8 *Buffer,
+ IN UINTN Length,
+ IN UINT8 DescType,
+ IN UINT8 DescLength,
+ OUT UINTN *ParsedBytes
+ );
+
+/**
+ The entrypoint of the module, it will enumerate all HCs.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS Usb initialization is done successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval EFI_UNSUPPORTED Can't find required PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimInitializeUsb (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+ PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
+
+ if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
+ // be produced at the same time
+ //
+ Index = 0;
+ while (TRUE) {
+ //
+ // Get UsbHcPpi at first.
+ //
+ Status = PeiServicesLocatePpi (
+ &gPeiUsbHostControllerPpiGuid,
+ Index,
+ NULL,
+ (VOID **) &UsbHcPpi
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // No more host controller, break out
+ //
+ break;
+ }
+ PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);
+ Index++;
+ }
+
+ if (Index == 0) {
+ //
+ // Then try to get Usb2HcPpi.
+ //
+ while (TRUE) {
+ Status = PeiServicesLocatePpi (
+ &gPeiUsb2HostControllerPpiGuid,
+ Index,
+ NULL,
+ (VOID **) &Usb2HcPpi
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // No more host controller, break out
+ //
+ break;
+ }
+ PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);
+ Index++;
+ }
+ }
+
+ if (Index == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The Hub Enumeration just scans the hub ports one time. It also
+ doesn't support hot-plug.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
+ @param CurrentAddress The DeviceAddress of usb device.
+
+ @retval EFI_SUCCESS The usb hub is enumerated successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 *CurrentAddress
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ EFI_USB_PORT_STATUS PortStatus;
+ UINTN MemPages;
+ EFI_PHYSICAL_ADDRESS AllocateAddress;
+ PEI_USB_DEVICE *NewPeiUsbDevice;
+
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+ for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
+
+ Status = PeiHubGetPortStatus (
+ PeiServices,
+ UsbIoPpi,
+ (UINT8) (Index + 1),
+ (UINT32 *) &PortStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (IsPortConnectChange (PortStatus.PortChangeStatus)) {
+ PeiHubClearPortFeature (
+ PeiServices,
+ UsbIoPpi,
+ (UINT8) (Index + 1),
+ EfiUsbPortConnectChange
+ );
+
+ MicroSecondDelay (100 * 1000);
+
+ if (IsPortConnect (PortStatus.PortStatus)) {
+
+ PeiHubGetPortStatus (
+ PeiServices,
+ UsbIoPpi,
+ (UINT8) (Index + 1),
+ (UINT32 *) &PortStatus
+ );
+
+ //
+ // Begin to deal with the new device
+ //
+ MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &AllocateAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
+ ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
+
+ NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
+ NewPeiUsbDevice->DeviceAddress = 0;
+ NewPeiUsbDevice->MaxPacketSize0 = 8;
+ NewPeiUsbDevice->DataToggle = 0;
+ CopyMem (
+ &(NewPeiUsbDevice->UsbIoPpi),
+ &mUsbIoPpi,
+ sizeof (PEI_USB_IO_PPI)
+ );
+ CopyMem (
+ &(NewPeiUsbDevice->UsbIoPpiList),
+ &mUsbIoPpiList,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
+ NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
+ NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;
+ NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;
+ NewPeiUsbDevice->IsHub = 0x0;
+ NewPeiUsbDevice->DownStreamPortNo = 0x0;
+
+ PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
+
+ PeiHubGetPortStatus (
+ PeiServices,
+ UsbIoPpi,
+ (UINT8) (Index + 1),
+ (UINT32 *) &PortStatus
+ );
+
+ NewPeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);
+
+ if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
+ if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
+ NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;
+ NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;
+ } else {
+ CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));
+ }
+ }
+
+ //
+ // Configure that Usb Device
+ //
+ Status = PeiConfigureUsbDevice (
+ PeiServices,
+ NewPeiUsbDevice,
+ (UINT8) (Index + 1),
+ CurrentAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
+
+ if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+ NewPeiUsbDevice->IsHub = 0x1;
+
+ Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
+ }
+ }
+
+ }
+ }
+
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The enumeration routine to detect device change.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+ @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+
+ @retval EFI_SUCCESS The usb is enumerated successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi
+ )
+{
+ UINT8 NumOfRootPort;
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_USB_PORT_STATUS PortStatus;
+ PEI_USB_DEVICE *PeiUsbDevice;
+ UINTN MemPages;
+ EFI_PHYSICAL_ADDRESS AllocateAddress;
+ UINT8 CurrentAddress;
+
+
+ CurrentAddress = 0;
+ if (Usb2HcPpi != NULL){
+ Usb2HcPpi->GetRootHubPortNumber (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8 *) &NumOfRootPort
+ );
+ } else {
+ UsbHcPpi->GetRootHubPortNumber (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8 *) &NumOfRootPort
+ );
+ }
+
+ for (Index = 0; Index < NumOfRootPort; Index++) {
+ //
+ // First get root port status to detect changes happen
+ //
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8) Index,
+ &PortStatus
+ );
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8) Index,
+ &PortStatus
+ );
+ }
+ DEBUG ((EFI_D_INFO, "USB Status --- ConnectChange[%04x] Status[%04x]\n", PortStatus.PortChangeStatus, PortStatus.PortStatus));
+ if (IsPortConnectChange (PortStatus.PortChangeStatus)) {
+ //
+ // Changes happen, first clear this change status
+ //
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8) Index,
+ EfiUsbPortConnectChange
+ );
+ } else {
+ UsbHcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8) Index,
+ EfiUsbPortConnectChange
+ );
+ }
+ MicroSecondDelay (100 * 1000);
+
+ if (IsPortConnect (PortStatus.PortStatus)) {
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8) Index,
+ &PortStatus
+ );
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8) Index,
+ &PortStatus
+ );
+ }
+
+ //
+ // Connect change happen
+ //
+ MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &AllocateAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
+ ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+
+ PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
+ PeiUsbDevice->DeviceAddress = 0;
+ PeiUsbDevice->MaxPacketSize0 = 8;
+ PeiUsbDevice->DataToggle = 0;
+ CopyMem (
+ &(PeiUsbDevice->UsbIoPpi),
+ &mUsbIoPpi,
+ sizeof (PEI_USB_IO_PPI)
+ );
+ CopyMem (
+ &(PeiUsbDevice->UsbIoPpiList),
+ &mUsbIoPpiList,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
+ PeiUsbDevice->UsbHcPpi = UsbHcPpi;
+ PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
+ PeiUsbDevice->IsHub = 0x0;
+ PeiUsbDevice->DownStreamPortNo = 0x0;
+
+ ResetRootPort (
+ PeiServices,
+ PeiUsbDevice->UsbHcPpi,
+ PeiUsbDevice->Usb2HcPpi,
+ Index,
+ 0
+ );
+
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8) Index,
+ &PortStatus
+ );
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8) Index,
+ &PortStatus
+ );
+ }
+
+ PeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);
+ DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
+
+ //
+ // Configure that Usb Device
+ //
+ Status = PeiConfigureUsbDevice (
+ PeiServices,
+ PeiUsbDevice,
+ Index,
+ &CurrentAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ DEBUG ((EFI_D_INFO, "PeiConfigureUsbDevice Success\n"));
+
+ Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
+
+ if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+ PeiUsbDevice->IsHub = 0x1;
+
+ Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
+ }
+ } else {
+ //
+ // Disconnect change happen, currently we don't support
+ //
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Configure new detected usb device.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
+ @param Port The port to be configured.
+ @param DeviceAddress The device address to be configured.
+
+ @retval EFI_SUCCESS The new detected usb device is configured successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiConfigureUsbDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 Port,
+ IN OUT UINT8 *DeviceAddress
+ )
+{
+ EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINT8 Retry;
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+ Status = EFI_SUCCESS;
+ ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
+ //
+ // Get USB device descriptor
+ //
+
+ for (Retry = 0; Retry < 3; Retry ++) {
+
+ PeiUsbDevice->MaxPacketSize0 = 8;
+
+ Status = PeiUsbGetDescriptor (
+ PeiServices,
+ UsbIoPpi,
+ (USB_DT_DEVICE << 8),
+ 0,
+ 8,
+ &DeviceDescriptor
+ );
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Sucess\n", Retry));
+ break;
+ }
+ }
+
+ if (Retry == 3) {
+ DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail\n", Retry));
+ return Status;
+ }
+
+ PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
+
+ (*DeviceAddress) ++;
+
+ Status = PeiUsbSetDeviceAddress (
+ PeiServices,
+ UsbIoPpi,
+ *DeviceAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed\n"));
+ return Status;
+ }
+
+ PeiUsbDevice->DeviceAddress = *DeviceAddress;
+
+ //
+ // Get whole USB device descriptor
+ //
+ Status = PeiUsbGetDescriptor (
+ PeiServices,
+ UsbIoPpi,
+ (USB_DT_DEVICE << 8),
+ 0,
+ (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),
+ &DeviceDescriptor
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));
+ return Status;
+ }
+ //
+ // Get its default configuration and its first interface
+ //
+ Status = PeiUsbGetAllConfiguration (
+ PeiServices,
+ PeiUsbDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PeiUsbSetConfiguration (
+ PeiServices,
+ UsbIoPpi
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get all configurations from a detected usb device.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.
+
+ @retval EFI_SUCCESS The new detected usb device is configured successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetAllConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ UINT16 ConfigDescLength;
+ UINT8 *Ptr;
+ UINTN SkipBytes;
+ UINTN LengthLeft;
+ UINTN Index;
+ UINTN NumOfEndpoint;
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+ //
+ // First get its 4-byte configuration descriptor
+ //
+ Status = PeiUsbGetDescriptor (
+ PeiServices,
+ UsbIoPpi,
+ (USB_DT_CONFIG << 8), // Value
+ 0, // Index
+ 4, // Length
+ PeiUsbDevice->ConfigurationData
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));
+ return Status;
+ }
+
+ ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;
+ ConfigDescLength = ConfigDesc->TotalLength;
+
+ //
+ // Then we get the total descriptors for this configuration
+ //
+ Status = PeiUsbGetDescriptor (
+ PeiServices,
+ UsbIoPpi,
+ (USB_DT_CONFIG << 8),
+ 0,
+ ConfigDescLength,
+ PeiUsbDevice->ConfigurationData
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));
+ return Status;
+ }
+ //
+ // Parse this configuration descriptor
+ // First get the current config descriptor;
+ //
+ Status = GetExpectedDescriptor (
+ PeiUsbDevice->ConfigurationData,
+ ConfigDescLength,
+ USB_DT_CONFIG,
+ (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),
+ &SkipBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;
+ PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;
+
+ Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+ LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+
+ //
+ // Get the first interface descriptor
+ //
+ Status = GetExpectedDescriptor (
+ Ptr,
+ LengthLeft,
+ USB_DT_INTERFACE,
+ (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
+ &SkipBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr += SkipBytes;
+ PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
+
+ Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+ LengthLeft -= SkipBytes;
+ LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+
+ //
+ // Parse all the endpoint descriptor within this interface
+ //
+ NumOfEndpoint = PeiUsbDevice->InterfaceDesc->NumEndpoints;
+ ASSERT (NumOfEndpoint <= MAX_ENDPOINT);
+
+ for (Index = 0; Index < NumOfEndpoint; Index++) {
+ //
+ // Get the endpoint descriptor
+ //
+ Status = GetExpectedDescriptor (
+ Ptr,
+ LengthLeft,
+ USB_DT_ENDPOINT,
+ (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
+ &SkipBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr += SkipBytes;
+ PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
+
+ Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
+ LengthLeft -= SkipBytes;
+ LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the start position of next wanted descriptor.
+
+ @param Buffer Buffer containing data to parse.
+ @param Length Buffer length.
+ @param DescType Descriptor type.
+ @param DescLength Descriptor length.
+ @param ParsedBytes Bytes has been parsed.
+
+ @retval EFI_SUCCESS Get wanted descriptor successfully.
+ @retval EFI_DEVICE_ERROR Error occurred.
+
+**/
+EFI_STATUS
+GetExpectedDescriptor (
+ IN UINT8 *Buffer,
+ IN UINTN Length,
+ IN UINT8 DescType,
+ IN UINT8 DescLength,
+ OUT UINTN *ParsedBytes
+ )
+{
+ UINT16 DescriptorHeader;
+ UINT8 Len;
+ UINT8 *Ptr;
+ UINTN Parsed;
+
+ Parsed = 0;
+ Ptr = Buffer;
+
+ while (TRUE) {
+ //
+ // Buffer length should not less than Desc length
+ //
+ if (Length < DescLength) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DescriptorHeader = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));
+
+ Len = Buffer[0];
+
+ //
+ // Check to see if it is a start of expected descriptor
+ //
+ if (DescriptorHeader == ((DescType << 8) | DescLength)) {
+ break;
+ }
+
+ if ((UINT8) (DescriptorHeader >> 8) == DescType) {
+ if (Len > DescLength) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Descriptor length should be at least 2
+ // and should not exceed the buffer length
+ //
+ if (Len < 2) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Len > Length) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Skip this mismatch descriptor
+ //
+ Length -= Len;
+ Ptr += Len;
+ Parsed += Len;
+ }
+
+ *ParsedBytes = Parsed;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send reset signal over the given root hub port.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+ @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+ @param PortNum The port to be reset.
+ @param RetryIndex The retry times.
+
+**/
+VOID
+ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,
+ IN UINT8 PortNum,
+ IN UINT8 RetryIndex
+ )
+{
+ EFI_STATUS Status;
+
+
+ if (Usb2HcPpi != NULL) {
+ MicroSecondDelay (200 * 1000);
+
+ //
+ // reset root port
+ //
+ Status = Usb2HcPpi->SetRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
+ return;
+ }
+
+ MicroSecondDelay (200 * 1000);
+
+ //
+ // clear reset root port
+ //
+ Status = Usb2HcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
+ return;
+ }
+
+ MicroSecondDelay (1 * 1000);
+
+ Usb2HcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ PortNum,
+ EfiUsbPortConnectChange
+ );
+
+ //
+ // Set port enable
+ //
+ Usb2HcPpi->SetRootHubPortFeature(
+ PeiServices,
+ Usb2HcPpi,
+ PortNum,
+ EfiUsbPortEnable
+ );
+
+ Usb2HcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ PortNum,
+ EfiUsbPortEnableChange
+ );
+
+ MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
+ } else {
+ MicroSecondDelay (200 * 1000);
+
+ //
+ // reset root port
+ //
+ Status = UsbHcPpi->SetRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
+ return;
+ }
+
+ MicroSecondDelay (200 * 1000);
+
+ //
+ // clear reset root port
+ //
+ Status = UsbHcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
+ return;
+ }
+
+ MicroSecondDelay (1 * 1000);
+
+ UsbHcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortConnectChange
+ );
+
+ //
+ // Set port enable
+ //
+ UsbHcPpi->SetRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortEnable
+ );
+
+ UsbHcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortEnableChange
+ );
+
+ MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
+ }
+ return;
+}
+
+
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
new file mode 100644
index 0000000..c9e75ba
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
@@ -0,0 +1,203 @@
+/** @file
+Usb Peim definition.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution. The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_USB_PEIM_H_
+#define _PEI_USB_PEIM_H_
+
+
+#include <PiPei.h>
+
+#include <Ppi/UsbHostController.h>
+#include <Ppi/Usb2HostController.h>
+#include <Ppi/UsbIo.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Usb.h>
+
+#define MAX_ROOT_PORT 2
+#define MAX_ENDPOINT 16
+
+#define USB_SLOW_SPEED_DEVICE 0x01
+#define USB_FULL_SPEED_DEVICE 0x02
+
+#define PEI_USB_DEVICE_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'D')
+typedef struct {
+ UINTN Signature;
+ PEI_USB_IO_PPI UsbIoPpi;
+ EFI_PEI_PPI_DESCRIPTOR UsbIoPpiList;
+ UINT8 DeviceAddress;
+ UINT8 MaxPacketSize0;
+ UINT8 DeviceSpeed;
+ UINT8 DataToggle;
+ UINT8 IsHub;
+ UINT8 DownStreamPortNo;
+ UINT8 Reserved[2]; // Padding for IPF
+ UINTN AllocateAddress;
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+ PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
+ UINT8 ConfigurationData[1024];
+ EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
+ EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc[MAX_ENDPOINT];
+ EFI_USB2_HC_TRANSACTION_TRANSLATOR Translator;
+} PEI_USB_DEVICE;
+
+#define PEI_USB_DEVICE_FROM_THIS(a) CR (a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE)
+
+
+/**
+ Submits control transfer to a target USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_IO_PPI.
+ @param Request USB device request to send.
+ @param Direction Specifies the data direction for the data stage.
+ @param Timeout Indicates the maximum timeout, in millisecond.
+ @param Data Data buffer to be transmitted or received from USB device.
+ @param DataLength The size (in bytes) of the data buffer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbControlTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data, OPTIONAL
+ IN UINTN DataLength OPTIONAL
+ );
+
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param PeiServices The pointer of EFI_PEI_SERVICES.
+ @param This The pointer of PEI_USB_IO_PPI.
+ @param DeviceEndpoint Endpoint number and its direction in bit 7.
+ @param Data A pointer to the buffer of data to transmit
+ from or receive into.
+ @param DataLength The lenght of the data buffer.
+ @param Timeout Indicates the maximum time, in millisecond, which the
+ transfer is allowed to complete.
+
+ @retval EFI_SUCCESS The transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
+ @retval EFI_INVALID_PARAMETER Parameters are invalid.
+ @retval EFI_TIMEOUT The transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbBulkTransfer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout
+ );
+
+/**
+ Get the usb interface descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the PEI_USB_IO_PPI instance.
+ @param InterfaceDescriptor Request interface descriptor.
+
+
+ @retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetInterfaceDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
+ );
+
+/**
+ Get the usb endpoint descriptor.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the PEI_USB_IO_PPI instance.
+ @param EndpointIndex The valid index of the specified endpoint.
+ @param EndpointDescriptor Request endpoint descriptor.
+
+ @retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
+ @retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetEndpointDescriptor (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This,
+ IN UINT8 EndpointIndex,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
+ );
+
+/**
+ Reset the port and re-configure the usb device.
+
+ @param PeiServices General-purpose services that are available to every PEIM.
+ @param This Indicates the PEI_USB_IO_PPI instance.
+
+ @retval EFI_SUCCESS Usb device is reset and configured successfully.
+ @retval Others Other failure occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbPortReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_IO_PPI *This
+ );
+
+/**
+ Send reset signal over the given root hub port.
+
+ @param PeiServices Describes the list of possible PEI Services.
+ @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+ @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+ @param PortNum The port to be reset.
+ @param RetryIndex The retry times.
+
+**/
+VOID
+ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,
+ IN UINT8 PortNum,
+ IN UINT8 RetryIndex
+ );
+
+#endif