mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-27 15:44:04 +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
|
/** @file
|
||||||
The XHCI controller driver.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
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);
|
ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
|
||||||
Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);
|
Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);
|
||||||
CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *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) ||
|
} else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
|
||||||
(DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {
|
(DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {
|
||||||
@ -1009,6 +1013,20 @@ XhcControlTransfer (
|
|||||||
break;
|
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) &&
|
} else if ((Request->Request == USB_REQ_GET_STATUS) &&
|
||||||
(Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {
|
(Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {
|
||||||
ASSERT (Data != NULL);
|
ASSERT (Data != NULL);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Provides some data structure definitions used by the XHCI host controller driver.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
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.
|
// These information is used to support XHCI's Config_Endpoint cmd.
|
||||||
//
|
//
|
||||||
EFI_USB_CONFIG_DESCRIPTOR **ConfDesc;
|
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 {
|
struct _USB_XHCI_INSTANCE {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
XHCI transfer scheduling routines.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -750,7 +750,7 @@ CreateEventRing (
|
|||||||
//
|
//
|
||||||
EventRing->EventRingCCS = 1;
|
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);
|
Buf = UsbHcAllocateMem (Xhc->MemPool, Size);
|
||||||
ASSERT (Buf != NULL);
|
ASSERT (Buf != NULL);
|
||||||
ASSERT (((UINTN) Buf & 0x3F) == 0);
|
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) {
|
if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
|
||||||
UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));
|
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) {
|
if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
|
||||||
UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));
|
UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));
|
||||||
}
|
}
|
||||||
@ -2506,31 +2514,29 @@ XhcDisableSlotCmd64 (
|
|||||||
return Status;
|
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 Xhc The XHCI Instance.
|
||||||
@param SlotId The slot id to be configured.
|
@param SlotId The slot id to be configured.
|
||||||
@param DeviceSpeed The device's speed.
|
@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
|
EFIAPI
|
||||||
XhcSetConfigCmd (
|
XhcInitializeEndpointContext (
|
||||||
IN USB_XHCI_INSTANCE *Xhc,
|
IN USB_XHCI_INSTANCE *Xhc,
|
||||||
IN UINT8 SlotId,
|
IN UINT8 SlotId,
|
||||||
IN UINT8 DeviceSpeed,
|
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;
|
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
||||||
UINT8 Index;
|
|
||||||
UINTN NumEp;
|
UINTN NumEp;
|
||||||
UINTN EpIndex;
|
UINTN EpIndex;
|
||||||
UINT8 EpAddr;
|
UINT8 EpAddr;
|
||||||
@ -2539,30 +2545,10 @@ XhcSetConfigCmd (
|
|||||||
UINT8 MaxDci;
|
UINT8 MaxDci;
|
||||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||||
UINT8 Interval;
|
UINT8 Interval;
|
||||||
|
|
||||||
TRANSFER_RING *EndpointTransferRing;
|
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;
|
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;
|
NumEp = IfDesc->NumEndpoints;
|
||||||
|
|
||||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
|
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
|
||||||
@ -2677,6 +2663,217 @@ XhcSetConfigCmd (
|
|||||||
|
|
||||||
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
|
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);
|
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2701,7 +2898,10 @@ XhcSetConfigCmd (
|
|||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));
|
DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));
|
||||||
|
} else {
|
||||||
|
Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2727,18 +2927,11 @@ XhcSetConfigCmd64 (
|
|||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
USB_INTERFACE_DESCRIPTOR *IfDesc;
|
||||||
USB_ENDPOINT_DESCRIPTOR *EpDesc;
|
|
||||||
UINT8 Index;
|
UINT8 Index;
|
||||||
UINTN NumEp;
|
|
||||||
UINTN EpIndex;
|
|
||||||
UINT8 EpAddr;
|
|
||||||
UINT8 Direction;
|
|
||||||
UINT8 Dci;
|
UINT8 Dci;
|
||||||
UINT8 MaxDci;
|
UINT8 MaxDci;
|
||||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||||
UINT8 Interval;
|
|
||||||
|
|
||||||
TRANSFER_RING *EndpointTransferRing;
|
|
||||||
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
|
||||||
INPUT_CONTEXT_64 *InputContext;
|
INPUT_CONTEXT_64 *InputContext;
|
||||||
DEVICE_CONTEXT_64 *OutputContext;
|
DEVICE_CONTEXT_64 *OutputContext;
|
||||||
@ -2757,126 +2950,15 @@ XhcSetConfigCmd64 (
|
|||||||
|
|
||||||
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
|
||||||
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
|
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);
|
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
NumEp = IfDesc->NumEndpoints;
|
Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);
|
||||||
|
|
||||||
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) {
|
if (Dci > MaxDci) {
|
||||||
MaxDci = Dci;
|
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);
|
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2901,11 +2983,452 @@ XhcSetConfigCmd64 (
|
|||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));
|
DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));
|
||||||
|
} else {
|
||||||
|
Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
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.
|
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.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -1041,6 +1041,49 @@ XhcSetConfigCmd64 (
|
|||||||
IN USB_CONFIG_DESCRIPTOR *ConfigDesc
|
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.
|
Find out the actual device address according to the requested device address from UsbBus.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user