Author: arty Date: Wed Jan 3 12:31:26 2007 New Revision: 25280
URL: http://svn.reactos.org/svn/reactos?rev=25280&view=rev Log: - Reserve and map a page for Pcr - Some stubs (KeInitExceptions, KeInitInterrupts, ...) - Normalize segments and bats
Added: branches/powerpc/reactos/ntoskrnl/ke/powerpc/cpu.c branches/powerpc/reactos/ntoskrnl/ke/powerpc/exp.c branches/powerpc/reactos/ntoskrnl/ke/powerpc/kiinit.c branches/powerpc/reactos/ntoskrnl/ke/powerpc/mmu.c branches/powerpc/reactos/ntoskrnl/ke/powerpc/ppc_irq.c Modified: branches/powerpc/reactos/ntoskrnl/ntoskrnl.rbuild
Added: branches/powerpc/reactos/ntoskrnl/ke/powerpc/cpu.c URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/ntoskrnl/ke/powe... ============================================================================== --- branches/powerpc/reactos/ntoskrnl/ke/powerpc/cpu.c (added) +++ branches/powerpc/reactos/ntoskrnl/ke/powerpc/cpu.c Wed Jan 3 12:31:26 2007 @@ -1,0 +1,277 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/i386/cpu.c + * PURPOSE: Routines for CPU-level support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include <ntoskrnl.h> +#define NDEBUG +#include <debug.h> + +/* GLOBALS *******************************************************************/ + +/* CPU Features and Flags */ +ULONG KeProcessorArchitecture; +ULONG KeProcessorLevel; +ULONG KeProcessorRevision; +ULONG KeFeatureBits; +ULONG KeLargestCacheLine = 0x40; +ULONG KeDcacheFlushCount = 0; +ULONG KeIcacheFlushCount = 0; +ULONG KiDmaIoCoherency = 0; +CHAR KeNumberProcessors; +KAFFINITY KeActiveProcessors = 1; +BOOLEAN KiSMTProcessorsPresent; + +/* CPU Signatures */ +#if 0 +CHAR CmpIntelID[] = "GenuineIntel"; +CHAR CmpAmdID[] = "AuthenticAMD"; +CHAR CmpCyrixID[] = "CyrixInstead"; +CHAR CmpTransmetaID[] = "GenuineTMx86"; +CHAR CmpCentaurID[] = "CentaurHauls"; +CHAR CmpRiseID[] = "RiseRiseRise"; +#endif + +/* SUPPORT ROUTINES FOR MSVC COMPATIBILITY ***********************************/ + +VOID +NTAPI +CPUID(IN ULONG CpuInfo[4], + IN ULONG InfoType) +{ + RtlZeroMemory(CpuInfo, sizeof(CpuInfo)); +} + +VOID +WRMSR(IN ULONG Register, + IN LONGLONG Value) +{ +} + +LONGLONG +RDMSR(IN ULONG Register) +{ + LARGE_INTEGER LargeVal; + LargeVal.QuadPart = 0; + return LargeVal.QuadPart; +} + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +KiSetProcessorType(VOID) +{ +} + +ULONG +NTAPI +KiGetCpuVendor(VOID) +{ + return 0; +} + +ULONG +NTAPI +KiGetFeatureBits(VOID) +{ + ULONG FeatureBits = 0; + /* Return the Feature Bits */ + return FeatureBits; +} + +VOID +NTAPI +KiGetCacheInformation(VOID) +{ +} + +VOID +NTAPI +KiSetCR0Bits(VOID) +{ +} + +VOID +NTAPI +KiInitializeTSS2(IN PKTSS Tss, + IN PKGDTENTRY TssEntry OPTIONAL) +{ +} + +VOID +NTAPI +KiInitializeTSS(IN PKTSS Tss) +{ +} + +VOID +FASTCALL +Ki386InitializeTss(IN PKTSS Tss, + IN PKIDTENTRY Idt, + IN PKGDTENTRY Gdt) +{ +} + +VOID +NTAPI +KeFlushCurrentTb(VOID) +{ +} + +VOID +NTAPI +KiSaveProcessorControlState(IN PKPROCESSOR_STATE ProcessorState) +{ +} + +VOID +NTAPI +KiInitializeMachineType(VOID) +{ +} + +ULONG_PTR +NTAPI +KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context) +{ + return 0; +} + +VOID +NTAPI +KiRestoreFastSyscallReturnState(VOID) +{ +} + +ULONG_PTR +NTAPI +Ki386EnableDE(IN ULONG_PTR Context) +{ + return 0; +} + +ULONG_PTR +NTAPI +Ki386EnableFxsr(IN ULONG_PTR Context) +{ + return 0; +} + +ULONG_PTR +NTAPI +Ki386EnableXMMIExceptions(IN ULONG_PTR Context) +{ + /* FIXME: Support this */ + DPRINT1("Your machine supports XMMI exceptions but ReactOS doesn't\n"); + return 0; +} + +VOID +NTAPI +KiI386PentiumLockErrataFixup(VOID) +{ + /* FIXME: Support this */ + DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't bypass!\n"); +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save) +{ + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save) +{ + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +ULONG +NTAPI +KeGetRecommendedSharedDataAlignment(VOID) +{ + /* Return the global variable */ + return KeLargestCacheLine; +} + +/* + * @implemented + */ +VOID +NTAPI +KeFlushEntireTb(IN BOOLEAN Invalid, + IN BOOLEAN AllProcessors) +{ + KIRQL OldIrql; + + /* Raise the IRQL for the TB Flush */ + OldIrql = KeRaiseIrqlToSynchLevel(); + +#ifdef CONFIG_SMP + /* FIXME: Support IPI Flush */ +#error Not yet implemented! +#endif + + /* Flush the TB for the Current CPU */ + //KeFlushCurrentTb(); + + /* Return to Original IRQL */ + KeLowerIrql(OldIrql); +} + +/* + * @implemented + */ +VOID +NTAPI +KeSetDmaIoCoherency(IN ULONG Coherency) +{ + /* Save the coherency globally */ + KiDmaIoCoherency = Coherency; +} + +/* + * @implemented + */ +KAFFINITY +NTAPI +KeQueryActiveProcessors(VOID) +{ + PAGED_CODE(); + + /* Simply return the number of active processors */ + return KeActiveProcessors; +} + +/* + * @implemented + */ +VOID +__cdecl +KeSaveStateForHibernate(IN PKPROCESSOR_STATE State) +{ + /* Capture the context */ + RtlCaptureContext(&State->ContextFrame); + + /* Capture the control state */ + KiSaveProcessorControlState(State); +}
Added: branches/powerpc/reactos/ntoskrnl/ke/powerpc/exp.c URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/ntoskrnl/ke/powe... ============================================================================== --- branches/powerpc/reactos/ntoskrnl/ke/powerpc/exp.c (added) +++ branches/powerpc/reactos/ntoskrnl/ke/powerpc/exp.c Wed Jan 3 12:31:26 2007 @@ -1,0 +1,114 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/i386/exp.c + * PURPOSE: Exception Dispatching and Context<->Trap Frame Conversion + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Gregor Anich + * Skywing (skywing@valhallalegends.com) + */ + +/* INCLUDES ******************************************************************/ + +#include <ntoskrnl.h> +#define NDEBUG +#include <debug.h> + +/* FUNCTIONS *****************************************************************/ + +_SEH_DEFINE_LOCALS(KiCopyInfo) +{ + volatile EXCEPTION_RECORD SehExceptRecord; +}; + +_SEH_FILTER(KiCopyInformation) +{ + _SEH_ACCESS_LOCALS(KiCopyInfo); + + /* Copy the exception records and return to the handler */ + RtlMoveMemory((PVOID)&_SEH_VAR(SehExceptRecord), + _SEH_GetExceptionPointers()->ExceptionRecord, + sizeof(EXCEPTION_RECORD)); + return EXCEPTION_EXECUTE_HANDLER; +} + +VOID +INIT_FUNCTION +NTAPI +KeInitExceptions(VOID) +{ +} + +ULONG +NTAPI +KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame) +{ + return 0; +} + +VOID +NTAPI +KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame, + IN ULONG Esp) +{ +} + +ULONG +NTAPI +KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame) +{ + return 0; +} + +VOID +NTAPI +KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame, + IN ULONG Ss) +{ +} + +USHORT +NTAPI +KiTagWordFnsaveToFxsave(USHORT TagWord) +{ + return 0; +} + +VOID +NTAPI +KeContextToTrapFrame(IN PCONTEXT Context, + IN OUT PKEXCEPTION_FRAME ExceptionFrame, + IN OUT PKTRAP_FRAME TrapFrame, + IN ULONG ContextFlags, + IN KPROCESSOR_MODE PreviousMode) +{ +} + +VOID +NTAPI +KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN OUT PCONTEXT Context) +{ +} + +VOID +NTAPI +KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PKTRAP_FRAME TrapFrame, + IN KPROCESSOR_MODE PreviousMode, + IN BOOLEAN FirstChance) +{ +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +KeRaiseUserException(IN NTSTATUS ExceptionCode) +{ + return STATUS_SUCCESS; +} +
Added: branches/powerpc/reactos/ntoskrnl/ke/powerpc/kiinit.c URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/ntoskrnl/ke/powe... ============================================================================== --- branches/powerpc/reactos/ntoskrnl/ke/powerpc/kiinit.c (added) +++ branches/powerpc/reactos/ntoskrnl/ke/powerpc/kiinit.c Wed Jan 3 12:31:26 2007 @@ -1,0 +1,339 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/powerpc/kiinit.c + * PURPOSE: Kernel Initialization for x86 CPUs + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Art Yerkes (ayerkes@speakeasy.net) + */ + +/* INCLUDES *****************************************************************/ + +#include <ntoskrnl.h> +#include <reactos/ppcboot.h> + +#define NDEBUG +#include <debug.h> + +/* GLOBALS *******************************************************************/ + +extern LOADER_MODULE KeLoaderModules[64]; +extern ULONG KeLoaderModuleCount; +KPRCB PrcbData[MAXIMUM_PROCESSORS]; + +/* FUNCTIONS *****************************************************************/ + +extern void SetPhysByte(ULONG_PTR address, char value); + +VOID +DrawDigit(struct _boot_infos_t *BootInfo, ULONG Digit, int x, int y) +{ + int i,j,k; + + for( i = 0; i < 7; i++ ) { + for( j = 0; j < 8; j++ ) { + for( k = 0; k < BootInfo->dispDeviceDepth/8; k++ ) { + SetPhysByte(((ULONG_PTR)BootInfo->dispDeviceBase)+ + k + + (((j+x) * (BootInfo->dispDeviceDepth/8)) + + ((i+y) * (BootInfo->dispDeviceRowBytes))), + BootInfo->dispFont[Digit][i*8+j] == 'X' ? 255 : 0); + } + } + } +} + +VOID +DrawNumber(struct _boot_infos_t *BootInfo, ULONG Number, int x, int y) +{ + int i; + + for( i = 0; i < 8; i++, Number<<=4 ) { + DrawDigit(BootInfo,(Number>>28)&0xf,x+(i*8),y); + } +} + +VOID +DrawString(struct _boot_infos_t *BootInfo, const char *str, int x, int y) +{ + int i, xx; + + for( i = 0; str[i]; i++ ) { + xx = x + (i * 8); + if( str[i] >= '0' && str[i] <= '9' ) + DrawDigit(BootInfo, str[i] - '0', xx, y); + else if( str[i] >= 'A' && str[i] <= 'Z' ) + DrawDigit(BootInfo, str[i] - 'A' + 10, xx, y); + else if( str[i] >= 'a' && str[i] <= 'z' ) + DrawDigit(BootInfo, str[i] - 'a' + 10, xx, y); + else + DrawDigit(BootInfo, 37, xx, y); + } +} + +VOID +NTAPI +KiInitializePcr(IN ULONG ProcessorNumber, + IN PKIPCR Pcr, + IN PKTHREAD IdleThread, + IN PVOID DpcStack) +{ + TRACE; + Pcr->MajorVersion = PCR_MAJOR_VERSION; + TRACE; + Pcr->MinorVersion = PCR_MINOR_VERSION; + TRACE; + Pcr->CurrentIrql = PASSIVE_LEVEL; + TRACE; + Pcr->Prcb = PrcbData; + TRACEXY(Pcr->Prcb, PrcbData); + Pcr->Prcb->MajorVersion = 1; + TRACE; + Pcr->Prcb->MinorVersion = 1; + TRACE; + Pcr->Prcb->Number = 0; /* UP for now */ + TRACE; + Pcr->Prcb->SetMember = 1; + TRACE; + Pcr->Prcb->BuildType = 0; + TRACE; + Pcr->Prcb->DpcStack = DpcStack; + TRACE; + KiProcessorBlock[ProcessorNumber] = Pcr->Prcb; + TRACEXY(0xd00d,0xbeef); +} + +extern ULONG KiGetFeatureBits(); +extern VOID KiSetProcessorType(); +extern VOID KiGetCacheInformation(); + +VOID +NTAPI +KiInitializeKernel(IN PKPROCESS InitProcess, + IN PKTHREAD InitThread, + IN PVOID IdleStack, + IN PKPRCB Prcb, + IN CCHAR Number, + IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) +{ + ULONG FeatureBits; + LARGE_INTEGER PageDirectory; + PVOID DpcStack; + + /* Detect and set the CPU Type */ + KiSetProcessorType(); + + /* Initialize the Power Management Support for this PRCB */ + PoInitializePrcb(Prcb); + + /* Get the processor features for the CPU */ + FeatureBits = KiGetFeatureBits(); + + /* Save feature bits */ + Prcb->FeatureBits = FeatureBits; + + /* Get cache line information for this CPU */ + KiGetCacheInformation(); + + /* Initialize spinlocks and DPC data */ + KiInitSpinLocks(Prcb, Number); + + /* Check if this is the Boot CPU */ + if (!Number) + { + /* Set Node Data */ + KeNodeBlock[0] = &KiNode0; + Prcb->ParentNode = KeNodeBlock[0]; + KeNodeBlock[0]->ProcessorMask = Prcb->SetMember; + + /* Set boot-level flags */ + KeProcessorArchitecture = 0; + KeProcessorLevel = (USHORT)Prcb->CpuType; + KeFeatureBits = FeatureBits; + + /* Set the current MP Master KPRCB to the Boot PRCB */ + Prcb->MultiThreadSetMaster = Prcb; + + /* Initialize portable parts of the OS */ + KiInitSystem(); + + /* Initialize the Idle Process and the Process Listhead */ + InitializeListHead(&KiProcessListHead); + PageDirectory.QuadPart = 0; + KeInitializeProcess(InitProcess, + 0, + 0xFFFFFFFF, + &PageDirectory, + TRUE); + InitProcess->QuantumReset = MAXCHAR; + } + else + { + /* FIXME */ + DPRINT1("SMP Boot support not yet present\n"); + } + +#if 0 + /* Setup the Idle Thread */ + KeInitializeThread(InitProcess, + InitThread, + NULL, + NULL, + NULL, + NULL, + NULL, + IdleStack); +#endif + InitThread->NextProcessor = Number; + InitThread->Priority = HIGH_PRIORITY; + InitThread->State = Running; + InitThread->Affinity = 1 << Number; + InitThread->WaitIrql = DISPATCH_LEVEL; + InitProcess->ActiveProcessors = 1 << Number; + + /* Set up the thread-related fields in the PRCB */ + //Prcb->CurrentThread = InitThread; + Prcb->NextThread = NULL; + //Prcb->IdleThread = InitThread; + + /* Initialize the Kernel Executive */ + ExpInitializeExecutive(0, (PLOADER_PARAMETER_BLOCK)LoaderBlock); + + /* Only do this on the boot CPU */ + if (!Number) + { + /* Calculate the time reciprocal */ + KiTimeIncrementReciprocal = + KiComputeReciprocal(KeMaximumIncrement, + &KiTimeIncrementShiftCount); + + /* Update DPC Values in case they got updated by the executive */ + Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; + Prcb->MinimumDpcRate = KiMinimumDpcRate; + Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; + + /* Allocate the DPC Stack */ + DpcStack = MmCreateKernelStack(FALSE); + if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); + Prcb->DpcStack = DpcStack; + } + + /* Free Initial Memory */ + MiFreeInitMemory(); + + while (1) + { + LARGE_INTEGER Timeout; + Timeout.QuadPart = 0x7fffffffffffffffLL; + KeDelayExecutionThread(KernelMode, FALSE, &Timeout); + } + + /* Bug Check and loop forever if anything failed */ + KEBUGCHECK(0); + for(;;); +} + +/* translate address */ +int PpcVirt2phys( int virt, int inst ); +/* Add a new page table entry for the indicated mapping */ +BOOLEAN InsertPageEntry( int virt, int phys, int slot, int _sdr1 ); +void SetBat( int bat, int inst, int hi, int lo ); +void SetSR( int n, int val ); + +/* Use this for early boot additions to the page table */ +VOID +NTAPI +KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + ULONG Cpu, PhysicalPage, i; + PKIPCR Pcr = (PKIPCR)KPCR_BASE; + PKPRCB Prcb; + + /* Zero bats for now ... We may use these for something later */ + for( i = 0; i < 4; i++ ) { + SetBat( i, 0, 0, 0 ); + SetBat( i, 1, 0, 0 ); + } + + /* Set up segs for normal paged address space. */ + for( i = 0; i < 16; i++ ) { + SetSR(i, i); + } + + /* Save the loader block and get the current CPU */ + //KeLoaderBlock = LoaderBlock; + Cpu = KeNumberProcessors; + if (!Cpu) + { + /* Skippable initialization for secondary processor */ + /* We'll allocate a page from the end of the kernel area for KPCR. This code will probably + * change when we get SMP support. + */ + ULONG LastPage = ROUND_UP(KeLoaderModules[KeLoaderModuleCount-1].ModEnd,1<<PAGE_SHIFT); + PhysicalPage = PpcVirt2phys(LastPage, FALSE); + InsertPageEntry((ULONG)Pcr, PhysicalPage, 0, 0); + *((PULONG)Pcr) = -1; + if(!((PULONG)Pcr)) { + TRACEXY(0xCABBA9E, 0xC0FFEE); + while(1); + } + } + + /* Skip initial setup if this isn't the Boot CPU */ + if (Cpu) goto AppCpuInit; + + /* Initialize the PCR */ + RtlZeroMemory(Pcr, PAGE_SIZE); + KiInitializePcr(Cpu, + Pcr, + &KiInitialThread.Tcb, + KiDoubleFaultStack); + + TRACE; + /* Set us as the current process */ + KiInitialThread.Tcb.ApcState.Process = &KiInitialProcess.Pcb; + + TRACE; + /* Setup CPU-related fields */ +AppCpuInit: + TRACE; + Prcb = Pcr->Prcb; + Pcr->Number = Cpu; + Pcr->SetMember = 1 << Cpu; + Prcb->SetMember = 1 << Cpu; + + TRACE; + /* Initialize the Processor with HAL */ + HalInitializeProcessor(Cpu, LoaderBlock); + + TRACE; + /* Set active processors */ + KeActiveProcessors |= Pcr->SetMember; + KeNumberProcessors++; + + TRACE; + /* Initialize the Debugger for the Boot CPU */ + if (!Cpu) KdInitSystem (0, LoaderBlock); + + TRACE; + /* Check for break-in */ + if (KdPollBreakIn()) + { + DbgBreakPointWithStatus(1); + } + + TRACE; + /* Raise to HIGH_LEVEL */ + KfRaiseIrql(HIGH_LEVEL); + + TRACE; + /* Call main kernel intialization */ + KiInitializeKernel(&KiInitialProcess.Pcb, + &KiInitialThread.Tcb, + P0BootStack, + Prcb, + Cpu, + (PVOID)LoaderBlock); + TRACE; +} +
Added: branches/powerpc/reactos/ntoskrnl/ke/powerpc/mmu.c URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/ntoskrnl/ke/powe... ============================================================================== --- branches/powerpc/reactos/ntoskrnl/ke/powerpc/mmu.c (added) +++ branches/powerpc/reactos/ntoskrnl/ke/powerpc/mmu.c Wed Jan 3 12:31:26 2007 @@ -1,0 +1,397 @@ +#include <ntoskrnl.h> + +inline int GetMSR() { + register int res asm ("r3"); + __asm__("mfmsr 3"); + return res; +} + +inline int GetDEC() { + register int res asm ("r3"); + __asm__("mfdec 3"); + return res; +} + +extern int GetPhys(int Addr); +extern void SetPhys(int Addr, int Val); + +__asm__("\t.globl GetPhys\n" + "GetPhys:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "xori 3,3,4\n\t" /* Undo effects of LE without swapping */ + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "isync\n\t" + "sync\n\t" + "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" + "isync\n\t" + "sync\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl SetPhys\n" + "SetPhys:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "xori 3,3,4\n\t" /* Undo effects of LE without swapping */ + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "sync\n\t" + "eieio\n\t" + "stw 4,0(3)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,3\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" + "mr 3,4\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl SetPhysByte\n" + "SetPhysByte:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "xori 3,3,7\n\t" /* Undo effects of LE without swapping */ + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "sync\n\t" + "eieio\n\t" + "stb 4,0(3)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,3\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" + "mr 3,4\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +inline int GetSR(int n) { + register int res asm ("r3"); + switch( n ) { + case 0: + __asm__("mfsr 3,0"); + break; + case 1: + __asm__("mfsr 3,1"); + break; + case 2: + __asm__("mfsr 3,2"); + break; + case 3: + __asm__("mfsr 3,3"); + break; + case 4: + __asm__("mfsr 3,4"); + break; + case 5: + __asm__("mfsr 3,5"); + break; + case 6: + __asm__("mfsr 3,6"); + break; + case 7: + __asm__("mfsr 3,7"); + break; + case 8: + __asm__("mfsr 3,8"); + break; + case 9: + __asm__("mfsr 3,9"); + break; + case 10: + __asm__("mfsr 3,10"); + break; + case 11: + __asm__("mfsr 3,11"); + break; + case 12: + __asm__("mfsr 3,12"); + break; + case 13: + __asm__("mfsr 3,13"); + break; + case 14: + __asm__("mfsr 3,14"); + break; + case 15: + __asm__("mfsr 3,15"); + break; + } + return res; +} + +inline void SetSR(int n, int val) { + switch( n ) { + case 0: + __asm__("mtsr 4,0"); + break; + case 1: + __asm__("mtsr 4,1"); + break; + case 2: + __asm__("mtsr 4,2"); + break; + case 3: + __asm__("mtsr 4,3"); + break; + case 4: + __asm__("mtsr 4,4"); + break; + case 5: + __asm__("mtsr 4,5"); + break; + case 6: + __asm__("mtsr 4,6"); + break; + case 7: + __asm__("mtsr 4,7"); + break; + case 8: + __asm__("mtsr 4,8"); + break; + case 9: + __asm__("mtsr 4,9"); + break; + case 10: + __asm__("mtsr 4,10"); + break; + case 11: + __asm__("mtsr 4,11"); + break; + case 12: + __asm__("mtsr 4,12"); + break; + case 13: + __asm__("mtsr 4,13"); + break; + case 14: + __asm__("mtsr 4,14"); + break; + case 15: + __asm__("mtsr 4,15"); + break; + } +} + +inline void GetBat( int bat, int inst, int *batHi, int *batLo ) { + register int bh asm("r3"), bl asm("r4"); + if( inst ) { + switch( bat ) { + case 0: + __asm__("mfibatu 3,0"); + __asm__("mfibatl 4,0"); + break; + case 1: + __asm__("mfibatu 3,1"); + __asm__("mfibatl 4,1"); + break; + case 2: + __asm__("mfibatu 3,2"); + __asm__("mfibatl 4,2"); + break; + case 3: + __asm__("mfibatu 3,3"); + __asm__("mfibatl 4,3"); + break; + } + } else { + switch( bat ) { + case 0: + __asm__("mfdbatu 3,0"); + __asm__("mfdbatl 4,0"); + break; + case 1: + __asm__("mfdbatu 3,1"); + __asm__("mfdbatl 4,1"); + break; + case 2: + __asm__("mfdbatu 3,2"); + __asm__("mfdbatl 4,2"); + break; + case 3: + __asm__("mfdbatu 3,3"); + __asm__("mfdbatl 4,3"); + break; + } + } + *batHi = bh; + *batLo = bl; +} + +inline void SetBat( int bat, int inst, int batHi, int batLo ) { + register int bh asm("r3"), bl asm("r4"); + bh = batHi; + bl = batLo; + if( inst ) { + switch( bat ) { + case 0: + __asm__("mtibatu 0,3"); + __asm__("mtibatl 0,4"); + break; + case 1: + __asm__("mtibatu 1,3"); + __asm__("mtibatl 1,4"); + break; + case 2: + __asm__("mtibatu 2,3"); + __asm__("mtibatl 2,4"); + break; + case 3: + __asm__("mtibatu 3,3"); + __asm__("mtibatl 3,4"); + break; + } + } else { + switch( bat ) { + case 0: + __asm__("mtdbatu 0,3"); + __asm__("mtdbatl 0,4"); + break; + case 1: + __asm__("mtdbatu 1,3"); + __asm__("mtdbatl 1,4"); + break; + case 2: + __asm__("mtdbatu 2,3"); + __asm__("mtdbatl 2,4"); + break; + case 3: + __asm__("mtdbatu 3,3"); + __asm__("mtdbatl 3,4"); + break; + } + } + __asm__("isync\n\tsync"); +} + +inline int GetSDR1() { + register int res asm("r3"); + __asm__("mfsdr1 3"); + return res; +} + +inline void SetSDR1( int sdr ) { +#if 0 + int i,j; +#endif + __asm__("mtsdr1 3"); +#if 0 + __asm__("sync"); + __asm__("isync"); + __asm__("ptesync"); + + for( i = 0; i < 256; i++ ) { + j = i << 12; + __asm__("tlbie %0,0" : : "r" (j)); + } + __asm__("eieio"); + __asm__("tlbsync"); + __asm__("ptesync"); +#endif +} + +inline int BatHit( int bath, int batl, int virt ) { + int mask = 0xfffe0000 & ~((batl & 0x3f) << 17); + return (batl & 0x40) && ((virt & mask) == (bath & mask)); +} + +inline int BatTranslate( int bath, int batl, int virt ) { + return (virt & 0x007fffff) | (batl & 0xfffe0000); +} + +/* translate address */ +int PpcVirt2phys( int virt, int inst ) { + int msr = GetMSR(); + int txmask = inst ? 0x20 : 0x10; + int i, bath, batl, sr, sdr1, physbase, vahi, valo; + int npteg, hash, hashmask, ptehi, ptelo, ptegaddr; + int vsid, pteh, ptevsid, pteapi; + + if( msr & txmask ) { + sr = GetSR( virt >> 28 ); + vsid = sr & 0xfffffff; + vahi = vsid >> 4; + valo = (vsid << 28) | (virt & 0xfffffff); + if( sr & 0x80000000 ) { + return valo; + } + + for( i = 0; i < 4; i++ ) { + GetBat( i, inst, &bath, &batl ); + if( BatHit( bath, batl, virt ) ) { + return BatTranslate( bath, batl, virt ); + } + } + + sdr1 = GetSDR1(); + + physbase = sdr1 & ~0xffff; + hashmask = ((sdr1 & 0x1ff) << 10) | 0x3ff; + hash = (vsid & 0x7ffff) ^ ((valo >> 12) & 0xffff); + npteg = hashmask + 1; + + for( pteh = 0; pteh < 0x80; pteh += 64, hash ^= 0x7ffff ) { + ptegaddr = ((hashmask & hash) * 64) + physbase; + + for( i = 0; i < 8; i++ ) { + ptehi = GetPhys( ptegaddr + (i * 8) ); + ptelo = GetPhys( ptegaddr + (i * 8) + 4 ); + + ptevsid = (ptehi >> 7) & 0xffffff; + pteapi = ptehi & 0x3f; + + if( (ptehi & 64) != pteh ) continue; + if( ptevsid != (vsid & 0xffffff) ) continue; + if( pteapi != ((virt >> 22) & 0x3f) ) continue; + + return (ptelo & 0xfffff000) | (virt & 0xfff); + } + } + return -1; + } else { + return virt; + } +} + +/* Add a new page table entry for the indicated mapping */ +BOOLEAN InsertPageEntry( int virt, int phys, int slot, int _sdr1 ) { + int i, ptehi, ptelo; + int sdr1 = _sdr1 ? _sdr1 : GetSDR1(); + int sr = GetSR( (virt >> 28) & 0xf ); + int vsid = sr & 0xfffffff; + int physbase = sdr1 & ~0xffff; + int hashmask = ((sdr1 & 0x1ff) << 10) | 0x3ff; + int valo = (vsid << 28) | (virt & 0xfffffff); + int hash = (vsid & 0x7ffff) ^ ((valo >> 12) & 0xffff); + int ptegaddr = ((hashmask & hash) * 64) + physbase; + + for( i = 0; i < 8; i++ ) { + ptehi = GetPhys( ptegaddr + (i * 8) ); + + if( (slot != i) && (ptehi & 0x80000000) ) continue; + + ptehi = (1 << 31) | (vsid << 7) | ((virt >> 22) & 0x3f); + ptelo = phys & ~0xfff; + + SetPhys( ptegaddr + (i * 8), ptehi ); + SetPhys( ptegaddr + (i * 8) + 4, ptelo ); + + return TRUE; + } + + return FALSE; +}
Added: branches/powerpc/reactos/ntoskrnl/ke/powerpc/ppc_irq.c URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/ntoskrnl/ke/powe... ============================================================================== --- branches/powerpc/reactos/ntoskrnl/ke/powerpc/ppc_irq.c (added) +++ branches/powerpc/reactos/ntoskrnl/ke/powerpc/ppc_irq.c Wed Jan 3 12:31:26 2007 @@ -1,0 +1,739 @@ +/* $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> + +#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 */ + +#define NR_TRAPS 16 +#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_TRAPS, 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 trap_handler_0(void); +void trap_handler_1(void); +void trap_handler_2(void); +void trap_handler_3(void); +void trap_handler_4(void); +void trap_handler_5(void); +void trap_handler_6(void); +void trap_handler_7(void); +void trap_handler_8(void); +void trap_handler_9(void); +void trap_handler_10(void); +void trap_handler_11(void); +void trap_handler_12(void); +void trap_handler_13(void); +void trap_handler_14(void); +void trap_handler_15(void); + +static unsigned int trap_handler[NR_TRAPS] __attribute__((unused)) = +{ + (int)&trap_handler_0, + (int)&trap_handler_1, + (int)&trap_handler_2, + (int)&trap_handler_3, + (int)&trap_handler_4, + (int)&trap_handler_5, + (int)&trap_handler_6, + (int)&trap_handler_7, + (int)&trap_handler_8, + (int)&trap_handler_9, + (int)&trap_handler_10, + (int)&trap_handler_11, + (int)&trap_handler_12, + (int)&trap_handler_13, + (int)&trap_handler_14, + (int)&trap_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_TRAPS][MAXIMUM_PROCESSORS]; +#else +static ISR_TABLE IsrTable[NR_TRAPS][1]; +#endif + +#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L') + +/* FUNCTIONS ****************************************************************/ + +VOID +INIT_FUNCTION +NTAPI +KeInitInterrupts (VOID) +{ + int i, j; + + /* + * Setup the IDT entries to point to the interrupt handlers + */ + for (i=0;i<NR_TRAPS;i++) + { +#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) +{ +} + +static VOID +KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame, + PKIRQ_TRAPFRAME IrqTrapFrame) +{ +} + +/* + * 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->PreviousMode != 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, 0, 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, 0, 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][(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 (vector, + vector, + &old_level)) + { + return; + } + + + /* + * Enable interrupts + * NOTE: Only higher priority interrupts will get through + */ + _enable(); + +#ifndef CONFIG_SMP + if (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) + { + 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; + } + + _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_TRAPS;i++) + { + printed = FALSE; + KeRaiseIrql(i,&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 < 0 || Vector >= NR_TRAPS) + return FALSE; + + ASSERT (InterruptObject->Number < KeNumberProcessors); + + KeSetSystemAffinityThread(1 << InterruptObject->Number); + + CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number]; + + KeRaiseIrql(Vector,&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, 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] + [(ULONG)InterruptObject->Number]; + + /* Raise IRQL to required level and lock table */ + KeRaiseIrql(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_TRAPS; i++) + { + if (IsrTable[i][j].Count) + { + DPRINT1(" Irq %x(%d): %d\n", i, i, IsrTable[i][j].Count); + } + } + } +} + +/* EOF */
Modified: branches/powerpc/reactos/ntoskrnl/ntoskrnl.rbuild URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/ntoskrnl/ntoskrn... ============================================================================== --- branches/powerpc/reactos/ntoskrnl/ntoskrnl.rbuild (original) +++ branches/powerpc/reactos/ntoskrnl/ntoskrnl.rbuild Wed Jan 3 12:31:26 2007 @@ -49,6 +49,9 @@ <if property="ARCH" value="powerpc"> <directory name="powerpc"> <file first="true">main_asm.S</file> + <file>mmu.c</file> + <file>cpu.c</file> + <file>exp.c</file> <file>kiinit.c</file> <file>ppc_irq.c</file> </directory>