--- trunk/reactos/ntoskrnl/io/irq.c 2005-06-22 21:55:43 UTC (rev 16228)
+++ trunk/reactos/ntoskrnl/io/irq.c 2005-06-22 23:10:15 UTC (rev 16229)
@@ -14,24 +14,17 @@
#define NDEBUG
#include <internal/debug.h>
+/* TYPES ********************************************************************/
+typedef struct _IO_INTERRUPT
+{
+ KINTERRUPT FirstInterrupt;
+ PKINTERRUPT Interrupt[MAXIMUM_PROCESSORS];
+ KSPIN_LOCK SpinLock;
+} IO_INTERRUPT, *PIO_INTERRUPT;
+
/* 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
* ARGUMENTS:
* InterruptObject (OUT) = Points to the interrupt object created on
@@ -57,106 +50,163 @@
* the isr runs. Must be false for x86 drivers
* RETURNS: Status
* 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;
- ULONG i, count;
+ PKINTERRUPT Interrupt;
+ PKINTERRUPT InterruptUsed;
+ PIO_INTERRUPT IoInterrupt;
+ PKSPIN_LOCK SpinLockUsed;
+ BOOLEAN FirstRun = TRUE;
+ ULONG i, count;
+
+ PAGED_CODE();
- ASSERT_IRQL(PASSIVE_LEVEL);
+ DPRINT1("IoConnectInterrupt(Vector %x)\n",Vector);
- DPRINT("IoConnectInterrupt(Vector %x)\n",Vector);
+ /* Convert the Mask */
+ ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1);
- ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1);
+ /* Make sure at least one CPU is on it */
+ if (!ProcessorEnableMask) return STATUS_INVALID_PARAMETER;
- if (ProcessorEnableMask == 0)
- {
- return STATUS_INVALID_PARAMETER;
- }
+ /* Determine the allocation */
+ for (i = 0, count = 0; i < KeNumberProcessors; i++)
+ {
+ if (ProcessorEnableMask & (1 << i)) count++;
+ }
+
+ /* Allocate the array of I/O Interrupts */
+ IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,
+ (count - 1)* sizeof(KINTERRUPT) +
+ sizeof(IO_INTERRUPT),
+ TAG_KINTERRUPT);
+ if (!Interrupt) return(STATUS_INSUFFICIENT_RESOURCES);
- for (i = 0, count = 0; i < KeNumberProcessors; i++)
- {
- if (ProcessorEnableMask & (1 << i))
- {
- count++;
- }
- }
- /*
- * Initialize interrupt object
- */
- Interrupt=ExAllocatePoolWithTag(NonPagedPool,count*sizeof(KINTERRUPT),
- TAG_KINTERRUPT);
- if (Interrupt==NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
+ /* Select which Spinlock to use */
+ if (SpinLock)
+ {
+ SpinLockUsed = SpinLock;
+ }
+ else
+ {
+ SpinLockUsed = &IoInterrupt->SpinLock;
+ }
+
+ /* We first start with a built-in Interrupt inside the I/O Structure */
+ *InterruptObject = &IoInterrupt->FirstInterrupt;
+ Interrupt = (PKINTERRUPT)(IoInterrupt + 1);
+ FirstRun = TRUE;
+
+ /* Start with a fresh structure */
+ RtlZeroMemory(IoInterrupt, sizeof(IO_INTERRUPT));
+
+ /* Now create all the interrupts */
+ for (i = 0; i < KeNumberProcessors; i++)
+ {
+ /* Check if it's enabled for this CPU */
+ if (ProcessorEnableMask & (1 << i))
+ {
+ /* Check which one we will use */
+ InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;
+
+ /* Initialize it */
+ KeInitializeInterrupt(InterruptUsed,
+ ServiceRoutine,
+ ServiceContext,
+ SpinLockUsed,
+ Vector,
+ Irql,
+ SynchronizeIrql,
+ InterruptMode,
+ ShareVector,
+ i,
+ FloatingSave);
+
+ /* Connect it */
+ if (!KeConnectInterrupt(InterruptUsed))
+ {
+ /* Check how far we got */
+ if (FirstRun)
+ {
+ /* We failed early so just free this */
+ ExFreePool(IoInterrupt);
+ }
+ else
+ {
+ /* Far enough, so disconnect everything */
+ IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
+ }
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Now we've used up our First Run */
+ if (FirstRun)
+ {
+ FirstRun = FALSE;
+ }
+ else
+ {
+ /* Move on to the next one */
+ IoInterrupt->Interrupt[i] = Interrupt++;
+ }
+ }
+ }
- if (SpinLock == NULL)
- {
- SpinLock = &Interrupt[0].SpinLock;
- KeInitializeSpinLock(SpinLock);
- }
-
- Interrupt[0].ProcessorEnableMask = ProcessorEnableMask;
-
- for (i = 0, count = 0; i < KeNumberProcessors; i++)
- {
- if (ProcessorEnableMask & (1 << i))
- {
- KeInitializeInterrupt(&Interrupt[count],
- ServiceRoutine,
- ServiceContext,
- SpinLock,
- Vector,
- Irql,
- SynchronizeIrql,
- InterruptMode,
- ShareVector,
- i,
- FloatingSave);
- if (!KeConnectInterrupt(&Interrupt[count]))
- {
- for (i = 0; i < count; i++)
- {
- if (ProcessorEnableMask & (1 << i))
- {
- KeDisconnectInterrupt(&Interrupt[i]);
- }
- }
- ExFreePool(Interrupt);
- return STATUS_INVALID_PARAMETER;
- }
- count++;
- }
- }
-
- *InterruptObject = Interrupt;
-
- return(STATUS_SUCCESS);
+ /* Return Success */
+ return STATUS_SUCCESS;
}
-
/*
- * @implemented
- */
-VOID STDCALL
-IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
-/*
* FUNCTION: Releases a drivers isr
* ARGUMENTS:
* InterruptObject = isr to release
+ *
+ * @implemented
*/
+VOID
+STDCALL
+IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
+
{
- ULONG i, count;
+ 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);
- for (i = 0, count = 0; i < KeNumberProcessors; i++)
+ /* Now disconnect the others */
+ for (i = 0; i < KeNumberProcessors; i++)
{
- if (InterruptObject[0].ProcessorEnableMask & (1 << i))
+ if (IoInterrupt->Interrupt[i])
{
- KeDisconnectInterrupt(&InterruptObject[count]);
- count++;
- }
+ KeDisconnectInterrupt(&InterruptObject[i]);
+ }
}
- ExFreePool(InterruptObject);
+
+ /* Free the I/O Interrupt */
+ ExFreePool(IoInterrupt);
}
/* EOF */
--- trunk/reactos/ntoskrnl/ke/i386/irq.c 2005-06-22 21:55:43 UTC (rev 16228)
+++ trunk/reactos/ntoskrnl/ke/i386/irq.c 2005-06-22 23:10:15 UTC (rev 16229)
@@ -278,7 +278,7 @@
while (current != &CurrentIsr->ListHead)
{
- isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
+ isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
oldlvl = KeAcquireInterruptSpinLock(isr);
if (isr->ServiceRoutine(isr, isr->ServiceContext))
{
@@ -401,7 +401,7 @@
KiAcquireSpinLock(&IsrTable[i][j].Lock);
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))
{
if (printed == FALSE)
@@ -411,7 +411,7 @@
}
DPRINT(" Isr %x\n",current);
current_entry = current_entry->Flink;
- current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry);
+ current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
}
KiReleaseSpinLock(&IsrTable[i][j].Lock);
}
@@ -422,7 +422,8 @@
/*
* @implemented
*/
-BOOLEAN STDCALL
+BOOLEAN
+STDCALL
KeConnectInterrupt(PKINTERRUPT InterruptObject)
{
KIRQL oldlvl,synch_oldlvl;
@@ -440,11 +441,11 @@
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);
KiAcquireSpinLock(&CurrentIsr->Lock);
@@ -454,8 +455,8 @@
*/
if (!IsListEmpty(&CurrentIsr->ListHead))
{
- ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,Entry);
- if (InterruptObject->Shareable == FALSE || ListHead->Shareable==FALSE)
+ ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
+ if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
{
KiReleaseSpinLock(&CurrentIsr->Lock);
KeLowerIrql(oldlvl);
@@ -468,13 +469,14 @@
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)
{
- InsertTailList(&CurrentIsr->ListHead,&InterruptObject->Entry);
- DPRINT("%x %x\n",InterruptObject->Entry.Flink, InterruptObject->Entry.Blink);
+ InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
+ DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->Entry.Blink);
}
+ InterruptObject->Connected = TRUE;
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
/*
@@ -490,78 +492,112 @@
return Result;
}
-
/*
* @implemented
- */
-VOID STDCALL
-KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
-/*
+ *
* FUNCTION: Releases a drivers isr
* ARGUMENTS:
* InterruptObject = isr to release
*/
+BOOLEAN
+STDCALL
+KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
{
- KIRQL oldlvl,synch_oldlvl;
- PISR_TABLE CurrentIsr;
+ KIRQL oldlvl,synch_oldlvl;
+ 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]
+ [(ULONG)InterruptObject->Number];
- CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE][(ULONG)InterruptObject->ProcessorNumber];
+ /* Raise IRQL to required level and lock table */
+ KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
+ KiAcquireSpinLock(&CurrentIsr->Lock);
- KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
- KiAcquireSpinLock(&CurrentIsr->Lock);
+ /* Check if it's actually connected */
+ if ((State = InterruptObject->Connected))
+ {
+ /* Lock the Interrupt */
+ synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
- synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
+ /* Remove this one, and check if all are gone */
+ RemoveEntryList(&InterruptObject->InterruptListEntry);
+ if (IsListEmpty(&CurrentIsr->ListHead))
+ {
+ /* Completely Disable the Interrupt */
+ HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
+ }
+
+ /* Disconnect it */
+ InterruptObject->Connected = FALSE;
+
+ /* Release the interrupt lock */
+ KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
+ }
+ /* Release the table spinlock */
+ KiReleaseSpinLock(&CurrentIsr->Lock);
+ KeLowerIrql(oldlvl);
- RemoveEntryList(&InterruptObject->Entry);
- if (IsListEmpty(&CurrentIsr->ListHead))
- {
- HalDisableSystemInterrupt(InterruptObject->Vector, 0);
- }
- KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
-
- /*
- * Release the table spinlock
- */
- KiReleaseSpinLock(&CurrentIsr->Lock);
- KeLowerIrql(oldlvl);
-
- KeRevertToUserAffinityThread();
+ /* Go back to default affinity */
+ KeRevertToUserAffinityThread();
+
+ /* Return Old Interrupt State */
+ return State;
}
-
/*
* @implemented
*/
VOID
STDCALL
-KeInitializeInterrupt(PKINTERRUPT InterruptObject,
- PKSERVICE_ROUTINE ServiceRoutine,
- PVOID ServiceContext,
- PKSPIN_LOCK SpinLock,
- ULONG Vector,
- KIRQL Irql,
- KIRQL SynchronizeIrql,
- KINTERRUPT_MODE InterruptMode,
- BOOLEAN ShareVector,
- CHAR ProcessorNumber,
- BOOLEAN FloatingSave)
+KeInitializeInterrupt(PKINTERRUPT Interrupt,
+ PKSERVICE_ROUTINE ServiceRoutine,
+ PVOID ServiceContext,
+ PKSPIN_LOCK SpinLock,
+ ULONG Vector,
+ KIRQL Irql,
+ KIRQL SynchronizeIrql,
+ KINTERRUPT_MODE InterruptMode,
+ BOOLEAN ShareVector,
+ CHAR ProcessorNumber,
+ BOOLEAN FloatingSave)
{
- InterruptObject->ServiceRoutine = ServiceRoutine;
- InterruptObject->ServiceContext = ServiceContext;
- InterruptObject->ActualLock = SpinLock;
- InterruptObject->Vector = Vector;
- InterruptObject->Irql = Irql;
- InterruptObject->SynchLevel = SynchronizeIrql;
- InterruptObject->InterruptMode = InterruptMode;
- InterruptObject->Shareable = ShareVector;
- InterruptObject->ProcessorNumber = ProcessorNumber;
- InterruptObject->FloatingSave = FloatingSave;
+ /* Set the Interrupt Header */
+ Interrupt->Type = InterruptObject;
+ Interrupt->Size = sizeof(KINTERRUPT);
+
+ /* Check if we got a spinlock */
+ if (SpinLock)
+ {
+ Interrupt->ActualLock = SpinLock;
+ }
+ 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)