[USBUHCI_NEW] Bring-in the USB UHCI miniport driver created by Vadim Galyant. (#245)
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 1 Sep 2018 15:45:45 +0000 (16:45 +0100)
committerThomas Faber <18138474+ThFabba@users.noreply.github.com>
Sat, 1 Sep 2018 15:45:45 +0000 (17:45 +0200)
drivers/usb/CMakeLists.txt
drivers/usb/usbuhci_new/CMakeLists.txt [new file with mode: 0644]
drivers/usb/usbuhci_new/dbg_uhci.h [new file with mode: 0644]
drivers/usb/usbuhci_new/guid.c [new file with mode: 0644]
drivers/usb/usbuhci_new/hardware.h [new file with mode: 0644]
drivers/usb/usbuhci_new/roothub.c [new file with mode: 0644]
drivers/usb/usbuhci_new/usbuhci.c [new file with mode: 0644]
drivers/usb/usbuhci_new/usbuhci.h [new file with mode: 0644]
drivers/usb/usbuhci_new/usbuhci.rc [new file with mode: 0644]

index 51edb17..72b4869 100644 (file)
@@ -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 (file)
index 0000000..b46c724
--- /dev/null
@@ -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 (file)
index 0000000..50c03ca
--- /dev/null
@@ -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 (file)
index 0000000..50a6036
--- /dev/null
@@ -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 (file)
index 0000000..c9b6d4a
--- /dev/null
@@ -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 (file)
index 0000000..9ec3612
--- /dev/null
@@ -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 (file)
index 0000000..eed9b0b
--- /dev/null
@@ -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 (file)
index 0000000..f9db2d7
--- /dev/null
@@ -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 (file)
index 0000000..801d5be
--- /dev/null
@@ -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>