1368 lines
46 KiB
C
1368 lines
46 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1993 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
openhci.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains the PRIVATE definitions for the
|
||
|
code that implements the OpenHCI Host Controller Driver for USB.
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Kernel & user mode
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
12-28-95 : created jfuller
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdarg.h"
|
||
|
#include "wdm.h"
|
||
|
|
||
|
#include "usbdi.h"
|
||
|
#include "hcdi.h"
|
||
|
#include "usbdlibi.h"
|
||
|
#include "usbdlib.h"
|
||
|
|
||
|
#include "dbg.h"
|
||
|
|
||
|
#ifndef OPENHCI_H
|
||
|
#define OPENHCI_H
|
||
|
// #define COMPAQ
|
||
|
// #define NEC
|
||
|
// #define CMD
|
||
|
// #define NSC //National Semiconductor
|
||
|
#define NEC_XXX
|
||
|
#define DISABLE_INT_DELAY_NO_INT 0
|
||
|
#define PREALLOCATE_DESCRIPTOR_MEMORY 1
|
||
|
#define PREALLOCATE_DESCRIPTOR_MEMORY_NUM_PAGES 2
|
||
|
|
||
|
#define RESOURCES_NOT_ON_IRP_STACK 0
|
||
|
|
||
|
#ifdef PNP_POWER
|
||
|
#define PnPEnabled() TRUE
|
||
|
#else
|
||
|
#define PnPEnabled() FALSE
|
||
|
#endif /* PNP_POWER */
|
||
|
|
||
|
#define HCD_PENDING_STATUS_SUBMITTING 0x40404001
|
||
|
#define HCD_PENDING_STATUS_SUBMITTED 0x40404002
|
||
|
#define HCD_PENDING_STATUS_QUEUED 0x40404003
|
||
|
|
||
|
//
|
||
|
// OpenHCI PCI Identification values
|
||
|
//
|
||
|
#define OpenHCI_PCI_BASE_CLASS 0x0C // base class is serial bus
|
||
|
#define OpenHCI_PCI_SUB_CLASS 0x03 // sub class is USB
|
||
|
#define OpenHCI_PCI_PROG_IF 0x10 // programming interface is OpenHCI
|
||
|
|
||
|
//
|
||
|
// Tag for memory allocations: 'OHCI'
|
||
|
//
|
||
|
#define OpenHCI_TAG 0x4943484F
|
||
|
|
||
|
//
|
||
|
// Eventually CacheCommon should determine if the platform snoops i/o cycles;
|
||
|
// for now, just cache memory allocated by HalAllocateCommonBuffer
|
||
|
|
||
|
#define CacheCommon TRUE
|
||
|
|
||
|
//
|
||
|
// Maximum length of name strings used in initialization code
|
||
|
//
|
||
|
|
||
|
#define NAME_MAX 256
|
||
|
#define NAME_STRING L"\\Device\\USB#"
|
||
|
/* 0 1234567 89012345 */
|
||
|
#define NAME_NO_POS 11
|
||
|
|
||
|
|
||
|
//
|
||
|
// highest physical address we can use
|
||
|
//
|
||
|
#define OpenHCI_HIGHEST_ADDRESS 0x000000FFFFFFFF;
|
||
|
|
||
|
//
|
||
|
// Maximum frame and packet overhead
|
||
|
//
|
||
|
#define MAXIMUM_OVERHEAD 210
|
||
|
|
||
|
#define OHCI_PAGE_SIZE 0x1000
|
||
|
// #define OHCI_PAGE_SIZE 0x20
|
||
|
#define OHCI_PAGE_SIZE_MASK (OHCI_PAGE_SIZE - 1)
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
#if !defined(FAKEPORTCHANGE)
|
||
|
#define FAKEPORTCHANGE 1
|
||
|
#endif
|
||
|
#else
|
||
|
#if !defined(FAKEPORTCHANGE)
|
||
|
#define FAKEPORTCHANGE 0
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#ifdef MAX_DEBUG
|
||
|
#define OHCI_DEFAULT_DEBUG_OUTPUT_LEVEL 0xFFFFFFFF
|
||
|
#else
|
||
|
//#define OHCI_DEFAULT_DEBUG_OUTPUT_LEVEL 0xFEAAFFEE // 0xF8A8888E
|
||
|
#define OHCI_DEFAULT_DEBUG_OUTPUT_LEVEL 0x00000000
|
||
|
#endif
|
||
|
|
||
|
#define MIN(_A_,_B_) (((_A_) < (_B_)) ? (_A_) : (_B_))
|
||
|
|
||
|
#define IoDecrementStackLocation(IRP) \
|
||
|
(IRP)->CurrentLocation++; \
|
||
|
(IRP)->Tail.Overlay.CurrentStackLocation++;
|
||
|
|
||
|
#define IoCopyStackToNextStack(IRP) \
|
||
|
{ \
|
||
|
PIO_STACK_LOCATION now, later; \
|
||
|
now = IoGetCurrentIrpStackLocation (IRP); \
|
||
|
later = IoGetNextIrpStackLocation (IRP); \
|
||
|
later->Parameters = now->Parameters; \
|
||
|
later->MajorFunction = now->MajorFunction; \
|
||
|
later->MinorFunction = now->MinorFunction; \
|
||
|
later->Flags = now->Flags; \
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// 7.1.1 HcRevision Register
|
||
|
// Definition of Host Controller Revision register
|
||
|
//
|
||
|
typedef union _HC_REVISION {
|
||
|
ULONG ul;
|
||
|
struct {
|
||
|
ULONG Rev:8;
|
||
|
ULONG :24;
|
||
|
};
|
||
|
} HC_REVISION, *PHC_REVISION;
|
||
|
|
||
|
|
||
|
//
|
||
|
// 7.1.2 HcControl Register
|
||
|
// Definition of Host Controller Control register
|
||
|
//
|
||
|
typedef union _HC_CONTROL {
|
||
|
ULONG ul;
|
||
|
struct {
|
||
|
ULONG ControlBulkServiceRatio:2;
|
||
|
ULONG PeriodicListEnable:1;
|
||
|
ULONG IsochronousEnable:1;
|
||
|
ULONG ControlListEnable:1;
|
||
|
ULONG BulkListEnable:1;
|
||
|
ULONG HostControllerFunctionalState:2;
|
||
|
ULONG InterruptRouting:1;
|
||
|
ULONG RemoteWakeupConnected:1;
|
||
|
ULONG RemoteWakeupEnable:1;
|
||
|
ULONG :21;
|
||
|
};
|
||
|
} HC_CONTROL, *PHC_CONTROL;
|
||
|
|
||
|
#define HcCtrl_CBSR_MASK 0x00000003L
|
||
|
#define HcCtrl_CBSR_1_to_1 0x00000000L
|
||
|
#define HcCtrl_CBSR_2_to_1 0x00000001L
|
||
|
#define HcCtrl_CBSR_3_to_1 0x00000002L
|
||
|
#define HcCtrl_CBSR_4_to_1 0x00000003L
|
||
|
#define HcCtrl_PeriodicListEnable 0x00000004L
|
||
|
#define HcCtrl_IsochronousEnable 0x00000008L
|
||
|
#define HcCtrl_ControlListEnable 0x00000010L
|
||
|
#define HcCtrl_BulkListEnable 0x00000020L
|
||
|
#define HcCtrl_ListEnableMask 0x00000038L
|
||
|
|
||
|
#define HcCtrl_HCFS_MASK 0x000000C0L
|
||
|
#define HcCtrl_HCFS_USBReset 0x00000000L
|
||
|
#define HcCtrl_HCFS_USBResume 0x00000040L
|
||
|
#define HcCtrl_HCFS_USBOperational 0x00000080L
|
||
|
#define HcCtrl_HCFS_USBSuspend 0x000000C0L
|
||
|
|
||
|
#define HcCtrl_InterruptRouting 0x00000100L
|
||
|
#define HcCtrl_RemoteWakeupConnected 0x00000200L
|
||
|
#define HcCtrl_RemoteWakeupEnable 0x00000400L
|
||
|
|
||
|
#define HcHCFS_USBReset 0x00000000
|
||
|
#define HcHCFS_USBResume 0x00000001
|
||
|
#define HcHCFS_USBOperational 0x00000002
|
||
|
#define HcHCFS_USBSuspend 0x00000003
|
||
|
|
||
|
//
|
||
|
// 7.1.3 HcCommandStatus Register
|
||
|
// Definition of Host Controller Command/Status register
|
||
|
//
|
||
|
typedef union _HC_COMMAND_STATUS {
|
||
|
ULONG ul; // use HcCmd flags below
|
||
|
struct {
|
||
|
ULONG HostControllerReset:1;
|
||
|
ULONG ControlListFilled:1;
|
||
|
ULONG BulkListFilled:1;
|
||
|
ULONG OwnershipChangeRequest:1;
|
||
|
ULONG :12;
|
||
|
ULONG SchedulingOverrunCount:2;
|
||
|
ULONG :14;
|
||
|
};
|
||
|
} HC_COMMAND_STATUS, *PHC_COMMAND_STATUS;
|
||
|
|
||
|
#define HcCmd_HostControllerReset 0x00000001
|
||
|
#define HcCmd_ControlListFilled 0x00000002
|
||
|
#define HcCmd_BulkListFilled 0x00000004
|
||
|
#define HcCmd_OwnershipChangeRequest 0x00000008
|
||
|
#define HcCmd_SOC_Mask 0x00030000
|
||
|
#define HcCmd_SOC_Offset 16
|
||
|
#define HcCmd_SOC_Mask_LowBits 0x00000003
|
||
|
|
||
|
//
|
||
|
// 7.3.1 HcFmInterval Register
|
||
|
// Definition of Host Controller Frame Interval register
|
||
|
//
|
||
|
typedef union _HC_FM_INTERVAL {
|
||
|
ULONG ul; // use HcFmI flags below
|
||
|
struct {
|
||
|
ULONG FrameInterval:14;
|
||
|
ULONG :2;
|
||
|
ULONG FSLargestDataPacket:15;
|
||
|
ULONG FrameIntervalToggle:1;
|
||
|
};
|
||
|
} HC_FM_INTERVAL, *PHC_FM_INTERVAL;
|
||
|
|
||
|
#define HcFmI_FRAME_INTERVAL_MASK 0x00003FFF
|
||
|
#define HcFmI_FS_LARGEST_DATA_PACKET_MASK 0x7FFF0000
|
||
|
#define HcFmI_FS_LARGEST_DATA_PACKET_SHIFT 16
|
||
|
#define HcFmI_FRAME_INTERVAL_TOGGLE 0x80000000
|
||
|
|
||
|
//
|
||
|
// 7.3.2 HcFmRemaining Register
|
||
|
// Definition of Host Controller Frame Remaining register
|
||
|
//
|
||
|
typedef union _HC_FM_REMAINING {
|
||
|
ULONG ul;
|
||
|
struct {
|
||
|
ULONG FrameRemaining:14;
|
||
|
ULONG :17;
|
||
|
ULONG FrameRemainingToggle:1;
|
||
|
};
|
||
|
} HC_FM_REMAINING, *PHC_FM_REMAINING;
|
||
|
|
||
|
//
|
||
|
// 7.4.1 HcRhDescriptorA Register
|
||
|
// Definition of Host Controller Root Hub DescriptorA register
|
||
|
//
|
||
|
typedef union _HC_RH_DESCRIPTOR_A {
|
||
|
ULONG ul;
|
||
|
struct {
|
||
|
ULONG NumberDownstreamPorts:8;
|
||
|
ULONG PowerSwitchingMode:1;
|
||
|
ULONG NoPowerSwitching:1;
|
||
|
ULONG :1;
|
||
|
ULONG OverCurrentProtectionMode:1;
|
||
|
ULONG NoOverCurrentProtection:1;
|
||
|
ULONG :11;
|
||
|
ULONG PowerOnToPowerGoodTime:8;
|
||
|
};
|
||
|
} HC_RH_DESCRIPTOR_A, *PHC_RH_DESCRIPTOR_A;
|
||
|
|
||
|
//
|
||
|
// 7.4.2 HcRhDescriptorB Register
|
||
|
// Definition of Host Controller Root Hub DescritorB register
|
||
|
//
|
||
|
typedef union _HC_RH_DESCRIPTOR_B {
|
||
|
ULONG ul;
|
||
|
struct {
|
||
|
USHORT DeviceRemovableMask;
|
||
|
USHORT PortPowerControlMask;
|
||
|
};
|
||
|
} HC_RH_DESCRIPTOR_B, *PHC_RH_DESCRIPTOR_B;
|
||
|
|
||
|
//
|
||
|
// Host Controler Hardware Registers as accessed in memory
|
||
|
//
|
||
|
typedef struct _HC_OPERATIONAL_REGISTER {
|
||
|
// 0 0x00 - 0,4,8,c
|
||
|
HC_REVISION HcRevision;
|
||
|
HC_CONTROL HcControl;
|
||
|
HC_COMMAND_STATUS HcCommandStatus;
|
||
|
ULONG HcInterruptStatus; // use HcInt flags below
|
||
|
// 1 0x10
|
||
|
ULONG HcInterruptEnable; // use HcInt flags below
|
||
|
ULONG HcInterruptDisable; // use HcInt flags below
|
||
|
ULONG HcHCCA; // physical pointer to Host Controller Communications Area
|
||
|
ULONG HcPeriodCurrentED; // physical ptr to current periodic ED
|
||
|
// 2 0x20
|
||
|
ULONG HcControlHeadED; // physical ptr to head of control list
|
||
|
ULONG HcControlCurrentED; // physical ptr to current control ED
|
||
|
ULONG HcBulkHeadED; // physical ptr to head of bulk list
|
||
|
ULONG HcBulkCurrentED; // physical ptr to current bulk ED
|
||
|
// 3 0x30
|
||
|
ULONG HcDoneHead; // physical ptr to internal done queue
|
||
|
HC_FM_INTERVAL HcFmInterval;
|
||
|
HC_FM_REMAINING HcFmRemaining;
|
||
|
ULONG HcFmNumber;
|
||
|
// 4 0x40
|
||
|
ULONG HcPeriodicStart;
|
||
|
ULONG HcLSThreshold;
|
||
|
HC_RH_DESCRIPTOR_A HcRhDescriptorA;
|
||
|
HC_RH_DESCRIPTOR_B HcRhDescriptorB;
|
||
|
// 5 0x50
|
||
|
ULONG HcRhStatus; // use HcRhS flags below
|
||
|
ULONG HcRhPortStatus[15]; // use HcRhPS flags below
|
||
|
} HC_OPERATIONAL_REGISTER, *PHC_OPERATIONAL_REGISTER;
|
||
|
|
||
|
//
|
||
|
// 7.1.4 HcInterrruptStatus Register
|
||
|
// 7.1.5 HcInterruptEnable Register
|
||
|
// 7.1.6 HcInterruptDisable Register
|
||
|
//
|
||
|
#define HcInt_SchedulingOverrun 0x00000001L
|
||
|
#define HcInt_WritebackDoneHead 0x00000002L
|
||
|
#define HcInt_StartOfFrame 0x00000004L
|
||
|
#define HcInt_ResumeDetected 0x00000008L
|
||
|
#define HcInt_UnrecoverableError 0x00000010L
|
||
|
#define HcInt_FrameNumberOverflow 0x00000020L
|
||
|
#define HcInt_RootHubStatusChange 0x00000040L
|
||
|
#define HcInt_OwnershipChange 0x40000000L
|
||
|
#define HcInt_MasterInterruptEnable 0x80000000L
|
||
|
|
||
|
//
|
||
|
// 7.4.3 HcRhStatus Register
|
||
|
//
|
||
|
#define HcRhS_LocalPowerStatus 0x00000001 // read only
|
||
|
#define HcRhS_OverCurrentIndicator 0x00000002 // read only
|
||
|
#define HcRhS_DeviceRemoteWakeupEnable 0x00008000 // read only
|
||
|
#define HcRhS_LocalPowerStatusChange 0x00010000 // read only
|
||
|
#define HcRhS_OverCurrentIndicatorChange 0x00020000 // read only
|
||
|
|
||
|
#define HcRhS_ClearGlobalPower 0x00000001 // write only
|
||
|
#define HcRhS_SetRemoteWakeupEnable 0x00008000 // write only
|
||
|
#define HcRhS_SetGlobalPower 0x00010000 // write only
|
||
|
#define HcRhS_ClearOverCurrentIndicatorChange 0x00020000 // write only
|
||
|
#define HcRhS_ClearRemoteWakeupEnable 0x80000000 // write only
|
||
|
|
||
|
//
|
||
|
// 7.4.4 HcRhPortStatus Register
|
||
|
//
|
||
|
#define HcRhPS_CurrentConnectStatus 0x00000001 // read only
|
||
|
#define HcRhPS_PortEnableStatus 0x00000002 // read only
|
||
|
#define HcRhPS_PortSuspendStatus 0x00000004 // read only
|
||
|
#define HcRhPS_PortOverCurrentIndicator 0x00000008 // read only
|
||
|
#define HcRhPS_PortResetStatus 0x00000010 // read only
|
||
|
#define HcRhPS_PortPowerStatus 0x00000100 // read only
|
||
|
#define HcRhPS_LowSpeedDeviceAttached 0x00000200 // read only
|
||
|
#define HcRhPS_ConnectStatusChange 0x00010000 // read only
|
||
|
#define HcRhPS_PortEnableStatusChange 0x00020000 // read only
|
||
|
#define HcRhPS_PortSuspendStatusChange 0x00040000 // read only
|
||
|
#define HcRhPS_OverCurrentIndicatorChange 0x00080000 // read only
|
||
|
#define HcRhPS_PortResetStatusChange 0x00100000 // read only
|
||
|
|
||
|
#define HcRhPS_ClearPortEnable 0x00000001 // write only
|
||
|
#define HcRhPS_SetPortEnable 0x00000002 // write only
|
||
|
#define HcRhPS_SetPortSuspend 0x00000004 // write only
|
||
|
#define HcRhPS_ClearPortSuspend 0x00000008 // write only
|
||
|
#define HcRhPS_SetPortReset 0x00000010 // write only
|
||
|
#define HcRhPS_SetPortPower 0x00000100 // write only
|
||
|
#define HcRhPS_ClearPortPower 0x00000200 // write only
|
||
|
#define HcRhPS_ClearConnectStatusChange 0x00010000 // write only
|
||
|
#define HcRhPS_ClearPortEnableStatusChange 0x00020000 // write only
|
||
|
#define HcRhPS_ClearPortSuspendStatusChange 0x00040000 // write only
|
||
|
#define HcRhPS_ClearPortOverCurrentChange 0x00080000 // write only
|
||
|
#define HcRhPS_ClearPortResetStatusChange 0x00100000 // write only
|
||
|
|
||
|
#define HcRhPS_RESERVED (~(HcRhPS_CurrentConnectStatus | \
|
||
|
HcRhPS_PortEnableStatus | \
|
||
|
HcRhPS_PortSuspendStatus | \
|
||
|
HcRhPS_PortOverCurrentIndicator | \
|
||
|
HcRhPS_PortResetStatus | \
|
||
|
HcRhPS_PortPowerStatus | \
|
||
|
HcRhPS_LowSpeedDeviceAttached | \
|
||
|
HcRhPS_ConnectStatusChange | \
|
||
|
HcRhPS_PortEnableStatusChange | \
|
||
|
HcRhPS_PortSuspendStatusChange | \
|
||
|
HcRhPS_OverCurrentIndicatorChange | \
|
||
|
HcRhPS_PortResetStatusChange \
|
||
|
))
|
||
|
|
||
|
//
|
||
|
// Host Controller Communications Area
|
||
|
//
|
||
|
typedef struct _HCCA_BLOCK {
|
||
|
ULONG HccaInterruptTable[32]; // physical pointer to interrupt lists
|
||
|
USHORT HccaFrameNumber; // 16-bit current frame number
|
||
|
USHORT HccaPad1; // When the HC updates
|
||
|
// HccaFrameNumber, it sets
|
||
|
// this word to zero.
|
||
|
ULONG HccaDoneHead; // pointer to done queue
|
||
|
ULONG Reserved[30]; // pad to 256 bytes
|
||
|
} HCCA_BLOCK, *PHCCA_BLOCK;
|
||
|
|
||
|
C_ASSERT(sizeof(HCCA_BLOCK) == 256);
|
||
|
|
||
|
#define HCCADoneHead_INT_FLAG 0x00000001 // bit set if other ints pending
|
||
|
|
||
|
//
|
||
|
// Host Controller Endpoint Descriptor Control DWORD
|
||
|
//
|
||
|
typedef union _HC_ENDPOINT_CONTROL {
|
||
|
ULONG Control; // use HcEDControl flags below
|
||
|
struct {
|
||
|
ULONG FunctionAddress:7;
|
||
|
ULONG EndpointNumber:4;
|
||
|
ULONG Direction:2; // use HcEDDirection flags below
|
||
|
ULONG LowSpeed:1;
|
||
|
ULONG sKip:1;
|
||
|
ULONG Isochronous:1;
|
||
|
ULONG MaxPacket:11;
|
||
|
ULONG Unused:5; //available for software use
|
||
|
};
|
||
|
} HC_ENDPOINT_CONTROL, *PHC_ENDPOINT_CONTROL;
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_ENDPOINT_CONTROL.Control
|
||
|
//
|
||
|
#define HcEDControl_MPS_MASK 0x07FF0000 // Maximum Packet Size field
|
||
|
#define HcEDControl_MPS_SHIFT 16 // Shift Count for MPS
|
||
|
#define HcEDControl_ISOCH 0x00008000 // Bit set for isochronous endpoints
|
||
|
#define HcEDControl_SKIP 0x00004000 // Bit tells hw to skip this endpoint
|
||
|
#define HcEDControl_LOWSPEED 0x00002000 // Bit set if device is a low speed device
|
||
|
#define HcEDControl_DIR_MASK 0x00001800 // Transfer direction field
|
||
|
#define HcEDControl_DIR_DEFER 0x00000000 // Defer direction select to TD (Control Endpoints)
|
||
|
#define HcEDControl_DIR_OUT 0x00000800 // Direction is from host to device
|
||
|
#define HcEDControl_DIR_IN 0x00001000 // Direction is from device to host
|
||
|
#define HcEDControl_EN_MASK 0x00000780 // Endpoint Number field
|
||
|
#define HcEDControl_EN_SHIFT 7 // Shift Count for EN
|
||
|
#define HcEDControl_FA_MASK 0x0000007F // Function Address field
|
||
|
#define HcEDControl_FA_SHIFT 0 // Shift Count for FA
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_ENDPOINT_CONTROL.Direction
|
||
|
//
|
||
|
#define HcEDDirection_Defer 0 // Defer direction to TD (Control Endpoints)
|
||
|
#define HcEDDirection_Out 1 // Direction from host to device
|
||
|
#define HcEDDirection_In 2 // Direction from device to host
|
||
|
|
||
|
//
|
||
|
// Host Controller Endpoint Descriptor, refer to Section 4.2, Endpoint Descriptor
|
||
|
//
|
||
|
typedef struct _HC_ENDPOINT_DESCRIPTOR {
|
||
|
HC_ENDPOINT_CONTROL; // dword 0
|
||
|
ULONG TailP; //physical pointer to HC_TRANSFER_DESCRIPTOR
|
||
|
volatile ULONG HeadP; //flags + phys ptr to HC_TRANSFER_DESCRIPTOR
|
||
|
ULONG NextED; //phys ptr to HC_ENDPOINT_DESCRIPTOR
|
||
|
} HC_ENDPOINT_DESCRIPTOR, *PHC_ENDPOINT_DESCRIPTOR;
|
||
|
|
||
|
C_ASSERT(sizeof(HC_ENDPOINT_DESCRIPTOR) == 16);
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_ENDPOINT_DESCRIPTOR.HeadP
|
||
|
//
|
||
|
#define HcEDHeadP_FLAGS 0x0000000F //mask for flags in HeadP
|
||
|
#define HcEDHeadP_HALT 0x00000001 //hardware stopped bit
|
||
|
#define HcEDHeadP_CARRY 0x00000002 //hardware toggle carry bit
|
||
|
|
||
|
//
|
||
|
// HCD Isochronous offset/status words
|
||
|
//
|
||
|
typedef union _HC_OFFSET_PSW {
|
||
|
struct {
|
||
|
USHORT Offset:13; // Offset within two pages of packet buffer
|
||
|
USHORT Ones:3; // should be 111b when in Offset format
|
||
|
};
|
||
|
struct {
|
||
|
USHORT Size:11; // Size of packet received
|
||
|
USHORT :1; // reserved
|
||
|
USHORT ConditionCode:4; // use HcCC flags below
|
||
|
};
|
||
|
USHORT PSW; // use HcPSW flags below
|
||
|
} HC_OFFSET_PSW, *PHC_OFFSET_PSW;
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_OFFSET_PSW.PSW
|
||
|
//
|
||
|
#define HcPSW_OFFSET_MASK 0x0FFF // Packet buffer offset field
|
||
|
#define HcPSW_SECOND_PAGE 0x1000 // Is this packet on 2nd page
|
||
|
#define HcPSW_ONES 0xE000 // The ones for Offset form
|
||
|
#define HcPSW_CONDITION_CODE_MASK 0xF000 // Packet ConditionCode field
|
||
|
#define HcPSW_CONDITION_CODE_SHIFT 12 // shift count for Code
|
||
|
#define HcPSW_RETURN_SIZE 0x07FF // The size field.
|
||
|
|
||
|
//
|
||
|
// HCD Transfer Descriptor Control DWord
|
||
|
//
|
||
|
typedef union _HC_TRANSFER_CONTROL {
|
||
|
ULONG Control; // use HcTDControl flags below
|
||
|
struct _HC_GENERAL_TD_CONTROL{
|
||
|
ULONG :16; // available for s/w use in GTD
|
||
|
ULONG IsochFlag:1; // should be 0 for GTD, s/w flag
|
||
|
ULONG :1; // available for s/w use
|
||
|
ULONG ShortXferOk:1; // if set don't report error on short transfer
|
||
|
ULONG Direction:2; // use HcTDDirection flags below
|
||
|
ULONG IntDelay:3; // use HcTDIntDelay flags below
|
||
|
ULONG Toggle:2; // use HcTDToggle flags below
|
||
|
ULONG ErrorCount:2;
|
||
|
ULONG ConditionCode:4; // use HcCC flags below
|
||
|
};
|
||
|
struct _HC_ISOCHRONOUS_TD_CONTROL{
|
||
|
ULONG StartingFrame:16;
|
||
|
ULONG Isochronous:1; // should be 1 for ITD, s/w flag
|
||
|
ULONG :1; // available for s/w use
|
||
|
ULONG :3; // available for s/w use in ITD
|
||
|
ULONG :3; // IntDelay
|
||
|
ULONG FrameCount:3; // one less than number of frames described in ITD
|
||
|
ULONG :1; // available for s/w use in ITD
|
||
|
ULONG :4; // ConditionCode
|
||
|
};
|
||
|
} HC_TRANSFER_CONTROL, *PHC_TRANSFER_CONTROL;
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_TRANSFER_CONTROL.Control
|
||
|
//
|
||
|
#define HcTDControl_STARTING_FRAME 0x0000FFFF // mask for starting frame (Isochronous)
|
||
|
#define HcTDControl_ISOCHRONOUS 0x00010000 // 1 for Isoch TD, 0 for General TD
|
||
|
#define HcTDControl_SHORT_XFER_OK 0x00040000 // 0 if short transfers are errors
|
||
|
#define HcTDControl_DIR_MASK 0x00180000 // Transfer direction field
|
||
|
#define HcTDControl_DIR_SETUP 0x00000000 // direction is setup packet from host to device
|
||
|
#define HcTDControl_DIR_OUT 0x00080000 // direction is from host to device
|
||
|
#define HcTDControl_DIR_IN 0x00100000 // direction is from device to host
|
||
|
#define HcTDControl_INT_DELAY_MASK 0x00E00000 // Interrupt Delay field
|
||
|
#define HcTDControl_INT_DELAY_0_MS 0x00000000 // Interrupt at end of frame TD is completed
|
||
|
#define HcTDControl_INT_DELAY_1_MS 0x00200000 // Interrupt no later than end of 1st frame after TD is completed
|
||
|
#define HcTDControl_INT_DELAY_2_MS 0x00400000 // Interrupt no later than end of 2nd frame after TD is completed
|
||
|
#define HcTDControl_INT_DELAY_3_MS 0x00600000 // Interrupt no later than end of 3rd frame after TD is completed
|
||
|
#define HcTDControl_INT_DELAY_4_MS 0x00800000 // Interrupt no later than end of 4th frame after TD is completed
|
||
|
#define HcTDControl_INT_DELAY_5_MS 0x00A00000 // Interrupt no later than end of 5th frame after TD is completed
|
||
|
#define HcTDControl_INT_DELAY_6_MS 0x00C00000 // Interrupt no later than end of 6th frame after TD is completed
|
||
|
|
||
|
#ifdef NSC
|
||
|
#define HcTDControl_INT_DELAY_NO_INT 0x00C00000 // Almost infinity but not yet quite.
|
||
|
#elif DISABLE_INT_DELAY_NO_INT
|
||
|
#define HcTDControl_INT_DELAY_NO_INT 0x00000000 // Interrupt at the completion of all packets.
|
||
|
#else
|
||
|
#define HcTDControl_INT_DELAY_NO_INT 0x00E00000 // Do not cause an interrupt for normal completion of this TD
|
||
|
#endif
|
||
|
|
||
|
#define HcTDControl_FRAME_COUNT_MASK 0x07000000 // mask for FrameCount field (Isochronous)
|
||
|
#define HcTDControl_FRAME_COUNT_SHIFT 24 // shift count for FrameCount (Isochronous)
|
||
|
#define HcTDControl_FRAME_COUNT_MAX 8 // Max number of for frame count per TD
|
||
|
#define HcTDControl_TOGGLE_MASK 0x03000000 // mask for Toggle control field
|
||
|
#define HcTDControl_TOGGLE_FROM_ED 0x00000000 // get data toggle from CARRY field of ED
|
||
|
#define HcTDControl_TOGGLE_DATA0 0x02000000 // use DATA0 for data PID
|
||
|
#define HcTDControl_TOGGLE_DATA1 0x03000000 // use DATA1 for data PID
|
||
|
#define HcTDControl_ERROR_COUNT 0x0C000000 // mask for Error Count field
|
||
|
#define HcTDControl_CONDITION_CODE_MASK 0xF0000000 // mask for ConditionCode field
|
||
|
#define HcTDControl_CONDITION_CODE_SHIFT 28 // shift count for ConditionCode
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_TRANSFER_CONTROL.Direction
|
||
|
//
|
||
|
#define HcTDDirection_Setup 0 // setup packet from host to device
|
||
|
#define HcTDDirection_Out 1 // direction from host to device
|
||
|
#define HcTDDirection_In 2 // direction from device to host
|
||
|
|
||
|
//
|
||
|
// Definitions for Hc_TRANSFER_CONTROL.IntDelay
|
||
|
//
|
||
|
#define HcTDIntDelay_0ms 0 // interrupt at end of frame TD is completed
|
||
|
#define HcTDIntDelay_1ms 1 // Interrupt no later than end of 1st frame after TD is completed
|
||
|
#define HcTDIntDelay_2ms 2 // Interrupt no later than end of 2nd frame after TD is completed
|
||
|
#define HcTDIntDelay_3ms 3 // Interrupt no later than end of 3rd frame after TD is completed
|
||
|
#define HcTDIntDelay_4ms 4 // Interrupt no later than end of 4th frame after TD is completed
|
||
|
#define HcTDIntDelay_5ms 5 // Interrupt no later than end of 5th frame after TD is completed
|
||
|
#define HcTDIntDelay_6ms 6 // Interrupt no later than end of 6th frame after TD is completed
|
||
|
#define HcTDIntDelay_NoInterrupt 7 // do not generate interrupt for normal completion of this TD
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_TRANSFER_CONTROL.Toggle
|
||
|
//
|
||
|
#define HcTDToggle_FromEd 0 // get toggle for Endpoint Descriptor toggle CARRY bit
|
||
|
#define HcTDToggle_Data0 2 // use Data0 PID
|
||
|
#define HcTDToggle_Data1 3 // use Data1 PID
|
||
|
|
||
|
//
|
||
|
// Definitions for HC_TRANSFER_CONTROL.ConditionCode and HC_OFFSET_PSW.ConditionCode
|
||
|
//
|
||
|
#define HcCC_NoError 0x0UL
|
||
|
#define HcCC_CRC 0x1UL
|
||
|
#define HcCC_BitStuffing 0x2UL
|
||
|
#define HcCC_DataToggleMismatch 0x3UL
|
||
|
#define HcCC_Stall 0x4UL
|
||
|
#define HcCC_DeviceNotResponding 0x5UL
|
||
|
#define HcCC_PIDCheckFailure 0x6UL
|
||
|
#define HcCC_UnexpectedPID 0x7UL
|
||
|
#define HcCC_DataOverrun 0x8UL
|
||
|
#define HcCC_DataUnderrun 0x9UL
|
||
|
// 0xA // reserved
|
||
|
// 0xB // reserved
|
||
|
#define HcCC_BufferOverrun 0xCUL
|
||
|
#define HcCC_BufferUnderrun 0xDUL
|
||
|
#define HcCC_NotAccessed 0xEUL
|
||
|
// 0xF // this also means NotAccessed
|
||
|
|
||
|
//
|
||
|
// Host Controller Transfer Descriptor, refer to Section 4.3, Transfer Descriptors
|
||
|
//
|
||
|
typedef struct _HC_TRANSFER_DESCRIPTOR {
|
||
|
HC_TRANSFER_CONTROL; // dword 0
|
||
|
ULONG CBP; // phys ptr to start of buffer
|
||
|
ULONG NextTD; // phys ptr to HC_TRANSFER_DESCRIPTOR
|
||
|
ULONG BE; // phys ptr to end of buffer (last byte)
|
||
|
HC_OFFSET_PSW Packet[8]; // isoch & Control packets
|
||
|
} HC_TRANSFER_DESCRIPTOR, *PHC_TRANSFER_DESCRIPTOR;
|
||
|
|
||
|
//
|
||
|
// HCD Endpoint Descriptor
|
||
|
//
|
||
|
typedef struct _HCD_ENDPOINT_DESCRIPTOR {
|
||
|
HC_ENDPOINT_DESCRIPTOR HcED;
|
||
|
ULONG Pad[4]; // make Physical Address the same as in HCD_TRANSFER_DESCRIPTOR
|
||
|
ULONG PhysicalAddress;
|
||
|
|
||
|
UCHAR ListIndex;
|
||
|
UCHAR PauseFlag;
|
||
|
UCHAR Flags;
|
||
|
UCHAR Reserved[1]; // fill out to 64 bytes
|
||
|
|
||
|
LIST_ENTRY Link;
|
||
|
struct _HCD_ENDPOINT *Endpoint;
|
||
|
ULONG ReclamationFrame;
|
||
|
LIST_ENTRY PausedLink;
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
ULONG Pad24[9]; // file out to 128 bytes
|
||
|
#endif
|
||
|
} HCD_ENDPOINT_DESCRIPTOR, *PHCD_ENDPOINT_DESCRIPTOR;
|
||
|
|
||
|
C_ASSERT((sizeof(HCD_ENDPOINT_DESCRIPTOR) == 64) ||
|
||
|
(sizeof(HCD_ENDPOINT_DESCRIPTOR) == 128));
|
||
|
|
||
|
// Values for HCD_ENDPOINT_DESCRIPTOR->PauseFlag
|
||
|
//
|
||
|
// Used by:
|
||
|
//
|
||
|
// OpenHCI_CancelTDsForED()
|
||
|
// OpenHCI_PauseED()
|
||
|
// OpenHCI_CloseEndpoint()
|
||
|
//
|
||
|
|
||
|
// Normal state. If the endpoint is in this state, OpenHCI_PauseED()
|
||
|
// will set the endpoint sKip bit, else the sKip bit is already set.
|
||
|
//
|
||
|
#define HCD_ED_PAUSE_NOT_PAUSED 0
|
||
|
|
||
|
// Set when OpenHCI_PauseED() is called, which is called either by
|
||
|
// OpenHCI_CancelTransfer() or by OpenHCI_AbortEndpoint().
|
||
|
//
|
||
|
#define HCD_ED_PAUSE_NEEDED 1
|
||
|
|
||
|
// Set when OpenHCI_CancelTDsForED() starts running. If the endpoint is
|
||
|
// still in this state after OpenHCI_CancelTDsForED() has made a pass through
|
||
|
// all of the requests queued on the endpoint, the pause is complete and
|
||
|
// the state is set back to HCD_ED_PAUSE_NOT_PAUSED and the sKip is cleared.
|
||
|
// Else the state is set back to HCD_ED_PAUSE_PROCESSING again and another
|
||
|
// pass is made through all of the requests queued on the endpoints.
|
||
|
//
|
||
|
#define HCD_ED_PAUSE_PROCESSING 2
|
||
|
|
||
|
|
||
|
//
|
||
|
// HCD Transfer Descriptor
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// HCD_TRANSFER_DESCRIPTOR and HCD_ENDPOINT_DESCRIPTOR structures are
|
||
|
// allocated from a common pool and share the Flags field.
|
||
|
//
|
||
|
|
||
|
#define TD_FLAG_INUSE 0x01 // Indicates that the structure is allocated
|
||
|
#define TD_FLAG_IS_ED 0x80 // Indicates that the structure is an ED
|
||
|
|
||
|
|
||
|
// This structure MUST be exactly 64 or 128 bytes long
|
||
|
// we use 128 byte EDs for the 64 bit platform
|
||
|
|
||
|
typedef struct _HCD_TRANSFER_DESCRIPTOR {
|
||
|
HC_TRANSFER_DESCRIPTOR HcTD; /* first 16 bytes */
|
||
|
ULONG PhysicalAddress;
|
||
|
|
||
|
UCHAR BaseIsocURBOffset;
|
||
|
BOOLEAN Canceled;
|
||
|
UCHAR Flags;
|
||
|
UCHAR Reserved[1]; // fill out to 64 bytes
|
||
|
|
||
|
LIST_ENTRY RequestList; /* list of TDs for a req */
|
||
|
struct _HCD_TRANSFER_DESCRIPTOR *NextHcdTD;
|
||
|
PHCD_URB UsbdRequest;
|
||
|
struct _HCD_ENDPOINT *Endpoint;
|
||
|
ULONG TransferCount;
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
ULONG64 _SortNext;
|
||
|
ULONG Pad22[8]; // fill out to 128 bytes
|
||
|
#endif
|
||
|
} HCD_TRANSFER_DESCRIPTOR, *PHCD_TRANSFER_DESCRIPTOR;
|
||
|
|
||
|
C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) == 64) ||
|
||
|
(sizeof(HCD_TRANSFER_DESCRIPTOR) == 128));
|
||
|
|
||
|
C_ASSERT(sizeof(HCD_ENDPOINT_DESCRIPTOR) == sizeof(HCD_TRANSFER_DESCRIPTOR));
|
||
|
|
||
|
C_ASSERT(FIELD_OFFSET(HCD_ENDPOINT_DESCRIPTOR, PhysicalAddress) ==
|
||
|
FIELD_OFFSET(HCD_TRANSFER_DESCRIPTOR, PhysicalAddress));
|
||
|
|
||
|
C_ASSERT(FIELD_OFFSET(HCD_ENDPOINT_DESCRIPTOR, Flags) ==
|
||
|
FIELD_OFFSET(HCD_TRANSFER_DESCRIPTOR, Flags));
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
#define SortNext _SortNext
|
||
|
#else
|
||
|
#define SortNext HcTD.NextTD
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// HCD Endpoint control structure
|
||
|
//
|
||
|
|
||
|
// set when ep is closed successfully
|
||
|
#define EP_CLOSED 0x00000001
|
||
|
// set to if the root hub code owns this ep
|
||
|
#define EP_ROOT_HUB 0x00000002
|
||
|
// need to abort all transfers for this endpoint
|
||
|
#define EP_ABORT 0x00000004
|
||
|
// endpoint needs to be freed
|
||
|
#define EP_FREE 0x00000008
|
||
|
// endpoint has had no transfers submitted,
|
||
|
// restored on reset
|
||
|
#define EP_VIRGIN 0x00000020
|
||
|
// limit endpoint to one outstanding TD
|
||
|
#define EP_ONE_TD 0x00000040
|
||
|
// in active list
|
||
|
#define EP_IN_ACTIVE_LIST 0x00000080
|
||
|
|
||
|
|
||
|
#define SET_EPFLAG(ep, flag) ((ep)->EpFlags |= (flag))
|
||
|
#define CLR_EPFLAG(ep, flag) ((ep)->EpFlags &= ~(flag))
|
||
|
|
||
|
typedef struct _HCD_ENDPOINT {
|
||
|
ULONG Sig;
|
||
|
PHCD_ENDPOINT_DESCRIPTOR HcdED;
|
||
|
PHCD_TRANSFER_DESCRIPTOR HcdHeadP;
|
||
|
PHCD_TRANSFER_DESCRIPTOR HcdTailP;
|
||
|
|
||
|
ULONG EpFlags;
|
||
|
UCHAR Pad[3];
|
||
|
UCHAR Rate;
|
||
|
|
||
|
LIST_ENTRY RequestQueue; // Protected by QueueLock
|
||
|
LIST_ENTRY EndpointListEntry;
|
||
|
LONG EndpointStatus; // Requests currently on HW
|
||
|
LONG MaxRequest; // Max requests allowed on HW
|
||
|
|
||
|
UCHAR Type;
|
||
|
UCHAR ListIndex;
|
||
|
USHORT Bandwidth;
|
||
|
|
||
|
struct _HCD_DEVICE_DATA *DeviceData;
|
||
|
|
||
|
HC_ENDPOINT_CONTROL; // copy of control that is/will be in
|
||
|
|
||
|
ULONG DescriptorsReserved;
|
||
|
KSPIN_LOCK QueueLock; // QueueLock protects RequestQueue
|
||
|
|
||
|
ULONG NextIsoFreeFrame;
|
||
|
ULONG MaxTransfer;
|
||
|
PVOID TrueTail;
|
||
|
PIRP AbortIrp;
|
||
|
} HCD_ENDPOINT, *PHCD_ENDPOINT;
|
||
|
|
||
|
//
|
||
|
// Each Host Controller Endpoint Descriptor is also doubly linked into a list tracked by HCD.
|
||
|
// Each ED queue is managed via an HCD_ED_LIST
|
||
|
//
|
||
|
typedef struct _HCD_ED_LIST {
|
||
|
LIST_ENTRY Head;
|
||
|
PULONG PhysicalHead;
|
||
|
USHORT Bandwidth;
|
||
|
UCHAR Next;
|
||
|
BOOLEAN HcRegister; // PhysicalHead is in a Host Controller register
|
||
|
} HCD_ED_LIST, *PHCD_ED_LIST;
|
||
|
|
||
|
//
|
||
|
// The different ED lists are as follows.
|
||
|
//
|
||
|
#define ED_INTERRUPT_1ms 0
|
||
|
#define ED_INTERRUPT_2ms 1
|
||
|
#define ED_INTERRUPT_4ms 3
|
||
|
#define ED_INTERRUPT_8ms 7
|
||
|
#define ED_INTERRUPT_16ms 15
|
||
|
#define ED_INTERRUPT_32ms 31
|
||
|
#define ED_CONTROL 63
|
||
|
#define ED_BULK 64
|
||
|
#define ED_ISOCHRONOUS 0 // same as 1ms interrupt queue
|
||
|
#define NO_ED_LISTS 65
|
||
|
#define ED_EOF 0xff
|
||
|
|
||
|
//
|
||
|
// HCD Descriptor Page List Entry data structure.
|
||
|
//
|
||
|
// These entries are used to link together the common buffer pages that are
|
||
|
// allocated to hold TD and ED data structures. In addition, the HCCA and the
|
||
|
// static EDs for the interrupt endpoint polling interval tree are contained
|
||
|
// in the first common buffer page that is allocated.
|
||
|
//
|
||
|
|
||
|
typedef struct _PAGE_LIST_ENTRY *PPAGE_LIST_ENTRY;
|
||
|
|
||
|
typedef struct _PAGE_LIST_ENTRY {
|
||
|
PPAGE_LIST_ENTRY NextPage; // NULL terminated list
|
||
|
ULONG BufferSize; // Allocated buffer size
|
||
|
PHYSICAL_ADDRESS PhysAddr; // Base phys address of page
|
||
|
PHYSICAL_ADDRESS FirstTDPhys; // Phys addr of the first TD
|
||
|
PHYSICAL_ADDRESS LastTDPhys; // Phys addr of the last TD
|
||
|
PCHAR VirtAddr; // Base virt address of page
|
||
|
PHCD_TRANSFER_DESCRIPTOR FirstTDVirt; // Virt addr of the first TD
|
||
|
PHCD_TRANSFER_DESCRIPTOR LastTDVirt; // Virt Addr of the last TD
|
||
|
} PAGE_LIST_ENTRY, *PPAGE_LIST_ENTRY;
|
||
|
|
||
|
|
||
|
//values for HcFlags
|
||
|
#define HC_FLAG_REMOTE_WAKEUP_CONNECTED 0x00000001
|
||
|
#define HC_FLAG_LEGACY_BIOS_DETECTED 0x00000002
|
||
|
#define HC_FLAG_SLOW_BULK_ENABLE 0x00000004
|
||
|
#define HC_FLAG_SHUTDOWN 0x00000008 // not really used
|
||
|
#define HC_FLAG_MAP_SX_TO_D3 0x00000010
|
||
|
#define HC_FLAG_IDLE 0x00000020
|
||
|
#define HC_FLAG_DISABLE_IDLE_CHECK 0x00000040
|
||
|
#define HC_FLAG_DEVICE_STARTED 0x00000080
|
||
|
#define HC_FLAG_LOST_POWER 0x00000100
|
||
|
#define HC_FLAG_DISABLE_IDLE_MODE 0x00000200
|
||
|
#define HC_FLAG_USE_HYDRA_HACK 0x00000400
|
||
|
#define HC_FLAG_IN_DPC 0x00000800
|
||
|
#define HC_FLAG_SUSPEND_NEXT_D3 0x00001000
|
||
|
#define HC_FLAG_LIST_FIX_ENABLE 0x00002000
|
||
|
#define HC_FLAG_HUNG_CHECK_ENABLE 0x00004000
|
||
|
|
||
|
#define PENDING_TD_LIST_SIZE 1000
|
||
|
|
||
|
//
|
||
|
// HCD Device Data == Device Extention data
|
||
|
//
|
||
|
typedef struct _HCD_DEVICE_DATA {
|
||
|
UCHAR UsbdWorkArea[sizeof(USBD_EXTENSION)];
|
||
|
|
||
|
ULONG DebugLevel;
|
||
|
ULONG DeviceNameHandle; // handle passed to USBD to generate device name
|
||
|
ULONG HcFlags;
|
||
|
KSPIN_LOCK InterruptSpin; // Spinlock for interrupt
|
||
|
|
||
|
PDEVICE_OBJECT DeviceObject; // point back to device object
|
||
|
PDMA_ADAPTER AdapterObject; // point to our adapter object
|
||
|
ULONG NumberOfMapRegisters;// max number of map registers per transfer
|
||
|
PKINTERRUPT InterruptObject; // Pointer to interrupt object.
|
||
|
|
||
|
KDPC IsrDPC;
|
||
|
PHC_OPERATIONAL_REGISTER HC; // pointer to hw registers
|
||
|
ULONG HClength; // save length for MmUnmapIoSpace
|
||
|
PHCCA_BLOCK HCCA; // pointer to shared memory
|
||
|
KSPIN_LOCK EDListSpin;
|
||
|
|
||
|
// our pool of descriptors
|
||
|
SINGLE_LIST_ENTRY FreeDescriptorList;
|
||
|
ULONG FreeDescriptorCount;
|
||
|
PPAGE_LIST_ENTRY PageList; // pages aquired for descriptors
|
||
|
LIST_ENTRY StalledEDReclamation;
|
||
|
LIST_ENTRY RunningEDReclamation;
|
||
|
LIST_ENTRY PausedEDRestart;
|
||
|
LIST_ENTRY ActiveEndpointList; // list of
|
||
|
// endpoints that
|
||
|
// processing
|
||
|
LONG HcDma;
|
||
|
HCD_ED_LIST EDList[NO_ED_LISTS];
|
||
|
|
||
|
HC_CONTROL CurrentHcControl;
|
||
|
HC_CONTROL ListEnablesAtNextSOF;
|
||
|
|
||
|
HC_FM_INTERVAL OriginalInterval;
|
||
|
ULONG FrameHighPart;
|
||
|
ULONG AvailableBandwidth;
|
||
|
ULONG MaxBandwidthInUse;
|
||
|
|
||
|
ULONG ControlSav;
|
||
|
ULONG BulkSav;
|
||
|
ULONG HcHCCASav;
|
||
|
|
||
|
ULONG LostDoneHeadCount; // Diagnostic aid
|
||
|
ULONG ResurrectHCCount; // Diagnostic aid
|
||
|
ULONG FrozenHcDoneHead;
|
||
|
ULONG LastHccaDoneHead;
|
||
|
ULONGLONG LastDeadmanTime;
|
||
|
|
||
|
KSPIN_LOCK DescriptorsSpin;
|
||
|
KSPIN_LOCK ReclamationSpin;
|
||
|
KSPIN_LOCK PausedSpin;
|
||
|
KSPIN_LOCK HcFlagSpin;
|
||
|
KSPIN_LOCK PageListSpin;
|
||
|
KSPIN_LOCK HcDmaSpin;
|
||
|
|
||
|
LARGE_INTEGER LastIdleTime;
|
||
|
LONG IdleTime;
|
||
|
|
||
|
struct
|
||
|
{ /* A context structure between Isr and Dpc */
|
||
|
ULONG ContextInfo;
|
||
|
ULONG Frame;
|
||
|
} IsrDpc_Context;
|
||
|
|
||
|
BOOLEAN InterruptShare;
|
||
|
UCHAR Pad3[3];
|
||
|
|
||
|
PHYSICAL_ADDRESS cardAddress;
|
||
|
PHCD_ENDPOINT RootHubControl;
|
||
|
PHCD_ENDPOINT RootHubInterrupt; // root hub interrupt endpoint (EP 1)
|
||
|
UCHAR RootHubAddress; // device address of root hub (starts as 0)
|
||
|
ULONG PortsSuspendedAtSuspend;
|
||
|
ULONG PortsEnabledAtSuspend;
|
||
|
|
||
|
DEVICE_POWER_STATE CurrentDevicePowerState;
|
||
|
// When we suspend, the states of the ports are not kept by the host
|
||
|
// controller through the resume. We have to find out what the states
|
||
|
// are and put them back. These are bit masks of the ports that are
|
||
|
// either set enabled or suspended.
|
||
|
//
|
||
|
UCHAR RootHubConfig;
|
||
|
UCHAR NumberOfPorts;
|
||
|
UCHAR Pad2[1];
|
||
|
UCHAR ZeroLoadEndpoint_AddrHolder;
|
||
|
|
||
|
USHORT VendorID;
|
||
|
USHORT DeviceID;
|
||
|
|
||
|
UCHAR RevisionID;
|
||
|
UCHAR Pad[3];
|
||
|
|
||
|
PDEVICE_OBJECT RealPhysicalDeviceObject;
|
||
|
PDEVICE_OBJECT TopOfStackPhysicalDeviceObject;
|
||
|
|
||
|
KTIMER DeadmanTimer;
|
||
|
KDPC DeadmanTimerDPC;
|
||
|
|
||
|
#define ZERO_LOAD_ENDPOINT(DeviceData) \
|
||
|
((PVOID) (&(DeviceData)->ZeroLoadEndpoint_AddrHolder))
|
||
|
//
|
||
|
// We need a memory location that will not be used by any other
|
||
|
// pointer so that we can uniquely identify an endpoint on which there
|
||
|
// is a max packet size of zero. AKA one with no load.
|
||
|
//
|
||
|
|
||
|
LONG OpenCloseSync; // Debugging tool to insure serial
|
||
|
// _OpenEndpoint and _CloseEndpoint
|
||
|
|
||
|
ULONG FakePortChange; // Per port bitmap
|
||
|
ULONG FakePortDisconnect; // Per port bitmap
|
||
|
|
||
|
|
||
|
} HCD_DEVICE_DATA, *PHCD_DEVICE_DATA;
|
||
|
|
||
|
|
||
|
typedef struct _OHCI_RESOURCES {
|
||
|
ULONG InterruptVector;
|
||
|
KIRQL InterruptLevel;
|
||
|
KAFFINITY Affinity;
|
||
|
BOOLEAN ShareIRQ;
|
||
|
KINTERRUPT_MODE InterruptMode;
|
||
|
} OHCI_RESOURCES, *POHCI_RESOURCES;
|
||
|
|
||
|
|
||
|
#define OHCI_MAP_INIT 0x01
|
||
|
|
||
|
typedef struct _MAP_CONTEXT {
|
||
|
BOOLEAN Mapped;
|
||
|
UCHAR Flags;
|
||
|
UCHAR Pad[2];
|
||
|
PHYSICAL_ADDRESS PhysAddress;
|
||
|
ULONG LengthMapped;
|
||
|
PVOID CurrentVa;
|
||
|
PVOID MapRegisterBase;
|
||
|
ULONG TotalLength;
|
||
|
} MAP_CONTEXT, *PMAP_CONTEXT;
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct _KeSync_HcControl
|
||
|
{
|
||
|
PHCD_DEVICE_DATA DeviceData;
|
||
|
HC_CONTROL NewHcControl;
|
||
|
|
||
|
} KeSynch_HcControl, *PKeSynch_HcControl;
|
||
|
|
||
|
#ifdef DEBUG_LOG
|
||
|
|
||
|
#ifdef IRP_LOG
|
||
|
#define IRP_IN(i) OHCI_LogIrp((i), 1)
|
||
|
#define IRP_OUT(i) OHCI_LogIrp((i), 0)
|
||
|
#else
|
||
|
#define IRP_IN(i)
|
||
|
#define IRP_OUT(i)
|
||
|
#endif
|
||
|
|
||
|
#define LOGENTRY(m, sig, info1, info2, info3) \
|
||
|
OHCI_Debug_LogEntry(m, sig, (ULONG_PTR)info1, \
|
||
|
(ULONG_PTR)info2, \
|
||
|
(ULONG_PTR)info3)
|
||
|
|
||
|
#define LOGIRQL() LOGENTRY(G, 'IRQL', KeGetCurrentIrql(), 0, 0);
|
||
|
|
||
|
VOID
|
||
|
OHCI_Debug_LogEntry(
|
||
|
IN ULONG Mask,
|
||
|
IN ULONG Sig,
|
||
|
IN ULONG_PTR Info1,
|
||
|
IN ULONG_PTR Info2,
|
||
|
IN ULONG_PTR Info3
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OHCI_LogInit(
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OHCI_LogFree(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define LOGENTRY(mask, sig, info1, info2, info3)
|
||
|
#define OHCI_LogInit()
|
||
|
#define OHCI_LogFree()
|
||
|
#define LOGIRQL()
|
||
|
#define IRP_IN(i)
|
||
|
#define IRP_OUT(i)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
#define ENABLE_LIST(hc, ep) \
|
||
|
{ \
|
||
|
ULONG listFilled = 0;\
|
||
|
ULONG temp;\
|
||
|
ASSERT_ENDPOINT(ep);\
|
||
|
\
|
||
|
temp = READ_REGISTER_ULONG (&(hc)->HcControlHeadED);\
|
||
|
if (temp) {\
|
||
|
listFilled |= HcCmd_ControlListFilled;\
|
||
|
}\
|
||
|
temp = READ_REGISTER_ULONG (&(hc)->HcBulkHeadED);\
|
||
|
if (temp) {\
|
||
|
listFilled |= HcCmd_BulkListFilled;\
|
||
|
}\
|
||
|
if (USB_ENDPOINT_TYPE_BULK == (ep)->Type) {\
|
||
|
listFilled |= HcCmd_BulkListFilled;\
|
||
|
} else if (USB_ENDPOINT_TYPE_CONTROL == (ep)->Type) {\
|
||
|
listFilled |= HcCmd_ControlListFilled;\
|
||
|
}\
|
||
|
WRITE_REGISTER_ULONG(&(hc)->HcCommandStatus.ul,\
|
||
|
listFilled);\
|
||
|
LOGENTRY(G, 'enaL', listFilled, ep, 0); \
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Function Prototypes
|
||
|
//
|
||
|
|
||
|
BOOLEAN OpenHCI_InterruptService (IN PKINTERRUPT Interrupt,
|
||
|
IN void * ServiceContext);
|
||
|
NTSTATUS OpenHCI_URB_Dispatch (IN PDEVICE_OBJECT, IN PIRP);
|
||
|
ULONG Get32BitFrameNumber (PHCD_DEVICE_DATA);
|
||
|
PHCD_ENDPOINT_DESCRIPTOR InsertEDForEndpoint (IN PHCD_DEVICE_DATA, IN PHCD_ENDPOINT, IN UCHAR,
|
||
|
IN PHCD_TRANSFER_DESCRIPTOR *);
|
||
|
|
||
|
PHCD_TRANSFER_DESCRIPTOR
|
||
|
OpenHCI_Alloc_HcdTD(
|
||
|
PHCD_DEVICE_DATA DeviceData
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_Free_HcdTD(
|
||
|
PHCD_DEVICE_DATA DeviceData,
|
||
|
PHCD_TRANSFER_DESCRIPTOR Td
|
||
|
);
|
||
|
|
||
|
PHCD_ENDPOINT_DESCRIPTOR
|
||
|
OpenHCI_Alloc_HcdED(
|
||
|
PHCD_DEVICE_DATA DeviceData
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_Free_HcdED(
|
||
|
PHCD_DEVICE_DATA DeviceData,
|
||
|
PHCD_ENDPOINT_DESCRIPTOR Ed
|
||
|
);
|
||
|
|
||
|
PHCD_TRANSFER_DESCRIPTOR
|
||
|
OpenHCI_LogDesc_to_PhyDesc (PHCD_DEVICE_DATA, ULONG);
|
||
|
|
||
|
void OpenHCI_PauseED (PHCD_ENDPOINT);
|
||
|
|
||
|
BOOLEAN OpenHCI_InterruptService (PKINTERRUPT, void *);
|
||
|
void OpenHCI_IsrDPC (PKDPC, PVOID, PVOID, PVOID);
|
||
|
|
||
|
void OpenHCI_CompleteIrp(PDEVICE_OBJECT, PIRP, NTSTATUS);
|
||
|
BOOLEAN OpenHCI_StartController (PVOID context);
|
||
|
|
||
|
void OpenHCI_StartEndpoint (PHCD_ENDPOINT);
|
||
|
NTSTATUS OpenHCI_StartTransfer (PDEVICE_OBJECT, PIRP);
|
||
|
NTSTATUS OpenHCI_RootHubStartXfer (PDEVICE_OBJECT, PHCD_DEVICE_DATA, PIRP, PHCD_URB, PHCD_ENDPOINT);
|
||
|
BOOLEAN OpenHCI_HcControl_OR (PVOID);
|
||
|
BOOLEAN OpenHCI_HcControl_AND (PVOID);
|
||
|
BOOLEAN OpenHCI_HcControl_SetHCFS (PVOID);
|
||
|
BOOLEAN OpenHCI_ListEnablesAtNextSOF (PVOID);
|
||
|
void OpenHCI_CancelTransfer (PDEVICE_OBJECT, PIRP);
|
||
|
NTSTATUS OpenHCI_AbortEndpoint(PDEVICE_OBJECT, PIRP, PHCD_DEVICE_DATA, PHCD_URB);
|
||
|
void EmulateRootHubInterruptXfer(PHCD_DEVICE_DATA, PHC_OPERATIONAL_REGISTER);
|
||
|
NTSTATUS CheckRootHub(PHCD_DEVICE_DATA , PHC_OPERATIONAL_REGISTER HC, PHCD_URB);
|
||
|
|
||
|
//jd
|
||
|
VOID
|
||
|
RemoveEDForEndpoint(
|
||
|
IN PHCD_ENDPOINT
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_SetDevicePowerState(
|
||
|
IN PDEVICE_OBJECT,
|
||
|
IN PIRP,
|
||
|
IN DEVICE_POWER_STATE
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_DeferredStartDevice(
|
||
|
IN PDEVICE_OBJECT,
|
||
|
IN PIRP
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_DeferIrpCompletion(
|
||
|
PDEVICE_OBJECT,
|
||
|
PIRP,
|
||
|
PVOID
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_StartDevice(
|
||
|
IN PDEVICE_OBJECT,
|
||
|
IN POHCI_RESOURCES
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_QueryCapabilities(
|
||
|
PDEVICE_OBJECT,
|
||
|
PDEVICE_CAPABILITIES
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_PnPAddDevice(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PDEVICE_OBJECT PhysicalDeviceObject
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_SaveHCstate(
|
||
|
PHCD_DEVICE_DATA
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_RestoreHCstate(
|
||
|
PHCD_DEVICE_DATA,
|
||
|
PBOOLEAN
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_DeferPoRequestCompletion(
|
||
|
IN PDEVICE_OBJECT,
|
||
|
IN UCHAR,
|
||
|
IN POWER_STATE,
|
||
|
IN PVOID,
|
||
|
IN PIO_STATUS_BLOCK
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_RootHubPower(
|
||
|
IN PDEVICE_OBJECT,
|
||
|
IN PIRP
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_ReserveDescriptors(
|
||
|
IN PHCD_DEVICE_DATA,
|
||
|
IN ULONG
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_QueueTransfer(
|
||
|
PDEVICE_OBJECT ,
|
||
|
PIRP
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_Dispatch(
|
||
|
IN PDEVICE_OBJECT ,
|
||
|
IN PIRP
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_Unload(
|
||
|
IN PDRIVER_OBJECT
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_SetTranferError(
|
||
|
PHCD_URB,
|
||
|
NTSTATUS
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_EndpointWorker(
|
||
|
PHCD_ENDPOINT
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_GrowDescriptorPool (
|
||
|
IN PHCD_DEVICE_DATA DeviceData,
|
||
|
IN ULONG ReserveLength,
|
||
|
OUT PCHAR *VirtAddr OPTIONAL,
|
||
|
OUT PHYSICAL_ADDRESS *PhysAddr OPTIONAL
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_LockAndCheckEndpoint(
|
||
|
PHCD_ENDPOINT ,
|
||
|
PBOOLEAN ,
|
||
|
PBOOLEAN ,
|
||
|
PKIRQL
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_UnlockEndpoint(
|
||
|
PHCD_ENDPOINT ,
|
||
|
KIRQL
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
OpenHCI_StopController(
|
||
|
IN PVOID
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_StopDevice(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN BOOLEAN TouchTheHardware
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_Shutdown(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_StartBIOS(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_StopBIOS(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_GetSOFRegModifyValue(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN OUT PULONG SofModifyValue
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_GetRegFlags(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN OUT PULONG SofModifyValue
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_DeadmanDPC(
|
||
|
PKDPC Dpc,
|
||
|
PVOID DeviceObject,
|
||
|
PVOID Context1,
|
||
|
PVOID Context2
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_InsertMagicEDs(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_ResurrectHC(
|
||
|
PHCD_DEVICE_DATA DeviceData
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
FindLostDoneHead (
|
||
|
IN PHCD_DEVICE_DATA DeviceData
|
||
|
);
|
||
|
|
||
|
|
||
|
PHYSICAL_ADDRESS
|
||
|
OpenHCI_IoMapTransfer(
|
||
|
IN PMAP_CONTEXT MapContext,
|
||
|
IN PDMA_ADAPTER DmaAdapter,
|
||
|
IN PMDL Mdl,
|
||
|
IN PVOID MapRegisterBase,
|
||
|
IN PVOID CurrentVa,
|
||
|
IN OUT PULONG Length,
|
||
|
IN ULONG TotalLength,
|
||
|
IN BOOLEAN WriteToDevice
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_ExternalGetCurrentFrame(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PULONG CurrentFrame
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
OpenHCI_ExternalGetConsumedBW(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
OpenHCI_RhPortsIdle(
|
||
|
PHCD_DEVICE_DATA DeviceData
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
OpenHCI_ProcessEndpoint(
|
||
|
PHCD_DEVICE_DATA DeviceData,
|
||
|
PHCD_ENDPOINT Endpoint
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
OpenHCI_Resume(
|
||
|
PDEVICE_OBJECT DeviceObject,
|
||
|
BOOLEAN LostPower
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
ReadPortStatusFix(
|
||
|
PHCD_DEVICE_DATA DeviceData,
|
||
|
ULONG PortIndex
|
||
|
);
|
||
|
|
||
|
|
||
|
#endif /* OPENHCI_H */
|
||
|
|
||
|
|