Fix definition of KINTERRUPT in ROS headers so that moving to NDK will be easier. Also fix KeDisconnectInterrupt to return the old state instead of VOID, and re-write the I/O Interrupt code to work with an array and first object for better speed

svn path=/trunk/; revision=16229
This commit is contained in:
Alex Ionescu 2005-06-22 23:10:15 +00:00
parent 9925309a13
commit d1258e99fa
5 changed files with 293 additions and 182 deletions

View file

@ -62,7 +62,7 @@ BOOLEAN STDCALL
KeConnectInterrupt( KeConnectInterrupt(
PKINTERRUPT InterruptObject); PKINTERRUPT InterruptObject);
VOID STDCALL BOOLEAN STDCALL
KeDisconnectInterrupt( KeDisconnectInterrupt(
PKINTERRUPT InterruptObject); PKINTERRUPT InterruptObject);

View file

@ -1781,22 +1781,48 @@ typedef struct _LPC_PORT_BASIC_INFORMATION
} LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION; } LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION;
#if 0
typedef struct _KINTERRUPT typedef struct _KINTERRUPT
{ {
ULONG Vector; ULONG Vector; // Idem
KAFFINITY ProcessorEnableMask; KAFFINITY ProcessorEnableMask; // not needed
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock; // Idem
PKSPIN_LOCK ActualLock; PKSPIN_LOCK ActualLock; // Idem
BOOLEAN Shareable; BOOLEAN Shareable; // ShareVector
BOOLEAN FloatingSave; BOOLEAN FloatingSave; // Idem
CHAR ProcessorNumber; CHAR ProcessorNumber; // Number
PKSERVICE_ROUTINE ServiceRoutine; // Idem
PVOID ServiceContext; // Idem
LIST_ENTRY Entry; // InteruptListEntry
KIRQL Irql; // Irql
KIRQL SynchLevel; // SynchronizeIrql
KINTERRUPT_MODE InterruptMode; // Mode
} KINTERRUPT;
#endif
typedef struct _KINTERRUPT
{
CSHORT Type;
CSHORT Size;
LIST_ENTRY InterruptListEntry;
PKSERVICE_ROUTINE ServiceRoutine; PKSERVICE_ROUTINE ServiceRoutine;
PVOID ServiceContext; PVOID ServiceContext;
LIST_ENTRY Entry; KSPIN_LOCK SpinLock;
ULONG TickCount;
PKSPIN_LOCK ActualLock;
PVOID DispatchAddress;
ULONG Vector;
KIRQL Irql; KIRQL Irql;
KIRQL SynchLevel; KIRQL SynchronizeIrql;
KINTERRUPT_MODE InterruptMode; BOOLEAN FloatingSave;
} KINTERRUPT; BOOLEAN Connected;
CHAR Number;
UCHAR ShareVector;
KINTERRUPT_MODE Mode;
ULONG ServiceCount;
ULONG DispatchCount;
ULONG DispatchCode[106];
} KINTERRUPT, *PKINTERRUPT;
#ifndef __USE_W32API #ifndef __USE_W32API

View file

