2018-09-10 07:05:35 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS USB EHCI Miniport Driver
|
|
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
|
|
* PURPOSE: USBEHCI root hub functions
|
|
|
|
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "usbehci.h"
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#define NDEBUG_EHCI_ROOT_HUB
|
|
|
|
#include "dbg_ehci.h"
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ChirpRootPort(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
ULONG PortBit;
|
|
|
|
ULONG ix;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: PortSC - %X\n", PortSC.AsULONG);
|
|
|
|
|
|
|
|
PortBit = 1 << (Port - 1);
|
|
|
|
|
|
|
|
if (PortBit & EhciExtension->ResetPortBits)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Skip port - %x\n", Port);
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PortSC.PortPower == 0)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Skip port - %x\n", Port);
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PortSC.CurrentConnectStatus == 0 ||
|
|
|
|
PortSC.PortEnabledDisabled == 1 ||
|
|
|
|
PortSC.PortOwner == EHCI_PORT_OWNER_COMPANION_CONTROLLER)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: No port - %x\n", Port);
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PortSC.LineStatus == EHCI_LINE_STATUS_K_STATE_LOW_SPEED &&
|
|
|
|
PortSC.Suspend == 0 &&
|
|
|
|
PortSC.CurrentConnectStatus == 1)
|
|
|
|
{
|
|
|
|
/* Attached device is not a high-speed device.
|
|
|
|
Release ownership of the port to a selected HC.
|
|
|
|
Companion HC owns and controls the port. Section 4.2 */
|
|
|
|
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER;
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Companion HC port - %x\n", Port);
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ChirpRootPort: EhciExtension - %p, Port - %x\n",
|
|
|
|
EhciExtension,
|
|
|
|
Port);
|
|
|
|
|
|
|
|
PortSC.PortEnabledDisabled = 0;
|
|
|
|
PortSC.PortReset = 1;
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
RegPacket.UsbPortWait(EhciExtension, 10);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.PortReset = 0;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
for (ix = 0; ix <= 500; ix += 20)
|
|
|
|
{
|
|
|
|
KeStallExecutionProcessor(20);
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Reset port - %x\n", Port);
|
|
|
|
|
|
|
|
if (PortSC.PortReset == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (PortSC.PortReset == 1);
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
if (PortSC.PortEnabledDisabled == 1)
|
|
|
|
{
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnabledDisabled = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
|
|
|
|
RegPacket.UsbPortWait(EhciExtension, 10);
|
|
|
|
|
|
|
|
EhciExtension->ResetPortBits |= PortBit;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Disable port - %x\n", Port);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER;
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
DPRINT_RH("EHCI_RH_ChirpRootPort: Companion HC port - %x\n", Port);
|
|
|
|
}
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_GetRootHubData(IN PVOID ehciExtension,
|
|
|
|
IN PVOID rootHubData)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PUSBPORT_ROOT_HUB_DATA RootHubData;
|
|
|
|
USBPORT_HUB_20_CHARACTERISTICS HubCharacteristics;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_GetRootHubData: EhciExtension - %p, rootHubData - %p\n",
|
|
|
|
EhciExtension,
|
|
|
|
rootHubData);
|
|
|
|
|
|
|
|
RootHubData = rootHubData;
|
|
|
|
|
|
|
|
RootHubData->NumberOfPorts = EhciExtension->NumberOfPorts;
|
|
|
|
|
|
|
|
HubCharacteristics.AsUSHORT = 0;
|
|
|
|
|
|
|
|
/* Logical Power Switching Mode */
|
|
|
|
if (EhciExtension->PortPowerControl == 1)
|
|
|
|
{
|
|
|
|
/* Individual port power switching */
|
|
|
|
HubCharacteristics.PowerControlMode = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-25 17:56:16 +00:00
|
|
|
/* Ganged power switching (all ports' power at once) */
|
2018-09-10 07:05:35 +00:00
|
|
|
HubCharacteristics.PowerControlMode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
HubCharacteristics.NoPowerSwitching = 0;
|
|
|
|
|
|
|
|
/* EHCI RH is not part of a compound device */
|
|
|
|
HubCharacteristics.PartOfCompoundDevice = 0;
|
|
|
|
|
|
|
|
/* Global Over-current Protection */
|
|
|
|
HubCharacteristics.OverCurrentProtectionMode = 0;
|
|
|
|
|
|
|
|
RootHubData->HubCharacteristics.Usb20HubCharacteristics = HubCharacteristics;
|
|
|
|
|
|
|
|
RootHubData->PowerOnToPowerGood = 2; // Time (in 2 ms intervals)
|
|
|
|
RootHubData->HubControlCurrent = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_GetStatus(IN PVOID ehciExtension,
|
|
|
|
IN PUSHORT Status)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_GetStatus: ... \n");
|
|
|
|
*Status = USB_GETSTATUS_SELF_POWERED;
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_GetPortStatus(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port,
|
|
|
|
IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
USB_PORT_STATUS_AND_CHANGE status;
|
|
|
|
ULONG PortMaskBits;
|
|
|
|
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
if (PortSC.CurrentConnectStatus)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_GetPortStatus: Port - %x, PortSC.AsULONG - %X\n",
|
|
|
|
Port,
|
|
|
|
PortSC.AsULONG);
|
|
|
|
}
|
|
|
|
|
|
|
|
PortStatus->AsUlong32 = 0;
|
|
|
|
|
|
|
|
if (PortSC.LineStatus == EHCI_LINE_STATUS_K_STATE_LOW_SPEED &&
|
|
|
|
PortSC.PortOwner != EHCI_PORT_OWNER_COMPANION_CONTROLLER &&
|
|
|
|
(PortSC.PortEnabledDisabled | PortSC.Suspend) && // Enable or Suspend
|
|
|
|
PortSC.CurrentConnectStatus == 1) // Device is present
|
|
|
|
{
|
|
|
|
DPRINT("EHCI_RH_GetPortStatus: LowSpeed device detected\n");
|
|
|
|
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER; // release ownership
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
status.AsUlong32 = 0;
|
|
|
|
|
|
|
|
status.PortStatus.Usb20PortStatus.CurrentConnectStatus = PortSC.CurrentConnectStatus;
|
|
|
|
status.PortStatus.Usb20PortStatus.PortEnabledDisabled = PortSC.PortEnabledDisabled;
|
|
|
|
status.PortStatus.Usb20PortStatus.Suspend = PortSC.Suspend;
|
|
|
|
status.PortStatus.Usb20PortStatus.OverCurrent = PortSC.OverCurrentActive;
|
|
|
|
status.PortStatus.Usb20PortStatus.Reset = PortSC.PortReset;
|
|
|
|
status.PortStatus.Usb20PortStatus.PortPower = PortSC.PortPower;
|
|
|
|
if (PortSC.PortOwner == EHCI_PORT_OWNER_COMPANION_CONTROLLER)
|
|
|
|
status.PortStatus.Usb20PortStatus.Reserved1 = USB20_PORT_STATUS_RESERVED1_OWNED_BY_COMPANION;
|
|
|
|
|
|
|
|
status.PortChange.Usb20PortChange.PortEnableDisableChange = PortSC.PortEnableDisableChange;
|
|
|
|
status.PortChange.Usb20PortChange.OverCurrentIndicatorChange = PortSC.OverCurrentChange;
|
|
|
|
|
|
|
|
PortMaskBits = 1 << (Port - 1);
|
|
|
|
|
|
|
|
if (status.PortStatus.Usb20PortStatus.CurrentConnectStatus)
|
|
|
|
status.PortStatus.Usb20PortStatus.LowSpeedDeviceAttached = 0;
|
|
|
|
|
|
|
|
status.PortStatus.Usb20PortStatus.HighSpeedDeviceAttached = 1;
|
|
|
|
|
|
|
|
if (PortSC.ConnectStatusChange)
|
|
|
|
EhciExtension->ConnectPortBits |= PortMaskBits;
|
|
|
|
|
|
|
|
if (EhciExtension->FinishResetPortBits & PortMaskBits)
|
|
|
|
status.PortChange.Usb20PortChange.ResetChange = 1;
|
|
|
|
|
|
|
|
if (EhciExtension->ConnectPortBits & PortMaskBits)
|
|
|
|
status.PortChange.Usb20PortChange.ConnectStatusChange = 1;
|
|
|
|
|
|
|
|
if (EhciExtension->SuspendPortBits & PortMaskBits)
|
|
|
|
status.PortChange.Usb20PortChange.SuspendChange = 1;
|
|
|
|
|
|
|
|
*PortStatus = status;
|
|
|
|
|
|
|
|
if (status.PortStatus.Usb20PortStatus.CurrentConnectStatus)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_GetPortStatus: Port - %x, status.AsULONG - %X\n",
|
|
|
|
Port,
|
|
|
|
status.AsUlong32);
|
|
|
|
}
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_GetHubStatus(IN PVOID ehciExtension,
|
|
|
|
IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_GetHubStatus: ... \n");
|
|
|
|
HubStatus->AsUlong32 = 0;
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_FinishReset(IN PVOID ehciExtension,
|
|
|
|
IN PVOID Context)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
PUSHORT Port = Context;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_FinishReset: *Port - %x\n", *Port);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG;
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
if (PortSC.AsULONG != -1)
|
|
|
|
{
|
|
|
|
if (!PortSC.CurrentConnectStatus)
|
|
|
|
DPRINT("EHCI_RH_FinishReset: PortSC.AsULONG - %X\n", PortSC.AsULONG);
|
|
|
|
|
|
|
|
if (PortSC.PortEnabledDisabled ||
|
|
|
|
!PortSC.CurrentConnectStatus ||
|
|
|
|
PortSC.ConnectStatusChange)
|
|
|
|
{
|
|
|
|
EhciExtension->FinishResetPortBits |= (1 << (*Port - 1));
|
|
|
|
RegPacket.UsbPortInvalidateRootHub(EhciExtension);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
PortSC.PortOwner = EHCI_PORT_OWNER_COMPANION_CONTROLLER;
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
EhciExtension->FinishResetPortBits |= (1 << (*Port - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
EhciExtension->ResetPortBits &= ~(1 << (*Port - 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_PortResetComplete(IN PVOID ehciExtension,
|
|
|
|
IN PVOID Context)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
ULONG ix;
|
|
|
|
PUSHORT Port = Context;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_PortResetComplete: *Port - %x\n", *Port);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.PortReset = 0;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
for (ix = 0; ix <= 500; ix += 20)
|
|
|
|
{
|
|
|
|
KeStallExecutionProcessor(20);
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_PortResetComplete: Reset port - %x\n", Port);
|
|
|
|
|
|
|
|
if (PortSC.PortReset == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (PortSC.PortReset == 1 && (PortSC.AsULONG != -1));
|
|
|
|
|
|
|
|
RegPacket.UsbPortRequestAsyncCallback(EhciExtension,
|
|
|
|
50, // TimerValue
|
|
|
|
Port,
|
2021-10-25 17:56:16 +00:00
|
|
|
sizeof(*Port),
|
2018-09-10 07:05:35 +00:00
|
|
|
EHCI_RH_FinishReset);
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_SetFeaturePortReset(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_SetFeaturePortReset: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
EhciExtension->ResetPortBits |= 1 << (Port - 1);
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnabledDisabled = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.PortReset = 1;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
RegPacket.UsbPortRequestAsyncCallback(EhciExtension,
|
|
|
|
50, // TimerValue
|
|
|
|
&Port,
|
|
|
|
sizeof(Port),
|
|
|
|
EHCI_RH_PortResetComplete);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_SetFeaturePortPower(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_SetFeaturePortPower: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.PortPower = 1;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_SetFeaturePortEnable(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
DPRINT_RH("EHCI_RH_SetFeaturePortEnable: Not supported\n");
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_SetFeaturePortSuspend(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_SetFeaturePortSuspend: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.Suspend = 1;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
KeStallExecutionProcessor(125);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortEnable(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ClearFeaturePortEnable: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnabledDisabled = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortPower(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ClearFeaturePortPower: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
PortSC.PortPower = 0;
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_PortResumeComplete(IN PVOID ehciExtension,
|
|
|
|
IN PVOID Context)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
PUSHORT Port = Context;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_PortResumeComplete: *Port - %x\n", *Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[*Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.ForcePortResume = 0;
|
|
|
|
PortSC.Suspend = 0;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
EhciExtension->SuspendPortBits |= 1 << (*Port - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortSuspend(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ClearFeaturePortSuspend: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
EhciExtension->ResetPortBits |= 1 << (Port - 1);
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
PortSC.ForcePortResume = 1;
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
RegPacket.UsbPortRequestAsyncCallback(EhciExtension,
|
|
|
|
50, // TimerValue
|
|
|
|
&Port,
|
|
|
|
sizeof(Port),
|
|
|
|
EHCI_RH_PortResumeComplete);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortEnableChange(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ClearFeaturePortEnableChange: Port - %p\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 1;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortConnectChange(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_ClearFeaturePortConnectChange: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
if (PortSC.ConnectStatusChange)
|
|
|
|
{
|
|
|
|
PortSC.ConnectStatusChange = 1;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 0;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
}
|
|
|
|
|
|
|
|
EhciExtension->ConnectPortBits &= ~(1 << (Port - 1));
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortResetChange(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ClearFeaturePortConnectChange: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
EhciExtension->FinishResetPortBits &= ~(1 << (Port - 1));
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortSuspendChange(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
|
|
|
|
DPRINT("EHCI_RH_ClearFeaturePortSuspendChange: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
EhciExtension->SuspendPortBits &= ~(1 << (Port - 1));
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPSTATUS
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_ClearFeaturePortOvercurrentChange(IN PVOID ehciExtension,
|
|
|
|
IN USHORT Port)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG PortStatusReg;
|
|
|
|
EHCI_PORT_STATUS_CONTROL PortSC;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_ClearFeaturePortOvercurrentChange: Port - %x\n", Port);
|
|
|
|
ASSERT(Port != 0);
|
|
|
|
|
|
|
|
PortStatusReg = &EhciExtension->OperationalRegs->PortControl[Port - 1].AsULONG;
|
|
|
|
|
|
|
|
PortSC.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
|
|
|
|
|
|
|
|
PortSC.ConnectStatusChange = 0;
|
|
|
|
PortSC.PortEnableDisableChange = 0;
|
|
|
|
PortSC.OverCurrentChange = 1;
|
|
|
|
|
|
|
|
WRITE_REGISTER_ULONG(PortStatusReg, PortSC.AsULONG);
|
|
|
|
|
|
|
|
return MP_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_DisableIrq(IN PVOID ehciExtension)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG IntrStsReg;
|
|
|
|
EHCI_INTERRUPT_ENABLE IntrSts;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_DisableIrq: ... \n");
|
|
|
|
|
|
|
|
IntrStsReg = &EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG;
|
|
|
|
IntrSts.AsULONG = READ_REGISTER_ULONG(IntrStsReg);
|
|
|
|
|
|
|
|
EhciExtension->InterruptMask.PortChangeInterrupt = 0;
|
|
|
|
IntrSts.PortChangeInterrupt = 0;
|
|
|
|
|
|
|
|
if (IntrSts.Interrupt)
|
|
|
|
WRITE_REGISTER_ULONG(IntrStsReg, IntrSts.AsULONG);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
EHCI_RH_EnableIrq(IN PVOID ehciExtension)
|
|
|
|
{
|
|
|
|
PEHCI_EXTENSION EhciExtension = ehciExtension;
|
|
|
|
PULONG IntrStsReg;
|
|
|
|
EHCI_INTERRUPT_ENABLE IntrSts;
|
|
|
|
|
|
|
|
DPRINT_RH("EHCI_RH_EnableIrq: ... \n");
|
|
|
|
|
|
|
|
IntrStsReg = &EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG;
|
|
|
|
IntrSts.AsULONG = READ_REGISTER_ULONG(IntrStsReg);
|
|
|
|
|
|
|
|
EhciExtension->InterruptMask.PortChangeInterrupt = 1;
|
|
|
|
IntrSts.PortChangeInterrupt = 1;
|
|
|
|
|
|
|
|
if (IntrSts.Interrupt)
|
|
|
|
WRITE_REGISTER_ULONG(IntrStsReg, IntrSts.AsULONG);
|
|
|
|
}
|