/* * @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); }
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; }
/* * @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; }