/** @file Provides some data structure definitions used by the XHCI host controller driver. (C) Copyright 2023 Hewlett Packard Enterprise Development LP
Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef _EFI_XHCI_H_ #define _EFI_XHCI_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _USB_XHCI_INSTANCE USB_XHCI_INSTANCE; typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT; #include "XhciReg.h" #include "XhciSched.h" #include "ComponentName.h" #include "UsbHcMem.h" // // Converts a count from microseconds to nanoseconds // #define XHC_MICROSECOND_TO_NANOSECOND(Time) (MultU64x32((Time), 1000)) // // The unit is microsecond, setting it as 1us. // #define XHC_1_MICROSECOND (1) // // The unit is microsecond, setting it as 1ms. // #define XHC_1_MILLISECOND (1000) // // XHC generic timeout experience values. // The unit is millisecond, setting it as 10s. // #define XHC_GENERIC_TIMEOUT (10 * 1000) // // XHC reset timeout experience values. // The unit is millisecond, setting it as 1s. // #define XHC_RESET_TIMEOUT (1000) // // TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5. // The unit is microsecond, setting it as 10ms. // #define XHC_RESET_RECOVERY_DELAY (10 * 1000) // // XHC async transfer timer interval, set by experience. // The unit is 100us, takes 1ms as interval. // #define XHC_ASYNC_TIMER_INTERVAL EFI_TIMER_PERIOD_MILLISECONDS(1) // // XHC raises TPL to TPL_NOTIFY to serialize all its operations // to protect shared data structures. // #define XHC_TPL TPL_NOTIFY #define CMD_RING_TRB_NUMBER 0x100 #define TR_RING_TRB_NUMBER 0x100 #define ERST_NUMBER 0x01 #define EVENT_RING_TRB_NUMBER 0x200 #define CMD_INTER 0 #define CTRL_INTER 1 #define BULK_INTER 2 #define INT_INTER 3 #define INT_INTER_ASYNC 4 #define EFI_LIST_CONTAINER(Entry, Type, Field) BASE_CR(Entry, Type, Field) #define XHC_LOW_32BIT(Addr64) ((UINT32)(((UINTN)(Addr64)) & 0xFFFFFFFF)) #define XHC_HIGH_32BIT(Addr64) ((UINT32)(RShiftU64((UINT64)(UINTN)(Addr64), 32) & 0xFFFFFFFF)) #define XHC_BIT_IS_SET(Data, Bit) ((BOOLEAN)(((Data) & (Bit)) == (Bit))) #define XHC_REG_BIT_IS_SET(Xhc, Offset, Bit) \ (XHC_BIT_IS_SET(XhcReadOpReg ((Xhc), (Offset)), (Bit))) #define XHCI_IS_DATAIN(EndpointAddr) XHC_BIT_IS_SET((EndpointAddr), 0x80) #define XHCI_INSTANCE_SIG SIGNATURE_32 ('x', 'h', 'c', 'i') #define XHC_FROM_THIS(a) CR(a, USB_XHCI_INSTANCE, Usb2Hc, XHCI_INSTANCE_SIG) #define USB_DESC_TYPE_HUB 0x29 #define USB_DESC_TYPE_HUB_SUPER_SPEED 0x2a // // The RequestType in EFI_USB_DEVICE_REQUEST is composed of // three fields: One bit direction, 2 bit type, and 5 bit // target. // #define USB_REQUEST_TYPE(Dir, Type, Target) \ ((UINT8)((((Dir) == EfiUsbDataIn ? 0x01 : 0) << 7) | (Type) | (Target))) // // Xhci Data and Ctrl Structures // #pragma pack(1) typedef struct { UINT8 ProgInterface; UINT8 SubClassCode; UINT8 BaseCode; } USB_CLASSC; typedef struct { UINT8 Length; UINT8 DescType; UINT8 NumPorts; UINT16 HubCharacter; UINT8 PwrOn2PwrGood; UINT8 HubContrCurrent; UINT8 Filler[16]; } EFI_USB_HUB_DESCRIPTOR; #pragma pack() struct _USB_DEV_CONTEXT { // // Whether this entry in UsbDevContext array is used or not. // BOOLEAN Enabled; // // The slot id assigned to the new device through XHCI's Enable_Slot cmd. // UINT8 SlotId; // // The route string presented an attached usb device. // USB_DEV_ROUTE RouteString; // // The route string of parent device if it exists. Otherwise it's zero. // USB_DEV_ROUTE ParentRouteString; // // The actual device address assigned by XHCI through Address_Device command. // UINT8 XhciDevAddr; // // The requested device address from UsbBus driver through Set_Address standard usb request. // As XHCI spec replaces this request with Address_Device command, we have to record the // requested device address and establish a mapping relationship with the actual device address. // Then UsbBus driver just need to be aware of the requested device address to access usb device // through EFI_USB2_HC_PROTOCOL. Xhci driver would be responsible for translating it to actual // device address and access the actual device. // UINT8 BusDevAddr; // // The pointer to the input device context. // VOID *InputContext; // // The pointer to the output device context. // VOID *OutputContext; // // The transfer queue for every endpoint. // VOID *EndpointTransferRing[31]; // // The device descriptor which is stored to support XHCI's Evaluate_Context cmd. // EFI_USB_DEVICE_DESCRIPTOR DevDesc; // // As a usb device may include multiple configuration descriptors, we dynamically allocate an array // to store them. // Note that every configuration descriptor stored here includes those lower level descriptors, // such as Interface descriptor, Endpoint descriptor, and so on. // These information is used to support XHCI's Config_Endpoint cmd. // EFI_USB_CONFIG_DESCRIPTOR **ConfDesc; // // A device has an active Configuration. // UINT8 ActiveConfiguration; // // Every interface has an active AlternateSetting. // UINT8 *ActiveAlternateSetting; }; struct _USB_XHCI_INSTANCE { UINT32 Signature; EFI_PCI_IO_PROTOCOL *PciIo; UINT64 OriginalPciAttributes; USBHC_MEM_POOL *MemPool; EFI_USB2_HC_PROTOCOL Usb2Hc; EFI_DEVICE_PATH_PROTOCOL *DevicePath; // // ExitBootServicesEvent is used to set OS semaphore and // stop the XHC DMA operation after exit boot service. // EFI_EVENT ExitBootServiceEvent; EFI_EVENT PollTimer; LIST_ENTRY AsyncIntTransfers; UINT8 CapLength; ///< Capability Register Length XHC_HCSPARAMS1 HcSParams1; ///< Structural Parameters 1 XHC_HCSPARAMS2 HcSParams2; ///< Structural Parameters 2 XHC_HCCPARAMS HcCParams; ///< Capability Parameters UINT32 DBOff; ///< Doorbell Offset UINT32 RTSOff; ///< Runtime Register Space Offset UINT16 MaxInterrupt; UINT32 PageSize; UINT64 *ScratchBuf; VOID *ScratchMap; UINT32 MaxScratchpadBufs; UINT64 *ScratchEntry; UINTN *ScratchEntryMap; UINT32 ExtCapRegBase; UINT32 UsbLegSupOffset; UINT32 DebugCapSupOffset; UINT32 Usb2SupOffset; UINT32 Usb3SupOffset; UINT64 *DCBAA; VOID *DCBAAMap; UINT32 MaxSlotsEn; URB *PendingUrb; // // Cmd Transfer Ring // TRANSFER_RING CmdRing; // // EventRing // EVENT_RING EventRing; // // Misc // EFI_UNICODE_STRING_TABLE *ControllerNameTable; // // Store device contexts managed by XHCI instance // The array supports up to 255 devices, entry 0 is reserved and should not be used. // USB_DEV_CONTEXT UsbDevContext[256]; BOOLEAN Support64BitDma; // Whether 64 bit DMA may be used with this device }; extern EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding; extern EFI_COMPONENT_NAME_PROTOCOL gXhciComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gXhciComponentName2; /** Test to see if this driver supports ControllerHandle. Any ControllerHandle that has Usb2HcProtocol installed will be supported. @param This Protocol instance pointer. @param Controller Handle of device to test. @param RemainingDevicePath Not used. @return EFI_SUCCESS This driver supports this device. @return EFI_UNSUPPORTED This driver does not support this device. **/ EFI_STATUS EFIAPI XhcDriverBindingSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ); /** Starting the Usb XHCI Driver. @param This Protocol instance pointer. @param Controller Handle of device to test. @param RemainingDevicePath Not used. @return EFI_SUCCESS supports this device. @return EFI_UNSUPPORTED do not support this device. @return EFI_DEVICE_ERROR cannot be started due to device Error. @return EFI_OUT_OF_RESOURCES cannot allocate resources. **/ EFI_STATUS EFIAPI XhcDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ); /** Stop this driver on ControllerHandle. Support stopping any child handles created by this driver. @param This Protocol instance pointer. @param Controller Handle of device to stop driver on. @param NumberOfChildren Number of Children in the ChildHandleBuffer. @param ChildHandleBuffer List of handles for the children we need to stop. @return EFI_SUCCESS Success. @return EFI_DEVICE_ERROR Fail. **/ EFI_STATUS EFIAPI XhcDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ); /** Retrieves the capability of root hub ports. @param This The EFI_USB2_HC_PROTOCOL instance. @param MaxSpeed Max speed supported by the controller. @param PortNumber Number of the root hub ports. @param Is64BitCapable Whether the controller supports 64-bit memory addressing. @retval EFI_SUCCESS Host controller capability were retrieved successfully. @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL. **/ EFI_STATUS EFIAPI XhcGetCapability ( IN EFI_USB2_HC_PROTOCOL *This, OUT UINT8 *MaxSpeed, OUT UINT8 *PortNumber, OUT UINT8 *Is64BitCapable ); /** Provides software reset for the USB host controller. @param This This EFI_USB2_HC_PROTOCOL instance. @param Attributes A bit mask of the reset operation to perform. @retval EFI_SUCCESS The reset operation succeeded. @retval EFI_INVALID_PARAMETER Attributes is not valid. @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is not currently supported by the host controller. @retval EFI_DEVICE_ERROR Host controller isn't halted to reset. **/ EFI_STATUS EFIAPI XhcReset ( IN EFI_USB2_HC_PROTOCOL *This, IN UINT16 Attributes ); /** Retrieve the current state of the USB host controller. @param This This EFI_USB2_HC_PROTOCOL instance. @param State Variable to return the current host controller state. @retval EFI_SUCCESS Host controller state was returned in State. @retval EFI_INVALID_PARAMETER State is NULL. @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the host controller's current state. **/ EFI_STATUS EFIAPI XhcGetState ( IN EFI_USB2_HC_PROTOCOL *This, OUT EFI_USB_HC_STATE *State ); /** Sets the USB host controller to a specific state. @param This This EFI_USB2_HC_PROTOCOL instance. @param State The state of the host controller that will be set. @retval EFI_SUCCESS The USB host controller was successfully placed in the state specified by State. @retval EFI_INVALID_PARAMETER State is invalid. @retval EFI_DEVICE_ERROR Failed to set the state due to device error. **/ EFI_STATUS EFIAPI XhcSetState ( IN EFI_USB2_HC_PROTOCOL *This, IN EFI_USB_HC_STATE State ); /** Retrieves the current status of a USB root hub port. @param This This EFI_USB2_HC_PROTOCOL instance. @param PortNumber The root hub port to retrieve the state from. This value is zero-based. @param PortStatus Variable to receive the port state. @retval EFI_SUCCESS The status of the USB root hub port specified. by PortNumber was returned in PortStatus. @retval EFI_INVALID_PARAMETER PortNumber is invalid. @retval EFI_DEVICE_ERROR Can't read register. **/ EFI_STATUS EFIAPI XhcGetRootHubPortStatus ( IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 PortNumber, OUT EFI_USB_PORT_STATUS *PortStatus ); /** Sets a feature for the specified root hub port. @param This This EFI_USB2_HC_PROTOCOL instance. @param PortNumber Root hub port to set. @param PortFeature Feature to set. @retval EFI_SUCCESS The feature specified by PortFeature was set. @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid. @retval EFI_DEVICE_ERROR Can't read register. **/ EFI_STATUS EFIAPI XhcSetRootHubPortFeature ( IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature ); /** Clears a feature for the specified root hub port. @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. @param PortNumber Specifies the root hub port whose feature is requested to be cleared. @param PortFeature Indicates the feature selector associated with the feature clear request. @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the USB root hub port specified by PortNumber. @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid. @retval EFI_DEVICE_ERROR Can't read register. **/ EFI_STATUS EFIAPI XhcClearRootHubPortFeature ( IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature ); /** Submits control transfer to a target USB device. @param This This EFI_USB2_HC_PROTOCOL instance. @param DeviceAddress The target device address. @param DeviceSpeed Target device speed. @param MaximumPacketLength Maximum packet size the default control transfer endpoint is capable of sending or receiving. @param Request USB device request to send. @param TransferDirection Specifies the data direction for the data stage @param Data Data buffer to be transmitted or received from USB device. @param DataLength The size (in bytes) of the data buffer. @param Timeout Indicates the maximum timeout, in millisecond. @param Translator Transaction translator to be used by this device. @param TransferResult Return the result of this control transfer. @retval EFI_SUCCESS Transfer was completed successfully. @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources. @retval EFI_INVALID_PARAMETER Some parameters are invalid. @retval EFI_TIMEOUT Transfer failed due to timeout. @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error. **/ EFI_STATUS EFIAPI XhcControlTransfer ( 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 ); /** Submits bulk transfer to a bulk endpoint of a USB device. @param This This EFI_USB2_HC_PROTOCOL instance. @param DeviceAddress Target device address. @param EndPointAddress Endpoint number and its direction in bit 7. @param DeviceSpeed Device speed, Low speed device doesn't support bulk transfer. @param MaximumPacketLength Maximum packet size the endpoint is capable of sending or receiving. @param DataBuffersNumber Number of data buffers prepared for the transfer. @param Data Array of pointers to the buffers of data to transmit from or receive into. @param DataLength The lenght of the data buffer. @param DataToggle On input, the initial data toggle for the transfer; On output, it is updated to to next data toggle to use of the subsequent bulk transfer. @param Timeout Indicates the maximum time, in millisecond, which the transfer is allowed to complete. @param Translator A pointr to the transaction translator data. @param TransferResult A pointer to the detailed result information of the bulk transfer. @retval EFI_SUCCESS The transfer was completed successfully. @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. @retval EFI_INVALID_PARAMETER Some parameters are invalid. @retval EFI_TIMEOUT The transfer failed due to timeout. @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. **/ EFI_STATUS EFIAPI XhcBulkTransfer ( 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], IN OUT UINTN *DataLength, IN OUT UINT8 *DataToggle, IN UINTN Timeout, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult ); /** Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. @param This This EFI_USB2_HC_PROTOCOL instance. @param DeviceAddress Target device address. @param EndPointAddress Endpoint number and its direction encoded in bit 7 @param DeviceSpeed Indicates device speed. @param MaximumPacketLength Maximum packet size the target endpoint is capable @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt transfer If FALSE, to remove the specified asynchronous interrupt. @param DataToggle On input, the initial data toggle to use; on output, it is updated to indicate the next data toggle. @param PollingInterval The he interval, in milliseconds, that the transfer is polled. @param DataLength The length of data to receive at the rate specified by PollingInterval. @param Translator Transaction translator to use. @param CallBackFunction Function to call at the rate specified by PollingInterval. @param Context Context to CallBackFunction. @retval EFI_SUCCESS The request has been successfully submitted or canceled. @retval EFI_INVALID_PARAMETER Some parameters are invalid. @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources. @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. **/ EFI_STATUS EFIAPI XhcAsyncInterruptTransfer ( IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN BOOLEAN IsNewTransfer, IN OUT UINT8 *DataToggle, IN UINTN PollingInterval, IN UINTN DataLength, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, IN VOID *Context OPTIONAL ); /** Submits synchronous interrupt transfer to an interrupt endpoint of a USB device. @param This This EFI_USB2_HC_PROTOCOL instance. @param DeviceAddress Target device address. @param EndPointAddress Endpoint number and its direction encoded in bit 7 @param DeviceSpeed Indicates device speed. @param MaximumPacketLength Maximum packet size the target endpoint is capable of sending or receiving. @param Data Buffer of data that will be transmitted to USB device or received from USB device. @param DataLength On input, the size, in bytes, of the data buffer; On output, the number of bytes transferred. @param DataToggle On input, the initial data toggle to use; on output, it is updated to indicate the next data toggle. @param Timeout Maximum time, in second, to complete. @param Translator Transaction translator to use. @param TransferResult Variable to receive the transfer result. @return EFI_SUCCESS The transfer was completed successfully. @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. @return EFI_INVALID_PARAMETER Some parameters are invalid. @return EFI_TIMEOUT The transfer failed due to timeout. @return EFI_DEVICE_ERROR The failed due to host controller or device error **/ EFI_STATUS EFIAPI XhcSyncInterruptTransfer ( IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN OUT UINT8 *DataToggle, IN UINTN Timeout, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult ); /** Submits isochronous transfer to a target USB device. @param This This EFI_USB2_HC_PROTOCOL instance. @param DeviceAddress Target device address. @param EndPointAddress End point address with its direction. @param DeviceSpeed Device speed, Low speed device doesn't support this type. @param MaximumPacketLength Maximum packet size that the endpoint is capable of sending or receiving. @param DataBuffersNumber Number of data buffers prepared for the transfer. @param Data Array of pointers to the buffers of data that will be transmitted to USB device or received from USB device. @param DataLength The size, in bytes, of the data buffer. @param Translator Transaction translator to use. @param TransferResult Variable to receive the transfer result. @return EFI_UNSUPPORTED Isochronous transfer is unsupported. **/ EFI_STATUS EFIAPI XhcIsochronousTransfer ( 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_ISO_BUFFER_NUM], IN UINTN DataLength, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult ); /** Submits Async isochronous transfer to a target USB device. @param This This EFI_USB2_HC_PROTOCOL instance. @param DeviceAddress Target device address. @param EndPointAddress End point address with its direction. @param DeviceSpeed Device speed, Low speed device doesn't support this type. @param MaximumPacketLength Maximum packet size that the endpoint is capable of sending or receiving. @param DataBuffersNumber Number of data buffers prepared for the transfer. @param Data Array of pointers to the buffers of data that will be transmitted to USB device or received from USB device. @param DataLength The size, in bytes, of the data buffer. @param Translator Transaction translator to use. @param IsochronousCallBack Function to be called when the transfer complete. @param Context Context passed to the call back function as parameter. @return EFI_UNSUPPORTED Isochronous transfer isn't supported. **/ EFI_STATUS EFIAPI XhcAsyncIsochronousTransfer ( 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_ISO_BUFFER_NUM], IN UINTN DataLength, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, IN VOID *Context ); /** Converts a time in nanoseconds to a performance counter tick count. @param Time The time in nanoseconds to be converted to performance counter ticks. @return Time in nanoseconds converted to ticks. **/ UINT64 XhcConvertTimeToTicks ( UINT64 Time ); /** Computes and returns the elapsed ticks since PreviousTick. The value of PreviousTick is overwritten with the current performance counter value. @param PreviousTick Pointer to PreviousTick count. @return The elapsed ticks since PreviousCount. PreviousCount is overwritten with the current performance counter value. **/ UINT64 XhcGetElapsedTicks ( IN OUT UINT64 *PreviousTick ); #endif