[USBEHCI_NEW] Bring-in the USB EHCI miniport driver created by Vadim Galyant. (#301)

This commit is contained in:
Amine Khaldi 2018-09-10 08:05:35 +01:00 committed by Thomas Faber
parent 419e014675
commit 3bf751e046
11 changed files with 5284 additions and 0 deletions

View file

@ -1,6 +1,7 @@
add_subdirectory(usbccgp)
add_subdirectory(usbd)
add_subdirectory(usbehci)
#add_subdirectory(usbehci_new)
add_subdirectory(usbhub)
#add_subdirectory(usbhub_new)
add_subdirectory(usbohci)

View file

@ -0,0 +1,16 @@
list(APPEND SOURCE
debug.c
roothub.c
usbehci.c
usbehci.h)
add_library(usbehci SHARED
${SOURCE}
guid.c
usbehci.rc)
set_module_type(usbehci kernelmodedriver)
add_importlibs(usbehci usbport usbd hal ntoskrnl)
add_pch(usbehci usbehci.h SOURCE)
add_cd_file(TARGET usbehci DESTINATION reactos/system32/drivers NO_CAB FOR all)

View file

@ -0,0 +1,51 @@
/*
* PROJECT: ReactOS USB EHCI Miniport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBEHCI debugging declarations
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
*/
#ifndef DBG_EHCI_H__
#define DBG_EHCI_H__
#if DBG
#ifndef NDEBUG_EHCI_TRACE
#define DPRINT_EHCI(fmt, ...) do { \
if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)) \
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
} while (0)
#else
#if defined(_MSC_VER)
#define DPRINT_EHCI __noop
#else
#define DPRINT_EHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
#endif
#endif
#ifndef NDEBUG_EHCI_ROOT_HUB
#define DPRINT_RH(fmt, ...) do { \
if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)) \
DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
} while (0)
#else
#if defined(_MSC_VER)
#define DPRINT_RH __noop
#else
#define DPRINT_RH(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
#endif
#endif
#else /* not DBG */
#if defined(_MSC_VER)
#define DPRINT_EHCI __noop
#define DPRINT_RH __noop
#else
#define DPRINT_EHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
#define DPRINT_RH(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
#endif /* _MSC_VER */
#endif /* not DBG */
#endif /* DBG_EHCI_H__ */

View file

@ -0,0 +1,40 @@
/*
* PROJECT: ReactOS USB EHCI Miniport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBEHCI debugging functions
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
*/
#include "usbehci.h"
//#define NDEBUG
#include <debug.h>
VOID
NTAPI
EHCI_DumpHwTD(IN PEHCI_HCD_TD TD)
{
while (TD)
{
DPRINT(": TD - %p\n", TD);
DPRINT(": TD->PhysicalAddress - %lx\n", TD->PhysicalAddress);
DPRINT(": TD->HwTD.NextTD - %lx\n", TD->HwTD.NextTD);
DPRINT(": TD->HwTD.AlternateNextTD - %lx\n", TD->HwTD.AlternateNextTD);
DPRINT(": TD->HwTD.Token.AsULONG - %lx\n", TD->HwTD.Token.AsULONG);
TD = TD->NextHcdTD;
}
}
VOID
NTAPI
EHCI_DumpHwQH(IN PEHCI_HCD_QH QH)
{
if (!QH)
return;
DPRINT(": QH->sqh.HwQH.CurrentTD - %lx\n", QH->sqh.HwQH.CurrentTD);
DPRINT(": QH->sqh.HwQH.NextTD - %lx\n", QH->sqh.HwQH.NextTD);
DPRINT(": QH->sqh.HwQH.AlternateNextTD - %lx\n", QH->sqh.HwQH.AlternateNextTD);
DPRINT(": QH->sqh.HwQH.Token.AsULONG - %lx\n", QH->sqh.HwQH.Token.AsULONG);
}

View file

@ -0,0 +1,9 @@
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
#include <wdm.h>
#include <initguid.h>
#include <wdmguid.h>
#include <hubbusif.h>
#include <usbbusif.h>
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */

View file

