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.
 
 
 
 
 
 

402 lines
8.5 KiB

/*++
Copyright (c) 1999, 2000 Microsoft Corporation
Module Name:
int.c
Abstract:
interrupt service routine
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, 2000 Microsoft Corporation. All Rights Reserved.
Revision History:
7-19-99 : created, jdunn
--*/
#include "common.h"
BOOLEAN
EHCI_InterruptService (
PDEVICE_DATA DeviceData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
BOOLEAN usbInt;
PHC_OPERATIONAL_REGISTER hcOp;
ULONG enabledIrqs, frameNumber;
USBSTS irqStatus;
FRINDEX frameIndex;
hcOp = DeviceData->OperationalRegisters;
// assume it is not ours
usbInt = FALSE;
if (EHCI_HardwarePresent(DeviceData, FALSE) == FALSE) {
return FALSE;
}
// get a mask of possible interrupts
enabledIrqs = READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
irqStatus.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
// just look at the IRQ status bits
irqStatus.ul &= HcInterruptStatusMask;
// AND with the enabled IRQs
irqStatus.ul &= enabledIrqs;
// irqStatus now possibly contains bits set for any currently
// enabled interrupts
if (irqStatus.ul != 0) {
DeviceData->IrqStatus = irqStatus.ul;
WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
irqStatus.ul);
#if DBG
if (irqStatus.HostSystemError) {
// something has gone terribly wrong
EHCI_ASSERT(DeviceData, FALSE);
}
#endif
// This code maintains the 32-bit 1 ms frame counter
// bugbug this code does not handle varaible frame list
// sizes
frameIndex.ul = READ_REGISTER_ULONG(&hcOp->UsbFrameIndex.ul);
frameNumber = (ULONG) frameIndex.FrameListCurrentIndex;
// shut off the microframes
frameNumber >>= 3;
// did the sign bit change ?
if ((DeviceData->LastFrame ^ frameNumber) & 0x0400) {
// Yes
DeviceData->FrameNumberHighPart += 0x0800 -
((frameNumber ^ DeviceData->FrameNumberHighPart) & 0x0400);
}
// remember the last frame number
DeviceData->LastFrame = frameNumber;
// inications are that this came from the
// USB controller
usbInt = TRUE;
// disable all interrupts until the DPC for ISR runs
//WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
// 0);
}
return usbInt;
}
VOID
EHCI_InterruptDpc (
PDEVICE_DATA DeviceData,
BOOLEAN EnableInterrupts
)
/*++
Routine Description:
process an interrupt
Arguments:
Return Value:
--*/
{
PHC_OPERATIONAL_REGISTER hcOp;
USBSTS irqStatus, tmp;
FRINDEX frameIndex;
hcOp = DeviceData->OperationalRegisters;
// ack all status bits asserted now
//tmp.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
tmp.ul = DeviceData->IrqStatus;
DeviceData->IrqStatus = 0;
frameIndex.ul = READ_REGISTER_ULONG(&hcOp->UsbFrameIndex.ul);
LOGENTRY(DeviceData, G, '_idp', tmp.ul, 0,
frameIndex.ul);
//WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
// tmp.ul);
// now process status bits aserted,
// just look at the IRQ status bits
irqStatus.ul = tmp.ul & HcInterruptStatusMask;
// AND with the enabled IRQs, these are the interrupts
// we are interested in
irqStatus.ul &= DeviceData->EnabledInterrupts.ul;
if (irqStatus.UsbInterrupt ||
irqStatus.UsbError ||
irqStatus.IntOnAsyncAdvance) {
LOGENTRY(DeviceData, G, '_iEP', irqStatus.ul, 0, 0);
USBPORT_INVALIDATE_ENDPOINT(DeviceData, NULL);
}
if (irqStatus.PortChangeDetect) {
USBPORT_INVALIDATE_ROOTHUB(DeviceData);
}
// since ehci does not provide a way to globally mask
// interrupts we must mask off all interrupts in our ISR.
// When the ISR DPC completes we re-enable the set of
// currently enabled interrupts.
if (EnableInterrupts) {
LOGENTRY(DeviceData, G, '_iEE', 0, 0, 0);
WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
DeviceData->EnabledInterrupts.ul);
}
}
VOID
USBMPFN
EHCI_DisableInterrupts(
PDEVICE_DATA DeviceData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PHC_OPERATIONAL_REGISTER hcOp = NULL;
hcOp = DeviceData->OperationalRegisters;
// mask off all interrupts
WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
0);
}
VOID
USBMPFN
EHCI_FlushInterrupts(
PDEVICE_DATA DeviceData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PHC_OPERATIONAL_REGISTER hcOp = NULL;
USBSTS irqStatus;
hcOp = DeviceData->OperationalRegisters;
// flush any outstanding interrupts
irqStatus.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
irqStatus.ul);
}
VOID
USBMPFN
EHCI_EnableInterrupts(
PDEVICE_DATA DeviceData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PHC_OPERATIONAL_REGISTER hcOp = NULL;
hcOp = DeviceData->OperationalRegisters;
// activate the controllers interrupt
WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
DeviceData->EnabledInterrupts.ul);
}
VOID
EHCI_RH_DisableIrq(
PDEVICE_DATA DeviceData
)
{
PHC_OPERATIONAL_REGISTER hcOp = NULL;
USBINTR enabledIrqs;
hcOp = DeviceData->OperationalRegisters;
// clear the port change interrupt
enabledIrqs.ul =
READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
enabledIrqs.PortChangeDetect =
DeviceData->EnabledInterrupts.PortChangeDetect = 0;
if (enabledIrqs.UsbInterrupt) {
WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
enabledIrqs.ul);
}
}
VOID
EHCI_RH_EnableIrq(
PDEVICE_DATA DeviceData
)
{
PHC_OPERATIONAL_REGISTER hcOp = NULL;
USBINTR enabledIrqs;
hcOp = DeviceData->OperationalRegisters;
// enable the port change interrupt
enabledIrqs.ul =
READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
enabledIrqs.PortChangeDetect =
DeviceData->EnabledInterrupts.PortChangeDetect = 1;
if (enabledIrqs.UsbInterrupt) {
WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
enabledIrqs.ul);
}
}
VOID
EHCI_InterruptNextSOF(
PDEVICE_DATA DeviceData
)
{
PHC_OPERATIONAL_REGISTER hcOp = NULL;
USBCMD cmd;
hcOp = DeviceData->OperationalRegisters;
// before we use the doorbell enable the async list
EHCI_EnableAsyncList(DeviceData);
cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
cmd.IntOnAsyncAdvanceDoorbell = 1;
WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul,
cmd.ul);
// TEST_TRAP();
}
ULONG
EHCI_Get32BitFrameNumber(
PDEVICE_DATA DeviceData
)
{
ULONG highPart, currentFrame, frameNumber;
PHC_OPERATIONAL_REGISTER hcOp = NULL;
FRINDEX frameIndex;
hcOp = DeviceData->OperationalRegisters;
// get Hcd's high part of frame number
highPart = DeviceData->FrameNumberHighPart;
// bugbug this code does not handle varaible frame list
// sizes
frameIndex.ul = READ_REGISTER_ULONG(&hcOp->UsbFrameIndex.ul);
frameNumber = (ULONG) frameIndex.FrameListCurrentIndex;
// shift off the microframes
frameNumber >>= 3;
currentFrame = ((frameNumber & 0x0bff) | highPart) +
((frameNumber ^ highPart) & 0x0400);
return currentFrame;
}
BOOLEAN
EHCI_HardwarePresent(
PDEVICE_DATA DeviceData,
BOOLEAN Notify
)
{
ULONG tmp;
PHC_OPERATIONAL_REGISTER hcOp;
hcOp = DeviceData->OperationalRegisters;
tmp = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
if (tmp == 0xffffffff) {
if (Notify) {
USBPORT_INVALIDATE_CONTROLLER(DeviceData, UsbMpControllerRemoved);
}
return FALSE;
}
return TRUE;
}