From f2f2dd055244bc6a641d00a8b5d79154c0dc445b Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Fri, 12 Jan 2018 21:09:58 +0100 Subject: [PATCH] [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(+) create mode 100644 drivers/usb/usbohci_new/CMakeLists.txt create mode 100644 drivers/usb/usbohci_new/dbg_ohci.h create mode 100644 drivers/usb/usbohci_new/guid.c create mode 100644 drivers/usb/usbohci_new/hardware.h create mode 100644 drivers/usb/usbohci_new/roothub.c create mode 100644 drivers/usb/usbohci_new/usbohci.c create mode 100644 drivers/usb/usbohci_new/usbohci.h create mode 100644 drivers/usb/usbohci_new/usbohci.rc diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt index d47a55cc821..05817b0f828 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 00000000000..ea7634b1486 --- /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 00000000000..273fe56e3f3 --- /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 00000000000..50a60369ff3 --- /dev/null +++ b/drivers/usb/usbohci_new/guid.c @@ -0,0 +1,9 @@ +/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ + +#include +#include +#include +#include +#include + +/* 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 00000000000..43fe27a199a --- /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 00000000000..bbd4e7e5f33 --- /dev/null +++ b/drivers/usb/usbohci_new/roothub.c @@ -0,0 +1,579 @@ +#include "usbohci.h" + +#define NDEBUG +#include + +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 00000000000..87c3c13838d --- /dev/null +++ b/drivers/usb/usbohci_new/usbohci.c @@ -0,0 +1,2653 @@ +#include "usbohci.h" + +#define NDEBUG +#include + +#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 00000000000..281b6c856d3 --- /dev/null +++ b/drivers/usb/usbohci_new/usbohci.h @@ -0,0 +1,257 @@ +#ifndef USBOHCI_H__ +#define USBOHCI_H__ + +#include +#include +#include +#include +#include +#include +#include +#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 00000000000..41799623bbd --- /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 -- 2.17.1