ehcisched.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,975 行 · 第 1/5 页
C
2,975 行
}
BOOLEAN
IsQtdStatusBufferError (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Whether Qtd status is buffer error or not
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
TRUE Buffer error
FALSE No buffer error
--*/
{
UINT8 QtdStatus;
BOOLEAN Value;
QtdStatus = (UINT8) (HwQtdPtr->Status);
Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BUFFER_ERR);
return Value;
}
BOOLEAN
IsQtdStatusBabbleError (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Whether Qtd status is babble error or not
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
TRUE Babble error
FALSE No babble error
--*/
{
UINT8 QtdStatus;
BOOLEAN Value;
QtdStatus = (UINT8) (HwQtdPtr->Status);
Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BABBLE_ERR);
return Value;
}
BOOLEAN
IsQtdStatusTransactionError (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Whether Qtd status is transaction error or not
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
TRUE Transaction error
FALSE No transaction error
--*/
{
UINT8 QtdStatus;
BOOLEAN Value;
QtdStatus = (UINT8) (HwQtdPtr->Status);
Value = (BOOLEAN) (QtdStatus & QTD_STATUS_TRANSACTION_ERR);
return Value;
}
BOOLEAN
IsDataInTransfer (
IN UINT8 EndPointAddress
)
/*++
Routine Description:
Whether is a DataIn direction transfer
Arguments:
EndPointAddress - address of the endpoint
Returns:
TRUE DataIn
FALSE DataOut
--*/
{
BOOLEAN Value;
if (EndPointAddress & 0x80) {
Value = TRUE;
} else {
Value = FALSE;
}
return Value;
}
EFI_STATUS
MapDataBuffer (
IN USB2_HC_DEV *HcDev,
IN EFI_USB_DATA_DIRECTION TransferDirection,
IN VOID *Data,
IN OUT UINTN *DataLength,
OUT UINT8 *PktId,
OUT UINT8 **DataCursor,
OUT VOID **DataMap
)
/*++
Routine Description:
Map address of user data buffer
Arguments:
HcDev - USB2_HC_DEV
TransferDirection - direction of transfer
Data - A pointer to user data buffer
DataLength - length of user data
PktId - Packte Identificaion
DataCursor - mapped address to return
DataMap - identificaion of this mapping to return
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TempPhysicalAddr;
Status = EFI_SUCCESS;
switch (TransferDirection) {
case EfiUsbDataIn:
*PktId = INPUT_PACKET_ID;
//
// BusMasterWrite means cpu read
//
Status = HcDev->PciIo->Map (
HcDev->PciIo,
EfiPciIoOperationBusMasterWrite,
Data,
DataLength,
&TempPhysicalAddr,
DataMap
);
if (EFI_ERROR (Status)) {
DEBUG ((gEHCDebugLevel, "EHCI: MapDataBuffer Failed\n"));
Status = EFI_DEVICE_ERROR;
goto exit;
}
*DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
break;
case EfiUsbDataOut:
*PktId = OUTPUT_PACKET_ID;
//
// BusMasterRead means cpu write
//
Status = HcDev->PciIo->Map (
HcDev->PciIo,
EfiPciIoOperationBusMasterRead,
Data,
DataLength,
&TempPhysicalAddr,
DataMap
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
*DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
break;
case EfiUsbNoData:
*PktId = OUTPUT_PACKET_ID;
Data = NULL;
*DataLength = 0;
*DataCursor = NULL;
*DataMap = NULL;
break;
default:
Status = EFI_INVALID_PARAMETER;
}
exit:
return Status;
}
EFI_STATUS
MapRequestBuffer (
IN USB2_HC_DEV *HcDev,
IN OUT VOID *Request,
OUT UINT8 **RequestCursor,
OUT VOID **RequestMap
)
/*++
Routine Description:
Map address of request structure buffer
Arguments:
HcDev - USB2_HC_DEV
Request - A pointer to request structure
RequestCursor - Mapped address of request structure to return
RequestMap - Identificaion of this mapping to return
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
UINTN RequestLen;
EFI_PHYSICAL_ADDRESS TempPhysicalAddr;
RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
Status = HcDev->PciIo->Map (
HcDev->PciIo,
EfiPciIoOperationBusMasterRead,
(UINT8 *) Request,
(UINTN *) &RequestLen,
&TempPhysicalAddr,
RequestMap
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
*RequestCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
exit:
return Status;
}
EFI_STATUS
DeleteAsyncRequestTransfer (
IN USB2_HC_DEV *HcDev,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
OUT UINT8 *DataToggle
)
/*++
Routine Description:
Delete all asynchronous request transfer
Arguments:
HcDev - USB2_HC_DEV
DeviceAddress - address of usb device
EndPointAddress - address of endpoint
DataToggle - stored data toggle
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
EHCI_ASYNC_REQUEST *AsyncRequestPtr;
EHCI_ASYNC_REQUEST *MatchPtr;
EHCI_QH_HW *QhHwPtr;
UINT8 EndPointNum;
if (NULL == HcDev->AsyncRequestList) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
MatchPtr = NULL;
QhHwPtr = NULL;
EndPointNum = EndPointAddress & 0x0f;
AsyncRequestPtr = HcDev->AsyncRequestList;
//
// Find QH of AsyncRequest by DeviceAddress and EndPointNum
//
do {
QhHwPtr = &(AsyncRequestPtr->QhPtr->Qh);
if (QhHwPtr->DeviceAddr == DeviceAddress && QhHwPtr->EndpointNum == EndPointNum) {
MatchPtr = AsyncRequestPtr;
break;
}
AsyncRequestPtr = AsyncRequestPtr->Next;
} while (NULL != AsyncRequestPtr);
if (NULL == MatchPtr) {
Status = EFI_INVALID_PARAMETER;
goto exit;
}
Status = DisablePeriodicSchedule (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) {
DEBUG ((gEHCErrorLevel, "EHCI: WaitForPeriodicScheduleDisable TimeOut\n"));
Status = EFI_TIMEOUT;
goto exit;
}
*DataToggle = (UINT8) MatchPtr->QhPtr->Qh.DataToggle;
UnlinkQhFromPeriodicList (HcDev, MatchPtr->QhPtr, MatchPtr->QhPtr->Interval);
UnlinkFromAsyncReqeust (HcDev, MatchPtr);
if (NULL == HcDev->AsyncRequestList) {
Status = StopPollingTimer (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
} else {
Status = EnablePeriodicSchedule (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) {
DEBUG ((gEHCErrorLevel, "EHCI: WaitForPeriodicScheduleEnable TimeOut\n"));
Status = EFI_TIMEOUT;
goto exit;
}
if (IsEhcHalted (HcDev)) {
Status = StartScheduleExecution (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
}
}
DestoryQtds (HcDev, MatchPtr->QhPtr->FirstQtdPtr);
DestoryQh (HcDev, MatchPtr->QhPtr);
EhciFreePool (HcDev, (UINT8 *) MatchPtr, sizeof (EHCI_ASYNC_REQUEST));
exit:
return Status;
}
VOID
CleanUpAllAsyncRequestTransfer (
IN USB2_HC_DEV *HcDev
)
/*++
Routine Description:
Clean up all asynchronous request transfer
Arguments:
HcDev - USB2_HC_DEV
Returns:
VOID
--*/
{
EHCI_ASYNC_REQUEST *AsyncRequestPtr;
EHCI_ASYNC_REQUEST *FreePtr;
AsyncRequestPtr = NULL;
FreePtr = NULL;
StopPollingTimer (HcDev);
AsyncRequestPtr = HcDev->AsyncRequestList;
while (NULL != AsyncRequestPtr) {
FreePtr = AsyncRequestPtr;
AsyncRequestPtr = AsyncRequestPtr->Next;
UnlinkFromAsyncReqeust (HcDev, FreePtr);
UnlinkQhFromPeriodicList (HcDev, FreePtr->QhPtr, FreePtr->QhPtr->Interval);
DestoryQtds (HcDev, FreePtr->QhPtr->FirstQtdPtr);
DestoryQh (HcDev, FreePtr->QhPtr);
EhciFreePool (HcDev, (UINT8 *) FreePtr, sizeof (EHCI_ASYNC_REQUEST));
}
return ;
}
VOID
ZeroOutQhOverlay (
IN EHCI_QH_ENTITY *QhPtr
)
/*++
Routine Description:
Zero out the fields in Qh structure
Arguments:
QhPtr - A pointer to Qh structure
Returns:
VOID
--*/
{
QhPtr->Qh.CurrentQtdPointer = 0;
QhPtr->Qh.AltNextQtdPointer = 0;
QhPtr->Qh.NakCount = 0;
QhPtr->Qh.AltNextQtdTerminate = 0;
QhPtr->Qh.TotalBytes = 0;
QhPtr->Qh.InterruptOnComplete = 0;
QhPtr->Qh.CurrentPage = 0;
QhPtr->Qh.ErrorCount = 0;
QhPtr->Qh.PidCode = 0;
QhPtr->Qh.Status = 0;
QhPtr->Qh.BufferPointer0 = 0;
QhPtr->Qh.CurrentOffset = 0;
QhPtr->Qh.BufferPointer1 = 0;
QhPtr->Qh.CompleteSplitMask = 0;
QhPtr->Qh.BufferPointer2 = 0;
QhPtr->Qh.SplitBytes = 0;
QhPtr->Qh.FrameTag = 0;
QhPtr->Qh.BufferPointer3 = 0;
QhPtr->Qh.BufferPointer4 = 0;
}
VOID
UpdateAsyncRequestTransfer (
IN EHCI_ASYNC_REQUEST *AsyncRequestPtr,
IN UINT32 TransferResult,
IN UINTN ErrQtdPos
)
/*++
Routine Description:
Update asynchronous request transfer
Arguments:
AsyncRequestPtr - A pointer to async request
TransferResult - transfer result
ErrQtdPos - postion of error Qtd
Returns:
VOID
--*/
{
EHCI_QTD_ENTITY *QtdPtr;
QtdPtr = NULL;
if (EFI_USB_NOERROR == TransferResult) {
//
// Update Qh for next trigger
//
QtdPtr = AsyncRequestPtr->QhPtr->FirstQtdPtr;
//
// Update fields in Qh
//
//
// Get DataToggle from Overlay in Qh
//
// ZeroOut Overlay in Qh except DataToggle, HostController will update this field
//
ZeroOutQhOverlay (AsyncRequestPtr->QhPtr);
AsyncRequestPtr->QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (&(QtdPtr->Qtd)) >> 5);
AsyncRequestPtr->QhPtr->Qh.NextQtdTerminate = FALSE;
//
// Update fields in Qtd
//
while (NULL != QtdPtr) {
QtdPtr->Qtd.TotalBytes = QtdPtr->StaticTotalBytes;
QtdPtr->Qtd.CurrentOffset = QtdPtr->StaticCurrentOffset;
QtdPtr->Qtd.CurrentPage = 0;
QtdPtr->Qtd.ErrorCount = QTD_ERROR_COUNTER;
QtdPtr->Qtd.Status = QTD_STATUS_ACTIVE;
QtdPtr->TotalBytes = QtdPtr->StaticTotalBytes;
QtdPtr = QtdPtr->Next;
}
}
return ;
}
BOOLEAN
CheckQtdsTransferResult (
IN BOOLEAN IsControl,
IN EHCI_QH_ENTITY *QhPtr,
OUT UINT32 *Result,
OUT UINTN *ErrQtdPos,
OUT UINTN *ActualLen
)
/*++
Routine Description:
Check transfer result of Qtds
Arguments:
IsControl - Is control transfer or not
QhPtr - A pointer to Qh
Result - Transfer result
ErrQtdPos - Error TD Position
ActualLen - Actual Transfer Size
Returns:
TRUE Qtds finished
FALSE Not finish
--*/
{
UINTN ActualLenPerQtd;
EHCI_QTD_ENTITY *QtdPtr;
EHCI_QTD_HW *QtdHwPtr;
BOOLEAN Value;
ASSERT (QhPtr);
ASSERT (Result);
ASSERT (ErrQtdPos);
ASSERT (ActualLen);
Value = TRUE;
QtdPtr = QhPtr->FirstQtdPtr;
QtdHwPtr = &(QtdPtr->Qtd);
while (NULL !
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?