Esempio n. 1
0
/*
 * @implemented
 */
VP_STATUS
NTAPI
VideoPortDisableInterrupt(IN PVOID HwDeviceExtension)
{
#ifndef _M_AMD64
    PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;

    /* Get the device extension */
    DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);

    /* Fail if the driver didn't register an ISR */
    if (!DeviceExtension->DriverExtension->InitializationData.HwInterrupt)
    {
        /* No ISR, no interrupts */
        return ERROR_INVALID_FUNCTION;
    }

    /* Disable the interrupt and return */
    HalDisableSystemInterrupt(DeviceExtension->InterruptVector, 0);
    return NO_ERROR;
#else
    /* FIXME: Function still present? If so what to use instead of HalDisableSystemInterrupt? */
    UNIMPLEMENTED;
    return ERROR_INVALID_FUNCTION;
#endif
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
VOID
KeDumpMachineState (
    IN PKPROCESSOR_STATE ProcessorState,
    IN PCHAR Buffer,
    IN PULONG BugCheckParameters,
    IN ULONG NumberOfParameters,
    IN PKE_BUGCHECK_UNICODE_TO_ANSI UnicodeToAnsiRoutine
)

/*++

Routine Description:

    This function formats and displays the machine state at the time of the
    to bug check.

Arguments:

    ProcessorState - Supplies a pointer to a processor state record.

    Buffer - Supplies a pointer to a buffer to be used to output machine
        state information.

    BugCheckParameters - Supplies a pointer to an array of additional
        bug check information.

    NumberOfParameters - Suppiles the size of the bug check parameters
        array.

    UnicodeToAnsiRoutine - Supplies a pointer to a routine to convert Unicode strings
        to Ansi strings without touching paged translation tables.

Return Value:

    None.

--*/

