[USBOHCI_NEW] Bring-in the USB OHCI miniport driver created by Vadim Galyant. (#244)
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 12 Jan 2018 20:09:58 +0000 (21:09 +0100)
committerThomas Faber <github@tfaber.net>
Fri, 12 Jan 2018 20:09:58 +0000 (21:09 +0100)
[USBOHCI_NEW] Add the new usbport-based OHCI driver.

drivers/usb/CMakeLists.txt
drivers/usb/usbohci_new/CMakeLists.txt [new file with mode: 0644]
drivers/usb/usbohci_new/dbg_ohci.h [new file with mode: 0644]
drivers/usb/usbohci_new/guid.c [new file with mode: 0644]
drivers/usb/usbohci_new/hardware.h [new file with mode: 0644]
drivers/usb/usbohci_new/roothub.c [new file with mode: 0644]
drivers/usb/usbohci_new/usbohci.c [new file with mode: 0644]
drivers/usb/usbohci_new/usbohci.h [new file with mode: 0644]
drivers/usb/usbohci_new/usbohci.rc [new file with mode: 0644]

index d47a55c..05817b0 100644 (file)
@@ -4,6 +4,7 @@ add_subdirectory(usbehci)
 add_subdirectory(usbhub)
 #add_subdirectory(usbhub_new)
 add_subdirectory(usbohci)
+#add_subdirectory(usbohci_new)
 add_subdirectory(usbport)
 add_subdirectory(usbstor)
 add_subdirectory(usbuhci)
diff --git a/drivers/usb/usbohci_new/CMakeLists.txt b/drivers/usb/usbohci_new/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ea7634b
--- /dev/null
@@ -0,0 +1,15 @@
+
+list(APPEND SOURCE
+    roothub.c
+    usbohci.c
+    usbohci.h)
+
+add_library(usbohci SHARED
+    ${SOURCE}
+    guid.c
+    usbohci.rc)
+
+set_module_type(usbohci kernelmodedriver)
+add_importlibs(usbohci usbport usbd hal ntoskrnl)
+add_pch(usbohci usbohci.h SOURCE)
+add_cd_file(TARGET usbohci DESTINATION reactos/system32/drivers NO_CAB FOR all)
diff --git a/drivers/usb/usbohci_new/dbg_ohci.h b/drivers/usb/usbohci_new/dbg_ohci.h
new file mode 100644 (file)
index 0000000..273fe56
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef DBG_OHCI_H__
+#define DBG_OHCI_H__
+
+#if DBG
+
+    #ifndef NDEBUG_OHCI_TRACE
+        #define DPRINT_OHCI(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_OHCI __noop
+        #else
+            #define DPRINT_OHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
+        #endif
+    #endif
+
+#else /* not DBG */
+
+    #if defined(_MSC_VER)
+        #define DPRINT_OHCI __noop
+    #else
+        #define DPRINT_OHCI(...) do {if(0) {DbgPrint(__VA_ARGS__);}} while(0)
+    #endif /* _MSC_VER */
+
+#endif /* not DBG */
+
+#endif /* DBG_OHCI_H__ */
diff --git a/drivers/usb/usbohci_new/guid.c b/drivers/usb/usbohci_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/usbohci_new/hardware.h b/drivers/usb/usbohci_new/hardware.h
new file mode 100644 (file)
index 0000000..43fe27a
--- /dev/null
@@ -0,0 +1,328 @@
+#define OHCI_NUMBER_OF_INTERRUPTS    32
+#define OHCI_MAX_PORT_COUNT          15
+#define ED_EOF                       -1
+#define OHCI_MAXIMUM_OVERHEAD        210 // 5.4  FrameInterval Counter, in bit-times
+#define OHCI_DEFAULT_FRAME_INTERVAL  11999 // 6.3.1  Frame Timing
+#define OHCI_MINIMAL_POTPGT          25 // == 50 ms., PowerOnToPowerGoodTime (HcRhDescriptorA Register)
+
+/* Controller states */
+#define OHCI_HC_STATE_RESET       0
+#define OHCI_HC_STATE_RESUME      1
+#define OHCI_HC_STATE_OPERATIONAL 2
+#define OHCI_HC_STATE_SUSPEND     3
+
+/* Endpoint Descriptor Control */
+#define OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD 0
+#define OHCI_ED_DATA_FLOW_DIRECTION_OUT     1
+#define OHCI_ED_DATA_FLOW_DIRECTION_IN      2
+
+#define OHCI_ENDPOINT_FULL_SPEED 0
+#define OHCI_ENDPOINT_LOW_SPEED  1
+
+#define OHCI_ENDPOINT_GENERAL_FORMAT     0
+#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 1
+
+/* Transfer Descriptor Control */
+#define OHCI_TD_INTERRUPT_IMMEDIATE 0
+#define OHCI_TD_INTERRUPT_NONE      7
+
+#define OHCI_TD_DIRECTION_PID_SETUP    0
+#define OHCI_TD_DIRECTION_PID_OUT      1
+#define OHCI_TD_DIRECTION_PID_IN       2
+#define OHCI_TD_DIRECTION_PID_RESERVED 3
+
+#define OHCI_TD_DATA_TOGGLE_FROM_ED  0
+#define OHCI_TD_DATA_TOGGLE_DATA0    2
+#define OHCI_TD_DATA_TOGGLE_DATA1    3
+
+#define OHCI_TD_CONDITION_NO_ERROR          0x00
+#define OHCI_TD_CONDITION_CRC_ERROR         0x01
+#define OHCI_TD_CONDITION_BIT_STUFFING      0x02
+#define OHCI_TD_CONDITION_TOGGLE_MISMATCH   0x03
+#define OHCI_TD_CONDITION_STALL             0x04
+#define OHCI_TD_CONDITION_NO_RESPONSE       0x05
+#define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06
+#define OHCI_TD_CONDITION_UNEXPECTED_PID    0x07
+#define OHCI_TD_CONDITION_DATA_OVERRUN      0x08
+#define OHCI_TD_CONDITION_DATA_UNDERRUN     0x09
+#define OHCI_TD_CONDITION_BUFFER_OVERRUN    0x0C
+#define OHCI_TD_CONDITION_BUFFER_UNDERRUN   0x0D
+#define OHCI_TD_CONDITION_NOT_ACCESSED      0x0E
+
+#define OHCI_RH_STATUS_GOOD  1
+
+typedef union _OHCI_TRANSFER_CONTROL {
+  struct {
+    ULONG Reserved       : 18;
+    ULONG BufferRounding : 1;
+    ULONG DirectionPID   : 2;
+    ULONG DelayInterrupt : 3;
+    ULONG DataToggle     : 2;
+    ULONG ErrorCount     : 2;
+    ULONG ConditionCode  : 4;
+  };
+  ULONG  AsULONG;
+} OHCI_TRANSFER_CONTROL, *POHCI_TRANSFER_CONTROL;
+
+C_ASSERT(sizeof(OHCI_TRANSFER_CONTROL) == sizeof(ULONG));
+
+typedef struct _OHCI_TRANSFER_DESCRIPTOR { // must be aligned to a 16-byte boundary
+  OHCI_TRANSFER_CONTROL Control;
+  ULONG CurrentBuffer; // physical address of the next memory location
+  ULONG NextTD; // pointer to the next TD on the list of TDs
+  ULONG BufferEnd; // physical address of the last byte
+} OHCI_TRANSFER_DESCRIPTOR, *POHCI_TRANSFER_DESCRIPTOR;
+
+C_ASSERT(sizeof(OHCI_TRANSFER_DESCRIPTOR) == 16);
+
+typedef union _OHCI_ISO_TRANSFER_CONTROL {
+  struct {
+    ULONG StartingFrame  : 16;
+    ULONG Reserved1      : 5;
+    ULONG DelayInterrupt : 3;
+    ULONG FrameCount     : 3;
+    ULONG Reserved2      : 1;
+    ULONG ConditionCode  : 4;
+  };
+  ULONG  AsULONG;
+} OHCI_ISO_TRANSFER_CONTROL, *POHCI_ISO_TRANSFER_CONTROL;
+
+C_ASSERT(sizeof(OHCI_ISO_TRANSFER_CONTROL) == sizeof(ULONG));
+
+typedef struct _OHCI_ISO_TRANSFER_DESCRIPTOR { // must be aligned to a 32-byte boundary
+  OHCI_ISO_TRANSFER_CONTROL Control;
+  ULONG BufferPage0; // physical page number of the 1 byte of the data buffer
+  ULONG NextTD; // pointer to the next Isochronous TD on the queue of Isochronous TDs
+  ULONG BufferEnd; // physical address of the last byte in the buffer
+  USHORT Offset[8]; // for determine size and start addr. iso packet | PacketStatusWord - completion code
+} OHCI_ISO_TRANSFER_DESCRIPTOR, *POHCI_ISO_TRANSFER_DESCRIPTOR;
+
+C_ASSERT(sizeof(OHCI_ISO_TRANSFER_DESCRIPTOR) == 32);
+
+typedef union _OHCI_ENDPOINT_CONTROL {
+  struct {
+    ULONG FunctionAddress   : 7;
+    ULONG EndpointNumber    : 4;
+    ULONG Direction         : 2;
+    ULONG Speed             : 1;
+    ULONG sKip              : 1;
+    ULONG Format            : 1;
+    ULONG MaximumPacketSize : 11;
+    ULONG Reserved          : 5;
+  };
+  ULONG  AsULONG;
+} OHCI_ENDPOINT_CONTROL, *POHCI_ENDPOINT_CONTROL;
+
+C_ASSERT(sizeof(OHCI_ENDPOINT_CONTROL) == sizeof(ULONG));
+
+/* Bit flags for HeadPointer member of the EP descriptor */
+#define OHCI_ED_HEAD_POINTER_HALT        0x00000001 // hardware stopped bit
+#define OHCI_ED_HEAD_POINTER_CARRY       0x00000002 // hardware toggle carry bit
+#define OHCI_ED_HEAD_POINTER_MASK        0XFFFFFFF0 // mask physical pointer
+#define OHCI_ED_HEAD_POINTER_FLAGS_MASK  0X0000000F // mask bit flags
+
+typedef struct _OHCI_ENDPOINT_DESCRIPTOR { // must be aligned to a 16-byte boundary
+  OHCI_ENDPOINT_CONTROL EndpointControl;
+  ULONG TailPointer; // if TailP and HeadP are different, then the list contains a TD to be processed
+  ULONG HeadPointer; // physical pointer to the next TD to be processed for this endpoint
+  ULONG NextED; // entry points to the next ED on the list
+} OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
+
+C_ASSERT(sizeof(OHCI_ENDPOINT_DESCRIPTOR) == 16);
+
+typedef struct _OHCI_HCCA { // must be located on a 256-byte boundary
+  ULONG InterrruptTable[OHCI_NUMBER_OF_INTERRUPTS];
+  USHORT FrameNumber;
+  USHORT Pad1;
+  ULONG DoneHead;
+  UCHAR reserved_hc[116];
+  UCHAR Pad[4];
+} OHCI_HCCA, *POHCI_HCCA;
+
+C_ASSERT(sizeof(OHCI_HCCA) == 256);
+
+typedef union _OHCI_REG_CONTROL {
+  struct {
+    ULONG ControlBulkServiceRatio       : 2;
+    ULONG PeriodicListEnable            : 1;
+    ULONG IsochronousEnable             : 1;
+    ULONG ControlListEnable             : 1;
+    ULONG BulkListEnable                : 1;
+    ULONG HostControllerFunctionalState : 2;
+    ULONG InterruptRouting              : 1;
+    ULONG RemoteWakeupConnected         : 1;
+    ULONG RemoteWakeupEnable            : 1;
+    ULONG Reserved                      : 21;
+  };
+  ULONG AsULONG;
+} OHCI_REG_CONTROL, *POHCI_REG_CONTROL;
+
+C_ASSERT(sizeof(OHCI_REG_CONTROL) == sizeof(ULONG));
+
+typedef union _OHCI_REG_COMMAND_STATUS {
+  struct {
+    ULONG HostControllerReset    : 1;
+    ULONG ControlListFilled      : 1;
+    ULONG BulkListFilled         : 1;
+    ULONG OwnershipChangeRequest : 1;
+    ULONG Reserved1              : 12;
+    ULONG SchedulingOverrunCount : 1;
+    ULONG Reserved2              : 15;
+  };
+  ULONG AsULONG;
+} OHCI_REG_COMMAND_STATUS, *POHCI_REG_COMMAND_STATUS;
+
+C_ASSERT(sizeof(OHCI_REG_COMMAND_STATUS) == sizeof(ULONG));
+
+typedef union _OHCI_REG_INTERRUPT_STATUS {
+  struct {
+    ULONG SchedulingOverrun   : 1;
+    ULONG WritebackDoneHead   : 1;
+    ULONG StartofFrame        : 1;
+    ULONG ResumeDetected      : 1;
+    ULONG UnrecoverableError  : 1;
+    ULONG FrameNumberOverflow : 1;
+    ULONG RootHubStatusChange : 1;
+    ULONG Reserved1           : 23;
+    ULONG OwnershipChange     : 1;
+    ULONG Reserved2           : 1;
+  };
+  ULONG AsULONG;
+} OHCI_REG_INTERRUPT_STATUS, *POHCI_REG_INTERRUPT_STATUS;
+
+C_ASSERT(sizeof(OHCI_REG_INTERRUPT_STATUS) == sizeof(ULONG));
+
+typedef union _OHCI_REG_INTERRUPT_ENABLE_DISABLE {
+  struct {
+    ULONG SchedulingOverrun     : 1;
+    ULONG WritebackDoneHead     : 1;
+    ULONG StartofFrame          : 1;
+    ULONG ResumeDetected        : 1;
+    ULONG UnrecoverableError    : 1;
+    ULONG FrameNumberOverflow   : 1;
+    ULONG RootHubStatusChange   : 1;
+    ULONG Reserved1             : 23;
+    ULONG OwnershipChange       : 1;
+    ULONG MasterInterruptEnable : 1;
+  };
+  ULONG AsULONG;
+} OHCI_REG_INTERRUPT_ENABLE_DISABLE, *POHCI_REG_INTERRUPT_ENABLE_DISABLE;
+
+C_ASSERT(sizeof(OHCI_REG_INTERRUPT_ENABLE_DISABLE) == sizeof(ULONG));
+
+typedef union _OHCI_REG_FRAME_INTERVAL {
+  struct {
+    ULONG FrameInterval       : 14;
+    ULONG Reserved            : 2;
+    ULONG FSLargestDataPacket : 15;
+    ULONG FrameIntervalToggle : 1;
+  };
+  ULONG AsULONG;
+} OHCI_REG_FRAME_INTERVAL, *POHCI_REG_FRAME_INTERVAL;
+
+C_ASSERT(sizeof(OHCI_REG_FRAME_INTERVAL) == sizeof(ULONG));
+
+typedef union _OHCI_REG_RH_DESCRIPTORA {
+  struct {
+    ULONG NumberDownstreamPorts     : 8;
+    ULONG PowerSwitchingMode        : 1;
+    ULONG NoPowerSwitching          : 1;
+    ULONG DeviceType                : 1;
+    ULONG OverCurrentProtectionMode : 1;
+    ULONG NoOverCurrentProtection   : 1;
+    ULONG Reserved                  : 11;
+    ULONG PowerOnToPowerGoodTime    : 8;
+  };
+  ULONG AsULONG;
+} OHCI_REG_RH_DESCRIPTORA, *POHCI_REG_RH_DESCRIPTORA;
+
+C_ASSERT(sizeof(OHCI_REG_RH_DESCRIPTORA) == sizeof(ULONG));
+
+typedef union _OHCI_REG_RH_STATUS {
+  union {
+    struct { // read
+      ULONG LocalPowerStatus            : 1;
+      ULONG OverCurrentIndicator        : 1;
+      ULONG Reserved10                  : 13;
+      ULONG DeviceRemoteWakeupEnable    : 1;
+      ULONG LocalPowerStatusChange      : 1;
+      ULONG OverCurrentIndicatorChangeR : 1;
+      ULONG Reserved20                  : 14;
+    };
+    struct { // write
+      ULONG ClearGlobalPower            : 1;
+      ULONG Reserved11                  : 14;
+      ULONG SetRemoteWakeupEnable       : 1;
+      ULONG SetGlobalPower              : 1;
+      ULONG OverCurrentIndicatorChangeW : 1;
+      ULONG Reserved22                  : 13;
+      ULONG ClearRemoteWakeupEnable     : 1;
+    };
+  };
+  ULONG AsULONG;
+} OHCI_REG_RH_STATUS, *POHCI_REG_RH_STATUS;
+
+C_ASSERT(sizeof(OHCI_REG_RH_STATUS) == sizeof(ULONG));
+
+typedef union _OHCI_REG_RH_PORT_STATUS {
+  struct {
+    union  {
+      struct { // read
+        USHORT  CurrentConnectStatus     : 1;
+        USHORT  PortEnableStatus         : 1;
+        USHORT  PortSuspendStatus        : 1;
+        USHORT  PortOverCurrentIndicator : 1;
+        USHORT  PortResetStatus          : 1;
+        USHORT  Reserved1r               : 3;
+        USHORT  PortPowerStatus          : 1;
+        USHORT  LowSpeedDeviceAttached   : 1;
+        USHORT  Reserved2r               : 6;
+      };
+      struct { // write
+        USHORT  ClearPortEnable    : 1;
+        USHORT  SetPortEnable      : 1;
+        USHORT  SetPortSuspend     : 1;
+        USHORT  ClearSuspendStatus : 1;
+        USHORT  SetPortReset       : 1;
+        USHORT  Reserved1w         : 3;
+        USHORT  SetPortPower       : 1;
+        USHORT  ClearPortPower     : 1;
+        USHORT  Reserved2w         : 6;
+      };
+    };
+    USHORT ConnectStatusChange            : 1;
+    USHORT PortEnableStatusChange         : 1;
+    USHORT PortSuspendStatusChange        : 1;
+    USHORT PortOverCurrentIndicatorChange : 1;
+    USHORT PortResetStatusChange          : 1;
+    USHORT Reserved3                      : 11;
+  };
+  ULONG  AsULONG;
+} OHCI_REG_RH_PORT_STATUS, *POHCI_REG_RH_PORT_STATUS;
+
+C_ASSERT(sizeof(OHCI_REG_RH_PORT_STATUS) == sizeof(ULONG));
+
+typedef struct _OHCI_OPERATIONAL_REGISTERS {
+  ULONG HcRevision;
+  OHCI_REG_CONTROL HcControl;
+  OHCI_REG_COMMAND_STATUS HcCommandStatus;
+  OHCI_REG_INTERRUPT_STATUS HcInterruptStatus;
+  OHCI_REG_INTERRUPT_ENABLE_DISABLE HcInterruptEnable;
+  OHCI_REG_INTERRUPT_ENABLE_DISABLE HcInterruptDisable;
+  ULONG HcHCCA;
+  ULONG HcPeriodCurrentED;
+  ULONG HcControlHeadED;
+  ULONG HcControlCurrentED;
+  ULONG HcBulkHeadED;
+  ULONG HcBulkCurrentED;
+  ULONG HcDoneHead;
+  OHCI_REG_FRAME_INTERVAL HcFmInterval;
+  ULONG HcFmRemaining;
+  ULONG HcFmNumber;
+  ULONG HcPeriodicStart;
+  ULONG HcLSThreshold;
+  OHCI_REG_RH_DESCRIPTORA HcRhDescriptorA;
+  ULONG HcRhDescriptorB;
+  OHCI_REG_RH_STATUS HcRhStatus;
+  OHCI_REG_RH_PORT_STATUS HcRhPortStatus[OHCI_MAX_PORT_COUNT];
+} OHCI_OPERATIONAL_REGISTERS, *POHCI_OPERATIONAL_REGISTERS;
diff --git a/drivers/usb/usbohci_new/roothub.c b/drivers/usb/usbohci_new/roothub.c
new file mode 100644 (file)
index 0000000..bbd4e7e
--- /dev/null
@@ -0,0 +1,579 @@
+#include "usbohci.h"
+
+#define NDEBUG
+#include <debug.h>
+
+OHCI_REG_RH_DESCRIPTORA
+NTAPI 
+OHCI_ReadRhDescriptorA(IN POHCI_EXTENSION OhciExtension)
+{
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    OHCI_REG_RH_DESCRIPTORA DescriptorA;
+    PULONG DescriptorAReg;
+    ULONG ix;
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    DescriptorAReg = (PULONG)&OperationalRegs->HcRhDescriptorA;
+
+    DPRINT("OHCI_ReadRhDescriptorA: OhciExtension - %p\n", OhciExtension);
+
+    for (ix = 0; ix < 10; ix++)
+    {
+        DescriptorA.AsULONG = READ_REGISTER_ULONG(DescriptorAReg);
+
+        if (DescriptorA.AsULONG != 0 &&
+            DescriptorA.Reserved == 0 &&
+            DescriptorA.NumberDownstreamPorts <= OHCI_MAX_PORT_COUNT)
+        {
+            break;
+        }
+
+        DPRINT1("OHCI_ReadRhDescriptorA: DescriptorA - %lX, ix - %d\n",
+                DescriptorA.AsULONG, ix);
+
+        KeStallExecutionProcessor(5);
+    }
+
+    return DescriptorA;
+}
+
+VOID
+NTAPI
+OHCI_RH_GetRootHubData(IN PVOID ohciExtension,
+                       IN PVOID rootHubData)
+{
+    POHCI_EXTENSION OhciExtension;
+    PUSBPORT_ROOT_HUB_DATA RootHubData;
+    OHCI_REG_RH_DESCRIPTORA DescriptorA;
+    UCHAR PowerOnToPowerGoodTime;
+    USBPORT_HUB_11_CHARACTERISTICS HubCharacteristics;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_GetRootHubData: OhciExtension - %p, rootHubData - %p\n",
+           OhciExtension,
+           rootHubData);
+
+    RootHubData = rootHubData;
+    DescriptorA = OHCI_ReadRhDescriptorA(OhciExtension);
+
+    RootHubData->NumberOfPorts = DescriptorA.NumberDownstreamPorts;
+
+    /* Waiting time (in 2 ms intervals) */
+    PowerOnToPowerGoodTime = DescriptorA.PowerOnToPowerGoodTime;
+    if (PowerOnToPowerGoodTime <= OHCI_MINIMAL_POTPGT)
+        PowerOnToPowerGoodTime = OHCI_MINIMAL_POTPGT;
+    RootHubData->PowerOnToPowerGood = PowerOnToPowerGoodTime;
+
+    HubCharacteristics.AsUSHORT = 0;
+
+    if (DescriptorA.PowerSwitchingMode)
+    {
+        /* Individual port power switching */
+        HubCharacteristics.PowerControlMode = 1;
+    }
+    else
+    {
+        /* Ganged power switching */
+        HubCharacteristics.PowerControlMode = 0;
+    }
+
+    HubCharacteristics.NoPowerSwitching = 0;
+
+    /* always 0 (OHCI RH is not a compound device) */
+    ASSERT(DescriptorA.DeviceType == 0);
+    HubCharacteristics.PartOfCompoundDevice = DescriptorA.DeviceType;
+
+    HubCharacteristics.OverCurrentProtectionMode = DescriptorA.OverCurrentProtectionMode;
+    HubCharacteristics.NoOverCurrentProtection = DescriptorA.NoOverCurrentProtection;
+
+    RootHubData->HubCharacteristics.Usb11HubCharacteristics = HubCharacteristics;
+    RootHubData->HubControlCurrent = 0;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetStatus(IN PVOID ohciExtension,
+                  IN PUSHORT Status)
+{
+    DPRINT("OHCI_RH_GetStatus: \n");
+    *Status = OHCI_RH_STATUS_GOOD;
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetPortStatus(IN PVOID ohciExtension,
+                      IN USHORT Port,
+                      IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS OhciPortStatus;
+    ULONG ix;
+    ULONG Reserved;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_GetPortStatus: OhciExtension - %p, Port - %x, PortStatus - %lX\n",
+           OhciExtension,
+           Port,
+           PortStatus->AsUlong32);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    for (ix = 0; ix < 10; ix++)
+    {
+        OhciPortStatus.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
+
+        Reserved = OhciPortStatus.Reserved1r |
+                   OhciPortStatus.Reserved2r |
+                   OhciPortStatus.Reserved3;
+
+        if (OhciPortStatus.AsULONG && !Reserved)
+            break;
+
+        DPRINT("OHCI_RH_GetPortStatus: OhciPortStatus - %X\n", OhciPortStatus.AsULONG);
+
+        KeStallExecutionProcessor(5);
+    }
+
+    PortStatus->AsUlong32 = OhciPortStatus.AsULONG;
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetHubStatus(IN PVOID ohciExtension,
+                     IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG RhStatusReg;
+    OHCI_REG_RH_STATUS HcRhStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_GetHubStatus: ohciExtension - %p, HubStatus - %lX\n",
+           ohciExtension,
+           HubStatus->AsUlong32);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
+
+    HcRhStatus.AsULONG = READ_REGISTER_ULONG(RhStatusReg);
+
+    HubStatus->HubStatus.LocalPowerLost = HcRhStatus.LocalPowerStatus;
+    HubStatus->HubChange.LocalPowerChange = HcRhStatus.LocalPowerStatusChange;
+
+    HubStatus->HubStatus.OverCurrent = HcRhStatus.OverCurrentIndicator;
+    HubStatus->HubChange.OverCurrentChange = HcRhStatus.OverCurrentIndicatorChangeR;
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortReset(IN PVOID ohciExtension,
+                            IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_SetFeaturePortReset: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.SetPortReset = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortPower(IN PVOID ohciExtension,
+                            IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_SetFeaturePortPower: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.SetPortPower = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortEnable(IN PVOID ohciExtension,
+                             IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_SetFeaturePortEnable: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.SetPortEnable = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortSuspend(IN PVOID ohciExtension,
+                              IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_SetFeaturePortSuspend: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.SetPortSuspend = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortEnable(IN PVOID ohciExtension,
+                               IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortEnable: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.ClearPortEnable = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortPower(IN PVOID ohciExtension,
+                              IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortPower: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.ClearPortPower = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortSuspend(IN PVOID ohciExtension,
+                                IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortSuspend: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.ClearSuspendStatus = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortEnableChange(IN PVOID ohciExtension,
+                                     IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortEnableChange: ohciExtension - %p, Port - %x\n",
+           ohciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.PortEnableStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortConnectChange(IN PVOID ohciExtension,
+                                      IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortConnectChange: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.ConnectStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortResetChange(IN PVOID ohciExtension,
+                                    IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortResetChange: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.PortResetStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortSuspendChange(IN PVOID ohciExtension,
+                                      IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortSuspendChange: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    ASSERT(Port > 0);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+    PortStatus.AsULONG = 0;
+    PortStatus.PortSuspendStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortOvercurrentChange(IN PVOID ohciExtension,
+                                          IN USHORT Port)
+{
+    POHCI_EXTENSION OhciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG PortStatusReg;
+    PULONG RhStatusReg;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+    OHCI_REG_RH_STATUS RhStatus;
+
+    OhciExtension = ohciExtension;
+
+    DPRINT("OHCI_RH_ClearFeaturePortOvercurrentChange: OhciExtension - %p, Port - %x\n",
+           OhciExtension,
+           Port);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    if (Port)
+    {
+        /* USBPORT_RECIPIENT_PORT */
+        PortStatus.AsULONG = 0;
+        PortStatus.PortOverCurrentIndicatorChange = 1;
+
+        PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+        WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+    }
+    else
+    {
+        /* USBPORT_RECIPIENT_HUB */
+        RhStatus.AsULONG = 0;
+        RhStatus.OverCurrentIndicatorChangeW = 1;
+
+        RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
+        WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
+    }
+
+    return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+OHCI_RH_DisableIrq(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION  OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG InterruptDisableReg;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptDisable;
+
+    DPRINT("OHCI_RH_DisableIrq: OhciExtension - %p\n", OhciExtension);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
+
+    InterruptDisable.AsULONG = 0;
+    InterruptDisable.RootHubStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(InterruptDisableReg, InterruptDisable.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_RH_EnableIrq(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG InterruptEnableReg;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptEnable;
+
+    DPRINT("OHCI_RH_EnableIrq: OhciExtension - %p\n", OhciExtension);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+
+    InterruptEnable.AsULONG = 0;
+    InterruptEnable.RootHubStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptEnable.AsULONG);
+}
diff --git a/drivers/usb/usbohci_new/usbohci.c b/drivers/usb/usbohci_new/usbohci.c
new file mode 100644 (file)
index 0000000..87c3c13
--- /dev/null
@@ -0,0 +1,2653 @@
+#include "usbohci.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_OHCI_TRACE
+#include "dbg_ohci.h"
+
+USBPORT_REGISTRATION_PACKET RegPacket;
+
+static const UCHAR Index[8] =
+{
+    ENDPOINT_INTERRUPT_1ms - 1,
+    ENDPOINT_INTERRUPT_2ms - 1,
+    ENDPOINT_INTERRUPT_4ms - 1,
+    ENDPOINT_INTERRUPT_8ms - 1,
+    ENDPOINT_INTERRUPT_16ms - 1,
+    ENDPOINT_INTERRUPT_32ms - 1,
+    ENDPOINT_INTERRUPT_32ms - 1,
+    ENDPOINT_INTERRUPT_32ms - 1
+};
+
+static const UCHAR Balance[OHCI_NUMBER_OF_INTERRUPTS] =
+{
+    0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,
+    1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31
+};
+
+VOID
+NTAPI 
+OHCI_DumpHcdED(POHCI_HCD_ED ED)
+{
+    DPRINT("ED                - %p\n", ED);
+    DPRINT("EndpointControl   - %X\n", ED->HwED.EndpointControl.AsULONG);
+    DPRINT("TailPointer       - %08X\n", ED->HwED.TailPointer);
+    DPRINT("HeadPointer       - %08X\n", ED->HwED.HeadPointer);
+    DPRINT("NextED            - %08X\n", ED->HwED.NextED);
+}
+
+VOID
+NTAPI 
+OHCI_DumpHcdTD(POHCI_HCD_TD TD)
+{
+    DPRINT("TD                - %p\n", TD);
+    DPRINT("gTD.Control       - %08X\n", TD->HwTD.gTD.Control.AsULONG);
+if (TD->HwTD.gTD.CurrentBuffer)
+    DPRINT("gTD.CurrentBuffer - %08X\n", TD->HwTD.gTD.CurrentBuffer);
+if (TD->HwTD.gTD.NextTD)
+    DPRINT("gTD.NextTD        - %08X\n", TD->HwTD.gTD.NextTD);
+if (TD->HwTD.gTD.BufferEnd)
+    DPRINT("gTD.BufferEnd     - %08X\n", TD->HwTD.gTD.BufferEnd);
+
+if (TD->HwTD.SetupPacket.bmRequestType.B)
+    DPRINT("bmRequestType     - %02X\n", TD->HwTD.SetupPacket.bmRequestType.B);
+if (TD->HwTD.SetupPacket.bRequest)
+    DPRINT("bRequest          - %02X\n", TD->HwTD.SetupPacket.bRequest);
+if (TD->HwTD.SetupPacket.wValue.W)
+    DPRINT("wValue            - %04X\n", TD->HwTD.SetupPacket.wValue.W);
+if (TD->HwTD.SetupPacket.wIndex.W)
+    DPRINT("wIndex            - %04X\n", TD->HwTD.SetupPacket.wIndex.W);
+if (TD->HwTD.SetupPacket.wLength)
+    DPRINT("wLength           - %04X\n", TD->HwTD.SetupPacket.wLength);
+
+    DPRINT("PhysicalAddress   - %p\n", TD->PhysicalAddress);
+    DPRINT("Flags             - %X\n", TD->Flags);
+    DPRINT("OhciTransfer      - %08X\n", TD->OhciTransfer);
+    DPRINT("NextHcdTD         - %08X\n", TD->NextHcdTD);
+if (TD->TransferLen)
+    DPRINT("TransferLen       - %X\n", TD->TransferLen);
+}
+
+VOID
+NTAPI
+OHCI_EnableList(IN POHCI_EXTENSION OhciExtension,
+                IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG CommandStatusReg;
+    ULONG TransferType;
+    OHCI_REG_COMMAND_STATUS CommandStatus;
+
+    DPRINT_OHCI("OHCI_EnableList: ... \n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
+
+    CommandStatus.AsULONG = 0;
+
+    if (READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcControlHeadED))
+        CommandStatus.ControlListFilled = 1;
+
+    if (READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcBulkHeadED))
+        CommandStatus.BulkListFilled = 1;
+
+    TransferType = OhciEndpoint->EndpointProperties.TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_BULK)
+        CommandStatus.BulkListFilled = 1;
+    else if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+        CommandStatus.ControlListFilled = 1;
+
+    WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_InsertEndpointInSchedule(IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_STATIC_ED HeadED;
+    POHCI_HCD_ED ED;
+    POHCI_HCD_ED PrevED;
+    PLIST_ENTRY HeadLink;
+
+    DPRINT_OHCI("OHCI_InsertEndpointInSchedule: OhciEndpoint - %p\n",
+                OhciEndpoint);
+
+    ED = OhciEndpoint->HcdED;
+
+    HeadED = OhciEndpoint->HeadED;
+    HeadLink = &HeadED->Link;
+
+    if (IsListEmpty(HeadLink))
+    {
+        InsertHeadList(HeadLink, &ED->HcdEDLink);
+
+        if (HeadED->Type == OHCI_STATIC_ED_TYPE_CONTROL ||
+            HeadED->Type == OHCI_STATIC_ED_TYPE_BULK)
+        {
+            ED->HwED.NextED = READ_REGISTER_ULONG(HeadED->pNextED);
+            WRITE_REGISTER_ULONG(HeadED->pNextED, ED->PhysicalAddress);
+        }
+        else if (HeadED->Type == OHCI_STATIC_ED_TYPE_INTERRUPT)
+        {
+            ED->HwED.NextED = *HeadED->pNextED;
+            *HeadED->pNextED = ED->PhysicalAddress;
+        }
+        else
+        {
+            DPRINT1("OHCI_InsertEndpointInSchedule: Unknown HeadED->Type - %x\n",
+                    HeadED->Type);
+            DbgBreakPoint();
+        }
+    }
+    else
+    {
+        PrevED = CONTAINING_RECORD(HeadLink->Blink,
+                                   OHCI_HCD_ED,
+                                   HcdEDLink);
+
+        InsertTailList(HeadLink, &ED->HcdEDLink);
+
+        ED->HwED.NextED = 0;
+        PrevED->HwED.NextED = ED->PhysicalAddress;
+    }
+}
+
+POHCI_HCD_ED
+NTAPI
+OHCI_InitializeED(IN POHCI_ENDPOINT OhciEndpoint,
+                  IN POHCI_HCD_ED ED,
+                  IN POHCI_HCD_TD FirstTD,
+                  IN ULONG_PTR EdPA)
+{
+    OHCI_ENDPOINT_CONTROL EndpointControl;
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+
+    DPRINT_OHCI("OHCI_InitializeED: OhciEndpoint - %p, ED - %p, FirstTD - %p, EdPA - %p\n",
+                OhciEndpoint,
+                ED,
+                FirstTD,
+                EdPA);
+
+    RtlZeroMemory(ED, sizeof(OHCI_HCD_ED));
+
+    ED->PhysicalAddress = EdPA;
+
+    EndpointProperties = &OhciEndpoint->EndpointProperties;
+
+    EndpointControl = ED->HwED.EndpointControl;
+
+    EndpointControl.FunctionAddress = EndpointProperties->DeviceAddress;
+    EndpointControl.EndpointNumber = EndpointProperties->EndpointAddress;
+    EndpointControl.MaximumPacketSize = EndpointProperties->TotalMaxPacketSize;
+
+    if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+    {
+        EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD;
+    }
+    else if (EndpointProperties->Direction)
+    {
+        EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_OUT;
+    }
+    else
+    {
+        EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_IN;
+    }
+
+    if (EndpointProperties->DeviceSpeed == UsbLowSpeed)
+        EndpointControl.Speed = OHCI_ENDPOINT_LOW_SPEED;
+
+    if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        EndpointControl.Format = OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
+    else
+        EndpointControl.sKip = 1;
+
+    ED->HwED.EndpointControl = EndpointControl;
+
+    ED->HwED.TailPointer = FirstTD->PhysicalAddress;
+    ED->HwED.HeadPointer = FirstTD->PhysicalAddress;
+
+    FirstTD->Flags |= OHCI_HCD_TD_FLAG_ALLOCATED;
+
+    OhciEndpoint->HcdTailP = FirstTD;
+    OhciEndpoint->HcdHeadP = FirstTD;
+
+    return ED;
+}
+
+VOID
+NTAPI
+OHCI_InitializeTDs(IN POHCI_ENDPOINT OhciEndpoint,
+                   IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties)
+{
+    POHCI_HCD_TD TdVA;
+    ULONG TdPA;
+    ULONG TdCount;
+    ULONG ix;
+
+    ASSERT(EndpointProperties->BufferLength > sizeof(OHCI_HCD_ED));
+
+    TdCount = (EndpointProperties->BufferLength - sizeof(OHCI_HCD_ED)) / 
+              sizeof(OHCI_HCD_TD);
+
+    OhciEndpoint->MaxTransferDescriptors = TdCount;
+
+    DPRINT_OHCI("OHCI_InitializeTDs: TdCount - %x\n", TdCount);
+
+    ASSERT(TdCount > 0);
+
+    TdVA = OhciEndpoint->FirstTD;
+
+    TdPA = (ULONG)EndpointProperties->BufferPA + sizeof(OHCI_HCD_ED);
+
+    for (ix = 0; ix < TdCount; ix++)
+    {
+        DPRINT_OHCI("OHCI_InitializeTDs: TdVA - %p, TdPA - %08X\n", TdVA, TdPA);
+
+        RtlZeroMemory(TdVA, sizeof(OHCI_HCD_TD));
+
+        TdVA->PhysicalAddress = TdPA;
+        TdVA->Flags = 0;
+        TdVA->OhciTransfer = 0;
+
+        TdVA++;
+        TdPA += sizeof(OHCI_HCD_TD);
+    }
+}
+
+MPSTATUS
+NTAPI
+OHCI_OpenControlEndpoint(IN POHCI_EXTENSION OhciExtension,
+                         IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                         IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_OpenControlEndpoint: ... \n");
+
+    ED = (POHCI_HCD_ED)EndpointProperties->BufferVA;
+
+    OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED));
+    OhciEndpoint->HeadED = &OhciExtension->ControlStaticED;
+
+    OHCI_InitializeTDs(OhciEndpoint, EndpointProperties);
+
+    OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint,
+                                            ED,
+                                            OhciEndpoint->FirstTD,
+                                            EndpointProperties->BufferPA);
+
+    OhciEndpoint->HcdED->Flags = OHCI_HCD_ED_FLAG_CONTROL |
+                                 OHCI_HCD_ED_FLAG_RESET_ON_HALT;
+
+    OHCI_InsertEndpointInSchedule(OhciEndpoint);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_OpenBulkEndpoint(IN POHCI_EXTENSION OhciExtension,
+                      IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                      IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_OpenBulkEndpoint: ... \n");
+
+    ED = (POHCI_HCD_ED)EndpointProperties->BufferVA;
+
+    OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED));
+    OhciEndpoint->HeadED = &OhciExtension->BulkStaticED;
+
+    OHCI_InitializeTDs(OhciEndpoint, EndpointProperties);
+
+    OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint,
+                                            ED,
+                                            OhciEndpoint->FirstTD,
+                                            EndpointProperties->BufferPA);
+
+    OHCI_InsertEndpointInSchedule(OhciEndpoint);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_OpenInterruptEndpoint(IN POHCI_EXTENSION OhciExtension,
+                           IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                           IN POHCI_ENDPOINT OhciEndpoint)
+{
+    UCHAR Period;
+    ULONG PeriodIdx = 0;
+    POHCI_HCD_ED ED;
+    ULONG ScheduleOffset;
+
+    DPRINT_OHCI("OHCI_OpenInterruptEndpoint: ... \n");
+
+    ED = (POHCI_HCD_ED)EndpointProperties->BufferVA;
+
+    OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED));
+
+    Period = EndpointProperties->Period;
+
+    ASSERT(Period != 0);
+
+    while (!(Period & 1))
+    {
+        PeriodIdx++;
+        Period >>= 1;
+    }
+
+    ASSERT(PeriodIdx < ARRAYSIZE(Index));
+
+    ScheduleOffset = EndpointProperties->ScheduleOffset;
+    DPRINT_OHCI("OHCI_OpenInterruptEndpoint: InitTD. Index[PeriodIdx] - %x, ScheduleOffset - %x\n",
+                Index[PeriodIdx],
+                ScheduleOffset);
+
+    OhciEndpoint->HeadED = &OhciExtension->IntStaticED[Index[PeriodIdx] +
+                                                       ScheduleOffset];
+
+    //OhciEndpoint->HeadED->UsbBandwidth += EndpointProperties->UsbBandwidth;
+
+    OHCI_InitializeTDs(OhciEndpoint, EndpointProperties);
+
+    OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint,
+                                            ED,
+                                            OhciEndpoint->FirstTD,
+                                            EndpointProperties->BufferPA);
+
+    OHCI_InsertEndpointInSchedule(OhciEndpoint);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_OpenIsoEndpoint(IN POHCI_EXTENSION OhciExtension,
+                     IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                     IN POHCI_ENDPOINT OhciEndpoint)
+{
+    DPRINT1("OHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n");
+    return MP_STATUS_NOT_SUPPORTED;
+}
+
+MPSTATUS
+NTAPI
+OHCI_OpenEndpoint(IN PVOID ohciExtension,
+                  IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                  IN PVOID ohciEndpoint)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    ULONG TransferType;
+    MPSTATUS MPStatus;
+
+    DPRINT_OHCI("OHCI_OpenEndpoint: ... \n");
+
+    RtlCopyMemory(&OhciEndpoint->EndpointProperties,
+                  EndpointProperties,
+                  sizeof(OhciEndpoint->EndpointProperties));
+
+    InitializeListHead(&OhciEndpoint->TDList);
+
+    TransferType = EndpointProperties->TransferType;
+
+    switch (TransferType)
+    {
+        case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
+            MPStatus = OHCI_OpenIsoEndpoint(OhciExtension,
+                                            EndpointProperties,
+                                            OhciEndpoint);
+            break;
+
+        case USBPORT_TRANSFER_TYPE_CONTROL:
+            MPStatus = OHCI_OpenControlEndpoint(OhciExtension,
+                                                EndpointProperties,
+                                                OhciEndpoint);
+            break;
+
+        case USBPORT_TRANSFER_TYPE_BULK:
+            MPStatus = OHCI_OpenBulkEndpoint(OhciExtension,
+                                             EndpointProperties,
+                                             OhciEndpoint);
+            break;
+
+        case USBPORT_TRANSFER_TYPE_INTERRUPT:
+            MPStatus = OHCI_OpenInterruptEndpoint(OhciExtension,
+                                                  EndpointProperties,
+                                                  OhciEndpoint);
+            break;
+
+        default:
+            MPStatus = MP_STATUS_NOT_SUPPORTED;
+            break;
+    }
+
+    return MPStatus;
+}
+
+MPSTATUS
+NTAPI
+OHCI_ReopenEndpoint(IN PVOID ohciExtension,
+                    IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                    IN PVOID ohciEndpoint)
+{
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_ReopenEndpoint: ... \n");
+
+    ED = OhciEndpoint->HcdED;
+
+    RtlCopyMemory(&OhciEndpoint->EndpointProperties,
+                  EndpointProperties,
+                  sizeof(OhciEndpoint->EndpointProperties));
+
+    ED->HwED.EndpointControl.FunctionAddress =
+        OhciEndpoint->EndpointProperties.DeviceAddress;
+
+    ED->HwED.EndpointControl.MaximumPacketSize =
+        OhciEndpoint->EndpointProperties.TotalMaxPacketSize;
+
+    return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+OHCI_QueryEndpointRequirements(IN PVOID ohciExtension,
+                               IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,
+                               IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements)
+{
+    ULONG TransferType;
+
+    DPRINT_OHCI("OHCI_QueryEndpointRequirements: ... \n");
+
+    TransferType = EndpointProperties->TransferType;
+
+    switch (TransferType)
+    {
+        case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
+            DPRINT_OHCI("OHCI_QueryEndpointRequirements: IsoTransfer\n");
+            EndpointRequirements->MaxTransferSize = OHCI_MAX_ISO_TRANSFER_SIZE;
+            EndpointRequirements->HeaderBufferSize =
+            sizeof(OHCI_HCD_ED) + OHCI_MAX_ISO_TD_COUNT * sizeof(OHCI_HCD_TD);
+            break;
+
+        case USBPORT_TRANSFER_TYPE_CONTROL:
+            DPRINT_OHCI("OHCI_QueryEndpointRequirements: ControlTransfer\n");
+            EndpointRequirements->MaxTransferSize = OHCI_MAX_CONTROL_TRANSFER_SIZE;
+            EndpointRequirements->HeaderBufferSize =
+            sizeof(OHCI_HCD_ED) + OHCI_MAX_CONTROL_TD_COUNT * sizeof(OHCI_HCD_TD);
+            break;
+
+        case USBPORT_TRANSFER_TYPE_BULK:
+            DPRINT_OHCI("OHCI_QueryEndpointRequirements: BulkTransfer\n");
+            EndpointRequirements->MaxTransferSize = OHCI_MAX_BULK_TRANSFER_SIZE;
+            EndpointRequirements->HeaderBufferSize =
+            sizeof(OHCI_HCD_ED) + OHCI_MAX_BULK_TD_COUNT * sizeof(OHCI_HCD_TD);
+            break;
+
+        case USBPORT_TRANSFER_TYPE_INTERRUPT:
+            DPRINT_OHCI("OHCI_QueryEndpointRequirements: InterruptTransfer\n");
+            EndpointRequirements->MaxTransferSize = OHCI_MAX_INTERRUPT_TRANSFER_SIZE;
+            EndpointRequirements->HeaderBufferSize =
+            sizeof(OHCI_HCD_ED) + OHCI_MAX_INTERRUPT_TD_COUNT * sizeof(OHCI_HCD_TD);
+            break;
+
+        default:
+            DPRINT1("OHCI_QueryEndpointRequirements: Unknown TransferType - %x\n",
+                    TransferType);
+            DbgBreakPoint();
+            break;
+    }
+}
+
+VOID
+NTAPI
+OHCI_CloseEndpoint(IN PVOID ohciExtension,
+                   IN PVOID ohciEndpoint,
+                   IN BOOLEAN IsDoDisablePeriodic)
+{
+#if DBG
+    DPRINT1("OHCI_CloseEndpoint: Not supported\n");
+#endif
+    return;
+}
+
+MPSTATUS
+NTAPI
+OHCI_TakeControlHC(IN POHCI_EXTENSION OhciExtension,
+                   IN PUSBPORT_RESOURCES Resources)
+{
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG ControlReg;
+    PULONG InterruptEnableReg;
+    PULONG InterruptDisableReg;
+    PULONG CommandStatusReg;
+    PULONG InterruptStatusReg;
+    OHCI_REG_CONTROL Control;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
+    OHCI_REG_COMMAND_STATUS CommandStatus;
+    OHCI_REG_INTERRUPT_STATUS IntStatus;
+    LARGE_INTEGER EndTime;
+    LARGE_INTEGER SystemTime;
+
+    DPRINT("OHCI_TakeControlHC: ...\n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    ControlReg = (PULONG)&OperationalRegs->HcControl;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+    InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
+    CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
+    InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus;
+
+    /* 5.1.1.3 Take Control of Host Controller */
+    Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+
+    if (Control.InterruptRouting == 0)
+        return MP_STATUS_SUCCESS;
+
+    DPRINT1("OHCI_TakeControlHC: detected Legacy BIOS\n");
+
+    IntEnable.AsULONG = READ_REGISTER_ULONG(InterruptEnableReg);
+
+    DPRINT("OHCI_TakeControlHC: Control - %lX, IntEnable - %lX\n",
+           Control.AsULONG,
+           IntEnable.AsULONG);
+
+    if (Control.HostControllerFunctionalState == OHCI_HC_STATE_RESET &&
+        IntEnable.AsULONG == 0)
+    {
+        Control.AsULONG = 0;
+        WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
+        return MP_STATUS_SUCCESS;
+    }
+
+    /* Enable interrupt generations */
+    IntEnable.AsULONG = 0;
+    IntEnable.MasterInterruptEnable = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
+
+    /* Request a change of control of the HC */
+    CommandStatus.AsULONG = 0;
+    CommandStatus.OwnershipChangeRequest = 1;
+
+    WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
+
+    /* Disable interrupt generation due to Root Hub Status Change */
+    IntDisable.AsULONG = 0;
+    IntDisable.RootHubStatusChange = 1;
+
+    WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
+
+    /* Monitoring the InterruptRouting bit
+       to determine when the ownership change has taken effect. */
+
+    KeQuerySystemTime(&EndTime);
+    EndTime.QuadPart += 500 * 10000; // 0.5 sec;
+
+    do
+    {
+        Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+
+        if (Control.InterruptRouting == 0)
+        {
+            /* Clear all bits in register */
+            IntStatus.AsULONG = 0xFFFFFFFF;
+            WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG);
+
+            /* Disable interrupt generations */
+            IntDisable.AsULONG = 0;
+            IntDisable.MasterInterruptEnable = 1;
+
+            WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
+
+            return MP_STATUS_SUCCESS;
+        }
+
+        KeQuerySystemTime(&SystemTime);
+    }
+    while (SystemTime.QuadPart < EndTime.QuadPart);
+
+    return MP_STATUS_HW_ERROR;
+}
+
+MPSTATUS
+NTAPI
+OHCI_StartController(IN PVOID ohciExtension,
+                     IN PUSBPORT_RESOURCES Resources)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG CommandStatusReg;
+    PULONG FmIntervalReg;
+    PULONG ControlReg;
+    PULONG InterruptEnableReg;
+    PULONG RhStatusReg;
+    OHCI_REG_COMMAND_STATUS CommandStatus;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE Interrupts;
+    OHCI_REG_RH_STATUS RhStatus;
+    OHCI_REG_FRAME_INTERVAL FrameInterval;
+    ULONG MaxFrameIntervalAdjusting;
+    OHCI_REG_CONTROL Control;
+    UCHAR HeadIndex;
+    POHCI_ENDPOINT_DESCRIPTOR IntED;
+    ULONG_PTR IntEdPA;
+    POHCI_HCCA OhciHCCA;
+    LARGE_INTEGER SystemTime;
+    LARGE_INTEGER EndTime;
+    ULONG ix;
+    ULONG jx;
+    MPSTATUS MPStatus = MP_STATUS_SUCCESS;
+
+    DPRINT_OHCI("OHCI_StartController: ohciExtension - %p, Resources - %p\n",
+                ohciExtension,
+                Resources);
+
+    /* HC on-chip operational registers */
+    OperationalRegs = (POHCI_OPERATIONAL_REGISTERS)Resources->ResourceBase;
+    OhciExtension->OperationalRegs = OperationalRegs;
+
+    CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
+    FmIntervalReg = (PULONG)&OperationalRegs->HcFmInterval;
+    ControlReg = (PULONG)&OperationalRegs->HcControl;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+    RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
+
+    /* 5.1.1 Initialization */
+
+    MPStatus = OHCI_TakeControlHC(OhciExtension, Resources);
+
+    if (MPStatus != MP_STATUS_SUCCESS)
+    {
+        DPRINT1("OHCI_StartController: OHCI_TakeControlHC return MPStatus - %x\n",
+                MPStatus);
+
+        return MPStatus;
+    }
+
+    OhciExtension->HcResourcesVA = Resources->StartVA;
+    OhciExtension->HcResourcesPA = Resources->StartPA;
+
+    DPRINT_OHCI("OHCI_StartController: HcResourcesVA - %p, HcResourcesPA - %p\n",
+                OhciExtension->HcResourcesVA,
+                OhciExtension->HcResourcesPA);
+
+    /* 5.2.7.2 Interrupt */
+
+    /* Build structure of interrupt static EDs */
+    for (ix = 0; ix < INTERRUPT_ENDPOINTs; ix++) 
+    {
+        IntED = &OhciExtension->HcResourcesVA->InterrruptHeadED[ix];
+        IntEdPA = (ULONG_PTR)&OhciExtension->HcResourcesPA->InterrruptHeadED[ix];
+
+        if (ix == (ENDPOINT_INTERRUPT_1ms - 1))
+        {
+            HeadIndex = ED_EOF;
+            IntED->NextED = 0;
+        }
+        else
+        {
+            HeadIndex = ((ix - 1) / 2);
+
+            ASSERT(HeadIndex >= (ENDPOINT_INTERRUPT_1ms - 1) &&
+                   HeadIndex < (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms));
+
+            IntED->NextED = OhciExtension->IntStaticED[HeadIndex].PhysicalAddress;
+        }
+
+        IntED->EndpointControl.sKip = 1;
+
+        IntED->TailPointer = 0;
+        IntED->HeadPointer = 0;
+
+        OhciExtension->IntStaticED[ix].HwED = IntED;
+        OhciExtension->IntStaticED[ix].PhysicalAddress = IntEdPA;
+        OhciExtension->IntStaticED[ix].HeadIndex = HeadIndex;
+        OhciExtension->IntStaticED[ix].pNextED = &IntED->NextED;
+        OhciExtension->IntStaticED[ix].Type = OHCI_STATIC_ED_TYPE_INTERRUPT;
+
+        InitializeListHead(&OhciExtension->IntStaticED[ix].Link);
+    }
+
+    OhciHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
+    DPRINT_OHCI("OHCI_InitializeSchedule: OhciHCCA - %p\n", OhciHCCA);
+
+    /* Set head pointers which start from HCCA */
+    for (ix = 0, jx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms);
+         ix < OHCI_NUMBER_OF_INTERRUPTS;
+         ix++, jx++)
+    {
+        OhciHCCA->InterrruptTable[Balance[ix]] =
+            OhciExtension->IntStaticED[jx].PhysicalAddress;
+
+        OhciExtension->IntStaticED[jx].pNextED =
+            (PULONG)&OhciHCCA->InterrruptTable[Balance[ix]];
+
+        OhciExtension->IntStaticED[jx].HccaIndex = Balance[ix];
+    }
+
+    DPRINT_OHCI("OHCI_InitializeSchedule: ix - %x\n", ix);
+
+    /* Init static Control and Bulk EDs head pointers which start from HCCA */
+    InitializeListHead(&OhciExtension->ControlStaticED.Link);
+
+    OhciExtension->ControlStaticED.HeadIndex = ED_EOF;
+    OhciExtension->ControlStaticED.Type = OHCI_STATIC_ED_TYPE_CONTROL;
+    OhciExtension->ControlStaticED.pNextED = &OperationalRegs->HcControlHeadED;
+
+    InitializeListHead(&OhciExtension->BulkStaticED.Link);
+
+    OhciExtension->BulkStaticED.HeadIndex = ED_EOF;
+    OhciExtension->BulkStaticED.Type = OHCI_STATIC_ED_TYPE_BULK;
+    OhciExtension->BulkStaticED.pNextED = &OperationalRegs->HcBulkHeadED;
+
+    /* 6.3.1 Frame Timing */
+    FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg);
+
+    MaxFrameIntervalAdjusting = OHCI_DEFAULT_FRAME_INTERVAL / 10; // 10%
+
+    if ((FrameInterval.FrameInterval) < (OHCI_DEFAULT_FRAME_INTERVAL - MaxFrameIntervalAdjusting) ||
+        (FrameInterval.FrameInterval) > (OHCI_DEFAULT_FRAME_INTERVAL + MaxFrameIntervalAdjusting))
+    {
+        FrameInterval.FrameInterval = OHCI_DEFAULT_FRAME_INTERVAL;
+    }
+
+    /* 5.4 FrameInterval Counter */
+    FrameInterval.FrameIntervalToggle = 1;
+
+    /* OHCI_MAXIMUM_OVERHEAD is the maximum overhead per frame */
+    FrameInterval.FSLargestDataPacket = 
+        ((FrameInterval.FrameInterval - OHCI_MAXIMUM_OVERHEAD) * 6) / 7;
+
+    OhciExtension->FrameInterval = FrameInterval;
+
+    DPRINT_OHCI("OHCI_StartController: FrameInterval - %lX\n",
+                FrameInterval.AsULONG);
+
+    /* Reset HostController */
+    CommandStatus.AsULONG = 0;
+    CommandStatus.HostControllerReset = 1;
+
+    WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
+
+    KeStallExecutionProcessor(25);
+
+    Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+    Control.HostControllerFunctionalState = OHCI_HC_STATE_RESET;
+
+    WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
+
+    KeQuerySystemTime(&EndTime);
+    EndTime.QuadPart += 500 * 10000; // 0.5 sec
+
+    while (TRUE)
+    {
+        WRITE_REGISTER_ULONG(FmIntervalReg, OhciExtension->FrameInterval.AsULONG);
+        FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg);
+
+        KeQuerySystemTime(&SystemTime);
+
+        if (SystemTime.QuadPart >= EndTime.QuadPart)
+        {
+            MPStatus = MP_STATUS_HW_ERROR;
+            break;
+        }
+
+        if (FrameInterval.AsULONG == OhciExtension->FrameInterval.AsULONG)
+        {
+            MPStatus = MP_STATUS_SUCCESS;
+            break;
+        }
+    }
+
+    if (MPStatus != MP_STATUS_SUCCESS)
+    {
+        DPRINT_OHCI("OHCI_StartController: frame interval not set\n");
+        return MPStatus;
+    }
+
+    /* Setup HcPeriodicStart register */
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart,
+                        (OhciExtension->FrameInterval.FrameInterval * 9) / 10); //90%
+
+    /* Setup HcHCCA register */
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcHCCA,
+                         (ULONG)&OhciExtension->HcResourcesPA->HcHCCA);
+
+    /* Setup HcInterruptEnable register */
+    Interrupts.AsULONG = 0;
+
+    Interrupts.SchedulingOverrun = 1;
+    Interrupts.WritebackDoneHead = 1;
+    Interrupts.UnrecoverableError = 1;
+    Interrupts.FrameNumberOverflow = 1;
+    Interrupts.OwnershipChange = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, Interrupts.AsULONG);
+
+    /* Setup HcControl register */
+    Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+
+    Control.ControlBulkServiceRatio = 0; // FIXME (1 : 1)
+    Control.PeriodicListEnable = 1;
+    Control.IsochronousEnable = 1;
+    Control.ControlListEnable = 1;
+    Control.BulkListEnable = 1;
+    Control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
+
+    WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
+
+    /* Setup HcRhStatus register */
+    RhStatus.AsULONG = 0;
+    RhStatus.SetGlobalPower = 1;
+
+    WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+OHCI_StopController(IN PVOID ohciExtension,
+                    IN BOOLEAN IsDoDisableInterrupts)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG ControlReg;
+    PULONG InterruptDisableReg;
+    PULONG InterruptStatusReg;
+    OHCI_REG_CONTROL Control;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
+    OHCI_REG_INTERRUPT_STATUS IntStatus;
+
+    DPRINT("OHCI_StopController: ... \n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    ControlReg = (PULONG)&OperationalRegs->HcControl;
+    InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
+    InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus;
+
+    /* Setup HcControl register */
+    Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+
+    Control.PeriodicListEnable = 0;
+    Control.IsochronousEnable = 0;
+    Control.ControlListEnable = 0;
+    Control.BulkListEnable = 0;
+    Control.HostControllerFunctionalState = OHCI_HC_STATE_SUSPEND;
+    Control.RemoteWakeupEnable = 0;
+
+    WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
+
+    /* Disable interrupt generations */
+    IntDisable.AsULONG = 0xFFFFFFFF;
+    WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
+
+    /* Clear all bits in HcInterruptStatus register */
+    IntStatus.AsULONG = 0xFFFFFFFF;
+    WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_SuspendController(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG ControlReg;
+    PULONG InterruptEnableReg;
+    OHCI_REG_CONTROL Control;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg;
+
+    DPRINT("OHCI_SuspendController: ... \n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    ControlReg = (PULONG)&OperationalRegs->HcControl;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+
+    /* Disable all interrupt generations */
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptDisable.AsULONG,
+                         0xFFFFFFFF);
+
+    /* Clear all bits in HcInterruptStatus register */
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptStatus.AsULONG,
+                         0xFFFFFFFF);
+
+    /* Setup HcControl register */
+    Control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+    Control.HostControllerFunctionalState = OHCI_HC_STATE_SUSPEND;
+    Control.RemoteWakeupEnable =  1;
+
+    WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
+
+    /* Setup HcInterruptEnable register */
+    InterruptReg.AsULONG = 0;
+    InterruptReg.ResumeDetected = 1;
+    InterruptReg.UnrecoverableError = 1;
+    InterruptReg.RootHubStatusChange = 1;
+    InterruptReg.MasterInterruptEnable = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptReg.AsULONG);
+}
+
+MPSTATUS
+NTAPI
+OHCI_ResumeController(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG ControlReg;
+    PULONG InterruptEnableReg;
+    POHCI_HCCA HcHCCA;
+    OHCI_REG_CONTROL control;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg;
+
+    DPRINT("OHCI_ResumeController \n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    ControlReg = (PULONG)&OperationalRegs->HcControl;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+
+    control.AsULONG = READ_REGISTER_ULONG(ControlReg);
+
+    if (control.HostControllerFunctionalState != OHCI_HC_STATE_SUSPEND)
+        return MP_STATUS_HW_ERROR;
+
+    HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
+    HcHCCA->Pad1 = 0;
+
+    /* Setup HcControl register */
+    control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
+    WRITE_REGISTER_ULONG(ControlReg, control.AsULONG);
+
+    /* Setup HcInterruptEnable register */
+    InterruptReg.AsULONG = 0;
+    InterruptReg.SchedulingOverrun = 1;
+    InterruptReg.WritebackDoneHead = 1;
+    InterruptReg.UnrecoverableError = 1;
+    InterruptReg.FrameNumberOverflow = 1;
+    InterruptReg.OwnershipChange = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptReg.AsULONG);
+    WRITE_REGISTER_ULONG(ControlReg, control.AsULONG);
+
+    return MP_STATUS_SUCCESS;
+}
+
+BOOLEAN
+NTAPI
+OHCI_HardwarePresent(IN POHCI_EXTENSION OhciExtension,
+                     IN BOOLEAN IsInvalidateController)
+{
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG CommandStatusReg;
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
+
+    if (READ_REGISTER_ULONG(CommandStatusReg) != 0xFFFFFFFF)
+        return TRUE;
+
+    DPRINT1("OHCI_HardwarePresent: IsInvalidateController - %x\n",
+            IsInvalidateController);
+
+    if (IsInvalidateController)
+    {
+        RegPacket.UsbPortInvalidateController(OhciExtension,
+                                              USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
+    }
+
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+OHCI_InterruptService(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    OHCI_REG_INTERRUPT_STATUS IntStatus;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
+    BOOLEAN HardwarePresent = FALSE;
+
+    DPRINT_OHCI("OHCI_Interrupt: Ext %p\n", OhciExtension);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    HardwarePresent = OHCI_HardwarePresent(OhciExtension, FALSE);
+
+    if (!HardwarePresent)
+        return FALSE;
+
+    IntEnable.AsULONG = READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptEnable);
+    IntStatus.AsULONG = READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptStatus) & IntEnable.AsULONG;
+
+    if ((IntStatus.AsULONG == 0) || (IntEnable.MasterInterruptEnable == 0))
+        return FALSE;
+
+    if (IntStatus.UnrecoverableError)
+        DPRINT1("OHCI_InterruptService: IntStatus.UnrecoverableError\n");
+
+    if (IntStatus.FrameNumberOverflow)
+    {
+        POHCI_HCCA HcHCCA;
+        ULONG fm;
+        ULONG hp;
+
+        HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
+
+        DPRINT("FrameNumberOverflow %lX\n", HcHCCA->FrameNumber);
+
+        hp = OhciExtension->FrameHighPart;
+        fm = HcHCCA->FrameNumber;
+
+        /* Increment value of FrameHighPart */
+        OhciExtension->FrameHighPart += 1 * (1 << 16) - ((hp ^ fm) & 0x8000);
+    }
+
+    /* Disable interrupt generation */
+    IntDisable.AsULONG = 0;
+    IntDisable.MasterInterruptEnable = 1;
+    WRITE_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptDisable,
+                         IntDisable.AsULONG);
+
+    return TRUE;
+}
+
+VOID
+NTAPI
+OHCI_InterruptDpc(IN PVOID ohciExtension,
+                  IN BOOLEAN IsDoEnableInterrupts)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG InterruptDisableReg;
+    PULONG InterruptEnableReg;
+    PULONG InterruptStatusReg;
+    OHCI_REG_INTERRUPT_STATUS IntStatus;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptBits;
+    POHCI_HCCA HcHCCA;
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+    InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
+    InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus;
+
+    DPRINT_OHCI("OHCI_InterruptDpc: OhciExtension - %p, IsDoEnableInterrupts - %x\n",
+                OhciExtension,
+                IsDoEnableInterrupts);
+
+    IntStatus.AsULONG = READ_REGISTER_ULONG(InterruptStatusReg);
+
+    if (IntStatus.RootHubStatusChange)
+    {
+        DPRINT_OHCI("OHCI_InterruptDpc: RootHubStatusChange\n");
+        RegPacket.UsbPortInvalidateRootHub(OhciExtension);
+    }
+
+    if (IntStatus.WritebackDoneHead)
+    {
+        DPRINT_OHCI("OHCI_InterruptDpc: WritebackDoneHead\n");
+
+        HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
+        HcHCCA->DoneHead = 0;
+
+        RegPacket.UsbPortInvalidateEndpoint(OhciExtension, NULL);
+    }
+
+    if (IntStatus.StartofFrame)
+    {
+        /* Disable interrupt generation due to Start of Frame */
+        InterruptBits.AsULONG = 0;
+        InterruptBits.StartofFrame = 1;
+
+        WRITE_REGISTER_ULONG(InterruptDisableReg, InterruptBits.AsULONG);
+    }
+
+    if (IntStatus.ResumeDetected)
+        DPRINT1("OHCI_IntDpc: ResumeDetected\n");
+
+    if (IntStatus.UnrecoverableError)
+    {
+        DPRINT1("OHCI_IntDpc: UnrecoverableError\n");
+    }
+
+    WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG);
+
+    if (IsDoEnableInterrupts)
+    {
+        /*  Enable interrupt generation */
+        InterruptBits.AsULONG = 0;
+        InterruptBits.MasterInterruptEnable = 1;
+
+        WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptBits.AsULONG);
+    }
+}
+
+ULONG
+NTAPI 
+OHCI_MapTransferToTD(IN POHCI_EXTENSION OhciExtension,
+                     IN ULONG MaxPacketSize,
+                     IN OUT ULONG TransferedLen,
+                     IN POHCI_TRANSFER OhciTransfer,
+                     IN POHCI_HCD_TD TD,
+                     IN PUSBPORT_SCATTER_GATHER_LIST SGList)
+{
+    PUSBPORT_SCATTER_GATHER_ELEMENT SgElement;
+    ULONG SgIdx;
+    ULONG SgRemain;
+    ULONG LengthThisTd;
+    ULONG BufferEnd;
+    ULONG Offset;
+    ULONG TransferLength;
+    ULONG Buffer;
+
+    DPRINT_OHCI("OHCI_MapTransferToTD: TransferedLen - %x\n", TransferedLen);
+
+    for (SgIdx = 0; SgIdx < SGList->SgElementCount; SgIdx++)
+    {
+        SgElement = &SGList->SgElement[SgIdx];
+
+        if (TransferedLen >= SgElement->SgOffset &&
+            TransferedLen < SgElement->SgOffset + SgElement->SgTransferLength)
+        {
+            break;
+        }
+    }
+
+    DPRINT_OHCI("OHCI_MapTransferToTD: SgIdx - %x, SgCount - %x\n",
+                SgIdx,
+                SGList->SgElementCount);
+
+    ASSERT(SgIdx < SGList->SgElementCount);
+
+    Offset = TransferedLen - SGList->SgElement[SgIdx].SgOffset;
+    Buffer = SGList->SgElement[SgIdx].SgPhysicalAddress.LowPart + Offset;
+
+    SgRemain = SGList->SgElementCount - SgIdx;
+
+    if (SgRemain == 1)
+    {
+        LengthThisTd = OhciTransfer->TransferParameters->TransferBufferLength -
+                       TransferedLen -
+                       Offset;
+
+        BufferEnd = SGList->SgElement[SgIdx].SgPhysicalAddress.LowPart +
+                    LengthThisTd;
+    }
+    else if (SgRemain == 2)
+    {
+        LengthThisTd = OhciTransfer->TransferParameters->TransferBufferLength - 
+                       TransferedLen;
+
+        BufferEnd = SGList->SgElement[SgIdx + 1].SgPhysicalAddress.LowPart +
+                    SGList->SgElement[SgIdx + 1].SgTransferLength;
+    }
+    else
+    {
+        TransferLength = SGList->SgElement[SgIdx].SgTransferLength +
+                         SGList->SgElement[SgIdx+1].SgTransferLength -
+                         Offset;
+
+        BufferEnd = SGList->SgElement[SgIdx + 1].SgPhysicalAddress.LowPart +
+                    SGList->SgElement[SgIdx + 1].SgTransferLength;
+
+        LengthThisTd = MaxPacketSize * (TransferLength / MaxPacketSize);
+
+        if (TransferLength > LengthThisTd)
+            BufferEnd -= (TransferLength - LengthThisTd);
+    }
+
+    TD->HwTD.gTD.CurrentBuffer = Buffer;
+    TD->HwTD.gTD.BufferEnd = BufferEnd - 1;
+    TD->TransferLen = LengthThisTd;
+
+    return TransferedLen + LengthThisTd;
+}
+
+POHCI_HCD_TD
+NTAPI 
+OHCI_AllocateTD(IN POHCI_EXTENSION OhciExtension,
+                IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_HCD_TD TD;
+
+    DPRINT_OHCI("OHCI_AllocateTD: ... \n");
+
+    TD = OhciEndpoint->FirstTD;
+
+    while (TD->Flags & OHCI_HCD_TD_FLAG_ALLOCATED)
+    {
+        TD += 1;
+    }
+
+    TD->Flags |= OHCI_HCD_TD_FLAG_ALLOCATED;
+
+    return TD;
+}
+
+ULONG
+NTAPI 
+OHCI_RemainTDs(IN POHCI_EXTENSION OhciExtension,
+               IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_HCD_TD TD;
+    ULONG MaxTDs;
+    ULONG RemainTDs;
+    ULONG ix;
+
+    DPRINT_OHCI("OHCI_RemainTDs: ... \n");
+
+    MaxTDs = OhciEndpoint->MaxTransferDescriptors;
+    TD = (POHCI_HCD_TD)OhciEndpoint->FirstTD;
+
+    RemainTDs = 0;
+
+    for (ix = 0; ix < MaxTDs; ix++)
+    {
+        if (!(TD->Flags & OHCI_HCD_TD_FLAG_ALLOCATED))
+            RemainTDs++;
+
+        TD += 1;
+    }
+
+    return RemainTDs;
+}
+
+MPSTATUS
+NTAPI
+OHCI_ControlTransfer(IN POHCI_EXTENSION OhciExtension,
+                     IN POHCI_ENDPOINT OhciEndpoint,
+                     IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+                     IN POHCI_TRANSFER OhciTransfer,
+                     IN PUSBPORT_SCATTER_GATHER_LIST SGList)
+{
+    POHCI_HCD_TD FirstTD;
+    POHCI_HCD_TD FirstTdPA;
+    POHCI_HCD_TD TD;
+    POHCI_HCD_TD TD2;
+    POHCI_HCD_TD PrevTD;
+    POHCI_HCD_TD NextTD;
+    ULONG MaxTDs;
+    ULONG TransferedLen;
+    ULONG MaxPacketSize;
+    ULONG BufferEnd;
+    UCHAR DataToggle;
+
+    DPRINT_OHCI("OHCI_ControlTransfer: Ext %p, Endpoint %p\n",
+                OhciExtension,
+                OhciEndpoint);
+
+    MaxTDs = OHCI_RemainTDs(OhciExtension, OhciEndpoint);
+
+    if ((SGList->SgElementCount + OHCI_NON_DATA_CONTROL_TDS) > MaxTDs)
+        return MP_STATUS_FAILURE;
+
+    FirstTD = OhciEndpoint->HcdTailP;
+    FirstTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
+
+    FirstTD->HwTD.gTD.NextTD = 0;
+    FirstTD->HwTD.gTD.CurrentBuffer = 0;
+    FirstTD->HwTD.gTD.BufferEnd = 0;
+
+    FirstTD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
+    FirstTD->NextHcdTD = 0;
+    FirstTD->OhciTransfer = (ULONG)OhciTransfer;
+
+    FirstTD->HwTD.Padded[0] = 0;
+    FirstTD->HwTD.Padded[1] = 0;
+
+    OhciTransfer->PendingTDs++;
+
+    RtlCopyMemory(&FirstTD->HwTD.SetupPacket,
+                  &TransferParameters->SetupPacket,
+                  sizeof(FirstTD->HwTD.SetupPacket));
+
+    FirstTdPA = (POHCI_HCD_TD)FirstTD->PhysicalAddress;
+
+    FirstTD->HwTD.gTD.CurrentBuffer = (ULONG)&FirstTdPA->HwTD.SetupPacket;
+
+    BufferEnd = (ULONG_PTR)&FirstTdPA->HwTD.SetupPacket +
+                           sizeof(USB_DEFAULT_PIPE_SETUP_PACKET) - 1;
+
+    FirstTD->HwTD.gTD.BufferEnd = BufferEnd;
+
+    FirstTD->HwTD.gTD.Control.AsULONG = 0;
+    FirstTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
+    FirstTD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
+    FirstTD->HwTD.gTD.Control.DataToggle = OHCI_TD_DATA_TOGGLE_DATA0;
+
+    TD2 = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
+
+    TD2->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
+    TD2->HwTD.gTD.CurrentBuffer = 0;
+    TD2->HwTD.gTD.BufferEnd = 0;
+    TD2->HwTD.gTD.NextTD = 0;
+
+    TD2->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
+    TD2->NextHcdTD = 0;
+    TD2->OhciTransfer = (ULONG)OhciTransfer;
+
+    RtlZeroMemory(&TD2->HwTD.SetupPacket,
+                  sizeof(TD2->HwTD.SetupPacket));
+
+    TD2->HwTD.Padded[0] = 0;
+    TD2->HwTD.Padded[1] = 0;
+
+    PrevTD = FirstTD;
+    TD = TD2;
+
+    PrevTD->HwTD.gTD.NextTD = TD2->PhysicalAddress;
+    PrevTD->NextHcdTD = (ULONG)TD2;
+
+    MaxPacketSize = OhciEndpoint->EndpointProperties.TotalMaxPacketSize;
+
+    TransferedLen = 0;
+    DataToggle = OHCI_TD_DATA_TOGGLE_DATA1;
+
+    while (TransferedLen < TransferParameters->TransferBufferLength)
+    {
+        OhciTransfer->PendingTDs++;
+
+        if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+            TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN;
+        else
+            TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT;
+
+        TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
+        TD->HwTD.gTD.Control.DataToggle = DataToggle;
+        TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
+
+        DataToggle = OHCI_TD_DATA_TOGGLE_FROM_ED;
+
+        TransferedLen = OHCI_MapTransferToTD(OhciExtension,
+                                             MaxPacketSize,
+                                             TransferedLen,
+                                             OhciTransfer,
+                                             TD,
+                                             SGList);
+
+        PrevTD = TD;
+
+        TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
+
+        TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
+
+        TD->HwTD.gTD.NextTD = 0;
+        TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
+
+        TD->NextHcdTD = 0;
+        TD->OhciTransfer = (ULONG)OhciTransfer;
+
+        TD->HwTD.gTD.CurrentBuffer = 0;
+        TD->HwTD.gTD.BufferEnd = 0;
+
+        RtlZeroMemory(&TD->HwTD.SetupPacket,
+                      sizeof(TD->HwTD.SetupPacket));
+
+        TD->HwTD.Padded[0] = 0;
+        TD->HwTD.Padded[1] = 0;
+
+        PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
+        PrevTD->NextHcdTD = (ULONG)TD;
+    }
+
+    if (TransferParameters->TransferFlags & USBD_SHORT_TRANSFER_OK)
+    {
+        PrevTD->HwTD.gTD.Control.BufferRounding = TRUE;
+        OhciTransfer->Flags |= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK;
+    }
+
+    TD->HwTD.gTD.CurrentBuffer = 0;
+    TD->HwTD.gTD.BufferEnd = 0;
+
+    TD->Flags |= OHCI_HCD_TD_FLAG_CONTROL_STATUS;
+    TD->TransferLen = 0;
+
+    TD->HwTD.gTD.Control.AsULONG = 0;
+
+    if ((TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) != 0)
+    {
+        TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT;
+    }
+    else
+    {
+        TD->HwTD.gTD.Control.BufferRounding = TRUE;
+        TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN;
+    }
+
+    TD->HwTD.gTD.Control.DataToggle = OHCI_TD_DATA_TOGGLE_DATA1;
+    TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
+
+    OhciTransfer->PendingTDs++;
+    OhciTransfer->ControlStatusTD = TD;
+
+    NextTD = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
+
+    TD->HwTD.gTD.NextTD = NextTD->PhysicalAddress;
+    TD->NextHcdTD = (ULONG)NextTD;
+
+    NextTD->NextHcdTD = 0;
+    NextTD->HwTD.gTD.NextTD = 0;
+
+    OhciTransfer->NextTD = NextTD;
+    OhciEndpoint->HcdTailP = NextTD;
+
+    OhciEndpoint->HcdED->HwED.TailPointer = NextTD->PhysicalAddress;
+
+    OHCI_EnableList(OhciExtension, OhciEndpoint);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI 
+OHCI_BulkOrInterruptTransfer(IN POHCI_EXTENSION OhciExtension,
+                             IN POHCI_ENDPOINT OhciEndpoint,
+                             IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+                             IN POHCI_TRANSFER OhciTransfer,
+                             IN PUSBPORT_SCATTER_GATHER_LIST SGList)
+{
+    POHCI_HCD_TD TD;
+    POHCI_HCD_TD PrevTD;
+    ULONG TransferedLen;
+    ULONG MaxTDs;
+    ULONG MaxPacketSize;
+
+    DPRINT_OHCI("OHCI_BulkOrInterruptTransfer: ... \n");
+
+    MaxTDs = OHCI_RemainTDs(OhciExtension, OhciEndpoint);
+
+    if (SGList->SgElementCount > MaxTDs)
+        return MP_STATUS_FAILURE;
+
+    TD = OhciEndpoint->HcdTailP;
+
+    TransferedLen = 0;
+
+    do
+    {
+        TD->HwTD.gTD.Control.AsULONG = 0;
+        TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE;
+        TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED;
+
+        if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+        {
+            TD->HwTD.gTD.Control.BufferRounding = 0;
+            TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN;
+        }
+        else
+        {
+            TD->HwTD.gTD.Control.BufferRounding = TRUE;
+            TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT;
+        }
+
+        TD->HwTD.gTD.CurrentBuffer = 0;
+        TD->HwTD.gTD.NextTD = 0;
+        TD->HwTD.gTD.BufferEnd = 0;
+
+        RtlZeroMemory(&TD->HwTD.SetupPacket,
+                      sizeof(TD->HwTD.SetupPacket));
+
+        TD->HwTD.Padded[0] = 0;
+        TD->HwTD.Padded[1] = 0;
+
+        TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED;
+        TD->OhciTransfer = (ULONG)OhciTransfer;
+        TD->NextHcdTD = 0;
+
+        if (TransferParameters->TransferBufferLength)
+        {
+            MaxPacketSize = OhciEndpoint->EndpointProperties.TotalMaxPacketSize;
+
+            TransferedLen = OHCI_MapTransferToTD(OhciExtension,
+                                                 MaxPacketSize,
+                                                 TransferedLen,
+                                                 OhciTransfer,
+                                                 TD,
+                                                 SGList);
+        }
+        else
+        {
+            ASSERT(SGList->SgElementCount == 0);
+
+            TD->HwTD.gTD.CurrentBuffer = 0;
+            TD->HwTD.gTD.BufferEnd = 0;
+
+            TD->TransferLen = 0;
+        }
+
+        PrevTD = TD;
+
+        TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint);
+        OhciTransfer->PendingTDs++;
+
+        PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
+        PrevTD->NextHcdTD = (ULONG)TD;
+    }
+    while (TransferedLen < TransferParameters->TransferBufferLength);
+
+    if (TransferParameters->TransferFlags & USBD_SHORT_TRANSFER_OK)
+    {
+        PrevTD->HwTD.gTD.Control.BufferRounding = TRUE;
+        OhciTransfer->Flags |= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK;
+    }
+
+    PrevTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_IMMEDIATE;
+    PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
+    PrevTD->NextHcdTD = (ULONG)TD;
+
+    TD->HwTD.gTD.NextTD = 0;
+    TD->NextHcdTD = 0;
+
+    OhciTransfer->NextTD = TD;
+    OhciEndpoint->HcdTailP = TD;
+
+    OhciEndpoint->HcdED->HwED.TailPointer = TD->PhysicalAddress;
+
+    OHCI_EnableList(OhciExtension, OhciEndpoint);
+
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_SubmitTransfer(IN PVOID ohciExtension,
+                    IN PVOID ohciEndpoint,
+                    IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+                    IN PVOID ohciTransfer,
+                    IN PUSBPORT_SCATTER_GATHER_LIST SGList)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_TRANSFER OhciTransfer = ohciTransfer;
+    ULONG TransferType;
+
+    DPRINT_OHCI("OHCI_SubmitTransfer: ... \n");
+
+    RtlZeroMemory(OhciTransfer, sizeof(OHCI_TRANSFER));
+
+    OhciTransfer->TransferParameters = TransferParameters;
+    OhciTransfer->OhciEndpoint = OhciEndpoint;
+
+    TransferType = OhciEndpoint->EndpointProperties.TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+    {
+        return OHCI_ControlTransfer(OhciExtension,
+                                    OhciEndpoint,
+                                    TransferParameters,
+                                    OhciTransfer,
+                                    SGList);
+    }
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+        TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        return OHCI_BulkOrInterruptTransfer(OhciExtension,
+                                            OhciEndpoint,
+                                            TransferParameters,
+                                            OhciTransfer,
+                                            SGList);
+    }
+
+    return MP_STATUS_FAILURE;
+}
+
+MPSTATUS
+NTAPI
+OHCI_SubmitIsoTransfer(IN PVOID ohciExtension,
+                       IN PVOID ohciEndpoint,
+                       IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,
+                       IN PVOID ohciTransfer,
+                       IN PVOID isoParameters)
+{
+    DPRINT1("OHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n");
+    return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+OHCI_ProcessDoneTD(IN POHCI_EXTENSION OhciExtension,
+                   IN POHCI_HCD_TD TD,
+                   IN BOOLEAN IsPortComplete)
+{
+    POHCI_TRANSFER OhciTransfer;
+    POHCI_ENDPOINT OhciEndpoint;
+    ULONG Buffer;
+    ULONG BufferEnd;
+    ULONG Length;
+
+    DPRINT_OHCI("OHCI_ProcessDoneTD: ... \n");
+
+    OhciTransfer = (POHCI_TRANSFER)TD->OhciTransfer;
+    OhciEndpoint = OhciTransfer->OhciEndpoint;
+
+    OhciTransfer->PendingTDs--;
+
+    Buffer = TD->HwTD.gTD.CurrentBuffer;
+    BufferEnd = TD->HwTD.gTD.BufferEnd;
+
+    if (TD->Flags & OHCI_HCD_TD_FLAG_NOT_ACCESSED)
+    {
+        TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NO_ERROR;
+    }
+    else
+    {
+        if (TD->HwTD.gTD.CurrentBuffer)
+        {
+            if (TD->TransferLen)
+            {
+                Length = (BufferEnd & (PAGE_SIZE - 1)) -
+                         (Buffer & (PAGE_SIZE - 1));
+
+                Length++;
+
+                if (Buffer >> PAGE_SHIFT != BufferEnd >> PAGE_SHIFT)
+                    Length += PAGE_SIZE;
+
+                TD->TransferLen -= Length;
+            }
+        }
+
+        if (TD->HwTD.gTD.Control.DirectionPID != OHCI_TD_DIRECTION_PID_SETUP)
+            OhciTransfer->TransferLen += TD->TransferLen;
+
+        if (TD->HwTD.gTD.Control.ConditionCode)
+        {
+            OhciTransfer->USBDStatus = USBD_STATUS_HALTED |
+                                       TD->HwTD.gTD.Control.ConditionCode;
+        }
+    }
+
+    TD->Flags = 0;
+    TD->HwTD.gTD.NextTD = 0;
+    TD->OhciTransfer = 0;
+
+    TD->DoneLink.Flink = NULL;
+    TD->DoneLink.Blink = NULL;
+
+    if (IsPortComplete && (OhciTransfer->PendingTDs == 0))
+    {
+        RegPacket.UsbPortCompleteTransfer(OhciExtension,
+                                          OhciEndpoint,
+                                          OhciTransfer->TransferParameters,
+                                          OhciTransfer->USBDStatus,
+                                          OhciTransfer->TransferLen);
+    }
+}
+
+VOID
+NTAPI
+OHCI_ProcessDoneIsoTD(IN POHCI_EXTENSION OhciExtension,
+                      IN POHCI_HCD_TD TD,
+                      IN BOOLEAN IsPortComplete)
+{
+    DPRINT1("OHCI_ProcessDoneIsoTD: UNIMPLEMENTED. FIXME\n");
+}
+
+VOID
+NTAPI
+OHCI_AbortTransfer(IN PVOID ohciExtension,
+                   IN PVOID ohciEndpoint,
+                   IN PVOID ohciTransfer,
+                   IN OUT PULONG CompletedLength)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_TRANSFER OhciTransfer = ohciTransfer;
+    POHCI_TRANSFER TmpTransfer;
+    POHCI_HCD_ED ED;
+    ULONG_PTR NextTdPA;
+    POHCI_HCD_TD NextTD;
+    POHCI_HCD_TD TD;
+    POHCI_HCD_TD PrevTD;
+    POHCI_HCD_TD LastTD;
+    POHCI_HCD_TD td = NULL;
+    ULONG ix;
+    BOOLEAN IsIsoEndpoint = FALSE;
+    BOOLEAN IsProcessed = FALSE;
+
+    DPRINT("OHCI_AbortTransfer: ohciEndpoint - %p, ohciTransfer - %p\n",
+           OhciEndpoint,
+           OhciTransfer);
+
+    if (OhciEndpoint->EndpointProperties.TransferType ==
+        USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+    {
+        IsIsoEndpoint = TRUE;
+    }
+
+    ED = OhciEndpoint->HcdED;
+    NextTdPA = ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_MASK;
+
+    NextTD = RegPacket.UsbPortGetMappedVirtualAddress((PVOID)NextTdPA,
+                                                       OhciExtension,
+                                                       OhciEndpoint);
+
+    if (NextTD->OhciTransfer == (ULONG)OhciTransfer)
+    {
+        LastTD = OhciTransfer->NextTD;
+
+        ED->HwED.HeadPointer = LastTD->PhysicalAddress |
+                               (ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_CARRY);
+
+        OhciEndpoint->HcdHeadP = LastTD;
+
+        for (ix = 0; ix < OhciEndpoint->MaxTransferDescriptors; ix++)
+        {
+            TD = &OhciEndpoint->FirstTD[ix];
+
+            if (TD->OhciTransfer == (ULONG)OhciTransfer)
+            {
+                if (IsIsoEndpoint)
+                    OHCI_ProcessDoneIsoTD(OhciExtension, TD, FALSE);
+                else
+                    OHCI_ProcessDoneTD(OhciExtension, TD, FALSE);
+            }
+        }
+
+        *CompletedLength = OhciTransfer->TransferLen;
+        return;
+    }
+
+    TD = OhciEndpoint->HcdHeadP;
+
+    if (TD == NextTD)
+        goto Exit;
+
+    do
+    {
+        if (TD->OhciTransfer == (ULONG)ohciTransfer)
+        {
+            PrevTD = TD;
+            TD = (POHCI_HCD_TD)TD->NextHcdTD;
+
+            if (PrevTD == OhciEndpoint->HcdHeadP)
+                OhciEndpoint->HcdHeadP = TD;
+
+            if (IsIsoEndpoint)
+                OHCI_ProcessDoneIsoTD(OhciExtension, PrevTD, FALSE);
+            else
+                OHCI_ProcessDoneTD(OhciExtension, PrevTD, FALSE);
+
+            IsProcessed = TRUE;
+        }
+        else
+        {
+            TD = (POHCI_HCD_TD)TD->NextHcdTD;
+        }
+    }
+    while (TD != NextTD);
+
+    if (!IsProcessed)
+    {
+        TD = OhciEndpoint->HcdHeadP;
+
+        LastTD = TD;
+        td = NULL;
+
+        while (TD != OhciEndpoint->HcdTailP)
+        {
+            if (TD->OhciTransfer == (ULONG)OhciTransfer)
+            {
+                td = TD;
+                break;
+            }
+
+            LastTD = TD;
+
+            TD = (POHCI_HCD_TD)TD->NextHcdTD;
+        }
+
+        TD = td;
+
+        do
+        {
+            if (TD == OhciEndpoint->HcdTailP)
+                break;
+
+            PrevTD = TD;
+            TD = (POHCI_HCD_TD)TD->NextHcdTD;
+
+            if (IsIsoEndpoint)
+                OHCI_ProcessDoneIsoTD(OhciExtension, PrevTD, FALSE);
+            else
+                OHCI_ProcessDoneTD(OhciExtension, PrevTD, FALSE);
+        }
+        while (TD->OhciTransfer == (ULONG)OhciTransfer);
+
+        TmpTransfer = (POHCI_TRANSFER)LastTD->OhciTransfer;
+        TmpTransfer->NextTD = TD;
+
+        LastTD->NextHcdTD = (ULONG)TD;
+        LastTD->HwTD.gTD.NextTD = TD->PhysicalAddress;
+    }
+
+Exit:
+
+    *CompletedLength = OhciTransfer->TransferLen;
+
+    if (OhciTransfer->TransferLen)
+    {
+        DPRINT("OHCI_AbortTransfer: *CompletedLength - %x\n", *CompletedLength);
+    }
+}
+
+ULONG
+NTAPI
+OHCI_GetEndpointState(IN PVOID ohciExtension,
+                      IN PVOID ohciEndpoint)
+{
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_GetEndpointState: ... \n");
+
+    ED = OhciEndpoint->HcdED;
+
+    if (ED->Flags & OHCI_HCD_TD_FLAG_NOT_ACCESSED)
+        return USBPORT_ENDPOINT_REMOVE;
+
+    if (ED->HwED.EndpointControl.sKip)
+        return USBPORT_ENDPOINT_PAUSED;
+
+    return USBPORT_ENDPOINT_ACTIVE;
+}
+
+VOID
+NTAPI
+OHCI_RemoveEndpointFromSchedule(IN POHCI_ENDPOINT OhciEndpoint)
+{
+    POHCI_HCD_ED ED;
+    POHCI_HCD_ED PreviousED;
+    POHCI_STATIC_ED HeadED;
+
+    DPRINT_OHCI("OHCI_RemoveEndpointFromSchedule \n");
+
+    ED = OhciEndpoint->HcdED;
+    HeadED = OhciEndpoint->HeadED;
+
+    if (&HeadED->Link == ED->HcdEDLink.Blink)
+    {
+        if (HeadED->Type == OHCI_STATIC_ED_TYPE_CONTROL ||
+            HeadED->Type == OHCI_STATIC_ED_TYPE_BULK)
+        {
+            WRITE_REGISTER_ULONG(HeadED->pNextED, ED->HwED.NextED);
+        }
+        else if (HeadED->Type == OHCI_STATIC_ED_TYPE_INTERRUPT)
+        {
+            *HeadED->pNextED = ED->HwED.NextED;
+        }
+        else
+        {
+            DPRINT1("OHCI_RemoveEndpointFromSchedule: Unknown HeadED->Type - %x\n",
+                    HeadED->Type);
+            DbgBreakPoint();
+        }
+    }
+    else
+    {
+        PreviousED = CONTAINING_RECORD(ED->HcdEDLink.Blink,
+                                       OHCI_HCD_ED,
+                                       HcdEDLink);
+
+        PreviousED->HwED.NextED = ED->HwED.NextED;
+    }
+
+    RemoveEntryList(&ED->HcdEDLink);
+
+    OhciEndpoint->HeadED = NULL;
+}
+
+VOID
+NTAPI
+OHCI_SetEndpointState(IN PVOID ohciExtension,
+                      IN PVOID ohciEndpoint,
+                      IN ULONG EndpointState)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_SetEndpointState: EndpointState - %x\n",
+                EndpointState);
+
+    ED = OhciEndpoint->HcdED;
+
+    switch (EndpointState)
+    {
+        case USBPORT_ENDPOINT_PAUSED:
+            ED->HwED.EndpointControl.sKip = 1;
+            break;
+
+        case USBPORT_ENDPOINT_ACTIVE:
+            ED->HwED.EndpointControl.sKip = 0;
+            OHCI_EnableList(OhciExtension, OhciEndpoint);
+            break;
+
+        case USBPORT_ENDPOINT_REMOVE:
+            ED->HwED.EndpointControl.sKip = 1;
+            ED->Flags |= OHCI_HCD_ED_FLAG_NOT_ACCESSED;
+            OHCI_RemoveEndpointFromSchedule(OhciEndpoint);
+            break;
+
+        default:
+            ASSERT(FALSE);
+            break;
+    }
+}
+
+VOID
+NTAPI 
+OHCI_PollAsyncEndpoint(IN POHCI_EXTENSION OhciExtension,
+                       IN POHCI_ENDPOINT OhciEndpoint)
+{
+    PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
+    POHCI_HCD_ED ED;
+    ULONG_PTR NextTdPA;
+    POHCI_HCD_TD NextTD;
+    POHCI_HCD_TD TD;
+    PLIST_ENTRY DoneList;
+    POHCI_TRANSFER OhciTransfer;
+    POHCI_HCD_TD ControlStatusTD;
+    ULONG_PTR PhysicalAddress;
+    ULONG TransferNumber;
+    POHCI_TRANSFER transfer;
+    UCHAR ConditionCode;
+    BOOLEAN IsResetOnHalt = FALSE;
+
+    //DPRINT_OHCI("OHCI_PollAsyncEndpoint: Endpoint - %p\n", OhciEndpoint);
+
+    ED = OhciEndpoint->HcdED;
+    NextTdPA = ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_MASK;
+
+    if (!NextTdPA)
+    {
+        OHCI_DumpHcdED(ED);
+        DbgBreakPoint();
+    }
+
+    NextTD = RegPacket.UsbPortGetMappedVirtualAddress((PVOID)NextTdPA,
+                                                      OhciExtension,
+                                                      OhciEndpoint);
+    DPRINT_OHCI("NextTD - %p\n", NextTD);
+
+    if ((ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_HALT) == 0)
+        goto ProcessListTDs;
+
+    OHCI_DumpHcdED(ED);
+
+    IsResetOnHalt = (ED->Flags & OHCI_HCD_ED_FLAG_RESET_ON_HALT) != 0;
+    DPRINT1("PollAsyncEndpoint: IsResetOnHalt %x\n", IsResetOnHalt);
+
+    for (TD = OhciEndpoint->HcdHeadP; ; TD = (POHCI_HCD_TD)TD->NextHcdTD)
+    {
+        if (!TD)
+        {
+            OHCI_DumpHcdED(ED);
+            DbgBreakPoint();
+        }
+
+        if (TD == NextTD)
+        {
+            DPRINT("TD == NextTD - %p\n", TD);
+            goto HandleDoneList;
+        }
+
+        OhciTransfer = (POHCI_TRANSFER)TD->OhciTransfer;
+        ConditionCode = TD->HwTD.gTD.Control.ConditionCode;
+
+        DPRINT("TD - %p, ConditionCode - %X\n", TD, ConditionCode);
+        OHCI_DumpHcdTD(TD);
+
+        switch (ConditionCode)
+        {
+            case OHCI_TD_CONDITION_NO_ERROR:
+                TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
+                InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
+                continue;
+
+            case OHCI_TD_CONDITION_NOT_ACCESSED:
+                TD->Flags |= (OHCI_HCD_TD_FLAG_DONE | OHCI_HCD_TD_FLAG_NOT_ACCESSED);
+                InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
+                continue;
+
+            case OHCI_TD_CONDITION_DATA_UNDERRUN:
+                DPRINT1("DATA_UNDERRUN. Transfer->Flags - %X\n", OhciTransfer->Flags);
+
+                if (OhciTransfer->Flags & OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK)
+                {
+                    IsResetOnHalt = TRUE;
+                    TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NO_ERROR;
+
+                    ControlStatusTD = OhciTransfer->ControlStatusTD;
+
+                    if ((TD->Flags & OHCI_HCD_TD_FLAG_CONTROL_STATUS) == 0 &&
+                        ControlStatusTD)
+                    {
+                        PhysicalAddress = ControlStatusTD->PhysicalAddress;
+                        PhysicalAddress |= (ED->HwED.HeadPointer &
+                                            OHCI_ED_HEAD_POINTER_FLAGS_MASK);
+
+                        ED->HwED.HeadPointer = PhysicalAddress;
+
+                        NextTD = OhciTransfer->ControlStatusTD;
+                        DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD);
+                    }
+                    else
+                    {
+                        TransferParameters = OhciTransfer->TransferParameters;
+
+                        if (TransferParameters->IsTransferSplited)
+                        {
+                            TransferNumber = TransferParameters->TransferCounter;
+                            transfer = OhciTransfer;
+
+                            do
+                            {
+                                transfer = (POHCI_TRANSFER)transfer->NextTD->OhciTransfer;
+                                NextTD = transfer->NextTD;
+                            }
+                            while (transfer && TransferNumber ==
+                                   transfer->TransferParameters->TransferCounter);
+
+                            PhysicalAddress = NextTD->PhysicalAddress;
+                            PhysicalAddress |= (ED->HwED.HeadPointer &
+                                                OHCI_ED_HEAD_POINTER_FLAGS_MASK);
+
+                            ED->HwED.HeadPointer = PhysicalAddress;
+                            DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD);
+                        }
+                        else
+                        {
+                            PhysicalAddress = OhciTransfer->NextTD->PhysicalAddress;
+                            PhysicalAddress |= (ED->HwED.HeadPointer &
+                                                OHCI_ED_HEAD_POINTER_FLAGS_MASK);
+
+                            ED->HwED.HeadPointer = PhysicalAddress;
+
+                            NextTD = OhciTransfer->NextTD;
+                            DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD);
+                        }
+                    }
+
+                    TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
+                    InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
+                    continue;
+                }
+
+                /* fall through */
+
+            default:
+                TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
+                InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
+
+                ED->HwED.HeadPointer = OhciTransfer->NextTD->PhysicalAddress |
+                                       (ED->HwED.HeadPointer &
+                                        OHCI_ED_HEAD_POINTER_FLAGS_MASK);
+
+                NextTD = OhciTransfer->NextTD;
+                break;
+        }
+    }
+
+ProcessListTDs:
+
+    TD = OhciEndpoint->HcdHeadP;
+
+    while (TD != NextTD)
+    {
+        OHCI_DumpHcdTD(TD);
+        TD->Flags |= OHCI_HCD_TD_FLAG_DONE;
+        InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink);
+        TD = (POHCI_HCD_TD)TD->NextHcdTD;
+    }
+
+HandleDoneList:
+
+    TD = NextTD;
+    OhciEndpoint->HcdHeadP = NextTD;
+
+    DoneList = &OhciEndpoint->TDList;
+
+    while (!IsListEmpty(DoneList))
+    {
+        TD = CONTAINING_RECORD(DoneList->Flink,
+                               OHCI_HCD_TD,
+                               DoneLink);
+
+        RemoveHeadList(DoneList);
+
+        if (TD->Flags & OHCI_HCD_TD_FLAG_DONE &&
+            TD->Flags & OHCI_HCD_TD_FLAG_PROCESSED)
+        {
+            OHCI_ProcessDoneTD(OhciExtension, TD, TRUE);
+        }
+    }
+
+    if (IsResetOnHalt)
+    {
+        ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_HALT;
+        DPRINT("ED->HwED.HeadPointer - %p\n", ED->HwED.HeadPointer);
+    }
+}
+
+VOID
+NTAPI 
+OHCI_PollIsoEndpoint(IN POHCI_EXTENSION OhciExtension,
+                     IN POHCI_ENDPOINT OhciEndpoint)
+{
+    DPRINT1("OHCI_PollAsyncEndpoint: UNIMPLEMENTED. FIXME \n");
+    ASSERT(FALSE);
+}
+
+VOID
+NTAPI
+OHCI_PollEndpoint(IN PVOID ohciExtension,
+                  IN PVOID ohciEndpoint)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    ULONG TransferType;
+
+    DPRINT_OHCI("OHCI_PollEndpoint: OhciExtension - %p, Endpoint - %p\n",
+                OhciExtension,
+                OhciEndpoint);
+
+    TransferType = OhciEndpoint->EndpointProperties.TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+    {
+        OHCI_PollIsoEndpoint(OhciExtension, OhciEndpoint);
+        return;
+    }
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+        TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+        TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        OHCI_PollAsyncEndpoint(OhciExtension, OhciEndpoint);
+    }
+}
+
+VOID
+NTAPI
+OHCI_CheckController(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG HcControlReg;
+    OHCI_REG_CONTROL HcControl;
+    ULONG FmNumber;
+    USHORT FmDiff;
+    POHCI_HCCA HcHCCA;
+
+    //DPRINT_OHCI("OHCI_CheckController: ...\n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    if (!OHCI_HardwarePresent(OhciExtension, TRUE))
+        return;
+
+    HcControlReg = (PULONG)&OperationalRegs->HcControl;
+    HcControl.AsULONG = READ_REGISTER_ULONG(HcControlReg);
+
+    if (HcControl.HostControllerFunctionalState != OHCI_HC_STATE_OPERATIONAL)
+        return;
+
+    FmNumber = READ_REGISTER_ULONG(&OperationalRegs->HcFmNumber);
+    FmDiff = (USHORT)(FmNumber - OhciExtension->HcdFmNumber);
+
+    if (FmNumber == 0 || FmDiff < 5)
+        return;
+
+    HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
+    OhciExtension->HcdFmNumber = FmNumber;
+
+    if (HcHCCA->Pad1 == 0)
+    {
+        HcHCCA->Pad1 = 0xBAD1;
+        return;
+    }
+
+    DPRINT1("OHCI_CheckController: HcHCCA->Pad1 - %x\n", HcHCCA->Pad1);
+
+    if (HcHCCA->Pad1 == 0xBAD1)
+    {
+        HcHCCA->Pad1 = 0xBAD2;
+    }
+    else if (HcHCCA->Pad1 == 0xBAD2)
+    {
+        HcHCCA->Pad1 = 0xBAD3;
+
+        RegPacket.UsbPortInvalidateController(OhciExtension,
+                                              USBPORT_INVALIDATE_CONTROLLER_RESET);
+    }
+}
+
+ULONG
+NTAPI
+OHCI_Get32BitFrameNumber(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_HCCA HcHCCA;
+    ULONG fm;
+    ULONG hp;
+
+    HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA;
+
+    /* 5.4 FrameInterval Counter: Get32BitFrameNumber() */
+
+    hp = OhciExtension->FrameHighPart;
+    fm = HcHCCA->FrameNumber;
+
+    DPRINT_OHCI("OHCI_Get32BitFrameNumber: hp - %lX, fm - %lX\n", hp, fm);
+
+    return ((fm & 0x7FFF) | hp) + ((fm ^ hp) & 0x8000);
+}
+
+VOID
+NTAPI
+OHCI_InterruptNextSOF(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG InterruptEnableReg;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
+
+    DPRINT_OHCI("OHCI_InterruptNextSOF: OhciExtension - %p\n",
+                OhciExtension);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+
+    /* Enable interrupt generation due to Start of Frame */
+    IntEnable.AsULONG = 0;
+    IntEnable.StartofFrame = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_EnableInterrupts(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG InterruptEnableReg;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
+
+    DPRINT_OHCI("OHCI_EnableInterrupts: OhciExtension - %p\n",
+                OhciExtension);
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+
+    /*  Enable interrupt generation */
+    IntEnable.AsULONG = 0;
+    IntEnable.MasterInterruptEnable = 1;
+
+    WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_DisableInterrupts(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION  OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    PULONG InterruptDisableReg;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable;
+
+    DPRINT_OHCI("OHCI_DisableInterrupts\n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+    InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
+
+    /*  Disable interrupt generation */
+    IntDisable.AsULONG = 0;
+    IntDisable.MasterInterruptEnable = 1;
+
+    WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_PollController(IN PVOID ohciExtension)
+{
+    DPRINT1("OHCI_PollController: UNIMPLEMENTED. FIXME\n");
+}
+
+VOID
+NTAPI
+OHCI_SetEndpointDataToggle(IN PVOID ohciExtension,
+                           IN PVOID ohciEndpoint,
+                           IN ULONG DataToggle)
+{
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_SetEndpointDataToggle: Endpoint - %p, DataToggle - %x\n",
+                OhciEndpoint,
+                DataToggle);
+
+    ED = OhciEndpoint->HcdED;
+
+    if (DataToggle)
+        ED->HwED.HeadPointer |= OHCI_ED_HEAD_POINTER_CARRY;
+    else
+        ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_CARRY;
+}
+
+ULONG
+NTAPI
+OHCI_GetEndpointStatus(IN PVOID ohciExtension,
+                       IN PVOID ohciEndpoint)
+{
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_HCD_ED ED;
+    ULONG EndpointStatus = USBPORT_ENDPOINT_RUN;
+
+    DPRINT_OHCI("OHCI_GetEndpointStatus: ... \n");
+
+    ED = OhciEndpoint->HcdED;
+
+    if ((ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_HALT) &&
+        !(ED->Flags & OHCI_HCD_ED_FLAG_RESET_ON_HALT)) 
+    {
+        EndpointStatus = USBPORT_ENDPOINT_HALT;
+    }
+
+    return EndpointStatus;
+}
+
+VOID
+NTAPI
+OHCI_SetEndpointStatus(IN PVOID ohciExtension,
+                       IN PVOID ohciEndpoint,
+                       IN ULONG EndpointStatus)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_ENDPOINT OhciEndpoint = ohciEndpoint;
+    POHCI_HCD_ED ED;
+
+    DPRINT_OHCI("OHCI_SetEndpointStatus: Endpoint - %p, EndpointStatus - %lX\n",
+                OhciEndpoint,
+                EndpointStatus);
+
+    if (EndpointStatus == USBPORT_ENDPOINT_RUN)
+    {
+        ED = OhciEndpoint->HcdED;
+        ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_HALT;
+
+        OHCI_EnableList(OhciExtension, OhciEndpoint);
+    }
+    else if (EndpointStatus == USBPORT_ENDPOINT_HALT)
+    {
+        ASSERT(FALSE);
+    }
+}
+
+VOID
+NTAPI
+OHCI_ResetController(IN PVOID ohciExtension)
+{
+    POHCI_EXTENSION OhciExtension = ohciExtension;
+    POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+    ULONG FrameNumber;
+    PULONG ControlReg;
+    PULONG CommandStatusReg;
+    PULONG InterruptEnableReg;
+    PULONG FmIntervalReg;
+    PULONG RhStatusReg;
+    PULONG PortStatusReg;
+    OHCI_REG_CONTROL ControlBak;
+    OHCI_REG_CONTROL Control;
+    OHCI_REG_COMMAND_STATUS CommandStatus;
+    OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable;
+    ULONG_PTR HCCA;
+    ULONG_PTR ControlHeadED;
+    ULONG_PTR BulkHeadED;
+    OHCI_REG_FRAME_INTERVAL FrameInterval;
+    ULONG_PTR PeriodicStart;
+    ULONG_PTR LSThreshold;
+    OHCI_REG_RH_STATUS RhStatus;
+    OHCI_REG_RH_DESCRIPTORA RhDescriptorA;
+    OHCI_REG_RH_PORT_STATUS PortStatus;
+    ULONG NumPorts;
+    ULONG ix;
+
+    DPRINT("OHCI_ResetController: ... \n");
+
+    OperationalRegs = OhciExtension->OperationalRegs;
+
+    ControlReg = (PULONG)&OperationalRegs->HcControl;
+    CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus;
+    InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+    FmIntervalReg = (PULONG)&OperationalRegs->HcFmInterval;
+    RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
+
+    /* Backup FrameNumber from HcHCCA */
+    FrameNumber = OhciExtension->HcResourcesVA->HcHCCA.FrameNumber;
+
+    /* Backup registers */
+    ControlBak.AsULONG = READ_REGISTER_ULONG(ControlReg);
+    HCCA = READ_REGISTER_ULONG(&OperationalRegs->HcHCCA);
+    ControlHeadED = READ_REGISTER_ULONG(&OperationalRegs->HcControlHeadED);
+    BulkHeadED = READ_REGISTER_ULONG(&OperationalRegs->HcBulkHeadED);
+    FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg);
+    PeriodicStart = READ_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart);
+    LSThreshold = READ_REGISTER_ULONG(&OperationalRegs->HcLSThreshold);
+
+    /* Reset HostController */
+    CommandStatus.AsULONG = 0;
+    CommandStatus.HostControllerReset = 1;
+    WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG);
+
+    KeStallExecutionProcessor(10);
+
+    /* Restore registers */
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcHCCA, HCCA);
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcControlHeadED, ControlHeadED);
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcBulkHeadED, BulkHeadED);
+
+    /* Set OPERATIONAL state for HC */
+    Control.AsULONG = 0;
+    Control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
+    WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG);
+
+    /* Set Toggle bit for FmInterval register */
+    FrameInterval.FrameIntervalToggle = 1;
+    WRITE_REGISTER_ULONG(FmIntervalReg, FrameInterval.AsULONG);
+
+    /* Restore registers */
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcFmNumber, FrameNumber);
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart, PeriodicStart);
+    WRITE_REGISTER_ULONG(&OperationalRegs->HcLSThreshold, LSThreshold);
+
+    /* Setup RhStatus register */
+    RhStatus.AsULONG = 0;
+    RhStatus.SetRemoteWakeupEnable = 1;
+    RhStatus.SetGlobalPower = 1;
+    WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
+
+    /* Setup RH PortStatus registers */
+    RhDescriptorA = OHCI_ReadRhDescriptorA(OhciExtension);
+    NumPorts = RhDescriptorA.NumberDownstreamPorts;
+
+    PortStatus.AsULONG = 0;
+    PortStatus.SetPortPower = 1;
+
+    for (ix = 0; ix < NumPorts; ix++)
+    {
+        PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[ix];
+        WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+    }
+
+    /* Restore HcControl register */
+    ControlBak.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL;
+    WRITE_REGISTER_ULONG(ControlReg, ControlBak.AsULONG);
+
+    /* Setup HcInterruptEnable register */
+    IntEnable.AsULONG = 0xFFFFFFFF;
+    IntEnable.Reserved1 = 0;
+    WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG);
+}
+
+MPSTATUS
+NTAPI
+OHCI_StartSendOnePacket(IN PVOID ohciExtension,
+                        IN PVOID PacketParameters,
+                        IN PVOID Data,
+                        IN PULONG pDataLength,
+                        IN PVOID BufferVA,
+                        IN PVOID BufferPA,
+                        IN ULONG BufferLength,
+                        IN USBD_STATUS * pUSBDStatus)
+{
+    DPRINT1("OHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n");
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_EndSendOnePacket(IN PVOID ohciExtension,
+                      IN PVOID PacketParameters,
+                      IN PVOID Data,
+                      IN PULONG pDataLength,
+                      IN PVOID BufferVA,
+                      IN PVOID BufferPA,
+                      IN ULONG BufferLength,
+                      IN USBD_STATUS * pUSBDStatus)
+{
+    DPRINT1("OHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n");
+    return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_PassThru(IN PVOID ohciExtension,
+              IN PVOID passThruParameters,
+              IN ULONG ParameterLength,
+              IN PVOID pParameters)
+{
+    DPRINT1("OHCI_PassThru: UNIMPLEMENTED. FIXME\n");
+    return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+OHCI_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+#if DBG
+    DPRINT1("OHCI_Unload: Not supported\n");
+#endif
+    return;
+}
+
+VOID
+NTAPI
+OHCI_FlushInterrupts(IN PVOID uhciExtension)
+{
+#if DBG
+    DPRINT1("OHCI_FlushInterrupts: Not supported\n");
+#endif
+    return;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(IN PDRIVER_OBJECT DriverObject,
+            IN PUNICODE_STRING RegistryPath)
+{
+    NTSTATUS Status;
+
+    DPRINT_OHCI("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n",
+                DriverObject,
+                RegistryPath);
+
+    RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET));
+
+    RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_OHCI;
+
+    RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT |
+                              USB_MINIPORT_FLAGS_MEMORY_IO;
+
+    RegPacket.MiniPortBusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
+
+    RegPacket.MiniPortExtensionSize = sizeof(OHCI_EXTENSION);
+    RegPacket.MiniPortEndpointSize = sizeof(OHCI_ENDPOINT);
+    RegPacket.MiniPortTransferSize = sizeof(OHCI_TRANSFER);
+    RegPacket.MiniPortResourcesSize = sizeof(OHCI_HC_RESOURCES);
+
+    RegPacket.OpenEndpoint = OHCI_OpenEndpoint;
+    RegPacket.ReopenEndpoint = OHCI_ReopenEndpoint;
+    RegPacket.QueryEndpointRequirements = OHCI_QueryEndpointRequirements;
+    RegPacket.CloseEndpoint = OHCI_CloseEndpoint;
+    RegPacket.StartController = OHCI_StartController;
+    RegPacket.StopController = OHCI_StopController;
+    RegPacket.SuspendController = OHCI_SuspendController;
+    RegPacket.ResumeController = OHCI_ResumeController;
+    RegPacket.InterruptService = OHCI_InterruptService;
+    RegPacket.InterruptDpc = OHCI_InterruptDpc;
+    RegPacket.SubmitTransfer = OHCI_SubmitTransfer;
+    RegPacket.SubmitIsoTransfer = OHCI_SubmitIsoTransfer;
+    RegPacket.AbortTransfer = OHCI_AbortTransfer;
+    RegPacket.GetEndpointState = OHCI_GetEndpointState;
+    RegPacket.SetEndpointState = OHCI_SetEndpointState;
+    RegPacket.PollEndpoint = OHCI_PollEndpoint;
+    RegPacket.CheckController = OHCI_CheckController;
+    RegPacket.Get32BitFrameNumber = OHCI_Get32BitFrameNumber;
+    RegPacket.InterruptNextSOF = OHCI_InterruptNextSOF;
+    RegPacket.EnableInterrupts = OHCI_EnableInterrupts;
+    RegPacket.DisableInterrupts = OHCI_DisableInterrupts;
+    RegPacket.PollController = OHCI_PollController;
+    RegPacket.SetEndpointDataToggle = OHCI_SetEndpointDataToggle;
+    RegPacket.GetEndpointStatus = OHCI_GetEndpointStatus;
+    RegPacket.SetEndpointStatus = OHCI_SetEndpointStatus;
+    RegPacket.ResetController = OHCI_ResetController;
+    RegPacket.RH_GetRootHubData = OHCI_RH_GetRootHubData;
+    RegPacket.RH_GetStatus = OHCI_RH_GetStatus;
+    RegPacket.RH_GetPortStatus = OHCI_RH_GetPortStatus;
+    RegPacket.RH_GetHubStatus = OHCI_RH_GetHubStatus;
+    RegPacket.RH_SetFeaturePortReset = OHCI_RH_SetFeaturePortReset;
+    RegPacket.RH_SetFeaturePortPower = OHCI_RH_SetFeaturePortPower;
+    RegPacket.RH_SetFeaturePortEnable = OHCI_RH_SetFeaturePortEnable;
+    RegPacket.RH_SetFeaturePortSuspend = OHCI_RH_SetFeaturePortSuspend;
+    RegPacket.RH_ClearFeaturePortEnable = OHCI_RH_ClearFeaturePortEnable;
+    RegPacket.RH_ClearFeaturePortPower = OHCI_RH_ClearFeaturePortPower;
+    RegPacket.RH_ClearFeaturePortSuspend = OHCI_RH_ClearFeaturePortSuspend;
+    RegPacket.RH_ClearFeaturePortEnableChange = OHCI_RH_ClearFeaturePortEnableChange;
+    RegPacket.RH_ClearFeaturePortConnectChange = OHCI_RH_ClearFeaturePortConnectChange;
+    RegPacket.RH_ClearFeaturePortResetChange = OHCI_RH_ClearFeaturePortResetChange;
+    RegPacket.RH_ClearFeaturePortSuspendChange = OHCI_RH_ClearFeaturePortSuspendChange;
+    RegPacket.RH_ClearFeaturePortOvercurrentChange = OHCI_RH_ClearFeaturePortOvercurrentChange;
+    RegPacket.RH_DisableIrq = OHCI_RH_DisableIrq;
+    RegPacket.RH_EnableIrq = OHCI_RH_EnableIrq;
+    RegPacket.StartSendOnePacket = OHCI_StartSendOnePacket;
+    RegPacket.EndSendOnePacket = OHCI_EndSendOnePacket;
+    RegPacket.PassThru = OHCI_PassThru;
+    RegPacket.FlushInterrupts = OHCI_FlushInterrupts;
+
+    DriverObject->DriverUnload = OHCI_Unload;
+
+    Status = USBPORT_RegisterUSBPortDriver(DriverObject,
+                                           USB10_MINIPORT_INTERFACE_VERSION,
+                                           &RegPacket);
+
+    DPRINT_OHCI("DriverEntry: USBPORT_RegisterUSBPortDriver return Status - %x\n",
+                Status);
+
+    return Status;
+}
diff --git a/drivers/usb/usbohci_new/usbohci.h b/drivers/usb/usbohci_new/usbohci.h
new file mode 100644 (file)
index 0000000..281b6c8
--- /dev/null
@@ -0,0 +1,257 @@
+#ifndef USBOHCI_H__
+#define USBOHCI_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 OHCI_HCD_ED_FLAG_CONTROL       0x00000001
+#define OHCI_HCD_ED_FLAG_RESET_ON_HALT 0x00000008
+#define OHCI_HCD_ED_FLAG_NOT_ACCESSED  0x00000010
+
+#define OHCI_HCD_TD_FLAG_ALLOCATED       0x00000001
+#define OHCI_HCD_TD_FLAG_PROCESSED       0x00000002
+#define OHCI_HCD_TD_FLAG_CONTROL_STATUS  0x00000004
+#define OHCI_HCD_TD_FLAG_DONE            0x00000008
+#define OHCI_HCD_TD_FLAG_NOT_ACCESSED    0x00000010
+
+#define OHCI_MAX_ISO_TRANSFER_SIZE        0x10000
+#define OHCI_MAX_CONTROL_TRANSFER_SIZE    0x10000
+#define OHCI_MAX_BULK_TRANSFER_SIZE       0x40000
+#define OHCI_MAX_INTERRUPT_TRANSFER_SIZE  0x1000
+
+#define OHCI_MAX_ISO_TD_COUNT        64
+#define OHCI_MAX_CONTROL_TD_COUNT    38
+#define OHCI_MAX_BULK_TD_COUNT       68
+#define OHCI_MAX_INTERRUPT_TD_COUNT  4
+
+#define OHCI_NON_DATA_CONTROL_TDS  2
+
+#define OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK  1
+
+typedef struct _OHCI_TRANSFER *POHCI_TRANSFER;
+
+typedef union _OHCI_HW_TRANSFER_DESCRIPTOR {
+  struct {
+    OHCI_TRANSFER_DESCRIPTOR gTD; // must be aligned to a 16-byte boundary
+    USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+    ULONG Padded[2];
+  };
+  struct {
+    OHCI_ISO_TRANSFER_DESCRIPTOR iTD; // must be aligned to a 32-byte boundary
+  };
+} OHCI_HW_TRANSFER_DESCRIPTOR, *POHCI_HW_TRANSFER_DESCRIPTOR;
+
+C_ASSERT(sizeof(OHCI_HW_TRANSFER_DESCRIPTOR) == 32);
+
+typedef struct _OHCI_HCD_TD {
+  /* Hardware part */
+  OHCI_HW_TRANSFER_DESCRIPTOR HwTD; // must be aligned to a 32-byte boundary
+  /* Software part */
+  ULONG PhysicalAddress;
+  ULONG Flags;
+  ULONG OhciTransfer;
+  ULONG NextHcdTD;
+  ULONG TransferLen;
+  LIST_ENTRY DoneLink;
+  ULONG Pad[1];
+} OHCI_HCD_TD, *POHCI_HCD_TD;
+
+C_ASSERT(sizeof(OHCI_HCD_TD) == 64);
+
+typedef struct _OHCI_HCD_ED {
+  /* Hardware part */
+  OHCI_ENDPOINT_DESCRIPTOR HwED; // must be aligned to a 16-byte boundary
+  /* Software part */
+  ULONG PhysicalAddress;
+  ULONG Flags;
+  LIST_ENTRY HcdEDLink;
+  ULONG Pad[8];
+} OHCI_HCD_ED, *POHCI_HCD_ED;
+
+C_ASSERT(sizeof(OHCI_HCD_ED) == 64);
+
+#define OHCI_STATIC_ED_TYPE_INTERRUPT  0
+#define OHCI_STATIC_ED_TYPE_CONTROL    1
+#define OHCI_STATIC_ED_TYPE_BULK       2
+
+typedef struct _OHCI_STATIC_ED {
+  /* Software only */
+  POHCI_ENDPOINT_DESCRIPTOR HwED;
+  ULONG PhysicalAddress;
+  UCHAR HeadIndex;
+  UCHAR Reserved[3];
+  LIST_ENTRY Link;
+  ULONG Type;
+  PULONG pNextED;
+  ULONG HccaIndex;
+} OHCI_STATIC_ED, *POHCI_STATIC_ED;
+
+typedef struct _OHCI_HC_RESOURCES {
+  OHCI_HCCA HcHCCA; // (256 byte align)
+  OHCI_ENDPOINT_DESCRIPTOR InterrruptHeadED[63]; // (16 byte align)
+  OHCI_ENDPOINT_DESCRIPTOR ControlHeadED; // (16 byte align)
+  OHCI_ENDPOINT_DESCRIPTOR BulkHeadED; // (16 byte align)
+} OHCI_HC_RESOURCES, *POHCI_HC_RESOURCES;
+
+/* OHCI Endpoint follows USBPORT Endpoint */
+typedef struct _OHCI_ENDPOINT {
+  ULONG Reserved;
+  USBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+  POHCI_STATIC_ED HeadED;
+  POHCI_HCD_TD FirstTD;
+  POHCI_HCD_ED HcdED;
+  ULONG MaxTransferDescriptors;
+  POHCI_HCD_TD HcdHeadP;
+  POHCI_HCD_TD HcdTailP;
+  LIST_ENTRY TDList;
+} OHCI_ENDPOINT, *POHCI_ENDPOINT;
+
+/* OHCI Transfer follows USBPORT Transfer */
+typedef struct _OHCI_TRANSFER {
+  ULONG Reserved;
+  ULONG TransferLen;
+  PUSBPORT_TRANSFER_PARAMETERS TransferParameters;
+  ULONG PendingTDs;
+  ULONG Flags;
+  USBD_STATUS USBDStatus;
+  POHCI_ENDPOINT OhciEndpoint;
+  POHCI_HCD_TD NextTD;
+  POHCI_HCD_TD ControlStatusTD;
+} OHCI_TRANSFER, *POHCI_TRANSFER;
+
+/* OHCI Extension follows USBPORT Extension */
+typedef struct _OHCI_EXTENSION {
+  ULONG Reserved;
+  POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+  OHCI_REG_FRAME_INTERVAL FrameInterval;
+  ULONG FrameHighPart;
+  ULONG HcdFmNumber;
+  POHCI_HC_RESOURCES HcResourcesVA;
+  POHCI_HC_RESOURCES HcResourcesPA;
+  OHCI_STATIC_ED IntStaticED[63];
+  OHCI_STATIC_ED ControlStaticED;
+  OHCI_STATIC_ED BulkStaticED;
+} OHCI_EXTENSION, *POHCI_EXTENSION;
+
+/* roothub.c */
+VOID
+NTAPI
+OHCI_RH_GetRootHubData(
+  IN PVOID ohciExtension,
+  IN PVOID rootHubData);
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetStatus(
+  IN PVOID ohciExtension,
+  IN PUSHORT Status);
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetPortStatus(
+  IN PVOID ohciExtension,
+  IN USHORT Port,
+  IN PUSB_PORT_STATUS_AND_CHANGE PortStatus);
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetHubStatus(
+  IN PVOID ohciExtension,
+  IN PUSB_HUB_STATUS_AND_CHANGE HubStatus);
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortReset(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortPower(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortEnable(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortSuspend(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortEnable(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortPower(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortSuspend(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortEnableChange(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortConnectChange(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortResetChange(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortSuspendChange(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortOvercurrentChange(
+  IN PVOID ohciExtension,
+  IN USHORT Port);
+
+VOID
+NTAPI
+OHCI_RH_DisableIrq(
+  IN PVOID ohciExtension);
+
+VOID
+NTAPI
+OHCI_RH_EnableIrq(
+  IN PVOID ohciExtension);
+
+OHCI_REG_RH_DESCRIPTORA
+NTAPI 
+OHCI_ReadRhDescriptorA(
+  IN POHCI_EXTENSION OhciExtension);
+
+#endif /* USBOHCI_H__ */
diff --git a/drivers/usb/usbohci_new/usbohci.rc b/drivers/usb/usbohci_new/usbohci.rc
new file mode 100644 (file)
index 0000000..4179962
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION  "USB OHCI miniport driver"
+#define REACTOS_STR_INTERNAL_NAME     "usbohci"
+#define REACTOS_STR_ORIGINAL_FILENAME "usbohci.sys"
+#include <reactos/version.rc>