[PATCH v2] MdeModulePkg/XhciDxe: Add access xHCI Extended Capabilities Pointer


Chiu, Ian
 

From: Ian Chiu <Ian.chiu@...>

Add support process Port Speed field value of PORTSC according to Supported=
Protocol Capability
(new design in xHCI spec 1.2 2019)

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D3914

The value of Port Speed field in PORTSC bit[10:13] (xHCI spec 1.2 2019 sect=
ion 5.4.8)
should be change to use this value to query thru Protocol Speed ID (PSI)
(xHCI spec 1.2 2019 section 7.2.1) in xHCI Supported Protocol Capability and
return the value according the Protocol Speed ID (PSIV) Dword.

Cc: Jenny Huang <jenny.huang@...>
Cc: More Shih <more.shih@...>
Cc: Hao A Wu <hao.a.wu@...>
Cc: Ray Ni <ray.ni@...>
Signed-off-by: Ian Chiu <Ian.chiu@...>
---
MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c | 41 ++++--
MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h | 2 +
MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c | 147 ++++++++++++++++++++
MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h | 87 ++++++++++++
4 files changed, 262 insertions(+), 15 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/Xhc=
iDxe/Xhci.c
index b79499e225..f5b99210c9 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -398,25 +398,32 @@ XhcGetRootHubPortStatus (
State =3D XhcReadOpReg (Xhc, Offset);=0D
=0D
//=0D
- // According to XHCI 1.1 spec November 2017,=0D
- // bit 10~13 of the root port status register identifies the speed of th=
e attached device.=0D
+ // According to XHCI 1.2 spec November 2019,=0D
+ // Section 7.2 xHCI Support Protocol Capability=0D
//=0D
- switch ((State & XHC_PORTSC_PS) >> 10) {=0D
- case 2:=0D
- PortStatus->PortStatus |=3D USB_PORT_STAT_LOW_SPEED;=0D
- break;=0D
+ PortStatus->PortStatus =3D XhcCheckUsbPortSpeedUsedPsic (Xhc, ((State & =
XHC_PORTSC_PS) >> 10));=0D
+ if (PortStatus->PortStatus =3D=3D 0) {=0D
+ //=0D
+ // According to XHCI 1.1 spec November 2017,=0D
+ // bit 10~13 of the root port status register identifies the speed of =
the attached device.=0D
+ //=0D
+ switch ((State & XHC_PORTSC_PS) >> 10) {=0D
+ case 2:=0D
+ PortStatus->PortStatus |=3D USB_PORT_STAT_LOW_SPEED;=0D
+ break;=0D
=0D
- case 3:=0D
- PortStatus->PortStatus |=3D USB_PORT_STAT_HIGH_SPEED;=0D
- break;=0D
+ case 3:=0D
+ PortStatus->PortStatus |=3D USB_PORT_STAT_HIGH_SPEED;=0D
+ break;=0D
=0D
- case 4:=0D
- case 5:=0D
- PortStatus->PortStatus |=3D USB_PORT_STAT_SUPER_SPEED;=0D
- break;=0D
+ case 4:=0D
+ case 5:=0D
+ PortStatus->PortStatus |=3D USB_PORT_STAT_SUPER_SPEED;=0D
+ break;=0D
=0D
- default:=0D
- break;=0D
+ default:=0D
+ break;=0D
+ }=0D
}=0D
=0D
//=0D
@@ -1820,6 +1827,8 @@ XhcCreateUsbHc (
Xhc->ExtCapRegBase =3D ExtCapReg << 2;=0D
Xhc->UsbLegSupOffset =3D XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY=
);=0D
Xhc->DebugCapSupOffset =3D XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG)=
;=0D
+ Xhc->Usb2SupOffset =3D XhcGetUsbSupportedCapabilityAddr (Xhc, USB_SUPPOR=
T_PROTOCOL_USB2_MAJOR_VER);=0D
+ Xhc->UsbSsSupOffset =3D XhcGetUsbSupportedCapabilityAddr (Xhc, USB_SUPPO=
RT_PROTOCOL_USB3_MAJOR_VER);=0D
=0D
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->Ca=
pLength));=0D
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams=
1));=0D
@@ -1829,6 +1838,8 @@ XhcCreateUsbHc (
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));=0D
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbL=
egSupOffset));=0D
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->De=
bugCapSupOffset));=0D
+ DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Usb2SupOffset 0x%x\n", Xhc->Usb2Su=
pOffset));=0D
+ DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: UsbSsSupOffset 0x%x\n", Xhc->UsbSs=
SupOffset));=0D
=0D
//=0D
// Create AsyncRequest Polling Timer=0D
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/Xhc=
iDxe/Xhci.h
index 5054d796b1..7eed7bd15e 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
@@ -227,6 +227,8 @@ struct _USB_XHCI_INSTANCE {
UINT32 ExtCapRegBase;=0D
UINT32 UsbLegSupOffset;=0D
UINT32 DebugCapSupOffset;=0D
+ UINT32 Usb2SupOffset;=0D
+ UINT32 UsbSsSupOffset;=0D
UINT64 *DCBAA;=0D
VOID *DCBAAMap;=0D
UINT32 MaxSlotsEn;=0D
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/=
XhciDxe/XhciReg.c
index 80be3311d4..5bff698edb 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -564,7 +564,57 @@ XhcGetCapabilityAddr (
if ((Data & 0xFF) =3D=3D CapId) {=0D
return ExtCapOffset;=0D
}=0D
+ //=0D
+ // If not, then traverse all of the ext capability registers till find=
ing out it.=0D
+ //=0D
+ NextExtCapReg =3D (UINT8)((Data >> 8) & 0xFF);=0D
+ ExtCapOffset +=3D (NextExtCapReg << 2);=0D
+ } while (NextExtCapReg !=3D 0);=0D
+=0D
+ return 0xFFFFFFFF;=0D
+}=0D
=0D
+/**=0D
+ Calculate the offset of the xHCI Supported Protocol Capability.=0D
+=0D
+ @param Xhc The XHCI Instance.=0D
+ @param MajorVersion The USB Major Version in xHCI Support Protocol Cap=
ability Field=0D
+=0D
+ @return The offset of xHCI Supported Protocol capability register.=0D
+=0D
+**/=0D
+UINT32=0D
+XhcGetUsbSupportedCapabilityAddr (=0D
+ IN USB_XHCI_INSTANCE *Xhc,=0D
+ IN UINT8 MajorVersion=0D
+ )=0D
+{=0D
+ UINT32 ExtCapOffset;=0D
+ UINT8 NextExtCapReg;=0D
+ UINT32 Data;=0D
+ UINT32 NameString;=0D
+ XHC_SUPPORTED_PROTOCOL_DW0 UsbSupportDw0;=0D
+=0D
+ if (Xhc =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ ExtCapOffset =3D 0;=0D
+=0D
+ do {=0D
+ //=0D
+ // Check if the extended capability register's capability id is USB Le=
gacy Support.=0D
+ //=0D
+ Data =3D XhcReadExtCapReg (Xhc, ExtCapOffset);=0D
+ UsbSupportDw0.Dword =3D Data;=0D
+ if ((Data & 0xFF) =3D=3D XHC_CAP_USB_SUPPORTED) {=0D
+ if (UsbSupportDw0.Data.RevMajor =3D=3D MajorVersion) {=0D
+ NameString =3D XhcReadExtCapReg (Xhc, ExtCapOffset + USB_SUPPORTED=
_NAME_STRING_OFFSET);=0D
+ if (NameString =3D=3D USB_SUPPORTED_PROTOCOL_NAME_STRING) {=0D
+ return ExtCapOffset;=0D
+ }=0D
+ }=0D
+ }=0D
//=0D
// If not, then traverse all of the ext capability registers till find=
ing out it.=0D
//=0D
@@ -575,6 +625,103 @@ XhcGetCapabilityAddr (
return 0xFFFFFFFF;=0D
}=0D
=0D
+/**=0D
+ Find SpeedField value match with Port Speed ID value.=0D
+=0D
+ @param Xhc The XHCI Instance.=0D
+ @param ExtCapOffset The USB Major Version in xHCI Support Protocol Cap=
ability Field=0D
+ @param SpeedField The Port Speed filed in USB PortSc register=0D
+=0D
+ @return The Protocol Speed ID xHCI Supported Protocol capability registe=
r.=0D
+=0D
+**/=0D
+UINT32=0D
+XhciPsivGetPsid (=0D
+ IN USB_XHCI_INSTANCE *Xhc,=0D
+ IN UINT32 ExtCapOffset,=0D
+ IN UINT8 SpeedField=0D
+ )=0D
+{=0D
+ XHC_SUPPORTED_PROTOCOL_DW2 PortId;=0D
+ XHC_SUPPORTED_PROTOCOL_FIELD Reg;=0D
+ UINT32 Count;=0D
+=0D
+ if ((Xhc =3D=3D NULL) || (ExtCapOffset =3D=3D 0xFFFFFFFF)) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ //=0D
+ // According to XHCI 1.2 spec November 2019,=0D
+ // Section 7.2 xHCI Supported Protocol Capability=0D
+ // 1. Get the PSIC(Protocol Speed ID Count) Value.=0D
+ // 2. The PSID register boundary should be Base address + PSIC * 0x04=0D
+ //=0D
+ PortId.Dword =3D XhcReadExtCapReg (Xhc, ExtCapOffset + USB_SUPPORTED_PO=
RT_ID_OFFSET);=0D
+=0D
+ for (Count =3D 0; Count < PortId.Data.Psic; Count++) {=0D
+ Reg.Dword =3D XhcReadExtCapReg (Xhc, ExtCapOffset + USB_SUPPORT_SPEED_=
ID_OFFSET + (Count << 2));=0D
+ if (Reg.Data.Psiv =3D=3D SpeedField) {=0D
+ return Reg.Dword;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Find SpeedField value match with Port Speed ID value.=0D
+=0D
+ @param Xhc The XHCI Instance.=0D
+ @param Speed The Port Speed filed in USB PortSc register=0D
+=0D
+ @return The USB Port Speed.=0D
+=0D
+**/=0D
+UINT16=0D
+XhcCheckUsbPortSpeedUsedPsic (=0D
+ IN USB_XHCI_INSTANCE *Xhc,=0D
+ IN UINT8 Speed=0D
+ )=0D
+{=0D
+ XHC_SUPPORTED_PROTOCOL_FIELD SpField;=0D
+ UINT16 ReturnSpeed;=0D
+=0D
+ if (Xhc =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ SpField.Dword =3D 0;=0D
+ ReturnSpeed =3D 0;=0D
+ //=0D
+ // Check USB3 Protocol Speed ID if ReturnSpeed didn't get match speed.=0D
+ //=0D
+ if ((ReturnSpeed =3D=3D 0) && (Xhc->UsbSsSupOffset !=3D 0xFFFFFFFF)) {=0D
+ SpField.Dword =3D XhciPsivGetPsid (Xhc, Xhc->UsbSsSupOffset, Speed);=0D
+ if (SpField.Dword !=3D 0) {=0D
+ // Super Speed=0D
+ ReturnSpeed =3D USB_PORT_STAT_SUPER_SPEED;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Check USB2 Protocol Speed ID if ReturnSpeed didn't get match speed.=0D
+ //=0D
+ if ((ReturnSpeed =3D=3D 0) && (Xhc->Usb2SupOffset !=3D 0xFFFFFFFF)) {=0D
+ SpField.Dword =3D XhciPsivGetPsid (Xhc, Xhc->Usb2SupOffset, Speed);=0D
+ if (SpField.Dword !=3D 0) {=0D
+ if (SpField.Data.Psie =3D=3D 2) {=0D
+ if (SpField.Data.Mantissa =3D=3D USB_SUPPORT_PROTOCOL_USB2_HIGH_SP=
EED_PSIM) {=0D
+ // High Speed=0D
+ ReturnSpeed =3D USB_PORT_STAT_HIGH_SPEED;=0D
+ }=0D
+ } else if (SpField.Data.Psie =3D=3D 1) {=0D
+ // Low speed=0D
+ ReturnSpeed =3D USB_PORT_STAT_LOW_SPEED;=0D
+ }=0D
+ }=0D
+ }=0D
+ return ReturnSpeed;=0D
+}=0D
+=0D
/**=0D
Whether the XHCI host controller is halted.=0D
=0D
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h b/MdeModulePkg/Bus/Pci/=
XhciDxe/XhciReg.h
index 4950eed272..4f83b49027 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
@@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
=0D
#define XHC_CAP_USB_LEGACY 0x01=0D
#define XHC_CAP_USB_DEBUG 0x0A=0D
+#define XHC_CAP_USB_SUPPORTED 0x02=0D
=0D
// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D//=0D
// XHCI register offset //=0D
@@ -74,6 +75,17 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define USBLEGSP_BIOS_SEMAPHORE BIT16 // HC BIOS Owned Semaphor=
e=0D
#define USBLEGSP_OS_SEMAPHORE BIT24 // HC OS Owned Semaphore=
=0D
=0D
+//=0D
+// xHCI Supported Protocol Capability=0D
+//=0D
+#define USB_SUPPORTED_PROTOCOL_NAME_STRING 0x20425355=0D
+#define USB_SUPPORTED_NAME_STRING_OFFSET 0x04=0D
+#define USB_SUPPORTED_PORT_ID_OFFSET 0x08=0D
+#define USB_SUPPORT_SPEED_ID_OFFSET 0x10=0D
+#define USB_SUPPORT_PROTOCOL_USB2_MAJOR_VER 0x02=0D
+#define USB_SUPPORT_PROTOCOL_USB3_MAJOR_VER 0x03=0D
+#define USB_SUPPORT_PROTOCOL_USB2_HIGH_SPEED_PSIM 480=0D
+=0D
#pragma pack (1)=0D
typedef struct {=0D
UINT8 MaxSlots; // Number of Device Slots=0D
@@ -130,6 +142,52 @@ typedef union {
HCCPARAMS Data;=0D
} XHC_HCCPARAMS;=0D
=0D
+//=0D
+// xHCI Supported Protocol Cabability=0D
+//=0D
+typedef struct {=0D
+ UINT8 CapId;=0D
+ UINT8 NextExtCapReg;=0D
+ UINT8 RevMinor;=0D
+ UINT8 RevMajor;=0D
+} SUPP_PROTOCOL_DW0;=0D
+=0D
+typedef union {=0D
+ UINT32 Dword;=0D
+ SUPP_PROTOCOL_DW0 Data;=0D
+} XHC_SUPPORTED_PROTOCOL_DW0;=0D
+=0D
+typedef struct {=0D
+ UINT32 NameString;=0D
+} XHC_SUPPORTED_PROTOCOL_DW1;=0D
+=0D
+typedef struct {=0D
+ UINT8 CompPortOffset : 8;=0D
+ UINT8 CompPortCount : 8;=0D
+ UINT16 ProtocolDef :12;=0D
+ UINT16 Psic : 4;=0D
+} SUPP_PROTOCOL_DW2;=0D
+=0D
+typedef union {=0D
+ UINT32 Dword;=0D
+ SUPP_PROTOCOL_DW2 Data;=0D
+} XHC_SUPPORTED_PROTOCOL_DW2;=0D
+=0D
+typedef struct {=0D
+ UINT16 Psiv : 4;=0D
+ UINT16 Psie : 2;=0D
+ UINT16 Plt : 2;=0D
+ UINT16 Pfd : 1;=0D
+ UINT16 RsvdP : 5;=0D
+ UINT16 Lp : 2;=0D
+ UINT16 Mantissa :16;=0D
+} XHCI_PROTOCOL_FIELD;=0D
+=0D
+typedef union {=0D
+ UINT32 Dword;=0D
+ XHCI_PROTOCOL_FIELD Data;=0D
+} XHC_SUPPORTED_PROTOCOL_FIELD;=0D
+=0D
#pragma pack ()=0D
=0D
//=0D
@@ -546,4 +604,33 @@ XhcGetCapabilityAddr (
IN UINT8 CapId=0D
);=0D
=0D
+/**=0D
+ Calculate the offset of the xHCI Supported Protocol Capability.=0D
+=0D
+ @param Xhc The XHCI Instance.=0D
+ @param MajorVersion The USB Major Version in xHCI Support Protocol Cap=
ability Field=0D
+=0D
+ @return The offset of xHCI Supported Protocol capability register.=0D
+=0D
+**/=0D
+UINT32=0D
+XhcGetUsbSupportedCapabilityAddr (=0D
+ IN USB_XHCI_INSTANCE *Xhc,=0D
+ IN UINT8 MajorVersion=0D
+ );=0D
+=0D
+/**=0D
+ Find SpeedField value match with Port Speed ID value.=0D
+=0D
+ @param Xhc The XHCI Instance.=0D
+ @param Speed The Port Speed filed in USB PortSc register=0D
+=0D
+ @return The USB Port Speed.=0D
+=0D
+**/=0D
+UINT16=0D
+XhcCheckUsbPortSpeedUsedPsic (=0D
+ IN USB_XHCI_INSTANCE *Xhc,=0D
+ IN UINT8 Speed=0D
+ );=0D
#endif=0D
--=20
2.26.2.windows.1

Join devel@edk2.groups.io to automatically receive all group messages.