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)
|
2005-01-01 11:28:46 +00:00
|
|
|
* Hartmut Birr
|
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>
|
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
|
|
|
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2001-04-13 16:12:26 +00:00
|
|
|
|
|
|
|
#define __STR(x) #x
|
|
|
|
#define STR(x) __STR(x)
|
|
|
|
|
|
|
|
#define INT_NAME(intnum) _KiUnexpectedInterrupt##intnum
|
|
|
|
#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum
|
|
|
|
|
|
|
|
#define BUILD_COMMON_INTERRUPT_HANDLER() \
|
|
|
|
__asm__( \
|
|
|
|
"_KiCommonInterrupt:\n\t" \
|
|
|
|
"cld\n\t" \
|
|
|
|
"pushl %ds\n\t" \
|
|
|
|
"pushl %es\n\t" \
|
|
|
|
"pushl %fs\n\t" \
|
|
|
|
"pushl %gs\n\t" \
|
|
|
|
"movl $0xceafbeef,%eax\n\t" \
|
|
|
|
"pushl %eax\n\t" \
|
|
|
|
"movl $" STR(KERNEL_DS) ",%eax\n\t" \
|
|
|
|
"movl %eax,%ds\n\t" \
|
|
|
|
"movl %eax,%es\n\t" \
|
2004-10-31 12:49:37 +00:00
|
|
|
"movl %eax,%gs\n\t" \
|
2001-04-13 16:12:26 +00:00
|
|
|
"movl $" STR(PCR_SELECTOR) ",%eax\n\t" \
|
|
|
|
"movl %eax,%fs\n\t" \
|
|
|
|
"pushl %esp\n\t" \
|
|
|
|
"pushl %ebx\n\t" \
|
|
|
|
"call _KiInterruptDispatch\n\t" \
|
2005-05-21 12:57:34 +00:00
|
|
|
"addl $0xC, %esp\n\t" \
|
2001-04-13 16:12:26 +00:00
|
|
|
"popl %gs\n\t" \
|
|
|
|
"popl %fs\n\t" \
|
|
|
|
"popl %es\n\t" \
|
|
|
|
"popl %ds\n\t" \
|
|
|
|
"popa\n\t" \
|
|
|
|
"iret\n\t");
|
|
|
|
|
|
|
|
#define BUILD_INTERRUPT_HANDLER(intnum) \
|
|
|
|
VOID INT_NAME2(intnum)(VOID); \
|
|
|
|
__asm__( \
|
|
|
|
STR(INT_NAME(intnum)) ":\n\t" \
|
|
|
|
"pusha\n\t" \
|
|
|
|
"movl $0x" STR(intnum) ",%ebx\n\t" \
|
|
|
|
"jmp _KiCommonInterrupt");
|
|
|
|
|
|
|
|
|
|
|
|
/* Interrupt handlers and declarations */
|
|
|
|
|
|
|
|
#define B(x,y) \
|
|
|
|
BUILD_INTERRUPT_HANDLER(x##y)
|
|
|
|
|
|
|
|
#define B16(x) \
|
|
|
|
B(x,0) B(x,1) B(x,2) B(x,3) \
|
|
|
|
B(x,4) B(x,5) B(x,6) B(x,7) \
|
|
|
|
B(x,8) B(x,9) B(x,A) B(x,B) \
|
|
|
|
B(x,C) B(x,D) B(x,E) B(x,F)
|
|
|
|
|
|
|
|
|
|
|
|
BUILD_COMMON_INTERRUPT_HANDLER()
|
|
|
|
B16(3) B16(4) B16(5) B16(6)
|
|
|
|
B16(7) B16(8) B16(9) B16(A)
|
|
|
|
B16(B) B16(C) B16(D) B16(E)
|
|
|
|
B16(F)
|
|
|
|
|
2001-04-16 16:29:03 +00:00
|
|
|
#undef B
|
|
|
|
#undef B16
|
2001-04-13 16:12:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Interrupt handler list */
|
|
|
|
|
|
|
|
#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) \
|
|
|
|
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)
|
|
|
|
|
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
|
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
|
|
|
|
2000-06-29 23:35:53 +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
|
|
|
|
|
|
|
static unsigned int irq_handler[NR_IRQS]=
|
|
|
|
{
|
|
|
|
(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,
|
|
|
|
};
|
|
|
|
|
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')
|
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)
|
|
|
|
|
2003-10-12 17:05:50 +00:00
|
|
|
VOID INIT_FUNCTION
|
|
|
|
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++)
|
|
|
|
{
|
|
|
|
KiIdt[IRQ_BASE+i].a=(irq_handler[i]&0xffff)+(KERNEL_CS<<16);
|
|
|
|
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-01-01 11:28:46 +00:00
|
|
|
for (j = 0; j < MAXIMUM_PROCESSORS; j++)
|
|
|
|
#else
|
|
|
|
j = 0;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
InitializeListHead(&IsrTable[i][j].ListHead);
|
|
|
|
KeInitializeSpinLock(&IsrTable[i][j].Lock);
|
|
|
|
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,
|
2004-11-01 14:37:19 +00:00
|
|
|
PKTRAP_FRAME TrapFrame)
|
2002-01-23 23:39:26 +00:00
|
|
|
{
|
2004-10-31 12:49:37 +00:00
|
|
|
TrapFrame->Gs = (USHORT)IrqTrapFrame->Gs;
|
2003-12-30 18:52:06 +00:00
|
|
|
TrapFrame->Fs = (USHORT)IrqTrapFrame->Fs;
|
|
|
|
TrapFrame->Es = (USHORT)IrqTrapFrame->Es;
|
|
|
|
TrapFrame->Ds = (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;
|
|
|
|
TrapFrame->Esp = IrqTrapFrame->Esp;
|
|
|
|
TrapFrame->Ebp = IrqTrapFrame->Ebp;
|
|
|
|
TrapFrame->Esi = IrqTrapFrame->Esi;
|
|
|
|
TrapFrame->Edi = IrqTrapFrame->Edi;
|
|
|
|
TrapFrame->Eip = IrqTrapFrame->Eip;
|
|
|
|
TrapFrame->Cs = IrqTrapFrame->Cs;
|
|
|
|
TrapFrame->Eflags = IrqTrapFrame->Eflags;
|
|
|
|
}
|
|
|
|
|
2004-11-01 14:37:19 +00:00
|
|
|
STATIC VOID
|
2003-06-07 19:13:43 +00:00
|
|
|
KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
|
2004-11-01 14:37:19 +00:00
|
|
|
PKIRQ_TRAPFRAME IrqTrapFrame)
|
2003-06-07 19:13:43 +00:00
|
|
|
{
|
2004-10-31 12:49:37 +00:00
|
|
|
IrqTrapFrame->Gs = TrapFrame->Gs;
|
2003-06-07 19:13:43 +00:00
|
|
|
IrqTrapFrame->Fs = TrapFrame->Fs;
|
|
|
|
IrqTrapFrame->Es = TrapFrame->Es;
|
|
|
|
IrqTrapFrame->Ds = TrapFrame->Ds;
|
|
|
|
IrqTrapFrame->Eax = TrapFrame->Eax;
|
|
|
|
IrqTrapFrame->Ecx = TrapFrame->Ecx;
|
|
|
|
IrqTrapFrame->Edx = TrapFrame->Edx;
|
|
|
|
IrqTrapFrame->Ebx = TrapFrame->Ebx;
|
|
|
|
IrqTrapFrame->Esp = TrapFrame->Esp;
|
|
|
|
IrqTrapFrame->Ebp = TrapFrame->Ebp;
|
|
|
|
IrqTrapFrame->Esi = TrapFrame->Esi;
|
|
|
|
IrqTrapFrame->Edi = TrapFrame->Edi;
|
|
|
|
IrqTrapFrame->Eip = TrapFrame->Eip;
|
|
|
|
IrqTrapFrame->Cs = TrapFrame->Cs;
|
|
|
|
IrqTrapFrame->Eflags = TrapFrame->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);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
PKTHREAD CurrentThread;
|
2003-06-11 18:38:44 +00:00
|
|
|
PKTRAP_FRAME OldTrapFrame=NULL;
|
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-05-09 01:38:29 +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
|
|
|
*/
|
2004-11-01 14:37:19 +00:00
|
|
|
if (!HalBeginSystemInterrupt (vector,
|
|
|
|
VECTOR2IRQL(vector),
|
2002-05-02 23:45:33 +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
|
|
|
{
|
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();
|
2003-12-30 22:10:45 +00:00
|
|
|
|
2003-01-02 16:06:49 +00:00
|
|
|
HalEndSystemInterrupt (old_level, 0);
|
2004-07-30 19:28:49 +00:00
|
|
|
|
2003-08-25 09:14:09 +00:00
|
|
|
if (old_level==PASSIVE_LEVEL && Trapframe->Cs != KERNEL_CS)
|
2003-07-20 12:14:46 +00:00
|
|
|
{
|
2003-08-25 09:14:09 +00:00
|
|
|
CurrentThread = KeGetCurrentThread();
|
|
|
|
if (CurrentThread!=NULL && CurrentThread->Alerted[1])
|
|
|
|
{
|
2005-05-09 01:38:29 +00:00
|
|
|
DPRINT("PID: %d, TID: %d CS %04x/%04x\n",
|
2003-08-25 09:14:09 +00:00
|
|
|
((PETHREAD)CurrentThread)->ThreadsProcess->UniqueProcessId,
|
|
|
|
((PETHREAD)CurrentThread)->Cid.UniqueThread,
|
2005-05-09 01:38:29 +00:00
|
|
|
Trapframe->Cs,
|
2003-08-25 09:14:09 +00:00
|
|
|
CurrentThread->TrapFrame ? CurrentThread->TrapFrame->Cs : 0);
|
|
|
|
if (CurrentThread->TrapFrame == NULL)
|
|
|
|
{
|
|
|
|
OldTrapFrame = CurrentThread->TrapFrame;
|
|
|
|
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
|
|
|
CurrentThread->TrapFrame = &KernelTrapFrame;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-11-27 19:24:15 +00:00
|
|
|
Ke386EnableInterrupts();
|
2004-11-10 02:51:00 +00:00
|
|
|
KiDeliverApc(KernelMode, NULL, NULL);
|
2004-11-27 19:24:15 +00:00
|
|
|
Ke386DisableInterrupts();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-10-22 20:43:58 +00:00
|
|
|
ASSERT(KeGetCurrentThread() == CurrentThread);
|
2003-08-25 09:14:09 +00:00
|
|
|
if (CurrentThread->TrapFrame == &KernelTrapFrame)
|
|
|
|
{
|
|
|
|
KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
|
|
|
|
CurrentThread->TrapFrame = OldTrapFrame;
|
|
|
|
}
|
|
|
|
}
|
2003-07-20 12:14:46 +00:00
|
|
|
}
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
static VOID
|
2000-12-10 23:42:01 +00:00
|
|
|
KeDumpIrqList(VOID)
|
1998-09-05 17:34:23 +00:00
|
|
|
{
|
|
|
|
PKINTERRUPT current;
|
|
|
|
PLIST_ENTRY current_entry;
|
2005-01-01 11:28:46 +00:00
|
|
|
ULONG i, j;
|
|
|
|
KIRQL oldlvl;
|
|
|
|
BOOLEAN printed;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
1998-09-05 17:34:23 +00:00
|
|
|
for (i=0;i<NR_IRQS;i++)
|
|
|
|
{
|
2005-01-01 11:28:46 +00:00
|
|
|
printed = FALSE;
|
|
|
|
KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl);
|
|
|
|
|
|
|
|
for (j=0; j < KeNumberProcessors; j++)
|
1998-09-05 17:34:23 +00:00
|
|
|
{
|
2005-01-01 11:28:46 +00:00
|
|
|
KiAcquireSpinLock(&IsrTable[i][j].Lock);
|
|
|
|
|
|
|
|
current_entry = IsrTable[i][j].ListHead.Flink;
|
2005-06-22 23:10:15 +00:00
|
|
|
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
|
2005-01-01 11:28:46 +00:00
|
|
|
while (current_entry!=&(IsrTable[i][j].ListHead))
|
|
|
|
{
|
|
|
|
if (printed == FALSE)
|
|
|
|
{
|
|
|
|
printed = TRUE;
|
|
|
|
DPRINT("For irq %x:\n",i);
|
|
|
|
}
|
|
|
|
DPRINT(" Isr %x\n",current);
|
|
|
|
current_entry = current_entry->Flink;
|
2005-06-22 23:10:15 +00:00
|
|
|
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
|
2005-01-01 11:28:46 +00:00
|
|
|
}
|
|
|
|
KiReleaseSpinLock(&IsrTable[i][j].Lock);
|
1998-09-05 17:34:23 +00:00
|
|
|
}
|
2005-01-01 11:28:46 +00:00
|
|
|
KeLowerIrql(oldlvl);
|
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
|
|
|
|
|
|
|
DPRINT("KeConnectInterrupt()\n");
|
|
|
|
|
|
|
|
Vector = InterruptObject->Vector;
|
|
|
|
|
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
|
|
|
|
2000-07-10 21:55:49 +00:00
|
|
|
KeDumpIrqList();
|
|
|
|
|
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
|
|
|
{
|
2005-06-22 23:10:15 +00:00
|
|
|
/* 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;
|
2005-01-01 11:28:46 +00:00
|
|
|
}
|
2000-07-10 21:55:49 +00:00
|
|
|
|
2005-01-01 11:28:46 +00:00
|
|
|
VOID KePrintInterruptStatistic(VOID)
|
|
|
|
{
|
|
|
|
ULONG i, j;
|
|
|
|
|
|
|
|
for (j = 0; j < KeNumberProcessors; j++)
|
|
|
|
{
|
|
|
|
DPRINT1("CPU%d:\n", j);
|
|
|
|
for (i = 0; i < NR_IRQS; i++)
|
|
|
|
{
|
|
|
|
if (IsrTable[i][j].Count)
|
|
|
|
{
|
|
|
|
DPRINT1(" Irq %x(%d): %d\n", i, VECTOR2IRQ(i + IRQ_BASE), IsrTable[i][j].Count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-07-10 21:55:49 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 11:28:46 +00:00
|
|
|
|
2000-03-19 13:35:38 +00:00
|
|
|
/* EOF */
|