+++ /dev/null
-/** @file\r
-This file contains the implementation of Usb Hc Protocol.\r
-\r
-Copyright (c) 2013-2016 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-\r
-#include "Ohci.h"\r
-\r
-/**\r
- Provides software reset for the USB host controller.\r
-\r
- @param This This EFI_USB_HC_PROTOCOL instance.\r
- @param Attributes A bit mask of the reset operation to perform.\r
-\r
- @retval EFI_SUCCESS The reset operation succeeded.\r
- @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
- @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is\r
- not currently supported by the host controller.\r
- @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OhciReset (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT16 Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- USB_OHCI_HC_DEV *Ohc;\r
- UINT8 Index;\r
- UINT8 NumOfPorts;\r
- UINT32 PowerOnGoodTime;\r
- UINT32 Data32;\r
- BOOLEAN Flag = FALSE;\r
-\r
- if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {\r
- gBS->Stall (50 * 1000);\r
- Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- gBS->Stall (50 * 1000);\r
- //\r
- // Wait for host controller reset.\r
- //\r
- PowerOnGoodTime = 50;\r
- do {\r
- gBS->Stall (1 * 1000);\r
- Data32 = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- if ((Data32 & HC_RESET) == 0) {\r
- Flag = TRUE;\r
- break;\r
- }\r
- }while(PowerOnGoodTime--);\r
- if (!Flag){\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
- OhciFreeIntTransferMemory (Ohc);\r
- Status = OhciInitializeInterruptList (Ohc);\r
- OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);\r
- if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {\r
- Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- gBS->Stall (50 * 1000);\r
- }\r
- //\r
- // Initialize host controller operational registers\r
- //\r
- OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);\r
- OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);\r
- OhciSetPeriodicStart (Ohc, 0x2a2f);\r
- OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x3);\r
- OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);\r
- OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);\r
- OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);\r
- //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);\r
- //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);\r
-\r
- OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);\r
- OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);\r
- OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);\r
- OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);\r
- OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
- for (Index = 0; Index < NumOfPorts; Index++) {\r
- if (!EFI_ERROR (OhciSetRootHubPortFeature (This, Index, EfiUsbPortReset))) {\r
- gBS->Stall (200 * 1000);\r
- OhciClearRootHubPortFeature (This, Index, EfiUsbPortReset);\r
- gBS->Stall (1000);\r
- OhciSetRootHubPortFeature (This, Index, EfiUsbPortEnable);\r
- gBS->Stall (1000);\r
- }\r
- }\r
- OhciSetMemoryPointer (Ohc, HC_HCCA, Ohc->HccaMemoryBlock);\r
- OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
- OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
- OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | BULK_ENABLE, 1); /*ISOCHRONOUS_ENABLE*/\r
- OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);\r
- gBS->Stall (50*1000);\r
- //\r
- // Wait till first SOF occurs, and then clear it\r
- //\r
- while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);\r
- OhciClearInterruptStatus (Ohc, START_OF_FRAME);\r
- gBS->Stall (1000);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Retrieve the current state of the USB host controller.\r
-\r
- @param This This EFI_USB_HC_PROTOCOL instance.\r
- @param State Variable to return the current host controller\r
- state.\r
-\r
- @retval EFI_SUCCESS Host controller state was returned in State.\r
- @retval EFI_INVALID_PARAMETER State is NULL.\r
- @retval EFI_DEVICE_ERROR An error was encountered while attempting to\r
- retrieve the host controller's current state.\r
-\r
-**/\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciGetState (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- OUT EFI_USB_HC_STATE *State\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- UINT32 FuncState;\r
-\r
- if (State == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- FuncState = OhciGetHcControl (Ohc, HC_FUNCTIONAL_STATE);\r
-\r
- switch (FuncState) {\r
- case HC_STATE_RESET:\r
- case HC_STATE_RESUME:\r
- *State = EfiUsbHcStateHalt;\r
- break;\r
-\r
- case HC_STATE_OPERATIONAL:\r
- *State = EfiUsbHcStateOperational;\r
- break;\r
-\r
- case HC_STATE_SUSPEND:\r
- *State = EfiUsbHcStateSuspend;\r
- break;\r
-\r
- default:\r
- ASSERT (FALSE);\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Sets the USB host controller to a specific state.\r
-\r
- @param This This EFI_USB_HC_PROTOCOL instance.\r
- @param State The state of the host controller that will be set.\r
-\r
- @retval EFI_SUCCESS The USB host controller was successfully placed\r
- in the state specified by State.\r
- @retval EFI_INVALID_PARAMETER State is invalid.\r
- @retval EFI_DEVICE_ERROR Failed to set the state due to device error.\r
-\r
-**/\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciSetState(\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN EFI_USB_HC_STATE State\r
- )\r
-{\r
- EFI_STATUS Status;\r
- USB_OHCI_HC_DEV *Ohc;\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);\r
-\r
- switch (State) {\r
- case EfiUsbHcStateHalt:\r
- Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);\r
- break;\r
-\r
- case EfiUsbHcStateOperational:\r
- Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);\r
- break;\r
-\r
- case EfiUsbHcStateSuspend:\r
- Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_SUSPEND);\r
- break;\r
-\r
- default:\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
-\r
- gBS->Stall (1000);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- Submits control transfer to a target USB device.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
- @param MaxPaketLength Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
- @param Request A pointer to the USB device request that will be sent\r
- to the USB device.\r
- @param TransferDirection Specifies the data direction for the transfer.\r
- There are three values available, DataIn, DataOut\r
- and NoData.\r
- @param Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- @param DataLength Indicates the size, in bytes, of the data buffer\r
- specified by Data.\r
- @param TimeOut Indicates the maximum time, in microseconds,\r
- which the transfer is allowed to complete.\r
- @param TransferResult A pointer to the detailed result information generated\r
- by this control transfer.\r
-\r
- @retval EFI_SUCCESS The control transfer was completed successfully.\r
- @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources.\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
- @retval EFI_TIMEOUT The control transfer failed due to timeout.\r
- @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error.\r
- Caller should check TranferResult for detailed error information.\r
-\r
---*/\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciControlTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaxPacketLength,\r
- IN EFI_USB_DEVICE_REQUEST *Request,\r
- IN EFI_USB_DATA_DIRECTION TransferDirection,\r
- IN OUT VOID *Data OPTIONAL,\r
- IN OUT UINTN *DataLength OPTIONAL,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- ED_DESCRIPTOR *HeadEd;\r
- ED_DESCRIPTOR *Ed;\r
- TD_DESCRIPTOR *HeadTd;\r
- TD_DESCRIPTOR *SetupTd;\r
- TD_DESCRIPTOR *DataTd;\r
- TD_DESCRIPTOR *StatusTd;\r
- TD_DESCRIPTOR *EmptyTd;\r
- EFI_STATUS Status;\r
- UINT32 DataPidDir;\r
- UINT32 StatusPidDir;\r
- UINTN TimeCount;\r
- OHCI_ED_RESULT EdResult;\r
-\r
- EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
-\r
- UINTN ActualSendLength;\r
- UINTN LeftLength;\r
- UINT8 DataToggle;\r
-\r
- VOID *ReqMapping = NULL;\r
- UINTN ReqMapLength = 0;\r
- EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;\r
-\r
- VOID *DataMapping = NULL;\r
- UINTN DataMapLength = 0;\r
- EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;\r
-\r
- HeadTd = NULL;\r
- DataTd = NULL;\r
-\r
- if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&\r
- TransferDirection != EfiUsbNoData) ||\r
- Request == NULL || DataLength == NULL || TransferResult == NULL ||\r
- (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||\r
- (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||\r
- (IsSlowDevice && MaxPacketLength != 8) ||\r
- (MaxPacketLength != 8 && MaxPacketLength != 16 &&\r
- MaxPacketLength != 32 && MaxPacketLength != 64)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (*DataLength > MAX_BYTES_PER_TD) {\r
- DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\r\n"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);\r
-\r
- if (TransferDirection == EfiUsbDataIn) {\r
- DataPidDir = TD_IN_PID;\r
- StatusPidDir = TD_OUT_PID;\r
- } else {\r
- DataPidDir = TD_OUT_PID;\r
- StatusPidDir = TD_IN_PID;\r
- }\r
-\r
- Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_ENABLE\r\n"));\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
- Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 0);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_LIST_FILLED\r\n"));\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
- gBS->Stall(20 * 1000);\r
-\r
- OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
- Ed = OhciCreateED (Ohc);\r
- if (Ed == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));\r
- goto CTRL_EXIT;\r
- }\r
- OhciSetEDField (Ed, ED_SKIP, 1);\r
- OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
- OhciSetEDField (Ed, ED_ENDPT_NUM, 0);\r
- OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
- OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);\r
- OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);\r
- OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
- OhciSetEDField (Ed, ED_PDATA, 0);\r
- OhciSetEDField (Ed, ED_ZERO, 0);\r
- OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);\r
- OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);\r
- OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);\r
- HeadEd = OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);\r
- //\r
- // Setup Stage\r
- //\r
- if(Request != NULL) {\r
- ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);\r
- MapOp = EfiPciIoOperationBusMasterRead;\r
- Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Request, &ReqMapLength, &ReqMapPhyAddr, &ReqMapping);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to Map Request Buffer\r\n"));\r
- goto FREE_ED_BUFF;\r
- }\r
- }\r
- SetupTd = OhciCreateTD (Ohc);\r
- if (SetupTd == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\r\n"));\r
- goto UNMAP_SETUP_BUFF;\r
- }\r
- HeadTd = SetupTd;\r
- OhciSetTDField (SetupTd, TD_PDATA, 0);\r
- OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);\r
- OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);\r
- OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);\r
- OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);\r
- OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
- OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINT32)ReqMapPhyAddr);\r
- OhciSetTDField (SetupTd, TD_NEXT_PTR, 0);\r
- OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINT32)(ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1));\r
- SetupTd->ActualSendLength = sizeof (EFI_USB_DEVICE_REQUEST);\r
- SetupTd->DataBuffer = (UINT32)ReqMapPhyAddr;\r
- SetupTd->NextTDPointer = 0;\r
-\r
- if (TransferDirection == EfiUsbDataIn) {\r
- MapOp = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- MapOp = EfiPciIoOperationBusMasterRead;\r
- }\r
- DataMapLength = *DataLength;\r
- if ((Data != NULL) && (DataMapLength != 0)) {\r
- Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, Data, &DataMapLength, &DataMapPhyAddr, &DataMapping);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail To Map Data Buffer\r\n"));\r
- goto FREE_TD_BUFF;\r
- }\r
- }\r
- //\r
- //Data Stage\r
- //\r
- LeftLength = DataMapLength;\r
- ActualSendLength = DataMapLength;\r
- DataToggle = 1;\r
- while (LeftLength > 0) {\r
- ActualSendLength = LeftLength;\r
- if (LeftLength > MaxPacketLength) {\r
- ActualSendLength = MaxPacketLength;\r
- }\r
- DataTd = OhciCreateTD (Ohc);\r
- if (DataTd == NULL) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Data Stage TD\r\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto UNMAP_DATA_BUFF;\r
- }\r
- OhciSetTDField (DataTd, TD_PDATA, 0);\r
- OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
- OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
- OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
- OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);\r
- OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
- OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);\r
- OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(DataMapPhyAddr + ActualSendLength - 1));\r
- OhciSetTDField (DataTd, TD_NEXT_PTR, 0);\r
- DataTd->ActualSendLength = (UINT32)ActualSendLength;\r
- DataTd->DataBuffer = (UINT32)DataMapPhyAddr;\r
- DataTd->NextTDPointer = 0;\r
- OhciLinkTD (HeadTd, DataTd);\r
- DataToggle ^= 1;\r
- DataMapPhyAddr += ActualSendLength;\r
- LeftLength -= ActualSendLength;\r
- }\r
- //\r
- // Status Stage\r
- //\r
- StatusTd = OhciCreateTD (Ohc);\r
- if (StatusTd == NULL) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Status Stage TD\r\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto UNMAP_DATA_BUFF;\r
- }\r
- OhciSetTDField (StatusTd, TD_PDATA, 0);\r
- OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);\r
- OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);\r
- OhciSetTDField (StatusTd, TD_DELAY_INT, 7);\r
- OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);\r
- OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
- OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, 0);\r
- OhciSetTDField (StatusTd, TD_NEXT_PTR, 0);\r
- OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, 0);\r
- StatusTd->ActualSendLength = 0;\r
- StatusTd->DataBuffer = 0;\r
- StatusTd->NextTDPointer = 0;\r
- OhciLinkTD (HeadTd, StatusTd);\r
- //\r
- // Empty Stage\r
- //\r
- EmptyTd = OhciCreateTD (Ohc);\r
- if (EmptyTd == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto UNMAP_DATA_BUFF;\r
- }\r
- OhciSetTDField (EmptyTd, TD_PDATA, 0);\r
- OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);\r
- OhciSetTDField (EmptyTd, TD_DIR_PID, 0);\r
- OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);\r
- //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);\r
- EmptyTd->Word0.DataToggle = 0;\r
- OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (EmptyTd, TD_COND_CODE, 0);\r
- OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);\r
- OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);\r
- OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);\r
- EmptyTd->ActualSendLength = 0;\r
- EmptyTd->DataBuffer = 0;\r
- EmptyTd->NextTDPointer = 0;\r
- OhciLinkTD (HeadTd, EmptyTd);\r
- Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;\r
- OhciAttachTDListToED (Ed, HeadTd);\r
- //\r
- // For debugging, dump ED & TD buffer befor transferring\r
- //\r
- //\r
- //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);\r
- //\r
- OhciSetEDField (Ed, ED_SKIP, 0);\r
- Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_ENABLE\r\n"));\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- Status = EFI_DEVICE_ERROR;\r
- goto UNMAP_DATA_BUFF;\r
- }\r
- Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_LIST_FILLED\r\n"));\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- Status = EFI_DEVICE_ERROR;\r
- goto UNMAP_DATA_BUFF;\r
- }\r
- gBS->Stall(20 * 1000);\r
-\r
-\r
- TimeCount = 0;\r
- Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);\r
-\r
- while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {\r
- gBS->Stall (1000);\r
- TimeCount++;\r
- Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);\r
- }\r
- //\r
- // For debugging, dump ED & TD buffer after transferring\r
- //\r
- //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);\r
- //\r
- *TransferResult = ConvertErrorCode (EdResult.ErrorCode);\r
-\r
- if (EdResult.ErrorCode != TD_NO_ERROR) {\r
- if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {\r
- DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));\r
- } else {\r
- DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));\r
- }\r
- *DataLength = 0;\r
- } else {\r
- DEBUG ((EFI_D_INFO, "Control transfer successed\r\n"));\r
- }\r
-\r
-UNMAP_DATA_BUFF:\r
- OhciSetEDField (Ed, ED_SKIP, 1);\r
- if (HeadEd == Ed) {\r
- OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
- } else {\r
- HeadEd->NextED = Ed->NextED;\r
- }\r
- if(DataMapping != NULL) {\r
- Ohc->PciIo->Unmap(Ohc->PciIo, DataMapping);\r
- }\r
-\r
-FREE_TD_BUFF:\r
- while (HeadTd) {\r
- DataTd = HeadTd;\r
- HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
- UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
- }\r
-\r
-UNMAP_SETUP_BUFF:\r
- if(ReqMapping != NULL) {\r
- Ohc->PciIo->Unmap(Ohc->PciIo, ReqMapping);\r
- }\r
-\r
-FREE_ED_BUFF:\r
- UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
-\r
-CTRL_EXIT:\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- Submits bulk transfer to a bulk endpoint of a USB device.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param EndPointAddress The combination of an endpoint number and an\r
- endpoint direction of the target USB device.\r
- Each endpoint address supports data transfer in\r
- one direction except the control endpoint\r
- (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents a bulk endpoint.\r
- @param MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
- @param Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- @param DataLength When input, indicates the size, in bytes, of the data buffer\r
- specified by Data. When output, indicates the actually\r
- transferred data size.\r
- @param DataToggle A pointer to the data toggle value. On input, it indicates\r
- the initial data toggle value the bulk transfer should adopt;\r
- on output, it is updated to indicate the data toggle value\r
- of the subsequent bulk transfer.\r
- @param TimeOut Indicates the maximum time, in microseconds, which the\r
- transfer is allowed to complete.\r
- TransferResult A pointer to the detailed result information of the\r
- bulk transfer.\r
-\r
- @retval EFI_SUCCESS The bulk transfer was completed successfully.\r
- @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to lack of resource.\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
- @retval EFI_TIMEOUT The bulk transfer failed due to timeout.\r
- @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.\r
- Caller should check TranferResult for detailed error information.\r
-\r
-**/\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciBulkTransfer(\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 MaxPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- ED_DESCRIPTOR *HeadEd;\r
- ED_DESCRIPTOR *Ed;\r
- UINT32 DataPidDir;\r
- TD_DESCRIPTOR *HeadTd;\r
- TD_DESCRIPTOR *DataTd;\r
- TD_DESCRIPTOR *EmptyTd;\r
- EFI_STATUS Status;\r
- UINT8 EndPointNum;\r
- UINTN TimeCount;\r
- OHCI_ED_RESULT EdResult;\r
-\r
- EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
- VOID *Mapping;\r
- UINTN MapLength;\r
- EFI_PHYSICAL_ADDRESS MapPyhAddr;\r
- UINTN LeftLength;\r
- UINTN ActualSendLength;\r
- BOOLEAN FirstTD;\r
-\r
- Mapping = NULL;\r
- MapLength = 0;\r
- MapPyhAddr = 0;\r
- LeftLength = 0;\r
- Status = EFI_SUCCESS;\r
-\r
- if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||\r
- *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||\r
- (MaxPacketLength != 8 && MaxPacketLength != 16 &&\r
- MaxPacketLength != 32 && MaxPacketLength != 64)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- if ((EndPointAddress & 0x80) != 0) {\r
- DataPidDir = TD_IN_PID;\r
- MapOp = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- DataPidDir = TD_OUT_PID;\r
- MapOp = EfiPciIoOperationBusMasterRead;\r
- }\r
-\r
- EndPointNum = (EndPointAddress & 0xF);\r
- EdResult.NextToggle = *DataToggle;\r
-\r
- Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
- Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
- gBS->Stall(20 * 1000);\r
-\r
- OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
-\r
- Ed = OhciCreateED (Ohc);\r
- if (Ed == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- OhciSetEDField (Ed, ED_SKIP, 1);\r
- OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
- OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);\r
- OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
- OhciSetEDField (Ed, ED_SPEED, HI_SPEED);\r
- OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);\r
- OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
- OhciSetEDField (Ed, ED_PDATA, 0);\r
- OhciSetEDField (Ed, ED_ZERO, 0);\r
- OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);\r
- OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);\r
- OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);\r
- HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);\r
-\r
- if(Data != NULL) {\r
- MapLength = *DataLength;\r
- Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));\r
- goto FREE_ED_BUFF;\r
- }\r
- }\r
- //\r
- //Data Stage\r
- //\r
- LeftLength = MapLength;\r
- ActualSendLength = MapLength;\r
- HeadTd = NULL;\r
- FirstTD = TRUE;\r
- while (LeftLength > 0) {\r
- ActualSendLength = LeftLength;\r
- if (LeftLength > MaxPacketLength) {\r
- ActualSendLength = MaxPacketLength;\r
- }\r
- DataTd = OhciCreateTD (Ohc);\r
- if (DataTd == NULL) {\r
- DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
- OhciSetTDField (DataTd, TD_PDATA, 0);\r
- OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
- OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
- OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
- OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);\r
- OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
- OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);\r
- OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));\r
- OhciSetTDField (DataTd, TD_NEXT_PTR, 0);\r
- DataTd->ActualSendLength = (UINT32)ActualSendLength;\r
- DataTd->DataBuffer = (UINT32)MapPyhAddr;\r
- DataTd->NextTDPointer = 0;\r
- if (FirstTD) {\r
- HeadTd = DataTd;\r
- FirstTD = FALSE;\r
- } else {\r
- OhciLinkTD (HeadTd, DataTd);\r
- }\r
- *DataToggle ^= 1;\r
- MapPyhAddr += ActualSendLength;\r
- LeftLength -= ActualSendLength;\r
- }\r
- //\r
- // Empty Stage\r
- //\r
- EmptyTd = OhciCreateTD (Ohc);\r
- if (EmptyTd == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
- OhciSetTDField (EmptyTd, TD_PDATA, 0);\r
- OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);\r
- OhciSetTDField (EmptyTd, TD_DIR_PID, 0);\r
- OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);\r
- //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);\r
- EmptyTd->Word0.DataToggle = 0;\r
- OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (EmptyTd, TD_COND_CODE, 0);\r
- OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);\r
- OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);\r
- OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);\r
- EmptyTd->ActualSendLength = 0;\r
- EmptyTd->DataBuffer = 0;\r
- EmptyTd->NextTDPointer = 0;\r
- OhciLinkTD (HeadTd, EmptyTd);\r
- Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;\r
- OhciAttachTDListToED (Ed, HeadTd);\r
-\r
- OhciSetEDField (Ed, ED_SKIP, 0);\r
- Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);\r
- if (EFI_ERROR(Status)) {\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- Status = EFI_DEVICE_ERROR;\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
- Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);\r
- if (EFI_ERROR(Status)) {\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- Status = EFI_DEVICE_ERROR;\r
- DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
- gBS->Stall(20 * 1000);\r
-\r
- TimeCount = 0;\r
- Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);\r
- while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {\r
- gBS->Stall (1000);\r
- TimeCount++;\r
- Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);\r
- }\r
-\r
- *TransferResult = ConvertErrorCode (EdResult.ErrorCode);\r
-\r
- if (EdResult.ErrorCode != TD_NO_ERROR) {\r
- if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {\r
- DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));\r
- } else {\r
- DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));\r
- *DataToggle = EdResult.NextToggle;\r
- }\r
- *DataLength = 0;\r
- } else {\r
- DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));\r
- }\r
- //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);\r
-\r
-FREE_OHCI_TDBUFF:\r
- OhciSetEDField (Ed, ED_SKIP, 1);\r
- if (HeadEd == Ed) {\r
- OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
- }else {\r
- HeadEd->NextED = Ed->NextED;\r
- }\r
- while (HeadTd) {\r
- DataTd = HeadTd;\r
- HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
- UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
- }\r
-\r
- if(Mapping != NULL) {\r
- Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);\r
- }\r
-\r
-FREE_ED_BUFF:\r
- UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
-\r
- return Status;\r
-}\r
-/**\r
-\r
- Submits an interrupt transfer to an interrupt endpoint of a USB device.\r
-\r
- @param Ohc Device private data\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint address\r
- supports data transfer in one direction except the\r
- control endpoint (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents an interrupt endpoint.\r
- @param IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
- @param MaxPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
- @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
- the host and the target interrupt endpoint.\r
- If FALSE, the specified asynchronous interrupt pipe\r
- is canceled.\r
- @param DataToggle A pointer to the data toggle value. On input, it is valid\r
- when IsNewTransfer is TRUE, and it indicates the initial\r
- data toggle value the asynchronous interrupt transfer\r
- should adopt.\r
- On output, it is valid when IsNewTransfer is FALSE,\r
- and it is updated to indicate the data toggle value of\r
- the subsequent asynchronous interrupt transfer.\r
- @param PollingInterval Indicates the interval, in milliseconds, that the\r
- asynchronous interrupt transfer is polled.\r
- This parameter is required when IsNewTransfer is TRUE.\r
- @param UCBuffer Uncacheable buffer\r
- @param DataLength Indicates the length of data to be received at the\r
- rate specified by PollingInterval from the target\r
- asynchronous interrupt endpoint. This parameter\r
- is only required when IsNewTransfer is TRUE.\r
- @param CallBackFunction The Callback function.This function is called at the\r
- rate specified by PollingInterval.This parameter is\r
- only required when IsNewTransfer is TRUE.\r
- @param Context The context that is passed to the CallBackFunction.\r
- This is an optional parameter and may be NULL.\r
- @param IsPeriodic Periodic interrupt or not\r
- @param OutputED The correspoding ED carried out\r
- @param OutputTD The correspoding TD carried out\r
-\r
-\r
- @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully\r
- submitted or canceled.\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
-\r
-**/\r
-\r
-EFI_STATUS\r
-OhciInterruptTransfer (\r
- IN USB_OHCI_HC_DEV *Ohc,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaxPacketLength,\r
- IN BOOLEAN IsNewTransfer,\r
- IN OUT UINT8 *DataToggle OPTIONAL,\r
- IN UINTN PollingInterval OPTIONAL,\r
- IN VOID *UCBuffer OPTIONAL,\r
- IN UINTN DataLength OPTIONAL,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,\r
- IN VOID *Context OPTIONAL,\r
- IN BOOLEAN IsPeriodic OPTIONAL,\r
- OUT ED_DESCRIPTOR **OutputED OPTIONAL,\r
- OUT TD_DESCRIPTOR **OutputTD OPTIONAL\r
- )\r
-{\r
- ED_DESCRIPTOR *Ed;\r
- UINT8 EdDir;\r
- ED_DESCRIPTOR *HeadEd;\r
- TD_DESCRIPTOR *HeadTd;\r
- TD_DESCRIPTOR *DataTd;\r
- TD_DESCRIPTOR *EmptTd;\r
- UINTN Depth;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- UINT8 EndPointNum;\r
- UINT32 DataPidDir;\r
- INTERRUPT_CONTEXT_ENTRY *Entry;\r
- EFI_TPL OldTpl;\r
- BOOLEAN FirstTD;\r
-\r
- VOID *Mapping;\r
- UINTN MapLength;\r
- EFI_PHYSICAL_ADDRESS MapPyhAddr;\r
- UINTN LeftLength;\r
- UINTN ActualSendLength;\r
-\r
-\r
- if (DataLength > MAX_BYTES_PER_TD) {\r
- DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((EndPointAddress & 0x80) != 0) {\r
- EdDir = ED_IN_DIR;\r
- DataPidDir = TD_IN_PID;\r
- } else {\r
- EdDir = ED_OUT_DIR;\r
- DataPidDir = TD_OUT_PID;\r
- }\r
-\r
- EndPointNum = (EndPointAddress & 0xF);\r
-\r
- if (!IsNewTransfer) {\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
- OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);\r
- OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);\r
- Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);\r
- OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
- }\r
- MapLength = DataLength;\r
- Status = Ohc->PciIo->Map(\r
- Ohc->PciIo,\r
- EfiPciIoOperationBusMasterWrite,\r
- UCBuffer,\r
- &MapLength,\r
- &MapPyhAddr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));\r
- goto EXIT;\r
- }\r
- Depth = 5;\r
- Index = 1;\r
- while (PollingInterval >= Index * 2 && Depth > 0) {\r
- Index *= 2;\r
- Depth--;\r
- }\r
- //\r
- //ED Stage\r
- //\r
- HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);\r
- if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {\r
- OhciSetEDField (Ed, ED_SKIP, 1);\r
- } else {\r
- Ed = OhciCreateED (Ohc);\r
- if (Ed == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));\r
- goto UNMAP_OHCI_XBUFF;\r
- }\r
- OhciSetEDField (Ed, ED_SKIP, 1);\r
- OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
- OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);\r
- OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
- OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);\r
- OhciSetEDField (Ed, ED_FORMAT, 0);\r
- OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
- OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);\r
- OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);\r
- OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);\r
- OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);\r
- OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);\r
- }\r
- //\r
- //Data Stage\r
- //\r
- LeftLength = MapLength;\r
- ActualSendLength = MapLength;\r
- HeadTd = NULL;\r
- FirstTD = TRUE;\r
- while (LeftLength > 0) {\r
- ActualSendLength = LeftLength;\r
- if (LeftLength > MaxPacketLength) {\r
- ActualSendLength = MaxPacketLength;\r
- }\r
- DataTd = OhciCreateTD (Ohc);\r
- if (DataTd == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
- OhciSetTDField (DataTd, TD_PDATA, 0);\r
- OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
- OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
- OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
- OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);\r
- OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
- OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);\r
- OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));\r
- OhciSetTDField (DataTd, TD_NEXT_PTR, 0);\r
- DataTd->ActualSendLength = (UINT32)ActualSendLength;\r
- DataTd->DataBuffer = (UINT32)MapPyhAddr;\r
- DataTd->NextTDPointer = 0;\r
- if (FirstTD) {\r
- HeadTd = DataTd;\r
- FirstTD = FALSE;\r
- } else {\r
- OhciLinkTD (HeadTd, DataTd);\r
- }\r
- *DataToggle ^= 1;\r
- MapPyhAddr += ActualSendLength;\r
- LeftLength -= ActualSendLength;\r
- }\r
-\r
- EmptTd = OhciCreateTD (Ohc);\r
- if (EmptTd == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
- OhciSetTDField (EmptTd, TD_PDATA, 0);\r
- OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);\r
- OhciSetTDField (EmptTd, TD_DIR_PID, 0);\r
- OhciSetTDField (EmptTd, TD_DELAY_INT, 0);\r
- //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);\r
- EmptTd->Word0.DataToggle = 0;\r
- OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);\r
- OhciSetTDField (EmptTd, TD_COND_CODE, 0);\r
- OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);\r
- OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);\r
- OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);\r
- EmptTd->ActualSendLength = 0;\r
- EmptTd->DataBuffer = 0;\r
- EmptTd->NextTDPointer = 0;\r
- OhciLinkTD (HeadTd, EmptTd);\r
- Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;\r
- OhciAttachTDListToED (Ed, HeadTd);\r
-\r
- if (OutputED != NULL) {\r
- *OutputED = Ed;\r
- }\r
- if (OutputTD != NULL) {\r
- *OutputTD = HeadTd;\r
- }\r
-\r
- if (CallBackFunction != NULL) {\r
- Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));\r
- if (Entry == NULL) {\r
- goto FREE_OHCI_TDBUFF;\r
- }\r
-\r
- Entry->DeviceAddress = DeviceAddress;\r
- Entry->EndPointAddress = EndPointAddress;\r
- Entry->Ed = Ed;\r
- Entry->DataTd = HeadTd;\r
- Entry->IsSlowDevice = IsSlowDevice;\r
- Entry->MaxPacketLength = MaxPacketLength;\r
- Entry->PollingInterval = PollingInterval;\r
- Entry->CallBackFunction = CallBackFunction;\r
- Entry->Context = Context;\r
- Entry->IsPeriodic = IsPeriodic;\r
- Entry->UCBuffer = UCBuffer;\r
- Entry->UCBufferMapping = Mapping;\r
- Entry->DataLength = DataLength;\r
- Entry->Toggle = DataToggle;\r
- Entry->NextEntry = NULL;\r
- OhciAddInterruptContextEntry (Ohc, Entry);\r
- }\r
- OhciSetEDField (Ed, ED_SKIP, 0);\r
-\r
- if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {\r
- Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);\r
- gBS->Stall (1000);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-FREE_OHCI_TDBUFF:\r
- while (HeadTd) {\r
- DataTd = HeadTd;\r
- HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
- UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
- }\r
-\r
-//FREE_OHCI_EDBUFF:\r
- if ((HeadEd != Ed) && HeadEd && Ed) {\r
- while(HeadEd->NextED != (UINT32)(UINTN)Ed) {\r
- HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);\r
- }\r
- HeadEd->NextED = Ed->NextED;\r
- UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
- }\r
-\r
-UNMAP_OHCI_XBUFF:\r
- Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);\r
-\r
-EXIT:\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint address\r
- supports data transfer in one direction except the\r
- control endpoint (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents an interrupt endpoint.\r
- @param IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
- @param MaxiumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
- @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
- the host and the target interrupt endpoint.\r
- If FALSE, the specified asynchronous interrupt pipe\r
- is canceled.\r
- @param DataToggle A pointer to the data toggle value. On input, it is valid\r
- when IsNewTransfer is TRUE, and it indicates the initial\r
- data toggle value the asynchronous interrupt transfer\r
- should adopt.\r
- On output, it is valid when IsNewTransfer is FALSE,\r
- and it is updated to indicate the data toggle value of\r
- the subsequent asynchronous interrupt transfer.\r
- @param PollingInterval Indicates the interval, in milliseconds, that the\r
- asynchronous interrupt transfer is polled.\r
- This parameter is required when IsNewTransfer is TRUE.\r
- @param DataLength Indicates the length of data to be received at the\r
- rate specified by PollingInterval from the target\r
- asynchronous interrupt endpoint. This parameter\r
- is only required when IsNewTransfer is TRUE.\r
- @param CallBackFunction The Callback function.This function is called at the\r
- rate specified by PollingInterval.This parameter is\r
- only required when IsNewTransfer is TRUE.\r
- @param Context The context that is passed to the CallBackFunction.\r
- This is an optional parameter and may be NULL.\r
-\r
- @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully\r
- submitted or canceled.\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
-\r
-**/\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciAsyncInterruptTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaxPacketLength,\r
- IN BOOLEAN IsNewTransfer,\r
- IN OUT UINT8 *DataToggle OPTIONAL,\r
- IN UINTN PollingInterval OPTIONAL,\r
- IN UINTN DataLength OPTIONAL,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,\r
- IN VOID *Context OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- USB_OHCI_HC_DEV *Ohc;\r
- VOID *UCBuffer;\r
-\r
- if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||\r
- (IsNewTransfer && (DataLength == 0 ||\r
- (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
- if ( IsNewTransfer ) {\r
- UCBuffer = AllocatePool(DataLength);\r
- if (UCBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- UCBuffer = NULL;\r
- }\r
- Status = OhciInterruptTransfer (\r
- Ohc,\r
- DeviceAddress,\r
- EndPointAddress,\r
- IsSlowDevice,\r
- MaxPacketLength,\r
- IsNewTransfer,\r
- DataToggle,\r
- PollingInterval,\r
- UCBuffer,\r
- DataLength,\r
- CallBackFunction,\r
- Context,\r
- TRUE,\r
- NULL,\r
- NULL\r
- );\r
- if ( IsNewTransfer ) {\r
- if (EFI_ERROR(Status)) {\r
- gBS->FreePool (UCBuffer);\r
- }\r
- }\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
-\r
- Submits synchronous interrupt transfer to an interrupt endpoint\r
- of a USB device.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint\r
- address supports data transfer in one direction\r
- except the control endpoint (whose default\r
- endpoint address is 0). It is the caller's responsibility\r
- to make sure that the EndPointAddress represents\r
- an interrupt endpoint.\r
- @param IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
- @param MaxPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
- @param Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- @param DataLength On input, the size, in bytes, of the data buffer specified\r
- by Data. On output, the number of bytes transferred.\r
- @param DataToggle A pointer to the data toggle value. On input, it indicates\r
- the initial data toggle value the synchronous interrupt\r
- transfer should adopt;\r
- on output, it is updated to indicate the data toggle value\r
- of the subsequent synchronous interrupt transfer.\r
- @param TimeOut Indicates the maximum time, in microseconds, which the\r
- transfer is allowed to complete.\r
- @param TransferResult A pointer to the detailed result information from\r
- the synchronous interrupt transfer.\r
-\r
- @retval EFI_UNSUPPORTED This interface not available.\r
- @retval EFI_INVALID_PARAMETER Parameters not follow spec\r
-\r
-**/\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciSyncInterruptTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaxPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- EFI_STATUS Status;\r
- ED_DESCRIPTOR *Ed;\r
- TD_DESCRIPTOR *HeadTd;\r
- OHCI_ED_RESULT EdResult;\r
- VOID *UCBuffer;\r
-\r
- if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||\r
- (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||\r
- DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
- UCBuffer = AllocatePool (*DataLength);\r
- if (UCBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- Status = OhciInterruptTransfer (\r
- Ohc,\r
- DeviceAddress,\r
- EndPointAddress,\r
- IsSlowDevice,\r
- MaxPacketLength,\r
- TRUE,\r
- DataToggle,\r
- 1,\r
- UCBuffer,\r
- *DataLength,\r
- NULL,\r
- NULL,\r
- FALSE,\r
- &Ed,\r
- &HeadTd\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);\r
- while (Status == EFI_NOT_READY && TimeOut > 0) {\r
- gBS->Stall (1000);\r
- TimeOut--;\r
- Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);\r
- }\r
-\r
- *TransferResult = ConvertErrorCode (EdResult.ErrorCode);\r
- }\r
- CopyMem(Data, UCBuffer, *DataLength);\r
- Status = OhciInterruptTransfer (\r
- Ohc,\r
- DeviceAddress,\r
- EndPointAddress,\r
- IsSlowDevice,\r
- MaxPacketLength,\r
- FALSE,\r
- DataToggle,\r
- 0,\r
- NULL,\r
- 0,\r
- NULL,\r
- NULL,\r
- FALSE,\r
- NULL,\r
- NULL\r
- );\r
-\r
- return Status;\r
-}\r
-/**\r
-\r
- Submits isochronous transfer to a target USB device.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param EndPointAddress End point address\r
- @param MaximumPacketLength Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
- @param Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- @param DataLength Indicates the size, in bytes, of the data buffer\r
- specified by Data.\r
- @param TransferResult A pointer to the detailed result information generated\r
- by this control transfer.\r
-\r
- @retval EFI_UNSUPPORTED This interface not available\r
- @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL\r
-\r
-**/\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciIsochronousTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN DataLength,\r
- OUT UINT32 *TransferResult\r
- )\r
-{\r
- if (Data == NULL || DataLength == 0 || TransferResult == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
-\r
- Submits Async isochronous transfer to a target USB device.\r
-\r
- @param his A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- @param EndPointAddress End point address\r
- @param MaximumPacketLength Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
- @param Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- @param IsochronousCallBack When the transfer complete, the call back function will be called\r
- @param Context Pass to the call back function as parameter\r
-\r
- @retval EFI_UNSUPPORTED This interface not available\r
- @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0\r
-\r
-**/\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciAsyncIsochronousTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN DataLength,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
- IN VOID *Context OPTIONAL\r
- )\r
-{\r
-\r
- if (Data == NULL || DataLength == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
-\r
- Retrieves the number of root hub ports.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param NumOfPorts A pointer to the number of the root hub ports.\r
-\r
- @retval EFI_SUCCESS The port number was retrieved successfully.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OhciGetRootHubNumOfPorts (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- OUT UINT8 *NumOfPorts\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- if (NumOfPorts == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-/**\r
-\r
- Retrieves the current status of a USB root hub port.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL.\r
- @param PortNumber Specifies the root hub port from which the status\r
- is to be retrieved. This value is zero-based. For example,\r
- if a root hub has two ports, then the first port is numbered 0,\r
- and the second port is numbered 1.\r
- @param PortStatus A pointer to the current port status bits and\r
- port status change bits.\r
-\r
- @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber\r
- was returned in PortStatus.\r
- @retval EFI_INVALID_PARAMETER Port number not valid\r
-**/\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-OhciGetRootHubPortStatus (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 PortNumber,\r
- OUT EFI_USB_PORT_STATUS *PortStatus\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- UINT8 NumOfPorts;\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
- if (PortNumber >= NumOfPorts) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- PortStatus->PortStatus = 0;\r
- PortStatus->PortChangeStatus = 0;\r
-\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_POWER;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;\r
- }\r
- if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-/**\r
-\r
- Sets a feature for the specified root hub port.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL.\r
- @param PortNumber Specifies the root hub port whose feature\r
- is requested to be set.\r
- @param PortFeature Indicates the feature selector associated\r
- with the feature set request.\r
-\r
- @retval EFI_SUCCESS The feature specified by PortFeature was set for the\r
- USB root hub port specified by PortNumber.\r
- @retval EFI_DEVICE_ERROR Set feature failed because of hardware issue\r
- @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OhciSetRootHubPortFeature (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 PortNumber,\r
- IN EFI_USB_PORT_FEATURE PortFeature\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- EFI_STATUS Status;\r
- UINT8 NumOfPorts;\r
- UINTN RetryTimes;\r
-\r
- OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
- if (PortNumber >= NumOfPorts) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- Status = EFI_SUCCESS;\r
-\r
-\r
- switch (PortFeature) {\r
- case EfiUsbPortPower:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortReset:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||\r
- OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);\r
- break;\r
-\r
- case EfiUsbPortEnable:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
-\r
- case EfiUsbPortSuspend:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- Clears a feature for the specified root hub port.\r
-\r
- @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- @param PortNumber Specifies the root hub port whose feature\r
- is requested to be cleared.\r
- @param PortFeature Indicates the feature selector associated with the\r
- feature clear request.\r
-\r
- @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the\r
- USB root hub port specified by PortNumber.\r
- @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
- @retval EFI_DEVICE_ERROR Some error happened when clearing feature\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OhciClearRootHubPortFeature (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 PortNumber,\r
- IN EFI_USB_PORT_FEATURE PortFeature\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- EFI_STATUS Status;\r
- UINT8 NumOfPorts;\r
- UINTN RetryTimes;\r
-\r
-\r
- OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
- if (PortNumber >= NumOfPorts) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- switch (PortFeature) {\r
- case EfiUsbPortEnable:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortSuspend:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortReset:\r
- break;\r
-\r
- case EfiUsbPortPower:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortConnectChange:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortResetChange:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
-\r
- case EfiUsbPortEnableChange:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortSuspendChange:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbPortOverCurrentChange:\r
- Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);\r
-\r
- //\r
- // Verify the state\r
- //\r
- RetryTimes = 0;\r
- do {\r
- gBS->Stall (1000);\r
- RetryTimes++;\r
- } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&\r
- RetryTimes < MAX_RETRY_TIMES);\r
-\r
- if (RetryTimes >= MAX_RETRY_TIMES) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {\r
- OHCIDriverBindingSupported,\r
- OHCIDriverBindingStart,\r
- OHCIDriverBindingStop,\r
- 0x10,\r
- NULL,\r
- NULL\r
-};\r
-\r
-\r
-/**\r
- Entry point for EFI drivers.\r
-\r
- @param ImageHandle EFI_HANDLE.\r
- @param SystemTable EFI_SYSTEM_TABLE.\r
-\r
- @retval EFI_SUCCESS Driver is successfully loaded.\r
- @return Others Failed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OHCIDriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- return EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gOhciDriverBinding,\r
- ImageHandle,\r
- &gOhciComponentName,\r
- &gOhciComponentName2\r
- );\r
-}\r
-\r
-\r
-/**\r
- Test to see if this driver supports ControllerHandle. Any\r
- ControllerHandle that has UsbHcProtocol installed will be supported.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to test.\r
- @param RemainingDevicePath Not used.\r
-\r
- @return EFI_SUCCESS This driver supports this device.\r
- @return EFI_UNSUPPORTED This driver does not support this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OHCIDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- USB_CLASSC UsbClassCReg;\r
- //\r
- // Test whether there is PCI IO Protocol attached on the controller handle.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- PCI_CLASSCODE_OFFSET,\r
- sizeof (USB_CLASSC) / sizeof (UINT8),\r
- &UsbClassCReg\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto ON_EXIT;\r
- }\r
- //\r
- // Test whether the controller belongs to OHCI type\r
- //\r
- if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
- (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
- (UsbClassCReg.ProgInterface != PCI_IF_OHCI)\r
- ) {\r
-\r
- Status = EFI_UNSUPPORTED;\r
- }\r
-ON_EXIT:\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-\r
-}\r
-\r
-/**\r
-\r
- Allocate and initialize the empty OHCI device.\r
-\r
- @param PciIo The PCIIO to use.\r
- @param OriginalPciAttributes The original PCI attributes.\r
-\r
- @return Allocated OHCI device If err, return NULL.\r
-\r
-**/\r
-\r
-USB_OHCI_HC_DEV *\r
-OhciAllocateDev (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT64 OriginalPciAttributes\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- EFI_STATUS Status;\r
- VOID *Buf;\r
- EFI_PHYSICAL_ADDRESS PhyAddr;\r
- VOID *Map;\r
- UINTN Pages;\r
- UINTN Bytes;\r
-\r
- Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));\r
- if (Ohc == NULL) {\r
- return NULL;\r
- }\r
-\r
- Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;\r
- Ohc->PciIo = PciIo;\r
-\r
- Ohc->UsbHc.Reset = OhciReset;\r
- Ohc->UsbHc.GetState = OhciGetState;\r
- Ohc->UsbHc.SetState = OhciSetState;\r
- Ohc->UsbHc.ControlTransfer = OhciControlTransfer;\r
- Ohc->UsbHc.BulkTransfer = OhciBulkTransfer;\r
- Ohc->UsbHc.AsyncInterruptTransfer = OhciAsyncInterruptTransfer;\r
- Ohc->UsbHc.SyncInterruptTransfer = OhciSyncInterruptTransfer;\r
- Ohc->UsbHc.IsochronousTransfer = OhciIsochronousTransfer;\r
- Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;\r
- Ohc->UsbHc.GetRootHubPortNumber = OhciGetRootHubNumOfPorts;\r
- Ohc->UsbHc.GetRootHubPortStatus = OhciGetRootHubPortStatus;\r
- Ohc->UsbHc.SetRootHubPortFeature = OhciSetRootHubPortFeature;\r
- Ohc->UsbHc.ClearRootHubPortFeature = OhciClearRootHubPortFeature;\r
- Ohc->UsbHc.MajorRevision = 0x1;\r
- Ohc->UsbHc.MinorRevision = 0x1;\r
-\r
- Ohc->OriginalPciAttributes = OriginalPciAttributes;\r
-\r
- Ohc->HccaMemoryBlock = NULL;\r
- Ohc->HccaMemoryMapping = NULL;\r
- Ohc->HccaMemoryBuf = NULL;\r
- Ohc->HccaMemoryPages = 0;\r
- Ohc->InterruptContextList = NULL;\r
- Ohc->ControllerNameTable = NULL;\r
- Ohc->HouseKeeperTimer = NULL;\r
-\r
- Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);\r
- if(Ohc->MemPool == NULL) {\r
- goto FREE_DEV_BUFFER;\r
- }\r
-\r
- Bytes = 4096;\r
- Pages = EFI_SIZE_TO_PAGES (Bytes);\r
-\r
- Status = PciIo->AllocateBuffer (\r
- PciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- Pages,\r
- &Buf,\r
- 0\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto FREE_MEM_POOL;\r
- }\r
-\r
- Status = PciIo->Map (\r
- PciIo,\r
- EfiPciIoOperationBusMasterCommonBuffer,\r
- Buf,\r
- &Bytes,\r
- &PhyAddr,\r
- &Map\r
- );\r
-\r
- if (EFI_ERROR (Status) || (Bytes != 4096)) {\r
- goto FREE_MEM_PAGE;\r
- }\r
-\r
- Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;\r
- Ohc->HccaMemoryMapping = Map;\r
- Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;\r
- Ohc->HccaMemoryPages = Pages;\r
-\r
- return Ohc;\r
-\r
-FREE_MEM_PAGE:\r
- PciIo->FreeBuffer (PciIo, Pages, Buf);\r
-FREE_MEM_POOL:\r
- UsbHcFreeMemPool (Ohc->MemPool);\r
-FREE_DEV_BUFFER:\r
- FreePool(Ohc);\r
-\r
- return NULL;\r
-}\r
-/**\r
-\r
- Free the OHCI device and release its associated resources.\r
-\r
- @param Ohc The OHCI device to release.\r
-\r
-**/\r
-VOID\r
-OhciFreeDev (\r
- IN USB_OHCI_HC_DEV *Ohc\r
- )\r
-{\r
- OhciFreeFixedIntMemory (Ohc);\r
-\r
- if (Ohc->HouseKeeperTimer != NULL) {\r
- gBS->CloseEvent (Ohc->HouseKeeperTimer);\r
- }\r
-\r
- if (Ohc->ExitBootServiceEvent != NULL) {\r
- gBS->CloseEvent (Ohc->ExitBootServiceEvent);\r
- }\r
-\r
- if (Ohc->MemPool != NULL) {\r
- UsbHcFreeMemPool (Ohc->MemPool);\r
- }\r
-\r
- if (Ohc->HccaMemoryMapping != NULL ) {\r
- Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);\r
- }\r
-\r
- if (Ohc->ControllerNameTable != NULL) {\r
- FreeUnicodeStringTable (Ohc->ControllerNameTable);\r
- }\r
-\r
- FreePool (Ohc);\r
-}\r
-/**\r
-\r
- Uninstall all Ohci Interface.\r
-\r
- @param Controller Controller handle.\r
- @param This Protocol instance pointer.\r
-\r
-**/\r
-VOID\r
-OhciCleanDevUp (\r
- IN EFI_HANDLE Controller,\r
- IN EFI_USB_HC_PROTOCOL *This\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
-\r
- //\r
- // Retrieve private context structure\r
- //\r
- Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
-\r
- //\r
- // Uninstall the USB_HC and USB_HC2 protocol\r
- //\r
- gBS->UninstallProtocolInterface (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- &Ohc->UsbHc\r
- );\r
-\r
- //\r
- // Cancel the timer event\r
- //\r
- gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);\r
-\r
- //\r
- // Stop the host controller\r
- //\r
- OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);\r
- This->Reset (This, EFI_USB_HC_RESET_GLOBAL);\r
- This->SetState (This, EfiUsbHcStateHalt);\r
-\r
- //\r
- // Free resources\r
- //\r
- OhciFreeDynamicIntMemory (Ohc);\r
-\r
- //\r
- // Restore original PCI attributes\r
- //\r
- Ohc->PciIo->Attributes (\r
- Ohc->PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- Ohc->OriginalPciAttributes,\r
- NULL\r
- );\r
-\r
- //\r
- // Free the private context structure\r
- //\r
- OhciFreeDev (Ohc);\r
-}\r
-\r
-/**\r
-\r
- One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
-\r
- @param Event Pointer to this event\r
- @param Context Event handler private data\r
-**/\r
-VOID\r
-EFIAPI\r
-OhcExitBootService (\r
- EFI_EVENT Event,\r
- VOID *Context\r
- )\r
-{\r
- USB_OHCI_HC_DEV *Ohc;\r
- EFI_USB_HC_PROTOCOL *UsbHc;\r
- Ohc = (USB_OHCI_HC_DEV *) Context;\r
-\r
- UsbHc = &Ohc->UsbHc;\r
- //\r
- // Stop the Host Controller\r
- //\r
- //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);\r
- OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);\r
- UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);\r
- UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);\r
-\r
- return;\r
-}\r
-\r
-\r
-/**\r
- Starting the Usb OHCI Driver.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to test.\r
- @param RemainingDevicePath Not used.\r
-\r
- @retval EFI_SUCCESS This driver supports this device.\r
- @retval EFI_UNSUPPORTED This driver does not support this device.\r
- @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
- EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OHCIDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- USB_OHCI_HC_DEV *Ohc;\r
- UINT64 Supports;\r
- UINT64 OriginalPciAttributes;\r
- BOOLEAN PciAttributesSaved;\r
-\r
- //\r
- // Open PCIIO, then enable the HC device and turn off emulation\r
- //\r
- Ohc = NULL;\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- PciAttributesSaved = FALSE;\r
- //\r
- // Save original PCI attributes\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationGet,\r
- 0,\r
- &OriginalPciAttributes\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_PCIIO;\r
- }\r
- PciAttributesSaved = TRUE;\r
-\r
- //\r
- // Robustnesss improvement such as for UoL\r
- // Default is not required.\r
- //\r
- //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
- // OhciTurnOffUsbEmulation (PciIo);\r
- //}\r
-\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE;\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_PCIIO;\r
- }\r
- //\r
- //Allocate memory for OHC private data structure\r
- //\r
- Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);\r
- if (Ohc == NULL){\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto CLOSE_PCIIO;\r
- }\r
-\r
- //Status = OhciInitializeInterruptList ( Uhc );\r
- //if (EFI_ERROR (Status)) {\r
- // goto FREE_OHC;\r
- //}\r
-\r
- //\r
- // Set 0.01 s timer\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- OhciHouseKeeper,\r
- Ohc,\r
- &Ohc->HouseKeeperTimer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto FREE_OHC;\r
- }\r
-\r
- Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);\r
- if (EFI_ERROR (Status)) {\r
- goto FREE_OHC;\r
- }\r
-\r
- //\r
- //Install Host Controller Protocol\r
- //\r
- Status = gBS->InstallProtocolInterface (\r
- &Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &Ohc->UsbHc\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_INFO, "Install protocol error"));\r
- goto FREE_OHC;\r
- }\r
- //\r
- // Create event to stop the HC when exit boot service.\r
- //\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- OhcExitBootService,\r
- Ohc,\r
- &gEfiEventExitBootServicesGuid,\r
- &Ohc->ExitBootServiceEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_INFO, "Create exit boot event error"));\r
- goto UNINSTALL_USBHC;\r
- }\r
- AddUnicodeString2 (\r
- "eng",\r
- gOhciComponentName.SupportedLanguages,\r
- &Ohc->ControllerNameTable,\r
- L"Usb Universal Host Controller",\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gOhciComponentName2.SupportedLanguages,\r
- &Ohc->ControllerNameTable,\r
- L"Usb Universal Host Controller",\r
- FALSE\r
- );\r
-\r
- return EFI_SUCCESS;\r
-\r
-UNINSTALL_USBHC:\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- &Ohc->UsbHc,\r
- NULL\r
- );\r
-\r
-FREE_OHC:\r
- OhciFreeDev (Ohc);\r
-\r
-CLOSE_PCIIO:\r
- if (PciAttributesSaved) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- OriginalPciAttributes,\r
- NULL\r
- );\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
-}\r
-\r
-/**\r
- Stop this driver on ControllerHandle. Support stopping any child handles\r
- created by this driver.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to stop driver on.\r
- @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
- @param ChildHandleBuffer List of handles for the children we need to stop.\r
-\r
- @return EFI_SUCCESS\r
- @return others\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OHCIDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_USB_HC_PROTOCOL *UsbHc;\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- (VOID **)&UsbHc,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- OhciCleanDevUp(Controller, UsbHc);\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r