Author: arty Date: Sun Dec 3 14:25:56 2006 New Revision: 25030
URL: http://svn.reactos.org/svn/reactos?rev=25030&view=rev Log: After a clean, these seem to be needed. Probably due to my patchy import.
Added: branches/arty-stable/reactos/ntoskrnl/deprecated/ branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S
Added: branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c URL: http://svn.reactos.org/svn/reactos/branches/arty-stable/reactos/ntoskrnl/dep... ============================================================================== --- branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c (added) +++ branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c Sun Dec 3 14:25:56 2006 @@ -1,0 +1,779 @@ +/* $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') + +/* 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++) + { + ((IDT_DESCRIPTOR*)&KiIdt[IRQ_BASE+i])->a=(irq_handler[i]&0xffff)+(KGDT_R0_CODE<<16); + ((IDT_DESCRIPTOR*)&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 + */ + _enable(); + +#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. + */ + _disable(); + + 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->SegCs : 0); + if (CurrentThread->TrapFrame == NULL) + { + OldTrapFrame = CurrentThread->TrapFrame; + KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); + CurrentThread->TrapFrame = &KernelTrapFrame; + } + + _enable(); + KiDeliverApc(UserMode, NULL, NULL); + _disable(); + + 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: branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S URL: http://svn.reactos.org/svn/reactos/branches/arty-stable/reactos/ntoskrnl/dep... ============================================================================== --- branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S (added) +++ branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S Sun Dec 3 14:25:56 2006 @@ -1,0 +1,99 @@ +#include <ndk/asm.h> +#include <../hal/halx86/include/halirq.h> + +_KiCommonInterrupt: + cld + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushl $0xceafbeef + + /* Load DS/ES (with override) */ + .intel_syntax noprefix + mov eax, KGDT_R3_DATA + RPL_MASK + .byte 0x66 + mov ds, ax + .byte 0x66 + mov es, ax + + /* Clear gs */ + xor eax, eax + .byte 0x66 + mov gs, ax + .att_syntax + 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 +