VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts) { ULONG_PTR EFlags; /* Save EFlags and disable interrupts */ EFlags = __readeflags(); _disable(); /* Initialize and mask the PIC */ HalpInitializeLegacyPIC(); /* Initialize the I/O APIC */ ApicInitializeIOApic(); /* Manually reserve some vectors */ HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8; HalpVectorToIndex[APC_VECTOR] = 99; HalpVectorToIndex[DISPATCH_VECTOR] = 99; /* Set interrupt handlers in the IDT */ KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt); #ifndef _M_AMD64 KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt); KeRegisterInterruptHandler(DISPATCH_VECTOR, HalpDispatchInterrupt); #endif /* Register the vectors for APC and dispatch interrupts */ HalpRegisterVector(IDT_INTERNAL, 0, APC_VECTOR, APC_LEVEL); HalpRegisterVector(IDT_INTERNAL, 0, DISPATCH_VECTOR, DISPATCH_LEVEL); /* Restore interrupt state */ if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; __writeeflags(EFlags); }
VOID HalpEnableInterruptHandler ( IN UCHAR ReportFlags, IN ULONG BusInterruptVector, IN ULONG SystemInterruptVector, IN KIRQL SystemIrql, IN VOID (*HalInterruptServiceRoutine)(VOID), IN KINTERRUPT_MODE InterruptMode ) /*++ Routine Description: This function connects & registers an IDT vectors usage by the HAL. Arguments: Return Value: --*/ { // // Remember which vector the hal is connecting so it can be reported // later on // HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql); // // Connect the IDT and enable the vector now // KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine); HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode); }
BOOLEAN HalpCreateSioStructures ( VOID ) /*++ Routine Description: This routine initializes the structures necessary for SIO operations and connects the intermediate interrupt dispatcher. Arguments: None. Return Value: If the second level interrupt dispatcher is connected, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { UCHAR DataByte; KIRQL oldIrql; // // Initialize the Machine Check interrupt handler // if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt, HalpHandleMachineCheck, NULL, NULL, MACHINE_CHECK_VECTOR, MACHINE_CHECK_LEVEL, MACHINE_CHECK_LEVEL, Latched, FALSE, 0, FALSE, InternalUsage, MACHINE_CHECK_VECTOR ) == FALSE) { KeBugCheck(HAL_INITIALIZATION_FAILED); } // // Enable NMI IOCHK# and PCI SERR# // DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus); WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus, DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI); // // Clear the SIO NMI disable bit. This bit is the high order of the // NMI enable register. // DataByte = 0; WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable, DataByte ); // // Connect the external interrupt handler // PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt; // // register the interrupt vector // HalpRegisterVector(InternalUsage, EXTERNAL_INTERRUPT_VECTOR, EXTERNAL_INTERRUPT_VECTOR, HIGH_LEVEL); // Connect directly to the decrementer handler. This is done // directly rather than thru HalpEnableInterruptHandler due to // special handling required because the handler calls KdPollBreakIn(). // PCR->InterruptRoutine[DECREMENT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt; // // Initialize and connect the Timer 1 interrupt (IRQ0) // if (HalpEnableInterruptHandler( &HalpProfileInterrupt, (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt, (PVOID) NULL, (PKSPIN_LOCK)NULL, PROFILE_VECTOR, PROFILE_LEVEL, PROFILE_LEVEL, Latched, TRUE, 0, FALSE, DeviceUsage, PROFILE_VECTOR ) == FALSE) { KeBugCheck(HAL_INITIALIZATION_FAILED); } // // Disable Timer 1; only used by profiling // HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL); // // Set default profile rate // HalSetProfileInterval(5000); // // Raise the IRQL while the SIO interrupt controller is initialized. // KeRaiseIrql(CLOCK2_LEVEL, &oldIrql); // // Initialize any planar registers // HalpInitPlanar(); // // Enable the clock interrupt // HalpUpdateDecrementer(1000); // Get those decrementer ticks going // // Set ISA bus interrupt affinity. // HalpIsaBusAffinity = PCR->SetMember; // // Restore IRQL level. // KeLowerIrql(oldIrql); // // DMA command - set assert level // DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus); WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus, DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW); // // Initialize the DMA mode registers to a default value. // Disable all of the DMA channels except channel 4 which is that // cascade of channels 0-3. // WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask, 0x0F ); WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask, 0x0E ); return(TRUE); }
BOOLEAN HalpEnableInterruptHandler ( IN PKINTERRUPT Interrupt, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock OPTIONAL, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN CCHAR ProcessorNumber, IN BOOLEAN FloatingSave, IN UCHAR ReportFlags, IN KIRQL BusVector ) /*++ Routine Description: This function connects & registers an IDT vectors usage by the HAL. Arguments: Return Value: --*/ { // // Remember which vector the hal is connecting so it can be reported // later on // KeInitializeInterrupt( Interrupt, ServiceRoutine, ServiceContext, SpinLock, Vector, Irql, SynchronizeIrql, InterruptMode, ShareVector, ProcessorNumber, FloatingSave ); // // Don't fail if the interrupt cannot be connected. // if (!KeConnectInterrupt( Interrupt )) { return(FALSE); } HalpRegisterVector (ReportFlags, BusVector, Vector, Irql); // // Connect the IDT and enable the vector now // return(TRUE); }