https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f2f2dd055244bc6a641d0…
commit f2f2dd055244bc6a641d00a8b5d79154c0dc445b
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Fri Jan 12 21:09:58 2018 +0100
Commit: Thomas Faber <github(a)tfaber.net>
CommitDate: Fri Jan 12 21:09:58 2018 +0100
[USBOHCI_NEW] Bring-in the USB OHCI miniport driver created by Vadim Galyant. (#244)
[USBOHCI_NEW] Add the new usbport-based OHCI driver.
---
drivers/usb/CMakeLists.txt | 1 +
drivers/usb/usbohci_new/CMakeLists.txt | 15 +
drivers/usb/usbohci_new/dbg_ohci.h | 29 +
drivers/usb/usbohci_new/guid.c | 9 +
drivers/usb/usbohci_new/hardware.h | 328 ++++
drivers/usb/usbohci_new/roothub.c | 579 +++++++
drivers/usb/usbohci_new/usbohci.c | 2653 ++++++++++++++++++++++++++++++++
drivers/usb/usbohci_new/usbohci.h | 257 ++++
drivers/usb/usbohci_new/usbohci.rc | 5 +
9 files changed, 3876 insertions(+)
diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt
index d47a55cc82..05817b0f82 100644
--- a/drivers/usb/CMakeLists.txt
+++ b/drivers/usb/CMakeLists.txt
@@ -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
index 0000000000..ea7634b148
--- /dev/null
+++ b/drivers/usb/usbohci_new/CMakeLists.txt
@@ -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
index 0000000000..273fe56e3f
--- /dev/null
+++ b/drivers/usb/usbohci_new/dbg_ohci.h
@@ -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
index 0000000000..50a60369ff
--- /dev/null
+++ b/drivers/usb/usbohci_new/guid.c
@@ -0,0 +1,9 @@
+/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
+
+#include <wdm.h>
+#include <initguid.h>
+#include <wdmguid.h>
+#include <hubbusif.h>
+#include <usbbusif.h>
+
+/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
diff --git a/drivers/usb/usbohci_new/hardware.h b/drivers/usb/usbohci_new/hardware.h
new file mode 100644
index 0000000000..43fe27a199
--- /dev/null
+++ b/drivers/usb/usbohci_new/hardware.h
@@ -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
index 0000000000..bbd4e7e5f3
--- /dev/null
+++ b/drivers/usb/usbohci_new/roothub.c
@@ -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
index 0000000000..87c3c13838
--- /dev/null
+++ b/drivers/usb/usbohci_new/usbohci.c
@@ -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
index 0000000000..281b6c856d
--- /dev/null
+++ b/drivers/usb/usbohci_new/usbohci.h
@@ -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
index 0000000000..41799623bb
--- /dev/null
+++ b/drivers/usb/usbohci_new/usbohci.rc
@@ -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>