{

    PCONTEXT ContextRecord;
    ULONG ControlPc;
    PLDR_DATA_TABLE_ENTRY DataTableEntry;
    ULONG DisplayColumn;
    ULONG DisplayHeight;
    ULONG DisplayRow;
    ULONG DisplayWidth;
    UNICODE_STRING DllName;
    ULONG EstablisherFrame;
    PRUNTIME_FUNCTION FunctionEntry;
    PVOID ImageBase;
    ULONG Index;
    BOOLEAN InFunction;
    ULONG LastStack;
    PLIST_ENTRY ModuleListHead;
    PLIST_ENTRY NextEntry;
    ULONG NextPc;
    ULONG StackLimit;
    UCHAR AnsiBuffer[ 32 ];
    ULONG DateStamp;

    //
    // Call the HAL to force all external interrupts to be disabled
    // at the interrupt controller. PowerPC optimization does not
    // do this when raising to high level.
    //
    for (Index = 0; Index < MAXIMUM_VECTOR; Index++) {
        HalDisableSystemInterrupt(Index, HIGH_LEVEL);
    }

    //
    // Query display parameters.
    //

    HalQueryDisplayParameters(&DisplayWidth,
                              &DisplayHeight,
                              &DisplayColumn,
                              &DisplayRow);

    //
    // Display any addresses that fall within the range of any module in
    // the loaded module list.
    //

    for (Index = 0; Index < NumberOfParameters; Index += 1) {
        ImageBase = KiPcToFileHeader((PVOID)*BugCheckParameters,
                                     &ImageBase,
                                     &DataTableEntry);

        if (ImageBase != NULL) {
            sprintf(Buffer,
                    "*** %08lX has base at %08lX - %s\n",
                    *BugCheckParameters,
                    ImageBase,
                    (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer )));

            HalDisplayString(Buffer);
        }

        BugCheckParameters += 1;
    }

    //
    // Virtually unwind to the caller of bug check.
    //

    ContextRecord = &ProcessorState->ContextFrame;
    LastStack = ContextRecord->Gpr1;
    ControlPc = ContextRecord->Lr - 4;
    NextPc = ControlPc;
    FunctionEntry = KiLookupFunctionEntry(ControlPc);
    if (FunctionEntry != NULL) {
        NextPc = RtlVirtualUnwind(ControlPc,
                                  FunctionEntry,
                                  ContextRecord,
                                  &InFunction,
                                  &EstablisherFrame,
                                  NULL,
                                  0,
                                  0xffffffff);
    }

    //
    // At this point the context record contains the machine state at the
    // call to bug check.
    //
    // Put out the machine state at the time of the bugcheck.
    //

    sprintf(Buffer,
            "\n Machine State at Call to Bug Check    IAR:%08lX MSR:%08lX\n",
            ContextRecord->Lr,
            ContextRecord->Msr);

    HalDisplayString(Buffer);

    //
    // Format and output the integer registers.
    //

    sprintf(Buffer,
            " R0:%8lX  R1:%8lX  R2:%8lX  R3:%8lX  R4:%8lX  R5:%8lX\n",
            ContextRecord->Gpr0,
            ContextRecord->Gpr1,
            ContextRecord->Gpr2,
            ContextRecord->Gpr3,
            ContextRecord->Gpr4,
            ContextRecord->Gpr5);

    HalDisplayString(Buffer);

    sprintf(Buffer,
            " R6:%8lX  R7:%8lX  R8:%8lX  R9:%8lX R10:%8lX R11:%8lX\n",
            ContextRecord->Gpr6,
            ContextRecord->Gpr7,
            ContextRecord->Gpr8,
            ContextRecord->Gpr9,
            ContextRecord->Gpr10,
            ContextRecord->Gpr11);

    HalDisplayString(Buffer);

    sprintf(Buffer,
            "R12:%8lX R13:%8lX R14:%8lX R15:%8lX R16:%8lX R17:%8lX\n",
            ContextRecord->Gpr12,
            ContextRecord->Gpr13,
            ContextRecord->Gpr14,
            ContextRecord->Gpr15,
            ContextRecord->Gpr16,
            ContextRecord->Gpr17);

    HalDisplayString(Buffer);

    sprintf(Buffer,
            "R18:%8lX R19:%8lX R20:%8lX R21:%8lX R22:%8lX R23:%8lX\n",
            ContextRecord->Gpr18,
            ContextRecord->Gpr19,
            ContextRecord->Gpr20,
            ContextRecord->Gpr21,
            ContextRecord->Gpr22,
            ContextRecord->Gpr23);

    HalDisplayString(Buffer);

    sprintf(Buffer,
            "R24:%8lX R25:%8lX R26:%8lX R27:%8lX R28:%8lX R29:%8lX\n",
            ContextRecord->Gpr24,
            ContextRecord->Gpr25,
            ContextRecord->Gpr26,
            ContextRecord->Gpr27,
            ContextRecord->Gpr28,
            ContextRecord->Gpr29);

    HalDisplayString(Buffer);

    sprintf(Buffer,
            "R30:%8lX R31:%8lX  CR:%8lX CTR:%8lX XER:%8lX\n",
            ContextRecord->Gpr30,
            ContextRecord->Gpr31,
            ContextRecord->Cr,
            ContextRecord->Ctr,
            ContextRecord->Xer);

    HalDisplayString(Buffer);

