ehci.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,436 行 · 第 1/5 页
C
2,436 行
Status = EFI_DEVICE_ERROR;
goto exit;
}
}
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg |= PORTSC_PR;
//
// Set one to PortReset bit must also set zero to PortEnable bit
//
PortStatusControlReg &= ~PORTSC_PED;
break;
case EfiUsbPortPower:
//
// No support, no operation
//
goto exit;
case EfiUsbPortOwner:
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg |= PORTSC_PO;
break;
default:
Status = EFI_INVALID_PARAMETER;
goto exit;
}
Status = WriteEhcOperationalReg (
HcDev,
PortStatusControlAddr,
PortStatusControlReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
exit:
return Status;
}
EFI_STATUS
EFIAPI
EhciClearRootHubPortFeature (
IN EFI_USB2_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
)
/*++
Routine Description:
Clears a feature for the specified root hub port.
Arguments:
This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
PortNumber - Specifies the root hub port whose feature
is requested to be cleared.
PortFeature - Indicates the feature selector associated with the
feature clear request.
Returns:
EFI_SUCCESS
The feature specified by PortFeature was cleared for the
USB root hub port specified by PortNumber.
EFI_INVALID_PARAMETER
PortNumber is invalid or PortFeature is invalid.
EFI_DEVICE_ERROR
Can't read register
--*/
{
EFI_STATUS Status;
USB2_HC_DEV *HcDev;
UINT32 PortStatusControlAddr;
UINT32 PortStatusControlReg;
UINT8 MaxSpeed;
UINT8 TotalPortNumber;
UINT8 Is64BitCapable;
EhciGetCapability (
This,
&MaxSpeed,
&TotalPortNumber,
&Is64BitCapable
);
if (PortNumber >= TotalPortNumber) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
HcDev = USB2_HC_DEV_FROM_THIS (This);
PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
Status = ReadEhcOperationalReg (
HcDev,
PortStatusControlAddr,
&PortStatusControlReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
switch (PortFeature) {
case EfiUsbPortEnable:
//
// Clear PORT_ENABLE feature means disable port.
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg &= ~PORTSC_PED;
break;
case EfiUsbPortSuspend:
//
// A write of zero to this bit is ignored by the host controller.
// The host controller will unconditionally set this bit to a zero when:
// 1. software sets the Forct Port Resume bit to a zero from a one.
// 2. software sets the Port Reset bit to a one frome a zero.
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg &= ~PORTSC_FPR;
break;
case EfiUsbPortReset:
//
// Clear PORT_RESET means clear the reset signal.
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg &= ~PORTSC_PR;
break;
case EfiUsbPortPower:
//
// No support, no operation
//
goto exit;
case EfiUsbPortOwner:
//
// Clear port owner means this port owned by EHC
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg &= ~PORTSC_PO;
break;
case EfiUsbPortConnectChange:
//
// Clear connect status change
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg |= PORTSC_CSC;
break;
case EfiUsbPortEnableChange:
//
// Clear enable status change
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg |= PORTSC_PEDC;
break;
case EfiUsbPortSuspendChange:
//
// No related bit, no operation
//
goto exit;
case EfiUsbPortOverCurrentChange:
//
// Clear PortOverCurrent change
//
PortStatusControlReg &= 0xffffffd5;
PortStatusControlReg |= PORTSC_OCC;
break;
case EfiUsbPortResetChange:
//
// No related bit, no operation
//
goto exit;
default:
Status = EFI_INVALID_PARAMETER;
goto exit;
}
Status = WriteEhcOperationalReg (
HcDev,
PortStatusControlAddr,
PortStatusControlReg
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
exit:
return Status;
}
EFI_STATUS
EFIAPI
EhciControlTransfer (
IN EFI_USB2_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 DeviceSpeed,
IN UINTN MaximumPacketLength,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION TransferDirection,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN TimeOut,
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
OUT UINT32 *TransferResult
)
/*++
Routine Description:
Submits control transfer to a target USB device.
Arguments:
This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
DeviceAddress - Represents the address of the target device on the USB,
which is assigned during USB enumeration.
DeviceSpeed - Indicates target device speed.
MaximumPacketLength - Indicates the maximum packet size that the
default control transfer endpoint is capable of
sending or receiving.
Request - A pointer to the USB device request that will be sent
to the USB device.
TransferDirection - Specifies the data direction for the transfer.
There are three values available, DataIn, DataOut
and NoData.
Data - A pointer to the buffer of data that will be transmitted
to USB device or received from USB device.
DataLength - Indicates the size, in bytes, of the data buffer
specified by Data.
TimeOut - Indicates the maximum time, in microseconds,
which the transfer is allowed to complete.
Translator - A pointr to the transaction translator data.
TransferResult - A pointer to the detailed result information generated
by this control transfer.
Returns:
EFI_SUCCESS
The control transfer was completed successfully.
EFI_OUT_OF_RESOURCES
The control transfer could not be completed due to a lack of resources.
EFI_INVALID_PARAMETER
Some parameters are invalid.
EFI_TIMEOUT
The control transfer failed due to timeout.
EFI_DEVICE_ERROR
The control transfer failed due to host controller or device error.
Caller should check TranferResult for detailed error information.
--*/
{
EFI_STATUS Status;
USB2_HC_DEV *HcDev;
UINT8 PktId;
EHCI_QH_ENTITY *QhPtr;
EHCI_QTD_ENTITY *ControlQtdsPtr;
UINT8 *DataCursor;
VOID *DataMap;
UINT8 *RequestCursor;
VOID *RequestMap;
QhPtr = NULL;
ControlQtdsPtr = NULL;
DataCursor = NULL;
DataMap = NULL;
RequestCursor = NULL;
RequestMap = NULL;
HcDev = USB2_HC_DEV_FROM_THIS (This);
//
// Parameters Checking
//
if (TransferDirection != EfiUsbDataIn &&
TransferDirection != EfiUsbDataOut &&
TransferDirection != EfiUsbNoData
) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
if (EfiUsbNoData == TransferDirection) {
if (NULL != Data || 0 != *DataLength) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
} else {
if (NULL == Data || 0 == *DataLength) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
}
if (Request == NULL || TransferResult == NULL) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
if (EFI_USB_SPEED_LOW == DeviceSpeed) {
if (MaximumPacketLength != 8) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
} else if (MaximumPacketLength != 8 &&
MaximumPacketLength != 16 &&
MaximumPacketLength != 32 &&
MaximumPacketLength != 64
) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
//
// If errors exist that cause host controller halt,
// then return EFI_DEVICE_ERROR.
//
if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
ClearEhcAllStatus (HcDev);
*TransferResult = EFI_USB_ERR_SYSTEM;
Status = EFI_DEVICE_ERROR;
goto exit;
}
//
// Map the Request for bus master access.
// BusMasterRead means cpu write
//
Status = MapRequestBuffer (
HcDev,
Request,
&RequestCursor,
&RequestMap
);
if (EFI_ERROR (Status)) {
*TransferResult = EFI_USB_ERR_SYSTEM;
Status = EFI_DEVICE_ERROR;
goto exit;
}
//
// Map the source data buffer for bus master access.
//
Status = MapDataBuffer (
HcDev,
TransferDirection,
Data,
DataLength,
&PktId,
&DataCursor,
&DataMap
);
if (EFI_ERROR (Status)) {
*TransferResult = EFI_USB_ERR_SYSTEM;
Status = EFI_DEVICE_ERROR;
goto unmap_request;
}
//
// Create and init control Qh
//
Status = CreateControlQh (
HcDev,
DeviceAddress,
DeviceSpeed,
MaximumPacketLength,
Translator,
&QhPtr
);
if (EFI_ERROR (Status)) {
*TransferResult = EFI_USB_ERR_SYSTEM;
Status = EFI_OUT_OF_RESOURCES;
goto unmap_data;
}
//
// Create and init control Qtds
//
Status = CreateControlQtds (
HcDev,
PktId,
RequestCursor,
DataCursor,
*DataLength,
Translator,
&ControlQtdsPtr
);
if (EFI_ERROR (Status)) {
*TransferResult = EFI_USB_ERR_SYSTEM;
Status = EFI_OUT_OF_RESOURCES;
goto destory_qh;
}
//
// Link Qtds to Qh
//
LinkQtdToQh (QhPtr, ControlQtdsPtr);
ClearEhcAllStatus (HcDev);
//
// Link Qh and Qtds to Async Schedule List
//
Status = LinkQhToAsyncList (HcDev, QhPtr);
if (EFI_ERROR (Status)) {
*TransferResult = EFI_USB_ERR_SYSTEM;
Status = EFI_DEVICE_ERROR;
goto destory_qtds;
}
//
// Poll Qh-Qtds execution and get result.
// detail status is returned
//
Status = ExecuteTransfer (
HcDev,
TRUE,
QhPtr,
DataLength,
0,
TimeOut,
TransferResult
);
if (EFI_ERROR (Status)) {
goto destory_qtds;
}
//
// If has errors that cause host controller halt,
// then return EFI_DEVICE_ERROR directly.
//
if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
*TransferResult |= EFI_USB_ERR_SYSTEM;
}
ClearEhcAllStatus (HcDev);
destory_qtds:
UnlinkQhFromAsyncList (HcDev, QhPtr);
DestoryQtds (HcDev, ControlQtdsPtr);
destory_qh:
DestoryQh (HcDev, QhPtr);
unmap_data:
HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
unmap_request:
HcDev->PciIo->Unmap (HcDev->PciIo, RequestMap);
exit:
HcDev->PciIo->Flush (HcDev->PciIo);
return Status;
}
EFI_STATUS
EFIAPI
EhciBulkTransfer (
IN EFI_USB2_HC_PROTOCOL *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 DeviceSpeed,
IN UINTN MaximumPacketLength,
IN UINT8 DataBuffersNumber,
IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?