VOID HalpInitializeNMI( VOID ) /*++ Routine Description: This function is called to intialize SIO NMI interrupts. Arguments: None. Return Value: None. --*/ { UCHAR DataByte; // // Initialize the SIO NMI interrupt. // KeInitializeInterrupt( &HalpEisaNmiInterrupt, HalHandleNMI, NULL, NULL, EISA_NMI_VECTOR, EISA_NMI_LEVEL, EISA_NMI_LEVEL, LevelSensitive, FALSE, 0, FALSE ); // // Don't fail if the interrupt cannot be connected. // KeConnectInterrupt( &HalpEisaNmiInterrupt ); // // Clear the Eisa NMI disable bit. This bit is the high order of the // NMI enable register. Note that the other bits should be left as // they are, according to the chip's documentation. // //[wem] ?? Avanti simply writes zero to NmiEnable -- OK DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&DataByte))->NmiDisable = 0; WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte); #ifdef DBG DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n", DataByte); #endif }
VOID HalpInitializeNMI( VOID ) /*++ Routine Description: This function is called to intialize SIO NMI interrupts. Arguments: None. Return Value: None. --*/ { UCHAR DataByte; // // Initialize the SIO NMI interrupt. // KeInitializeInterrupt( &HalpEisaNmiInterrupt, HalHandleNMI, NULL, NULL, EISA_NMI_VECTOR, EISA_NMI_LEVEL, EISA_NMI_LEVEL, LevelSensitive, FALSE, 0, FALSE ); // // Don't fail if the interrupt cannot be connected. // KeConnectInterrupt( &HalpEisaNmiInterrupt ); // // Clear the Eisa NMI disable bit. This bit is the high order of the // NMI enable register. // DataByte = 0; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte ); }
/* * @implemented */ NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave) { PKINTERRUPT Interrupt; PKINTERRUPT InterruptUsed; PIO_INTERRUPT IoInterrupt; PKSPIN_LOCK SpinLockUsed; BOOLEAN FirstRun; CCHAR Count = 0; KAFFINITY Affinity; PAGED_CODE(); /* Assume failure */ *InterruptObject = NULL; /* Get the affinity */ Affinity = ProcessorEnableMask & KeActiveProcessors; while (Affinity) { /* Increase count */ if (Affinity & 1) Count++; Affinity >>= 1; } /* Make sure we have a valid CPU count */ if (!Count) return STATUS_INVALID_PARAMETER; /* Allocate the array of I/O Interrupts */ IoInterrupt = ExAllocatePoolWithTag(NonPagedPool, (Count - 1) * sizeof(KINTERRUPT) + sizeof(IO_INTERRUPT), TAG_KINTERRUPT); if (!IoInterrupt) return STATUS_INSUFFICIENT_RESOURCES; /* Select which Spinlock to use */ SpinLockUsed = SpinLock ? SpinLock : &IoInterrupt->SpinLock; /* We first start with a built-in Interrupt inside the I/O Structure */ *InterruptObject = &IoInterrupt->FirstInterrupt; Interrupt = (PKINTERRUPT)(IoInterrupt + 1); FirstRun = TRUE; /* Start with a fresh structure */ RtlZeroMemory(IoInterrupt, sizeof(IO_INTERRUPT)); /* Now create all the interrupts */ Affinity = ProcessorEnableMask & KeActiveProcessors; for (Count = 0; Affinity; Count++, Affinity >>= 1) { /* Check if it's enabled for this CPU */ if (Affinity & 1) { /* Check which one we will use */ InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt; /* Initialize it */ KeInitializeInterrupt(InterruptUsed, ServiceRoutine, ServiceContext, SpinLockUsed, Vector, Irql, SynchronizeIrql, InterruptMode, ShareVector, Count, FloatingSave); /* Connect it */ if (!KeConnectInterrupt(InterruptUsed)) { /* Check how far we got */ if (FirstRun) { /* We failed early so just free this */ ExFreePoolWithTag(IoInterrupt, TAG_KINTERRUPT); } else { /* Far enough, so disconnect everything */ IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt); } /* And fail */ return STATUS_INVALID_PARAMETER; } /* Now we've used up our First Run */ if (FirstRun) { FirstRun = FALSE; } else { /* Move on to the next one */ IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt++; } } } /* Return Success */ return STATUS_SUCCESS; }
BOOLEAN HalpInitializeLegoInterrupts( VOID ) /*++ Routine Description: This routine initializes the structures necessary for EISA & PCI operations and connects the intermediate interrupt dispatchers. It also initializes the ISA interrupt controller; Lego's SIO-based interrupt controller is compatible with Avanti and with the EISA interrupt contoller used on Jensen. Arguments: None. Return Value: If the second level interrupt dispatchers are connected, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { KIRQL oldIrql; // // Initialize the EISA NMI interrupt. // HalpInitializeNMI(); // // Directly connect the ISA interrupt dispatcher to the level for // ISA bus interrupt. // // N.B. This vector is reserved for exclusive use by the HAL (see // interrupt initialization. // PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch; HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive); // // Initialize the interrupt dispatchers for PCI & Server management interrupts. // KeInitializeInterrupt( &HalpPciInterrupt, HalpPciInterruptHandler, (PVOID) HalpLegoPciInterruptMasterQva, // Service Context (PKSPIN_LOCK)NULL, PCI_VECTOR, PCI_DEVICE_LEVEL, PCI_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE ); if (!KeConnectInterrupt( &HalpPciInterrupt )) { return(FALSE); } KeInitializeInterrupt( &HalpServerMgmtInterrupt, HalpServerMgmtInterruptHandler, (PVOID) HalpLegoServerMgmtQva, // Service Context is... (PKSPIN_LOCK)NULL, SERVER_MGMT_VECTOR, SERVER_MGMT_LEVEL, SERVER_MGMT_LEVEL, LevelSensitive, TRUE, 0, FALSE ); if (!KeConnectInterrupt( &HalpServerMgmtInterrupt )) { return(FALSE); } // // Intitialize interrupt controller // KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql); // // We must initialize the SIO's PICs, for ISA interrupts. // HalpInitializeSioInterrupts(); // // There's no initialization required for the Lego PCI interrupt // "controller," as it's the wiring of the hardware, rather than a // PIC like the 82c59 that directs interrupts. We do set the IMR to // zero to disable all interrupts, initially. // HalpInitializePciInterrupts(); // // Setup server management interrupts. // On return, server management interrupts will be unmasked, // but secondary dispatch will not be performed unless appropriate // boolean has been set due to enable call. // HalpInitializeServerMgmtInterrupts(); // // Restore the IRQL. // KeLowerIrql(oldIrql); // // Initialize the EISA DMA mode registers to a default value. // Disable all of the DMA channels except channel 4 which is the // cascade of channels 0-3. // WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask, 0x0F ); WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask, 0x0E ); return(TRUE); }
BOOLEAN HalpInitializeMikasaAndNoritakeInterrupts( VOID ) /*++ Routine Description: This routine initializes the structures necessary for EISA & PCI operations and connects the intermediate interrupt dispatchers. It also initializes the EISA interrupt controller; the Mikasa and Noritake ESC interrupt controllers are compatible with the EISA interrupt contoller used on Jensen. Arguments: None. Return Value: If the second level interrupt dispatchers are connected, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { KIRQL oldIrql; // // Initialize the EISA NMI interrupt. // HalpInitializeNMI(); // // Initialize the interrupt dispatchers for PCI & EISA I/O interrupts. // if( HalpNoritakePlatform ) { KeInitializeInterrupt( &HalpPciInterrupt, HalpPciInterruptHandler, (PVOID) HalpNoritakePciIr1Qva, // Service Context (PKSPIN_LOCK)NULL, PCI_VECTOR, PCI_DEVICE_LEVEL, PCI_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE ); } else { KeInitializeInterrupt( &HalpPciInterrupt, HalpPciInterruptHandler, (PVOID) HalpMikasaPciIrQva, // Service Context (PKSPIN_LOCK)NULL, PCI_VECTOR, PCI_DEVICE_LEVEL, PCI_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE ); } if (!KeConnectInterrupt( &HalpPciInterrupt )) { return(FALSE); } KeInitializeInterrupt( &HalpEisaInterrupt, HalpEisaInterruptHandler, (PVOID) HalpEisaIntAckBase, // Service Context is... (PKSPIN_LOCK)NULL, PIC_VECTOR, EISA_DEVICE_LEVEL, EISA_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE ); if (!KeConnectInterrupt( &HalpEisaInterrupt )) { return(FALSE); } // // Intitialize interrupt controller // KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql); // // There's no initialization required for the Mikasa PCI interrupt // "controller," as it's the wiring of the hardware, rather than a // PIC like the 82c59 that directs interrupts. We do set the IMR to // zero to disable all interrupts, initially. // // The Noritake requires a separate routine to setup the 3 interrupt // mask registers correctly. // if( HalpNoritakePlatform ) { HalpInitializeNoritakePciInterrupts(); } else { HalpInitializeMikasaPciInterrupts(); } // // We must initialize the ESC's PICs, for EISA interrupts. // HalpInitializeEisaInterrupts(); // // Restore the IRQL. // KeLowerIrql(oldIrql); // // Initialize the EISA DMA mode registers to a default value. // Disable all of the DMA channels except channel 4 which is the // cascade of channels 0-3. // WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask, 0x0F ); WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->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); }