https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a1a65e940aca88d4dd910…
commit a1a65e940aca88d4dd910433c186375942545e5c
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sat Sep 1 16:45:45 2018 +0100
Commit: Thomas Faber <18138474+ThFabba(a)users.noreply.github.com>
CommitDate: Sat Sep 1 17:45:45 2018 +0200
[USBUHCI_NEW] Bring-in the USB UHCI miniport driver created by Vadim Galyant. (#245)
---
drivers/usb/CMakeLists.txt | 1 +
drivers/usb/usbuhci_new/CMakeLists.txt | 15 +
drivers/usb/usbuhci_new/dbg_uhci.h | 49 +
drivers/usb/usbuhci_new/guid.c | 9 +
drivers/usb/usbuhci_new/hardware.h | 218 +++
drivers/usb/usbuhci_new/roothub.c | 473 ++++++
drivers/usb/usbuhci_new/usbuhci.c | 2757 ++++++++++++++++++++++++++++++++
drivers/usb/usbuhci_new/usbuhci.h | 297 ++++
drivers/usb/usbuhci_new/usbuhci.rc | 5 +
9 files changed, 3824 insertions(+)
diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt
index 51edb17b0c..72b486972c 100644
--- a/drivers/usb/CMakeLists.txt
+++ b/drivers/usb/CMakeLists.txt
@@ -9,3 +9,4 @@ add_subdirectory(usbport)
add_subdirectory(usbstor)
#add_subdirectory(usbstor_new)
add_subdirectory(usbuhci)
+#add_subdirectory(usbuhci_new)
diff --git a/drivers/usb/usbuhci_new/CMakeLists.txt
b/drivers/usb/usbuhci_new/CMakeLists.txt
new file mode 100644
index 0000000000..b46c724fff
--- /dev/null
+++ b/drivers/usb/usbuhci_new/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+list(APPEND SOURCE
+ roothub.c
+ usbuhci.c
+ usbuhci.h)
+
+add_library(usbuhci SHARED
+ ${SOURCE}
+ guid.c
+ usbuhci.rc)
+
+set_module_type(usbuhci kernelmodedriver)
+add_importlibs(usbuhci usbport usbd hal ntoskrnl)
+add_pch(usbuhci usbuhci.h SOURCE)
+add_cd_file(TARGET usbuhci DESTINATION reactos/system32/drivers NO_CAB FOR all)
diff --git a/drivers/usb/usbuhci_new/dbg_uhci.h b/drivers/usb/usbuhci_new/dbg_uhci.h
new file mode 100644
index 0000000000..50c03ca4bd
--- /dev/null
+++ b/drivers/usb/usbuhci_new/dbg_uhci.h
@@ -0,0 +1,49 @@
+#ifndef DBG_UHCI_H__
+#define DBG_UHCI_H__
+
+#if DBG
+
+ #ifndef NDEBUG_UHCI_TRACE
+ #define DPRINT_UHCI(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_UHCI __noop
+ #else
+ #define DPRINT_UHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
+ #endif
+ #endif
+
+ #ifndef NDEBUG_UHCI_IMPLEMENT
+
+ #define DPRINT_IMPL(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_IMPL __noop
+ #else
+ #define DPRINT_IMPL(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+ #endif
+
+ #endif
+
+
+#else /* not DBG */
+
+ #if defined(_MSC_VER)
+ #define DPRINT_UHCI __noop
+ #define DPRINT_IMPL __noop
+ #else
+ #define DPRINT_UHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
+ #define DPRINT_IMPL(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+ #endif /* _MSC_VER */
+
+#endif /* not DBG */
+
+#endif /* DBG_UHCI_H__ */
diff --git a/drivers/usb/usbuhci_new/guid.c b/drivers/usb/usbuhci_new/guid.c
new file mode 100644
index 0000000000..50a60369ff
--- /dev/null
+++ b/drivers/usb/usbuhci_new/guid.c
@@ -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 */
diff --git a/drivers/usb/usbuhci_new/hardware.h b/drivers/usb/usbuhci_new/hardware.h
new file mode 100644
index 0000000000..c9b6d4a42a
--- /dev/null
+++ b/drivers/usb/usbuhci_new/hardware.h
@@ -0,0 +1,218 @@
+#define UHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List
+#define UHCI_NUM_ROOT_HUB_PORTS 2
+
+/* UHCI HC I/O Registers offset (PUSHORT) */
+#define UHCI_USBCMD 0 // USB Command R/W
+#define UHCI_USBSTS 1 // USB Status R/WC
+#define UHCI_USBINTR 2 // USB Interrupt Enable R/W
+#define UHCI_FRNUM 3 // Frame Number R/W WORD writeable only
+#define UHCI_FRBASEADD 4 // Frame List Base Address R/W // 32 bit
+#define UHCI_SOFMOD 6 // Start Of Frame Modify R/W // 8 bit
+#define UHCI_PORTSC1 8 // Port 1 Status/Control R/WC WORD writeable only
+#define UHCI_PORTSC2 9 // Port 2 Status/Control R/WC WORD writeable only
+
+/* PCI Legacy Support */
+#define PCI_LEGSUP 0xC0 // Legacy Support register offset. R/WC
+#define PCI_LEGSUP_USBPIRQDEN 0x2000
+#define PCI_LEGSUP_CLEAR_SMI 0x8F00
+
+/* LEGSUP Legacy support register (PCI Configuration - Function 2) */
+typedef union _UHCI_PCI_LEGSUP {
+ struct {
+ USHORT Smi60Read : 1; // (60REN) Trap/SMI On 60h Read Enable. R/W.
+ USHORT Smi60Write : 1; // (60WEN) Trap/SMI On 60h Write Enable. R/W.
+ USHORT Smi64Read : 1; // (64REN) Trap/SMI On 64h Read Enable. R/W.
+ USHORT Smi64Write : 1; // (64WEN) Trap/SMI On 64h Write Enable. R/W.
+ USHORT SmiIrq : 1; // (USBSMIEN) Trap/SMI ON IRQ Enable. R/W.
+ USHORT A20Gate : 1; // (A20PTEN) A20Gate Pass Through Enable. R/W.
+ USHORT PassThroughStatus : 1; // (PSS) Pass Through Status. RO.
+ USHORT SmiEndPassThrough : 1; // (SMIEPTE) SMI At End Of Pass Through Enable. R/W.
+ USHORT TrapBy60ReadStatus : 1; // (TBY60R) Trap By 60h Read Status. R/WC.
+ USHORT TrapBy60WriteStatus : 1; // (TBY60W) Trap By 60h Write Status. R/WC.
+ USHORT TrapBy64ReadStatus : 1; // (TBY64R) Trap By 64h Read Status. R/WC.
+ USHORT TrapBy64WriteStatus : 1; // (TBY64W) Trap By 64h Write Status. R/WC.
+ USHORT UsbIrqStatus : 1; // (USBIRQS) USB IRQ Status. RO.
+ USHORT UsbPIRQ : 1; // (USBPIRQDEN) USB PIRQ Enable. R/W.
+ USHORT Reserved : 1;
+ USHORT EndA20GateStatus : 1; // (A20PTS) End OF A20GATE Pass Through Status. R/WC.
+ };
+ USHORT AsUSHORT;
+} UHCI_PCI_LEGSUP;
+
+C_ASSERT(sizeof(UHCI_PCI_LEGSUP) == sizeof(USHORT));
+
+/* USBCMD Command register */
+typedef union _UHCI_USB_COMMAND {
+ struct {
+ USHORT Run : 1;
+ USHORT HcReset : 1;
+ USHORT GlobalReset : 1;
+ USHORT GlobalSuspend : 1;
+ USHORT GlobalResume : 1; // Force Global Resume
+ USHORT SoftwareDebug : 1; // 0 - Normal Mode, 1 - Debug mode
+ USHORT ConfigureFlag : 1; // no effect on the hardware
+ USHORT MaxPacket : 1; // 0 = 32, 1 = 64
+ USHORT Reserved : 8;
+ };
+ USHORT AsUSHORT;
+} UHCI_USB_COMMAND;
+
+C_ASSERT(sizeof(UHCI_USB_COMMAND) == sizeof(USHORT));
+
+/* USBSTS Status register */
+#define UHCI_USB_STATUS_MASK 0x3F
+
+typedef union _UHCI_USB_STATUS {
+ struct {
+ USHORT Interrupt : 1; // due to IOC (Interrupt On Complete)
+ USHORT ErrorInterrupt : 1; // due to error
+ USHORT ResumeDetect : 1;
+ USHORT HostSystemError : 1; // PCI problems
+ USHORT HcProcessError : 1; // Schedule is buggy
+ USHORT HcHalted : 1;
+ USHORT Reserved : 10;
+ };
+ USHORT AsUSHORT;
+} UHCI_USB_STATUS;
+
+C_ASSERT(sizeof(UHCI_USB_STATUS) == sizeof(USHORT));
+
+/* USBINTR Interrupt enable register */
+typedef union _UHCI_INTERRUPT_ENABLE {
+ struct {
+ USHORT TimeoutCRC : 1; // Timeout/CRC error enable
+ USHORT ResumeInterrupt : 1;
+ USHORT InterruptOnComplete : 1;
+ USHORT ShortPacket : 1;
+ USHORT Reserved : 12;
+ };
+ USHORT AsUSHORT;
+} UHCI_INTERRUPT_ENABLE;
+
+C_ASSERT(sizeof(UHCI_INTERRUPT_ENABLE) == sizeof(USHORT));
+
+/* FRNUM Frame Number register */
+#define UHCI_FRNUM_FRAME_MASK 0x7FF
+#define UHCI_FRNUM_INDEX_MASK 0x3FF
+#define UHCI_FRNUM_OVERFLOW_LIST 0x400
+
+/* PORTSC(1|2) USB port status and control registers */
+typedef union _UHCI_PORT_STATUS_CONTROL {
+ struct {
+ USHORT CurrentConnectStatus : 1;
+ USHORT ConnectStatusChange : 1;
+ USHORT PortEnabledDisabled : 1;
+ USHORT PortEnableDisableChange : 1;
+ USHORT LineStatus : 2; // D+ and D-
+ USHORT ResumeDetect : 1;
+ USHORT Reserved1 : 1; // always 1
+ USHORT LowSpeedDevice : 1; // LS device Attached
+ USHORT PortReset : 1;
+ USHORT Reserved2 : 2; // Intel use it (not UHCI 1.1d spec)
+ USHORT Suspend : 1;
+ USHORT Reserved3 : 3; // write zeroes
+ };
+ USHORT AsUSHORT;
+} UHCI_PORT_STATUS_CONTROL;
+
+C_ASSERT(sizeof(UHCI_PORT_STATUS_CONTROL) == sizeof(USHORT));
+
+typedef struct _UHCI_HW_REGISTERS {
+ UHCI_USB_COMMAND HcCommand; // R/W
+ UHCI_USB_STATUS HcStatus; // R/WC
+ UHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W
+ USHORT FrameNumber; // R/W WORD writeable only
+ ULONG FrameAddress; // R/W
+ UCHAR SOF_Modify; // R/W
+ UCHAR Reserved[3];
+ UHCI_PORT_STATUS_CONTROL PortControl[UHCI_NUM_ROOT_HUB_PORTS]; // R/WC WORD writeable
only
+} UHCI_HW_REGISTERS, *PUHCI_HW_REGISTERS;
+
+/* Transfer Descriptor (TD) */
+#define UHCI_TD_STS_ACTIVE (1 << 7)
+#define UHCI_TD_STS_STALLED (1 << 6)
+#define UHCI_TD_STS_DATA_BUFFER_ERROR (1 << 5)
+#define UHCI_TD_STS_BABBLE_DETECTED (1 << 4)
+#define UHCI_TD_STS_NAK_RECEIVED (1 << 3)
+#define UHCI_TD_STS_TIMEOUT_CRC_ERROR (1 << 2)
+#define UHCI_TD_STS_BITSTUFF_ERROR (1 << 1)
+//#define UHCI_TD_STS_Reserved (1 << 0)
+
+#define UHCI_TD_VALID_LENGTH 0x4FF
+#define UHCI_TD_LENGTH_INVALID 0x7FE
+#define UHCI_TD_LENGTH_NULL 0x7FF
+
+typedef union _UHCI_CONTROL_STATUS {
+ struct {
+ ULONG ActualLength : 11; // encoded as n - 1
+ ULONG Reserved1 : 5;
+ ULONG Status : 8; // UHCI_TD_STS_ xxx
+ ULONG InterruptOnComplete : 1;
+ ULONG IsochronousType : 1;
+ ULONG LowSpeedDevice : 1;
+ ULONG ErrorCounter : 2;
+ ULONG ShortPacketDetect : 1;
+ ULONG Reserved2 : 2;
+ };
+ ULONG AsULONG;
+} UHCI_CONTROL_STATUS;
+
+C_ASSERT(sizeof(UHCI_CONTROL_STATUS) == sizeof(ULONG));
+
+#define UHCI_TD_PID_IN 0x69
+#define UHCI_TD_PID_OUT 0xE1
+#define UHCI_TD_PID_SETUP 0x2D
+
+#define UHCI_TD_PID_DATA0 0
+#define UHCI_TD_PID_DATA1 1
+
+typedef union _UHCI_TD_TOKEN {
+ struct {
+ ULONG PIDCode : 8;
+ ULONG DeviceAddress : 7;
+ ULONG Endpoint : 4;
+ ULONG DataToggle : 1;
+ ULONG Reserved : 1;
+ ULONG MaximumLength : 11;
+ };
+ ULONG AsULONG;
+} UHCI_TD_TOKEN;
+
+C_ASSERT(sizeof(UHCI_TD_TOKEN) == sizeof(ULONG));
+
+#define UHCI_TD_LINK_PTR_VALID (0 << 0)
+#define UHCI_TD_LINK_PTR_TERMINATE (1 << 0)
+#define UHCI_TD_LINK_PTR_TD (0 << 1)
+#define UHCI_TD_LINK_PTR_QH (1 << 1)
+#define UHCI_TD_LINK_PTR_BREADTH_FIRST (0 << 2)
+#define UHCI_TD_LINK_PTR_DEPTH_FIRST (1 << 2)
+#define UHCI_TD_LINK_POINTER_MASK 0xFFFFFFF0
+
+typedef struct _UHCI_TD { // Transfer Descriptors always aligned on 16-byte boundaries
+ ULONG NextElement;
+ UHCI_CONTROL_STATUS ControlStatus;
+ UHCI_TD_TOKEN Token;
+ ULONG Buffer;
+} UHCI_TD, *PUHCI_TD;
+
+C_ASSERT(sizeof(UHCI_TD) == 16);
+
+/* Queue Header (QH) */
+#define UHCI_QH_HEAD_LINK_PTR_VALID (0 << 0)
+#define UHCI_QH_HEAD_LINK_PTR_TERMINATE (1 << 0)
+#define UHCI_QH_HEAD_LINK_PTR_TD (0 << 1)
+#define UHCI_QH_HEAD_LINK_PTR_QH (1 << 1)
+#define UHCI_QH_HEAD_LINK_POINTER_MASK 0xFFFFFFF0
+
+#define UHCI_QH_ELEMENT_LINK_PTR_VALID (0 << 0)
+#define UHCI_QH_ELEMENT_LINK_PTR_TERMINATE (1 << 0)
+#define UHCI_QH_ELEMENT_LINK_PTR_TD (0 << 1)
+#define UHCI_QH_ELEMENT_LINK_PTR_QH (1 << 1)
+#define UHCI_QH_ELEMENT_LINK_POINTER_MASK 0xFFFFFFF0
+
+typedef struct _UHCI_QH { // Queue Heads must be aligned on a 16-byte boundary
+ ULONG NextQH;
+ ULONG NextElement;
+} UHCI_QH, *PUHCI_QH;
+
+C_ASSERT(sizeof(UHCI_QH) == 8);
diff --git a/drivers/usb/usbuhci_new/roothub.c b/drivers/usb/usbuhci_new/roothub.c
new file mode 100644
index 0000000000..9ec3612a0d
--- /dev/null
+++ b/drivers/usb/usbuhci_new/roothub.c
@@ -0,0 +1,473 @@
+#include "usbuhci.h"
+
+#define NDEBUG
+#include <debug.h>
+
+VOID
+NTAPI
+UhciRHGetRootHubData(IN PVOID uhciExtension,
+ IN PVOID rootHubData)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUSBPORT_ROOT_HUB_DATA RootHubData = rootHubData;
+ USBPORT_HUB_11_CHARACTERISTICS HubCharacteristics;
+
+ DPRINT("UhciRHGetRootHubData: ...\n");
+
+ HubCharacteristics.AsUSHORT = 0;
+ HubCharacteristics.PowerControlMode = 1;
+ HubCharacteristics.NoPowerSwitching = 1;
+ HubCharacteristics.OverCurrentProtectionMode = 1;
+
+ if (UhciExtension->HcFlavor != UHCI_Piix4)
+ HubCharacteristics.NoOverCurrentProtection = 1;
+
+ RootHubData->NumberOfPorts = UHCI_NUM_ROOT_HUB_PORTS;
+ RootHubData->HubCharacteristics.Usb11HubCharacteristics = HubCharacteristics;
+ RootHubData->PowerOnToPowerGood = 1;
+ RootHubData->HubControlCurrent = 0;
+}
+
+MPSTATUS
+NTAPI
+UhciRHGetStatus(IN PVOID uhciExtension,
+ IN PUSHORT Status)
+{
+ DPRINT("UhciRHGetStatus: ...\n");
+ *Status = UHCI_RH_STATUS_SUCCESS;
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHGetPortStatus(IN PVOID uhciExtension,
+ IN USHORT Port,
+ IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+ ULONG PortBit;
+ USB_20_PORT_STATUS portStatus;
+ USB_20_PORT_CHANGE portChange;
+
+ //DPRINT("UhciRHGetPortStatus: ...\n");
+
+ ASSERT(Port);
+
+ BaseRegister = UhciExtension->BaseRegister;
+ PortControlRegister = &BaseRegister->PortControl[Port-1].AsUSHORT;
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ portStatus.AsUshort16 = 0;
+ portChange.AsUshort16 = 0;
+
+ portStatus.CurrentConnectStatus = PortControl.CurrentConnectStatus;
+ portStatus.PortEnabledDisabled = PortControl.PortEnabledDisabled;
+
+ if (PortControl.Suspend == 1 &&
+ PortControl.PortEnabledDisabled == 1)
+ {
+ portStatus.Suspend = 1;
+ }
+ else
+ {
+ portStatus.Suspend = 0;
+ }
+
+ //if (UhciExtension->HcFlavor == UHCI_Piix4) // check will work after supporting
HcFlavor in usbport.
+ if (TRUE)
+ {
+ portStatus.OverCurrent = PortControl.Reserved2 & 1;
+ portStatus.PortPower = (~PortControl.Reserved2 & 1);
+ portChange.OverCurrentIndicatorChange = (PortControl.Reserved2 & 2) != 0;
+ }
+ else
+ {
+ portStatus.OverCurrent = 0;
+ portStatus.PortPower = 1;
+ portChange.OverCurrentIndicatorChange = 0;
+ }
+
+ portStatus.HighSpeedDeviceAttached = 0;
+
+ portStatus.Reset = PortControl.PortReset;
+ portStatus.LowSpeedDeviceAttached = PortControl.LowSpeedDevice;
+ portChange.ConnectStatusChange = PortControl.ConnectStatusChange;
+
+ PortBit = 1 << (Port - 1);
+
+ if (UhciExtension->ResetPortMask & PortBit)
+ {
+ portChange.ConnectStatusChange = 0;
+ portChange.PortEnableDisableChange = 0;
+ }
+ else
+ {
+ portChange.PortEnableDisableChange = PortControl.PortEnableDisableChange;
+ }
+
+ if (UhciExtension->SuspendChangePortMask & PortBit)
+ portChange.SuspendChange = 1;
+
+ if (UhciExtension->ResetChangePortMask & PortBit)
+ portChange.ResetChange = 1;
+
+ PortStatus->PortStatus.Usb20PortStatus = portStatus;
+ PortStatus->PortChange.Usb20PortChange = portChange;
+
+ //DPRINT("UhciRHGetPortStatus: PortControl.AsUSHORT[%x] - %X, PortStatus -
%X\n",
+ // Port,
+ // PortControl.AsUSHORT,
+ // PortStatus->AsUlong32);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHGetHubStatus(IN PVOID uhciExtension,
+ IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
+{
+ //DPRINT("UhciRHGetHubStatus: ...\n");
+ HubStatus->AsUlong32 = 0;
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+UhciRHPortResetComplete(IN PVOID uhciExtension,
+ IN PVOID pPort)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ ULONG ix;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+ USHORT Port;
+
+ DPRINT("UhciRHPortResetComplete: ...\n");
+
+ BaseRegister = UhciExtension->BaseRegister;
+
+ Port = *(PUSHORT)pPort;
+ ASSERT(Port);
+
+ PortControlRegister = &BaseRegister->PortControl[Port - 1].AsUSHORT;
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ PortControl.ConnectStatusChange = 0;
+ PortControl.PortEnableDisableChange = 0;
+ PortControl.PortReset = 0;
+
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+
+ while (UhciHardwarePresent(UhciExtension))
+ {
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ if (PortControl.PortReset == 0)
+ break;
+ }
+
+ for (ix = 0; ix < 10; ++ix)
+ {
+ KeStallExecutionProcessor(50);
+
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ if (PortControl.PortEnabledDisabled == 1)
+ break;
+
+ PortControl.PortEnabledDisabled = 1;
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+ }
+
+ PortControl.ConnectStatusChange = 1;
+ PortControl.PortEnableDisableChange = 1;
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+
+ if (UhciExtension->HcFlavor == UHCI_VIA &&
+ UhciExtension->HcFlavor == UHCI_VIA_x01 &&
+ UhciExtension->HcFlavor == UHCI_VIA_x02 &&
+ UhciExtension->HcFlavor == UHCI_VIA_x03 &&
+ UhciExtension->HcFlavor == UHCI_VIA_x04)
+ {
+ DPRINT("UhciRHPortResetComplete: Via chip. FIXME\n");
+ DbgBreakPoint();
+ return;
+ }
+
+ UhciExtension->ResetChangePortMask |= (1 << (Port - 1));
+ UhciExtension->ResetPortMask &= ~(1 << (Port - 1));
+
+ RegPacket.UsbPortInvalidateRootHub(UhciExtension);
+}
+
+VOID
+NTAPI
+UhciRHSetFeaturePortResetWorker(IN PUHCI_EXTENSION UhciExtension,
+ IN PUSHORT pPort)
+{
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+ USHORT Port;
+
+ DPRINT("UhciRHSetFeaturePortResetWorker: ...\n");
+
+ BaseRegister = UhciExtension->BaseRegister;
+
+ Port = *(PUSHORT)pPort;
+ ASSERT(Port);
+
+ PortControlRegister = &BaseRegister->PortControl[Port - 1].AsUSHORT;
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ PortControl.ConnectStatusChange = 0;
+ PortControl.PortEnableDisableChange = 0;
+ PortControl.PortReset = 1;
+
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+
+ RegPacket.UsbPortRequestAsyncCallback(UhciExtension,
+ 10, // TimerValue
+ pPort,
+ sizeof(pPort),
+ UhciRHPortResetComplete);
+}
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortReset(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ ULONG ResetPortMask;
+ ULONG PortBit;
+
+ DPRINT("UhciRHSetFeaturePortReset: ...\n");
+
+ ASSERT(Port);
+
+ ResetPortMask = UhciExtension->ResetPortMask;
+ PortBit = 1 << (Port - 1);
+
+ if (ResetPortMask & PortBit)
+ return MP_STATUS_FAILURE;
+
+ UhciExtension->ResetPortMask = ResetPortMask | PortBit;
+
+ if (UhciExtension->HcFlavor == UHCI_VIA &&
+ UhciExtension->HcFlavor == UHCI_VIA_x01 &&
+ UhciExtension->HcFlavor == UHCI_VIA_x02 &&
+ UhciExtension->HcFlavor == UHCI_VIA_x03 &&
+ UhciExtension->HcFlavor == UHCI_VIA_x04)
+ {
+ DPRINT1("UhciRHSetFeaturePortReset: Via chip. FIXME\n");
+ return MP_STATUS_SUCCESS;
+ }
+
+ UhciRHSetFeaturePortResetWorker(UhciExtension, &Port);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortPower(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ DPRINT("UhciRHSetFeaturePortPower: ...\n");
+ ASSERT(Port);
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHPortEnable(IN PVOID uhciExtension,
+ IN USHORT Port,
+ IN BOOLEAN IsSet)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+
+ DPRINT("UhciRHPortEnable: ...\n");
+
+ ASSERT(Port);
+
+ BaseRegister = UhciExtension->BaseRegister;
+ PortControlRegister = &BaseRegister->PortControl[Port-1].AsUSHORT;
+
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ PortControl.ConnectStatusChange = 0;
+ PortControl.PortEnableDisableChange = 0;
+
+ if (IsSet)
+ PortControl.PortEnabledDisabled = 1;
+ else
+ PortControl.PortEnabledDisabled = 0;
+
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortEnable(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ DPRINT("UhciRHSetFeaturePortEnable: ...\n");
+ ASSERT(Port);
+ return UhciRHPortEnable(UhciExtension, Port, TRUE);
+}
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortSuspend(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ DPRINT("UhciRHSetFeaturePortSuspend: UNIMPLEMENTED. FIXME\n");
+ ASSERT(Port);
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortEnable(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ DPRINT("UhciRHClearFeaturePortEnable: ...\n");
+ ASSERT(Port);
+ return UhciRHPortEnable(UhciExtension, Port, FALSE);
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortPower(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ DPRINT("UhciRHClearFeaturePortPower: UNIMPLEMENTED. FIXME\n");
+ ASSERT(Port);
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortSuspend(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ DPRINT("UhciRHClearFeaturePortSuspend: UNIMPLEMENTED. FIXME\n");
+ ASSERT(Port);
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortEnableChange(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+
+ DPRINT("UhciRHClearFeaturePortEnableChange: ...\n");
+
+ ASSERT(Port);
+
+ BaseRegister = UhciExtension->BaseRegister;
+ PortControlRegister = (PUSHORT)&BaseRegister->PortControl[Port - 1];
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ PortControl.ConnectStatusChange = 0;
+ PortControl.PortEnableDisableChange = 1;
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortConnectChange(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+
+ DPRINT("UhciRHClearFeaturePortConnectChange: Port - %04X\n", Port);
+
+ ASSERT(Port);
+
+ BaseRegister = UhciExtension->BaseRegister;
+ PortControlRegister = (PUSHORT)&BaseRegister->PortControl[Port - 1];
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ if (PortControl.ConnectStatusChange == 1)
+ {
+ /* WC (Write Clear) bits */
+ PortControl.PortEnableDisableChange = 0;
+ PortControl.ConnectStatusChange = 1;
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+ }
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortResetChange(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ DPRINT("UhciRHClearFeaturePortResetChange: ...\n");
+ ASSERT(Port);
+ UhciExtension->ResetChangePortMask &= ~(1 << (Port - 1));
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortSuspendChange(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ DPRINT("UhciRHClearFeaturePortSuspendChange: UNIMPLEMENTED. FIXME\n");
+ ASSERT(Port);
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortOvercurrentChange(IN PVOID uhciExtension,
+ IN USHORT Port)
+{
+ DPRINT("UhciRHClearFeaturePortOvercurrentChange: UNIMPLEMENTED. FIXME\n");
+ ASSERT(Port);
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+UhciRHDisableIrq(IN PVOID uhciExtension)
+{
+ /* Do nothing */
+ return;
+}
+
+VOID
+NTAPI
+UhciRHEnableIrq(IN PVOID uhciExtension)
+{
+ /* Do nothing */
+ return;
+}
+
diff --git a/drivers/usb/usbuhci_new/usbuhci.c b/drivers/usb/usbuhci_new/usbuhci.c
new file mode 100644
index 0000000000..eed9b0b48d
--- /dev/null
+++ b/drivers/usb/usbuhci_new/usbuhci.c
@@ -0,0 +1,2757 @@
+#include "usbuhci.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_UHCI_TRACE
+#define NDEBUG_UHCI_IMPLEMENT
+#include "dbg_uhci.h"
+
+USBPORT_REGISTRATION_PACKET RegPacket;
+
+VOID
+NTAPI
+UhciDumpHcdQH(PUHCI_HCD_QH QH)
+{
+ DPRINT("QH - %p\n", QH);
+ DPRINT("NextQH - %p\n", QH->HwQH.NextQH);
+ DPRINT("NextElement - %p\n", QH->HwQH.NextElement);
+
+ DPRINT("PhysicalAddress - %p\n", QH->PhysicalAddress);
+ DPRINT("QhFlags - %X\n", QH->QhFlags);
+ DPRINT("NextHcdQH - %X\n", QH->NextHcdQH);
+ DPRINT("PrevHcdQH - %X\n", QH->PrevHcdQH);
+ DPRINT("UhciEndpoint - %X\n", QH->UhciEndpoint);
+}
+
+VOID
+NTAPI
+UhciDumpHcdTD(PUHCI_HCD_TD TD)
+{
+ DPRINT("TD - %p\n", TD);
+ DPRINT("NextElement - %p\n", TD->HwTD.NextElement);
+ DPRINT("ControlStatus - %08X\n", TD->HwTD.ControlStatus.AsULONG);
+ DPRINT("Token - %p\n", TD->HwTD.Token.AsULONG);
+if (TD->HwTD.Buffer)
+ DPRINT("Buffer - %p\n", TD->HwTD.Buffer);
+
+if (TD->SetupPacket.bmRequestType.B)
+ DPRINT("bmRequestType - %02X\n", TD->SetupPacket.bmRequestType.B);
+if (TD->SetupPacket.bRequest)
+ DPRINT("bRequest - %02X\n", TD->SetupPacket.bRequest);
+if (TD->SetupPacket.wValue.W)
+ DPRINT("wValue - %04X\n", TD->SetupPacket.wValue.W);
+if (TD->SetupPacket.wIndex.W)
+ DPRINT("wIndex - %04X\n", TD->SetupPacket.wIndex.W);
+if (TD->SetupPacket.wLength)
+ DPRINT("wLength - %04X\n", TD->SetupPacket.wLength);
+
+ DPRINT("PhysicalAddress - %p\n", TD->PhysicalAddress);
+ DPRINT("Flags - %X\n", TD->Flags);
+ DPRINT("NextHcdTD - %p\n", TD->NextHcdTD);
+ DPRINT("UhciTransfer - %p\n", TD->UhciTransfer);
+}
+
+VOID
+NTAPI
+UhciFixDataToggle(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUHCI_HCD_TD TD,
+ IN BOOL DataToggle)
+{
+ DPRINT_UHCI("UhciFixDataToggle: UhciExtension - %p, UhciEndpoint - %p,
DataToggle - %X\n",
+ UhciExtension,
+ UhciEndpoint,
+ DataToggle);
+
+ while (TD)
+ {
+ TD->HwTD.Token.DataToggle = !TD->HwTD.Token.DataToggle;
+ DataToggle = !DataToggle;
+
+ TD = TD->NextHcdTD;
+ }
+
+ UhciEndpoint->DataToggle = DataToggle;
+}
+
+VOID
+NTAPI
+UhciCleanupFrameListEntry(IN PUHCI_EXTENSION UhciExtension,
+ IN ULONG Index)
+{
+ PUHCI_HC_RESOURCES UhciResources;
+ ULONG PhysicalAddress;
+ ULONG HeadIdx;
+
+ UhciResources = UhciExtension->HcResourcesVA;
+
+ if (Index == 0)
+ {
+ PhysicalAddress = UhciExtension->StaticTD->PhysicalAddress;
+
+ UhciResources->FrameList[0] = PhysicalAddress |
+ UHCI_FRAME_LIST_POINTER_TD;
+ }
+ else
+ {
+ HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms) +
+ (Index & (ENDPOINT_INTERRUPT_32ms - 1));
+
+ PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
+
+ UhciResources->FrameList[Index] = PhysicalAddress |
+ UHCI_FRAME_LIST_POINTER_QH;
+ }
+}
+
+VOID
+NTAPI
+UhciCleanupFrameList(IN PUHCI_EXTENSION UhciExtension,
+ IN BOOLEAN IsAllEntries)
+{
+ ULONG NewFrameNumber;
+ ULONG OldFrameNumber;
+ ULONG ix;
+
+ DPRINT_UHCI("UhciCleanupFrameList: [%p] All - %x\n",
+ UhciExtension, IsAllEntries);
+
+ // FIXME: using UhciExtension->LockFrameList after supporting ISOs.
+
+ NewFrameNumber = UhciGet32BitFrameNumber(UhciExtension);
+ OldFrameNumber = UhciExtension->FrameNumber;
+
+ if ((NewFrameNumber - OldFrameNumber) < UHCI_FRAME_LIST_MAX_ENTRIES &&
+ IsAllEntries == FALSE)
+ {
+ for (ix = OldFrameNumber & UHCI_FRAME_LIST_INDEX_MASK;
+ ix != (NewFrameNumber & UHCI_FRAME_LIST_INDEX_MASK);
+ ix = (ix + 1) & UHCI_FRAME_LIST_INDEX_MASK)
+ {
+ UhciCleanupFrameListEntry(UhciExtension, ix);
+ }
+ }
+ else
+ {
+ for (ix = 0; ix < UHCI_FRAME_LIST_MAX_ENTRIES; ++ix)
+ {
+ UhciCleanupFrameListEntry(UhciExtension, ix);
+ }
+ }
+
+ UhciExtension->FrameNumber = NewFrameNumber;
+}
+
+VOID
+NTAPI
+UhciUpdateCounter(IN PUHCI_EXTENSION UhciExtension)
+{
+ ULONG FrameNumber;
+
+ FrameNumber = READ_PORT_USHORT(&UhciExtension->BaseRegister->FrameNumber);
+ FrameNumber &= UHCI_FRNUM_FRAME_MASK;
+
+ if ((FrameNumber ^ UhciExtension->FrameHighPart) & UHCI_FRNUM_OVERFLOW_LIST)
+ {
+ UhciExtension->FrameHighPart += UHCI_FRAME_LIST_MAX_ENTRIES;
+
+ DPRINT_UHCI("UhciUpdateCounter: UhciExtension->FrameHighPart -
%lX\n",
+ UhciExtension->FrameHighPart);
+ }
+}
+
+VOID
+NTAPI
+UhciSetNextQH(IN PUHCI_HCD_QH QH,
+ IN PUHCI_HCD_QH NextQH)
+{
+ DPRINT_UHCI("UhciSetNextQH: QH - %p, NextQH - %p\n", QH, NextQH);
+
+ QH->HwQH.NextQH = NextQH->PhysicalAddress | UHCI_QH_HEAD_LINK_PTR_QH;
+ QH->NextHcdQH = NextQH;
+
+ NextQH->PrevHcdQH = QH;
+ NextQH->QhFlags |= UHCI_HCD_QH_FLAG_ACTIVE;
+}
+
+MPSTATUS
+NTAPI
+UhciOpenEndpoint(IN PVOID uhciExtension,
+ IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+ IN PVOID uhciEndpoint)
+{
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ ULONG TransferType;
+ ULONG_PTR BufferVA;
+ ULONG BufferPA;
+ ULONG ix;
+ ULONG TdCount;
+ PUHCI_HCD_TD TD;
+ SIZE_T BufferLength;
+ PUHCI_HCD_QH QH;
+
+ RtlCopyMemory(&UhciEndpoint->EndpointProperties,
+ EndpointProperties,
+ sizeof(UhciEndpoint->EndpointProperties));
+
+ InitializeListHead(&UhciEndpoint->ListTDs);
+
+ UhciEndpoint->EndpointLock = 0;
+ UhciEndpoint->DataToggle = UHCI_TD_PID_DATA0;
+ UhciEndpoint->Flags = 0;
+
+ TransferType = EndpointProperties->TransferType;
+
+ DPRINT("UhciOpenEndpoint: UhciEndpoint - %p, TransferType - %x\n",
+ UhciEndpoint,
+ TransferType);
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+ TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ {
+ UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO;
+ }
+
+ BufferVA = EndpointProperties->BufferVA;
+ BufferPA = EndpointProperties->BufferPA;
+
+ BufferLength = EndpointProperties->BufferLength;
+
+ /* For Isochronous transfers not used QHs (only TDs) */
+ if (EndpointProperties->TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ {
+ /* Initialize HCD Queue Head */
+ UhciEndpoint->QH = (PUHCI_HCD_QH)BufferVA;
+
+ QH = UhciEndpoint->QH;
+
+ QH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ QH->PhysicalAddress = BufferPA;
+
+ QH->NextHcdQH = QH;
+ QH->PrevHcdQH = QH;
+ QH->UhciEndpoint = UhciEndpoint;
+
+ BufferVA += sizeof(UHCI_HCD_QH);
+ BufferPA += sizeof(UHCI_HCD_QH);
+
+ BufferLength -= sizeof(UHCI_HCD_QH);
+ }
+
+ /* Initialize HCD Transfer Descriptors */
+ TdCount = BufferLength / sizeof(UHCI_HCD_TD);
+ UhciEndpoint->MaxTDs = TdCount;
+
+ UhciEndpoint->FirstTD = (PUHCI_HCD_TD)BufferVA;
+ UhciEndpoint->AllocatedTDs = 0;
+
+ RtlZeroMemory(UhciEndpoint->FirstTD, TdCount * sizeof(UHCI_HCD_TD));
+
+ for (ix = 0; ix < UhciEndpoint->MaxTDs; ix++)
+ {
+ TD = &UhciEndpoint->FirstTD[ix];
+ TD->PhysicalAddress = BufferPA;
+ BufferPA += sizeof(UHCI_HCD_TD);
+ }
+
+ UhciEndpoint->TailTD = NULL;
+ UhciEndpoint->HeadTD = NULL;
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciReopenEndpoint(IN PVOID uhciExtension,
+ IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+ IN PVOID uhciEndpoint)
+{
+ DPRINT_IMPL("Uhci: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+UhciQueryEndpointRequirements(IN PVOID uhciExtension,
+ IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+ IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements)
+{
+ ULONG TransferType;
+ ULONG TdCount;
+
+ DPRINT("UhciQueryEndpointRequirements: ... \n");
+
+ TransferType = EndpointProperties->TransferType;
+
+ switch (TransferType)
+ {
+ case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
+ DPRINT("UhciQueryEndpointRequirements: IsoTransfer\n");
+ TdCount = 2 * UHCI_MAX_ISO_TD_COUNT;
+
+ EndpointRequirements->HeaderBufferSize = 0 + // Iso queue is have not
Queue Heads
+ TdCount * sizeof(UHCI_HCD_TD);
+
+ EndpointRequirements->MaxTransferSize = UHCI_MAX_ISO_TRANSFER_SIZE;
+ break;
+
+ case USBPORT_TRANSFER_TYPE_CONTROL:
+ DPRINT("UhciQueryEndpointRequirements: ControlTransfer\n");
+ TdCount = EndpointProperties->MaxTransferSize /
+ EndpointProperties->TotalMaxPacketSize;
+
+ TdCount += 2; // First + Last TDs
+
+ EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) +
+ TdCount * sizeof(UHCI_HCD_TD);
+
+ EndpointRequirements->MaxTransferSize =
EndpointProperties->MaxTransferSize;
+ break;
+
+ case USBPORT_TRANSFER_TYPE_BULK:
+ DPRINT("UhciQueryEndpointRequirements: BulkTransfer\n");
+ TdCount = 2 * UHCI_MAX_BULK_TRANSFER_SIZE /
+ EndpointProperties->TotalMaxPacketSize;
+
+ EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) +
+ TdCount * sizeof(UHCI_HCD_TD);
+
+ EndpointRequirements->MaxTransferSize = UHCI_MAX_BULK_TRANSFER_SIZE;
+ break;
+
+ case USBPORT_TRANSFER_TYPE_INTERRUPT:
+ DPRINT("UhciQueryEndpointRequirements: InterruptTransfer\n");
+ TdCount = 2 * UHCI_MAX_INTERRUPT_TD_COUNT;
+
+ EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) +
+ TdCount * sizeof(UHCI_HCD_TD);
+
+ EndpointRequirements->MaxTransferSize = UHCI_MAX_INTERRUPT_TD_COUNT *
+
EndpointProperties->TotalMaxPacketSize;
+ break;
+
+ default:
+ DPRINT1("UhciQueryEndpointRequirements: Unknown TransferType -
%x\n",
+ TransferType);
+ DbgBreakPoint();
+ break;
+ }
+}
+
+VOID
+NTAPI
+UhciCloseEndpoint(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint,
+ IN BOOLEAN IsDoDisablePeriodic)
+{
+ DPRINT_IMPL("UhciCloseEndpoint: UNIMPLEMENTED. FIXME\n");
+}
+
+MPSTATUS
+NTAPI
+UhciTakeControlHC(IN PUHCI_EXTENSION UhciExtension,
+ IN PUSBPORT_RESOURCES Resources)
+{
+ LARGE_INTEGER EndTime;
+ LARGE_INTEGER CurrentTime;
+ ULONG ResourcesTypes;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT StatusRegister;
+ UHCI_PCI_LEGSUP LegacySupport;
+ UHCI_PCI_LEGSUP LegacyMask;
+ UHCI_USB_COMMAND Command;
+ UHCI_USB_STATUS HcStatus;
+ MPSTATUS MpStatus = MP_STATUS_SUCCESS;
+
+ DPRINT("UhciTakeControlHC: Resources->ResourcesTypes - %x\n",
+ Resources->ResourcesTypes);
+
+ ResourcesTypes = Resources->ResourcesTypes;
+
+ if ((ResourcesTypes & (USBPORT_RESOURCES_PORT | USBPORT_RESOURCES_INTERRUPT)) !=
+ (USBPORT_RESOURCES_PORT | USBPORT_RESOURCES_INTERRUPT))
+ {
+ DPRINT1("UhciTakeControlHC: MP_STATUS_ERROR\n");
+ MpStatus = MP_STATUS_ERROR;
+ }
+
+ BaseRegister = UhciExtension->BaseRegister;
+ StatusRegister = &BaseRegister->HcStatus.AsUSHORT;
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ TRUE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+
+ UhciDisableInterrupts(UhciExtension);
+
+ Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT);
+
+ Command.Run = 0;
+ Command.GlobalReset = 0;
+ Command.ConfigureFlag = 0;
+
+ WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
+
+ KeQuerySystemTime(&EndTime);
+ EndTime.QuadPart += 100 * 10000; // 100 ms
+
+ HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister);
+ DPRINT("UhciTakeControlHC: HcStatus.AsUSHORT - %04X\n",
HcStatus.AsUSHORT);
+
+ while (HcStatus.HcHalted == 0)
+ {
+ HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister);
+ KeQuerySystemTime(&CurrentTime);
+
+ if (CurrentTime.QuadPart >= EndTime.QuadPart)
+ break;
+ }
+
+ WRITE_PORT_USHORT(StatusRegister, UHCI_USB_STATUS_MASK);
+
+ LegacyMask.AsUSHORT = 0;
+ LegacyMask.Smi60Read = 1;
+ LegacyMask.Smi60Write = 1;
+ LegacyMask.Smi64Read = 1;
+ LegacyMask.Smi64Write = 1;
+ LegacyMask.SmiIrq = 1;
+ LegacyMask.A20Gate = 1;
+ LegacyMask.SmiEndPassThrough = 1;
+
+ if (LegacySupport.AsUSHORT & LegacyMask.AsUSHORT)
+ {
+ DPRINT("UhciTakeControlHC: LegacySupport.AsUSHORT - %04X\n",
+ LegacySupport.AsUSHORT);
+
+ Resources->LegacySupport = 1;
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ TRUE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+ LegacySupport.AsUSHORT = 0;
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ FALSE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+ }
+
+ return MpStatus;
+}
+
+MPSTATUS
+NTAPI
+UhciInitializeHardware(IN PUHCI_EXTENSION UhciExtension)
+{
+ PUHCI_HW_REGISTERS BaseRegister;
+ UHCI_USB_COMMAND Command;
+ UHCI_USB_STATUS StatusMask;
+
+ DPRINT("UhciInitializeHardware: UhciExtension - %p\n", UhciExtension);
+ DPRINT("UhciInitializeHardware: VIA HW FIXME\n"); // after supporting
HcFlavor in usbport
+
+ BaseRegister = UhciExtension->BaseRegister;
+
+ /* Save SOF Timing Value */
+ UhciExtension->SOF_Modify = READ_PORT_UCHAR(&BaseRegister->SOF_Modify);
+
+ RegPacket.UsbPortWait(UhciExtension, 20);
+
+ Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT);
+
+ /* Global Reset */
+ Command.AsUSHORT = 0;
+ Command.GlobalReset = 1;
+ WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
+
+ RegPacket.UsbPortWait(UhciExtension, 20);
+
+ Command.AsUSHORT = 0;
+ WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
+
+ /* Set MaxPacket for full speed bandwidth reclamation */
+ Command.AsUSHORT = 0;
+ Command.MaxPacket = 1; // 64 bytes
+ WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
+
+ /* Restore SOF Timing Value */
+ WRITE_PORT_UCHAR(&BaseRegister->SOF_Modify, UhciExtension->SOF_Modify);
+
+ StatusMask = UhciExtension->StatusMask;
+
+ StatusMask.Interrupt = 1;
+ StatusMask.ErrorInterrupt = 1;
+ StatusMask.ResumeDetect = 1;
+ StatusMask.HostSystemError = 1;
+
+ UhciExtension->StatusMask = StatusMask;
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciInitializeSchedule(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_HC_RESOURCES HcResourcesVA,
+ IN ULONG hcResourcesPA)
+{
+ PUHCI_HCD_QH IntQH;
+ ULONG IntQhPA;
+ PUHCI_HCD_QH StaticControlHead;
+ ULONG StaticControlHeadPA;
+ PUHCI_HCD_QH StaticBulkHead;
+ ULONG StaticBulkHeadPA;
+ PUHCI_HCD_TD StaticBulkTD;
+ ULONG StaticBulkTdPA;
+ PUHCI_HCD_TD StaticTD;
+ ULONG StaticTdPA;
+ PUHCI_HCD_TD StaticSofTD;
+ ULONG StaticSofTdPA;
+ ULONG PhysicalAddress;
+ ULONG Idx;
+ ULONG HeadIdx;
+ UCHAR FrameIdx;
+
+ DPRINT("UhciInitializeSchedule: Ext[%p], VA - %p, PA - %lx\n",
+ UhciExtension,
+ HcResourcesVA,
+ hcResourcesPA);
+
+ /* Build structure (tree) of static QHs
+ for interrupt and isochronous transfers */
+ for (FrameIdx = 0; FrameIdx < INTERRUPT_ENDPOINTs; FrameIdx++)
+ {
+ IntQH = &HcResourcesVA->StaticIntHead[FrameIdx];
+ IntQhPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES,
StaticIntHead[FrameIdx]);
+
+ RtlZeroMemory(IntQH, sizeof(UHCI_HCD_QH));
+
+ IntQH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ IntQH->PhysicalAddress = IntQhPA;
+
+ UhciExtension->IntQH[FrameIdx] = IntQH;
+
+ if (FrameIdx == 0)
+ UhciSetNextQH(IntQH, UhciExtension->IntQH[0]);
+ else
+ UhciSetNextQH(IntQH, UhciExtension->IntQH[(FrameIdx - 1) / 2]);
+ }
+
+ /* Initialize static QH for control transfers */
+ StaticControlHead = &HcResourcesVA->StaticControlHead;
+ StaticControlHeadPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES,
StaticControlHead);
+
+ RtlZeroMemory(StaticControlHead, sizeof(UHCI_HCD_QH));
+
+ StaticControlHead->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ StaticControlHead->PhysicalAddress = StaticControlHeadPA;
+
+ UhciSetNextQH(UhciExtension->IntQH[0],StaticControlHead);
+
+ UhciExtension->ControlQH = StaticControlHead;
+
+ /* Initialize static QH for bulk transfers */
+ StaticBulkHead = &HcResourcesVA->StaticBulkHead;
+ StaticBulkHeadPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticBulkHead);
+
+ RtlZeroMemory(StaticBulkHead, sizeof(UHCI_HCD_QH));
+
+ StaticBulkHead->PhysicalAddress = StaticBulkHeadPA;
+ PhysicalAddress = StaticBulkHeadPA | UHCI_QH_ELEMENT_LINK_PTR_QH;
+ PhysicalAddress |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ StaticBulkHead->HwQH.NextQH = PhysicalAddress;
+
+ UhciSetNextQH(StaticControlHead, StaticBulkHead);
+
+ UhciExtension->BulkQH = StaticBulkHead;
+ UhciExtension->BulkTailQH = StaticBulkHead;
+
+ /* Initialize static TD for bulk transfers */
+ StaticBulkTD = &HcResourcesVA->StaticBulkTD;
+ StaticBulkTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticBulkTD);
+
+ StaticBulkTD->HwTD.NextElement = StaticBulkTdPA | UHCI_TD_LINK_PTR_TD;
+
+ StaticBulkTD->HwTD.ControlStatus.AsULONG = 0;
+ StaticBulkTD->HwTD.ControlStatus.IsochronousType = 1;
+
+ StaticBulkTD->HwTD.Token.AsULONG = 0;
+ StaticBulkTD->HwTD.Token.Endpoint = 1;
+ StaticBulkTD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL;
+ StaticBulkTD->HwTD.Token.PIDCode = UHCI_TD_PID_OUT;
+
+ StaticBulkTD->HwTD.Buffer = 0;
+
+ StaticBulkTD->PhysicalAddress = StaticBulkTdPA;
+ StaticBulkTD->NextHcdTD = NULL;
+ StaticBulkTD->Flags = UHCI_HCD_TD_FLAG_PROCESSED;
+
+ PhysicalAddress = StaticBulkTdPA | UHCI_QH_ELEMENT_LINK_PTR_TD;
+ UhciExtension->BulkQH->HwQH.NextElement = PhysicalAddress;
+
+ /* Set Frame List pointers */
+ for (Idx = 0; Idx < UHCI_FRAME_LIST_MAX_ENTRIES; Idx++)
+ {
+ HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms) +
+ (Idx & (ENDPOINT_INTERRUPT_32ms - 1));
+
+ PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
+ PhysicalAddress |= UHCI_FRAME_LIST_POINTER_QH;
+ HcResourcesVA->FrameList[Idx] = PhysicalAddress;
+ }
+
+ /* Initialize static TD for first frame */
+ StaticTD = &HcResourcesVA->StaticTD;
+ StaticTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticTD);
+
+ RtlZeroMemory(StaticTD, sizeof(UHCI_HCD_TD));
+
+ StaticTD->PhysicalAddress = StaticTdPA;
+
+ HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms);
+ PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
+ StaticTD->HwTD.NextElement = PhysicalAddress | UHCI_TD_LINK_PTR_QH;
+
+ StaticTD->HwTD.ControlStatus.InterruptOnComplete = 1;
+ StaticTD->HwTD.Token.PIDCode = UHCI_TD_PID_IN;
+
+ UhciExtension->StaticTD = StaticTD;
+
+ /* Initialize StaticSofTDs for UhciInterruptNextSOF() */
+ UhciExtension->SOF_HcdTDs = &HcResourcesVA->StaticSofTD[0];
+ StaticSofTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticSofTD[0]);
+
+ for (Idx = 0; Idx < UHCI_MAX_STATIC_SOF_TDS; Idx++)
+ {
+ StaticSofTD = UhciExtension->SOF_HcdTDs + Idx;
+
+ RtlZeroMemory(StaticSofTD, sizeof(UHCI_HCD_TD));
+
+ PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress;
+ StaticSofTD->HwTD.NextElement = PhysicalAddress | UHCI_TD_LINK_PTR_QH;
+
+ StaticSofTD->HwTD.ControlStatus.InterruptOnComplete = 1;
+ StaticSofTD->PhysicalAddress = StaticSofTdPA;
+
+ StaticSofTdPA += sizeof(UHCI_HCD_TD);
+ }
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciStartController(IN PVOID uhciExtension,
+ IN PUSBPORT_RESOURCES Resources)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ MPSTATUS MpStatus;
+ PUSHORT PortControlRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+ UHCI_USB_COMMAND Command;
+ USHORT Port;
+
+ UhciExtension->Flags &= ~UHCI_EXTENSION_FLAG_SUSPENDED;
+ UhciExtension->BaseRegister = Resources->ResourceBase;
+ BaseRegister = UhciExtension->BaseRegister;
+ DPRINT("UhciStartController: UhciExtension - %p, BaseRegister - %p\n",
UhciExtension, BaseRegister);
+
+ UhciExtension->HcFlavor = Resources->HcFlavor;
+
+ MpStatus = UhciTakeControlHC(UhciExtension, Resources);
+
+ if (MpStatus == MP_STATUS_SUCCESS)
+ {
+ MpStatus = UhciInitializeHardware(UhciExtension);
+
+ if (MpStatus == MP_STATUS_SUCCESS)
+ {
+ UhciExtension->HcResourcesVA = (PUHCI_HC_RESOURCES)Resources->StartVA;
+ UhciExtension->HcResourcesPA = Resources->StartPA;
+
+ MpStatus = UhciInitializeSchedule(UhciExtension,
+ UhciExtension->HcResourcesVA,
+ UhciExtension->HcResourcesPA);
+
+ UhciExtension->LockFrameList = 0;
+ }
+ }
+
+ WRITE_PORT_ULONG(&BaseRegister->FrameAddress,
+ UhciExtension->HcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES,
FrameList));
+
+ if (MpStatus == MP_STATUS_SUCCESS)
+ {
+ Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT);
+ Command.Run = 1;
+ WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT);
+
+ for (Port = 0; Port < UHCI_NUM_ROOT_HUB_PORTS; Port++)
+ {
+ PortControlRegister = &BaseRegister->PortControl[Port].AsUSHORT;
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
+
+ PortControl.ConnectStatusChange = 0;
+ PortControl.Suspend = 0;
+
+ WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
+ }
+
+ UhciExtension->HcResourcesVA->FrameList[0] =
+ UhciExtension->StaticTD->PhysicalAddress;
+ }
+
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+UhciStopController(IN PVOID uhciExtension,
+ IN BOOLEAN IsDoDisableInterrupts)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT CommandReg;
+ UHCI_USB_COMMAND Command;
+ LARGE_INTEGER EndTime;
+ LARGE_INTEGER CurrentTime;
+
+ DPRINT("UhciStopController: UhciExtension - %p\n", UhciExtension);
+
+ BaseRegister = UhciExtension->BaseRegister;
+ CommandReg = &BaseRegister->HcCommand.AsUSHORT;
+
+ Command.AsUSHORT = READ_PORT_USHORT(CommandReg);
+
+ if (Command.AsUSHORT == 0xFFFF)
+ {
+ DPRINT("UhciStopController: Command == -1\n");
+ return;
+ }
+
+ DPRINT("UhciStopController: Command.AsUSHORT - %p\n", Command.AsUSHORT);
+
+ if (Command.GlobalReset)
+ {
+ Command.GlobalReset = 0;
+ WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT);
+ }
+
+ Command.HcReset = 1;
+
+ WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT);
+
+ KeQuerySystemTime(&EndTime);
+ EndTime.QuadPart += 100 * 1000;
+
+ while (Command.AsUSHORT = READ_PORT_USHORT(CommandReg),
+ Command.HcReset == 1)
+ {
+ KeQuerySystemTime(&CurrentTime);
+
+ if (CurrentTime.QuadPart >= EndTime.QuadPart)
+ {
+ DPRINT1("UhciStopController: Failed to reset\n");
+ DbgBreakPoint();
+ break;
+ }
+ }
+}
+
+VOID
+NTAPI
+UhciSuspendController(IN PVOID uhciExtension)
+{
+ DPRINT_IMPL("UhciSuspendController: UNIMPLEMENTED. FIXME\n");
+}
+
+MPSTATUS
+NTAPI
+UhciResumeController(IN PVOID uhciExtension)
+{
+ DPRINT_IMPL("UhciResumeController: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+BOOLEAN
+NTAPI
+UhciHardwarePresent(IN PUHCI_EXTENSION UhciExtension)
+{
+ UHCI_USB_STATUS UhciStatus;
+ PUSHORT StatusReg;
+
+ StatusReg = &UhciExtension->BaseRegister->HcStatus.AsUSHORT;
+ UhciStatus.AsUSHORT = READ_PORT_USHORT(StatusReg);
+
+ if (UhciStatus.AsUSHORT == MAXUSHORT)
+ DPRINT_UHCI("UhciHardwarePresent: HW not present\n");
+
+ return UhciStatus.AsUSHORT != MAXUSHORT;
+}
+
+BOOLEAN
+NTAPI
+UhciInterruptService(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT CommandReg;
+ UHCI_USB_COMMAND Command;
+ PUSHORT StatusReg;
+ UHCI_USB_STATUS HcStatus;
+ PUSHORT InterruptEnableReg;
+ PUHCI_HCD_QH QH;
+ PUHCI_HCD_QH BulkTailQH;
+ ULONG ScheduleError;
+ BOOLEAN Result = FALSE;
+
+ BaseRegister = UhciExtension->BaseRegister;
+ StatusReg = &BaseRegister->HcStatus.AsUSHORT;
+ InterruptEnableReg = &BaseRegister->HcInterruptEnable.AsUSHORT;
+ CommandReg = &BaseRegister->HcCommand.AsUSHORT;
+
+ if (!UhciHardwarePresent(UhciExtension))
+ {
+ DPRINT1("UhciInterruptService: return FALSE\n");
+ return FALSE;
+ }
+
+ HcStatus.AsUSHORT = READ_PORT_USHORT(StatusReg) & UHCI_USB_STATUS_MASK;
+
+ if (HcStatus.HostSystemError || HcStatus.HcProcessError)
+ {
+ DPRINT1("UhciInterruptService: Error [%p] HcStatus %X\n",
+ UhciExtension,
+ HcStatus.AsUSHORT);
+ }
+ else if (HcStatus.AsUSHORT)
+ {
+ UhciExtension->HcScheduleError = 0;
+ }
+
+ if (HcStatus.HcProcessError)
+ {
+ USHORT fn = READ_PORT_USHORT(&BaseRegister->FrameNumber);
+ USHORT intr = READ_PORT_USHORT(InterruptEnableReg);
+ USHORT cmd = READ_PORT_USHORT(CommandReg);
+
+ DPRINT1("UhciInterruptService: HC ProcessError!\n");
+ DPRINT1("UhciExtension %p, frame %X\n", UhciExtension, fn);
+ DPRINT1("HcCommand %X\n", cmd);
+ DPRINT1("HcStatus %X\n", HcStatus.AsUSHORT);
+ DPRINT1("HcInterruptEnable %X\n", intr);
+
+ DbgBreakPoint();
+ }
+
+ if (HcStatus.HcHalted)
+ {
+ DPRINT_UHCI("UhciInterruptService: Hc Halted [%p] HcStatus %X\n",
+ UhciExtension,
+ HcStatus.AsUSHORT);
+ }
+ else if (HcStatus.AsUSHORT)
+ {
+ UhciExtension->HcStatus.AsUSHORT = HcStatus.AsUSHORT;
+
+ WRITE_PORT_USHORT(StatusReg, HcStatus.AsUSHORT);
+ WRITE_PORT_USHORT(InterruptEnableReg, 0);
+
+ if (HcStatus.HostSystemError)
+ {
+ DPRINT1("UhciInterruptService: HostSystemError! HcStatus - %X\n",
+ HcStatus.AsUSHORT);
+
+ DbgBreakPoint();
+ }
+
+ Result = TRUE;
+ }
+
+ if (!HcStatus.Interrupt)
+ goto NextProcess;
+
+ UhciUpdateCounter(UhciExtension);
+
+ BulkTailQH = UhciExtension->BulkTailQH;
+
+ if (BulkTailQH->HwQH.NextQH & UHCI_QH_HEAD_LINK_PTR_TERMINATE)
+ goto NextProcess;
+
+ QH = UhciExtension->BulkQH;
+
+ do
+ {
+ QH = QH->NextHcdQH;
+
+ if (!QH)
+ {
+ BulkTailQH->HwQH.NextQH |= UHCI_QH_HEAD_LINK_PTR_TERMINATE;
+ goto NextProcess;
+ }
+ }
+ while (QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_PTR_TERMINATE);
+
+NextProcess:
+
+ if (HcStatus.HcProcessError)
+ {
+ UhciCleanupFrameList(UhciExtension, TRUE);
+
+ ScheduleError = UhciExtension->HcScheduleError;
+ UhciExtension->HcScheduleError = ScheduleError + 1;
+
+ DPRINT1("UhciInterruptService: [%p] ScheduleError %X\n",
+ UhciExtension,
+ ScheduleError);
+
+ if (ScheduleError < UHCI_MAX_HC_SCHEDULE_ERRORS)
+ {
+ Command.AsUSHORT = READ_PORT_USHORT(CommandReg);
+ Command.Run = 1;
+ WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT);
+ }
+ }
+ else if (HcStatus.Interrupt && UhciExtension->ExtensionLock)
+ {
+ DPRINT1("UhciInterruptService: [%p] HcStatus %X\n",
+ UhciExtension,
+ HcStatus.AsUSHORT);
+
+ UhciCleanupFrameList(UhciExtension, FALSE);
+ }
+
+ return Result;
+}
+
+VOID
+NTAPI
+UhciInterruptDpc(IN PVOID uhciExtension,
+ IN BOOLEAN IsDoEnableInterrupts)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ UHCI_USB_STATUS HcStatus;
+
+ DPRINT_UHCI("UhciInterruptDpc: [%p] EnableInt %x, HcStatus %X\n",
+ uhciExtension, IsDoEnableInterrupts, UhciExtension->HcStatus);
+
+ BaseRegister = UhciExtension->BaseRegister;
+
+ HcStatus = UhciExtension->HcStatus;
+ UhciExtension->HcStatus.AsUSHORT = 0;
+
+ if ((HcStatus.Interrupt | HcStatus.ErrorInterrupt) != 0)
+ RegPacket.UsbPortInvalidateEndpoint(UhciExtension, 0);
+
+ if (IsDoEnableInterrupts)
+ {
+ WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT,
+ UhciExtension->StatusMask.AsUSHORT);
+ }
+}
+
+VOID
+NTAPI
+UhciQueueTransfer(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUHCI_HCD_TD FirstTD,
+ IN PUHCI_HCD_TD LastTD)
+{
+ PUHCI_HCD_QH QH;
+ PUHCI_HCD_QH BulkTailQH;
+ PUHCI_HCD_TD TailTD;
+ ULONG PhysicalAddress;
+
+ DPRINT("UhciQueueTransfer: FirstTD - %p, LastTD - %p\n", FirstTD, LastTD);
+
+ TailTD = UhciEndpoint->TailTD;
+ QH = UhciEndpoint->QH;
+
+ if (UhciEndpoint->HeadTD)
+ {
+ TailTD->NextHcdTD = FirstTD;
+
+ TailTD->HwTD.NextElement = FirstTD->PhysicalAddress;
+ TailTD->HwTD.NextElement |= UHCI_TD_LINK_PTR_TD;
+
+ PhysicalAddress = QH->HwQH.NextElement;
+
+ PhysicalAddress &= ~(UHCI_TD_LINK_PTR_TERMINATE |
+ UHCI_TD_LINK_PTR_QH |
+ UHCI_TD_LINK_PTR_DEPTH_FIRST);
+
+ if (FirstTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)
+ {
+ if (PhysicalAddress == TailTD->PhysicalAddress &&
+ !(TailTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE))
+ {
+ QH->HwQH.NextElement = FirstTD->PhysicalAddress;
+
+ QH->HwQH.NextElement &= ~(UHCI_QH_ELEMENT_LINK_PTR_TERMINATE |
+ UHCI_QH_ELEMENT_LINK_PTR_QH);
+ }
+ }
+ }
+ else
+ {
+ if (FirstTD)
+ {
+ UhciEndpoint->HeadTD = FirstTD;
+ }
+ else
+ {
+ UhciEndpoint->TailTD = NULL;
+ UhciEndpoint->HeadTD = NULL;
+ }
+
+ if (FirstTD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ {
+ PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+ else
+ {
+ PhysicalAddress = FirstTD->PhysicalAddress;
+ PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+
+ QH->HwQH.NextElement = PhysicalAddress & ~UHCI_QH_ELEMENT_LINK_PTR_QH;
+ }
+
+ if (UhciEndpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_BULK)
+ {
+ BulkTailQH = UhciExtension->BulkTailQH;
+ BulkTailQH->HwQH.NextQH &= ~UHCI_QH_HEAD_LINK_PTR_TERMINATE;
+ }
+
+ UhciEndpoint->TailTD = LastTD;
+}
+
+PUHCI_HCD_TD
+NTAPI
+UhciAllocateTD(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint)
+{
+ PUHCI_HCD_TD TD;
+ ULONG AllocTdCounter;
+ ULONG ix;
+
+ DPRINT_UHCI("UhciAllocateTD: ...\n");
+
+ AllocTdCounter = UhciEndpoint->AllocTdCounter;
+
+ for (ix = 0; ix < UhciEndpoint->MaxTDs; ++ix)
+ {
+ TD = &UhciEndpoint->FirstTD[AllocTdCounter];
+
+ if (!(TD->Flags & UHCI_HCD_TD_FLAG_ALLOCATED))
+ {
+ TD->Flags |= UHCI_HCD_TD_FLAG_ALLOCATED;
+
+ UhciEndpoint->AllocatedTDs++;
+ UhciEndpoint->AllocTdCounter = AllocTdCounter;
+
+ return TD;
+ }
+
+ if (AllocTdCounter < UhciEndpoint->MaxTDs - 1)
+ AllocTdCounter++;
+ else
+ AllocTdCounter = 0;
+ }
+
+ return NULL;
+}
+
+VOID
+NTAPI
+UhciMapAsyncTransferToTDs(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUHCI_TRANSFER UhciTransfer,
+ OUT PUHCI_HCD_TD * OutFirstTD,
+ OUT PUHCI_HCD_TD * OutLastTD,
+ IN PUSBPORT_SCATTER_GATHER_LIST SgList)
+{
+ PUHCI_HCD_TD TD;
+ PUHCI_HCD_TD LastTD = NULL;
+ ULONG PhysicalAddress;
+ USHORT TotalMaxPacketSize;
+ USHORT DeviceSpeed;
+ USHORT EndpointAddress;
+ USHORT DeviceAddress;
+ ULONG TransferType;
+ SIZE_T TransferLength = 0;
+ SIZE_T LengthMapped = 0;
+ SIZE_T BytesRemaining;
+ SIZE_T LengthThisTD;
+ ULONG ix;
+ BOOL DataToggle;
+ UCHAR PIDCode;
+ BOOLEAN IsLastTd = TRUE;
+ BOOLEAN ZeroLengthTransfer = TRUE;
+
+ DPRINT_UHCI("UhciMapAsyncTransferToTDs: ...\n");
+
+ TotalMaxPacketSize = UhciEndpoint->EndpointProperties.TotalMaxPacketSize;
+ DeviceSpeed = UhciEndpoint->EndpointProperties.DeviceSpeed;
+ EndpointAddress = UhciEndpoint->EndpointProperties.EndpointAddress;
+ DeviceAddress = UhciEndpoint->EndpointProperties.DeviceAddress;
+ TransferType = UhciEndpoint->EndpointProperties.TransferType;
+
+ if (SgList->SgElementCount || TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+ ZeroLengthTransfer = FALSE;
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+ {
+ if (UhciTransfer->TransferParameters->TransferFlags &
+ USBD_TRANSFER_DIRECTION_IN)
+ {
+ PIDCode = UHCI_TD_PID_IN;
+ }
+ else
+ {
+ PIDCode = UHCI_TD_PID_OUT;
+ }
+
+ DataToggle = UHCI_TD_PID_DATA1;
+ }
+ else
+ {
+ if (USB_ENDPOINT_DIRECTION_OUT(EndpointAddress))
+ PIDCode = UHCI_TD_PID_OUT;
+ else
+ PIDCode = UHCI_TD_PID_IN;
+
+ DataToggle = UhciEndpoint->DataToggle;
+ }
+
+ for (ix = 0; ix < SgList->SgElementCount || ZeroLengthTransfer; ix++)
+ {
+ BytesRemaining = SgList->SgElement[ix].SgTransferLength;
+ PhysicalAddress = SgList->SgElement[ix].SgPhysicalAddress.LowPart;
+
+ if (!IsLastTd)
+ {
+ PhysicalAddress += TransferLength;
+ BytesRemaining -= TransferLength;
+ }
+
+ IsLastTd = TRUE;
+ TransferLength = 0;
+
+ while (BytesRemaining || ZeroLengthTransfer)
+ {
+ ZeroLengthTransfer = FALSE;
+
+ if (BytesRemaining >= TotalMaxPacketSize)
+ {
+ LengthThisTD = TotalMaxPacketSize;
+ BytesRemaining -= TotalMaxPacketSize;
+ }
+ else
+ {
+ if (ix >= SgList->SgElementCount - 1)
+ {
+ LengthThisTD = BytesRemaining;
+ }
+ else
+ {
+ IsLastTd = FALSE;
+
+ DPRINT1("UhciMapAsyncTransferToTds: IsLastTd = FALSE.
FIXME\n");
+ ASSERT(FALSE);
+ }
+
+ BytesRemaining = 0;
+ }
+
+ UhciTransfer->PendingTds++;
+ TD = UhciAllocateTD(UhciExtension, UhciEndpoint);
+ TD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED;
+
+ TD->HwTD.NextElement = 0;
+ TD->HwTD.Buffer = PhysicalAddress;
+
+ TD->HwTD.ControlStatus.AsULONG = 0;
+ TD->HwTD.ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed);
+ TD->HwTD.ControlStatus.Status = UHCI_TD_STS_ACTIVE;
+ TD->HwTD.ControlStatus.ErrorCounter = 3;
+ TD->HwTD.ControlStatus.ActualLength = UHCI_TD_LENGTH_NULL;
+ TD->HwTD.ControlStatus.ShortPacketDetect = 1;
+
+ TD->HwTD.Token.AsULONG = 0;
+ TD->HwTD.Token.Endpoint = EndpointAddress;
+ TD->HwTD.Token.DeviceAddress = DeviceAddress;
+ TD->HwTD.Token.PIDCode = PIDCode;
+
+ if (LengthThisTD == 0)
+ TD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL;
+ else
+ TD->HwTD.Token.MaximumLength = LengthThisTD - 1;
+
+ TD->HwTD.Token.DataToggle = (DataToggle == UHCI_TD_PID_DATA1);
+
+ TD->NextHcdTD = 0;
+ TD->UhciTransfer = UhciTransfer;
+
+ if (!IsLastTd)
+ ASSERT(FALSE);
+
+ PhysicalAddress += LengthThisTD;
+ LengthMapped += LengthThisTD;
+
+ if (LastTD)
+ {
+ LastTD->HwTD.NextElement = TD->PhysicalAddress &
+ UHCI_TD_LINK_POINTER_MASK;
+ LastTD->NextHcdTD = TD;
+ }
+ else
+ {
+ *OutFirstTD = TD;
+ }
+
+ LastTD = TD;
+ DataToggle = DataToggle == UHCI_TD_PID_DATA0;
+ }
+ }
+
+ UhciEndpoint->DataToggle = DataToggle;
+
+ *OutLastTD = LastTD;
+}
+
+MPSTATUS
+NTAPI
+UhciControlTransfer(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+ IN PUHCI_TRANSFER UhciTransfer,
+ IN PUSBPORT_SCATTER_GATHER_LIST SgList)
+{
+ PUHCI_HCD_TD FirstTD;
+ PUHCI_HCD_TD LastTD;
+ PUHCI_HCD_TD DataFirstTD;
+ PUHCI_HCD_TD DataLastTD;
+ UHCI_CONTROL_STATUS ControlStatus;
+ USB_DEVICE_SPEED DeviceSpeed;
+ USHORT EndpointAddress;
+ USHORT DeviceAddress;
+ ULONG PhysicalAddress;
+
+ DPRINT_UHCI("UhciControlTransfer: UhciTransfer - %p\n", UhciTransfer);
+
+ if (UhciEndpoint->EndpointLock > 1)
+ {
+ InterlockedDecrement(&UhciEndpoint->EndpointLock);
+
+ if (UhciEndpoint->EndpointProperties.TransferType ==
+ USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ {
+ InterlockedDecrement(&UhciExtension->ExtensionLock);
+ }
+
+ DPRINT("UhciControlTransfer: end MP_STATUS_FAILURE\n");
+ return MP_STATUS_FAILURE;
+ }
+
+ DeviceSpeed = UhciEndpoint->EndpointProperties.DeviceSpeed;
+ EndpointAddress = UhciEndpoint->EndpointProperties.EndpointAddress;
+ DeviceAddress = UhciEndpoint->EndpointProperties.DeviceAddress;
+
+ /* Allocate and setup first TD */
+ UhciTransfer->PendingTds++;
+ FirstTD = UhciAllocateTD(UhciExtension, UhciEndpoint);
+ FirstTD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED;
+ DPRINT_UHCI("UhciControlTransfer: FirstTD - %p\n", FirstTD);
+
+ FirstTD->HwTD.NextElement = 0;
+
+ ControlStatus.AsULONG = 0;
+ ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed);
+ ControlStatus.Status |= UHCI_TD_STS_ACTIVE;
+ ControlStatus.ErrorCounter = 3;
+ FirstTD->HwTD.ControlStatus = ControlStatus;
+
+ FirstTD->HwTD.Token.AsULONG = 0;
+ FirstTD->HwTD.Token.Endpoint = EndpointAddress;
+ FirstTD->HwTD.Token.DeviceAddress = DeviceAddress;
+
+ FirstTD->HwTD.Token.MaximumLength = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET);
+ FirstTD->HwTD.Token.MaximumLength--;
+ FirstTD->HwTD.Token.PIDCode = UHCI_TD_PID_SETUP;
+ FirstTD->HwTD.Token.DataToggle = UHCI_TD_PID_DATA0;
+
+ RtlCopyMemory(&FirstTD->SetupPacket,
+ &TransferParameters->SetupPacket,
+ sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+ FirstTD->HwTD.Buffer = FirstTD->PhysicalAddress + FIELD_OFFSET(UHCI_HCD_TD,
SetupPacket);
+
+ FirstTD->NextHcdTD = NULL;
+ FirstTD->UhciTransfer = UhciTransfer;
+
+ /* Allocate and setup last TD */
+ UhciTransfer->PendingTds++;
+ LastTD = UhciAllocateTD(UhciExtension, UhciEndpoint);
+ LastTD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED;
+ DPRINT_UHCI("UhciControlTransfer: LastTD - %p\n", LastTD);
+
+ LastTD->HwTD.NextElement = 0;
+
+ LastTD->HwTD.ControlStatus.AsULONG = 0;
+ LastTD->HwTD.ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed);
+ LastTD->HwTD.ControlStatus.Status |= UHCI_TD_STS_ACTIVE;
+ LastTD->HwTD.ControlStatus.ErrorCounter = 3;
+
+ LastTD->HwTD.Token.AsULONG = 0;
+ LastTD->HwTD.Token.Endpoint = EndpointAddress;
+ LastTD->HwTD.Token.DeviceAddress = DeviceAddress;
+
+ LastTD->UhciTransfer = UhciTransfer;
+ LastTD->NextHcdTD = NULL;
+
+ /* Allocate and setup TDs for data */
+ DataFirstTD = NULL;
+ DataLastTD = NULL;
+
+ UhciMapAsyncTransferToTDs(UhciExtension,
+ UhciEndpoint,
+ UhciTransfer,
+ &DataFirstTD,
+ &DataLastTD,
+ SgList);
+
+ if (DataFirstTD)
+ {
+ PhysicalAddress = DataFirstTD->PhysicalAddress;
+ PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK;
+ FirstTD->HwTD.NextElement = PhysicalAddress;
+ FirstTD->NextHcdTD = DataFirstTD;
+
+ PhysicalAddress = LastTD->PhysicalAddress;
+ PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK;
+ DataLastTD->HwTD.NextElement = PhysicalAddress;
+ DataLastTD->NextHcdTD = LastTD;
+ }
+ else
+ {
+ PhysicalAddress = LastTD->PhysicalAddress;
+ PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK;
+ FirstTD->HwTD.NextElement = PhysicalAddress;
+ FirstTD->NextHcdTD = LastTD;
+ }
+
+ LastTD->HwTD.Buffer = 0;
+ LastTD->HwTD.ControlStatus.InterruptOnComplete = 1;
+
+ LastTD->HwTD.Token.DataToggle = UHCI_TD_PID_DATA1;
+ LastTD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL;
+
+ if (UhciTransfer->TransferParameters->TransferFlags &
+ USBD_TRANSFER_DIRECTION_IN)
+ {
+ LastTD->HwTD.Token.PIDCode = UHCI_TD_PID_OUT;
+ }
+ else
+ {
+ LastTD->HwTD.Token.PIDCode = UHCI_TD_PID_IN;
+ }
+
+ LastTD->HwTD.NextElement = UHCI_TD_LINK_PTR_TERMINATE;
+
+ LastTD->Flags |= UHCI_HCD_TD_FLAG_CONTROLL;
+ LastTD->NextHcdTD = NULL;
+
+ /* Link this transfer to queue */
+ UhciQueueTransfer(UhciExtension, UhciEndpoint, FirstTD, LastTD);
+
+ DPRINT_UHCI("UhciControlTransfer: end MP_STATUS_SUCCESS\n");
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciBulkOrInterruptTransfer(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+ IN PUHCI_TRANSFER UhciTransfer,
+ IN PUSBPORT_SCATTER_GATHER_LIST SgList)
+{
+ PUHCI_HCD_TD DataFirstTD;
+ PUHCI_HCD_TD DataLastTD;
+ ULONG TotalMaxPacketSize;
+ ULONG SgCount;
+ ULONG TransferLength;
+ ULONG TDs;
+ ULONG ix;
+
+ DPRINT_UHCI("UhciBulkOrInterruptTransfer: ...\n");
+
+ TotalMaxPacketSize = UhciEndpoint->EndpointProperties.TotalMaxPacketSize;
+
+ SgCount = SgList->SgElementCount;
+
+ if (SgCount == 0)
+ {
+ DPRINT("UhciBulkOrInterruptTransfer: SgCount == 0 \n");
+ TDs = 1;
+ }
+ else
+ {
+ TransferLength = 0;
+
+ for (ix = 0; ix < SgCount; ++ix)
+ {
+ TransferLength += SgList->SgElement[ix].SgTransferLength;
+ }
+
+ DPRINT("UhciBulkOrInterruptTransfer: SgCount - %X, TransferLength -
%X\n",
+ SgList->SgElementCount,
+ TransferLength);
+
+ if (TransferLength)
+ {
+ TDs = TransferLength + (TotalMaxPacketSize - 1);
+ TDs /= TotalMaxPacketSize;
+ }
+ else
+ {
+ TDs = 1;
+ }
+ }
+
+ if ((UhciEndpoint->MaxTDs - UhciEndpoint->AllocatedTDs) < TDs)
+ {
+ DPRINT1("UhciBulkOrInterruptTransfer: Not enough TDs \n");
+ return MP_STATUS_FAILURE;
+ }
+
+ DataFirstTD = NULL;
+ DataLastTD = NULL;
+
+ UhciMapAsyncTransferToTDs(UhciExtension,
+ UhciEndpoint,
+ UhciTransfer,
+ &DataFirstTD,
+ &DataLastTD,
+ SgList);
+
+ if (DataLastTD == NULL || DataFirstTD == NULL)
+ {
+ DPRINT1("UhciBulkOrInterruptTransfer: !DataLastTD || !DataFirstTD\n");
+ return MP_STATUS_FAILURE;
+ }
+
+ DataLastTD->HwTD.NextElement = UHCI_TD_LINK_PTR_TERMINATE;
+ DataLastTD->HwTD.ControlStatus.InterruptOnComplete = 1;
+ DataLastTD->NextHcdTD = NULL;
+
+ UhciQueueTransfer(UhciExtension,
+ UhciEndpoint,
+ DataFirstTD,
+ DataLastTD);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciSubmitTransfer(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint,
+ IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+ IN PVOID uhciTransfer,
+ IN PUSBPORT_SCATTER_GATHER_LIST SgList)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ PUHCI_TRANSFER UhciTransfer = uhciTransfer;
+ ULONG TransferType;
+
+ DPRINT_UHCI("UhciSubmitTransfer: ...\n");
+
+ InterlockedIncrement(&UhciEndpoint->EndpointLock);
+
+ TransferType = UhciEndpoint->EndpointProperties.TransferType;
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
+ InterlockedIncrement(&UhciExtension->ExtensionLock) == 1)
+ {
+ UhciExtension->FrameNumber = UhciGet32BitFrameNumber(UhciExtension);
+ }
+
+ RtlZeroMemory(UhciTransfer, sizeof(UHCI_TRANSFER));
+
+ UhciTransfer->TransferParameters = TransferParameters;
+ UhciTransfer->UhciEndpoint = UhciEndpoint;
+ UhciTransfer->USBDStatus = USBD_STATUS_SUCCESS;
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+ {
+ return UhciControlTransfer(UhciExtension,
+ UhciEndpoint,
+ TransferParameters,
+ UhciTransfer,
+ SgList);
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+ TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ return UhciBulkOrInterruptTransfer(UhciExtension,
+ UhciEndpoint,
+ TransferParameters,
+ UhciTransfer,
+ SgList);
+ }
+
+ DPRINT1("UhciSubmitTransfer: Error TransferType - %x\n", TransferType);
+
+ return MP_STATUS_SUCCESS;
+}
+
+USBD_STATUS
+NTAPI
+UhciGetErrorFromTD(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_HCD_TD TD)
+{
+ USBD_STATUS USBDStatus;
+ UCHAR TdStatus;
+
+ //DPRINT("UhciGetErrorFromTD: ...\n");
+
+ TdStatus = TD->HwTD.ControlStatus.Status;
+
+ if (TdStatus == UHCI_TD_STS_ACTIVE)
+ {
+ if (TD->HwTD.Token.MaximumLength == UHCI_TD_LENGTH_NULL)
+ return USBD_STATUS_SUCCESS;
+
+ if (TD->HwTD.ControlStatus.ActualLength + 1 >=
+ TD->HwTD.Token.MaximumLength + 1)
+ {
+ return USBD_STATUS_SUCCESS;
+ }
+
+ if (TD->HwTD.ControlStatus.InterruptOnComplete == 1)
+ return USBD_STATUS_SUCCESS;
+
+ return USBD_STATUS_ERROR_SHORT_TRANSFER;
+ }
+
+ if (TdStatus & UHCI_TD_STS_BABBLE_DETECTED &&
+ TdStatus & UHCI_TD_STS_STALLED)
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_BUFFER_OVERRUN, TD - %p\n",
TD);
+ return USBD_STATUS_BUFFER_OVERRUN;
+ }
+
+ if (TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR &&
+ TdStatus & UHCI_TD_STS_STALLED)
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DEV_NOT_RESPONDING, TD -
%p\n", TD);
+ return USBD_STATUS_DEV_NOT_RESPONDING;
+ }
+
+ if (TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR)
+ {
+ if (TD->HwTD.ControlStatus.ActualLength == UHCI_TD_LENGTH_NULL)
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DEV_NOT_RESPONDING, TD -
%p\n", TD);
+ return USBD_STATUS_DEV_NOT_RESPONDING;
+ }
+ else
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_CRC, TD - %p\n", TD);
+ return USBD_STATUS_CRC;
+ }
+ }
+ else if (TdStatus & UHCI_TD_STS_DATA_BUFFER_ERROR)
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DATA_OVERRUN, TD - %p\n",
TD);
+ USBDStatus = USBD_STATUS_DATA_OVERRUN;
+ }
+ else if (TdStatus & UHCI_TD_STS_STALLED)
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_STALL_PID, TD - %p\n", TD);
+ USBDStatus = USBD_STATUS_STALL_PID;
+ }
+ else
+ {
+ DPRINT1("UhciGetErrorFromTD: USBD_STATUS_INTERNAL_HC_ERROR, TD - %p\n",
TD);
+ USBDStatus = USBD_STATUS_INTERNAL_HC_ERROR;
+ }
+
+ return USBDStatus;
+}
+
+VOID
+NTAPI
+UhciProcessDoneNonIsoTD(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_HCD_TD TD)
+{
+ PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
+ PUHCI_ENDPOINT UhciEndpoint;
+ PUHCI_TRANSFER UhciTransfer;
+ USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
+ SIZE_T TransferedLen;
+
+ DPRINT_UHCI("UhciProcessDoneNonIsoTD: TD - %p\n", TD);
+
+ UhciTransfer = TD->UhciTransfer;
+ UhciTransfer->PendingTds--;
+
+ TransferParameters = UhciTransfer->TransferParameters;
+ UhciEndpoint = UhciTransfer->UhciEndpoint;
+
+ if (!(TD->Flags & UHCI_HCD_TD_FLAG_NOT_ACCESSED))
+ {
+ if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ USBDStatus = UhciGetErrorFromTD(UhciExtension, TD);
+
+ if (USBDStatus != USBD_STATUS_SUCCESS ||
+ (TD->HwTD.ControlStatus.ActualLength == UHCI_TD_LENGTH_NULL))
+ {
+ TransferedLen = 0;
+ }
+ else
+ {
+ TransferedLen = TD->HwTD.ControlStatus.ActualLength + 1;
+ }
+
+ if (TD->HwTD.Token.PIDCode != UHCI_TD_PID_SETUP)
+ UhciTransfer->TransferLen += TransferedLen;
+
+ if (TD->HwTD.Token.PIDCode == UHCI_TD_PID_IN &&
+ TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER)
+ {
+ DPRINT_IMPL("UhciProcessDoneNonIsoTD: UNIMPLEMENTED. FIXME\n");
+ }
+
+ if (USBDStatus != USBD_STATUS_SUCCESS)
+ UhciTransfer->USBDStatus = USBDStatus;
+ }
+
+ if (TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER)
+ DPRINT_IMPL("UhciProcessDoneNonIsoTD: UNIMPLEMENTED. FIXME\n");
+
+ UhciEndpoint->AllocatedTDs--;
+
+ TD->HwTD.NextElement = 0;
+ TD->UhciTransfer = NULL;
+ TD->Flags = 0;
+
+ if (UhciTransfer->PendingTds == 0)
+ {
+ InterlockedDecrement(&UhciEndpoint->EndpointLock);
+
+ if (UhciEndpoint->EndpointProperties.TransferType ==
+ USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ {
+ InterlockedDecrement(&UhciExtension->ExtensionLock);
+ }
+
+ RegPacket.UsbPortCompleteTransfer(UhciExtension,
+ UhciEndpoint,
+ TransferParameters,
+ UhciTransfer->USBDStatus,
+ UhciTransfer->TransferLen);
+ }
+}
+
+MPSTATUS
+NTAPI
+UhciIsochTransfer(IN PVOID ehciExtension,
+ IN PVOID ehciEndpoint,
+ IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+ IN PVOID ehciTransfer,
+ IN PVOID isoParameters)
+{
+ DPRINT_IMPL("UhciIsochTransfer: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+UhciAbortIsoTransfer(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUHCI_TRANSFER UhciTransfer)
+{
+ DPRINT_IMPL("UhciAbortIsoTransfer: UNIMPLEMENTED. FIXME\n");
+}
+
+VOID
+NTAPI
+UhciAbortNonIsoTransfer(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint,
+ IN PUHCI_TRANSFER UhciTransfer,
+ IN PULONG CompletedLength)
+{
+ PUHCI_HCD_TD TD;
+ PUHCI_HCD_TD PrevTD = NULL;
+ ULONG PhysicalAddress;
+ BOOL DataToggle;
+ BOOLEAN IsHeadTD = FALSE;
+
+ DPRINT("UhciAbortNonIsoTransfer: UhciExtension - %p, QH - %p, UhciTransfer -
%p\n",
+ UhciExtension,
+ UhciEndpoint->QH,
+ UhciTransfer);
+
+ for (TD = UhciEndpoint->HeadTD;
+ TD && TD->UhciTransfer != UhciTransfer;
+ TD = TD->NextHcdTD)
+ {
+ PrevTD = TD;
+ }
+
+ DataToggle = TD->HwTD.Token.DataToggle;
+
+ if (TD == UhciEndpoint->HeadTD)
+ IsHeadTD = TRUE;
+
+ while (TD && TD->UhciTransfer == UhciTransfer);
+ {
+ DPRINT_UHCI("UhciAbortNonIsoTransfer: TD - %p\n", TD);
+
+ if (TD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)
+ {
+ if (TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER)
+ DPRINT_IMPL("UhciAbortNonIsoTransfer: UNIMPLEMENTED.
FIXME\n");
+
+ UhciEndpoint->AllocatedTDs--;
+
+ DPRINT_UHCI("UhciAbortNonIsoTransfer: Active TD - %p\n", TD);
+
+ TD->HwTD.NextElement = 0;
+ TD->Flags = 0;
+ TD->UhciTransfer = NULL;
+ }
+ else
+ {
+ UhciProcessDoneNonIsoTD(UhciExtension, TD);
+ }
+
+ TD = TD->NextHcdTD;
+ }
+
+ UhciFixDataToggle(UhciExtension,
+ UhciEndpoint,
+ TD,
+ DataToggle);
+
+ if (IsHeadTD)
+ {
+ if (TD)
+ {
+ UhciEndpoint->HeadTD = TD;
+ }
+ else
+ {
+ UhciEndpoint->HeadTD = NULL;
+ UhciEndpoint->TailTD = NULL;
+ }
+
+ if (TD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ {
+ PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+ else
+ {
+ PhysicalAddress = TD->PhysicalAddress;
+ PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+
+ DPRINT_UHCI("UhciAbortNonIsoTransfer: TD - %p\n", TD);
+
+ UhciEndpoint->QH->HwQH.NextElement = PhysicalAddress;
+ UhciEndpoint->QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH;
+ }
+ else if (TD)
+ {
+ PrevTD->HwTD.NextElement = TD->PhysicalAddress &
UHCI_TD_LINK_POINTER_MASK;
+ PrevTD->NextHcdTD = TD;
+ }
+ else
+ {
+ PrevTD->NextHcdTD = NULL;
+ PrevTD->HwTD.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+
+ UhciEndpoint->TailTD = PrevTD;
+ }
+
+ *CompletedLength = UhciTransfer->TransferLen;
+}
+
+VOID
+NTAPI
+UhciAbortTransfer(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint,
+ IN PVOID uhciTransfer,
+ IN PULONG CompletedLength)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ PUHCI_TRANSFER UhciTransfer = uhciTransfer;
+ ULONG TransferType;
+
+ DPRINT("UhciAbortTransfer: ...\n");
+
+ InterlockedDecrement(&UhciEndpoint->EndpointLock);
+
+ TransferType = UhciEndpoint->EndpointProperties.TransferType;
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ {
+ InterlockedDecrement(&UhciExtension->ExtensionLock);
+
+ UhciAbortIsoTransfer(UhciExtension,
+ UhciEndpoint,
+ UhciTransfer);
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+ TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+ TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ UhciAbortNonIsoTransfer(UhciExtension,
+ UhciEndpoint,
+ UhciTransfer,
+ CompletedLength);
+ }
+}
+
+ULONG
+NTAPI
+UhciGetEndpointState(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint)
+{
+ DPRINT_IMPL("UhciGetEndpointState: UNIMPLEMENTED. FIXME\n");
+ return 0;
+}
+
+VOID
+NTAPI
+UhciInsertQH(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_HCD_QH StaticQH,
+ IN PUHCI_HCD_QH QH)
+{
+ PUHCI_HCD_QH NextHcdQH;
+
+ DPRINT("UhciInsertQH: UhciExtension - %p, StaticQH - %p, QH - %p\n",
UhciExtension, StaticQH, QH);
+
+ QH->HwQH.NextQH = StaticQH->HwQH.NextQH;
+ NextHcdQH = StaticQH->NextHcdQH;
+
+ QH->PrevHcdQH = StaticQH;
+ QH->NextHcdQH = NextHcdQH;
+
+ if (NextHcdQH)
+ NextHcdQH->PrevHcdQH = QH;
+ else
+ UhciExtension->BulkTailQH = QH;
+
+ StaticQH->HwQH.NextQH = QH->PhysicalAddress | UHCI_QH_HEAD_LINK_PTR_QH;
+ StaticQH->NextHcdQH = QH;
+
+ QH->QhFlags |= UHCI_HCD_QH_FLAG_ACTIVE;
+}
+
+VOID
+NTAPI
+UhciUnlinkQH(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_HCD_QH QH)
+{
+ PUHCI_HCD_QH NextHcdQH;
+ PUHCI_HCD_QH PrevHcdQH;
+ PUHCI_HCD_QH BulkQH;
+
+ DPRINT("UhciUnlinkQH: ... \n");
+
+ NextHcdQH = QH->NextHcdQH;
+ PrevHcdQH = QH->PrevHcdQH;
+
+ if (UhciExtension->BulkTailQH == QH)
+ UhciExtension->BulkTailQH = PrevHcdQH;
+
+ PrevHcdQH->HwQH.NextQH = QH->HwQH.NextQH;
+ PrevHcdQH->NextHcdQH = NextHcdQH;
+
+ if (NextHcdQH)
+ NextHcdQH->PrevHcdQH = PrevHcdQH;
+
+ QH->PrevHcdQH = QH;
+ QH->NextHcdQH = QH;
+
+ if (!(QH->UhciEndpoint->EndpointProperties.TransferType ==
+ USBPORT_TRANSFER_TYPE_BULK))
+ {
+ QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
+ return;
+ }
+
+ if ((UhciExtension->BulkTailQH->HwQH.NextQH &
UHCI_QH_HEAD_LINK_PTR_TERMINATE)
+ == UHCI_QH_HEAD_LINK_PTR_TERMINATE)
+ {
+ QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
+ return;
+ }
+
+ BulkQH = UhciExtension->BulkQH;
+
+ while (TRUE)
+ {
+ BulkQH = BulkQH->NextHcdQH;
+
+ if (!BulkQH)
+ break;
+
+ if (!(BulkQH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_PTR_TERMINATE))
+ {
+ QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
+ return;
+ }
+ }
+
+ UhciExtension->BulkTailQH->HwQH.NextQH |= UHCI_QH_HEAD_LINK_PTR_TERMINATE;
+
+ QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE;
+}
+
+VOID
+NTAPI
+UhciSetEndpointState(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint,
+ IN ULONG EndpointState)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ ULONG TransferType;
+ PUHCI_HCD_QH QH;
+ ULONG Idx;
+
+ TransferType = UhciEndpoint->EndpointProperties.TransferType;
+ QH = UhciEndpoint->QH;
+
+ DPRINT("UhciSetEndpointState: EndpointState - %x, TransferType - %x\n",
+ EndpointState,
+ TransferType);
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ return;
+
+ if (TransferType != USBPORT_TRANSFER_TYPE_CONTROL &&
+ TransferType != USBPORT_TRANSFER_TYPE_BULK &&
+ TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ DPRINT("UhciSetEndpointState: Unknown TransferType - %x\n",
+ TransferType);
+ }
+
+ switch (EndpointState)
+ {
+ case USBPORT_ENDPOINT_PAUSED:
+ UhciUnlinkQH(UhciExtension, QH);
+ return;
+
+ case USBPORT_ENDPOINT_ACTIVE:
+ switch (TransferType)
+ {
+ case USBPORT_TRANSFER_TYPE_CONTROL:
+ UhciInsertQH(UhciExtension,
+ UhciExtension->ControlQH,
+ UhciEndpoint->QH);
+ break;
+
+ case USBPORT_TRANSFER_TYPE_BULK:
+ UhciInsertQH(UhciExtension,
+ UhciExtension->BulkQH,
+ UhciEndpoint->QH);
+ break;
+
+ case USBPORT_TRANSFER_TYPE_INTERRUPT:
+ Idx = UhciEndpoint->EndpointProperties.Period +
+ UhciEndpoint->EndpointProperties.ScheduleOffset;
+
+ UhciInsertQH(UhciExtension,
+ UhciExtension->IntQH[Idx - 1],
+ UhciEndpoint->QH);
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ break;
+
+ case USBPORT_ENDPOINT_REMOVE:
+ QH->QhFlags |= UHCI_HCD_QH_FLAG_REMOVE;
+ UhciUnlinkQH(UhciExtension, QH);
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+}
+
+ULONG
+NTAPI
+UhciGetEndpointStatus(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint)
+{
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ ULONG EndpointStatus;
+
+ DPRINT_UHCI("UhciGetEndpointStatus: ...\n");
+
+ if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ EndpointStatus = USBPORT_ENDPOINT_HALT;
+ else
+ EndpointStatus = USBPORT_ENDPOINT_RUN;
+
+ return EndpointStatus;
+}
+
+VOID
+NTAPI
+UhciSetEndpointStatus(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint,
+ IN ULONG EndpointStatus)
+{
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ ULONG PhysicalAddress;
+
+ DPRINT("UhciSetEndpointStatus: uhciEndpoint - %p, EndpointStatus - %X\n",
+ uhciEndpoint,
+ EndpointStatus);
+
+ if (EndpointStatus != USBPORT_ENDPOINT_RUN)
+ return;
+
+ if (!(UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED))
+ return;
+
+ UhciEndpoint->Flags &= ~UHCI_ENDPOINT_FLAG_HALTED;
+
+ if (UhciEndpoint->HeadTD == NULL)
+ UhciEndpoint->TailTD = NULL;
+
+ if (UhciEndpoint->HeadTD)
+ {
+ PhysicalAddress = UhciEndpoint->HeadTD->PhysicalAddress;
+ PhysicalAddress &= ~UHCI_TD_LINK_PTR_TERMINATE;
+ UhciEndpoint->QH->HwQH.NextElement = PhysicalAddress;
+ UhciEndpoint->QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH;
+ }
+ else
+ {
+ UhciEndpoint->QH->HwQH.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+}
+
+VOID
+NTAPI
+UhciPollIsoEndpoint(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint)
+{
+ DPRINT_IMPL("UhciPollIsoEndpoint: UNIMPLEMENTED. FIXME\n");
+}
+
+VOID
+NTAPI
+UhciPollNonIsoEndpoint(IN PUHCI_EXTENSION UhciExtension,
+ IN PUHCI_ENDPOINT UhciEndpoint)
+{
+ PUHCI_HCD_QH QH;
+ PUHCI_HCD_TD NextTD;
+ PUHCI_HCD_TD TD;
+ ULONG NextTdPA;
+ ULONG PhysicalAddress;
+ SIZE_T TransferedLen;
+ PLIST_ENTRY ListTDs;
+ UCHAR TdStatus;
+
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: UhciExtension - %p, UhciEndpoint -
%p\n",
+ UhciExtension,
+ UhciEndpoint);
+
+ if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ {
+ DPRINT("UhciPollNonIsoEndpoint: Ep->Flags & UHCI_ENDPOINT_FLAG_HALTED
\n");
+ return;
+ }
+
+ QH = UhciEndpoint->QH;
+
+ NextTdPA = QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_POINTER_MASK;
+
+ if (NextTdPA)
+ {
+ NextTD = RegPacket.UsbPortGetMappedVirtualAddress(NextTdPA,
+ UhciExtension,
+ UhciEndpoint);
+ }
+ else
+ {
+ NextTD = NULL;
+ }
+
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, NextTdPA - %p\n",
+ NextTD,
+ NextTdPA);
+
+ for (TD = UhciEndpoint->HeadTD; TD != NextTD && TD != NULL; TD =
TD->NextHcdTD)
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p, TD->NextHcdTD -
%p\n",
+ TD,
+ TD->NextHcdTD);
+
+ TD->Flags |= UHCI_HCD_TD_FLAG_DONE;
+ InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink);
+
+ if (TD->NextHcdTD &&
+ TD->NextHcdTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)
+ {
+ if (NextTdPA == 0)
+ {
+ TD = TD->NextHcdTD;
+ goto EnqueueTD;
+ }
+
+ if (NextTdPA != TD->NextHcdTD->PhysicalAddress)
+ {
+ DPRINT("UhciPollNonIsoEndpoint: TD->NextHcdTD->PhysicalAddress
- %p\n",
+ TD->NextHcdTD->PhysicalAddress);
+ ASSERT(FALSE);
+ }
+ }
+ else
+ {
+ if (TD->NextHcdTD == NULL)
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: TD->NextHcdTD ==
NULL\n");
+ }
+ else
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: ControlStatus - %X\n",
+ TD->NextHcdTD->HwTD.ControlStatus.AsULONG);
+ }
+ }
+ }
+
+ UhciEndpoint->HeadTD = NextTD;
+
+ if (NextTD == NULL)
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD == NULL\n");
+
+ UhciEndpoint->HeadTD = NULL;
+ UhciEndpoint->TailTD = NULL;
+
+ QH->HwQH.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+
+ goto ProcessListTDs;
+ }
+
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, NextTdPA - %p\n",
+ NextTD,
+ NextTdPA);
+
+ TdStatus = NextTD->HwTD.ControlStatus.Status;
+
+ if (TdStatus & UHCI_TD_STS_ACTIVE)
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: UHCI_TD_STS_ACTIVE \n");
+ goto ProcessListTDs;
+ }
+
+ if (NextTD->HwTD.Token.PIDCode == UHCI_TD_PID_IN &&
+ TdStatus & UHCI_TD_STS_STALLED &&
+ TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR &&
+ !(TdStatus & UHCI_TD_STS_NAK_RECEIVED) &&
+ !(TdStatus & UHCI_TD_STS_BABBLE_DETECTED) &&
+ !(TdStatus & UHCI_TD_STS_BITSTUFF_ERROR))
+ {
+ DPRINT("UhciPollNonIsoEndpoint: USBD_STATUS_DEV_NOT_RESPONDING\n");
+
+ UhciDumpHcdTD(NextTD);
+
+ if (!(NextTD->Flags & UHCI_HCD_TD_FLAG_STALLED_SETUP))
+ {
+ NextTD->HwTD.ControlStatus.ErrorCounter = 3;
+
+ NextTD->HwTD.ControlStatus.Status &= ~(UHCI_TD_STS_STALLED |
+ UHCI_TD_STS_TIMEOUT_CRC_ERROR);
+
+ NextTD->HwTD.ControlStatus.Status |= UHCI_TD_STS_ACTIVE;
+
+ NextTD->Flags = NextTD->Flags | UHCI_HCD_TD_FLAG_STALLED_SETUP;
+
+ goto ProcessListTDs;
+ }
+ }
+
+ if (TdStatus & (UHCI_TD_STS_STALLED |
+ UHCI_TD_STS_DATA_BUFFER_ERROR |
+ UHCI_TD_STS_BABBLE_DETECTED |
+ UHCI_TD_STS_TIMEOUT_CRC_ERROR |
+ UHCI_TD_STS_BITSTUFF_ERROR))
+ {
+ DPRINT("UhciPollNonIsoEndpoint: NextTD UHCI_TD_STS_ - %02X, PIDCode -
%02X\n",
+ NextTD->HwTD.ControlStatus.Status,
+ NextTD->HwTD.Token.PIDCode);
+
+ UhciDumpHcdTD(NextTD);
+
+ UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_HALTED;
+ NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE;
+
+ InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink);
+
+ if (TD->UhciTransfer != NextTD->UhciTransfer)
+ ASSERT(TD->UhciTransfer == NextTD->UhciTransfer);
+
+ while (TD &&
+ TD->UhciTransfer->TransferParameters->TransferCounter ==
+ NextTD->UhciTransfer->TransferParameters->TransferCounter)
+ {
+ DPRINT("UhciPollNonIsoEndpoint: Bad TD - %p\n", TD);
+
+ if (!(TD->Flags & UHCI_HCD_TD_FLAG_DONE))
+ {
+ TD->Flags |= UHCI_HCD_TD_FLAG_DONE;
+ TD->Flags |= UHCI_HCD_TD_FLAG_NOT_ACCESSED;
+
+ InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink);
+ }
+
+ TD = TD->NextHcdTD;
+ }
+
+ if (UhciEndpoint->EndpointProperties.TransferType !=
+ USBPORT_TRANSFER_TYPE_CONTROL)
+ {
+ UhciFixDataToggle(UhciExtension,
+ UhciEndpoint,
+ TD,
+ NextTD->HwTD.Token.DataToggle);
+ }
+ }
+ else
+ {
+ TransferedLen = NextTD->HwTD.ControlStatus.ActualLength;
+
+ if (TransferedLen == UHCI_TD_LENGTH_NULL)
+ TransferedLen = 0;
+ else
+ TransferedLen += 1;
+
+ if (NextTD->HwTD.Token.MaximumLength == UHCI_TD_LENGTH_NULL ||
+ TransferedLen >= (NextTD->HwTD.Token.MaximumLength + 1))
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, TransferedLen -
%X\n",
+ NextTD,
+ TransferedLen);
+
+ if (NextTdPA ==
+ (QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_POINTER_MASK))
+ {
+ NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE;
+ InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink);
+
+ UhciEndpoint->HeadTD = NextTD->NextHcdTD;
+
+ QH->HwQH.NextElement = NextTD->HwTD.NextElement;
+ QH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TD;
+
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, TD - %p\n",
+ NextTD,
+ TD);
+ }
+
+ goto ProcessListTDs;
+ }
+
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: ShortPacket. ControlStatus -
%X\n",
+ NextTD->HwTD.ControlStatus.AsULONG);
+
+ NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE;
+ InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink);
+
+ while (TD &&
+ TD->UhciTransfer->TransferParameters->TransferCounter ==
+ NextTD->UhciTransfer->TransferParameters->TransferCounter)
+ {
+ if (TD->Flags & UHCI_HCD_TD_FLAG_CONTROLL &&
+ NextTD->UhciTransfer->TransferParameters->TransferFlags &
+ USBD_SHORT_TRANSFER_OK)
+ {
+ break;
+ }
+
+ if (!(TD->Flags & UHCI_HCD_TD_FLAG_DONE))
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p\n", TD);
+
+ TD->Flags |= (UHCI_HCD_TD_FLAG_DONE |
+ UHCI_HCD_TD_FLAG_NOT_ACCESSED);
+
+ InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink);
+ }
+
+ TD = TD->NextHcdTD;
+ }
+
+ if (NextTD->NextHcdTD &&
+ (UhciEndpoint->EndpointProperties.TransferType !=
+ USBPORT_TRANSFER_TYPE_CONTROL))
+ {
+ UhciFixDataToggle(UhciExtension,
+ UhciEndpoint,
+ TD,
+ NextTD->NextHcdTD->HwTD.Token.DataToggle);
+ }
+
+ if (!(NextTD->UhciTransfer->TransferParameters->TransferFlags &
+ USBD_SHORT_TRANSFER_OK))
+ {
+ UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_HALTED;
+ }
+ }
+
+EnqueueTD:
+
+ if (TD)
+ {
+ UhciEndpoint->HeadTD = TD;
+ }
+ else
+ {
+ UhciEndpoint->HeadTD = NULL;
+ UhciEndpoint->TailTD = NULL;
+ }
+
+ if (TD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ {
+ PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+ else
+ {
+ PhysicalAddress = TD->PhysicalAddress;
+ PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE;
+ }
+
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p\n", TD);
+
+ QH->HwQH.NextElement = PhysicalAddress;
+ QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH;
+
+ProcessListTDs:
+
+ ListTDs = &UhciEndpoint->ListTDs;
+
+ while (!IsListEmpty(ListTDs))
+ {
+ TD = CONTAINING_RECORD(ListTDs->Flink,
+ UHCI_HCD_TD,
+ TdLink.Flink);
+
+ RemoveHeadList(ListTDs);
+
+ if ((TD->Flags & (UHCI_HCD_TD_FLAG_PROCESSED | UHCI_HCD_TD_FLAG_DONE)) ==
+ (UHCI_HCD_TD_FLAG_PROCESSED | UHCI_HCD_TD_FLAG_DONE))
+ {
+ UhciProcessDoneNonIsoTD(UhciExtension, TD);
+ }
+ }
+
+ if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO &&
+ UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)
+ {
+ DPRINT_UHCI("UhciPollNonIsoEndpoint: Halted periodic EP - %p\n",
+ UhciEndpoint);
+
+ UhciSetEndpointStatus(UhciExtension,
+ UhciEndpoint,
+ USBPORT_ENDPOINT_RUN);
+ }
+}
+
+VOID
+NTAPI
+UhciPollEndpoint(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint;
+ ULONG TransferType;
+
+ DPRINT_UHCI("UhciPollEndpoint: ...\n");
+
+ TransferType = UhciEndpoint->EndpointProperties.TransferType;
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+ {
+ UhciPollIsoEndpoint(UhciExtension, UhciEndpoint);
+ return;
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+ TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+ TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ UhciPollNonIsoEndpoint(UhciExtension, UhciEndpoint);
+ }
+}
+
+VOID
+NTAPI
+UhciCheckController(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+
+ if (!UhciHardwarePresent(UhciExtension) ||
+ UhciExtension->HcScheduleError >= UHCI_MAX_HC_SCHEDULE_ERRORS)
+ {
+ DPRINT1("UhciCheckController: INVALIDATE_CONTROLLER_SURPRISE_REMOVE
!!!\n");
+
+ RegPacket.UsbPortInvalidateController(UhciExtension,
+
USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
+ }
+}
+
+ULONG
+NTAPI
+UhciGet32BitFrameNumber(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ ULONG Uhci32BitFrame;
+ USHORT Fn; // FrameNumber
+ ULONG Hp; // FrameHighPart
+
+ Fn = READ_PORT_USHORT(&UhciExtension->BaseRegister->FrameNumber);
+ Fn &= UHCI_FRNUM_FRAME_MASK;
+ Hp = UhciExtension->FrameHighPart;
+
+ Uhci32BitFrame = Hp;
+ Uhci32BitFrame += ((USHORT)Hp ^ Fn) & UHCI_FRNUM_OVERFLOW_LIST;
+ Uhci32BitFrame |= Fn;
+
+ DPRINT_UHCI("UhciGet32BitFrameNumber: Uhci32BitFrame - %lX\n",
+ Uhci32BitFrame);
+
+ return Uhci32BitFrame;
+}
+
+VOID
+NTAPI
+UhciInterruptNextSOF(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HC_RESOURCES UhciResources;
+ ULONG CurrentFrame;
+ PUHCI_HCD_TD SOF_HcdTDs;
+ ULONG ix;
+ ULONG NextFrame;
+ ULONG SofFrame;
+ ULONG Idx;
+
+ DPRINT_UHCI("UhciInterruptNextSOF: ...\n");
+
+ CurrentFrame = UhciGet32BitFrameNumber(UhciExtension);
+
+ SOF_HcdTDs = UhciExtension->SOF_HcdTDs;
+ NextFrame = CurrentFrame + 2;
+
+ for (ix = 0; ix < UHCI_MAX_STATIC_SOF_TDS; ++ix)
+ {
+ SofFrame = SOF_HcdTDs->Frame;
+
+ if (SofFrame == NextFrame)
+ break;
+
+ if (SofFrame < CurrentFrame)
+ {
+ SOF_HcdTDs->Frame = NextFrame;
+ SOF_HcdTDs->Flags |= UHCI_HCD_TD_FLAG_GOOD_FRAME;
+
+ /* Insert SOF_HcdTD (InterruptOnComplete = TRUE) in Frame List */
+ UhciResources = UhciExtension->HcResourcesVA;
+ Idx = SOF_HcdTDs->Frame & UHCI_FRAME_LIST_INDEX_MASK;
+
+ InterlockedExchange((PLONG)&SOF_HcdTDs->HwTD.NextElement,
+ UhciResources->FrameList[Idx]);
+
+ UhciResources->FrameList[Idx] = SOF_HcdTDs->PhysicalAddress;
+ break;
+ }
+
+ /* Go to next SOF_HcdTD */
+ SOF_HcdTDs += 1;
+ }
+
+ for (ix = 0; ix < UHCI_MAX_STATIC_SOF_TDS; ++ix)
+ {
+ SOF_HcdTDs = &UhciExtension->SOF_HcdTDs[ix];
+
+ if (SOF_HcdTDs->Frame &&
+ (SOF_HcdTDs->Frame < CurrentFrame ||
+ (SOF_HcdTDs->Frame - CurrentFrame) > UHCI_FRAME_LIST_MAX_ENTRIES))
+ {
+ SOF_HcdTDs->Frame = 0;
+ }
+ }
+}
+
+VOID
+NTAPI
+UhciEnableInterrupts(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ UHCI_PCI_LEGSUP LegacySupport;
+
+ DPRINT("UhciEnableInterrupts: UhciExtension - %p\n", UhciExtension);
+
+ BaseRegister = UhciExtension->BaseRegister;
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ TRUE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+
+ LegacySupport.UsbPIRQ = 1;
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ FALSE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+
+ WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT,
+ UhciExtension->StatusMask.AsUSHORT);
+}
+
+VOID
+NTAPI
+UhciDisableInterrupts(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ USB_CONTROLLER_FLAVOR HcFlavor;
+ UHCI_PCI_LEGSUP LegacySupport;
+
+ DPRINT("UhciDisableInterrupts: UhciExtension - %p\n", UhciExtension);
+
+ BaseRegister = UhciExtension->BaseRegister;
+ WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT, 0);
+
+ HcFlavor = UhciExtension->HcFlavor;
+ DPRINT("UhciDisableInterrupts: FIXME HcFlavor - %lx\n", HcFlavor);
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ TRUE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+
+ LegacySupport.UsbPIRQ = 0;
+
+ RegPacket.UsbPortReadWriteConfigSpace(UhciExtension,
+ FALSE,
+ &LegacySupport.AsUSHORT,
+ PCI_LEGSUP,
+ sizeof(USHORT));
+}
+
+VOID
+NTAPI
+UhciPollController(IN PVOID uhciExtension)
+{
+ PUHCI_EXTENSION UhciExtension = uhciExtension;
+ PUHCI_HW_REGISTERS BaseRegister;
+ PUSHORT PortRegister;
+ UHCI_PORT_STATUS_CONTROL PortControl;
+ USHORT Port;
+
+ DPRINT_UHCI("UhciPollController: UhciExtension - %p\n", UhciExtension);
+
+ BaseRegister = UhciExtension->BaseRegister;
+
+ if (!(UhciExtension->Flags & UHCI_EXTENSION_FLAG_SUSPENDED))
+ {
+ UhciCleanupFrameList(UhciExtension, FALSE);
+ UhciUpdateCounter(UhciExtension);
+ RegPacket.UsbPortInvalidateRootHub(UhciExtension);
+ return;
+ }
+
+ for (Port = 0; Port < UHCI_NUM_ROOT_HUB_PORTS; Port++)
+ {
+ PortRegister = (PUSHORT)&BaseRegister->PortControl[Port];
+ PortControl.AsUSHORT = READ_PORT_USHORT(PortRegister);
+
+ if (PortControl.ConnectStatusChange == 1)
+ RegPacket.UsbPortInvalidateRootHub(UhciExtension);
+ }
+}
+
+VOID
+NTAPI
+UhciSetEndpointDataToggle(IN PVOID uhciExtension,
+ IN PVOID uhciEndpoint,
+ IN ULONG DataToggle)
+{
+ DPRINT_IMPL("UhciSetEndpointDataToggle: UNIMPLEMENTED. FIXME\n");
+}
+
+VOID
+NTAPI
+UhciResetController(IN PVOID uhciExtension)
+{
+ DPRINT_IMPL("UhciResetController: UNIMPLEMENTED. FIXME\n");
+}
+
+MPSTATUS
+NTAPI
+UhciStartSendOnePacket(IN PVOID uhciExtension,
+ IN PVOID PacketParameters,
+ IN PVOID Data,
+ IN PULONG pDataLength,
+ IN PVOID BufferVA,
+ IN PVOID BufferPA,
+ IN ULONG BufferLength,
+ IN USBD_STATUS * pUSBDStatus)
+{
+ DPRINT_IMPL("UhciStartSendOnePacket: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciEndSendOnePacket(IN PVOID uhciExtension,
+ IN PVOID PacketParameters,
+ IN PVOID Data,
+ IN PULONG pDataLength,
+ IN PVOID BufferVA,
+ IN PVOID BufferPA,
+ IN ULONG BufferLength,
+ IN USBD_STATUS * pUSBDStatus)
+{
+ DPRINT_IMPL("UhciEndSendOnePacket: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+UhciPassThru(IN PVOID uhciExtension,
+ IN PVOID passThruParameters,
+ IN ULONG ParameterLength,
+ IN PVOID pParameters)
+{
+ DPRINT_IMPL("UhciPassThru: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+UhciFlushInterrupts(IN PVOID uhciExtension)
+{
+ DPRINT_IMPL("UhciFlushInterrupts: UNIMPLEMENTED. FIXME\n");
+}
+
+MPSTATUS
+NTAPI
+UhciUnload(IN PVOID uhciExtension)
+{
+ DPRINT_IMPL("UhciUnload: UNIMPLEMENTED. FIXME\n");
+ return MP_STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath)
+{
+ DPRINT("DriverEntry: DriverObject - %p, RegistryPath - %p\n", DriverObject,
RegistryPath);
+
+ RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET));
+
+ RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_UHCI;
+
+ RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT |
+ USB_MINIPORT_FLAGS_PORT_IO |
+ USB_MINIPORT_FLAGS_NOT_LOCK_INT |
+ USB_MINIPORT_FLAGS_POLLING |
+ USB_MINIPORT_FLAGS_WAKE_SUPPORT;
+
+ RegPacket.MiniPortBusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
+
+ RegPacket.MiniPortExtensionSize = sizeof(UHCI_EXTENSION);
+ RegPacket.MiniPortEndpointSize = sizeof(UHCI_ENDPOINT);
+ RegPacket.MiniPortTransferSize = sizeof(UHCI_TRANSFER);
+ RegPacket.MiniPortResourcesSize = sizeof(UHCI_HC_RESOURCES);
+
+ RegPacket.OpenEndpoint = UhciOpenEndpoint;
+ RegPacket.ReopenEndpoint = UhciReopenEndpoint;
+ RegPacket.QueryEndpointRequirements = UhciQueryEndpointRequirements;
+ RegPacket.CloseEndpoint = UhciCloseEndpoint;
+ RegPacket.StartController = UhciStartController;
+ RegPacket.StopController = UhciStopController;
+ RegPacket.SuspendController = UhciSuspendController;
+ RegPacket.ResumeController = UhciResumeController;
+ RegPacket.InterruptService = UhciInterruptService;
+ RegPacket.InterruptDpc = UhciInterruptDpc;
+ RegPacket.SubmitTransfer = UhciSubmitTransfer;
+ RegPacket.SubmitIsoTransfer = UhciIsochTransfer;
+ RegPacket.AbortTransfer = UhciAbortTransfer;
+ RegPacket.GetEndpointState = UhciGetEndpointState;
+ RegPacket.SetEndpointState = UhciSetEndpointState;
+ RegPacket.PollEndpoint = UhciPollEndpoint;
+ RegPacket.CheckController = UhciCheckController;
+ RegPacket.Get32BitFrameNumber = UhciGet32BitFrameNumber;
+ RegPacket.InterruptNextSOF = UhciInterruptNextSOF;
+ RegPacket.EnableInterrupts = UhciEnableInterrupts;
+ RegPacket.DisableInterrupts = UhciDisableInterrupts;
+ RegPacket.PollController = UhciPollController;
+ RegPacket.SetEndpointDataToggle = UhciSetEndpointDataToggle;
+ RegPacket.GetEndpointStatus = UhciGetEndpointStatus;
+ RegPacket.SetEndpointStatus = UhciSetEndpointStatus;
+ RegPacket.RH_GetRootHubData = UhciRHGetRootHubData;
+ RegPacket.RH_GetStatus = UhciRHGetStatus;
+ RegPacket.RH_GetPortStatus = UhciRHGetPortStatus;
+ RegPacket.RH_GetHubStatus = UhciRHGetHubStatus;
+ RegPacket.RH_SetFeaturePortReset = UhciRHSetFeaturePortReset;
+ RegPacket.RH_SetFeaturePortPower = UhciRHSetFeaturePortPower;
+ RegPacket.RH_SetFeaturePortEnable = UhciRHSetFeaturePortEnable;
+ RegPacket.RH_SetFeaturePortSuspend = UhciRHSetFeaturePortSuspend;
+ RegPacket.RH_ClearFeaturePortEnable = UhciRHClearFeaturePortEnable;
+ RegPacket.RH_ClearFeaturePortPower = UhciRHClearFeaturePortPower;
+ RegPacket.RH_ClearFeaturePortSuspend = UhciRHClearFeaturePortSuspend;
+ RegPacket.RH_ClearFeaturePortEnableChange = UhciRHClearFeaturePortEnableChange;
+ RegPacket.RH_ClearFeaturePortConnectChange = UhciRHClearFeaturePortConnectChange;
+ RegPacket.RH_ClearFeaturePortResetChange = UhciRHClearFeaturePortResetChange;
+ RegPacket.RH_ClearFeaturePortSuspendChange = UhciRHClearFeaturePortSuspendChange;
+ RegPacket.RH_ClearFeaturePortOvercurrentChange =
UhciRHClearFeaturePortOvercurrentChange;
+ RegPacket.RH_DisableIrq = UhciRHDisableIrq;
+ RegPacket.RH_EnableIrq = UhciRHEnableIrq;
+ RegPacket.StartSendOnePacket = UhciStartSendOnePacket;
+ RegPacket.EndSendOnePacket = UhciEndSendOnePacket;
+ RegPacket.PassThru = UhciPassThru;
+ RegPacket.FlushInterrupts = UhciFlushInterrupts;
+
+ DriverObject->DriverUnload = NULL;
+
+ return USBPORT_RegisterUSBPortDriver(DriverObject,
+ USB10_MINIPORT_INTERFACE_VERSION,
+ &RegPacket);
+}
diff --git a/drivers/usb/usbuhci_new/usbuhci.h b/drivers/usb/usbuhci_new/usbuhci.h
new file mode 100644
index 0000000000..f9db2d7d6a
--- /dev/null
+++ b/drivers/usb/usbuhci_new/usbuhci.h
@@ -0,0 +1,297 @@
+#ifndef USBUHCI_H__
+#define USBUHCI_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 UHCI_MAX_HC_SCHEDULE_ERRORS 16
+#define UHCI_RH_STATUS_SUCCESS 1
+
+#define UHCI_MAX_ISO_TRANSFER_SIZE 0x10000
+#define UHCI_MAX_BULK_TRANSFER_SIZE 0x1000
+//#define UHCI_MAX_BULK_TRANSFER_SIZE 0x10000 // Hack for testing w/o Split
Transfers
+#define UHCI_MAX_ISO_TD_COUNT 256
+#define UHCI_MAX_INTERRUPT_TD_COUNT 8
+
+/* Host Controller Driver Transfer Descriptor (HCD TD) */
+#define UHCI_HCD_TD_FLAG_ALLOCATED 0x00000001
+#define UHCI_HCD_TD_FLAG_PROCESSED 0x00000002
+#define UHCI_HCD_TD_FLAG_DONE 0x00000008
+#define UHCI_HCD_TD_FLAG_NOT_ACCESSED 0x00000010
+#define UHCI_HCD_TD_FLAG_DATA_BUFFER 0x00000020
+#define UHCI_HCD_TD_FLAG_GOOD_FRAME 0x00000040
+#define UHCI_HCD_TD_FLAG_CONTROLL 0x00000400
+#define UHCI_HCD_TD_FLAG_STALLED_SETUP 0x00000800
+
+typedef struct _UHCI_ENDPOINT *PUHCI_ENDPOINT;
+typedef struct _UHCI_TRANSFER *PUHCI_TRANSFER;
+
+typedef struct _UHCI_HCD_TD {
+ /* Hardware */
+ UHCI_TD HwTD;
+ /* Software */
+ USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+ ULONG PhysicalAddress;
+ ULONG Flags;
+ struct _UHCI_HCD_TD * NextHcdTD;
+ _ANONYMOUS_UNION union {
+ PUHCI_TRANSFER UhciTransfer;
+#if !defined(_M_X64)
+ ULONG Frame; // for SOF_HcdTDs only
+#else
+ struct {
+ ULONG Frame;
+ ULONG Pad2;
+ };
+#endif
+ } DUMMYUNIONNAME;
+ LIST_ENTRY TdLink;
+#if !defined(_M_X64)
+ ULONG Padded[4];
+#else
+ ULONG Padded[15];
+#endif
+} UHCI_HCD_TD, *PUHCI_HCD_TD;
+
+#if !defined(_M_X64)
+C_ASSERT(sizeof(UHCI_HCD_TD) == 0x40);
+#else
+C_ASSERT(sizeof(UHCI_HCD_TD) == 0x80);
+#endif
+
+/* Host Controller Driver Queue Header (HCD QH) */
+#define UHCI_HCD_QH_FLAG_ACTIVE 0x00000001
+#define UHCI_HCD_QH_FLAG_REMOVE 0x00000002
+
+typedef struct _UHCI_HCD_QH {
+ /* Hardware */
+ UHCI_QH HwQH;
+ /* Software */
+ ULONG PhysicalAddress;
+ ULONG QhFlags;
+ struct _UHCI_HCD_QH * NextHcdQH;
+#if !defined(_M_X64)
+ ULONG Pad1;
+#endif
+ struct _UHCI_HCD_QH * PrevHcdQH;
+#if !defined(_M_X64)
+ ULONG Pad2;
+#endif
+ PUHCI_ENDPOINT UhciEndpoint;
+#if !defined(_M_X64)
+ ULONG Pad3;
+#endif
+ ULONG Padded[6];
+} UHCI_HCD_QH, *PUHCI_HCD_QH;
+
+C_ASSERT(sizeof(UHCI_HCD_QH) == 0x40);
+
+#define UHCI_ENDPOINT_FLAG_HALTED 1
+#define UHCI_ENDPOINT_FLAG_RESERVED 2
+#define UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO 4
+
+/* UHCI Endpoint follows USBPORT Endpoint */
+typedef struct _UHCI_ENDPOINT {
+ ULONG Flags;
+ LONG EndpointLock;
+ USBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+ PUHCI_HCD_QH QH;
+ PUHCI_HCD_TD TailTD;
+ PUHCI_HCD_TD HeadTD;
+ PUHCI_HCD_TD FirstTD;
+ ULONG MaxTDs;
+ ULONG AllocatedTDs;
+ ULONG AllocTdCounter;
+ LIST_ENTRY ListTDs;
+ BOOL DataToggle;
+} UHCI_ENDPOINT, *PUHCI_ENDPOINT;
+
+/* UHCI Transfer follows USBPORT Transfer */
+typedef struct _UHCI_TRANSFER {
+ PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
+ PUHCI_ENDPOINT UhciEndpoint;
+ USBD_STATUS USBDStatus;
+ ULONG PendingTds;
+ SIZE_T TransferLen;
+} UHCI_TRANSFER, *PUHCI_TRANSFER;
+
+#define UHCI_FRAME_LIST_POINTER_VALID (0 << 0)
+#define UHCI_FRAME_LIST_POINTER_TERMINATE (1 << 0)
+#define UHCI_FRAME_LIST_POINTER_TD (0 << 1)
+#define UHCI_FRAME_LIST_POINTER_QH (1 << 1)
+
+#define UHCI_FRAME_LIST_INDEX_MASK 0x3FF
+#define UHCI_MAX_STATIC_SOF_TDS 8
+
+typedef struct _UHCI_HC_RESOURCES {
+ ULONG FrameList[UHCI_FRAME_LIST_MAX_ENTRIES]; // The 4-Kbyte Frame List Table is
aligned on a 4-Kbyte boundary
+ UHCI_HCD_QH StaticIntHead[INTERRUPT_ENDPOINTs];
+ UHCI_HCD_QH StaticControlHead;
+ UHCI_HCD_QH StaticBulkHead;
+ UHCI_HCD_TD StaticBulkTD;
+ UHCI_HCD_TD StaticTD;
+ UHCI_HCD_TD StaticSofTD[UHCI_MAX_STATIC_SOF_TDS];
+} UHCI_HC_RESOURCES, *PUHCI_HC_RESOURCES;
+
+#define UHCI_EXTENSION_FLAG_SUSPENDED 0x00000002
+
+/* UHCI Extension follows USBPORT Extension */
+typedef struct _UHCI_EXTENSION {
+ PUHCI_HW_REGISTERS BaseRegister;
+ USB_CONTROLLER_FLAVOR HcFlavor;
+ PUHCI_HC_RESOURCES HcResourcesVA;
+ ULONG HcResourcesPA;
+ PUHCI_HCD_QH IntQH[INTERRUPT_ENDPOINTs];
+ PUHCI_HCD_QH ControlQH;
+ PUHCI_HCD_QH BulkQH;
+ PUHCI_HCD_QH BulkTailQH;
+ PUHCI_HCD_TD StaticTD;
+ PUHCI_HCD_TD SOF_HcdTDs; // pointer to array StaticSofTD[UHCI_MAX_STATIC_SOF_TDS]
+ ULONG FrameNumber;
+ ULONG FrameHighPart;
+ ULONG Flags;
+ LONG LockFrameList;
+ ULONG ResetPortMask;
+ ULONG ResetChangePortMask;
+ ULONG SuspendChangePortMask;
+ ULONG HcScheduleError;
+ LONG ExtensionLock;
+ UHCI_USB_STATUS StatusMask;
+ UHCI_USB_STATUS HcStatus;
+ UCHAR SOF_Modify;
+ UCHAR Padded2[3];
+} UHCI_EXTENSION, *PUHCI_EXTENSION;
+
+/* roothub.c */
+VOID
+NTAPI
+UhciRHGetRootHubData(
+ IN PVOID uhciExtension,
+ IN PVOID rootHubData);
+
+MPSTATUS
+NTAPI
+UhciRHGetStatus(
+ IN PVOID uhciExtension,
+ IN PUSHORT Status);
+
+MPSTATUS
+NTAPI
+UhciRHGetPortStatus(
+ IN PVOID uhciExtension,
+ IN USHORT Port,
+ IN PUSB_PORT_STATUS_AND_CHANGE PortStatus);
+
+MPSTATUS
+NTAPI
+UhciRHGetHubStatus(
+ IN PVOID uhciExtension,
+ IN PUSB_HUB_STATUS_AND_CHANGE HubStatus);
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortReset(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortPower(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortEnable(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHSetFeaturePortSuspend(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortEnable(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortPower(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortSuspend(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortEnableChange(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortConnectChange(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortResetChange(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortSuspendChange(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+MPSTATUS
+NTAPI
+UhciRHClearFeaturePortOvercurrentChange(
+ IN PVOID uhciExtension,
+ IN USHORT Port);
+
+VOID
+NTAPI
+UhciRHDisableIrq(
+ IN PVOID uhciExtension);
+
+VOID
+NTAPI
+UhciRHEnableIrq(
+ IN PVOID uhciExtension);
+
+/* usbuhci.c */
+VOID
+NTAPI
+UhciDisableInterrupts(
+ IN PVOID uhciExtension);
+
+ULONG
+NTAPI
+UhciGet32BitFrameNumber(
+ IN PVOID uhciExtension);
+
+BOOLEAN
+NTAPI
+UhciHardwarePresent(
+ IN PUHCI_EXTENSION UhciExtension);
+
+#endif /* USBUHCI_H__ */
diff --git a/drivers/usb/usbuhci_new/usbuhci.rc b/drivers/usb/usbuhci_new/usbuhci.rc
new file mode 100644
index 0000000000..801d5be736
--- /dev/null
+++ b/drivers/usb/usbuhci_new/usbuhci.rc
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION "USB UHCI miniport driver"
+#define REACTOS_STR_INTERNAL_NAME "usbuhci"
+#define REACTOS_STR_ORIGINAL_FILENAME "usbuhci.sys"
+#include <reactos/version.rc>