Ejemplo n.º 1
0
Archivo: irq.c Proyecto: RPG-7/reactos
/*
 * @implemented
 */
VOID
NTAPI
IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
{
    LONG i;
    PIO_INTERRUPT IoInterrupt;
    PAGED_CODE();

    /* Get the I/O Interrupt */
    IoInterrupt = CONTAINING_RECORD(InterruptObject,
                                    IO_INTERRUPT,
                                    FirstInterrupt);

    /* Disconnect the first one */
    KeDisconnectInterrupt(&IoInterrupt->FirstInterrupt);

    /* Now disconnect the others */
    for (i = 0; i < KeNumberProcessors; i++)
    {
        /* Make sure one was registered */
        if (IoInterrupt->Interrupt[i])
        {
            /* Disconnect it */
            KeDisconnectInterrupt(&InterruptObject[i]);
        }
    }

    /* Free the I/O Interrupt */
    ExFreePool(IoInterrupt); // ExFreePoolWithTag(IoInterrupt, TAG_KINTERRUPT);
}
Ejemplo n.º 2
0
BOOLEAN
KeConnectInterrupt (
    __inout PKINTERRUPT Interrupt
    )

/*++

Routine Description:

    This function connects an interrupt object to the interrupt vector
    specified by the interrupt object. If the interrupt object is already
    connected, or an attempt is made to connect to an interrupt that cannot
    be connected, then a value of FALSE is returned. Else the specified
    interrupt object is connected to the interrupt vector, the connected
    state is set to TRUE, 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 already connected or an attempt is made to
    connect to an interrupt vector that cannot be connected, then a value
    of FALSE is returned. Else a value of TRUE is returned.

--*/

