Author: ion Date: Fri Aug 25 18:50:01 2006 New Revision: 23707
URL: http://svn.reactos.org/svn/reactos?rev=23707&view=rev Log: - Viva la deprecation! Trunk should now boot and the installer should work. - Basically revert the new HAL/KERNEL IRQ code by putting the old one in, but without the actual pain of svn reverting and losing all the previous code. - The old code goes in ntoskrnl\deprecated, and we only add a comment to the .rbuild file, re-export an old function, and initialize the old code in kernel.c. All the other kernel changes stay in-place to be tested. - Same for hal, basically replace irq.S with irql.c in the .rbuild file, and disable the call to Halpinit1. All the other changes remain.
Added: trunk/reactos/hal/halx86/generic/irql.c trunk/reactos/ntoskrnl/deprecated/ trunk/reactos/ntoskrnl/deprecated/irq.c trunk/reactos/ntoskrnl/deprecated/irqhand.S Modified: trunk/reactos/hal/halx86/generic/generic.rbuild trunk/reactos/hal/halx86/generic/halinit.c trunk/reactos/ntoskrnl/ke/clock.c trunk/reactos/ntoskrnl/ke/i386/kernel.c trunk/reactos/ntoskrnl/ntoskrnl.def trunk/reactos/ntoskrnl/ntoskrnl.rbuild
Modified: trunk/reactos/hal/halx86/generic/generic.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/generic.... ============================================================================== --- trunk/reactos/hal/halx86/generic/generic.rbuild (original) +++ trunk/reactos/hal/halx86/generic/generic.rbuild Fri Aug 25 18:50:01 2006 @@ -31,7 +31,7 @@ <define name="_NTHAL_" /> <define name="__USE_W32API" /> <file>ipi.c</file> - <file>irq.S</file> + <file>irql.c</file> <file>processor.c</file> <file>resource.c</file> <file>spinlock.c</file>
Modified: trunk/reactos/hal/halx86/generic/halinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/halinit.... ============================================================================== --- trunk/reactos/hal/halx86/generic/halinit.c (original) +++ trunk/reactos/hal/halx86/generic/halinit.c Fri Aug 25 18:50:01 2006 @@ -43,7 +43,7 @@ else if (BootPhase == 1) { /* Initialize the clock interrupt */ - HalpInitPhase1(); + //HalpInitPhase1();
/* Initialize display and make the screen black */ HalInitializeDisplay ((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock);
Added: trunk/reactos/hal/halx86/generic/irql.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/irql.c?r... ============================================================================== --- trunk/reactos/hal/halx86/generic/irql.c (added) +++ trunk/reactos/hal/halx86/generic/irql.c Fri Aug 25 18:50:01 2006 @@ -1,0 +1,425 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/irql.c + * PURPOSE: Implements IRQLs + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#include <hal.h> +#define NDEBUG +#include <debug.h> + +/* GLOBALS ******************************************************************/ + +/* + * FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS +*/ + +typedef union +{ + USHORT both; + struct + { + BYTE master; + BYTE slave; + }; +} +PIC_MASK; + +/* + * PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt + * - At startup enable timer and cascade + */ +#if defined(__GNUC__) +static PIC_MASK pic_mask = {.both = 0xFFFA}; +#else +static PIC_MASK pic_mask = { 0xFFFA }; +#endif + + +/* + * PURPOSE: Mask for disabling of acknowledged interrupts + */ +#if defined(__GNUC__) +static PIC_MASK pic_mask_intr = {.both = 0x0000}; +#else +static PIC_MASK pic_mask_intr = { 0 }; +#endif + +static ULONG HalpPendingInterruptCount[NR_IRQS]; + +#define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x) +#define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x) + +VOID STDCALL +KiInterruptDispatch2 (ULONG Irq, KIRQL old_level); + +/* FUNCTIONS ****************************************************************/ + +#undef KeGetCurrentIrql +KIRQL STDCALL KeGetCurrentIrql (VOID) +/* + * PURPOSE: Returns the current irq level + * RETURNS: The current irq level + */ +{ + return(KeGetPcr()->Irql); +} + +VOID NTAPI HalpInitPICs(VOID) +{ + memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount)); + + /* Initialization sequence */ + WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11); + WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11); + /* Start of hardware irqs (0x24) */ + WRITE_PORT_UCHAR((PUCHAR)0x21, IRQ_BASE); + WRITE_PORT_UCHAR((PUCHAR)0xa1, IRQ_BASE + 8); + /* 8259-1 is master */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4); + /* 8259-2 is slave */ + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2); + /* 8086 mode */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1); + /* Enable interrupts */ + WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master); + WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave); + + /* We can now enable interrupts */ + Ki386EnableInterrupts(); +} + +VOID HalpEndSystemInterrupt(KIRQL Irql) +/* + * FUNCTION: Enable all irqs with higher priority. + */ +{ + ULONG flags; + const USHORT mask[] = + { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, + 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0, + 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + }; + + /* Interrupts should be disable while enabling irqs of both pics */ + Ki386SaveFlags(flags); + Ki386DisableInterrupts(); + + pic_mask_intr.both &= mask[Irql]; + WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master)); + WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); + + /* restore flags */ + Ki386RestoreFlags(flags); +} + +VOID STATIC +HalpExecuteIrqs(KIRQL NewIrql) +{ + ULONG IrqLimit, i; + + IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS); + + /* + * For each irq if there have been any deferred interrupts then now + * dispatch them. + */ + for (i = 0; i < IrqLimit; i++) + { + if (HalpPendingInterruptCount[i] > 0) + { + KeGetPcr()->Irql = (KIRQL)IRQ_TO_DIRQL(i); + + while (HalpPendingInterruptCount[i] > 0) + { + /* + * For each deferred interrupt execute all the handlers at DIRQL. + */ + HalpPendingInterruptCount[i]--; + KiInterruptDispatch2(i + IRQ_BASE, NewIrql); + } + KeGetPcr()->Irql--; + HalpEndSystemInterrupt(KeGetPcr()->Irql); + } + } + +} + +VOID STATIC +HalpLowerIrql(KIRQL NewIrql) +{ + if (NewIrql >= PROFILE_LEVEL) + { + KeGetPcr()->Irql = NewIrql; + return; + } + HalpExecuteIrqs(NewIrql); + if (NewIrql >= DISPATCH_LEVEL) + { + KeGetPcr()->Irql = NewIrql; + return; + } + KeGetPcr()->Irql = DISPATCH_LEVEL; + if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST]) + { + ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE; + KiDispatchInterrupt(); + } + KeGetPcr()->Irql = APC_LEVEL; + if (NewIrql == APC_LEVEL) + { + return; + } + if (KeGetCurrentThread() != NULL && + KeGetCurrentThread()->ApcState.KernelApcPending) + { + KiDeliverApc(KernelMode, NULL, NULL); + } + KeGetPcr()->Irql = PASSIVE_LEVEL; +} + +/********************************************************************** + * NAME EXPORTED + * KfLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + * Uses fastcall convention + */ +VOID FASTCALL +KfLowerIrql (KIRQL NewIrql) +{ + DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql); + + if (NewIrql > KeGetPcr()->Irql) + { + DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n", + __FILE__, __LINE__, NewIrql, KeGetPcr()->Irql); + KEBUGCHECK(0); + for(;;); + } + + HalpLowerIrql(NewIrql); +} + +/********************************************************************** + * NAME EXPORTED + * KfRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * + * RETURN VALUE + * previous irq level + * + * NOTES + * Uses fastcall convention + */ + +KIRQL FASTCALL +KfRaiseIrql (KIRQL NewIrql) +{ + KIRQL OldIrql; + + DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql); + + if (NewIrql < KeGetPcr()->Irql) + { + DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n", + __FILE__,__LINE__,KeGetPcr()->Irql,NewIrql); + KEBUGCHECK (0); + for(;;); + } + + OldIrql = KeGetPcr()->Irql; + KeGetPcr()->Irql = NewIrql; + return OldIrql; +} + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToDpcLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to DISPATCH level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL STDCALL +KeRaiseIrqlToDpcLevel (VOID) +{ + return KfRaiseIrql (DISPATCH_LEVEL); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToSynchLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to CLOCK2 level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL STDCALL +KeRaiseIrqlToSynchLevel (VOID) +{ + return KfRaiseIrql (CLOCK2_LEVEL); +} + + +BOOLEAN STDCALL +HalBeginSystemInterrupt (KIRQL Irql, + ULONG Vector, + PKIRQL OldIrql) +{ + ULONG irq; + if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) + { + return(FALSE); + } + irq = Vector - IRQ_BASE; + pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt + + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master)); + WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20); + } + else + { + WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); + /* Send EOI to the PICs */ + WRITE_PORT_UCHAR((PUCHAR)0x20,0x20); + WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20); + } + + if (KeGetPcr()->Irql >= Irql) + { + HalpPendingInterruptCount[irq]++; + return(FALSE); + } + *OldIrql = KeGetPcr()->Irql; + KeGetPcr()->Irql = Irql; + + return(TRUE); +} + + +VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2) +/* + * FUNCTION: Finish a system interrupt and restore the specified irq level. + */ +{ + HalpLowerIrql(Irql); + HalpEndSystemInterrupt(Irql); +} + +BOOLEAN +STDCALL +HalDisableSystemInterrupt( + ULONG Vector, + KIRQL Irql) +{ + ULONG irq; + + if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) + return FALSE; + + irq = Vector - IRQ_BASE; + pic_mask.both |= (1 << irq); + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.slave)); + } + else + { + WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); + } + + return TRUE; +} + + +BOOLEAN +STDCALL +HalEnableSystemInterrupt( + ULONG Vector, + KIRQL Irql, + KINTERRUPT_MODE InterruptMode) +{ + ULONG irq; + + if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) + return FALSE; + + irq = Vector - IRQ_BASE; + pic_mask.both &= ~(1 << irq); + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master)); + } + else + { + WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); + } + + return TRUE; +} + + +VOID FASTCALL +HalRequestSoftwareInterrupt( + IN KIRQL Request) +{ + switch (Request) + { + case APC_LEVEL: + ((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE; + break; + + case DISPATCH_LEVEL: + ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE; + break; + + default: + KEBUGCHECK(0); + } +} + +/* EOF */
Added: trunk/reactos/ntoskrnl/deprecated/irq.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/deprecated/irq.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/deprecated/irq.c (added) +++ trunk/reactos/ntoskrnl/deprecated/irq.c Fri Aug 25 18:50:01 2006 @@ -1,0 +1,780 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/irq.c + * PURPOSE: IRQ handling + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + */ + +/* + * NOTE: In general the PIC interrupt priority facilities are used to + * preserve the NT IRQL semantics, global interrupt disables are only used + * to keep the PIC in a consistent state + * + */ + +/* INCLUDES ****************************************************************/ + +#include <ntoskrnl.h> +#include <../hal/halx86/include/halirq.h> +#include <../hal/halx86/include/mps.h> + +#define NDEBUG +#include <internal/debug.h> + +extern KDPC KiExpireTimerDpc; +extern ULONG KiMaximumDpcQueueDepth; +extern ULONG KiMinimumDpcRate; +extern ULONG KiAdjustDpcThreshold; +extern ULONG KiIdealDpcRate; +extern LONG KiTickOffset; +extern ULONG KeMaximumIncrement; +extern ULONG KeMinimumIncrement; +extern ULONG KeTimeAdjustment; +extern BOOLEAN KiClockSetupComplete; + +/* GLOBALS *****************************************************************/ + +/* Interrupt handler list */ + +#ifdef CONFIG_SMP + +#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum + +#define BUILD_INTERRUPT_HANDLER(intnum) \ +VOID INT_NAME2(intnum)(VOID); + +#define D(x,y) \ + BUILD_INTERRUPT_HANDLER(x##y) + +#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) + +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) + +#define L(x,y) \ + (ULONG)& INT_NAME2(x##y) + +#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) + +static ULONG irq_handler[ROUND_UP(NR_IRQS, 16)] = { + L16(3), L16(4), L16(5), L16(6), + L16(7), L16(8), L16(9), L16(A), + L16(B), L16(C), L16(D), L16(E) +}; + +#undef L +#undef L16 +#undef D +#undef D16 + +#else /* CONFIG_SMP */ + +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); + +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, +}; + +#endif /* CONFIG_SMP */ + +/* + * PURPOSE: Object describing each isr + * NOTE: The data in this table is only modified at passsive level but can + * be accessed at any irq level. + */ + +typedef struct +{ + LIST_ENTRY ListHead; + KSPIN_LOCK Lock; + ULONG Count; +} +ISR_TABLE, *PISR_TABLE; + +#ifdef CONFIG_SMP +static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS]; +#else +static ISR_TABLE IsrTable[NR_IRQS][1]; +#endif + +#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L') +extern IDT_DESCRIPTOR KiIdt[256]; + +/* FUNCTIONS ****************************************************************/ + +#define PRESENT (0x8000) +#define I486_INTERRUPT_GATE (0xe00) + +VOID +INIT_FUNCTION +NTAPI +KeInitInterrupts (VOID) +{ + int i, j; + + + /* + * 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)+(KGDT_R0_CODE<<16); + KiIdt[IRQ_BASE+i].b=(irq_handler[i]&0xffff0000)+PRESENT+ + I486_INTERRUPT_GATE; +#ifdef CONFIG_SMP + 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; + } + } +} + +STATIC VOID +KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame, + PKTRAP_FRAME TrapFrame) +{ + TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs; + TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs; + TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es; + TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds; + TrapFrame->Eax = IrqTrapFrame->Eax; + TrapFrame->Ecx = IrqTrapFrame->Ecx; + TrapFrame->Edx = IrqTrapFrame->Edx; + TrapFrame->Ebx = IrqTrapFrame->Ebx; + TrapFrame->HardwareEsp = IrqTrapFrame->Esp; + TrapFrame->Ebp = IrqTrapFrame->Ebp; + TrapFrame->Esi = IrqTrapFrame->Esi; + TrapFrame->Edi = IrqTrapFrame->Edi; + TrapFrame->Eip = IrqTrapFrame->Eip; + TrapFrame->SegCs = IrqTrapFrame->Cs; + TrapFrame->EFlags = IrqTrapFrame->Eflags; +} + +STATIC VOID +KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame, + PKIRQ_TRAPFRAME IrqTrapFrame) +{ + IrqTrapFrame->Gs = TrapFrame->SegGs; + IrqTrapFrame->Fs = TrapFrame->SegFs; + IrqTrapFrame->Es = TrapFrame->SegEs; + IrqTrapFrame->Ds = TrapFrame->SegDs; + IrqTrapFrame->Eax = TrapFrame->Eax; + IrqTrapFrame->Ecx = TrapFrame->Ecx; + IrqTrapFrame->Edx = TrapFrame->Edx; + IrqTrapFrame->Ebx = TrapFrame->Ebx; + IrqTrapFrame->Esp = TrapFrame->HardwareEsp; + IrqTrapFrame->Ebp = TrapFrame->Ebp; + IrqTrapFrame->Esi = TrapFrame->Esi; + IrqTrapFrame->Edi = TrapFrame->Edi; + IrqTrapFrame->Eip = TrapFrame->Eip; + IrqTrapFrame->Cs = TrapFrame->SegCs; + IrqTrapFrame->Eflags = TrapFrame->EFlags; +} + +/* + * NOTE: On Windows this function takes exactly one parameter and EBP is + * guaranteed to point to KTRAP_FRAME. The function is used only + * by HAL, so there's no point in keeping that prototype. + * + * @implemented + */ +VOID +STDCALL +KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, + IN KIRQL Irql) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + PKTHREAD CurrentThread; + PKPROCESS CurrentProcess; + + /* Make sure we don't go further if we're in early boot phase. */ + if (!(Prcb) || !(Prcb->CurrentThread)) return; + + /* Get the current thread and process */ + CurrentThread = Prcb->CurrentThread; + CurrentProcess = CurrentThread->ApcState.Process; + + /* Check if we came from user mode */ + if (TrapFrame->PreviousPreviousMode != KernelMode) + { + /* Update user times */ + CurrentThread->UserTime++; + InterlockedIncrement((PLONG)&CurrentProcess->UserTime); + Prcb->UserTime++; + } + else + { + /* Check IRQ */ + if (Irql > DISPATCH_LEVEL) + { + /* This was an interrupt */ + Prcb->InterruptTime++; + } + else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive)) + { + /* This was normal kernel time */ + CurrentThread->KernelTime++; + InterlockedIncrement((PLONG)&CurrentProcess->KernelTime); + } + else if (Irql == DISPATCH_LEVEL) + { + /* This was DPC time */ + Prcb->DpcTime++; + } + + /* Update CPU kernel time in all cases */ + Prcb->KernelTime++; + } + + /* Set the last DPC Count and request rate */ + Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount; + Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) + + Prcb->DpcRequestRate) / 2; + + /* Check if we should request a DPC */ + if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive)) + { + /* Request one */ + HalRequestSoftwareInterrupt(DISPATCH_LEVEL); + + /* Update the depth if needed */ + if ((Prcb->DpcRequestRate < KiIdealDpcRate) && + (Prcb->MaximumDpcQueueDepth > 1)) + { + /* Decrease the maximum depth by one */ + Prcb->MaximumDpcQueueDepth--; + } + } + else + { + /* Decrease the adjustment threshold */ + if (!(--Prcb->AdjustDpcThreshold)) + { + /* We've hit 0, reset it */ + Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; + + /* Check if we've hit queue maximum */ + if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth) + { + /* Increase maximum by one */ + Prcb->MaximumDpcQueueDepth++; + } + } + } + + /* + * If we're at end of quantum request software interrupt. The rest + * is handled in KiDispatchInterrupt. + * + * NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine + * which checks for quantum end will not be executed and decrementing + * the quantum here can result in overflow. This is not a problem since + * we don't care about the quantum value anymore after the QuantumEnd + * flag is set. + */ + if ((CurrentThread->Quantum -= 3) <= 0) + { + Prcb->QuantumEnd = TRUE; + HalRequestSoftwareInterrupt(DISPATCH_LEVEL); + } +} + + +/* + * NOTE: On Windows this function takes exactly zero parameters and EBP is + * guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL. + * The function is used only by HAL, so there's no point in keeping + * that prototype. + * + * @implemented + */ +VOID +STDCALL +KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, + IN KIRQL Irql, + IN ULONG Increment) +{ + LONG OldOffset; + LARGE_INTEGER Time; + ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL); + if (!KiClockSetupComplete) return; + + /* Update interrupt time */ + Time.LowPart = SharedUserData->InterruptTime.LowPart; + Time.HighPart = SharedUserData->InterruptTime.High1Time; + Time.QuadPart += Increment; + SharedUserData->InterruptTime.High2Time = Time.u.HighPart; + SharedUserData->InterruptTime.LowPart = Time.u.LowPart; + SharedUserData->InterruptTime.High1Time = Time.u.HighPart; + + /* Increase the tick offset */ + KiTickOffset -= Increment; + OldOffset = KiTickOffset; + + /* Check if this isn't a tick yet */ + if (KiTickOffset > 0) + { + /* Expire timers */ + KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0); + } + else + { + /* Setup time structure for system time */ + Time.LowPart = SharedUserData->SystemTime.LowPart; + Time.HighPart = SharedUserData->SystemTime.High1Time; + Time.QuadPart += KeTimeAdjustment; + SharedUserData->SystemTime.High2Time = Time.HighPart; + SharedUserData->SystemTime.LowPart = Time.LowPart; + SharedUserData->SystemTime.High1Time = Time.HighPart; + + /* Setup time structure for tick time */ + Time.LowPart = KeTickCount.LowPart; + Time.HighPart = KeTickCount.High1Time; + Time.QuadPart += 1; + KeTickCount.High2Time = Time.HighPart; + KeTickCount.LowPart = Time.LowPart; + KeTickCount.High1Time = Time.HighPart; + SharedUserData->TickCount.High2Time = Time.HighPart; + SharedUserData->TickCount.LowPart = Time.LowPart; + SharedUserData->TickCount.High1Time = Time.HighPart; + + /* Update tick count in shared user data as well */ + SharedUserData->TickCountLowDeprecated++; + + /* Queue a DPC that will expire timers */ + KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0); + } + + /* Update process and thread times */ + if (OldOffset <= 0) + { + /* This was a tick, calculate the next one */ + KiTickOffset += KeMaximumIncrement; + KeUpdateRunTime(TrapFrame, Irql); + } +} + +VOID STDCALL +KiInterruptDispatch2 (ULONG vector, KIRQL old_level) +/* + * FUNCTION: Calls all the interrupt handlers for a given irq. + * ARGUMENTS: + * vector - The number of the vector to call handlers for. + * old_level - The irql of the processor when the irq took place. + * NOTES: Must be called at DIRQL. + */ +{ + PKINTERRUPT isr; + PLIST_ENTRY current; + KIRQL oldlvl; + PISR_TABLE CurrentIsr; + + DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level); + + /* + * Iterate the list until one of the isr tells us its device interrupted + */ + CurrentIsr = &IsrTable[vector - IRQ_BASE][(ULONG)KeGetCurrentProcessorNumber()]; + + KiAcquireSpinLock(&CurrentIsr->Lock); + + CurrentIsr->Count++; + current = CurrentIsr->ListHead.Flink; + + while (current != &CurrentIsr->ListHead) + { + isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry); + oldlvl = KeAcquireInterruptSpinLock(isr); + if (isr->ServiceRoutine(isr, isr->ServiceContext)) + { + KeReleaseInterruptSpinLock(isr, oldlvl); + break; + } + KeReleaseInterruptSpinLock(isr, oldlvl); + current = current->Flink; + } + KiReleaseSpinLock(&CurrentIsr->Lock); +} + +VOID +KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe) +/* + * FUNCTION: Calls the irq specific handler for an irq + * ARGUMENTS: + * irq = IRQ that has interrupted + */ +{ + KIRQL old_level; + KTRAP_FRAME KernelTrapFrame; + PKTHREAD CurrentThread; + PKTRAP_FRAME OldTrapFrame=NULL; + + /* + * At this point we have interrupts disabled, nothing has been done to + * the PIC. + */ + + KeGetCurrentPrcb()->InterruptCount++; + + /* + * 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. + */ + if (!HalBeginSystemInterrupt (VECTOR2IRQL(vector), + vector, + &old_level)) + { + return; + } + + + /* + * Enable interrupts + * NOTE: Only higher priority interrupts will get through + */ + Ke386EnableInterrupts(); + +#ifndef CONFIG_SMP + if (VECTOR2IRQ(vector) == 0) + { + KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); + KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000); + } + else +#endif + { + /* + * Actually call the ISR. + */ + KiInterruptDispatch2(vector, old_level); + } + + /* + * End the system interrupt. + */ + Ke386DisableInterrupts(); + + if (old_level==PASSIVE_LEVEL && Trapframe->Cs != KGDT_R0_CODE) + { + HalEndSystemInterrupt (APC_LEVEL, 0); + + CurrentThread = KeGetCurrentThread(); + if (CurrentThread!=NULL && CurrentThread->ApcState.UserApcPending) + { + DPRINT("PID: %d, TID: %d CS %04x/%04x\n", + ((PETHREAD)CurrentThread)->ThreadsProcess->UniqueProcessId, + ((PETHREAD)CurrentThread)->Cid.UniqueThread, + Trapframe->Cs, + CurrentThread->TrapFrame ? CurrentThread->TrapFrame->Cs : 0); + if (CurrentThread->TrapFrame == NULL) + { + OldTrapFrame = CurrentThread->TrapFrame; + KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); + CurrentThread->TrapFrame = &KernelTrapFrame; + } + + Ke386EnableInterrupts(); + KiDeliverApc(UserMode, NULL, NULL); + Ke386DisableInterrupts(); + + ASSERT(KeGetCurrentThread() == CurrentThread); + if (CurrentThread->TrapFrame == &KernelTrapFrame) + { + KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe); + CurrentThread->TrapFrame = OldTrapFrame; + } + } + KeLowerIrql(PASSIVE_LEVEL); + } + else + { + HalEndSystemInterrupt (old_level, 0); + } + +} + +static VOID +KeDumpIrqList(VOID) +{ + PKINTERRUPT current; + PLIST_ENTRY current_entry; + LONG i, j; + KIRQL oldlvl; + BOOLEAN printed; + + for (i=0;i<NR_IRQS;i++) + { + printed = FALSE; + KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl); + + for (j=0; j < KeNumberProcessors; j++) + { + KiAcquireSpinLock(&IsrTable[i][j].Lock); + + current_entry = IsrTable[i][j].ListHead.Flink; + current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry); + 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; + current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry); + } + KiReleaseSpinLock(&IsrTable[i][j].Lock); + } + KeLowerIrql(oldlvl); + } +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +KeConnectInterrupt(PKINTERRUPT InterruptObject) +{ + KIRQL oldlvl,synch_oldlvl; + PKINTERRUPT ListHead; + ULONG Vector; + PISR_TABLE CurrentIsr; + BOOLEAN Result; + + DPRINT("KeConnectInterrupt()\n"); + + Vector = InterruptObject->Vector; + + if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) + return FALSE; + + Vector -= IRQ_BASE; + + ASSERT (InterruptObject->Number < KeNumberProcessors); + + KeSetSystemAffinityThread(1 << InterruptObject->Number); + + CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number]; + + KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl); + KiAcquireSpinLock(&CurrentIsr->Lock); + + /* + * Check if the vector is already in use that we can share it + */ + if (!IsListEmpty(&CurrentIsr->ListHead)) + { + ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry); + if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE) + { + KiReleaseSpinLock(&CurrentIsr->Lock); + KeLowerIrql(oldlvl); + KeRevertToUserAffinityThread(); + return FALSE; + } + } + + synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject); + + DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink); + + Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->Mode); + if (Result) + { + InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry); + DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->InterruptListEntry.Blink); + } + + InterruptObject->Connected = TRUE; + KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl); + + /* + * Release the table spinlock + */ + KiReleaseSpinLock(&CurrentIsr->Lock); + KeLowerIrql(oldlvl); + + KeDumpIrqList(); + + KeRevertToUserAffinityThread(); + + return Result; +} + +/* + * @implemented + * + * FUNCTION: Releases a drivers isr + * ARGUMENTS: + * InterruptObject = isr to release + */ +BOOLEAN +STDCALL +KeDisconnectInterrupt(PKINTERRUPT InterruptObject) +{ + KIRQL oldlvl,synch_oldlvl; + PISR_TABLE CurrentIsr; + BOOLEAN State; + + DPRINT1("KeDisconnectInterrupt\n"); + ASSERT (InterruptObject->Number < KeNumberProcessors); + + /* Set the affinity */ + KeSetSystemAffinityThread(1 << InterruptObject->Number); + + /* Get the ISR Tabe */ + CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE] + [(ULONG)InterruptObject->Number]; + + /* Raise IRQL to required level and lock table */ + 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); + + /* 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; +} + +/* + * @implemented + */ +VOID +STDCALL +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) +{ + /* 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) +{ + LONG 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); + } + } + } +} + +/* EOF */
Added: trunk/reactos/ntoskrnl/deprecated/irqhand.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/deprecated/irqhand... ============================================================================== --- trunk/reactos/ntoskrnl/deprecated/irqhand.S (added) +++ trunk/reactos/ntoskrnl/deprecated/irqhand.S Fri Aug 25 18:50:01 2006 @@ -1,0 +1,89 @@ +#include <ndk/asm.h> +#include <../hal/halx86/include/halirq.h> + +_KiCommonInterrupt: + cld + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushl $0xceafbeef + movl $KGDT_R0_DATA,%eax + movl %eax,%ds + movl %eax,%es + movl %eax,%gs + movl $KGDT_R0_PCR,%eax + movl %eax,%fs + pushl %esp + pushl %ebx + call _KiInterruptDispatch3 + addl $0xC, %esp + popl %gs + popl %fs + popl %es + popl %ds + popa + iret + + +#ifdef CONFIG_SMP + +#define BUILD_INTERRUPT_HANDLER(intnum) \ + .global _KiUnexpectedInterrupt##intnum; \ + _KiUnexpectedInterrupt##intnum:; \ + pusha; \ + movl $0x##intnum, %ebx; \ + 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) + +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) + +#undef B +#undef B16 +#undef BUILD_INTERRUPT_HANDLER + +#else /* CONFIG_SMP */ + +#define BUILD_INTERRUPT_HANDLER(intnum) \ + .global _irq_handler_##intnum; \ + _irq_handler_##intnum:; \ + pusha; \ + movl $(##intnum + IRQ_BASE), %ebx; \ + jmp _KiCommonInterrupt; + +/* Interrupt handlers and declarations */ + +#define B(x) \ + BUILD_INTERRUPT_HANDLER(x) + +B(0) B(1) B(2) B(3) +B(4) B(5) B(6) B(7) +B(8) B(9) B(10) B(11) +B(12) B(13) B(14) B(15) + +#undef B +#undef BUILD_INTERRUPT_HANDLER + +#endif /* CONFIG_SMP */ + +.intel_syntax noprefix +.globl _KiUnexpectedInterrupt@0 +_KiUnexpectedInterrupt@0: + + /* Bugcheck with invalid interrupt code */ + push 0x12 + call _KeBugCheck@4 +
Modified: trunk/reactos/ntoskrnl/ke/clock.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/clock.c?rev=237... ============================================================================== --- trunk/reactos/ntoskrnl/ke/clock.c (original) +++ trunk/reactos/ntoskrnl/ke/clock.c Fri Aug 25 18:50:01 2006 @@ -94,6 +94,7 @@ SharedUserData->SystemTime.High2Time = SystemBootTime.u.HighPart; SharedUserData->SystemTime.LowPart = SystemBootTime.u.LowPart; SharedUserData->SystemTime.High1Time = SystemBootTime.u.HighPart; + KiClockSetupComplete = TRUE; }
VOID
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kernel.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/kernel.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/kernel.c Fri Aug 25 18:50:01 2006 @@ -380,6 +380,7 @@ InitializeListHead(&KPCR->PrcbData.WaitListHead);
KeInitExceptions (); + KeInitInterrupts ();
KeActiveProcessors |= 1 << 0;
Modified: trunk/reactos/ntoskrnl/ntoskrnl.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.def?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.def (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.def Fri Aug 25 18:50:01 2006 @@ -663,6 +663,7 @@ KiCheckForKernelApcDelivery@0 KiDeliverApc@12 KiDispatchInterrupt@0 +KiInterruptDispatch2@8 KiEnableTimerWatchdog KiIpiServiceRoutine@8 @KiReleaseSpinLock@4
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?re... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Fri Aug 25 18:50:01 2006 @@ -33,7 +33,7 @@ <file>exp.c</file> <file>fpu.c</file> <file>gdt.c</file> - <file>irq.c</file> + <!-- <file>irq.c</file> --> <file>kernel.c</file> <file>ldt.c</file> <file>thread.c</file> @@ -68,6 +68,10 @@ <file>usercall.c</file> <file>wait.c</file> </directory> + <directory name="deprecated"> + <file>irqhand.S</file> + <file>irq.c</file> + </directory> <directory name="cc"> <file>cacheman.c</file> <file>copy.c</file>