#if 0

    //
    // I'd much rather see a longer stack trace and skip the floating
    // point stuff when the system crashes.  plj
    //

    //
    // Format and output the floating registers.
    //
    DumpFloat = (PULONG)(&ContextRecord->Fpr0);
    sprintf(Buffer,
            " F0- F3:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr4);
    sprintf(Buffer,
            " F4- F7:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr8);
    sprintf(Buffer,
            " F8-F11:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr12);
    sprintf(Buffer,
            "F12-F15:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr16);
    sprintf(Buffer,
            "F16-F19:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr20);
    sprintf(Buffer,
            "F20-F23:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr24);
    sprintf(Buffer,
            "F24-F27:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);

    DumpFloat = (PULONG)(&ContextRecord->Fpr28);
    sprintf(Buffer,
            "F28-F31:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat,
            *(DumpFloat+3),
            *(DumpFloat+2),
            *(DumpFloat+5),
            *(DumpFloat+4),
            *(DumpFloat+7),
            *(DumpFloat+6));

    HalDisplayString(Buffer);


    DumpFloat = (PULONG)(&ContextRecord->Fpscr);
    sprintf(Buffer,
            "  FPSCR:%08lX%08lX\n",
            *(DumpFloat+1),
            *DumpFloat);

    HalDisplayString(Buffer);

#define STAKWALK 4
#else
#define STAKWALK 8
#endif

    //
    // Output short stack back trace with base address.
    //

    DllName.Length = 0;
    DllName.Buffer = L"";
    if (FunctionEntry != NULL) {
        StackLimit = (ULONG)KeGetCurrentThread()->KernelStack;
        HalDisplayString("Callee-Sp Return-Ra  Dll Base - Name\n");
        for (Index = 0; Index < STAKWALK; Index += 1) {
            ImageBase = KiPcToFileHeader((PVOID)ControlPc,
                                         &ImageBase,
                                         &DataTableEntry);

            sprintf(Buffer,
                    " %08lX %08lX : %08lX - %s\n",
                    ContextRecord->Gpr1,
                    NextPc + 4,
                    ImageBase,
                    (*UnicodeToAnsiRoutine)( (ImageBase != NULL) ? &DataTableEntry->BaseDllName : &DllName,
                                             AnsiBuffer, sizeof( AnsiBuffer )));

            HalDisplayString(Buffer);

            if ((NextPc != ControlPc) || (ContextRecord->Gpr1 != LastStack)) {
                ControlPc = NextPc;
                LastStack = ContextRecord->Gpr1;
                FunctionEntry = KiLookupFunctionEntry(ControlPc);
                if ((FunctionEntry != NULL) && (LastStack < StackLimit)) {
                    NextPc = RtlVirtualUnwind(ControlPc,
                                              FunctionEntry,
                                              ContextRecord,
                                              &InFunction,
                                              &EstablisherFrame,
                                              NULL,
                                              0,
                                              0xffffffff);
                } else {
                    NextPc = ContextRecord->Lr;
                }

            } else {
                break;
            }
        }
    }

    //
    // Output the build number and other useful information.
    //

    sprintf(Buffer,
            "\nIRQL : %d, DPC Active : %s, SYSVER 0x%08x\n",
            KeGetCurrentIrql(),
            KeIsExecutingDpc() ? "TRUE" : "FALSE",
            NtBuildNumber);

    HalDisplayString(Buffer);

    //
    // Output the processor id and the primary cache sizes.
    //

    sprintf(Buffer,
            "Processor Id: %d.%d, Icache: %d, Dcache: %d",
            PCR->ProcessorVersion,
            PCR->ProcessorRevision,
            PCR->FirstLevelIcacheSize,
            PCR->FirstLevelDcacheSize);

    HalDisplayString(Buffer);

    //
    // If the display width is greater than 80 + 24 (the size of a DLL
    // name and base address), then display all the modules loaded in
    // the system.
    //

    HalQueryDisplayParameters(&DisplayWidth,
                              &DisplayHeight,
                              &DisplayColumn,
                              &DisplayRow);

    if (DisplayWidth > (80 + 24)) {
        HalDisplayString("\n");
        if (KeLoaderBlock != NULL) {
            ModuleListHead = &KeLoaderBlock->LoadOrderListHead;

        } else {
            ModuleListHead = &PsLoadedModuleList;
        }

        //
        // Output display headers.
        //

        Index = 1;
        KiDisplayString(80, Index, "Dll Base DateStmp - Name");
        NextEntry = ModuleListHead->Flink;
        if (NextEntry != NULL) {

            //
            // Scan the list of loaded modules and display their base
            // address and name.
            //

            while (NextEntry != ModuleListHead) {
                Index += 1;
                DataTableEntry = CONTAINING_RECORD(NextEntry,
                                                   LDR_DATA_TABLE_ENTRY,
                                                   InLoadOrderLinks);

                if (MmDbgReadCheck(DataTableEntry->DllBase) != NULL) {
                    PIMAGE_NT_HEADERS NtHeaders;

                    NtHeaders = RtlImageNtHeader(DataTableEntry->DllBase);
                    DateStamp = NtHeaders->FileHeader.TimeDateStamp;

                } else {
                    DateStamp = 0;
                }
                sprintf(Buffer,
                        "%08lX %08lx - %s",
                        DataTableEntry->DllBase,
                        DateStamp,
                        (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer )));

                KiDisplayString(80, Index, Buffer);
                NextEntry = NextEntry->Flink;
                if (Index > DisplayHeight) {
                    break;
                }
            }
        }
    }

    //
    // Reset the current display position.
    //

    HalSetDisplayParameters(DisplayColumn, DisplayRow);

    //
    // The system has crashed, if we are running without the Kernel
    // debugger attached, attach it now.
    //

    KdInitSystem(NULL, FALSE);

    return;
}
Esempio n. 4
0
BOOLEAN
KeDisconnectInterrupt (
    __inout PKINTERRUPT Interrupt
    )

/*++

Routine Description:

    This function disconnects an interrupt object from the interrupt vector
    specified by the interrupt object. If the interrupt object is not
    connected, then a value of FALSE is returned. Else the specified interrupt
    object is disconnected from the interrupt vector, the connected state is
    set to FALSE, and TRUE is returned as the function value.

Arguments:

    Interrupt - Supplies a pointer to a control object of type interrupt.

Return Value:

    If the interrupt object is not connected, then a value of FALSE is
    returned. Else a value of TRUE is returned.

--*/

{

    DISPATCH_INFO DispatchInfo;
    BOOLEAN Connected;
    PKINTERRUPT Interrupty;
    KIRQL Irql;
    KIRQL OldIrql;
    ULONG Vector;

    //
    // Set system affinity to the specified processor.
    //

    KeSetSystemAffinityThread((KAFFINITY)(1<<Interrupt->Number));

    //
    // Raise IRQL to dispatcher level and lock dispatcher database.
    //

    KiLockDispatcherDatabase(&OldIrql);

    //
    // If the interrupt object is connected, then disconnect it from the
    // specified vector.
    //

    Connected = Interrupt->Connected;
    if (Connected) {
        Irql = Interrupt->Irql;
        Vector = Interrupt->Vector;

        //
        // If the specified interrupt vector is not connected to the chained
        // interrupt dispatcher, then disconnect it by setting its dispatch
        // address to the unexpected interrupt routine. Else remove the
        // interrupt object from the interrupt chain. If there is only
        // one entry remaining in the list, then reestablish the dispatch
        // address.
        //

        //
        // Determine interrupt dispatch vector
        //

        KiGetVectorInfo (
            Vector,
            &DispatchInfo
            );


        //
        // Is dispatch a chained handler?
        //

        if (DispatchInfo.Type == ChainConnect) {

            ASSERT (Irql <= SYNCH_LEVEL);

            //
            // Is interrupt being removed from head?
            //

            if (Interrupt == DispatchInfo.Interrupt) {

                //
                // Update next interrupt object to be head
                //

                DispatchInfo.Interrupt = CONTAINING_RECORD(
                                               DispatchInfo.Interrupt->InterruptListEntry.Flink,
                                               KINTERRUPT,
                                               InterruptListEntry
                                               );

                KiConnectVectorAndInterruptObject (DispatchInfo.Interrupt, ChainConnect);
            }

            //
            // Remove interrupt object
            //

            RemoveEntryList(&Interrupt->InterruptListEntry);

            //
            // If there's only one interrupt object left on this vector,
            // determine proper interrupt dispatcher
            //

            Interrupty = CONTAINING_RECORD(
                                DispatchInfo.Interrupt->InterruptListEntry.Flink,
                                KINTERRUPT,
                                InterruptListEntry
                                );

            if (DispatchInfo.Interrupt == Interrupty) {
                KiConnectVectorAndInterruptObject (Interrupty, NormalConnect);
            }

        } else {

            //
            // Removing last interrupt object from the vector.  Disable the
            // vector, and set it to unconnected
            //

            HalDisableSystemInterrupt(Interrupt->Vector, Irql);
            KiConnectVectorAndInterruptObject (Interrupt, NoConnect);
        }


        KeSweepIcache(TRUE);
        Interrupt->Connected = FALSE;
    }

    //
    // Unlock dispatcher database and lower IRQL to its previous value.
    //

    KiUnlockDispatcherDatabase(OldIrql);

    //
    // Set system affinity back to the original value.
    //

    KeRevertToUserAffinityThread();

    //
    // Return whether interrupt was disconnected from the specified vector.
    //

    return Connected;
}
Esempio n. 5
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
{
    KIRQL OldIrql, Irql;
    ULONG Vector;
    DISPATCH_INFO Dispatch;
    PKINTERRUPT NextInterrupt;
    BOOLEAN State;

    /* Set the affinity */
    KeSetSystemAffinityThread(1 << Interrupt->Number);

    /* Lock the dispatcher */
    OldIrql = KiAcquireDispatcherLock();

    /* Check if it's actually connected */
    State = Interrupt->Connected;
    if (State)
    {
        /* Get the vector and IRQL */
        Irql = Interrupt->Irql;
        Vector = Interrupt->Vector;

        /* Get vector dispatch data */
        KiGetVectorDispatch(Vector, &Dispatch);

        /* Check if it was chained */
        if (Dispatch.Type == ChainConnect)
        {
            /* Check if the top-level interrupt is being removed */
            ASSERT(Irql <= SYNCH_LEVEL);
            if (Interrupt == Dispatch.Interrupt)
            {
                /* Get the next one */
                Dispatch.Interrupt = CONTAINING_RECORD(Dispatch.Interrupt->
                                                       InterruptListEntry.Flink,
                                                       KINTERRUPT,
                                                       InterruptListEntry);

                /* Reconnect it */
                KiConnectVectorToInterrupt(Dispatch.Interrupt, ChainConnect);
            }

            /* Remove it */
            RemoveEntryList(&Interrupt->InterruptListEntry);

            /* Get the next one */
            NextInterrupt = CONTAINING_RECORD(Dispatch.Interrupt->
                                              InterruptListEntry.Flink,
                                              KINTERRUPT,
                                              InterruptListEntry);

            /* Check if this is the only one left */
            if (Dispatch.Interrupt == NextInterrupt)
            {
                /* Connect it in non-chained mode */
                KiConnectVectorToInterrupt(Dispatch.Interrupt, NormalConnect);
            }
        }
        else
        {
            /* Only one left, disable and remove it */
            HalDisableSystemInterrupt(Interrupt->Vector, Irql);
            KiConnectVectorToInterrupt(Interrupt, NoConnect);
        }

        /* Disconnect it */
        Interrupt->Connected = FALSE;
    }

    /* Unlock the dispatcher and revert affinity */
    KiReleaseDispatcherLock(OldIrql);
    KeRevertToUserAffinityThread();

    /* Return to caller */
    return State;
}
Esempio n. 6
0
BOOLEAN
KeDisconnectInterrupt (
    IN PKINTERRUPT Interrupt
    )

/*++

Routine Description:

    This function disconnects an interrupt object from the interrupt vector
    specified by the interrupt object. If the interrupt object is not
    connected, then a value of FALSE is returned. Else the specified interrupt
    object is disconnected from the interrupt vector, the connected state is
    set to FALSE, and TRUE is returned as the function value.

Arguments:

    Interrupt - Supplies a pointer to a control object of type interrupt.

Return Value:

    If the interrupt object is not connected, then a value of FALSE is
    returned. Else a value of TRUE is returned.

--*/

{

    BOOLEAN Connected;
    PKINTERRUPT Interruptx;
    PKINTERRUPT Interrupty;
    KIRQL Irql;
    KIRQL OldIrql;
    KIRQL PreviousIrql;
    ULONG Vector;

    //
    // Set system affinity to the specified processor.
    //

    KeSetSystemAffinityThread((KAFFINITY)(1 << Interrupt->Number));

    //
    // Raise IRQL to dispatcher level and lock dispatcher database.
    //

    KiLockDispatcherDatabase(&OldIrql);

    //
    // If the interrupt object is connected, then disconnect it from the
    // specified vector.
    //

    Connected = Interrupt->Connected;
    if (Connected != FALSE) {
        Irql = Interrupt->Irql;
        Vector = Interrupt->Vector;

        //
        // If the specified interrupt vector is not connected to the chained
        // interrupt dispatcher, then disconnect it by setting its dispatch
        // address to the unexpected interrupt routine. Else remove the
        // interrupt object from the interrupt chain. If there is only
        // one entry remaining in the list, then reestablish the dispatch
        // address.
        //

        Interruptx = CONTAINING_RECORD(PCR->InterruptRoutine[Vector],
                                       KINTERRUPT,
                                       DispatchCode[0]);

        if (Interruptx->DispatchAddress ==
                                (PKINTERRUPT_ROUTINE)KiChainedDispatch) {
            KeRaiseIrql((KIRQL)(max(Irql, SYNCH_LEVEL)), &PreviousIrql);
            if (Interrupt == Interruptx) {
                Interruptx = CONTAINING_RECORD(Interruptx->InterruptListEntry.Flink,
                                               KINTERRUPT, InterruptListEntry);
                Interruptx->DispatchAddress =
                                (PKINTERRUPT_ROUTINE)KiChainedDispatch;
                Interruptx->DispatchCode[0] = *(PULONG)KiChainedDispatch;
                Interruptx->DispatchCode[1] = *(((PULONG)KiChainedDispatch)+1);
                PCR->InterruptRoutine[Vector] =
                                (PKINTERRUPT_ROUTINE)Interruptx->DispatchCode;

            }

            RemoveEntryList(&Interrupt->InterruptListEntry);
            Interrupty = CONTAINING_RECORD(Interruptx->InterruptListEntry.Flink,
                                           KINTERRUPT,
                                           InterruptListEntry);

            if (Interruptx == Interrupty) {
                if (Interrupt->FloatingSave) {
                    Interrupt->DispatchAddress = KiFloatingDispatch;

                } else {
                    if (Interrupt->Irql == Interrupt->SynchronizeIrql) {
#if defined(NT_UP)
                        Interrupt->DispatchAddress =
                                 (PKINTERRUPT_ROUTINE)Interrupt->ServiceRoutine;
#else
                        Interrupt->DispatchAddress =
                                 (PKINTERRUPT_ROUTINE)KiInterruptDispatchSame;
#endif

                    } else {
                        Interrupt->DispatchAddress =
                                 (PKINTERRUPT_ROUTINE)KiInterruptDispatchRaise;
                    }
                }

                //
                // Copy the function descriptor for the Dispatch routine
                // into DispatchCode.  This will be used by KiInterruptEx-
                // ception to dispatch the interrupt.
                //
                Interrupty->DispatchCode[0] =
                                *(PULONG)(Interrupty->DispatchAddress);
                Interrupty->DispatchCode[1] =
                                *(((PULONG)(Interrupty->DispatchAddress))+1);
                PCR->InterruptRoutine[Vector] =
                               (PKINTERRUPT_ROUTINE)Interrupty->DispatchCode;

                }

            KeLowerIrql(PreviousIrql);

        } else {
            HalDisableSystemInterrupt(Vector, Irql);
            PCR->InterruptRoutine[Vector] =
                    (PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode);
        }
#ifdef NOTDEF
        KeSweepIcache(TRUE);
#endif
        Interrupt->Connected = FALSE;
    }

    //
    // Unlock dispatcher database and lower IRQL to its previous value.
    //

    KiUnlockDispatcherDatabase(OldIrql);

    //
    // Set system affinity back to the original value.
    //

    KeRevertToUserAffinityThread();

    //
    // Return whether interrupt was disconnected from the specified vector.
    //

    return Connected;
}
Esempio n. 7
0
VOID
NTAPI
HalpInitializeTsc(VOID)
{
    ULONG_PTR Flags;
    KIDTENTRY OldIdtEntry, *IdtPointer;
    PKPCR Pcr = KeGetPcr();
    UCHAR RegisterA, RegisterB;

    /* Check if the CPU supports RDTSC */
    if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC))
    {
        KeBugCheck(HAL_INITIALIZATION_FAILED);
    }

     /* Save flags and disable interrupts */
    Flags = __readeflags();
    _disable();

    /* Enable the periodic interrupt in the CMOS */
    RegisterB = HalpReadCmos(RTC_REGISTER_B);
    HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI);

    /* Modify register A to RTC_MODE to get SAMPLE_FREQENCY */
    RegisterA = HalpReadCmos(RTC_REGISTER_A);
    RegisterA = (RegisterA & 0xF0) | RTC_MODE;
    HalpWriteCmos(RTC_REGISTER_A, RegisterA);

    /* Save old IDT entry */
    IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector);
    OldIdtEntry = *IdtPointer;

    /* Set the calibration ISR */
    KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR);

    /* Reset TSC value to 0 */
    __writemsr(MSR_RDTSC, 0);

    /* Enable the timer interupt */
    HalEnableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL, Latched);

    /* Read register C, so that the next interrupt can happen */
    HalpReadCmos(RTC_REGISTER_C);;

    /* Wait for completion */
    _enable();
    while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier();
    _disable();

    /* Disable the periodic interrupt in the CMOS */
    HalpWriteCmos(RTC_REGISTER_B, RegisterB & ~RTC_REG_B_PI);

    /* Disable the timer interupt */
    HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL);

    /* Restore old IDT entry */
    *IdtPointer = OldIdtEntry;

    /* Calculate an average, using simplified linear regression */
    HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1,
                                                        TscCalibrationArray);

    /* Restore flags */
    __writeeflags(Flags);

}
Esempio n. 8
0
VOID
HalStopProfileInterrupt (
    KPROFILE_SOURCE ProfileSource
    )

