mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:23:05 +00:00

- Fix linking of QueueHeads. Implement LinkQueueHeadToCompletedList and CleanupAsyncList. These functions are used to software link the completed queueheads to a completed list. Only after the driver handshakes with the controller can this memory be freed. Fix a few incorrect values for QueueHead. - EhciDefferedRoutine: Implement handling of completed QueueHeads by removing them from the AnsycList and setting any errors for failure. - Reserved a QueueHead that will always be in the AsyncList Address Register. By setting it as the Head of Reclamation the controller can know when it has reached the end of the QueueHead list. - Remove all code from FdoDispatchInternalDeviceControl. This should never be called by upper level drivers. Change 1 of 3. svn path=/trunk/; revision=51325
327 lines
8.4 KiB
C
327 lines
8.4 KiB
C
#pragma once
|
|
|
|
#include <ntddk.h>
|
|
#include <usb.h>
|
|
|
|
/* USB Command Register */
|
|
#define EHCI_USBCMD 0x00
|
|
#define EHCI_USBSTS 0x04
|
|
#define EHCI_USBINTR 0x08
|
|
#define EHCI_FRINDEX 0x0C
|
|
#define EHCI_CTRLDSSEGMENT 0x10
|
|
#define EHCI_PERIODICLISTBASE 0x14
|
|
#define EHCI_ASYNCLISTBASE 0x18
|
|
#define EHCI_CONFIGFLAG 0x40
|
|
#define EHCI_PORTSC 0x44
|
|
|
|
/* USB Interrupt Register Flags 32 Bits */
|
|
#define EHCI_USBINTR_INTE 0x01
|
|
#define EHCI_USBINTR_ERR 0x02
|
|
#define EHCI_USBINTR_PC 0x04
|
|
#define EHCI_USBINTR_FLROVR 0x08
|
|
#define EHCI_USBINTR_HSERR 0x10
|
|
#define EHCI_USBINTR_ASYNC 0x20
|
|
/* Bits 6:31 Reserved */
|
|
|
|
/* Status Register Flags 32 Bits */
|
|
#define EHCI_STS_INT 0x01
|
|
#define EHCI_STS_ERR 0x02
|
|
#define EHCI_STS_PCD 0x04
|
|
#define EHCI_STS_FLR 0x08
|
|
#define EHCI_STS_FATAL 0x10
|
|
#define EHCI_STS_IAA 0x20
|
|
/* Bits 11:6 Reserved */
|
|
#define EHCI_STS_HALT 0x1000
|
|
#define EHCI_STS_RECL 0x2000
|
|
#define EHCI_STS_PSS 0x4000
|
|
#define EHCI_STS_ASS 0x8000
|
|
#define EHCI_ERROR_INT ( EHCI_STS_FATAL | EHCI_STS_ERR )
|
|
|
|
|
|
/* Last bit in QUEUE ELEMENT TRANSFER DESCRIPTOR Next Pointer */
|
|
/* Used for Queue Element Transfer Descriptor Pointers
|
|
and Queue Head Horizontal Link Pointers */
|
|
#define TERMINATE_POINTER 0x01
|
|
|
|
/* QUEUE ELEMENT TRANSFER DESCRIPTOR, Token defines and structs */
|
|
|
|
/* PIDCodes for QETD_TOKEN
|
|
OR with QUEUE_TRANSFER_DESCRIPTOR Token.PIDCode*/
|
|
#define PID_CODE_OUT_TOKEN 0x00
|
|
#define PID_CODE_IN_TOKEN 0x01
|
|
#define PID_CODE_SETUP_TOKEN 0x02
|
|
|
|
/* Split Transaction States
|
|
OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */
|
|
#define DO_START_SPLIT 0x00
|
|
#define DO_COMPLETE_SPLIT 0x01
|
|
|
|
/* Ping States, OR with QUEUE_TRANSFER_DESCRIPTOR Token. */
|
|
#define PING_STATE_DO_OUT 0x00
|
|
#define PING_STATE_DO_PING 0x01
|
|
|
|
typedef struct _PERIODICFRAMELIST
|
|
{
|
|
PULONG VirtualAddr;
|
|
PHYSICAL_ADDRESS PhysicalAddr;
|
|
ULONG Size;
|
|
} PERIODICFRAMELIST, *PPERIODICFRAMELIST;
|
|
|
|
|
|
/* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */
|
|
typedef struct _QETD_TOKEN_BITS
|
|
{
|
|
ULONG PingState:1;
|
|
ULONG SplitTransactionState:1;
|
|
ULONG MissedMicroFrame:1;
|
|
ULONG TransactionError:1;
|
|
ULONG BabbleDetected:1;
|
|
ULONG DataBufferError:1;
|
|
ULONG Halted:1;
|
|
ULONG Active:1;
|
|
ULONG PIDCode:2;
|
|
ULONG ErrorCounter:2;
|
|
ULONG CurrentPage:3;
|
|
ULONG InterruptOnComplete:1;
|
|
ULONG TotalBytesToTransfer:15;
|
|
ULONG DataToggle:1;
|
|
} QETD_TOKEN_BITS, *PQETD_TOKEN_BITS;
|
|
|
|
/* QUEUE ELEMENT TRANSFER DESCRIPTOR */
|
|
typedef struct _QUEUE_TRANSFER_DESCRIPTOR
|
|
{
|
|
//Hardware
|
|
ULONG NextPointer;
|
|
ULONG AlternateNextPointer;
|
|
union
|
|
{
|
|
QETD_TOKEN_BITS Bits;
|
|
ULONG DWord;
|
|
} Token;
|
|
ULONG BufferPointer[5];
|
|
|
|
//Software
|
|
ULONG BufferPointerVA[5];
|
|
ULONG PhysicalAddr;
|
|
struct _QUEUE_TRANSFER_DESCRIPTOR *PreviousDescriptor;
|
|
struct _QUEUE_TRANSFER_DESCRIPTOR *NextDescriptor;
|
|
} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
|
|
|
|
/* EndPointSpeeds of END_POINT_CHARACTERISTICS */
|
|
#define QH_ENDPOINT_FULLSPEED 0x00
|
|
#define QH_ENDPOINT_LOWSPEED 0x01
|
|
#define QH_ENDPOINT_HIGHSPEED 0x02
|
|
|
|
typedef struct _END_POINT_CHARACTERISTICS
|
|
{
|
|
ULONG DeviceAddress:7;
|
|
ULONG InactiveOnNextTransaction:1;
|
|
ULONG EndPointNumber:4;
|
|
ULONG EndPointSpeed:2;
|
|
ULONG QEDTDataToggleControl:1;
|
|
ULONG HeadOfReclamation:1;
|
|
ULONG MaximumPacketLength:11;
|
|
ULONG ControlEndPointFlag:1;
|
|
ULONG NakCountReload:4;
|
|
} END_POINT_CHARACTERISTICS, *PEND_POINT_CHARACTERISTICS;
|
|
|
|
typedef struct _END_POINT_CAPABILITIES
|
|
{
|
|
ULONG InterruptScheduleMask:8;
|
|
ULONG SplitCompletionMask:8;
|
|
ULONG HubAddr:6;
|
|
ULONG PortNumber:6;
|
|
/* Multi */
|
|
ULONG NumberOfTransactionPerFrame:2;
|
|
} END_POINT_CAPABILITIES, *PEND_POINT_CAPABILITIES;
|
|
|
|
|
|
/* QUEUE HEAD defines and structs */
|
|
|
|
/* QUEUE HEAD Select Types, OR with QUEUE_HEAD HorizontalLinkPointer */
|
|
#define QH_TYPE_IDT 0x00
|
|
#define QH_TYPE_QH 0x02
|
|
#define QH_TYPE_SITD 0x04
|
|
#define QH_TYPE_FSTN 0x06
|
|
|
|
/* QUEUE HEAD */
|
|
typedef struct _QUEUE_HEAD
|
|
{
|
|
//Hardware
|
|
ULONG HorizontalLinkPointer;
|
|
END_POINT_CHARACTERISTICS EndPointCharacteristics;
|
|
END_POINT_CAPABILITIES EndPointCapabilities;
|
|
/* TERMINATE_POINTER not valid for this member */
|
|
ULONG CurrentLinkPointer;
|
|
/* TERMINATE_POINTER valid */
|
|
ULONG NextPointer;
|
|
/* TERMINATE_POINTER valid, bits 1:4 is NAK_COUNTER */
|
|
ULONG AlternateNextPointer;
|
|
/* Only DataToggle, InterruptOnComplete, ErrorCounter, PingState valid */
|
|
union
|
|
{
|
|
QETD_TOKEN_BITS Bits;
|
|
ULONG DWord;
|
|
} Token;
|
|
ULONG BufferPointer[5];
|
|
|
|
//Software
|
|
ULONG PhysicalAddr;
|
|
struct _QUEUE_HEAD *PreviousQueueHead;
|
|
struct _QUEUE_HEAD *NextQueueHead;
|
|
ULONG NumberOfTransferDescriptors;
|
|
PQUEUE_TRANSFER_DESCRIPTOR FirstTransferDescriptor;
|
|
PQUEUE_TRANSFER_DESCRIPTOR DeadDescriptor;
|
|
PIRP IrpToComplete;
|
|
PKEVENT Event;
|
|
PMDL Mdl;
|
|
BOOLEAN FreeMdl;
|
|
} QUEUE_HEAD, *PQUEUE_HEAD;
|
|
|
|
/* USBCMD register 32 bits */
|
|
typedef struct _EHCI_USBCMD_CONTENT
|
|
{
|
|
ULONG Run : 1;
|
|
ULONG HCReset : 1;
|
|
ULONG FrameListSize : 2;
|
|
ULONG PeriodicEnable : 1;
|
|
ULONG AsyncEnable : 1;
|
|
ULONG DoorBell : 1;
|
|
ULONG LightReset : 1;
|
|
ULONG AsyncParkCount : 2;
|
|
ULONG Reserved : 1;
|
|
ULONG AsyncParkEnable : 1;
|
|
ULONG Reserved1 : 4;
|
|
ULONG IntThreshold : 8;
|
|
ULONG Reserved2 : 8;
|
|
|
|
} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT;
|
|
|
|
typedef struct _EHCI_USBSTS_CONTENT
|
|
{
|
|
ULONG USBInterrupt:1;
|
|
ULONG ErrorInterrupt:1;
|
|
ULONG DetectChangeInterrupt:1;
|
|
ULONG FrameListRolloverInterrupt:1;
|
|
ULONG HostSystemErrorInterrupt:1;
|
|
ULONG AsyncAdvanceInterrupt:1;
|
|
ULONG Reserved:6;
|
|
ULONG HCHalted:1;
|
|
ULONG Reclamation:1;
|
|
ULONG PeriodicScheduleStatus:1;
|
|
ULONG AsynchronousScheduleStatus:1;
|
|
} EHCI_USBSTS_CONTEXT, *PEHCI_USBSTS_CONTEXT;
|
|
|
|
typedef struct _EHCI_USBPORTSC_CONTENT
|
|
{
|
|
ULONG CurrentConnectStatus:1;
|
|
ULONG ConnectStatusChange:1;
|
|
ULONG PortEnabled:1;
|
|
ULONG PortEnableChanged:1;
|
|
ULONG OverCurrentActive:1;
|
|
ULONG OverCurrentChange:1;
|
|
ULONG ForcePortResume:1;
|
|
ULONG Suspend:1;
|
|
ULONG PortReset:1;
|
|
ULONG Reserved:1;
|
|
ULONG LineStatus:2;
|
|
ULONG PortPower:1;
|
|
ULONG PortOwner:1;
|
|
} EHCI_USBPORTSC_CONTENT, *PEHCI_USBPORTSC_CONTENT;
|
|
|
|
typedef struct _EHCI_HCS_CONTENT
|
|
{
|
|
ULONG PortCount : 4;
|
|
ULONG PortPowerControl: 1;
|
|
ULONG Reserved : 2;
|
|
ULONG PortRouteRules : 1;
|
|
ULONG PortPerCHC : 4;
|
|
ULONG CHCCount : 4;
|
|
ULONG PortIndicator : 1;
|
|
ULONG Reserved2 : 3;
|
|
ULONG DbgPortNum : 4;
|
|
ULONG Reserved3 : 8;
|
|
|
|
} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT;
|
|
|
|
typedef struct _EHCI_HCC_CONTENT
|
|
{
|
|
ULONG CurAddrBits : 1;
|
|
ULONG VarFrameList : 1;
|
|
ULONG ParkMode : 1;
|
|
ULONG Reserved : 1;
|
|
ULONG IsoSchedThreshold : 4;
|
|
ULONG EECPCapable : 8;
|
|
ULONG Reserved2 : 16;
|
|
|
|
} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
|
|
|
|
typedef struct _EHCI_CAPS {
|
|
UCHAR Length;
|
|
UCHAR Reserved;
|
|
USHORT HCIVersion;
|
|
union
|
|
{
|
|
EHCI_HCS_CONTENT HCSParams;
|
|
ULONG HCSParamsLong;
|
|
};
|
|
ULONG HCCParams;
|
|
UCHAR PortRoute [8];
|
|
} EHCI_CAPS, *PEHCI_CAPS;
|
|
|
|
typedef struct _EHCIPORTS
|
|
{
|
|
ULONG PortNumber;
|
|
ULONG PortType;
|
|
USHORT PortStatus;
|
|
USHORT PortChange;
|
|
} EHCIPORTS, *PEHCIPORTS;
|
|
|
|
typedef struct _EHCI_HOST_CONTROLLER
|
|
{
|
|
PDMA_ADAPTER pDmaAdapter;
|
|
ULONG MapRegisters;
|
|
ULONG OpRegisters;
|
|
EHCI_CAPS ECHICaps;
|
|
ULONG NumberOfPorts;
|
|
EHCIPORTS Ports[127];
|
|
PVOID CommonBufferVA[16];
|
|
PHYSICAL_ADDRESS CommonBufferPA[16];
|
|
ULONG CommonBufferSize;
|
|
PQUEUE_HEAD AsyncListQueue;
|
|
PQUEUE_HEAD CompletedListQueue;
|
|
KSPIN_LOCK Lock;
|
|
} EHCI_HOST_CONTROLLER, *PEHCI_HOST_CONTROLLER;
|
|
|
|
ULONG
|
|
ReadControllerStatus(PEHCI_HOST_CONTROLLER hcd);
|
|
|
|
VOID
|
|
ClearControllerStatus(PEHCI_HOST_CONTROLLER hcd, ULONG Status);
|
|
|
|
VOID
|
|
GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister);
|
|
|
|
VOID
|
|
ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port);
|
|
|
|
VOID
|
|
StartEhci(PEHCI_HOST_CONTROLLER hcd);
|
|
|
|
VOID
|
|
StopEhci(PEHCI_HOST_CONTROLLER hcd);
|
|
|
|
VOID
|
|
SetAsyncListQueueRegister(PEHCI_HOST_CONTROLLER hcd, ULONG PhysicalAddr);
|
|
|
|
ULONG
|
|
GetAsyncListQueueRegister(PEHCI_HOST_CONTROLLER hcd);
|
|
|
|
VOID
|
|
SetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd, ULONG PhysicalAddr);
|
|
|
|
ULONG
|
|
GetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd);
|
|
|
|
BOOLEAN
|
|
EnumControllerPorts(PEHCI_HOST_CONTROLLER hcd);
|