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.
 
 
 
 
 
 

258 lines
6.3 KiB

/*++
Copyright (c) 1999 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 Microsoft Corporation. All Rights Reserved.
Revision History:
7-19-99 : created, jdunn
--*/
#include "common.h"
BOOLEAN
OHCI_InterruptService (
PDEVICE_DATA DeviceData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
BOOLEAN usbInt;
PHC_OPERATIONAL_REGISTER hc;
ULONG irqStatus, enabledIrqs, tmp;
hc = DeviceData->HC;
// assume it is not ours
usbInt = FALSE;
// see if we have lost the controller due to
// a surprise remove
if (OHCI_HardwarePresent(DeviceData, FALSE) == FALSE) {
return FALSE;
}
// get a mask of possible interrupts
enabledIrqs = READ_REGISTER_ULONG (&hc->HcInterruptEnable);
irqStatus = READ_REGISTER_ULONG(&hc->HcInterruptStatus);
// mask off non-enabled irqs
irqStatus &= enabledIrqs;
// irqStatus now possibly contains bits set for any currently
// enabled interrupts
if ((irqStatus != 0) &&
(enabledIrqs & HcInt_MasterInterruptEnable)) {
// check for frame number overflow
if (irqStatus & HcInt_FrameNumberOverflow) {
DeviceData->FrameHighPart
+= 0x10000 - (0x8000 & (DeviceData->HcHCCA->HccaFrameNumber
^ DeviceData->FrameHighPart));
}
#if DBG
if (irqStatus & HcInt_UnrecoverableError) {
// something has gone terribly wrong
OHCI_KdPrint((DeviceData, 0, "'HcInt_UnrecoverableError! DD(%x)\n",
DeviceData));
//DbgBreakPoint();
}
#endif
// indications are that this came from the USB controller
usbInt = TRUE;
// disable interrupts until the DPC for ISR runs
WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
HcInt_MasterInterruptEnable);
}
return usbInt;
}
VOID
OHCI_InterruptDpc (
PDEVICE_DATA DeviceData,
BOOLEAN EnableInterrupts
)
/*++
Routine Description:
process an interrupt
Arguments:
Return Value:
--*/
{
ULONG irqStatus;
PHC_OPERATIONAL_REGISTER hc;
ULONG doneQueue, cf;
hc = DeviceData->HC;
irqStatus = READ_REGISTER_ULONG(&hc->HcInterruptStatus);
cf = OHCI_Get32BitFrameNumber(DeviceData);
// what was the reason for the interrupt?
if (irqStatus & HcInt_RootHubStatusChange) {
LOGENTRY(DeviceData, G, '_rhS', DeviceData, 0, 0);
USBPORT_INVALIDATE_ROOTHUB(DeviceData);
}
if (irqStatus & HcInt_WritebackDoneHead) {
// controller indicates some done TDs
doneQueue = DeviceData->HcHCCA->HccaDoneHead;
LOGENTRY(DeviceData, G, '_dnQ', DeviceData, doneQueue,
cf);
// we will have a problem if we ever actually use the doneQ.
// Currently we do not use it so the hydra bug where the doneQ
// is wriiten back as zero won't hurt us.
//if (doneQueue == 0) {
//}
// write the done head back to zero
DeviceData->HcHCCA->HccaDoneHead = 0;
LOGENTRY(DeviceData, G, '_dQZ', DeviceData, doneQueue, 0);
// if (DoneQueue) {
// OpenHCI_ProcessDoneQueue(deviceData, (DoneQueue & 0xFFFFfffe));
// //
// // BUGBUG (?) No interrupts can come in while processing
// // the done queue. Is this bad? This might take a while.
// //
// }
// check all endpoints
USBPORT_INVALIDATE_ENDPOINT(DeviceData, NULL);
}
if (irqStatus & HcInt_StartOfFrame) {
// got the SOF we requested, disable it
WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
HcInt_StartOfFrame);
}
if (irqStatus & HcInt_ResumeDetected) {
// got the resume, disable it
WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
HcInt_ResumeDetected);
}
if (irqStatus & HcInt_UnrecoverableError) {
// host controller is dead, try to recover...
USBPORT_INVALIDATE_CONTROLLER(DeviceData, UsbMpControllerNeedsHwReset);
}
// acknowlege the interrupts we processed --
// we should have proceesed them all
WRITE_REGISTER_ULONG(&hc->HcInterruptStatus, irqStatus);
// see if we need to re-enable ints
if (EnableInterrupts) {
// throw the master irq enable to allow more interupts
WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
HcInt_MasterInterruptEnable);
}
}
VOID
OHCI_RH_DisableIrq(
PDEVICE_DATA DeviceData
)
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
HcInt_RootHubStatusChange);
}
VOID
OHCI_RH_EnableIrq(
PDEVICE_DATA DeviceData
)
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
HcInt_RootHubStatusChange);
}
ULONG
OHCI_Get32BitFrameNumber(
PDEVICE_DATA DeviceData
)
{
ULONG hp, fn, n;
/*
* This code accounts for the fact that HccaFrameNumber is updated by the
* HC before the HCD gets an interrupt that will adjust FrameHighPart. No
* synchronization is nescisary due to great cleaverness.
*/
hp = DeviceData->FrameHighPart;
fn = DeviceData->HcHCCA->HccaFrameNumber;
n = ((fn & 0x7FFF) | hp) + ((fn ^ hp) & 0x8000);
return n;
}
VOID
OHCI_InterruptNextSOF(
PDEVICE_DATA DeviceData
)
{
PHC_OPERATIONAL_REGISTER hc;
hc = DeviceData->HC;
WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
HcInt_StartOfFrame);
}