mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-27 07:34:06 +02:00
MdeModulePkg XhciDxe: XHCI multiple interface alternate setting support.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15617 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
8acb3f7b54
commit
e1f2dfec34
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
The XHCI controller driver.
|
||||
|
||||
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2014, 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
|
||||
@ -968,6 +968,10 @@ XhcControlTransfer (
|
||||
ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
|
||||
Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);
|
||||
CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
|
||||
//
|
||||
// Default to use AlternateSetting 0 for all interfaces.
|
||||
//
|
||||
Xhc->UsbDevContext[SlotId].ActiveAlternateSetting = AllocateZeroPool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->NumInterfaces * sizeof (UINT8));
|
||||
}
|
||||
} else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
|
||||
(DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {
|
||||
@ -1009,6 +1013,20 @@ XhcControlTransfer (
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((Request->Request == USB_REQ_SET_INTERFACE) &&
|
||||
(Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_INTERFACE))) {
|
||||
//
|
||||
// Hook Set_Interface request from UsbBus as we need configure interface setting.
|
||||
// Request->Value indicates AlterlateSetting to set
|
||||
// Request->Index indicates Interface to set
|
||||
//
|
||||
if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] != (UINT8) Request->Value) {
|
||||
if (Xhc->HcCParams.Data.Csz == 0) {
|
||||
Status = XhcSetInterface (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);
|
||||
} else {
|
||||
Status = XhcSetInterface64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);
|
||||
}
|
||||
}
|
||||
} else if ((Request->Request == USB_REQ_GET_STATUS) &&
|
||||
(Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {
|
||||
ASSERT (Data != NULL);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Provides some data structure definitions used by the XHCI host controller driver.
|
||||
|
||||
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2014, 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
|
||||
@ -196,6 +196,14 @@ struct _USB_DEV_CONTEXT {
|
||||
// These information is used to support XHCI's Config_Endpoint cmd.
|
||||
//
|
||||
EFI_USB_CONFIG_DESCRIPTOR **ConfDesc;
|
||||
//
|
||||
// A device has an active Configuration.
|
||||
//
|
||||
UINT8 ActiveConfiguration;
|
||||
//
|
||||
// Every interface has an active AlternateSetting.
|
||||
//
|
||||
UINT8 *ActiveAlternateSetting;
|
||||
};
|
||||
|
||||
struct _USB_XHCI_INSTANCE {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
XHCI transfer scheduling routines.
|
||||
|
||||
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2014, 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
|
||||
@ -750,7 +750,7 @@ CreateEventRing (
|
||||
//
|
||||
EventRing->EventRingCCS = 1;
|
||||
|
||||
Size = EFI_SIZE_TO_PAGES (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
|
||||
Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER;
|
||||
Buf = UsbHcAllocateMem (Xhc->MemPool, Size);
|
||||
ASSERT (Buf != NULL);
|
||||
ASSERT (((UINTN) Buf & 0x3F) == 0);
|
||||
@ -2385,6 +2385,10 @@ XhcDisableSlotCmd (
|
||||
}
|
||||
}
|
||||
|
||||
if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting != NULL) {
|
||||
FreePool (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting);
|
||||
}
|
||||
|
||||
if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
|
||||
UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));
|
||||
}
|
||||
@ -2488,6 +2492,10 @@ XhcDisableSlotCmd64 (
|
||||
}
|
||||
}
|
||||
|
||||
if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting != NULL) {
|
||||
FreePool (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting);
|
||||
}
|
||||
|
||||
if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
|
||||
UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));
|
||||
}
|
||||
@ -2506,31 +2514,29 @@ XhcDisableSlotCmd64 (
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure all the device endpoints through XHCI's Configure_Endpoint cmd.
|
||||
Initialize endpoint context in input context.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param ConfigDesc The pointer to the usb device configuration descriptor.
|
||||
@param InputContext The pointer to the input context.
|
||||
@param IfDesc The pointer to the usb device interface descriptor.
|
||||
|
||||
@retval EFI_SUCCESS Successfully configure all the device endpoints.
|
||||
@return The maximum device context index of endpoint.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UINT8
|
||||
EFIAPI
|
||||
XhcSetConfigCmd (
|
||||
XhcInitializeEndpointContext (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc
|
||||
IN INPUT_CONTEXT *InputContext,
|
||||
IN USB_INTERFACE_DESCRIPTOR *IfDesc
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
||||
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
||||
UINT8 Index;
|
||||
UINTN NumEp;
|
||||
UINTN EpIndex;
|
||||
UINT8 EpAddr;
|
||||
@ -2539,30 +2545,10 @@ XhcSetConfigCmd (
|
||||
UINT8 MaxDci;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
UINT8 Interval;
|
||||
|
||||
TRANSFER_RING *EndpointTransferRing;
|
||||
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
||||
INPUT_CONTEXT *InputContext;
|
||||
DEVICE_CONTEXT *OutputContext;
|
||||
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
|
||||
//
|
||||
// 4.6.6 Configure Endpoint
|
||||
//
|
||||
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
|
||||
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
|
||||
ZeroMem (InputContext, sizeof (INPUT_CONTEXT));
|
||||
CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT));
|
||||
|
||||
ASSERT (ConfigDesc != NULL);
|
||||
|
||||
MaxDci = 0;
|
||||
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
||||
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
|
||||
while (IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) {
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
NumEp = IfDesc->NumEndpoints;
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
|
||||
@ -2677,6 +2663,217 @@ XhcSetConfigCmd (
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
return MaxDci;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize endpoint context in input context.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param InputContext The pointer to the input context.
|
||||
@param IfDesc The pointer to the usb device interface descriptor.
|
||||
|
||||
@return The maximum device context index of endpoint.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
XhcInitializeEndpointContext64 (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN INPUT_CONTEXT_64 *InputContext,
|
||||
IN USB_INTERFACE_DESCRIPTOR *IfDesc
|
||||
)
|
||||
{
|
||||
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
||||
UINTN NumEp;
|
||||
UINTN EpIndex;
|
||||
UINT8 EpAddr;
|
||||
UINT8 Direction;
|
||||
UINT8 Dci;
|
||||
UINT8 MaxDci;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
UINT8 Interval;
|
||||
TRANSFER_RING *EndpointTransferRing;
|
||||
|
||||
MaxDci = 0;
|
||||
|
||||
NumEp = IfDesc->NumEndpoints;
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
|
||||
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
|
||||
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F);
|
||||
Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);
|
||||
|
||||
Dci = XhcEndpointToDci (EpAddr, Direction);
|
||||
ASSERT (Dci < 32);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
|
||||
InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);
|
||||
InputContext->EP[Dci-1].MaxPacketSize = EpDesc->MaxPacketSize;
|
||||
|
||||
if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
|
||||
//
|
||||
// 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.
|
||||
//
|
||||
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
|
||||
}
|
||||
|
||||
switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {
|
||||
case USB_ENDPOINT_BULK:
|
||||
if (Direction == EfiUsbDataIn) {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_BULK_IN;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_BULK_OUT;
|
||||
}
|
||||
|
||||
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
|
||||
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {
|
||||
EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));
|
||||
Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;
|
||||
CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_ENDPOINT_ISO:
|
||||
if (Direction == EfiUsbDataIn) {
|
||||
InputContext->EP[Dci-1].CErr = 0;
|
||||
InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].CErr = 0;
|
||||
InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;
|
||||
}
|
||||
break;
|
||||
case USB_ENDPOINT_INTERRUPT:
|
||||
if (Direction == EfiUsbDataIn) {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;
|
||||
}
|
||||
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
|
||||
InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;
|
||||
//
|
||||
// Get the bInterval from descriptor and init the the interval field of endpoint context
|
||||
//
|
||||
if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {
|
||||
Interval = EpDesc->Interval;
|
||||
//
|
||||
// Calculate through the bInterval field of Endpoint descriptor.
|
||||
//
|
||||
ASSERT (Interval != 0);
|
||||
InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3;
|
||||
} else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
|
||||
Interval = EpDesc->Interval;
|
||||
ASSERT (Interval >= 1 && Interval <= 16);
|
||||
//
|
||||
// Refer to XHCI 1.0 spec section 6.2.3.6, table 61
|
||||
//
|
||||
InputContext->EP[Dci-1].Interval = Interval - 1;
|
||||
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
|
||||
InputContext->EP[Dci-1].MaxESITPayload = 0x0002;
|
||||
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
}
|
||||
|
||||
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {
|
||||
EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));
|
||||
Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;
|
||||
CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_ENDPOINT_CONTROL:
|
||||
default:
|
||||
ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
PhyAddr = UsbHcGetPciAddrForHostAddr (
|
||||
Xhc->MemPool,
|
||||
((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,
|
||||
sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
|
||||
);
|
||||
PhyAddr &= ~(0x0F);
|
||||
PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
|
||||
InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);
|
||||
InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
return MaxDci;
|
||||
}
|
||||
|
||||
/**
|
||||
Configure all the device endpoints through XHCI's Configure_Endpoint cmd.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param ConfigDesc The pointer to the usb device configuration descriptor.
|
||||
|
||||
@retval EFI_SUCCESS Successfully configure all the device endpoints.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
XhcSetConfigCmd (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
||||
UINT8 Index;
|
||||
UINT8 Dci;
|
||||
UINT8 MaxDci;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
|
||||
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
||||
INPUT_CONTEXT *InputContext;
|
||||
DEVICE_CONTEXT *OutputContext;
|
||||
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
|
||||
//
|
||||
// 4.6.6 Configure Endpoint
|
||||
//
|
||||
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
|
||||
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
|
||||
ZeroMem (InputContext, sizeof (INPUT_CONTEXT));
|
||||
CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT));
|
||||
|
||||
ASSERT (ConfigDesc != NULL);
|
||||
|
||||
MaxDci = 0;
|
||||
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
||||
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
|
||||
while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
@ -2701,7 +2898,10 @@ XhcSetConfigCmd (
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));
|
||||
} else {
|
||||
Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
@ -2727,18 +2927,11 @@ XhcSetConfigCmd64 (
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
||||
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
||||
UINT8 Index;
|
||||
UINTN NumEp;
|
||||
UINTN EpIndex;
|
||||
UINT8 EpAddr;
|
||||
UINT8 Direction;
|
||||
UINT8 Dci;
|
||||
UINT8 MaxDci;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
UINT8 Interval;
|
||||
|
||||
TRANSFER_RING *EndpointTransferRing;
|
||||
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
||||
INPUT_CONTEXT_64 *InputContext;
|
||||
DEVICE_CONTEXT_64 *OutputContext;
|
||||
@ -2757,126 +2950,15 @@ XhcSetConfigCmd64 (
|
||||
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
||||
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
|
||||
while (IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) {
|
||||
while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
NumEp = IfDesc->NumEndpoints;
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
|
||||
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
|
||||
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F);
|
||||
Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);
|
||||
|
||||
Dci = XhcEndpointToDci (EpAddr, Direction);
|
||||
ASSERT (Dci < 32);
|
||||
Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
|
||||
InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);
|
||||
InputContext->EP[Dci-1].MaxPacketSize = EpDesc->MaxPacketSize;
|
||||
|
||||
if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
|
||||
//
|
||||
// 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.
|
||||
//
|
||||
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
|
||||
}
|
||||
|
||||
switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {
|
||||
case USB_ENDPOINT_BULK:
|
||||
if (Direction == EfiUsbDataIn) {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_BULK_IN;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_BULK_OUT;
|
||||
}
|
||||
|
||||
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
|
||||
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {
|
||||
EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));
|
||||
Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;
|
||||
CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_ENDPOINT_ISO:
|
||||
if (Direction == EfiUsbDataIn) {
|
||||
InputContext->EP[Dci-1].CErr = 0;
|
||||
InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].CErr = 0;
|
||||
InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;
|
||||
}
|
||||
break;
|
||||
case USB_ENDPOINT_INTERRUPT:
|
||||
if (Direction == EfiUsbDataIn) {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;
|
||||
} else {
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;
|
||||
}
|
||||
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
|
||||
InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;
|
||||
//
|
||||
// Get the bInterval from descriptor and init the the interval field of endpoint context
|
||||
//
|
||||
if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {
|
||||
Interval = EpDesc->Interval;
|
||||
//
|
||||
// Calculate through the bInterval field of Endpoint descriptor.
|
||||
//
|
||||
ASSERT (Interval != 0);
|
||||
InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3;
|
||||
} else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
|
||||
Interval = EpDesc->Interval;
|
||||
ASSERT (Interval >= 1 && Interval <= 16);
|
||||
//
|
||||
// Refer to XHCI 1.0 spec section 6.2.3.6, table 61
|
||||
//
|
||||
InputContext->EP[Dci-1].Interval = Interval - 1;
|
||||
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
|
||||
InputContext->EP[Dci-1].MaxESITPayload = 0x0002;
|
||||
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
|
||||
InputContext->EP[Dci-1].CErr = 3;
|
||||
}
|
||||
|
||||
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {
|
||||
EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));
|
||||
Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;
|
||||
CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_ENDPOINT_CONTROL:
|
||||
default:
|
||||
ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
PhyAddr = UsbHcGetPciAddrForHostAddr (
|
||||
Xhc->MemPool,
|
||||
((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,
|
||||
sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
|
||||
);
|
||||
|
||||
PhyAddr &= ~(0x0F);
|
||||
PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
|
||||
|
||||
InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);
|
||||
InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
@ -2901,11 +2983,452 @@ XhcSetConfigCmd64 (
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));
|
||||
} else {
|
||||
Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Stop endpoint through XHCI's Stop_Endpoint cmd.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param Dci The device context index of endpoint.
|
||||
|
||||
@retval EFI_SUCCESS Stop endpoint successfully.
|
||||
@retval Others Failed to stop endpoint.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
XhcStopEndpoint (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 Dci
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
|
||||
CMD_TRB_STOP_ENDPOINT CmdTrbStopED;
|
||||
|
||||
DEBUG ((EFI_D_INFO, "XhcStopEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci));
|
||||
|
||||
//
|
||||
// Send stop endpoint command to transit Endpoint from running to stop state
|
||||
//
|
||||
ZeroMem (&CmdTrbStopED, sizeof (CmdTrbStopED));
|
||||
CmdTrbStopED.CycleBit = 1;
|
||||
CmdTrbStopED.Type = TRB_TYPE_STOP_ENDPOINT;
|
||||
CmdTrbStopED.EDID = Dci;
|
||||
CmdTrbStopED.SlotId = SlotId;
|
||||
Status = XhcCmdTransfer (
|
||||
Xhc,
|
||||
(TRB_TEMPLATE *) (UINTN) &CmdTrbStopED,
|
||||
XHC_GENERIC_TIMEOUT,
|
||||
(TRB_TEMPLATE **) (UINTN) &EvtTrb
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "XhcStopEndpoint: Stop Endpoint Failed, Status = %r\n", Status));
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Set interface through XHCI's Configure_Endpoint cmd.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param ConfigDesc The pointer to the usb device configuration descriptor.
|
||||
@param Request USB device request to send.
|
||||
|
||||
@retval EFI_SUCCESS Successfully set interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
XhcSetInterface (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc,
|
||||
IN EFI_USB_DEVICE_REQUEST *Request
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDescActive;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDescSet;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
||||
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
||||
UINTN NumEp;
|
||||
UINTN EpIndex;
|
||||
UINT8 EpAddr;
|
||||
UINT8 Direction;
|
||||
UINT8 Dci;
|
||||
UINT8 MaxDci;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
VOID *RingSeg;
|
||||
|
||||
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
||||
INPUT_CONTEXT *InputContext;
|
||||
DEVICE_CONTEXT *OutputContext;
|
||||
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
|
||||
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
|
||||
//
|
||||
// XHCI 4.6.6 Configure Endpoint
|
||||
// When this command is used to "Set an Alternate Interface on a device", software shall set the Drop
|
||||
// Context and Add Context flags as follows:
|
||||
// 1) If an endpoint is not modified by the Alternate Interface setting, then software shall set the Drop
|
||||
// Context and Add Context flags to '0'.
|
||||
//
|
||||
// Except the interface indicated by Reqeust->Index, no impact to other interfaces.
|
||||
// So the default Drop Context and Add Context flags can be '0' to cover 1).
|
||||
//
|
||||
ZeroMem (InputContext, sizeof (INPUT_CONTEXT));
|
||||
CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT));
|
||||
|
||||
ASSERT (ConfigDesc != NULL);
|
||||
|
||||
MaxDci = 0;
|
||||
|
||||
IfDescActive = NULL;
|
||||
IfDescSet = NULL;
|
||||
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
||||
while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {
|
||||
if (IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) {
|
||||
if (IfDesc->InterfaceNumber == (UINT8) Request->Index) {
|
||||
if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {
|
||||
//
|
||||
// Find out the active interface descriptor.
|
||||
//
|
||||
IfDescActive = IfDesc;
|
||||
} else if (IfDesc->AlternateSetting == (UINT8) Request->Value) {
|
||||
//
|
||||
// Find out the interface descriptor to set.
|
||||
//
|
||||
IfDescSet = IfDesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
//
|
||||
// XHCI 4.6.6 Configure Endpoint
|
||||
// When this command is used to "Set an Alternate Interface on a device", software shall set the Drop
|
||||
// Context and Add Context flags as follows:
|
||||
// 2) If an endpoint previously disabled, is enabled by the Alternate Interface setting, then software shall set
|
||||
// the Drop Context flag to '0' and Add Context flag to '1', and initialize the Input Endpoint Context.
|
||||
// 3) If an endpoint previously enabled, is disabled by the Alternate Interface setting, then software shall set
|
||||
// the Drop Context flag to '1' and Add Context flag to '0'.
|
||||
// 4) If a parameter of an enabled endpoint is modified by an Alternate Interface setting, the Drop Context
|
||||
// and Add Context flags shall be set to '1'.
|
||||
//
|
||||
// Below codes are to cover 2), 3) and 4).
|
||||
//
|
||||
|
||||
if ((IfDescActive != NULL) && (IfDescSet != NULL)) {
|
||||
NumEp = IfDescActive->NumEndpoints;
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 1);
|
||||
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
|
||||
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
EpAddr = (UINT8) (EpDesc->EndpointAddress & 0x0F);
|
||||
Direction = (UINT8) ((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);
|
||||
|
||||
Dci = XhcEndpointToDci (EpAddr, Direction);
|
||||
ASSERT (Dci < 32);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 1) Stop any Running Transfer Rings affected by the Alternate Interface setting.
|
||||
//
|
||||
Status = XhcStopEndpoint (Xhc, SlotId, Dci);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting.
|
||||
//
|
||||
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {
|
||||
RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;
|
||||
if (RingSeg != NULL) {
|
||||
UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
|
||||
}
|
||||
FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);
|
||||
Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the Drop Context flag to '1'.
|
||||
//
|
||||
InputContext->InputControlContext.Dword1 |= (BIT0 << Dci);
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 3) Clear all the Endpoint Context fields of each endpoint that will be disabled by the Alternate
|
||||
// Interface setting, to '0'.
|
||||
//
|
||||
// The step 3) has been covered by the ZeroMem () to InputContext at the start of the function.
|
||||
//
|
||||
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 4) For each endpoint enabled by the Configure Endpoint Command:
|
||||
// a. Allocate a Transfer Ring.
|
||||
// b. Initialize the Transfer Ring Segment(s) by clearing all fields of all TRBs to '0'.
|
||||
// c. Initialize the Endpoint Context data structure.
|
||||
//
|
||||
Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDescSet);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
|
||||
InputContext->InputControlContext.Dword2 |= BIT0;
|
||||
InputContext->Slot.ContextEntries = MaxDci;
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 5) Issue and successfully complete a Configure Endpoint Command.
|
||||
//
|
||||
ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
|
||||
PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));
|
||||
CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);
|
||||
CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);
|
||||
CmdTrbCfgEP.CycleBit = 1;
|
||||
CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
|
||||
CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
|
||||
DEBUG ((EFI_D_INFO, "SetInterface: Configure Endpoint\n"));
|
||||
Status = XhcCmdTransfer (
|
||||
Xhc,
|
||||
(TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,
|
||||
XHC_GENERIC_TIMEOUT,
|
||||
(TRB_TEMPLATE **) (UINTN) &EvtTrb
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "SetInterface: Config Endpoint Failed, Status = %r\n", Status));
|
||||
} else {
|
||||
//
|
||||
// Update the active AlternateSetting.
|
||||
//
|
||||
Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Set interface through XHCI's Configure_Endpoint cmd.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param ConfigDesc The pointer to the usb device configuration descriptor.
|
||||
@param Request USB device request to send.
|
||||
|
||||
@retval EFI_SUCCESS Successfully set interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
XhcSetInterface64 (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc,
|
||||
IN EFI_USB_DEVICE_REQUEST *Request
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDescActive;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDescSet;
|
||||
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
||||
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
||||
UINTN NumEp;
|
||||
UINTN EpIndex;
|
||||
UINT8 EpAddr;
|
||||
UINT8 Direction;
|
||||
UINT8 Dci;
|
||||
UINT8 MaxDci;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
VOID *RingSeg;
|
||||
|
||||
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
||||
INPUT_CONTEXT_64 *InputContext;
|
||||
DEVICE_CONTEXT_64 *OutputContext;
|
||||
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
|
||||
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
|
||||
//
|
||||
// XHCI 4.6.6 Configure Endpoint
|
||||
// When this command is used to "Set an Alternate Interface on a device", software shall set the Drop
|
||||
// Context and Add Context flags as follows:
|
||||
// 1) If an endpoint is not modified by the Alternate Interface setting, then software shall set the Drop
|
||||
// Context and Add Context flags to '0'.
|
||||
//
|
||||
// Except the interface indicated by Reqeust->Index, no impact to other interfaces.
|
||||
// So the default Drop Context and Add Context flags can be '0' to cover 1).
|
||||
//
|
||||
ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));
|
||||
CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT_64));
|
||||
|
||||
ASSERT (ConfigDesc != NULL);
|
||||
|
||||
MaxDci = 0;
|
||||
|
||||
IfDescActive = NULL;
|
||||
IfDescSet = NULL;
|
||||
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
||||
while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {
|
||||
if (IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) {
|
||||
if (IfDesc->InterfaceNumber == (UINT8) Request->Index) {
|
||||
if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {
|
||||
//
|
||||
// Find out the active interface descriptor.
|
||||
//
|
||||
IfDescActive = IfDesc;
|
||||
} else if (IfDesc->AlternateSetting == (UINT8) Request->Value) {
|
||||
//
|
||||
// Find out the interface descriptor to set.
|
||||
//
|
||||
IfDescSet = IfDesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||
}
|
||||
|
||||
//
|
||||
// XHCI 4.6.6 Configure Endpoint
|
||||
// When this command is used to "Set an Alternate Interface on a device", software shall set the Drop
|
||||
// Context and Add Context flags as follows:
|
||||
// 2) If an endpoint previously disabled, is enabled by the Alternate Interface setting, then software shall set
|
||||
// the Drop Context flag to '0' and Add Context flag to '1', and initialize the Input Endpoint Context.
|
||||
// 3) If an endpoint previously enabled, is disabled by the Alternate Interface setting, then software shall set
|
||||
// the Drop Context flag to '1' and Add Context flag to '0'.
|
||||
// 4) If a parameter of an enabled endpoint is modified by an Alternate Interface setting, the Drop Context
|
||||
// and Add Context flags shall be set to '1'.
|
||||
//
|
||||
// Below codes are to cover 2), 3) and 4).
|
||||
//
|
||||
|
||||
if ((IfDescActive != NULL) && (IfDescSet != NULL)) {
|
||||
NumEp = IfDescActive->NumEndpoints;
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 1);
|
||||
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
|
||||
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
EpAddr = (UINT8) (EpDesc->EndpointAddress & 0x0F);
|
||||
Direction = (UINT8) ((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);
|
||||
|
||||
Dci = XhcEndpointToDci (EpAddr, Direction);
|
||||
ASSERT (Dci < 32);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 1) Stop any Running Transfer Rings affected by the Alternate Interface setting.
|
||||
//
|
||||
Status = XhcStopEndpoint (Xhc, SlotId, Dci);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting.
|
||||
//
|
||||
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {
|
||||
RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;
|
||||
if (RingSeg != NULL) {
|
||||
UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
|
||||
}
|
||||
FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);
|
||||
Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the Drop Context flag to '1'.
|
||||
//
|
||||
InputContext->InputControlContext.Dword1 |= (BIT0 << Dci);
|
||||
|
||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
||||
}
|
||||
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 3) Clear all the Endpoint Context fields of each endpoint that will be disabled by the Alternate
|
||||
// Interface setting, to '0'.
|
||||
//
|
||||
// The step 3) has been covered by the ZeroMem () to InputContext at the start of the function.
|
||||
//
|
||||
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 4) For each endpoint enabled by the Configure Endpoint Command:
|
||||
// a. Allocate a Transfer Ring.
|
||||
// b. Initialize the Transfer Ring Segment(s) by clearing all fields of all TRBs to '0'.
|
||||
// c. Initialize the Endpoint Context data structure.
|
||||
//
|
||||
Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDescSet);
|
||||
if (Dci > MaxDci) {
|
||||
MaxDci = Dci;
|
||||
}
|
||||
|
||||
InputContext->InputControlContext.Dword2 |= BIT0;
|
||||
InputContext->Slot.ContextEntries = MaxDci;
|
||||
//
|
||||
// XHCI 4.3.6 - Setting Alternate Interfaces
|
||||
// 5) Issue and successfully complete a Configure Endpoint Command.
|
||||
//
|
||||
ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
|
||||
PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));
|
||||
CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);
|
||||
CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);
|
||||
CmdTrbCfgEP.CycleBit = 1;
|
||||
CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
|
||||
CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
|
||||
DEBUG ((EFI_D_INFO, "SetInterface64: Configure Endpoint\n"));
|
||||
Status = XhcCmdTransfer (
|
||||
Xhc,
|
||||
(TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,
|
||||
XHC_GENERIC_TIMEOUT,
|
||||
(TRB_TEMPLATE **) (UINTN) &EvtTrb
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "SetInterface64: Config Endpoint Failed, Status = %r\n", Status));
|
||||
} else {
|
||||
//
|
||||
// Update the active AlternateSetting.
|
||||
//
|
||||
Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This file contains the definition for XHCI host controller schedule routines.
|
||||
|
||||
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2014, 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
|
||||
@ -1041,6 +1041,49 @@ XhcSetConfigCmd64 (
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc
|
||||
);
|
||||
|
||||
/**
|
||||
Set interface through XHCI's Configure_Endpoint cmd.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param ConfigDesc The pointer to the usb device configuration descriptor.
|
||||
@param Request USB device request to send.
|
||||
|
||||
@retval EFI_SUCCESS Successfully set interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
XhcSetInterface (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc,
|
||||
IN EFI_USB_DEVICE_REQUEST *Request
|
||||
);
|
||||
|
||||
/**
|
||||
Set interface through XHCI's Configure_Endpoint cmd.
|
||||
|
||||
@param Xhc The XHCI Instance.
|
||||
@param SlotId The slot id to be configured.
|
||||
@param DeviceSpeed The device's speed.
|
||||
@param ConfigDesc The pointer to the usb device configuration descriptor.
|
||||
@param Request USB device request to send.
|
||||
|
||||
@retval EFI_SUCCESS Successfully set interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
XhcSetInterface64 (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN UINT8 SlotId,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc,
|
||||
IN EFI_USB_DEVICE_REQUEST *Request
|
||||
);
|
||||
|
||||
/**
|
||||
Find out the actual device address according to the requested device address from UsbBus.
|
||||
|
Loading…
x
Reference in New Issue
Block a user