2005-02-08 01:46:01 +00:00
|
|
|
/* $Id$
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
1998-08-25 04:27:26 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
2000-07-10 21:55:49 +00:00
|
|
|
* FILE: ntoskrnl/ke/i386/irq.c
|
1998-08-25 04:27:26 +00:00
|
|
|
* PURPOSE: IRQ handling
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2000-07-10 21:55:49 +00:00
|
|
|
* NOTE: In general the PIC interrupt priority facilities are used to
|
1998-08-25 04:27:26 +00:00
|
|
|
* preserve the NT IRQL semantics, global interrupt disables are only used
|
|
|
|
* to keep the PIC in a consistent state
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2004-11-01 14:37:19 +00:00
|
|
|
#include <../hal/halx86/include/halirq.h>
|
2006-05-10 17:47:44 +00:00
|
|
|
#include <../hal/halx86/include/mps.h>
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <internal/debug.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2006-08-23 19:02:00 +00:00
|
|
|
extern ULONG KiInterruptTemplate[KINTERRUPT_DISPATCH_CODES];
|
|
|
|
extern PULONG KiInterruptTemplateObject;
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
|
2005-07-05 16:40:01 +00:00
|
|
|
/* Interrupt handler list */
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2005-07-05 16:40:01 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2001-04-13 16:12:26 +00:00
|
|
|
|
|
|
|
#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum
|
|
|
|
|
|
|
|
#define BUILD_INTERRUPT_HANDLER(intnum) \
|
2005-07-05 16:40:01 +00:00
|
|
|
VOID INT_NAME2(intnum)(VOID);
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2005-07-05 16:40:01 +00:00
|
|
|
#define D(x,y) \
|
2001-04-13 16:12:26 +00:00
|
|
|
BUILD_INTERRUPT_HANDLER(x##y)
|
|
|
|
|
2005-07-05 16:40:01 +00:00
|
|
|
#define D16(x) \
|
|
|
|
D(x,0) D(x,1) D(x,2) D(x,3) \
|
|
|
|
D(x,4) D(x,5) D(x,6) D(x,7) \
|
|
|
|
D(x,8) D(x,9) D(x,A) D(x,B) \
|
|
|
|
D(x,C) D(x,D) D(x,E) D(x,F)
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2005-07-05 16:40:01 +00:00
|
|
|
D16(3) D16(4) D16(5) D16(6)
|
|
|
|
D16(7) D16(8) D16(9) D16(A)
|
|
|
|
D16(B) D16(C) D16(D) D16(E)
|
|
|
|
D16(F)
|
2001-04-13 16:12:26 +00:00
|
|
|
|
|
|
|
#define L(x,y) \
|
2001-04-16 16:29:03 +00:00
|
|
|
(ULONG)& INT_NAME2(x##y)
|
2001-04-13 16:12:26 +00:00
|
|
|
|
|
|
|
#define L16(x) \
|
2005-11-02 23:12:55 +00:00
|
|
|
L(x,0), L(x,1), L(x,2), L(x,3), \
|
|
|
|
L(x,4), L(x,5), L(x,6), L(x,7), \
|
|
|
|
L(x,8), L(x,9), L(x,A), L(x,B), \
|
|
|
|
L(x,C), L(x,D), L(x,E), L(x,F)
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2004-11-01 19:01:25 +00:00
|
|
|
static ULONG irq_handler[ROUND_UP(NR_IRQS, 16)] = {
|
2001-04-13 16:12:26 +00:00
|
|
|
L16(3), L16(4), L16(5), L16(6),
|
|
|
|
L16(7), L16(8), L16(9), L16(A),
|
2004-11-01 19:01:25 +00:00
|
|
|
L16(B), L16(C), L16(D), L16(E)
|
2001-04-13 16:12:26 +00:00
|
|
|
};
|
|
|
|
|
2001-04-16 16:29:03 +00:00
|
|
|
#undef L
|
|
|
|
#undef L16
|
2005-07-05 16:40:01 +00:00
|
|
|
#undef D
|
|
|
|
#undef D16
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2005-01-05 19:25:49 +00:00
|
|
|
#else /* CONFIG_SMP */
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2005-07-05 16:40:01 +00:00
|
|
|
void irq_handler_0(void);
|
|
|
|
void irq_handler_1(void);
|
|
|
|
void irq_handler_2(void);
|
|
|
|
void irq_handler_3(void);
|
|
|
|
void irq_handler_4(void);
|
|
|
|
void irq_handler_5(void);
|
|
|
|
void irq_handler_6(void);
|
|
|
|
void irq_handler_7(void);
|
|
|
|
void irq_handler_8(void);
|
|
|
|
void irq_handler_9(void);
|
|
|
|
void irq_handler_10(void);
|
|
|
|
void irq_handler_11(void);
|
|
|
|
void irq_handler_12(void);
|
|
|
|
void irq_handler_13(void);
|
|
|
|
void irq_handler_14(void);
|
|
|
|
void irq_handler_15(void);
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2006-08-23 16:58:43 +00:00
|
|
|
unsigned int irq_handler[NR_IRQS]=
|
2005-07-05 16:40:01 +00:00
|
|
|
{
|
|
|
|
(int)&irq_handler_0,
|
|
|
|
(int)&irq_handler_1,
|
|
|
|
(int)&irq_handler_2,
|
|
|
|
(int)&irq_handler_3,
|
|
|
|
(int)&irq_handler_4,
|
|
|
|
(int)&irq_handler_5,
|
|
|
|
(int)&irq_handler_6,
|
|
|
|
(int)&irq_handler_7,
|
|
|
|
(int)&irq_handler_8,
|
|
|
|
(int)&irq_handler_9,
|
|
|
|
(int)&irq_handler_10,
|
|
|
|
(int)&irq_handler_11,
|
|
|
|
(int)&irq_handler_12,
|
|
|
|
(int)&irq_handler_13,
|
|
|
|
(int)&irq_handler_14,
|
|
|
|
(int)&irq_handler_15,
|
|
|
|
};
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2005-01-05 19:25:49 +00:00
|
|
|
#endif /* CONFIG_SMP */
|
2001-04-13 16:12:26 +00:00
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
* PURPOSE: Object describing each isr
|
1998-08-25 04:27:26 +00:00
|
|
|
* NOTE: The data in this table is only modified at passsive level but can
|
|
|
|
* be accessed at any irq level.
|
|
|
|
*/
|
2000-07-10 21:55:49 +00:00
|
|
|
|
2005-01-01 11:28:46 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
LIST_ENTRY ListHead;
|
|
|
|
KSPIN_LOCK Lock;
|
|
|
|
ULONG Count;
|
|
|
|
}
|
|
|
|
ISR_TABLE, *PISR_TABLE;
|
|
|
|
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-01-01 11:28:46 +00:00
|
|
|
static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS];
|
|
|
|
#else
|
|
|
|
static ISR_TABLE IsrTable[NR_IRQS][1];
|
|
|
|
#endif
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2001-03-07 16:48:45 +00:00
|
|
|
#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L')
|
2006-01-17 17:28:41 +00:00
|
|
|
extern IDT_DESCRIPTOR KiIdt[256];
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2000-07-10 21:55:49 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
|
|
#define PRESENT (0x8000)
|
|
|
|
#define I486_INTERRUPT_GATE (0xe00)
|
|
|
|
|
2005-09-14 01:44:19 +00:00
|
|
|
VOID
|
|
|
|
INIT_FUNCTION
|
|
|
|
NTAPI
|
2003-10-12 17:05:50 +00:00
|
|
|
KeInitInterrupts (VOID)
|
2000-07-10 21:55:49 +00:00
|
|
|
{
|
2005-01-01 11:28:46 +00:00
|
|
|
int i, j;
|
|
|
|
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2000-07-10 21:55:49 +00:00
|
|
|
/*
|
|
|
|
* Setup the IDT entries to point to the interrupt handlers
|
|
|
|
*/
|
|
|
|
for (i=0;i<NR_IRQS;i++)
|
|
|
|
{
|
2005-11-27 03:08:35 +00:00
|
|
|
KiIdt[IRQ_BASE+i].a=(irq_handler[i]&0xffff)+(KGDT_R0_CODE<<16);
|
2005-11-02 23:12:55 +00:00
|
|
|
KiIdt[IRQ_BASE+i].b=(irq_handler[i]&0xffff0000)+PRESENT+
|
|
|
|
I486_INTERRUPT_GATE;
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-11-02 23:12:55 +00:00
|
|
|
for (j = 0; j < MAXIMUM_PROCESSORS; j++)
|
2005-01-01 11:28:46 +00:00
|
|
|
#else
|
2005-11-02 23:12:55 +00:00
|
|
|
j = 0;
|
2005-01-01 11:28:46 +00:00
|
|
|
#endif
|
2005-11-02 23:12:55 +00:00
|
|
|
{
|
|
|
|
InitializeListHead(&IsrTable[i][j].ListHead);
|
2005-01-01 11:28:46 +00:00
|
|
|
KeInitializeSpinLock(&IsrTable[i][j].Lock);
|
2005-11-02 23:12:55 +00:00
|
|
|
IsrTable[i][j].Count = 0;
|
|
|
|
}
|
2000-07-10 21:55:49 +00:00
|
|
|
}
|
|
|
|
}
|
2000-06-29 23:35:53 +00:00
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
STATIC VOID
|
2002-01-23 23:39:26 +00:00
|
|
|
KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
|
2005-11-02 23:12:55 +00:00
|
|
|
PKTRAP_FRAME TrapFrame)
|
2002-01-23 23:39:26 +00:00
|
|
|
{
|
2005-11-27 19:21:19 +00:00
|
|
|
TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs;
|
|
|
|
TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs;
|
|
|
|
TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es;
|
|
|
|
TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds;
|
2002-01-23 23:39:26 +00:00
|
|
|
TrapFrame->Eax = IrqTrapFrame->Eax;
|
|
|
|
TrapFrame->Ecx = IrqTrapFrame->Ecx;
|
|
|
|
TrapFrame->Edx = IrqTrapFrame->Edx;
|
|
|
|
TrapFrame->Ebx = IrqTrapFrame->Ebx;
|
2005-11-27 19:21:19 +00:00
|
|
|
TrapFrame->HardwareEsp = IrqTrapFrame->Esp;
|
2002-01-23 23:39:26 +00:00
|
|
|
TrapFrame->Ebp = IrqTrapFrame->Ebp;
|
|
|
|
TrapFrame->Esi = IrqTrapFrame->Esi;
|
|
|
|
TrapFrame->Edi = IrqTrapFrame->Edi;
|
|
|
|
TrapFrame->Eip = IrqTrapFrame->Eip;
|
2005-11-27 19:21:19 +00:00
|
|
|
TrapFrame->SegCs = IrqTrapFrame->Cs;
|
|
|
|
TrapFrame->EFlags = IrqTrapFrame->Eflags;
|
2002-01-23 23:39:26 +00:00
|
|
|
}
|
|
|
|
|
2002-12-09 18:40:45 +00:00
|
|
|
VOID STDCALL
|
2003-04-06 10:45:16 +00:00
|
|
|
KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
|
2002-12-09 18:40:45 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Calls all the interrupt handlers for a given irq.
|
|
|
|
* ARGUMENTS:
|
2003-04-06 10:45:16 +00:00
|
|
|
* vector - The number of the vector to call handlers for.
|
2002-12-09 18:40:45 +00:00
|
|
|
* old_level - The irql of the processor when the irq took place.
|
|
|
|
* NOTES: Must be called at DIRQL.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
PKINTERRUPT isr;
|
|
|
|
PLIST_ENTRY current;
|
2005-01-01 11:28:46 +00:00
|
|
|
KIRQL oldlvl;
|
|
|
|
PISR_TABLE CurrentIsr;
|
2002-12-09 18:40:45 +00:00
|
|
|
|
2004-10-31 23:57:15 +00:00
|
|
|
DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level);
|
2002-12-09 18:40:45 +00:00
|
|
|
|
2004-10-30 23:48:57 +00:00
|
|
|
/*
|
|
|
|
* Iterate the list until one of the isr tells us its device interrupted
|
|
|
|
*/
|
2005-01-01 11:28:46 +00:00
|
|
|
CurrentIsr = &IsrTable[vector - IRQ_BASE][(ULONG)KeGetCurrentProcessorNumber()];
|
|
|
|
|
|
|
|
KiAcquireSpinLock(&CurrentIsr->Lock);
|
2004-10-30 23:48:57 +00:00
|
|
|
|
2005-01-01 11:28:46 +00:00
|
|
|
CurrentIsr->Count++;
|
|
|
|
current = CurrentIsr->ListHead.Flink;
|
|
|
|
|
|
|
|
while (current != &CurrentIsr->ListHead)
|
2002-12-09 18:40:45 +00:00
|
|
|
{
|
2005-06-22 23:10:15 +00:00
|
|
|
isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
|
2005-01-01 11:28:46 +00:00
|
|
|
oldlvl = KeAcquireInterruptSpinLock(isr);
|
|
|
|
if (isr->ServiceRoutine(isr, isr->ServiceContext))
|
|
|
|
{
|
|
|
|
KeReleaseInterruptSpinLock(isr, oldlvl);
|
2005-11-02 23:12:55 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-01-01 11:28:46 +00:00
|
|
|
KeReleaseInterruptSpinLock(isr, oldlvl);
|
|
|
|
current = current->Flink;
|
2004-10-30 23:48:57 +00:00
|
|
|
}
|
2005-01-01 11:28:46 +00:00
|
|
|
KiReleaseSpinLock(&CurrentIsr->Lock);
|
2002-12-09 18:40:45 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2004-11-01 14:37:19 +00:00
|
|
|
KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Calls the irq specific handler for an irq
|
|
|
|
* ARGUMENTS:
|
2000-07-10 21:55:49 +00:00
|
|
|
* irq = IRQ that has interrupted
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
{
|
|
|
|
KIRQL old_level;
|
2003-06-07 19:13:43 +00:00
|
|
|
KTRAP_FRAME KernelTrapFrame;
|
2002-05-02 23:45:33 +00:00
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
2002-05-02 23:45:33 +00:00
|
|
|
* At this point we have interrupts disabled, nothing has been done to
|
|
|
|
* the PIC.
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2005-03-12 09:40:07 +00:00
|
|
|
KeGetCurrentPrcb()->InterruptCount++;
|
2001-04-13 16:12:26 +00:00
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
2002-05-02 23:45:33 +00:00
|
|
|
* Notify the rest of the kernel of the raised irq level. For the
|
|
|
|
* default HAL this will send an EOI to the PIC and alter the IRQL.
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2006-05-27 15:38:37 +00:00
|
|
|
if (!HalBeginSystemInterrupt (VECTOR2IRQL(vector),
|
|
|
|
vector,
|
2005-11-02 23:12:55 +00:00
|
|
|
&old_level))
|
2001-03-14 23:19:14 +00:00
|
|
|
{
|
2002-05-02 23:45:33 +00:00
|
|
|
return;
|
2001-03-14 23:19:14 +00:00
|
|
|
}
|
2002-05-02 23:45:33 +00:00
|
|
|
|
2003-06-11 18:38:44 +00:00
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
2002-05-02 23:45:33 +00:00
|
|
|
* Enable interrupts
|
|
|
|
* NOTE: Only higher priority interrupts will get through
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2004-03-09 21:49:54 +00:00
|
|
|
Ke386EnableInterrupts();
|
2002-05-02 23:45:33 +00:00
|
|
|
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifndef CONFIG_SMP
|
2004-11-01 14:37:19 +00:00
|
|
|
if (VECTOR2IRQ(vector) == 0)
|
2004-10-01 20:09:57 +00:00
|
|
|
{
|
2006-08-23 18:09:44 +00:00
|
|
|
//DPRINT1("Tick\n");
|
2004-10-30 23:48:57 +00:00
|
|
|
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
2004-11-01 14:37:19 +00:00
|
|
|
KeUpdateSystemTime(&KernelTrapFrame, old_level);
|
2004-10-01 20:09:57 +00:00
|
|
|
}
|
|
|
|
else
|
2004-11-01 14:37:19 +00:00
|
|
|
#endif
|
2004-10-01 20:09:57 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Actually call the ISR.
|
|
|
|
*/
|
2004-11-01 14:37:19 +00:00
|
|
|
KiInterruptDispatch2(vector, old_level);
|
2004-10-01 20:09:57 +00:00
|
|
|
}
|
2002-05-02 23:45:33 +00:00
|
|
|
|
2003-01-02 16:06:49 +00:00
|
|
|
/*
|
|
|
|
* End the system interrupt.
|
|
|
|
*/
|
2004-03-09 21:49:54 +00:00
|
|
|
Ke386DisableInterrupts();
|
2006-08-23 18:09:44 +00:00
|
|
|
HalEndSystemInterrupt (old_level, 0);
|
1998-09-05 17:34:23 +00:00
|
|
|
}
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-06-22 23:10:15 +00:00
|
|
|
BOOLEAN
|
|
|
|
STDCALL
|
2000-07-10 21:55:49 +00:00
|
|
|
KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
|
|
|
{
|
2005-01-01 11:28:46 +00:00
|
|
|
KIRQL oldlvl,synch_oldlvl;
|
2000-07-10 21:55:49 +00:00
|
|
|
PKINTERRUPT ListHead;
|
|
|
|
ULONG Vector;
|
2005-01-01 11:28:46 +00:00
|
|
|
PISR_TABLE CurrentIsr;
|
|
|
|
BOOLEAN Result;
|
2000-07-10 21:55:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
Vector = InterruptObject->Vector;
|
2006-08-23 19:02:00 +00:00
|
|
|
DPRINT1("KeConnectInterrupt(): %lx\n", Vector);
|
2000-07-10 21:55:49 +00:00
|
|
|
|
2005-01-25 05:00:57 +00:00
|
|
|
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
|
2004-11-07 22:55:38 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2004-11-01 14:37:19 +00:00
|
|
|
Vector -= IRQ_BASE;
|
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
ASSERT (InterruptObject->Number < KeNumberProcessors);
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
KeSetSystemAffinityThread(1 << InterruptObject->Number);
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
|
2005-01-01 11:28:46 +00:00
|
|
|
|
|
|
|
KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
|
|
|
|
KiAcquireSpinLock(&CurrentIsr->Lock);
|
|
|
|
|
2000-07-10 21:55:49 +00:00
|
|
|
/*
|
|
|
|
* Check if the vector is already in use that we can share it
|
|
|
|
*/
|
2005-01-01 11:28:46 +00:00
|
|
|
if (!IsListEmpty(&CurrentIsr->ListHead))
|
2004-11-27 19:24:15 +00:00
|
|
|
{
|
2005-06-22 23:10:15 +00:00
|
|
|
ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
|
|
|
|
if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
|
2005-01-01 11:28:46 +00:00
|
|
|
{
|
|
|
|
KiReleaseSpinLock(&CurrentIsr->Lock);
|
|
|
|
KeLowerIrql(oldlvl);
|
|
|
|
KeRevertToUserAffinityThread();
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-11-27 19:24:15 +00:00
|
|
|
}
|
2000-07-10 21:55:49 +00:00
|
|
|
|
2005-01-01 11:28:46 +00:00
|
|
|
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
|
|
|
|
|
2005-01-01 14:35:46 +00:00
|
|
|
DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink);
|
2000-07-10 21:55:49 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->Mode);
|
2005-01-01 11:28:46 +00:00
|
|
|
if (Result)
|
2002-12-09 19:53:44 +00:00
|
|
|
{
|
2005-06-22 23:10:15 +00:00
|
|
|
InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
|
2005-07-04 21:46:20 +00:00
|
|
|
DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->InterruptListEntry.Blink);
|
2002-12-09 19:53:44 +00:00
|
|
|
}
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
InterruptObject->Connected = TRUE;
|
2005-01-01 11:28:46 +00:00
|
|
|
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
|
|
|
|
|
2000-07-10 21:55:49 +00:00
|
|
|
/*
|
|
|
|
* Release the table spinlock
|
|
|
|
*/
|
2005-01-01 11:28:46 +00:00
|
|
|
KiReleaseSpinLock(&CurrentIsr->Lock);
|
|
|
|
KeLowerIrql(oldlvl);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-01-01 11:28:46 +00:00
|
|
|
KeRevertToUserAffinityThread();
|
|
|
|
|
|
|
|
return Result;
|
2000-07-10 21:55:49 +00:00
|
|
|
}
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
2005-06-22 23:10:15 +00:00
|
|
|
*
|
2000-07-10 21:55:49 +00:00
|
|
|
* FUNCTION: Releases a drivers isr
|
|
|
|
* ARGUMENTS:
|
|
|
|
* InterruptObject = isr to release
|
|
|
|
*/
|
2005-06-22 23:10:15 +00:00
|
|
|
BOOLEAN
|
|
|
|
STDCALL
|
|
|
|
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
|
2000-07-10 21:55:49 +00:00
|
|
|
{
|
2005-06-22 23:10:15 +00:00
|
|
|
KIRQL oldlvl,synch_oldlvl;
|
|
|
|
PISR_TABLE CurrentIsr;
|
|
|
|
BOOLEAN State;
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
DPRINT1("KeDisconnectInterrupt\n");
|
|
|
|
ASSERT (InterruptObject->Number < KeNumberProcessors);
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Set the affinity */
|
|
|
|
KeSetSystemAffinityThread(1 << InterruptObject->Number);
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Get the ISR Tabe */
|
|
|
|
CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE]
|
|
|
|
[(ULONG)InterruptObject->Number];
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Raise IRQL to required level and lock table */
|
|
|
|
KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
|
|
|
|
KiAcquireSpinLock(&CurrentIsr->Lock);
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Check if it's actually connected */
|
|
|
|
if ((State = InterruptObject->Connected))
|
|
|
|
{
|
|
|
|
/* Lock the Interrupt */
|
|
|
|
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* Go back to default affinity */
|
|
|
|
KeRevertToUserAffinityThread();
|
|
|
|
|
|
|
|
/* Return Old Interrupt State */
|
|
|
|
return State;
|
2000-07-10 21:55:49 +00:00
|
|
|
}
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-01-01 11:28:46 +00:00
|
|
|
VOID
|
2000-07-10 21:55:49 +00:00
|
|
|
STDCALL
|
2005-06-22 23:10:15 +00:00
|
|
|
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)
|
2000-07-10 21:55:49 +00:00
|
|
|
{
|
2006-08-23 19:02:00 +00:00
|
|
|
ULONG i;
|
|
|
|
PULONG DispatchCode = &Interrupt->DispatchCode[0], Patch = DispatchCode;
|
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Set the Interrupt Header */
|
|
|
|
Interrupt->Type = InterruptObject;
|
|
|
|
Interrupt->Size = sizeof(KINTERRUPT);
|
2006-08-23 19:02:00 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2006-08-23 19:02:00 +00:00
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* 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;
|
2006-08-23 19:02:00 +00:00
|
|
|
|
|
|
|
/* Loop the template in memory */
|
|
|
|
for (i = 0; i < KINTERRUPT_DISPATCH_CODES; i++)
|
|
|
|
{
|
|
|
|
/* Copy the dispatch code */
|
|
|
|
*DispatchCode++ = KiInterruptTemplate[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Jump to the last 4 bytes */
|
|
|
|
Patch = (PULONG)((ULONG_PTR)Patch +
|
|
|
|
((ULONG_PTR)&KiInterruptTemplateObject -
|
|
|
|
(ULONG_PTR)KiInterruptTemplate) - 4);
|
|
|
|
|
|
|
|
/* Apply the patch */
|
|
|
|
*Patch = PtrToUlong(Interrupt);
|
|
|
|
|
2005-06-22 23:10:15 +00:00
|
|
|
/* Disconnect it at first */
|
|
|
|
Interrupt->Connected = FALSE;
|
2005-01-01 11:28:46 +00:00
|
|
|
}
|
2000-07-10 21:55:49 +00:00
|
|
|
|
2000-03-19 13:35:38 +00:00
|
|
|
/* EOF */
|