@ -0,0 +1,417 @@
/*
* PROJECT: ReactOS USB EHCI Miniport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBEHCI hardware declarations
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
*/
#define EHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List
/* EHCI hardware registers */
#define EHCI_USBCMD 0
#define EHCI_USBSTS 1
#define EHCI_USBINTR 2
#define EHCI_FRINDEX 3
#define EHCI_CTRLDSSEGMENT 4
#define EHCI_PERIODICLISTBASE 5
#define EHCI_ASYNCLISTBASE 6
#define EHCI_CONFIGFLAG 16
#define EHCI_PORTSC 17
#define EHCI_FLADJ_PCI_CONFIG_OFFSET 0x61
typedef union _EHCI_LEGACY_EXTENDED_CAPABILITY {
struct {
ULONG CapabilityID : 8;
ULONG NextCapabilityPointer : 8;
ULONG BiosOwnedSemaphore : 1;
ULONG Reserved1 : 7;
ULONG OsOwnedSemaphore : 1;
ULONG Reserved2 : 7;
};
ULONG AsULONG;
} EHCI_LEGACY_EXTENDED_CAPABILITY;
C_ASSERT(sizeof(EHCI_LEGACY_EXTENDED_CAPABILITY) == sizeof(ULONG));
typedef union _EHCI_HC_STRUCTURAL_PARAMS {
struct {
ULONG PortCount : 4;
ULONG PortPowerControl : 1;
ULONG Reserved1 : 2;
ULONG PortRouteRules : 1;
ULONG PortsPerCompanion : 4;
ULONG CompanionControllers : 4;
ULONG PortIndicators : 1;
ULONG Reserved2 : 3;
ULONG DebugPortNumber : 4; //Optional
ULONG Reserved3 : 8;
};
ULONG AsULONG;
} EHCI_HC_STRUCTURAL_PARAMS;
C_ASSERT(sizeof(EHCI_HC_STRUCTURAL_PARAMS) == sizeof(ULONG));
typedef union _EHCI_HC_CAPABILITY_PARAMS {
struct {
ULONG Addressing64bitCapability : 1;
ULONG IsProgrammableFrameList : 1;
ULONG IsScheduleParkSupport : 1;
ULONG Reserved1 : 1;
ULONG IsoSchedulingThreshold : 4;
ULONG ExtCapabilitiesPointer : 8; // (EECP)
ULONG Reserved2 : 16;
};
ULONG AsULONG;
} EHCI_HC_CAPABILITY_PARAMS;
C_ASSERT(sizeof(EHCI_HC_CAPABILITY_PARAMS) == sizeof(ULONG));
typedef struct _EHCI_HC_CAPABILITY_REGISTERS {
UCHAR RegistersLength; // RO
UCHAR Reserved; // RO
USHORT InterfaceVersion; // RO
EHCI_HC_STRUCTURAL_PARAMS StructParameters; // RO
EHCI_HC_CAPABILITY_PARAMS CapParameters; // RO
UCHAR CompanionPortRouteDesc[8]; // RO
} EHCI_HC_CAPABILITY_REGISTERS, *PEHCI_HC_CAPABILITY_REGISTERS;
typedef union _EHCI_USB_COMMAND {
struct {
ULONG Run : 1;
ULONG Reset : 1;
ULONG FrameListSize : 2;
ULONG PeriodicEnable : 1;
ULONG AsynchronousEnable : 1;
ULONG InterruptAdvanceDoorbell : 1;
ULONG LightResetHC : 1; // optional
ULONG AsynchronousParkModeCount : 2; // optional
ULONG Reserved1 : 1;
ULONG AsynchronousParkModeEnable : 1; // optional
ULONG Reserved2 : 4;
ULONG InterruptThreshold : 8;
ULONG Reserved3 : 8;
};
ULONG AsULONG;
} EHCI_USB_COMMAND;
C_ASSERT(sizeof(EHCI_USB_COMMAND) == sizeof(ULONG));
typedef union _EHCI_USB_STATUS {
struct {
ULONG Interrupt : 1;
ULONG ErrorInterrupt : 1;
ULONG PortChangeDetect : 1;
ULONG FrameListRollover : 1;
ULONG HostSystemError : 1;
ULONG InterruptOnAsyncAdvance : 1;
ULONG Reserved1 : 6;
ULONG HCHalted : 1;
ULONG Reclamation : 1;
ULONG PeriodicStatus : 1;
ULONG AsynchronousStatus : 1;
ULONG Reserved2 : 16;
};
ULONG AsULONG;
} EHCI_USB_STATUS;
C_ASSERT(sizeof(EHCI_USB_STATUS) == sizeof(ULONG));
#define EHCI_INTERRUPT_MASK 0x3F
typedef union _EHCI_INTERRUPT_ENABLE {
struct {
ULONG Interrupt : 1;
ULONG ErrorInterrupt : 1;
ULONG PortChangeInterrupt : 1;
ULONG FrameListRollover : 1;
ULONG HostSystemError : 1;
ULONG InterruptOnAsyncAdvance : 1;
ULONG Reserved : 26;
};
ULONG AsULONG;
} EHCI_INTERRUPT_ENABLE;
C_ASSERT(sizeof(EHCI_INTERRUPT_ENABLE) == sizeof(ULONG));
#define EHCI_LINE_STATUS_K_STATE_LOW_SPEED 1
#define EHCI_PORT_OWNER_COMPANION_CONTROLLER 1
typedef union _EHCI_PORT_STATUS_CONTROL {
struct {
ULONG CurrentConnectStatus : 1;
ULONG ConnectStatusChange : 1;
ULONG PortEnabledDisabled : 1;
ULONG PortEnableDisableChange : 1;
ULONG OverCurrentActive : 1;
ULONG OverCurrentChange : 1;
ULONG ForcePortResume : 1;
ULONG Suspend : 1;
ULONG PortReset : 1;
ULONG Reserved1 : 1;
ULONG LineStatus : 2;
ULONG PortPower : 1;
ULONG PortOwner : 1;
ULONG PortIndicatorControl : 2;
ULONG PortTestControl : 4;
ULONG WakeOnConnectEnable : 1;
ULONG WakeOnDisconnectEnable : 1;
ULONG WakeOnOverCurrentEnable : 1;
ULONG Reserved2 : 9;
};
ULONG AsULONG;
} EHCI_PORT_STATUS_CONTROL;
C_ASSERT(sizeof(EHCI_PORT_STATUS_CONTROL) == sizeof(ULONG));
/* FRINDEX Frame Index Register */
#define EHCI_FRINDEX_FRAME_MASK 0x7FF
#define EHCI_FRINDEX_INDEX_MASK 0x3FF
#define EHCI_CONFIG_FLAG_CONFIGURED 1
typedef struct _EHCI_HW_REGISTERS {
EHCI_USB_COMMAND HcCommand; // RO, R/W (field dependent), WO
EHCI_USB_STATUS HcStatus; // RO, R/W, R/WC, (field dependent)
EHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W
ULONG FrameIndex; // R/W (Writes must be DWord Writes)
ULONG SegmentSelector; // R/W (Writes must be DWord Writes)
ULONG PeriodicListBase; // R/W (Writes must be DWord Writes)
ULONG AsyncListBase; // Read/Write (Writes must be DWord Writes)
ULONG Reserved[9];
ULONG ConfigFlag; // R/W
EHCI_PORT_STATUS_CONTROL PortControl[15]; // (1-15) RO, R/W, R/WC (field dependent)
} EHCI_HW_REGISTERS, *PEHCI_HW_REGISTERS;
/* Link Pointer */
#define EHCI_LINK_TYPE_iTD 0 // isochronous transfer descriptor
#define EHCI_LINK_TYPE_QH 1 // queue head
#define EHCI_LINK_TYPE_siTD 2 // split transaction isochronous transfer
#define EHCI_LINK_TYPE_FSTN 3 // frame span traversal node
/* Used for QHs and qTDs to mark Pointers as the end */
#define TERMINATE_POINTER 1
#define LINK_POINTER_MASK 0xFFFFFFE0
typedef union _EHCI_LINK_POINTER {
struct {
ULONG Terminate : 1;
ULONG Type : 2;
ULONG Reserved : 2;
ULONG Address : 27;
};
ULONG AsULONG;
} EHCI_LINK_POINTER;
C_ASSERT(sizeof(EHCI_LINK_POINTER) == sizeof(ULONG));
/* Isochronous (High-Speed) Transfer Descriptor (iTD) */
typedef union _EHCI_TRANSACTION_CONTROL {
struct {
ULONG xOffset : 12;
ULONG PageSelect : 3;
ULONG InterruptOnComplete : 1;
ULONG xLength : 12;
ULONG Status : 4;
};
ULONG AsULONG;
} EHCI_TRANSACTION_CONTROL;
C_ASSERT(sizeof(EHCI_TRANSACTION_CONTROL) == sizeof(ULONG));
typedef union _EHCI_TRANSACTION_BUFFER {
struct {
ULONG DeviceAddress : 7;
ULONG Reserved1 : 1;
ULONG EndpointNumber : 4;
ULONG DataBuffer0 : 20;
};
struct {
ULONG MaximumPacketSize : 11;
ULONG Direction : 1;
ULONG DataBuffer1 : 20;
};
struct {
ULONG Multi : 2;
ULONG Reserved2 : 10;
ULONG DataBuffer2 : 20;
};
struct {
ULONG Reserved3 : 12;
ULONG DataBuffer : 20;
};
ULONG AsULONG;
} EHCI_TRANSACTION_BUFFER;
C_ASSERT(sizeof(EHCI_TRANSACTION_BUFFER) == sizeof(ULONG));
typedef struct _EHCI_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary
EHCI_LINK_POINTER NextLink;
EHCI_TRANSACTION_CONTROL Transaction[8];
EHCI_TRANSACTION_BUFFER Buffer[7];
ULONG ExtendedBuffer[7];
} EHCI_ISOCHRONOUS_TD, *PEHCI_ISOCHRONOUS_TD;
C_ASSERT(sizeof(EHCI_ISOCHRONOUS_TD) == 92);
/* Split Transaction Isochronous Transfer Descriptor (siTD) */
typedef union _EHCI_FS_ENDPOINT_PARAMS {
struct {
ULONG DeviceAddress : 7;
ULONG Reserved1 : 1;
ULONG EndpointNumber : 4;
ULONG Reserved2 : 4;
ULONG HubAddress : 7;
ULONG Reserved3 : 1;
ULONG PortNumber : 7;
ULONG Direction : 1;
};
ULONG AsULONG;
} EHCI_FS_ENDPOINT_PARAMS;
C_ASSERT(sizeof(EHCI_FS_ENDPOINT_PARAMS) == sizeof(ULONG));
typedef union _EHCI_MICROFRAME_CONTROL {
struct {
ULONG StartMask : 8;
ULONG CompletionMask : 8;
ULONG Reserved : 16;
};
ULONG AsULONG;
} EHCI_MICROFRAME_CONTROL;
C_ASSERT(sizeof(EHCI_MICROFRAME_CONTROL) == sizeof(ULONG));
typedef union _EHCI_SPLIT_TRANSFER_STATE {
struct {
ULONG Status : 8;
ULONG ProgressMask : 8;
ULONG TotalBytes : 10;
ULONG Reserved : 4;
ULONG PageSelect : 1;
ULONG InterruptOnComplete : 1;
};
ULONG AsULONG;
} EHCI_SPLIT_TRANSFER_STATE;
C_ASSERT(sizeof(EHCI_SPLIT_TRANSFER_STATE) == sizeof(ULONG));
typedef union _EHCI_SPLIT_BUFFER_POINTER {
struct {
ULONG CurrentOffset : 12;
ULONG DataBuffer0 : 20;
};
struct {
ULONG TransactionCount : 3;
ULONG TransactionPosition : 2;
ULONG Reserved : 7;
ULONG DataBuffer1 : 20;
};
ULONG AsULONG;
} EHCI_SPLIT_BUFFER_POINTER;
C_ASSERT(sizeof(EHCI_SPLIT_BUFFER_POINTER) == sizeof(ULONG));
typedef struct _EHCI_SPLIT_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary
EHCI_LINK_POINTER NextLink;
EHCI_FS_ENDPOINT_PARAMS EndpointCharacteristics;
EHCI_MICROFRAME_CONTROL MicroFrameControl;
EHCI_SPLIT_TRANSFER_STATE TransferState;
EHCI_SPLIT_BUFFER_POINTER Buffer[2];
ULONG BackPointer;
ULONG ExtendedBuffer[2];
} EHCI_SPLIT_ISOCHRONOUS_TD, *PEHCI_SPLIT_ISOCHRONOUS_TD;
C_ASSERT(sizeof(EHCI_SPLIT_ISOCHRONOUS_TD) == 36);
/* Queue Element Transfer Descriptor (qTD) */
#define EHCI_MAX_QTD_BUFFER_PAGES 5
#define EHCI_TOKEN_STATUS_ACTIVE (1 << 7)
#define EHCI_TOKEN_STATUS_HALTED (1 << 6)
#define EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR (1 << 5)
#define EHCI_TOKEN_STATUS_BABBLE_DETECTED (1 << 4)
#define EHCI_TOKEN_STATUS_TRANSACTION_ERROR (1 << 3)
#define EHCI_TOKEN_STATUS_MISSED_MICROFRAME (1 << 2)
#define EHCI_TOKEN_STATUS_SPLIT_STATE (1 << 1)
#define EHCI_TOKEN_STATUS_PING_STATE (1 << 0)
#define EHCI_TD_TOKEN_PID_OUT 0
#define EHCI_TD_TOKEN_PID_IN 1
#define EHCI_TD_TOKEN_PID_SETUP 2
#define EHCI_TD_TOKEN_PID_RESERVED 3
typedef union _EHCI_TD_TOKEN {
struct {
ULONG Status : 8;
ULONG PIDCode : 2;
ULONG ErrorCounter : 2;
ULONG CurrentPage : 3;
ULONG InterruptOnComplete : 1;
ULONG TransferBytes : 15;
ULONG DataToggle : 1;
};
ULONG AsULONG;
} EHCI_TD_TOKEN, *PEHCI_TD_TOKEN;
C_ASSERT(sizeof(EHCI_TD_TOKEN) == sizeof(ULONG));
typedef struct _EHCI_QUEUE_TD { // must be aligned on 32-byte boundaries
ULONG NextTD;
ULONG AlternateNextTD;
EHCI_TD_TOKEN Token;
ULONG Buffer[5];
ULONG ExtendedBuffer[5];
} EHCI_QUEUE_TD, *PEHCI_QUEUE_TD;
C_ASSERT(sizeof(EHCI_QUEUE_TD) == 52);
/* Queue Head */
#define EHCI_QH_EP_FULL_SPEED 0
#define EHCI_QH_EP_LOW_SPEED 1
#define EHCI_QH_EP_HIGH_SPEED 2
typedef union _EHCI_QH_EP_PARAMS {
struct {
ULONG DeviceAddress : 7;
ULONG InactivateOnNextTransaction : 1;
ULONG EndpointNumber : 4;
ULONG EndpointSpeed : 2;
ULONG DataToggleControl : 1;
ULONG HeadReclamationListFlag : 1;
ULONG MaximumPacketLength : 11; // corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize).
ULONG ControlEndpointFlag : 1;
ULONG NakCountReload : 4;
};
ULONG AsULONG;
} EHCI_QH_EP_PARAMS;
C_ASSERT(sizeof(EHCI_QH_EP_PARAMS) == sizeof(ULONG));
typedef union _EHCI_QH_EP_CAPS {
struct {
ULONG InterruptMask : 8;
ULONG SplitCompletionMask : 8;
ULONG HubAddr : 7;
ULONG PortNumber : 7;
ULONG PipeMultiplier : 2;
};
ULONG AsULONG;
} EHCI_QH_EP_CAPS;
C_ASSERT(sizeof(EHCI_QH_EP_CAPS) == sizeof(ULONG));
typedef struct _EHCI_QUEUE_HEAD { // must be aligned on 32-byte boundaries
EHCI_LINK_POINTER HorizontalLink;
EHCI_QH_EP_PARAMS EndpointParams;
EHCI_QH_EP_CAPS EndpointCaps;
ULONG CurrentTD;
ULONG NextTD;
ULONG AlternateNextTD;
EHCI_TD_TOKEN Token;
ULONG Buffer[5];
ULONG ExtendedBuffer[5];
} EHCI_QUEUE_HEAD, *PEHCI_QUEUE_HEAD;
C_ASSERT(sizeof(EHCI_QUEUE_HEAD) == 68);