{
    DISPATCH_INFO DispatchInfo;
    BOOLEAN Connected;
    BOOLEAN ConnectError;
    BOOLEAN Enabled;
    KIRQL Irql;
    CCHAR Number;
    KIRQL OldIrql;
    ULONG Vector;

    //
    // If the interrupt object is already connected, the interrupt vector
    // number is invalid, an attempt is being made to connect to a vector
    // that cannot be connected, the interrupt request level is invalid, or
    // the processor number is invalid, then do not connect the interrupt
    // object. Else connect interrupt object to the specified vector and
    // establish the proper interrupt dispatcher.
    //

    Connected = FALSE;
    ConnectError = FALSE;
    Irql = Interrupt->Irql;
    Number = Interrupt->Number;
    Vector = Interrupt->Vector;
    if ( !((Irql > HIGH_LEVEL) ||
           (Number >= KeNumberProcessors) ||
           (Interrupt->SynchronizeIrql < Irql) ||
           (Interrupt->FloatingSave)    // R0 x87 usage not supported on x86
          )
       ) {

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

        KeSetSystemAffinityThread((KAFFINITY)(1<<Number));

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

        KiLockDispatcherDatabase(&OldIrql);

        //
        // Is interrupt object already connected?
        //

        if (!Interrupt->Connected) {

            //
            // Determine interrupt dispatch vector
            //

            KiGetVectorInfo (
                Vector,
                &DispatchInfo
                );

            //
            // If dispatch vector is not connected, then connect it
            //

            if (DispatchInfo.Type == NoConnect) {
                Connected = TRUE;
                Interrupt->Connected = TRUE;

                //
                // Connect interrupt dispatch to interrupt object dispatch code
                //

                InitializeListHead(&Interrupt->InterruptListEntry);
                KiConnectVectorAndInterruptObject (Interrupt, NormalConnect);

                //
                // Enabled system vector
                //

                Enabled = HalEnableSystemInterrupt(Vector, Irql, Interrupt->Mode);
                if (!Enabled) {
                    ConnectError = TRUE;
                }


            } else if (DispatchInfo.Type != UnknownConnect &&
                       Interrupt->ShareVector  &&
                       DispatchInfo.Interrupt->ShareVector  &&
                       DispatchInfo.Interrupt->Mode == Interrupt->Mode) {

                //
                // Vector is already connected as sharable.  New vector is sharable
                // and modes match.  Chain new vector.
                //

                Connected = TRUE;
                Interrupt->Connected = TRUE;

                ASSERT (Irql <= SYNCH_LEVEL);

                //
                // If not already using chained dispatch handler, set it up
                //

                if (DispatchInfo.Type != ChainConnect) {
                    KiConnectVectorAndInterruptObject (DispatchInfo.Interrupt, ChainConnect);
                }

                //
                // Add to tail of chained dispatch
                //

                InsertTailList(
                    &DispatchInfo.Interrupt->InterruptListEntry,
                    &Interrupt->InterruptListEntry
                    );

            }
        }

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

        KiUnlockDispatcherDatabase(OldIrql);

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

        KeRevertToUserAffinityThread();
    }

    if (Connected  &&  ConnectError) {
#if DBG
        DbgPrint ("HalEnableSystemInterrupt failed\n");
#endif
        KeDisconnectInterrupt (Interrupt);
        Connected = FALSE;
    }

    //
    // Return whether interrupt was connected to the specified vector.
    //

    return Connected;
}
Ejemplo n.º 3
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
KeConnectInterrupt(IN PKINTERRUPT Interrupt)
{
    BOOLEAN Connected, Error, Status;
    KIRQL Irql, OldIrql;
    UCHAR Number;
    ULONG Vector;
    DISPATCH_INFO Dispatch;

    /* Get data from interrupt */
    Number = Interrupt->Number;
    Vector = Interrupt->Vector;
    Irql = Interrupt->Irql;

    /* Validate the settings */
    if ((Irql > HIGH_LEVEL) ||
        (Number >= KeNumberProcessors) ||
        (Interrupt->SynchronizeIrql < Irql) ||
        (Interrupt->FloatingSave))
    {
        return FALSE;
    }

    /* Set defaults */
    Connected = FALSE;
    Error = FALSE;

    /* Set the system affinity and acquire the dispatcher lock */
    KeSetSystemAffinityThread(1 << Number);
    OldIrql = KiAcquireDispatcherLock();

    /* Check if it's already been connected */
    if (!Interrupt->Connected)
    {
        /* Get vector dispatching information */
        KiGetVectorDispatch(Vector, &Dispatch);

        /* Check if the vector is already connected */
        if (Dispatch.Type == NoConnect)
        {
            /* Do the connection */
            Interrupt->Connected = Connected = TRUE;

            /* Initialize the list */
            InitializeListHead(&Interrupt->InterruptListEntry);

            /* Connect and enable the interrupt */
            KiConnectVectorToInterrupt(Interrupt, NormalConnect);
            Status = HalEnableSystemInterrupt(Vector, Irql, Interrupt->Mode);
            if (!Status) Error = TRUE;
        }
        else if ((Dispatch.Type != UnknownConnect) &&
                (Interrupt->ShareVector) &&
                (Dispatch.Interrupt->ShareVector) &&
                (Dispatch.Interrupt->Mode == Interrupt->Mode))
        {
            /* The vector is shared and the interrupts are compatible */
            Interrupt->Connected = Connected = TRUE;

            /* FIXME */
            // ASSERT(Irql <= SYNCH_LEVEL);

            /* Check if this is the first chain */
            if (Dispatch.Type != ChainConnect)
            {
                /* This is not supported */
                ASSERT(Dispatch.Interrupt->Mode != Latched);

                /* Setup the chainned handler */
                KiConnectVectorToInterrupt(Dispatch.Interrupt, ChainConnect);
            }

            /* Insert into the interrupt list */
            InsertTailList(&Dispatch.Interrupt->InterruptListEntry,
                           &Interrupt->InterruptListEntry);
        }
    }

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

    /* Check if we failed while trying to connect */
    if ((Connected) && (Error))
    {
        DPRINT1("HalEnableSystemInterrupt failed\n");
        KeDisconnectInterrupt(Interrupt);
        Connected = FALSE;
    }

    /* Return to caller */
    return Connected;
}