2006-06-30 18:54:34 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2015-10-04 11:54:25 +00:00
|
|
|
* FILE: ntoskrnl/io/iomgr/irq.c
|
2006-06-30 18:54:34 +00:00
|
|
|
* PURPOSE: I/O Wrappers (called Completion Ports) for Kernel Queues
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2004-11-07 22:55:38 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2004-11-07 22:55:38 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
/*
|
2005-06-22 23:10:15 +00:00
|
|
|
* @implemented
|
2004-11-07 22:55:38 +00:00
|
|
|
*/
|
2006-06-30 18:54:34 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject,
|
|
|
|
IN PKSERVICE_ROUTINE ServiceRoutine,
|
|
|
|
IN PVOID ServiceContext,
|
|
|
|
IN PKSPIN_LOCK SpinLock,
|
|
|
|
IN ULONG Vector,
|
|
|
|
IN KIRQL Irql,
|
|
|
|
IN KIRQL SynchronizeIrql,
|
|
|
|
IN KINTERRUPT_MODE InterruptMode,
|
|
|
|
IN BOOLEAN ShareVector,
|
|
|
|
IN KAFFINITY ProcessorEnableMask,
|
|
|
|
IN BOOLEAN FloatingSave)
|
2004-11-07 22:55:38 +00:00
|
|
|
{
|
2005-06-22 23:10:15 +00:00
|
|
|
PKINTERRUPT Interrupt;
|
|
|
|
PKINTERRUPT InterruptUsed;
|
|
|
|
PIO_INTERRUPT IoInterrupt;
|
|
|
|
PKSPIN_LOCK SpinLockUsed;
|
2008-08-16 14:18:42 +00:00
|
|
|
BOOLEAN FirstRun;
|
2007-08-04 08:49:47 +00:00
|
|
|
CCHAR Count = 0;
|
|
|
|
KAFFINITY Affinity;
|
2005-06-22 23:10:15 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-06-30 18:54:34 +00:00
|
|
|
/* Assume failure */
|
|
|
|
*InterruptObject = NULL;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2007-08-04 08:49:47 +00:00
|
|
|
/* Get the affinity */
|
|
|
|
Affinity = ProcessorEnableMask & KeActiveProcessors;
|
|
|
|
while (Affinity)
|
2005-06-22 23:10:15 +00:00
|
|
|
{
|
2007-08-04 08:49:47 +00:00
|
|
|
/* Increase count */
|
|
|
|
if (Affinity & 1) Count++;
|
|
|
|
Affinity >>= 1;
|
2005-06-22 23:10:15 +00:00
|
|
|
}
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2007-08-04 08:49:47 +00:00
|
|
|
/* Make sure we have a valid CPU count */
|
|
|
|
if (!Count) return STATUS_INVALID_PARAMETER;
|
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Allocate the array of I/O Interrupts */
|
|
|
|
IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,
|
2007-08-04 08:49:47 +00:00
|
|
|
(Count - 1) * sizeof(KINTERRUPT) +
|
2005-06-22 23:10:15 +00:00
|
|
|
sizeof(IO_INTERRUPT),
|
|
|
|
TAG_KINTERRUPT);
|
2006-06-30 18:54:34 +00:00
|
|
|
if (!IoInterrupt) return STATUS_INSUFFICIENT_RESOURCES;
|
2005-06-22 23:10:15 +00:00
|
|
|
|
|
|
|
/* Select which Spinlock to use */
|
2006-06-30 18:54:34 +00:00
|
|
|
SpinLockUsed = SpinLock ? SpinLock : &IoInterrupt->SpinLock;
|
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* We first start with a built-in Interrupt inside the I/O Structure */
|
|
|
|
*InterruptObject = &IoInterrupt->FirstInterrupt;
|
|
|
|
Interrupt = (PKINTERRUPT)(IoInterrupt + 1);
|
|
|
|
FirstRun = TRUE;
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Start with a fresh structure */
|
|
|
|
RtlZeroMemory(IoInterrupt, sizeof(IO_INTERRUPT));
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Now create all the interrupts */
|
2007-08-04 15:52:17 +00:00
|
|
|
Affinity = ProcessorEnableMask & KeActiveProcessors;
|
2007-08-04 08:49:47 +00:00
|
|
|
for (Count = 0; Affinity; Count++, Affinity >>= 1)
|
2005-06-22 23:10:15 +00:00
|
|
|
{
|
|
|
|
/* Check if it's enabled for this CPU */
|
2007-08-04 08:49:47 +00:00
|
|
|
if (Affinity & 1)
|
2005-06-22 23:10:15 +00:00
|
|
|
{
|
|
|
|
/* Check which one we will use */
|
|
|
|
InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Initialize it */
|
|
|
|
KeInitializeInterrupt(InterruptUsed,
|
|
|
|
ServiceRoutine,
|
|
|
|
ServiceContext,
|
|
|
|
SpinLockUsed,
|
|
|
|
Vector,
|
|
|
|
Irql,
|
|
|
|
SynchronizeIrql,
|
|
|
|
InterruptMode,
|
|
|
|
ShareVector,
|
2007-08-04 08:49:47 +00:00
|
|
|
Count,
|
2005-06-22 23:10:15 +00:00
|
|
|
FloatingSave);
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Connect it */
|
|
|
|
if (!KeConnectInterrupt(InterruptUsed))
|
|
|
|
{
|
|
|
|
/* Check how far we got */
|
|
|
|
if (FirstRun)
|
|
|
|
{
|
|
|
|
/* We failed early so just free this */
|
2012-09-28 12:17:23 +00:00
|
|
|
ExFreePoolWithTag(IoInterrupt, TAG_KINTERRUPT);
|
2005-06-22 23:10:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Far enough, so disconnect everything */
|
|
|
|
IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
|
|
|
|
}
|
2006-06-30 18:54:34 +00:00
|
|
|
|
|
|
|
/* And fail */
|
2005-06-22 23:10:15 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Now we've used up our First Run */
|
|
|
|
if (FirstRun)
|
|
|
|
{
|
|
|
|
FirstRun = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Move on to the next one */
|
2007-08-04 08:49:47 +00:00
|
|
|
IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt++;
|
2005-06-22 23:10:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-11-07 22:55:38 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Return Success */
|
|
|
|
return STATUS_SUCCESS;
|
2004-11-07 22:55:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-06-22 23:10:15 +00:00
|
|
|
* @implemented
|
2004-11-07 22:55:38 +00:00
|
|
|
*/
|
2007-10-19 23:21:45 +00:00
|
|
|
VOID
|
2006-06-30 18:54:34 +00:00
|
|
|
NTAPI
|
2005-06-22 23:10:15 +00:00
|
|
|
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
|
|
|
|
{
|
2005-07-05 22:35:29 +00:00
|
|
|
LONG i;
|
2005-06-22 23:10:15 +00:00
|
|
|
PIO_INTERRUPT IoInterrupt;
|
|
|
|
PAGED_CODE();
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Get the I/O Interrupt */
|
2006-06-30 18:54:34 +00:00
|
|
|
IoInterrupt = CONTAINING_RECORD(InterruptObject,
|
|
|
|
IO_INTERRUPT,
|
2005-06-22 23:10:15 +00:00
|
|
|
FirstInterrupt);
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Disconnect the first one */
|
|
|
|
KeDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
|
|
|
|
|
|
|
|
/* Now disconnect the others */
|
|
|
|
for (i = 0; i < KeNumberProcessors; i++)
|
2005-01-01 11:28:46 +00:00
|
|
|
{
|
2006-06-30 18:54:34 +00:00
|
|
|
/* Make sure one was registered */
|
2005-06-22 23:10:15 +00:00
|
|
|
if (IoInterrupt->Interrupt[i])
|
2005-01-01 11:28:46 +00:00
|
|
|
{
|
2006-06-30 18:54:34 +00:00
|
|
|
/* Disconnect it */
|
2005-06-22 23:10:15 +00:00
|
|
|
KeDisconnectInterrupt(&InterruptObject[i]);
|
|
|
|
}
|
2005-01-01 11:28:46 +00:00
|
|
|
}
|
2006-06-30 18:54:34 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Free the I/O Interrupt */
|
2012-09-28 12:17:23 +00:00
|
|
|
ExFreePool(IoInterrupt); // ExFreePoolWithTag(IoInterrupt, TAG_KINTERRUPT);
|
2004-11-07 22:55:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|