View file

@ -0,0 +1,710 @@
/*
* PROJECT: ReactOS USB EHCI Miniport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBEHCI root hub functions
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
*/
#include "usbehci.h"
#define NDEBUG
#include <debug.h>
#define NDEBUG_EHCI_ROOT_HUB
#include "dbg_ehci.h"
MPSTATUS
NTAPI
EHCI_RH_ChirpRootPort(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
ULONG PortBit;
ULONG ix;
DPRINT_RH("EHCI_RH_ChirpRootPort: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
DPRINT_RH("EHCI_RH_ChirpRootPort: PortSC - %X\n", PortSC.AsULONG);
PortBit = 1 << (Port - 1);
if (PortBit & EhciExtension->ResetPortBits)
{
DPRINT_RH("EHCI_RH_ChirpRootPort: Skip port - %x\n", Port);
return MP_STATUS_SUCCESS;
}
if (PortSC.PortPower == 0)
{
DPRINT_RH("EHCI_RH_ChirpRootPort: Skip port - %x\n", Port);
return MP_STATUS_SUCCESS;
}
if (PortSC.CurrentConnectStatus == 0 ||
PortSC.PortEnabledDisabled == 1 ||
PortSC.PortOwner == EHCI_PORT_OWNER_COMPANION_CONTROLLER)
{
DPRINT_RH("EHCI_RH_ChirpRootPort: No port - %x\n", Port);
return MP_STATUS_SUCCESS;
}
if (PortSC.LineStatus == EHCI_LINE_STATUS_K_STATE_LOW_SPEED &&
PortSC.Suspend == 0 &&
PortSC.CurrentConnectStatus == 1)
{
/* Attached device is not a high-speed device.
Release ownership of the port to a selected HC.
Companion HC owns and controls the port. Section 4.2 */
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
DPRINT_RH("EHCI_RH_ChirpRootPort: Companion HC port - %x\n", Port);
return MP_STATUS_SUCCESS;
}
DPRINT("EHCI_RH_ChirpRootPort: EhciExtension - %p, Port - %x\n",
EhciExtension,
Port);
PortSC.PortEnabledDisabled = 0;
PortSC.PortReset = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
RegPacket.UsbPortWait(EhciExtension, 10);
do
{
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.PortReset = 0;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
for (ix = 0; ix <= 500; ix += 20)
{
KeStallExecutionProcessor(20);
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
DPRINT_RH("EHCI_RH_ChirpRootPort: Reset port - %x\n", Port);
if (PortSC.PortReset == 0)
break;
}
}
while (PortSC.PortReset == 1);
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
if (PortSC.PortEnabledDisabled == 1)
{
PortSC.ConnectStatusChange = 0;
PortSC.PortEnabledDisabled = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
RegPacket.UsbPortWait(EhciExtension, 10);
EhciExtension->ResetPortBits |= PortBit;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
DPRINT_RH("EHCI_RH_ChirpRootPort: Disable port - %x\n", Port);
}
else
{
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
DPRINT_RH("EHCI_RH_ChirpRootPort: Companion HC port - %x\n", Port);
}
return MP_STATUS_SUCCESS;
}
VOID
NTAPI
EHCI_RH_GetRootHubData(IN PVOID ehciExtension,
IN PVOID rootHubData)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PUSBPORT_ROOT_HUB_DATA RootHubData;
USBPORT_HUB_20_CHARACTERISTICS HubCharacteristics;
DPRINT_RH("EHCI_RH_GetRootHubData: EhciExtension - %p, rootHubData - %p\n",
EhciExtension,
rootHubData);
RootHubData = rootHubData;
RootHubData->NumberOfPorts = EhciExtension->NumberOfPorts;
HubCharacteristics.AsUSHORT = 0;
/* Logical Power Switching Mode */
if (EhciExtension->PortPowerControl == 1)
{
/* Individual port power switching */
HubCharacteristics.PowerControlMode = 1;
}
else
{
/* Ganged power switching (all ports power at once) */
HubCharacteristics.PowerControlMode = 0;
}
HubCharacteristics.NoPowerSwitching = 0;
/* EHCI RH is not part of a compound device */
HubCharacteristics.PartOfCompoundDevice = 0;
/* Global Over-current Protection */
HubCharacteristics.OverCurrentProtectionMode = 0;
RootHubData->HubCharacteristics.Usb20HubCharacteristics = HubCharacteristics;
RootHubData->PowerOnToPowerGood = 2; // Time (in 2 ms intervals)
RootHubData->HubControlCurrent = 0;
}
MPSTATUS
NTAPI
EHCI_RH_GetStatus(IN PVOID ehciExtension,
IN PUSHORT Status)
{
DPRINT_RH("EHCI_RH_GetStatus: ... \n");
*Status = USB_GETSTATUS_SELF_POWERED;
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_GetPortStatus(IN PVOID ehciExtension,
IN USHORT Port,
IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
USB_PORT_STATUS_AND_CHANGE status;
ULONG PortMaskBits;
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
if (PortSC.CurrentConnectStatus)
{
DPRINT_RH("EHCI_RH_GetPortStatus: Port - %x, PortSC.AsULONG - %X\n",
Port,
PortSC.AsULONG);
}
PortStatus->AsUlong32 = 0;
if (PortSC.LineStatus == EHCI_LINE_STATUS_K_STATE_LOW_SPEED &&
PortSC.PortOwner != EHCI_PORT_OWNER_COMPANION_CONTROLLER &&
(PortSC.PortEnabledDisabled | PortSC.Suspend) && // Enable or Suspend
PortSC.CurrentConnectStatus == 1) // Device is present
{
DPRINT("EHCI_RH_GetPortStatus: LowSpeed device detected\n");
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER; // release ownership
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
return MP_STATUS_SUCCESS;
}
status.AsUlong32 = 0;
status.PortStatus.Usb20PortStatus.CurrentConnectStatus = PortSC.CurrentConnectStatus;
status.PortStatus.Usb20PortStatus.PortEnabledDisabled = PortSC.PortEnabledDisabled;
status.PortStatus.Usb20PortStatus.Suspend = PortSC.Suspend;
status.PortStatus.Usb20PortStatus.OverCurrent = PortSC.OverCurrentActive;
status.PortStatus.Usb20PortStatus.Reset = PortSC.PortReset;
status.PortStatus.Usb20PortStatus.PortPower = PortSC.PortPower;
if (PortSC.PortOwner == EHCI_PORT_OWNER_COMPANION_CONTROLLER)
status.PortStatus.Usb20PortStatus.Reserved1 = USB20_PORT_STATUS_RESERVED1_OWNED_BY_COMPANION;
status.PortChange.Usb20PortChange.PortEnableDisableChange = PortSC.PortEnableDisableChange;
status.PortChange.Usb20PortChange.OverCurrentIndicatorChange = PortSC.OverCurrentChange;
PortMaskBits = 1 << (Port - 1);
if (status.PortStatus.Usb20PortStatus.CurrentConnectStatus)
status.PortStatus.Usb20PortStatus.LowSpeedDeviceAttached = 0;
status.PortStatus.Usb20PortStatus.HighSpeedDeviceAttached = 1;
if (PortSC.ConnectStatusChange)
EhciExtension->ConnectPortBits |= PortMaskBits;
if (EhciExtension->FinishResetPortBits & PortMaskBits)
status.PortChange.Usb20PortChange.ResetChange = 1;
if (EhciExtension->ConnectPortBits & PortMaskBits)
status.PortChange.Usb20PortChange.ConnectStatusChange = 1;
if (EhciExtension->SuspendPortBits & PortMaskBits)
status.PortChange.Usb20PortChange.SuspendChange = 1;
*PortStatus = status;
if (status.PortStatus.Usb20PortStatus.CurrentConnectStatus)
{
DPRINT_RH("EHCI_RH_GetPortStatus: Port - %x, status.AsULONG - %X\n",
Port,
status.AsUlong32);
}
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_GetHubStatus(IN PVOID ehciExtension,
IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
{
DPRINT_RH("EHCI_RH_GetHubStatus: ... \n");
HubStatus->AsUlong32 = 0;
return MP_STATUS_SUCCESS;
}
VOID
NTAPI
EHCI_RH_FinishReset(IN PVOID ehciExtension,
IN PVOID Context)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
PUSHORT Port = Context;
DPRINT("EHCI_RH_FinishReset: *Port - %x\n", *Port);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
if (PortSC.AsULONG != -1)
{
if (!PortSC.CurrentConnectStatus)
DPRINT("EHCI_RH_FinishReset: PortSC.AsULONG - %X\n", PortSC.AsULONG);
if (PortSC.PortEnabledDisabled ||
!PortSC.CurrentConnectStatus ||
PortSC.ConnectStatusChange)
{
EhciExtension->FinishResetPortBits |= (1 << (*Port - 1));
RegPacket.UsbPortInvalidateRootHub(EhciExtension);
}
else
{
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
EhciExtension->FinishResetPortBits |= (1 << (*Port - 1));
}
EhciExtension->ResetPortBits &= ~(1 << (*Port - 1));
}
}
VOID
NTAPI
EHCI_RH_PortResetComplete(IN PVOID ehciExtension,
IN PVOID Context)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
ULONG ix;
PUSHORT Port = Context;
DPRINT("EHCI_RH_PortResetComplete: *Port - %x\n", *Port);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG;
do
{
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.PortReset = 0;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
for (ix = 0; ix <= 500; ix += 20)
{
KeStallExecutionProcessor(20);
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
DPRINT("EHCI_RH_PortResetComplete: Reset port - %x\n", Port);
if (PortSC.PortReset == 0)
break;
}
}
while (PortSC.PortReset == 1 && (PortSC.AsULONG != -1));
RegPacket.UsbPortRequestAsyncCallback(EhciExtension,
50, // TimerValue
Port,
sizeof(Port),
EHCI_RH_FinishReset);
}
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortReset(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT("EHCI_RH_SetFeaturePortReset: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
EhciExtension->ResetPortBits |= 1 << (Port - 1);
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnabledDisabled = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.PortReset = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
RegPacket.UsbPortRequestAsyncCallback(EhciExtension,
50, // TimerValue
&Port,
sizeof(Port),
EHCI_RH_PortResetComplete);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortPower(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT_RH("EHCI_RH_SetFeaturePortPower: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.PortPower = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortEnable(IN PVOID ehciExtension,
IN USHORT Port)
{
DPRINT_RH("EHCI_RH_SetFeaturePortEnable: Not supported\n");
ASSERT(Port != 0);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortSuspend(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT("EHCI_RH_SetFeaturePortSuspend: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.Suspend = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
KeStallExecutionProcessor(125);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortEnable(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT("EHCI_RH_ClearFeaturePortEnable: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnabledDisabled = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortPower(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT("EHCI_RH_ClearFeaturePortPower: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.PortPower = 0;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
return MP_STATUS_SUCCESS;
}
VOID
NTAPI
EHCI_RH_PortResumeComplete(IN PVOID ehciExtension,
IN PVOID Context)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
PUSHORT Port = Context;
DPRINT("EHCI_RH_PortResumeComplete: *Port - %x\n", *Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.ForcePortResume = 0;
PortSC.Suspend = 0;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
READ_REGISTER_ULONG(PortStatusReg);
EhciExtension->SuspendPortBits |= 1 << (*Port - 1);
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortSuspend(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT("EHCI_RH_ClearFeaturePortSuspend: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
EhciExtension->ResetPortBits |= 1 << (Port - 1);
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ForcePortResume = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
RegPacket.UsbPortRequestAsyncCallback(EhciExtension,
50, // TimerValue
&Port,
sizeof(Port),
EHCI_RH_PortResumeComplete);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortEnableChange(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT("EHCI_RH_ClearFeaturePortEnableChange: Port - %p\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.OverCurrentChange = 0;
PortSC.PortEnableDisableChange = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortConnectChange(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT_RH("EHCI_RH_ClearFeaturePortConnectChange: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
if (PortSC.ConnectStatusChange)
{
PortSC.ConnectStatusChange = 1;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 0;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
}
EhciExtension->ConnectPortBits &= ~(1 << (Port - 1));
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortResetChange(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
DPRINT("EHCI_RH_ClearFeaturePortConnectChange: Port - %x\n", Port);
ASSERT(Port != 0);
EhciExtension->FinishResetPortBits &= ~(1 << (Port - 1));
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortSuspendChange(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
DPRINT("EHCI_RH_ClearFeaturePortSuspendChange: Port - %x\n", Port);
ASSERT(Port != 0);
EhciExtension->SuspendPortBits &= ~(1 << (Port - 1));
return MP_STATUS_SUCCESS;
}
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortOvercurrentChange(IN PVOID ehciExtension,
IN USHORT Port)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG PortStatusReg;
EHCI_PORT_STATUS_CONTROL PortSC;
DPRINT_RH("EHCI_RH_ClearFeaturePortOvercurrentChange: Port - %x\n", Port);
ASSERT(Port != 0);
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
PortSC.ConnectStatusChange = 0;
PortSC.PortEnableDisableChange = 0;
PortSC.OverCurrentChange = 1;
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
return MP_STATUS_SUCCESS;
}
VOID
NTAPI
EHCI_RH_DisableIrq(IN PVOID ehciExtension)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG IntrStsReg;
EHCI_INTERRUPT_ENABLE IntrSts;
DPRINT_RH("EHCI_RH_DisableIrq: ... \n");
IntrStsReg = &EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG;
IntrSts.AsULONG = READ_REGISTER_ULONG(IntrStsReg);
EhciExtension->InterruptMask.PortChangeInterrupt = 0;
IntrSts.PortChangeInterrupt = 0;
if (IntrSts.Interrupt)
WRITE_REGISTER_ULONG(IntrStsReg, IntrSts.AsULONG);
}
VOID
NTAPI
EHCI_RH_EnableIrq(IN PVOID ehciExtension)
{
PEHCI_EXTENSION EhciExtension = ehciExtension;
PULONG IntrStsReg;
EHCI_INTERRUPT_ENABLE IntrSts;
DPRINT_RH("EHCI_RH_EnableIrq: ... \n");
IntrStsReg = &EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG;
IntrSts.AsULONG = READ_REGISTER_ULONG(IntrStsReg);
EhciExtension->InterruptMask.PortChangeInterrupt = 1;
IntrSts.PortChangeInterrupt = 1;
if (IntrSts.Interrupt)
WRITE_REGISTER_ULONG(IntrStsReg, IntrSts.AsULONG);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,337 @@
/*
* PROJECT: ReactOS USB EHCI Miniport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBEHCI declarations
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
*/
#ifndef USBEHCI_H__
#define USBEHCI_H__
#include <ntddk.h>
#include <windef.h>
#include <stdio.h>
#include <hubbusif.h>
#include <usbbusif.h>
#include <usbdlib.h>
#include <drivers/usbport/usbmport.h>
#include "hardware.h"
extern USBPORT_REGISTRATION_PACKET RegPacket;
#define EHCI_MAX_CONTROL_TRANSFER_SIZE 0x10000
#define EHCI_MAX_INTERRUPT_TRANSFER_SIZE 0x1000
#define EHCI_MAX_BULK_TRANSFER_SIZE 0x400000
#define EHCI_MAX_FS_ISO_TRANSFER_SIZE 0x40000
#define EHCI_MAX_HS_ISO_TRANSFER_SIZE 0x180000
#define EHCI_MAX_FS_ISO_HEADER_BUFFER_SIZE 0x1000
#define EHCI_MAX_HS_ISO_HEADER_BUFFER_SIZE 0x40000
#define EHCI_MAX_CONTROL_TD_COUNT 6
#define EHCI_MAX_INTERRUPT_TD_COUNT 4
#define EHCI_MAX_BULK_TD_COUNT 209
#define EHCI_FRAMES 32
#define EHCI_MICROFRAMES 8
#define EHCI_MAX_HC_SYSTEM_ERRORS 256
typedef struct _EHCI_PERIOD {
UCHAR Period;
UCHAR PeriodIdx;
UCHAR ScheduleMask;
} EHCI_PERIOD, *PEHCI_PERIOD;
/* Transfer Descriptor */
#define EHCI_HCD_TD_FLAG_ALLOCATED 0x01
#define EHCI_HCD_TD_FLAG_PROCESSED 0x02
#define EHCI_HCD_TD_FLAG_DONE 0x08
#define EHCI_HCD_TD_FLAG_ACTIVE 0x10
#define EHCI_HCD_TD_FLAG_DUMMY 0x20
struct _EHCI_HCD_QH;
struct _EHCI_ENDPOINT;
struct _EHCI_TRANSFER;
typedef struct _EHCI_HCD_TD {
/* Hardware*/
EHCI_QUEUE_TD HwTD;
/* Software */
ULONG PhysicalAddress;
ULONG TdFlags;
struct _EHCI_ENDPOINT * EhciEndpoint;
struct _EHCI_TRANSFER * EhciTransfer;
struct _EHCI_HCD_TD * NextHcdTD;
struct _EHCI_HCD_TD * AltNextHcdTD;
USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
ULONG LengthThisTD;
LIST_ENTRY DoneLink;
#ifdef _WIN64
ULONG Pad[31];
#else
ULONG Pad[40];
#endif
} EHCI_HCD_TD, *PEHCI_HCD_TD;
C_ASSERT(sizeof(EHCI_HCD_TD) == 0x100);
/* Queue Head */
#define EHCI_QH_FLAG_IN_SCHEDULE 0x01
#define EHCI_QH_FLAG_CLOSED 0x02
#define EHCI_QH_FLAG_STATIC 0x04
#define EHCI_QH_FLAG_STATIC_FAST 0x08
#define EHCI_QH_FLAG_UPDATING 0x10
#define EHCI_QH_FLAG_NUKED 0x20
typedef struct _EHCI_STATIC_QH {
/* Hardware part */
EHCI_QUEUE_HEAD HwQH;
/* Software part */
ULONG QhFlags;
ULONG PhysicalAddress;
struct _EHCI_HCD_QH * PrevHead;
#ifndef _WIN64
ULONG Pad2;
#endif
struct _EHCI_HCD_QH * NextHead;
#ifndef _WIN64
ULONG Pad3;
#endif
struct _EHCI_STATIC_QH * StaticQH;
#ifndef _WIN64
ULONG Pad4;
#endif
ULONG Period;
ULONG Ordinal;
#ifdef _WIN64
ULONG Pad[11];
#else
ULONG Pad[13];
#endif
} EHCI_STATIC_QH, *PEHCI_STATIC_QH;
C_ASSERT(sizeof(EHCI_STATIC_QH) == 0xA0);
#define EHCI_DUMMYQH_MAX_PACKET_LENGTH 64
typedef struct _EHCI_HCD_QH {
EHCI_STATIC_QH sqh;
#ifdef _WIN64
ULONG Pad[23];
#else
ULONG Pad[24];
#endif
} EHCI_HCD_QH, *PEHCI_HCD_QH;
C_ASSERT(sizeof(EHCI_HCD_QH) == 0x100);
/* EHCI Endpoint follows USBPORT Endpoint */
typedef struct _EHCI_ENDPOINT {
ULONG Reserved;
ULONG EndpointStatus;
ULONG EndpointState;
USBPORT_ENDPOINT_PROPERTIES EndpointProperties;
PVOID DmaBufferVA;
ULONG DmaBufferPA;
PEHCI_HCD_TD FirstTD;
ULONG MaxTDs;
ULONG PendingTDs;
ULONG RemainTDs;
PEHCI_HCD_QH QH;
PEHCI_HCD_TD HcdHeadP;
PEHCI_HCD_TD HcdTailP;
LIST_ENTRY ListTDs;
const EHCI_PERIOD * PeriodTable;
PEHCI_STATIC_QH StaticQH;
} EHCI_ENDPOINT, *PEHCI_ENDPOINT;
/* EHCI Transfer follows USBPORT Transfer */
typedef struct _EHCI_TRANSFER {
ULONG Reserved;
PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
ULONG USBDStatus;
ULONG TransferLen;
PEHCI_ENDPOINT EhciEndpoint;
ULONG PendingTDs;
ULONG TransferOnAsyncList;
} EHCI_TRANSFER, *PEHCI_TRANSFER;
typedef struct _EHCI_HC_RESOURCES {
ULONG PeriodicFrameList[EHCI_FRAME_LIST_MAX_ENTRIES]; // 4K-page aligned array
EHCI_STATIC_QH AsyncHead;
EHCI_STATIC_QH PeriodicHead[64];
UCHAR Padded[0x160];
EHCI_HCD_QH IsoDummyQH[EHCI_FRAME_LIST_MAX_ENTRIES];
} EHCI_HC_RESOURCES, *PEHCI_HC_RESOURCES;
#define EHCI_FLAGS_CONTROLLER_SUSPEND 0x01
#define EHCI_FLAGS_IDLE_SUPPORT 0x20
/* EHCI Extension follows USBPORT Extension */
typedef struct _EHCI_EXTENSION {
ULONG Reserved;
ULONG Flags;
PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters;
PEHCI_HW_REGISTERS OperationalRegs;
UCHAR FrameLengthAdjustment;
BOOLEAN IsStarted;
USHORT HcSystemErrors;
ULONG PortRoutingControl;
USHORT NumberOfPorts;
USHORT PortPowerControl;
EHCI_INTERRUPT_ENABLE InterruptMask;
EHCI_INTERRUPT_ENABLE InterruptStatus;
/* Schedule */
PEHCI_HC_RESOURCES HcResourcesVA;
ULONG HcResourcesPA;
PEHCI_STATIC_QH AsyncHead;
PEHCI_STATIC_QH PeriodicHead[64];
PEHCI_HCD_QH IsoDummyQHListVA;
ULONG IsoDummyQHListPA;
ULONG FrameIndex;
ULONG FrameHighPart;
/* Root Hub Bits */
ULONG ConnectPortBits;
ULONG SuspendPortBits;
ULONG ResetPortBits;
ULONG FinishResetPortBits;
/* Transfers */
ULONG PendingTransfers;
/* Lock Queue */
PEHCI_HCD_QH PrevQH;
PEHCI_HCD_QH LockQH;
PEHCI_HCD_QH NextQH;
/* Registers Copy Backup */
ULONG BackupPeriodiclistbase;
ULONG BackupAsynclistaddr;
ULONG BackupCtrlDSSegment;
ULONG BackupUSBCmd;
} EHCI_EXTENSION, *PEHCI_EXTENSION;
/* debug.c */
VOID
NTAPI
EHCI_DumpHwTD(
IN PEHCI_HCD_TD TD);
VOID
NTAPI
EHCI_DumpHwQH(
IN PEHCI_HCD_QH QH);
/* roothub.c */
MPSTATUS
NTAPI
EHCI_RH_ChirpRootPort(
IN PVOID ehciExtension,
IN USHORT Port);
VOID
NTAPI
EHCI_RH_GetRootHubData(
IN PVOID ohciExtension,
IN PVOID rootHubData);
MPSTATUS
NTAPI
EHCI_RH_GetStatus(
IN PVOID ohciExtension,
IN PUSHORT Status);
MPSTATUS
NTAPI
EHCI_RH_GetPortStatus(
IN PVOID ohciExtension,
IN USHORT Port,
IN PUSB_PORT_STATUS_AND_CHANGE PortStatus);
MPSTATUS
NTAPI
EHCI_RH_GetHubStatus(
IN PVOID ohciExtension,
IN PUSB_HUB_STATUS_AND_CHANGE HubStatus);
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortReset(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortPower(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortEnable(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_SetFeaturePortSuspend(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortEnable(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortPower(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortSuspend(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortEnableChange(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortConnectChange(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortResetChange(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortSuspendChange(
IN PVOID ohciExtension,
IN USHORT Port);
MPSTATUS
NTAPI
EHCI_RH_ClearFeaturePortOvercurrentChange(
IN PVOID ohciExtension,
IN USHORT Port);
VOID
NTAPI
EHCI_RH_DisableIrq(
IN PVOID ohciExtension);
VOID
NTAPI
EHCI_RH_EnableIrq(
IN PVOID ohciExtension);
#endif /* USBEHCI_H__ */

View file

@ -0,0 +1,5 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "USB EHCI miniport driver"
#define REACTOS_STR_INTERNAL_NAME "usbehci"
#define REACTOS_STR_ORIGINAL_FILENAME "usbehci.sys"
#include <reactos/version.rc>

View file

@ -285,6 +285,8 @@ typedef MPSTATUS
PVOID,
PUSHORT);
#define USB20_PORT_STATUS_RESERVED1_OWNED_BY_COMPANION (1 << 2)
typedef MPSTATUS
(NTAPI *PHCI_RH_GET_PORT_STATUS)(
PVOID,