/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: ohcd.h Abstract: Structures used by the OpenHCI hardware dependent driver. These are constructs specific to this driver implementation. Standard Structures defined by Specification are in ohci.h Environment: Designed for XBOX. Notes: Revision History: 01-14-00 created by Mitchell Dernis (mitchd) --*/ #ifndef __OCHD_H__ #define __OCHD_H__ // // Pull in the hardware spec stuff // #include "ohci.h" // // forward declaration of pointer types, easy access later. // typedef struct _OHCD_TRANSFER_DESCRIPTOR *POHCD_TRANSFER_DESCRIPTOR; typedef struct _OHCD_SETUP_BUFFER *POHCD_SETUP_BUFFER; typedef struct _OHCD_ENDPOINT *POHCD_ENDPOINT; typedef struct _OHCD_POOL *POHCD_POOL; typedef struct _OHCD_INTERRUPT_SCHEDULE_NODE *POHCD_INTERRUPT_SCHEDULE_NODE; typedef struct _OHCD_ENDPOINT_SCHEDULE *POHCD_ENDPOINT_SCHEDULE; typedef struct _OHCD_DEVICE_EXTENSION *POHCD_DEVICE_EXTENSION; // // READ_REGISTER_ULONG and WRITE_REGISTER_ULONG are no longer // support in the Xbox Kernel. Registers must be mapped to // noncached memory. Define macros here that simply do // a C assignement. // #define WRITE_REGISTER_ULONG(preg,value) (*((volatile ULONG *)(preg))=value) #define READ_REGISTER_ULONG(preg) (*((volatile ULONG *)(preg))) // // struct OHCD_TRANSFER_DESCRIPTOR // // This is the transfer descriptor as seen by the OHCD driver. // It is padded with 16 bytes of driver related fields. // Followed by the OHCI defined structure. // typedef struct _OHCD_TRANSFER_DESCRIPTOR { // // OHCI defined structure // OHCI_TRANSFER_DESCRIPTOR HcTransferDescriptor; // // 16 bytes of Extra driver related fields // ULONG PhysicalAddress; //Physical address of this descriptor union{ POHCD_TRANSFER_DESCRIPTOR NextFree; //Used when the block is on the free list. POHCD_ENDPOINT Endpoint; //Endpoint which executed this transfer }; PURB Urb; //Urb we are connected to UCHAR Flags; //Various flags UCHAR Bytes; //Various flags UCHAR Type; //Type of TD UCHAR HostControllerNumber; //0xFF when not in use. } OHCD_TRANSFER_DESCRIPTOR; #define OHCD_TD_FLAG_CANCEL_PENDING 0x00000001 //TD has been marked for cancel #define OHCD_TD_FLAG_LAST_TD 0x00000002 //Last TD of an URB #define OHCD_TD_TYPE_DATA 0 //Setup TD of control transfer #define OHCD_TD_TYPE_SETUP 1 //Setup TD of control transfer #define OHCD_TD_TYPE_STATUS 2 //Status TD of control transfer #define OHCD_TD_TYPE_DUMMY 3 //Dummy TD of control transfer // // Flags used for the HcdUrbFlags found in the HCD area // of asynchronous transfer URBS. These flags are used // for tracking the state of an URB so that it can be // cancelled. // #define OHCD_URB_FLAG_CANCELED 0x0001 #define OHCD_URB_FLAG_QUEUED 0x0002 #define OHCD_URB_FLAG_PROGRAMMED 0x0004 #define OHCD_URB_FLAG_COMPLETED 0x0008 // Flags for isoch use are defined in isoch.h // This mask just claims the bits. #define OHCD_URB_FLAG_ISOCH_USE 0x0F00 // // struct OHCD_SETUP_STATUS_BUFFER // // This structure is used for control transfers // to hold the setup packet data. We define it as a type of // descriptor block so that we can leverage // the same code used for EDs and TDs // typedef struct _OHCD_SETUP_BUFFER { UCHAR Setup[8]; //Holds the data for a setup packet ULONG Pad1[2]; //Padding to keep the structure the correct size // // Standard driver dependent part of block // ULONG PhysicalAddress; //Physical address of this block ULONG Pad2[3]; //Pad to 32 bytes } OHCD_SETUP_BUFFER; // // Interrupt Node - see schedule.c for overview // typedef struct _OHCD_INTERRUPT_SCHEDULE_NODE { BOOLEAN RegisterHead; UCHAR Pad; USHORT Bandwidth; USHORT BandwidthChildren; USHORT BandwidthParents; POHCD_ENDPOINT EndpointHead; POHCD_ENDPOINT EndpointTail; } OHCD_INTERRUPT_SCHEDULE_NODE; // // Endpoint schedule - see schedule.c for overview // typedef struct _OHCD_ENDPOINT_SCHEDULE { OHCD_INTERRUPT_SCHEDULE_NODE InterruptSchedule[64]; POHCD_ENDPOINT ControlHead; POHCD_ENDPOINT BulkHead; USHORT BandwidthPeriodic; USHORT BandwidthTotal; } OHCD_ENDPOINT_SCHEDULE; // // Endpoint. Due to the first member this structure must start on a 16-byte boundary. // typedef struct _OHCD_ENDPOINT { // // OHCI mandated portion of endpoint. This structure // must start on a paragraph(16-byte) boundary. // OHCI_ENDPOINT_DESCRIPTOR HcEndpointDescriptor; // // Fields for managing the schedule (especially for interrupt) // UCHAR Flags; //Endpoint flags UCHAR EndpointType; //Type of endpoint UCHAR ScheduleIndex; //Index in schedule - see definitions above UCHAR PollingInterval; //Maximum polling interval (in ms) ULONG PhysicalAddress; //Physical address of this structure. POHCD_ENDPOINT Next; //Next endpoint in schedule ULONG PauseFrame; //Used to verify that we have waited at least UCHAR PendingPauseCount; //Number of reasons that we are paused. UCHAR Padding; //Padding to keep up DWORD alignement. USHORT Bandwidth; //Bandwidth required by this endpoint (interrupt and isoch only) USHORT TDInUseCount; //Count of TDs in use. UCHAR QueuedUrbCount; //Count of URBs that are queued waiting to be programmed. UCHAR ProgrammedUrbCount; //Count URBs that are currently programmed. // // Fields for managing URBs and keeping track of transfers // PURB PendingUrbHeadP; PURB PendingUrbTailP; } OHCD_ENDPOINT; #define OHCD_ENDPOINT_FLAG_CLOSING 0x10 //Flag used to indicate that endpoint is being //closed, block cancels when endpoint is closing #define OHCD_ENDPOINT_FLAG_PAUSING 0x20 //Flag used so that we don't try //to pause the endpoint twice. #define OHCD_ENDPOINT_FLAG_DELAY_PAUSE 0x40 //Indicates that the endpoint should not be considered //paused until the next interrupt, set by the pause //routine if a DPC was already queued. typedef struct _OHCD_ROOT_HUB_OBJECT { UCHAR NumberOfPorts; //Number of ports present on the root hub. UCHAR DeviceDetectedBitmap; //Bitmap of ports which have a detected device LARGE_INTEGER PowerOnToGoodTime; //PowerOnToGoodTime in relative 100ns intervals PFNHCD_RESET_COMPLETE ResetComplete; //Completion Routine. PVOID ResetContext; //Completion Context. KTIMER ResetTimeoutTimer; //Timer in case reset times out. KDPC ResetTimeoutDPC; //DPC to be called if reset time-out occurs. } OHCD_ROOT_HUB_OBJECT, *POHCD_ROOT_HUB_OBJECT; VOID HCD_ResetRootHubPort( IN PVOID HcdDeviceExtension, IN ULONG PortNumber, IN PFNHCD_RESET_COMPLETE ResetCompleteProc, IN PVOID CompleteContext ); typedef struct _OHCD_DEVICE_EXTENSION { POHCI_OPERATIONAL_REGISTERS OperationalRegisters; //Port address of operational registers ULONG OperationalRegistersLength; //May vary depending on downstream port count POHCI_HCCA HCCA; //HCD accessable pointer to HCCA OHCD_ENDPOINT_SCHEDULE Schedule; //Everything we need to know about the schedule ULONG FrameHighPart; //The high part of a 32-bit frame counter. //The hardware only keeps 16 bits. PURB ControlUrbHeadP; //Head of URBs for control transfers PURB ControlUrbTailP; //Tail of URBs for control transfers PURB BulkUrbHeadP; //Head of URBs for bulk transfers PURB BulkUrbTailP; //Tail of URBs for bulk transfers PURB PendingCancels; //URBs that need to be canceled. PURB PendingAborts; //URBs that need to be aborted. PURB PendingCloses; //URBs representing pending closes. struct { /* A context structure between Isr and Dpc */ ULONG InterruptsSignaled; //Bit field of interrupt conditions signaled ULONG Frame; //The frame number when the interrupt occured } IsrDpc_Context; KDPC IsrDpc; //DPC for the ISR ULONG HostControllerNumber; //Host Controller Number - really only a byte OHCD_ROOT_HUB_OBJECT RootHubObject; //Everything the root hub needs to know HAL_SHUTDOWN_REGISTRATION ShutdownRegistration; } OHCD_DEVICE_EXTENSION; // // WorkItem Payload for Hotplug items. // typedef struct _OHCD_PORT_INFO { USHORT PortsConnectionChanged; //Bitfield of ports whose connection status needs updating USHORT PortsConnected; //Bitfield of ports that now show connected status } OHCD_PORT_INFO, *POHCD_PORT_INFO; //--------------------------------------------------------------------------------------------------------------- // Choose max controller based on the number of controllers //--------------------------------------------------------------------------------------------------------------- #define HCD_MAX_HOST_CONTROLLERS 1 #if (USB_HOST_CONTROLLER_CONFIGURATION!=USB_SINGLE_HOST_CONTROLLER) #undef HCD_MAX_HOST_CONTROLLERS #define HCD_MAX_HOST_CONTROLLERS 2 #endif //------------------------------------------------------ // Pull in Isochronous Support (or stubs) //------------------------------------------------------ #include "isoch.h" //------------------------------------------------------ // Implemented in OHCD.C //------------------------------------------------------ VOID FASTCALL OHCD_fPauseEndpoint( POHCD_DEVICE_EXTENSION DeviceExtension, POHCD_ENDPOINT endpoint ); //-------------------------------------------------------- // Implemented in Schedule.c //-------------------------------------------------------- VOID FASTCALL OHCD_ScheduleInitialize( IN POHCD_DEVICE_EXTENSION DeviceExtension ); USBD_STATUS FASTCALL OHCD_ScheduleAddEndpointPeriodic( IN POHCD_DEVICE_EXTENSION DeviceExtension, IN POHCD_ENDPOINT Endpoint ); VOID FASTCALL OHCD_ScheduleRemoveEndpointPeriodic( IN POHCD_DEVICE_EXTENSION DeviceExtension, IN POHCD_ENDPOINT Endpoint ); VOID FASTCALL OHCD_ScheduleAddEndpointControlOrBulk( IN POHCD_DEVICE_EXTENSION DeviceExtension, IN POHCD_ENDPOINT Endpoint ); VOID FASTCALL OHCD_ScheduleRemoveEndpointControlOrBulk( IN POHCD_DEVICE_EXTENSION DeviceExtension, IN POHCD_ENDPOINT Endpoint ); //------------------------------------------------------------ // Implemented in Isr.c //------------------------------------------------------------ BOOLEAN OHCD_InterruptService( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext ); VOID OHCD_IsrDpc( PKDPC Dpc, PVOID DeviceExtensionPtr, PVOID Bogus1, PVOID Bogus2 ); ULONG FASTCALL OHCD_Get32BitFrameNumber( IN POHCD_DEVICE_EXTENSION DeviceExtension ); //------------------------------------------------------------ // Implemented in transfer.c //------------------------------------------------------------ USBD_STATUS FASTCALL OHCD_fQueueTransferRequest( POHCD_DEVICE_EXTENSION DeviceExtension, PURB HcdUrb ); VOID FASTCALL OHCD_fProgramInterruptTransfer( POHCD_DEVICE_EXTENSION DeviceExtension, POHCD_ENDPOINT Endpoint ); VOID FASTCALL OHCD_fProgramBulkTransfer( POHCD_DEVICE_EXTENSION DeviceExtension ); VOID FASTCALL OHCD_fProgramControlTransfer( POHCD_DEVICE_EXTENSION DeviceExtension ); //------------------------------------------------------------ // Implemented in roothub.c //------------------------------------------------------------ VOID FASTCALL OHCD_RootHubInitialize( POHCD_DEVICE_EXTENSION DeviceExtension ); VOID FASTCALL OHCD_RootHubProcessInterrupt( POHCD_DEVICE_EXTENSION DeviceExtension ); VOID FASTCALL OHCD_RootHubProcessHotPlug( IN POHCD_DEVICE_EXTENSION DeviceExtension, IN POHCD_PORT_INFO PortInfo ); //------------------------------------------------------ // Implemented in pool.c //------------------------------------------------------ // // struct OHCD_POOL - Global structure pool for // all DMA managed structures // typedef struct _OHCD_POOL { ULONG VirtualToPhysical; POHCI_HCCA Hcca[HCD_MAX_HOST_CONTROLLERS]; POHCD_ENDPOINT FreeEndpoints; POHCD_TRANSFER_DESCRIPTOR FreeTDs; POHCD_TRANSFER_DESCRIPTOR FirstTD; //First TD in pool POHCD_TRANSFER_DESCRIPTOR LastTD; //Last TD in pool ULONG LostDoneHeadCount; //Number of times the DoneHead was lost. ULONG LostMinimumDoneListLength; //minimum length of the DoneHead when //it was lost USHORT ControlQuota; USHORT ControlQuotaRemaining; USHORT BulkQuota; USHORT BulkQuotaRemaining; OHCD_ISOCH_POOL } OHCD_POOL; extern OHCD_POOL OHCD_GlobalPool; #define OHCD_INTERRUPT_TD_QUOTA 3 //Per endpoint quota VOID FASTCALL OHCD_fPoolInit( IN PHCD_RESOURCE_REQUIREMENTS pResourceRequirements ); #ifdef SILVER ULONG FASTCALL OHCD_fPoolFindLostDoneHead( POHCD_DEVICE_EXTENSION DeviceExtension ); #endif //SILVER __inline POHCI_HCCA OHCD_PoolGetHcca( IN UCHAR HostControllerNumber ) { ASSERT(HCD_MAX_HOST_CONTROLLERS > HostControllerNumber); return OHCD_GlobalPool.Hcca[HostControllerNumber]; } __inline POHCD_ENDPOINT OHCD_PoolAllocateEndpoint() { POHCD_ENDPOINT retVal; ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); retVal = OHCD_GlobalPool.FreeEndpoints; if(retVal) { OHCD_GlobalPool.FreeEndpoints = retVal->Next; } ASSERT(retVal); return retVal; } __inline VOID OHCD_PoolFreeEndpoint(POHCD_ENDPOINT Endpoint) { ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); Endpoint->Next = OHCD_GlobalPool.FreeEndpoints; OHCD_GlobalPool.FreeEndpoints = Endpoint; } __inline POHCD_TRANSFER_DESCRIPTOR OHCD_PoolAllocateTD(UCHAR HostControllerNumber) { POHCD_TRANSFER_DESCRIPTOR retVal; retVal = OHCD_GlobalPool.FreeTDs; if(retVal) { OHCD_GlobalPool.FreeTDs = retVal->NextFree; } ASSERT(retVal); retVal->HostControllerNumber = HostControllerNumber; OHCD_CLEAR_TD_ISOCH_FORMAT_BIT(retVal); return retVal; } __inline VOID OHCD_PoolFreeTD( IN POHCD_TRANSFER_DESCRIPTOR TransferDescriptor ) { // We want the hardware NextTD to be an invalid // non-NULL address. This aids in searching for // lost TD lists. TransferDescriptor->HcTransferDescriptor.NextTD = 0xFFFFFFFF; TransferDescriptor->HostControllerNumber = 0xFF; TransferDescriptor->NextFree = OHCD_GlobalPool.FreeTDs; OHCD_GlobalPool.FreeTDs = TransferDescriptor; } __inline POHCD_TRANSFER_DESCRIPTOR OHCD_PoolTDFromPhysicalAddress( IN ULONG PhysicalAddress ) { return (POHCD_TRANSFER_DESCRIPTOR)(OHCD_GlobalPool.VirtualToPhysical + PhysicalAddress); } __inline ULONG OHCD_PoolGetPhysicalAddress(PVOID VirtualAddress) { return ((ULONG)VirtualAddress) - OHCD_GlobalPool.VirtualToPhysical; } __inline USHORT OHCD_PoolGetControlQuota() { return OHCD_GlobalPool.ControlQuota; } __inline BOOLEAN OHCD_PoolDebitControlTDQuota( IN USHORT Count ) { return (OHCD_GlobalPool.ControlQuotaRemaining < Count) ? FALSE : (OHCD_GlobalPool.ControlQuotaRemaining -= Count, TRUE); } __inline VOID OHCD_PoolCreditControlTDQuota( IN USHORT Count ) { OHCD_GlobalPool.ControlQuotaRemaining += Count; } __inline USHORT OHCD_PoolGetBulkQuota() { return OHCD_GlobalPool.BulkQuota; } __inline BOOLEAN OHCD_PoolDebitBulkTDQuota( IN USHORT Count ) { return (OHCD_GlobalPool.BulkQuotaRemaining < Count) ? FALSE : (OHCD_GlobalPool.BulkQuotaRemaining -= Count, TRUE); } __inline VOID OHCD_PoolCreditBulkTDQuota( IN USHORT Count ) { OHCD_GlobalPool.BulkQuotaRemaining += Count; } #ifdef DVTSNOOPBUG VOID OHCD_PoolCreateDoubleBufferPool(); VOID OHCD_PoolStartDoubleBufferTransfer(PURB Urb); VOID OHCD_PoolEndDoubleBufferTransfer(PURB Urb); #endif //Isoch routines are conditionally compiled #ifdef OHCD_ISOCHRONOUS_SUPPORTED __inline ULONG_PTR OHCD_IsochPoolAllocateEndpoint() { ULONG_PTR retVal; ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); retVal = OHCD_GlobalPool.IsochFreeEndpoints; if(retVal) { OHCD_GlobalPool.IsochFreeEndpoints = *((PULONG_PTR)retVal); } ASSERT(retVal); return retVal; } __inline VOID OHCD_IsochPoolFreeEndpoint(ULONG_PTR IsochEndpoint) { ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); *((PULONG_PTR)IsochEndpoint) = OHCD_GlobalPool.IsochFreeEndpoints; OHCD_GlobalPool.IsochFreeEndpoints = IsochEndpoint; } __inline ULONG OHCD_IsochPoolGetMaxBuffers() { return OHCD_GlobalPool.IsochMaxBuffers; } #endif //OHCD_ISOCHRONOUS_SUPPORTED #endif __OCHD_H__