Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

432 lines
9.2 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
roothub.c
Abstract:
miniport root hub
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
Revision History:
2-19-99 : created, jdunn
implements the following miniport functions:
MINIPORT_RH_GetStatus
MINIPORT_RH_GetPortStatus
MINIPORT_RH_GethubStatus
MINIPORT_RH_SetFeaturePortReset
MINIPORT_RH_SetFeaturePortSuspend
MINIPORT_RH_SetFeaturePortPower
MINIPORT_RH_ClearFeaturePortEnable
MINIPORT_RH_ClearFeaturePortSuspend
MINIPORT_RH_ClearFeaturePortPower
MINIPORT_RH_ClearFeaturePortConnectChange
MINIPORT_RH_ClearFeaturePortResetChange
MINIPORT_RH_ClearFeaturePortEnableChange
MINIPORT_RH_ClearFeaturePortSuspendChange
MINIPORT_RH_ClearFeaturePortOvercurrentChange
--*/
#include "common.h"
VOID
OHCI_RH_GetRootHubData(
PDEVICE_DATA DeviceData,
PROOTHUB_DATA HubData
)
/*++
return info about the root hub
--*/
{
HC_RH_DESCRIPTOR_A descrA;
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
descrA.ul = OHCI_ReadRhDescriptorA(DeviceData);
OHCI_ASSERT(DeviceData, (descrA.ul) && (!(descrA.ul & HcDescA_RESERVED)));
HubData->NumberOfPorts = descrA.s.NumberDownstreamPorts;
DeviceData->NumberOfPorts = HubData->NumberOfPorts;
HubData->HubCharacteristics.us = (USHORT)descrA.s.HubChars;
HubData->PowerOnToPowerGood = descrA.s.PowerOnToPowerGoodTime;
// This may upset the stopwatch fanatics, but it appears that a minimum
// delay is necessary here in some cases. One example being resuming from
// hibernation on a 7800 with a USB IntelliMouse Explorer attached.
// (The delay happens in the hub driver after powering on each port).
//
HubData->PowerOnToPowerGood = max(descrA.s.PowerOnToPowerGoodTime, 25);
// OHCI controllers generally use the 1.0 USB spec.
// HubChars were revised in 1.1 so we need to do some
// mapping.
// We will assume it is gang switched unless the port
// power switching bit is set
HubData->HubCharacteristics.PowerSwitchType =
USBPORT_RH_POWER_SWITCH_GANG;
if (descrA.ul & HcDescA_PowerSwitchingModePort) {
HubData->HubCharacteristics.PowerSwitchType =
USBPORT_RH_POWER_SWITCH_PORT;
}
// this value is the current consumed by the hub
// brains, for the embedded hub this doesn't make
// much sense.
// so we report zero.
//
HubData->HubControlCurrent = 0;
}
USB_MINIPORT_STATUS
OHCI_RH_GetStatus(
PDEVICE_DATA DeviceData,
PUSHORT Status
)
/*++
get the device status
--*/
{
// the root hub is self powered
*Status = USB_GETSTATUS_SELF_POWERED;
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortEnable (
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortEnable);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortPower (
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortPower);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_GetPortStatus(
PDEVICE_DATA DeviceData,
USHORT PortNumber,
PRH_PORT_STATUS portStatus
)
/*++
get the status of a partuclar port
--*/
{
PHC_OPERATIONAL_REGISTER hc;
PULONG pulRegister;
ULONG statusAsUlong;
ULONG i;
hc = DeviceData->HC;
// hw array is zero based
//
pulRegister = &hc->HcRhPortStatus[PortNumber-1];
//
// by coincedence rhStatus register defined in OHCI is an
// exact match of the RH_PORT_STATUS define in the USB core
// spec.
//
// If this register reads as all zero or any of the reserved bits are set
// then try reading the register again. This is a workaround for some
// early revs of the AMD K7 chipset, which can sometimes return bogus values
// if the root hub registers are read while the host controller is
// performing PCI bus master ED & TD reads.
//
for (i = 0; i < 10; i++)
{
statusAsUlong = READ_REGISTER_ULONG(pulRegister);
if ((statusAsUlong) && (!(statusAsUlong & HcRhPS_RESERVED)))
{
break;
}
else
{
KeStallExecutionProcessor(5);
}
}
portStatus->ul = statusAsUlong;
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_SetFeaturePortReset(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
Put a port in reset
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortReset);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_SetFeaturePortSuspend(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
Put a port in suspend
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortSuspend);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortSuspend(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortSuspend);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortSuspendChange(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortSuspendStatusChange);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortOvercurrentChange(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
if (PortNumber == 0) {
WRITE_REGISTER_ULONG(&hc->HcRhStatus, HcRhS_ClearOverCurrentIndicatorChange);
} else {
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortOverCurrentChange);
}
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_SetFeaturePortPower(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortPower);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_SetFeaturePortEnable(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortEnable);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortConnectChange(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1],
HcRhPS_ClearConnectStatusChange);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortEnableChange(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1],
HcRhPS_ClearPortEnableStatusChange);
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_GetHubStatus(
PDEVICE_DATA DeviceData,
PRH_HUB_STATUS HubStatus
)
{
PHC_OPERATIONAL_REGISTER hc;
ULONG statusAsUlong;
hc = DeviceData->HC;
// we will never report a localpower change
HubStatus->LocalPowerLost = 0;
HubStatus->LocalPowerChange = 0;
// see if we should reort an overcurrent condition
//
statusAsUlong =
READ_REGISTER_ULONG(&hc->HcRhStatus);
HubStatus->OverCurrent =
(statusAsUlong & HcRhS_OverCurrentIndicator) ? 1: 0;
HubStatus->OverCurrentChange =
(statusAsUlong & HcRhS_OverCurrentIndicatorChange) ? 1: 0;
return USBMP_STATUS_SUCCESS;
}
USB_MINIPORT_STATUS
OHCI_RH_ClearFeaturePortResetChange(
PDEVICE_DATA DeviceData,
USHORT PortNumber
)
/*++
--*/
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1],
HcRhPS_ClearPortResetStatusChange);
return USBMP_STATUS_SUCCESS;
}