2020-09-30 17:17:25 +02:00

573 lines
27 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
ohci.h
Abstract:
OpenHCI Version 1.0a defined registers and data structures
Some comments included. See OpenHCI specification for more details.
Environment:
Designed for XBOX.
Notes:
Revision History:
01-13-00 created by Mitchell Dernis (mitchd)
--*/
#ifndef __OCHI_H__
#define __OCHI_H__
//
// Program interface code for PCI configuration space.
// Couldn't find it in OpenHCI or UniversalHCI specification.
// I figure it out by looking at the Win2k usb.inf file.
//
#define OHCI_PCI_PROGRAM_INTERFACE 0x10
//
// Endpoint Control
//
typedef union _OHCI_ENDPOINT_CONTROL
{
ULONG ul;
struct {
ULONG FunctionAddress:7; //Address of function (or hub) containing endpoint
ULONG EndpointAddress:4; //Address of endpoint within function (or hub)
ULONG Direction:2; //00b - 11b = read from TD, 01b = OUT, 10b = IN
ULONG Speed:1; //0 = full speed, 1 = low speed
ULONG Skip:1; //When set, HC skips this Endpoint in the schedule
ULONG Format:1; //0 = Control, Bulk or Interrupt, 1=Isochronous
ULONG MaximumPacketSize:11; //Maximum bytes in a single packet
ULONG FutureSoftwareUse:5; //Preserved by HC, available for driver use.
};
} OHCI_ENDPOINT_CONTROL, *POHCI_ENDPOINT_CONTROL;
//
// Structure OHCI_ENDPOINT_DESCRIPTOR
// This structure is used to represent an endpoint in the USB schedule on OHCI controllers.
// (DO NOT CONFUSE WITH USB_ENDPOINT_DESCRIPTOR DEFINED IN USB SPECIFICATION)
//
// Comments:
//
// Must be 4 DWORDs (16 bytes) long.
//
// When TailP = HeadP the list contains no TD that the HC can process.
//
//
typedef struct _OHCI_ENDPOINT_DESCRIPTOR
{
//First DWORD
OHCI_ENDPOINT_CONTROL Control; //see OHCI_ENDPOINT_CONTROL
//Second DWORD
ULONG TailP; //Points to last TD for Endpoint. Pointer should be
//paragraph(16 bytes) aligned. 4 lsb are ignored.
//Third DWORD
ULONG HeadPHaltCarry; //Point to first TD for Endpoint. Pointer should be
//paragraph(16 bytes) aligned. 2 lsb are used though
//for Halt and toggleCarry fields. Bits 3, 4 must be zero.
//Therefore, use access macros. WRITE_HEADP/READ_HEADP,
//SET_HALTED/CLEAR_HALTED/GET_HALTED, and SET_TOGGLECARRY/
//CLEAR_TOGGLECARRY/GET_TOGGLECARRY defined below.
//Fourth DWORD
ULONG NextED; //Points to next endpoint. Pointer should be
//paragraph(16 bytes) aligned. 4 lsb are ignored.
} OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
//
// Macros for access to HeadPHaltCarry element of OHCI_ENDPOINT_DESCRIPTOR
//
#define WRITE_HEADP(_endpoint_descriptor_pointer_, _HeadP_)\
(_endpoint_descriptor_pointer_)->HeadPHaltCarry = (_HeadP_ & 0xFFFFFFF0) | \
((_endpoint_descriptor_pointer_)->HeadPHaltCarry & 0x0000000F);
#define READ_HEADP(_endpoint_descriptor_pointer_) ((_endpoint_descriptor_pointer_)->HeadPHaltCarry & 0xFFFFFFF0)
#define SET_HALTED(_endpoint_descriptor_pointer_) ((_endpoint_descriptor_pointer_)->HeadPHaltCarry |= 0x00000001)
#define CLEAR_HALTED(_endpoint_descriptor_pointer_) ((_endpoint_descriptor_pointer_)->HeadPHaltCarry &= ~0x00000001)
#define GET_HALTED(_endpoint_descriptor_pointer_) \
(((_endpoint_descriptor_pointer_)->HeadPHaltCarry & 0x00000001) ? TRUE : FALSE)
#define SET_TOGGLECARRY(_endpoint_descriptor_pointer_) ((_endpoint_descriptor_pointer_)->HeadPHaltCarry |= 0x00000002)
#define CLEAR_TOGGLECARRY(_endpoint_descriptor_pointer_) ((_endpoint_descriptor_pointer_)->HeadPHaltCarry &= ~0x00000002)
#define GET_TOGGLECARRY(_endpoint_descriptor_pointer_) \
(((_endpoint_descriptor_pointer_)->HeadPHaltCarry & 0x00000002) ? TRUE : FALSE)
//
// Structure OHCI_TRANSFER_DESCRIPTOR
// This structure is used to represent bulk, interrupt and control transfers
// descriptors in the USB schedule on OHCI controllers.
//
// Must be 4 DWORDs (16 bytes) long.
//
typedef struct _OHCI_TRANSFER_DESCRIPTOR *POHCI_TRANSFER_DESCRIPTOR;
typedef struct _OHCI_TRANSFER_DESCRIPTOR
{
//First DWORD
ULONG FutureSoftwareUse1:16; //Preserved by HC, available for driver use.
ULONG Format:1; //Preserved by HC, XBOX OHCD driver defined analog to format set in ED
ULONG FutureSoftwareUse2:1; //Preserved by HC, available for driver use.
ULONG BufferRounding:1; //If clear, than short packets generate an error.
ULONG Direction_PID:2; //00b = SETUP, 01b = OUT, 10b = IN, 11b = Reserved
ULONG DelayInterrupt:3; //Time (in frames) before interrupt must generated after
//this is TD is completed. 111b = No Interrupt
ULONG DataToggle:2; //Used for DATA0\DATA1 toggling. MSb = 0 indicates
//that toggleCarry in ED should be used. MSb = 1 indicates
//that LSb should be used.
ULONG ErrorCount:2; //Error count on attempts to process TD. After 3, TD is
//retired as a failure with the ConditionCode set. Endpoint
//is halted.
ULONG ConditionCode:4; //Status of TD
//Second DWORD
ULONG CurrentBufferPointer; //Pointer to current location in data buffer which receives
//or sends data.
//Third DWORD
// When a TD is handed over to the HC NextTD has a correct physical address.
// However, after dequeueing a TD from the DoneQueue, we use NextTDVirtual
// so that the driver may easily traverse the list.
//
union
{
ULONG NextTD; //Pointer to next Transfer Desciptor. Must be paragraph
POHCI_TRANSFER_DESCRIPTOR NextTDVirtual; //aligned, i.e. bits 0-3 must be 0. We also
};
//Fourth DWORD
ULONG BufferEnd; //BufferEnd - used for 2 page scatter\gather on long packets.
//see OHCI specification.
} OHCI_TRANSFER_DESCRIPTOR;
//
// Macros for OHCI_TRANSFER_DESCRIPTOR.Direction_PID
//
#define OHCI_TD_DIRECTION_PID_SETUP 0
#define OHCI_TD_DIRECTION_PID_OUT 1
#define OHCI_TD_DIRECTION_PID_IN 2
//
// Macros for OHCI_TRANSFER_DESCRIPTOR.DelayInterrupt;
//
#define OHCI_TD_DELAY_INTERRUPT_0_MS 0 // Interrupt at end of frame TD is completed
#define OHCI_TD_DELAY_INTERRUPT_1_MS 1 // Interrupt within 1 frame of TD compeletion
#define OHCI_TD_DELAY_INTERRUPT_2_MS 2 // Interrupt within 2 frames of TD compeletion
#define OHCI_TD_DELAY_INTERRUPT_3_MS 3 // Interrupt within 3 frame of TD compeletion
#define OHCI_TD_DELAY_INTERRUPT_4_MS 4 // Interrupt within 3 frame of TD compeletion
#define OHCI_TD_DELAY_INTERRUPT_5_MS 5 // Interrupt within 3 frame of TD compeletion
#define OHCI_TD_DELAY_INTERRUPT_6_MS 6 // Interrupt within 3 frame of TD compeletion
#define OHCI_TD_DELAY_INTERRUPT_NONE 7 // Do not Interrupt upon completion of TD
//
// Macros for OHCI_TRANSFER_DESCRIPTOR.DataToggle
//
#define OHCI_TD_TOGGLE_FROM_ED 0 // Get the toggle from the ED
#define OHCI_TD_TOGGLE_DATA_MASK 1 // Mask used for toggling the lsb.
#define OHCI_TD_TOGGLE_DATA0 2 // DATA0 and MSb is set, so it will not use
// endpoint toggle carry.
#define OHCI_TD_TOGGLE_DATA1 3 // DATA1 and MSb is set, so it will not use
// endpoint toggle carry.
//
// Condition Code definitions for both general and isochronous transfers
//
#define OHCI_CC_NO_ERROR 0x0 //Completed without detected error
#define OHCI_CC_CRC 0x1 //CRC error
#define OHCI_CC_BIT_STUFFING 0x2 //Bit-stuffing error
#define OHCI_CC_DATA_TOGGLE_MISMATCH 0x3 //DATA0\DATA1 mismatched
#define OHCI_CC_STALL 0x4 //Stall
#define OHCI_CC_DEVICE_NOT_RESPONDING 0x5 //Device screwed up handshake
#define OHCI_CC_PID_CHECK_FAILURE 0x6 //Send PID was not valid for endpoint
#define OHCI_CC_UNEXPECTED_PID 0x7 //Receive PID was not valid for endpoint
#define OHCI_CC_DATA_OVERRUN 0x8 //Endpoint returned more data than MaximumPacketSize
#define OHCI_CC_DATA_UNDERRUN 0x9 //Endpoint returned short packet (only if BufferRounding = 0)
#define OHCI_CC_RESERVED1 0xA //Reserved
#define OHCI_CC_RESERVED2 0xB //Reserved
#define OHCI_CC_BUFFER_OVERRUN 0xC //During an IN, HC received data faster than it could
//write it with DMA.
#define OHCI_CC_BUFFER_UNDERRUN 0xD //During an OUT, HC could not fetch data fast enough
//through DMA.
#define OHCI_CC_NOT_ACCESSED 0xE //Either of these may be set by driver before TD
#define OHCI_CC_NOT_ACCESSED2 0xF //is inserted in schedule
//
// A little 'coincidence' in the way USBD_STATUS_XXXX codes are defined.
// we can convert very easily.
//
#define OHCI_CC_TO_USBD_STATUS(_ConditionCode_) ((ULONG)_ConditionCode_ | 0xC0000000)
//
// Structure OHCI_ISOCHRONOUS_TRANSFER_DESCRIPTOR
// This structure is used to represent isochronous transfers
// in the USB schedule on OHCI controllers.
//
// Must be 8 DWORDs (32 bytes) long.
//
typedef struct _OHCI_ISOCHRONOUS_TRANSFER_DESCRIPTOR
{
//DWORD 0
ULONG StartingFrame:16; //Describes which frame transfer should start in.
ULONG Format:1; //Preserved by HC, XBOX driver defined analog to format set in ED
ULONG FutureSoftwareUse:4; //Preserved by HC, available for driver use.
ULONG DelayInterrupt:3; //Time (in frames) before interrupt must generated after
//this is TD is completed. 111b = No Interrupt
ULONG FrameCount:3; //One less than count of Data Packets (one data packet = one frame)
ULONG FutureSoftwareUse2:1; //Preserved by HC, available for driver use.
ULONG ConditionCode:4; //Status of TD
//DWORD 1
ULONG BufferPage0; //Pointer to current location in data buffer which receives
//or sends data.
//DWORD 2
ULONG NextTD; //Pointer to next Transfer Desciptor. Must be paragraph
//aligned, i.e. bits 0-3 must be 0.
//DWORD 3
ULONG BufferEnd; //BufferEnd - used for 2 page scatter\gather on long packets.
//see OHCI specification.
//DWORDs 4-7
USHORT Offset_PSW[8]; //On input each of these is a buffer offset for
//primitive scatter gather processing for each packet.
//When retired, they contain the size and status
//of transfers.
//There are eight of these, one for each possible frame
//that data can be sent in.
} OHCI_ISOCHRONOUS_TRANSFER_DESCRIPTOR, *POHCI_ISOCHRONOUS_TRANSFER_DESCRIPTOR;
//
// Structure Represented Host Controller Communications Area(HCCA)
//
typedef struct _OHCI_HCCA
{
ULONG InterruptTable[32]; //Each entry points to list of Interrupt Endpoints.
//These lists build the frame schedule for interrupts.
USHORT FrameNumber; //Current Frame number (16 bits)
USHORT Pad1; //HC clears this when the FrameNumber is updated
ULONG DoneHead; //Pointer to List of completed TDs
UCHAR Reserved[120]; //Scratch area for HC except for last 4 bytes which are
//padding so that this is divisible by 32.
} OHCI_HCCA, *POHCI_HCCA;
//
// Bit field for accessing the HcControl register
//
typedef union _HC_CONTROL_REGISTER
{
ULONG ul;
struct
{
ULONG ControlBulkServiceRatio:2; //One less than the count of control to bulk packets services
ULONG PeriodicListEnable:1; //If set, processing periodic lists is enabled
ULONG IsochronousEnable:1; //If set, processing of Isochronous TD is enable if PeriodLists are.
ULONG ControlListEnable:1; //If set, processing of Control Endpoints is enabled
ULONG BulkListEnable:1; //If set, processing of Bulk Endpoints is enabled
ULONG HostControllerFunctionalState:2;//See HC_OPSTATE_USB_XXX definitions below
ULONG InterruptRouting:1; //If set, interrupts are SMI routed, if clear normal bus interrupts
ULONG RemoteWakeupConnected:1; //If set, HC supports remote wakeup.
ULONG RemoteWakeupEnabled:1; //If set, remote wakeup is enabled.
ULONG Reserved:21;
};
} HC_CONTROL_REGISTER, *PHC_CONTROL_REGISTER;
#define HC_OPSTATE_USB_RESET 0
#define HC_OPSTATE_USB_RESUME 1
#define HC_OPSTATE_USB_OPERATIONAL 2
#define HC_OPSTATE_USB_SUSPEND 3
//
// Bit fields are a bit inefficient. When we are changing a 2 bit field
// or even a bit at a time, it makes the code more readable. However,
// during the vary initial setup we want to go to the running state
// while slamming a bunch of bits. Here's what we slam.
//
// 1) Control\Bulk Service Ratio start at 2:1
//
// 2) Periodic, Bulk, and Contorl lists are
// enabled. Isochronous is disabled.
//
// 3) HostControllerFunctionState is UsbOperational
//
// 4) Interrupt Routing is normal (bit clear)
//
// 5) Remote wakeup is disabled.
#define HC_CONTROL_REGISTER_START 0x000000B6
//
// For quick reboot, we shutdown USB. We slam it into the
// following stopped state.
//
// 1) Control\Bulk Service Ratio 2:1
//
// 2) All list processing disabled.
//
// 3) HostControllerFunctionState is UsbReset
//
// 4) Interrupt Routing is normal (bit clear)
//
// 5) Remote wakeup is disabled.
#define HC_CONTROL_REGISTER_STOP 0x00000002
//
// Bit field for accessing the HcCommandStatus register
//
typedef union _HC_COMMAND_STATUS
{
ULONG ul;
struct {
ULONG HostControllerReset:1; //Set to initiate software reset.
ULONG ControlListFilled:1; //Set to indicate that a TD was added to a control ED
ULONG BulkListFilled:1; //Set to indicate that a TD was added to a bulk ED
ULONG OwnerShipChangeRequest:1; //Set to request control from SMM
ULONG Reserved:12;
ULONG SchedulingOverrunCount:2; //Count of schedule overruns.
ULONG Reserved2:14;
};
} HC_COMMAND_STATUS, *PHC_COMMAND_STATUS;
//
// Macros to use insted for ControlListFilled and BulkListFilled
//
#define HCCS_ControlListFilled 0x00000002
#define HCCS_BulkListFilled 0x00000004
//
// Macros for HcInterruptEnable and HcInterruptDisable bit fields
//
// The HCD can write to both HcInterruptEnable and HcInterruptDisable, however, only bit
// setting is processed not bit clearing. To enable an interrupt, set the corresponding bit
// in HcInterruptEnable. To disable an interrupt write to HcInterruptDisable. Since the
// bit layouts are identical, there are only one set of macros.
//
#define HCINT_SchedulingOverrun 0x00000001 //Enables\Disables interrupt on scheduling overrun
#define HCINT_WritebackDoneHead 0x00000002 //Enables\Disables interrupt on Writeback of HcDoneHead
#define HCINT_StartOfFrame 0x00000004 //Enables\Disables interrupt on Start of Frame
#define HCINT_ResumeDetect 0x00000008 //Enables\Disables interrupt on Resume detect
#define HCINT_UnrecoverableError 0x00000010 //Enables\Disables interrupt on Unrecoverable Error
#define HCINT_FrameNumberOverflow 0x00000020 //Enables\Disables interrupt on HcFmNumber changes
#define HCINT_RootHubStatusChange 0x00000040 //Enables\Disables interrupt on HcRhStatus or HcRhPortStatus[n] changes
//Bunch of reserved bits
#define HCINT_OwnershipChange 0x40000000 //Enables\Disables interrupt on Ownership change
#define HCINT_MasterInterruptEnable 0x80000000 //Master switch for enabling interrupts
//
// Bit Field structure for HcFmInterval
//
typedef union _HC_FRAME_INTERVAL
{
ULONG ul;
struct{
ULONG FrameInterval:14; //adjustable interval in clocks between SOF, can be used
//to sync to external clock source
ULONG Reserved:2;
ULONG FullSpeedMaximumPacketSize:15; //Maximum number of bits in full speed packets to send
//with scheduling over flow. Calculated by HCD at initialization.
ULONG FrameIntervalToggle:1; //Toggled by HCD when FrameInterval changes.
};
} HC_FRAME_INTERVAL, *PHC_FRAME_INTERVAL;
//
// The frame interval is set in terms of clocks. However, there is overhead from SOF and other
// minutia. Additionally, there is bit stuffing which eats on average one out of 7 bits.
// According to OHCI we need to calculate this.
// 210 is an estimate of the overhead. I found this formula in existing Win2k code.
//
#define OHCI_DEFAULT_FRAME_INTERVAL 0x2EDF
#define OHCI_CLOCKS_TO_BITS(_Clocks_) ((((_Clocks_) - 210) * 6)/7)
//
// bit field structure fpr HcRhDescriptorA
//
typedef union _HC_RH_DESCRIPTOR_A
{
ULONG ul;
struct
{
//First byte
UCHAR NumberDownstreamPorts; //Count of downstream ports off of root hub.
//Second byte
UCHAR PowerSwitchingMode:1; //If NoPowerSwitch is set, this determines the mode.
UCHAR NoPowerSwitch:1; //0 = ports are power switchable, 1 = ports powered if HC powered.
UCHAR DeviceType:1; //Should always be 0, because Root Hub is not a compound device.
UCHAR OverCurrentProtectionMode:1; //If set overcurrent is reported on per port basis.fs
UCHAR NoOverCurrentProtection:1; //If set overcurrent is not reported.
UCHAR ReservedBits:3;
//Third byte
UCHAR Reserved;
//Fourth byte
UCHAR PowerOnToPowerGoodTime; //Time HCD waits after powering hub before accessing hub.
//Reported in 2 ms units.
};
} HC_RH_DESCRIPTOR_A, *PHC_RH_DESCRIPTOR_A;
//
// bit field structure fpr HcRhDescriptorB
//
typedef union _HC_RH_DESCRIPTOR_B
{
ULONG ul;
struct
{
USHORT DeviceRemovable; //Each bit is dedicated to a port. If set indicates
//that device can NOT be removed from root hub.
USHORT PortPowerControlMask; //Each bit is dedicated to a port. If set indicates
//that device is only effected by per port power control.
//Ignored if PowerSwitchingMode is cleared.
};
} HC_RH_DESCRIPTOR_B, *PHC_RH_DESCRIPTOR_B;
//
// macros and struct for HcRhStatus register
//
// The HubStatus part represents the status if read.
// Write a one to the corresponding bit in HubStatusChange.
//
// However to complicate matter, the LocalPower bit can be written
// to in HubStatus. It has the effect of turning off power. The corresponding
// bit in HubStatusChange turns power on. Guess what, reading LocalPower in the
// HubStatusChange register always returns 0.
//
// OverCurrentIndicator works as expected. On read of HubStatus it returns the
// state, it is not writeable. In HubStatusChange a read returns one if the state
// change. You can clear it with a write of a one to HubStatusChange.
//
// Reading DeviceRemoteWakeup in HubStatus indicates whether a remote wakeup was signaled.
// Writing a one to HubStatus enables remote wakeup. Writing a one to HubStatusChange
// disables remote wakeup.
//
#define HC_RH_STATUS_LocalPower 0x0001
#define HC_RH_STATUS_OvercurrentIndicator 0x0002
#define HC_RH_STATUS_DeviceRemoteWakeupEnable 0x8000
typedef union _HC_RH_STATUS
{
ULONG ul;
struct {
USHORT HubStatus; //bit field indicating hub status
USHORT HubStatusChange; //bit field for changing hub status
};
} HC_RH_STATUS, *PHC_RH_STATUS;
//
// Values for initializing the RootHub on Xbox
//
#define HC_RH_DESCRIPTOR_A_INIT_XBOX 0x00001200 //NoOverCurrentProtection|NoPowerSwitch
#define HC_RH_DESCRIPTOR_B_INIT_XBOX 0x00000000
#define HC_RH_STATUS_INIT_XBOX 0x80000000 //Clears DeviceRemoteWakeupEnable
//
// macros and struct for HcRhPortStatus,
// !!!!Some of the bits do double duty (different on read and write)
// so there may be more than one macro per bit!!!
//
#define HC_RH_PORT_STATUS_CurrentConnectStatus 0x0001 //Read PortStatus, 1 if device currently connected
#define HC_RH_PORT_STATUS_ClearPortEnable 0x0001 //Set PortStatus, disables clears PortEnableStatus
//Read PortStatusChange, 1 indicates connect or disconnect
//Set PortStatusChange, clears this bit in PortStatusChange
#define HC_RH_PORT_STATUS_PortEnableStatus 0x0002 //Read PortStatus, 1 if port is enable
#define HC_RH_PORT_STATUS_SetPortEnable 0x0002 //Set PortStatus, enables device
//Read PortStatusChange, 1 indicates change in PortStatus bit
//Set PortStatusChange, clears this bit in PortStatusChange
#define HC_RH_PORT_STATUS_PortSuspendStatus 0x0004 //Read PortStatus, 1 if port is suspended
#define HC_RH_PORT_STATUS_SetPortSuspend 0x0004 //Set PortStatus suspends device
//Read PortStatusChange, 1 indicates change in PortStatus bit
//Set PortStatusChange, clears this bit in PortStatusChange
#define HC_RH_PORT_STATUS_PortOverCurrentIndicator 0x0008 //Read PortStatus, 1 if port is overcurrent detected
#define HC_RH_PORT_STATUS_ClearSuspendStatus 0x0008 //Set PortStatus resumes device
//Read PortStatusChange, 1 indicates change in PortStatus bit
//Set PortStatusChange, clears this bit in PortStatusChange
#define HC_RH_PORT_STATUS_PortResetStatus 0x0010 //Read PortStatus, 1 if port reset signal is active
#define HC_RH_PORT_STATUS_SetPortReset 0x0010 //Set PortStatus initiates reset signal
//Read PortStatusChange, 1 indicates reset signal completed (10 ms)
//Set PortStatusChange, clears this bit in PortStatusChange
#define HC_RH_PORT_STATUS_PortPowerStatus 0x0100 //Read PortStatus, 1 if port power is on
#define HC_RH_PORT_STATUS_SetPortPower 0x0100 //Set PortStatus turns power on
//There is no PortStatusChange bit
#define HC_RH_PORT_STATUS_LowSpeedDeviceAttach 0x0200 //Read PortStatus, 1 connected device is low speed.
#define HC_RH_PORT_STATUS_ClearPortPower 0x0200 //Set PortStatus, shut port power off.
//There is no PortStatusChange bit
typedef union _HC_RH_PORT_STATUS
{
ULONG ul;
struct
{
USHORT PortStatus; //bit field indicating\changing port status
USHORT PortStatusChange; //bit field for indicating changes in port status
};
} HC_RH_PORT_STATUS, *PHC_RH_PORT_STATUS;
//
// Operational Registers
//
typedef struct _OHCI_OPERATIONAL_REGISTERS
{
//Control and Status
ULONG HcRevision; //LSB is BCD revision of OpenHCI
HC_CONTROL_REGISTER HcControl;
HC_COMMAND_STATUS HcCommandStatus;
ULONG HcInterruptStatus; //See HCINT_Xxxx macros above
ULONG HcInterruptEnable; //See HCINT_Xxxx macros above
ULONG HcInterruptDisable; //See HCINT_Xxxx macros above
//Memory Pointers
// All are pointers to physical memory. Excepting HcHCCA they are paragraph (16 bytes)
// aligned. HcHCCA is on 256 byte boundary at minimum, some controllers require more
// stringent alignmnet. Test by writing 0xFFFFFFFF and reading back to see how many
// of the least signficant bits are 0.
ULONG HcHCCA; //HCCA area
ULONG HcPeriodCurrentED; //Current ED being processed in (interrupt and isoch lists)
ULONG HcControlHeadED; //Head of ED list for control pipes
ULONG HcControlCurrentED; //Current location ED list for control pipes
ULONG HcBulkHeadED; //Head of ED list for bulk pipes
ULONG HcBulkCurrentED; //Current location ED list for bulk pipes
ULONG HcDoneHead; //Pointer list of completed TDs. Head of list is last completed.
//Frame Counter
HC_FRAME_INTERVAL HcFmInterval; //HC_FRAME_INTERVAL for comments
ULONG HcFmRemaining; //14 bit down counter of bits remaining in current frame
//high bit is a toggle, to sync with FrameInterval
ULONG HcFmNumber; //16-bit Frame Counter
ULONG HcPeriodicStart;//14-bit value calculated by HCD to reserve enough bandwidth
//for the interrupt and isoch ED list processing. It is the number
//of bits into the frame before moving to periodic processing.
ULONG HcLSThreshold; //12-bit value for minimum number of bits in frame for which to
//attempt transfering an 8 byte low-speed packet.
//Root Hub
// Registers which are involved with with the root hub emulation
HC_RH_DESCRIPTOR_A HcRhDescriptorA;
HC_RH_DESCRIPTOR_B HcRhDescriptorB;
HC_RH_STATUS HcRhStatus;
HC_RH_PORT_STATUS HcRhPortStatus[1]; //Variable length really, depends on count of hubs
} OHCI_OPERATIONAL_REGISTERS, *POHCI_OPERATIONAL_REGISTERS;
//
// This is not necessarily sizeof(OHCI_OPERATIONAL_REGISTERS).
// Rather it is the address space that it occupies in memory.
//
#define OHCI_OPERATIONAL_REGISTER_SIZE 0x1000
#endif //__OCHI_H__