--- /dev/null
+#include "usbohci.h"
+
+#define NDEBUG
+#include <debug.h>
+
+OHCI_REG_RH_DESCRIPTORA
+NTAPI
+OHCI_ReadRhDescriptorA(IN POHCI_EXTENSION OhciExtension)
+{
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ OHCI_REG_RH_DESCRIPTORA DescriptorA;
+ PULONG DescriptorAReg;
+ ULONG ix;
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ DescriptorAReg = (PULONG)&OperationalRegs->HcRhDescriptorA;
+
+ DPRINT("OHCI_ReadRhDescriptorA: OhciExtension - %p\n", OhciExtension);
+
+ for (ix = 0; ix < 10; ix++)
+ {
+ DescriptorA.AsULONG = READ_REGISTER_ULONG(DescriptorAReg);
+
+ if (DescriptorA.AsULONG != 0 &&
+ DescriptorA.Reserved == 0 &&
+ DescriptorA.NumberDownstreamPorts <= OHCI_MAX_PORT_COUNT)
+ {
+ break;
+ }
+
+ DPRINT1("OHCI_ReadRhDescriptorA: DescriptorA - %lX, ix - %d\n",
+ DescriptorA.AsULONG, ix);
+
+ KeStallExecutionProcessor(5);
+ }
+
+ return DescriptorA;
+}
+
+VOID
+NTAPI
+OHCI_RH_GetRootHubData(IN PVOID ohciExtension,
+ IN PVOID rootHubData)
+{
+ POHCI_EXTENSION OhciExtension;
+ PUSBPORT_ROOT_HUB_DATA RootHubData;
+ OHCI_REG_RH_DESCRIPTORA DescriptorA;
+ UCHAR PowerOnToPowerGoodTime;
+ USBPORT_HUB_11_CHARACTERISTICS HubCharacteristics;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_GetRootHubData: OhciExtension - %p, rootHubData - %p\n",
+ OhciExtension,
+ rootHubData);
+
+ RootHubData = rootHubData;
+ DescriptorA = OHCI_ReadRhDescriptorA(OhciExtension);
+
+ RootHubData->NumberOfPorts = DescriptorA.NumberDownstreamPorts;
+
+ /* Waiting time (in 2 ms intervals) */
+ PowerOnToPowerGoodTime = DescriptorA.PowerOnToPowerGoodTime;
+ if (PowerOnToPowerGoodTime <= OHCI_MINIMAL_POTPGT)
+ PowerOnToPowerGoodTime = OHCI_MINIMAL_POTPGT;
+ RootHubData->PowerOnToPowerGood = PowerOnToPowerGoodTime;
+
+ HubCharacteristics.AsUSHORT = 0;
+
+ if (DescriptorA.PowerSwitchingMode)
+ {
+ /* Individual port power switching */
+ HubCharacteristics.PowerControlMode = 1;
+ }
+ else
+ {
+ /* Ganged power switching */
+ HubCharacteristics.PowerControlMode = 0;
+ }
+
+ HubCharacteristics.NoPowerSwitching = 0;
+
+ /* always 0 (OHCI RH is not a compound device) */
+ ASSERT(DescriptorA.DeviceType == 0);
+ HubCharacteristics.PartOfCompoundDevice = DescriptorA.DeviceType;
+
+ HubCharacteristics.OverCurrentProtectionMode = DescriptorA.OverCurrentProtectionMode;
+ HubCharacteristics.NoOverCurrentProtection = DescriptorA.NoOverCurrentProtection;
+
+ RootHubData->HubCharacteristics.Usb11HubCharacteristics = HubCharacteristics;
+ RootHubData->HubControlCurrent = 0;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetStatus(IN PVOID ohciExtension,
+ IN PUSHORT Status)
+{
+ DPRINT("OHCI_RH_GetStatus: \n");
+ *Status = OHCI_RH_STATUS_GOOD;
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetPortStatus(IN PVOID ohciExtension,
+ IN USHORT Port,
+ IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS OhciPortStatus;
+ ULONG ix;
+ ULONG Reserved;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_GetPortStatus: OhciExtension - %p, Port - %x, PortStatus - %lX\n",
+ OhciExtension,
+ Port,
+ PortStatus->AsUlong32);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ for (ix = 0; ix < 10; ix++)
+ {
+ OhciPortStatus.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
+
+ Reserved = OhciPortStatus.Reserved1r |
+ OhciPortStatus.Reserved2r |
+ OhciPortStatus.Reserved3;
+
+ if (OhciPortStatus.AsULONG && !Reserved)
+ break;
+
+ DPRINT("OHCI_RH_GetPortStatus: OhciPortStatus - %X\n", OhciPortStatus.AsULONG);
+
+ KeStallExecutionProcessor(5);
+ }
+
+ PortStatus->AsUlong32 = OhciPortStatus.AsULONG;
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_GetHubStatus(IN PVOID ohciExtension,
+ IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG RhStatusReg;
+ OHCI_REG_RH_STATUS HcRhStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_GetHubStatus: ohciExtension - %p, HubStatus - %lX\n",
+ ohciExtension,
+ HubStatus->AsUlong32);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
+
+ HcRhStatus.AsULONG = READ_REGISTER_ULONG(RhStatusReg);
+
+ HubStatus->HubStatus.LocalPowerLost = HcRhStatus.LocalPowerStatus;
+ HubStatus->HubChange.LocalPowerChange = HcRhStatus.LocalPowerStatusChange;
+
+ HubStatus->HubStatus.OverCurrent = HcRhStatus.OverCurrentIndicator;
+ HubStatus->HubChange.OverCurrentChange = HcRhStatus.OverCurrentIndicatorChangeR;
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortReset(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_SetFeaturePortReset: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.SetPortReset = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortPower(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_SetFeaturePortPower: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.SetPortPower = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortEnable(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_SetFeaturePortEnable: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.SetPortEnable = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_SetFeaturePortSuspend(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_SetFeaturePortSuspend: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.SetPortSuspend = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortEnable(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortEnable: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.ClearPortEnable = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortPower(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortPower: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.ClearPortPower = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortSuspend(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortSuspend: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.ClearSuspendStatus = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortEnableChange(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortEnableChange: ohciExtension - %p, Port - %x\n",
+ ohciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.PortEnableStatusChange = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortConnectChange(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortConnectChange: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.ConnectStatusChange = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortResetChange(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortResetChange: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.PortResetStatusChange = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortSuspendChange(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortSuspendChange: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ ASSERT(Port > 0);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+
+ PortStatus.AsULONG = 0;
+ PortStatus.PortSuspendStatusChange = 1;
+
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+
+ return MP_STATUS_SUCCESS;
+}
+
+MPSTATUS
+NTAPI
+OHCI_RH_ClearFeaturePortOvercurrentChange(IN PVOID ohciExtension,
+ IN USHORT Port)
+{
+ POHCI_EXTENSION OhciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG PortStatusReg;
+ PULONG RhStatusReg;
+ OHCI_REG_RH_PORT_STATUS PortStatus;
+ OHCI_REG_RH_STATUS RhStatus;
+
+ OhciExtension = ohciExtension;
+
+ DPRINT("OHCI_RH_ClearFeaturePortOvercurrentChange: OhciExtension - %p, Port - %x\n",
+ OhciExtension,
+ Port);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+
+ if (Port)
+ {
+ /* USBPORT_RECIPIENT_PORT */
+ PortStatus.AsULONG = 0;
+ PortStatus.PortOverCurrentIndicatorChange = 1;
+
+ PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
+ WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
+ }
+ else
+ {
+ /* USBPORT_RECIPIENT_HUB */
+ RhStatus.AsULONG = 0;
+ RhStatus.OverCurrentIndicatorChangeW = 1;
+
+ RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
+ WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
+ }
+
+ return MP_STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+OHCI_RH_DisableIrq(IN PVOID ohciExtension)
+{
+ POHCI_EXTENSION OhciExtension = ohciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG InterruptDisableReg;
+ OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptDisable;
+
+ DPRINT("OHCI_RH_DisableIrq: OhciExtension - %p\n", OhciExtension);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
+
+ InterruptDisable.AsULONG = 0;
+ InterruptDisable.RootHubStatusChange = 1;
+
+ WRITE_REGISTER_ULONG(InterruptDisableReg, InterruptDisable.AsULONG);
+}
+
+VOID
+NTAPI
+OHCI_RH_EnableIrq(IN PVOID ohciExtension)
+{
+ POHCI_EXTENSION OhciExtension = ohciExtension;
+ POHCI_OPERATIONAL_REGISTERS OperationalRegs;
+ PULONG InterruptEnableReg;
+ OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptEnable;
+
+ DPRINT("OHCI_RH_EnableIrq: OhciExtension - %p\n", OhciExtension);
+
+ OperationalRegs = OhciExtension->OperationalRegs;
+ InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
+
+ InterruptEnable.AsULONG = 0;
+ InterruptEnable.RootHubStatusChange = 1;
+
+ WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptEnable.AsULONG);
+}