diff --git a/reactos/boot/freeldr/freeldr/arch/arm/loader.c b/reactos/boot/freeldr/freeldr/arch/arm/loader.c index ab30e324be7..25c6dad8692 100644 --- a/reactos/boot/freeldr/freeldr/arch/arm/loader.c +++ b/reactos/boot/freeldr/freeldr/arch/arm/loader.c @@ -742,7 +742,7 @@ ArmSetupPageDirectory(VOID) ArmTable->Pte[0] = Pte; // - // Map the page in MMIO space that contains the serial port into virtual memory + // Map the page in MMIO space that contains the serial port and timers // Pte.L1.Section.BaseAddress = ArmBoardBlock->UartRegisterBase >> PDE_SHIFT; ArmTable->Pte[UART_VIRTUAL >> PDE_SHIFT] = Pte; diff --git a/reactos/hal/halarm/generic/hal.c b/reactos/hal/halarm/generic/hal.c index 88ab9b39579..995c2d28d57 100644 --- a/reactos/hal/halarm/generic/hal.c +++ b/reactos/hal/halarm/generic/hal.c @@ -17,8 +17,10 @@ #include #include #include +#include #include #include +#include #define NDEBUG #include @@ -32,6 +34,9 @@ #undef KeRaiseIrql #undef KeReleaseSpinLock +#define READ_REGISTER_ULONG(r) (*(volatile ULONG * const)(r)) +#define WRITE_REGISTER_ULONG(r, v) (*(volatile ULONG *)(r) = (v)) + /* DATA **********************************************************************/ ULONG _KdComPortInUse = 0; @@ -371,16 +376,210 @@ HalHandleNMI( UNIMPLEMENTED; } +VOID +NTAPI +HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PCHAR CommandLine; + + /* Make sure we have a loader block and command line */ + if ((LoaderBlock) && (LoaderBlock->LoadOptions)) + { + /* Read the command line */ + CommandLine = LoaderBlock->LoadOptions; + + /* Check for initial breakpoint */ + if (strstr(CommandLine, "BREAK")) DbgBreakPoint(); + } +} + +// +// INTs on the Versatile: +// +// 0 WATCHDOG -> We use it for profiling +// 1 SOFTWARE INTERRUPT -> We use it for APC delivery +// 2 COMM RX -> We use it for DPC delivery +// 3 COMM TX -> We use it for IPI delivery +// 4 TIMER0/1 -> Use for Clock Interrupt. +// 5+ XXX -> Mapped to to actual device +// +// So we have the following IRQL masks: +// PASSIVE_LEVEL - 0xFFFFFFFF (enable all interrupts) +// APC_LEVEL - 0xFFFFFFFD (disable interrupt 1) +// DISPATCH_LEVEL - 0xFFFFFFF9 (disable interrupts 1, 2) +// DEVICE_LEVEL_0 - 0xFFFFFFD9 (disable interrupts 1, 2, 5) +// DEVICE_LEVEL_N - 0x19 (everything disabled except 0, 3, 4) +// PROFILE_LEVEL - 0x18 (everything disabled except, 3, 4) +// CLOCK_LEVEL - 0x10 (everything disabled except 4) +// POWER_LEVEL, IPI_LEVEL, HIGH_LEVEL - 0x00 (everything disabled) + +ULONG HalpIrqlTable[] = +{ + 0xFFFFFFFF, // IRQL 0 PASSIVE_LEVEL + 0xFFFFFFFD, // IRQL 1 APC_LEVEL + 0xFFFFFFF9, // IRQL 2 DISPATCH_LEVEL + 0xFFFFFFD9, // IRQL 3 + 0xFFFFFF99, // IRQL 4 + 0xFFFFFF19, // IRQL 5 + 0xFFFFFE19, // IRQL 6 + 0xFFFFFC19, // IRQL 7 + 0xFFFFF819, // IRQL 8 + 0xFFFFF019, // IRQL 9 + 0xFFFFE019, // IRQL 10 + 0xFFFFC019, // IRQL 11 + 0xFFFF8019, // IRQL 12 + 0xFFFF0019, // IRQL 13 + 0xFFFE0019, // IRQL 14 + 0xFFFC0019, // IRQL 15 + 0xFFF80019, // IRQL 16 + 0xFFF00019, // IRQL 17 + 0xFFE00019, // IRQL 18 + 0xFFC00019, // IRQL 19 + 0xFF800019, // IRQL 20 + 0xFF000019, // IRQL 21 + 0xFE000019, // IRQL 22 + 0xFC000019, // IRQL 23 + 0xF0000019, // IRQL 24 + 0x80000019, // IRQL 25 + 0x19, // IRQL 26 + 0x18, // IRQL 27 PROFILE_LEVEL + 0x10, // IRQL 28 CLOCK2_LEVEL + 0x00, // IRQL 29 IPI_LEVEL + 0x00, // IRQL 30 POWER_LEVEL + 0x00, // IRQL 31 HIGH_LEVEL +}; + + +VOID +HalpStallInterrupt(VOID) +{ + DPRINT1("STALL INTERRUPT!!!\n"); + while (TRUE); +} + +VOID +HalpInitializeInterrupts(VOID) +{ + ULONG i; + PKPCR Pcr = (PKPCR)KeGetPcr(); + + // + // Fill out the IRQL mappings + // + for (i = 0; i < (HIGH_LEVEL + 1); i++) + { + // + // Save the valeue in the PCR + // + Pcr->IrqlTable[i] = HalpIrqlTable[i]; + } + + // + // Setup the clock and profile interrupt + // + Pcr->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt; + // Pcr->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt; +} + +ULONG HalpCurrentTimeIncrement, HalpNextTimeIncrement, HalpNextIntervalCount; + +#define VICINTENABLE (PVOID)0xE0040010 +#define VICINTENCLEAR (PVOID)0xE0040014 +#define VICSOFTINT (PVOID)0xE0040018 +#define VICSOFTINTCLEAR (PVOID)0xE004001C + +/* + * @implemented + */ BOOLEAN NTAPI -HalInitSystem( - ULONG BootPhase, - PLOADER_PARAMETER_BLOCK LoaderBlock) +HalInitSystem(IN ULONG BootPhase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - UNIMPLEMENTED; - - return TRUE; + PKPRCB Prcb = KeGetCurrentPrcb(); + + // + // Check the boot phase + // + if (!BootPhase) + { + // + // Get command-line parameters + // + HalpGetParameters(LoaderBlock); + +#if DBG + // + // Checked HAL requires checked kernel + // + if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) + { + // + // No match, bugcheck + // + KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, 1, 0); + } +#else + // + // Release build requires release HAL + // + if (Prcb->BuildType & PRCB_BUILD_DEBUG) + { + // + // No match, bugcheck + // + KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0); + } +#endif + +#ifdef CONFIG_SMP + // + // SMP HAL requires SMP kernel + // + if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) + { + // + // No match, bugcheck + // + KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0); + } +#endif + + // + // Validate the PRCB + // + if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) + { + // + // Validation failed, bugcheck + // + KeBugCheckEx(MISMATCHED_HAL, 1, Prcb->MajorVersion, 1, 0); + } + + // + // Setup time increments to 10ms and 1ms + // + HalpCurrentTimeIncrement = 100000; + HalpNextTimeIncrement = 100000; + HalpNextIntervalCount = 0; + KeSetTimeIncrement(100000, 10000); + + // + // Initialize interrupts + // + HalpInitializeInterrupts(); + } + else if (BootPhase == 1) + { + UNIMPLEMENTED; + while (TRUE); + } + + // + // All done, return + // + return TRUE; } @@ -484,10 +683,35 @@ HalRequestIpi( VOID FASTCALL -HalRequestSoftwareInterrupt( - KIRQL Request) +HalRequestSoftwareInterrupt(IN KIRQL Request) { - UNIMPLEMENTED; + ULONG Interrupt = 0; + + // + // Get the interrupt that maches this IRQL level + // + switch (Request) + { + case APC_LEVEL: + + Interrupt = 1 << 1; + break; + + case DISPATCH_LEVEL: + + Interrupt = 1 << 2; + break; + + default: + + ASSERT(FALSE); + } + + // + // Force a software interrupt + // + DPRINT1("About to force interrupt mask: %d\n", Interrupt); + WRITE_REGISTER_ULONG(VICSOFTINT, Interrupt); } VOID FASTCALL @@ -766,23 +990,79 @@ KeStallExecutionProcessor( VOID FASTCALL -KfLowerIrql( - KIRQL NewIrql) +KfLowerIrql(IN KIRQL NewIrql) { - KeGetPcr()->CurrentIrql = NewIrql; - UNIMPLEMENTED; + ULONG InterruptMask; + PKPCR Pcr = (PKPCR)KeGetPcr(); + + // + // Validate the new IRQL + // + ASSERT(NewIrql <= Pcr->CurrentIrql); + + // + // IRQLs are internally 8 bits + // + NewIrql &= 0xFF; + + // + // Setup the interrupt mask for this IRQL + // + InterruptMask = KeGetPcr()->IrqlTable[NewIrql]; + DPRINT1("New IRQL: %d InterruptMask: %lx\n", NewIrql, InterruptMask); + + // + // Clear interrupts associated to the old IRQL + // + WRITE_REGISTER_ULONG(VICINTENCLEAR, 0xFFFFFFFF); + + // + // Set the new interrupt mask + // PL190 VIC support only for now + // + WRITE_REGISTER_ULONG(VICINTENABLE, InterruptMask); + + // + // Save the new IRQL + // + Pcr->CurrentIrql = NewIrql; } - KIRQL FASTCALL -KfRaiseIrql( - KIRQL NewIrql) +KfRaiseIrql(IN KIRQL NewIrql) { - KIRQL OldIrql = KeGetPcr()->CurrentIrql; - KeGetPcr()->CurrentIrql = NewIrql; - UNIMPLEMENTED; - + KIRQL OldIrql; + ULONG InterruptMask; + PKPCR Pcr = (PKPCR)KeGetPcr(); + + // + // Save the current IRQL + // + OldIrql = Pcr->CurrentIrql; + + // + // IRQLs are internally 8 bits + // + NewIrql &= 0xFF; + + // + // Setup the interrupt mask for this IRQL + // + InterruptMask = KeGetPcr()->IrqlTable[NewIrql]; + DPRINT1("New IRQL: %d InterruptMask: %lx\n", NewIrql, InterruptMask); + //ASSERT(NewIrql >= OldIrql); + + // + // Set the new interrupt mask + // PL190 VIC support only for now + // + WRITE_REGISTER_ULONG(VICINTENABLE, InterruptMask); + + // + // Save the new IRQL + // + Pcr->CurrentIrql = NewIrql; return OldIrql; } @@ -915,28 +1195,28 @@ WRITE_PORT_USHORT( KIRQL KeSwapIrql(IN KIRQL Irql) { - KIRQL OldIrql = KeGetPcr()->CurrentIrql; - KeGetPcr()->CurrentIrql = Irql; - UNIMPLEMENTED; - return OldIrql; + // + // Call the generic routine + // + return KfRaiseIrql(Irql); } KIRQL KeRaiseIrqlToDpcLevel(VOID) { - KIRQL OldIrql = KeGetPcr()->CurrentIrql; - KeGetPcr()->CurrentIrql = SYNCH_LEVEL; - UNIMPLEMENTED; - return OldIrql; + // + // Call the generic routine + // + return KfRaiseIrql(DISPATCH_LEVEL); } KIRQL KeRaiseIrqlToSynchLevel(VOID) { - KIRQL OldIrql = KeGetPcr()->CurrentIrql; - KeGetPcr()->CurrentIrql = SYNCH_LEVEL; - UNIMPLEMENTED; - return OldIrql; + // + // Call the generic routine + // + return KfRaiseIrql(DISPATCH_LEVEL); } BOOLEAN HalpProcessorIdentified; @@ -1136,7 +1416,7 @@ KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle) { /* Simply raise to synch */ - LockHandle->OldIrql = KfRaiseIrql(SYNCH_LEVEL); + LockHandle->OldIrql = KfRaiseIrql(DISPATCH_LEVEL); } /* diff --git a/reactos/include/reactos/armddk.h b/reactos/include/reactos/armddk.h index 7e1c7239e2f..fd51cfc13f5 100644 --- a/reactos/include/reactos/armddk.h +++ b/reactos/include/reactos/armddk.h @@ -4,15 +4,17 @@ // // IRQLs // -#define PASSIVE_LEVEL 0 -#define LOW_LEVEL 0 -#define APC_LEVEL 1 -#define DISPATCH_LEVEL 2 -#define IPI_LEVEL 7 -#define POWER_LEVEL 7 -#define PROFILE_LEVEL 8 -#define HIGH_LEVEL 8 -#define SYNCH_LEVEL (IPI_LEVEL - 1) +#define PASSIVE_LEVEL 0 +#define LOW_LEVEL 0 +#define APC_LEVEL 1 +#define DISPATCH_LEVEL 2 +#define SYNCH_LEVEL DISPATCH_LEVEL +#define PROFILE_LEVEL 27 +#define CLOCK1_LEVEL 28 +#define CLOCK2_LEVEL 28 +#define IPI_LEVEL 29 +#define POWER_LEVEL 30 +#define HIGH_LEVEL 31 // // FIXME: mmtypes.h? @@ -83,8 +85,8 @@ typedef struct _KPCR PVOID InstructionBusError; ULONG CachePolicy; ULONG AlignedCachePolicy; - UCHAR IrqlMask[64]; - UCHAR IrqlTable[64]; +// UCHAR IrqlMask[64]; + ULONG IrqlTable[HIGH_LEVEL + 1]; UCHAR CurrentIrql; KAFFINITY SetMember; struct _KTHREAD *CurrentThread;