/*++

Routine Description:

    This routine turns off the profile interrupt.

    N.B. This routine must be called at PROCLK_LEVEL while holding the
        profile lock.

Arguments:

    None.

Return Value:

    None.

--*/

{
    ULONG PerformanceCounter;
    ULONG Vector;

    //
    // Check input to see if we are turning off a source that is
    // supported.  If it is unsupported, just return.
    //

    if ((ProfileSource > (sizeof(HalpProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
        (!HalpProfileMapping[ProfileSource].Supported)) {
        return;
    }

    //
    // Stop the performance counter from interrupting.
    //

    PerformanceCounter = HalpProfileMapping[ProfileSource].Counter;
    HalpWritePerformanceCounter( PerformanceCounter,
                                 FALSE,
                                 0,
                                 0 );

    //
    // Disable the performance counter interrupt.
    //
    if (PerformanceCounter == Ev4PerformanceCounter0) {
        HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );

        //
        // Clear the current profile count.  Can't clear value in PCR
        // since a profile interrupt could be pending or in progress
        // so clear the reload counter.
        //

        PCRProfileCountReload[0] = 0;
    } else {
        HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );

        //
        // Clear the current profile count.  Can't clear value in PCR
        // since a profile interrupt could be pending or in progress
        // so clear the reload counter.
        //

        PCRProfileCountReload[0] = 0;
    }

    return;
}