@ -14,23 +14,16 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* TYPES ********************************************************************/
typedef struct _IO_INTERRUPT
{
KINTERRUPT FirstInterrupt;
PKINTERRUPT Interrupt[MAXIMUM_PROCESSORS];
KSPIN_LOCK SpinLock;
} IO_INTERRUPT, *PIO_INTERRUPT;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
NTSTATUS STDCALL
IoConnectInterrupt(PKINTERRUPT* InterruptObject,
PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext,
PKSPIN_LOCK SpinLock,
ULONG Vector,
KIRQL Irql,
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
KAFFINITY ProcessorEnableMask,
BOOLEAN FloatingSave)
/* /*
* FUNCTION: Registers a driver's isr to be called when its device interrupts * FUNCTION: Registers a driver's isr to be called when its device interrupts
* ARGUMENTS: * ARGUMENTS:
@ -57,55 +50,85 @@ IoConnectInterrupt(PKINTERRUPT* InterruptObject,
* the isr runs. Must be false for x86 drivers * the isr runs. Must be false for x86 drivers
* RETURNS: Status * RETURNS: Status
* IRQL: PASSIVE_LEVEL * IRQL: PASSIVE_LEVEL
*
* @implemented
*/ */
NTSTATUS
STDCALL
IoConnectInterrupt(PKINTERRUPT* InterruptObject,
PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext,
PKSPIN_LOCK SpinLock,
ULONG Vector,
KIRQL Irql,
KIRQL SynchronizeIrql,
KINTERRUPT_MODE InterruptMode,
BOOLEAN ShareVector,
KAFFINITY ProcessorEnableMask,
BOOLEAN FloatingSave)
{ {
PKINTERRUPT Interrupt; PKINTERRUPT Interrupt;
PKINTERRUPT InterruptUsed;
PIO_INTERRUPT IoInterrupt;
PKSPIN_LOCK SpinLockUsed;
BOOLEAN FirstRun = TRUE;
ULONG i, count; ULONG i, count;
ASSERT_IRQL(PASSIVE_LEVEL); PAGED_CODE();
DPRINT("IoConnectInterrupt(Vector %x)\n",Vector); DPRINT1("IoConnectInterrupt(Vector %x)\n",Vector);
/* Convert the Mask */
ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1); ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1);
if (ProcessorEnableMask == 0) /* Make sure at least one CPU is on it */
{ if (!ProcessorEnableMask) return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
}
/* Determine the allocation */
for (i = 0, count = 0; i < KeNumberProcessors; i++) for (i = 0, count = 0; i < KeNumberProcessors; i++)
{ {
if (ProcessorEnableMask & (1 << i)) if (ProcessorEnableMask & (1 << i)) count++;
{
count++;
} }
}
/* /* Allocate the array of I/O Interrupts */
* Initialize interrupt object IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,
*/ (count - 1)* sizeof(KINTERRUPT) +
Interrupt=ExAllocatePoolWithTag(NonPagedPool,count*sizeof(KINTERRUPT), sizeof(IO_INTERRUPT),
TAG_KINTERRUPT); TAG_KINTERRUPT);
if (Interrupt==NULL) if (!Interrupt) return(STATUS_INSUFFICIENT_RESOURCES);
/* Select which Spinlock to use */
if (SpinLock)
{ {
return(STATUS_INSUFFICIENT_RESOURCES); SpinLockUsed = SpinLock;
}
else
{
SpinLockUsed = &IoInterrupt->SpinLock;
} }
if (SpinLock == NULL) /* We first start with a built-in Interrupt inside the I/O Structure */
{ *InterruptObject = &IoInterrupt->FirstInterrupt;
SpinLock = &Interrupt[0].SpinLock; Interrupt = (PKINTERRUPT)(IoInterrupt + 1);
KeInitializeSpinLock(SpinLock); FirstRun = TRUE;
}
Interrupt[0].ProcessorEnableMask = ProcessorEnableMask; /* Start with a fresh structure */
RtlZeroMemory(IoInterrupt, sizeof(IO_INTERRUPT));
for (i = 0, count = 0; i < KeNumberProcessors; i++) /* Now create all the interrupts */
for (i = 0; i < KeNumberProcessors; i++)
{ {
/* Check if it's enabled for this CPU */
if (ProcessorEnableMask & (1 << i)) if (ProcessorEnableMask & (1 << i))
{ {
KeInitializeInterrupt(&Interrupt[count], /* Check which one we will use */
InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;
/* Initialize it */
KeInitializeInterrupt(InterruptUsed,
ServiceRoutine, ServiceRoutine,
ServiceContext, ServiceContext,
SpinLock, SpinLockUsed,
Vector, Vector,
Irql, Irql,
SynchronizeIrql, SynchronizeIrql,
@ -113,50 +136,77 @@ IoConnectInterrupt(PKINTERRUPT* InterruptObject,
ShareVector, ShareVector,
i, i,
FloatingSave); FloatingSave);
if (!KeConnectInterrupt(&Interrupt[count]))
/* Connect it */
if (!KeConnectInterrupt(InterruptUsed))
{ {
for (i = 0; i < count; i++) /* Check how far we got */
if (FirstRun)
{ {
if (ProcessorEnableMask & (1 << i)) /* We failed early so just free this */
{ ExFreePool(IoInterrupt);
KeDisconnectInterrupt(&Interrupt[i]);
} }
else
{
/* Far enough, so disconnect everything */
IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
} }
ExFreePool(Interrupt);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
count++;
/* Now we've used up our First Run */
if (FirstRun)
{
FirstRun = FALSE;
}
else
{
/* Move on to the next one */
IoInterrupt->Interrupt[i] = Interrupt++;
}
} }
} }
*InterruptObject = Interrupt; /* Return Success */
return STATUS_SUCCESS;
return(STATUS_SUCCESS);
} }
/*
* @implemented
*/
VOID STDCALL
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
/* /*
* FUNCTION: Releases a drivers isr * FUNCTION: Releases a drivers isr
* ARGUMENTS: * ARGUMENTS:
* InterruptObject = isr to release * InterruptObject = isr to release
*
* @implemented
*/ */
{ VOID
ULONG i, count; STDCALL
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
for (i = 0, count = 0; i < KeNumberProcessors; i++) {
ULONG i;
PIO_INTERRUPT IoInterrupt;
PAGED_CODE();
/* Get the I/O Interrupt */
IoInterrupt = CONTAINING_RECORD(InterruptObject,
IO_INTERRUPT,
FirstInterrupt);
/* Disconnect the first one */
KeDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
/* Now disconnect the others */
for (i = 0; i < KeNumberProcessors; i++)
{ {
if (InterruptObject[0].ProcessorEnableMask & (1 << i)) if (IoInterrupt->Interrupt[i])
{ {
KeDisconnectInterrupt(&InterruptObject[count]); KeDisconnectInterrupt(&InterruptObject[i]);
count++;
} }
} }
ExFreePool(InterruptObject);
/* Free the I/O Interrupt */
ExFreePool(IoInterrupt);
} }
/* EOF */ /* EOF */

View file

@ -278,7 +278,7 @@ KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
while (current != &CurrentIsr->ListHead) while (current != &CurrentIsr->ListHead)
{ {
isr = CONTAINING_RECORD(current,KINTERRUPT,Entry); isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
oldlvl = KeAcquireInterruptSpinLock(isr); oldlvl = KeAcquireInterruptSpinLock(isr);
if (isr->ServiceRoutine(isr, isr->ServiceContext)) if (isr->ServiceRoutine(isr, isr->ServiceContext))
{ {
@ -401,7 +401,7 @@ KeDumpIrqList(VOID)
KiAcquireSpinLock(&IsrTable[i][j].Lock); KiAcquireSpinLock(&IsrTable[i][j].Lock);
current_entry = IsrTable[i][j].ListHead.Flink; current_entry = IsrTable[i][j].ListHead.Flink;
current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry); current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
while (current_entry!=&(IsrTable[i][j].ListHead)) while (current_entry!=&(IsrTable[i][j].ListHead))
{ {
if (printed == FALSE) if (printed == FALSE)
@ -411,7 +411,7 @@ KeDumpIrqList(VOID)
} }
DPRINT(" Isr %x\n",current); DPRINT(" Isr %x\n",current);
current_entry = current_entry->Flink; current_entry = current_entry->Flink;
current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry); current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
} }
KiReleaseSpinLock(&IsrTable[i][j].Lock); KiReleaseSpinLock(&IsrTable[i][j].Lock);
} }
@ -422,7 +422,8 @@ KeDumpIrqList(VOID)
/* /*
* @implemented * @implemented
*/ */
BOOLEAN STDCALL BOOLEAN
STDCALL
KeConnectInterrupt(PKINTERRUPT InterruptObject) KeConnectInterrupt(PKINTERRUPT InterruptObject)
{ {
KIRQL oldlvl,synch_oldlvl; KIRQL oldlvl,synch_oldlvl;
@ -440,11 +441,11 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
Vector -= IRQ_BASE; Vector -= IRQ_BASE;
ASSERT (InterruptObject->ProcessorNumber < KeNumberProcessors); ASSERT (InterruptObject->Number < KeNumberProcessors);
KeSetSystemAffinityThread(1 << InterruptObject->ProcessorNumber); KeSetSystemAffinityThread(1 << InterruptObject->Number);
CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->ProcessorNumber]; CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl); KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
KiAcquireSpinLock(&CurrentIsr->Lock); KiAcquireSpinLock(&CurrentIsr->Lock);
@ -454,8 +455,8 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
*/ */
if (!IsListEmpty(&CurrentIsr->ListHead)) if (!IsListEmpty(&CurrentIsr->ListHead))
{ {
ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,Entry); ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
if (InterruptObject->Shareable == FALSE || ListHead->Shareable==FALSE) if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
{ {
KiReleaseSpinLock(&CurrentIsr->Lock); KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl); KeLowerIrql(oldlvl);
@ -468,13 +469,14 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink); DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink);
Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->InterruptMode); Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->Mode);
if (Result) if (Result)
{ {
InsertTailList(&CurrentIsr->ListHead,&InterruptObject->Entry); InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
DPRINT("%x %x\n",InterruptObject->Entry.Flink, InterruptObject->Entry.Blink); DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->Entry.Blink);
} }
InterruptObject->Connected = TRUE;
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl); KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
/* /*
@ -490,57 +492,72 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
return Result; return Result;
} }
/* /*
* @implemented * @implemented
*/ *
VOID STDCALL
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
/*
* FUNCTION: Releases a drivers isr * FUNCTION: Releases a drivers isr
* ARGUMENTS: * ARGUMENTS:
* InterruptObject = isr to release * InterruptObject = isr to release
*/ */
BOOLEAN
STDCALL
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
{ {
KIRQL oldlvl,synch_oldlvl; KIRQL oldlvl,synch_oldlvl;
PISR_TABLE CurrentIsr; PISR_TABLE CurrentIsr;
BOOLEAN State;
DPRINT("KeDisconnectInterrupt\n"); DPRINT1("KeDisconnectInterrupt\n");
ASSERT (InterruptObject->Number < KeNumberProcessors);
ASSERT (InterruptObject->ProcessorNumber < KeNumberProcessors); /* Set the affinity */
KeSetSystemAffinityThread(1 << InterruptObject->Number);
KeSetSystemAffinityThread(1 << InterruptObject->ProcessorNumber); /* Get the ISR Tabe */
CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE]
CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE][(ULONG)InterruptObject->ProcessorNumber]; [(ULONG)InterruptObject->Number];
/* Raise IRQL to required level and lock table */
KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl); KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
KiAcquireSpinLock(&CurrentIsr->Lock); KiAcquireSpinLock(&CurrentIsr->Lock);
/* Check if it's actually connected */
if ((State = InterruptObject->Connected))
{
/* Lock the Interrupt */
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject); synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
RemoveEntryList(&InterruptObject->Entry); /* Remove this one, and check if all are gone */
RemoveEntryList(&InterruptObject->InterruptListEntry);
if (IsListEmpty(&CurrentIsr->ListHead)) if (IsListEmpty(&CurrentIsr->ListHead))
{ {
HalDisableSystemInterrupt(InterruptObject->Vector, 0); /* Completely Disable the Interrupt */
HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
} }
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
/* /* Disconnect it */
* Release the table spinlock InterruptObject->Connected = FALSE;
*/
/* Release the interrupt lock */
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
}
/* Release the table spinlock */
KiReleaseSpinLock(&CurrentIsr->Lock); KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl); KeLowerIrql(oldlvl);
/* Go back to default affinity */
KeRevertToUserAffinityThread(); KeRevertToUserAffinityThread();
}
/* Return Old Interrupt State */
return State;
}
/* /*
* @implemented * @implemented
*/ */
VOID VOID
STDCALL STDCALL
KeInitializeInterrupt(PKINTERRUPT InterruptObject, KeInitializeInterrupt(PKINTERRUPT Interrupt,
PKSERVICE_ROUTINE ServiceRoutine, PKSERVICE_ROUTINE ServiceRoutine,
PVOID ServiceContext, PVOID ServiceContext,
PKSPIN_LOCK SpinLock, PKSPIN_LOCK SpinLock,
@ -552,16 +569,35 @@ KeInitializeInterrupt(PKINTERRUPT InterruptObject,
CHAR ProcessorNumber, CHAR ProcessorNumber,
BOOLEAN FloatingSave) BOOLEAN FloatingSave)
{ {
InterruptObject->ServiceRoutine = ServiceRoutine; /* Set the Interrupt Header */
InterruptObject->ServiceContext = ServiceContext; Interrupt->Type = InterruptObject;
InterruptObject->ActualLock = SpinLock; Interrupt->Size = sizeof(KINTERRUPT);
InterruptObject->Vector = Vector;
InterruptObject->Irql = Irql; /* Check if we got a spinlock */
InterruptObject->SynchLevel = SynchronizeIrql; if (SpinLock)
InterruptObject->InterruptMode = InterruptMode; {
InterruptObject->Shareable = ShareVector; Interrupt->ActualLock = SpinLock;
InterruptObject->ProcessorNumber = ProcessorNumber; }
InterruptObject->FloatingSave = FloatingSave; else
{
/* This means we'll be usin the built-in one */
KeInitializeSpinLock(&Interrupt->SpinLock);
Interrupt->ActualLock = &Interrupt->SpinLock;
}
/* Set the other settings */
Interrupt->ServiceRoutine = ServiceRoutine;
Interrupt->ServiceContext = ServiceContext;
Interrupt->Vector = Vector;
Interrupt->Irql = Irql;
Interrupt->SynchronizeIrql = SynchronizeIrql;
Interrupt->Mode = InterruptMode;
Interrupt->ShareVector = ShareVector;
Interrupt->Number = ProcessorNumber;
Interrupt->FloatingSave = FloatingSave;
/* Disconnect it at first */
Interrupt->Connected = FALSE;
} }
VOID KePrintInterruptStatistic(VOID) VOID KePrintInterruptStatistic(VOID)

View file

@ -62,8 +62,7 @@ KeAcquireInterruptSpinLock(
{ {
KIRQL oldIrql; KIRQL oldIrql;
//KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql); KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql);
KeRaiseIrql(Interrupt->SynchLevel, &oldIrql);
KiAcquireSpinLock(Interrupt->ActualLock); KiAcquireSpinLock(Interrupt->ActualLock);
return oldIrql; return oldIrql;
} }