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 Modified: trunk/reactos/include/ntos/kefuncs.h Modified: trunk/reactos/include/ntos/zwtypes.h Modified: trunk/reactos/ntoskrnl/io/irq.c Modified: trunk/reactos/ntoskrnl/ke/i386/irq.c Modified: trunk/reactos/ntoskrnl/ke/spinlock.c _____
Modified: trunk/reactos/include/ntos/kefuncs.h --- trunk/reactos/include/ntos/kefuncs.h 2005-06-22 21:55:43 UTC (rev 16228) +++ trunk/reactos/include/ntos/kefuncs.h 2005-06-22 23:10:15 UTC (rev 16229) @@ -62,7 +62,7 @@
KeConnectInterrupt( PKINTERRUPT InterruptObject);
-VOID STDCALL +BOOLEAN STDCALL KeDisconnectInterrupt( PKINTERRUPT InterruptObject);
_____
Modified: trunk/reactos/include/ntos/zwtypes.h --- trunk/reactos/include/ntos/zwtypes.h 2005-06-22 21:55:43 UTC (rev 16228) +++ trunk/reactos/include/ntos/zwtypes.h 2005-06-22 23:10:15 UTC (rev 16229) @@ -1781,23 +1781,49 @@
} LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION;
+#if 0 typedef struct _KINTERRUPT { - ULONG Vector; - KAFFINITY ProcessorEnableMask; - KSPIN_LOCK SpinLock; - PKSPIN_LOCK ActualLock; - BOOLEAN Shareable; - BOOLEAN FloatingSave; - CHAR ProcessorNumber; - PKSERVICE_ROUTINE ServiceRoutine; - PVOID ServiceContext; - LIST_ENTRY Entry; - KIRQL Irql; - KIRQL SynchLevel; - KINTERRUPT_MODE InterruptMode; + ULONG Vector; // Idem + KAFFINITY ProcessorEnableMask; // not needed + KSPIN_LOCK SpinLock; // Idem + PKSPIN_LOCK ActualLock; // Idem + BOOLEAN Shareable; // ShareVector + BOOLEAN FloatingSave; // Idem + 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; + PVOID ServiceContext; + KSPIN_LOCK SpinLock; + ULONG TickCount; + PKSPIN_LOCK ActualLock; + PVOID DispatchAddress; + ULONG Vector; + KIRQL Irql; + KIRQL SynchronizeIrql; + BOOLEAN FloatingSave; + BOOLEAN Connected; + CHAR Number; + UCHAR ShareVector; + KINTERRUPT_MODE Mode; + ULONG ServiceCount; + ULONG DispatchCount; + ULONG DispatchCode[106]; +} KINTERRUPT, *PKINTERRUPT; + #ifndef __USE_W32API
typedef struct _KINTERRUPT *PKINTERRUPT; _____
Modified: trunk/reactos/ntoskrnl/io/irq.c --- 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 */ _____
Modified: trunk/reactos/ntoskrnl/ke/i386/irq.c --- 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,InterruptListEnt ry); + 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->InterruptListEntr y); + 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) _____
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c --- trunk/reactos/ntoskrnl/ke/spinlock.c 2005-06-22 21:55:43 UTC (rev 16228) +++ trunk/reactos/ntoskrnl/ke/spinlock.c 2005-06-22 23:10:15 UTC (rev 16229) @@ -62,8 +62,7 @@
{ KIRQL oldIrql;
- //KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql); - KeRaiseIrql(Interrupt->SynchLevel, &oldIrql); + KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql); KiAcquireSpinLock(Interrupt->ActualLock); return oldIrql; }