BOOLEAN 
DeviceInterrupt_EvtAttachDetachInterruptIsr (
    _In_ WDFINTERRUPT Interrupt,
    _In_ ULONG MessageID
    )
/*++

Routine Description:

    'EvtInterruptIsr' handler for the attach/detach interrupt object.
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff541735(v=vs.85).aspx

Arguments:

    Interrupt - Associated interrupt object.

    MessageID - Message IDs for MSI

Return Value:

    BOOLEAN

--*/
{
    PCONTROLLER_CONTEXT ControllerContext;

    UNREFERENCED_PARAMETER(MessageID);

    TraceEntry();

    ControllerContext = DeviceGetControllerContext(WdfInterruptGetDevice(Interrupt));
    
    WdfInterruptAcquireLock(ControllerContext->DeviceInterrupt);

    //
    // This is an ActiveBoth interrupt used for attach/detach.  State is determined
    // by counting interrupts.  Previous state was attached, so this is a detach.
    //
    if (!ControllerContext->Attached) {
        ControllerContext->Attached = TRUE;
        ControllerContext->GotAttachOrDetach = TRUE;

        (void) WdfInterruptQueueDpcForIsr(Interrupt);
    } else  {
        ControllerContext->Attached = FALSE;
        ControllerContext->GotAttachOrDetach = TRUE;
        (void) WdfInterruptQueueDpcForIsr(Interrupt);
    }
        
    WdfInterruptReleaseLock(ControllerContext->DeviceInterrupt);
        
    TraceExit();
    return TRUE;
}
BOOLEAN VirtRngEvtInterruptIsr(IN WDFINTERRUPT Interrupt, IN ULONG MessageId)
{
    PDEVICE_CONTEXT context = GetDeviceContext(
        WdfInterruptGetDevice(Interrupt));
    WDF_INTERRUPT_INFO info;
    BOOLEAN serviced;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT,
        "--> %!FUNC! Interrupt: %p MessageId: %u", Interrupt, MessageId);

    WDF_INTERRUPT_INFO_INIT(&info);
    WdfInterruptGetInfo(context->WdfInterrupt, &info);

    if ((info.MessageSignaled && (MessageId == 0)) ||
        VirtIODeviceISR(&context->VirtDevice))
    {
        WdfInterruptQueueDpcForIsr(Interrupt);
        serviced = TRUE;
    }
    else
    {
        serviced = FALSE;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "<-- %!FUNC!");

    return serviced;
}
Example #3
0
//
// Routine Description:
//
//  PL011EvtInterruptIsr is the interrupt service routine for 
//  ARM PL011 UART. PL011EvtInterruptIsr calls PL011pInterruptIsr to do
//  incoming events ISR level processing, and schedules a DPC level 
//  processing PL011EvtInterruptDpc if our device generated the interrupt.
//
// Arguments:
//
//  WdfInterrupt - The WDF interrupt object the created for the ARM PL011
//      interrupt.
//
//  MessageID - The message ID, in case the device is using MSIs, otherwise 0.
//
// Return Value:
//
//  TRUE if the interrupt originated from the PL011 device and was serviced,
//  otherwise FALSE.
//
_Use_decl_annotations_
BOOLEAN
PL011EvtInterruptIsr(
    WDFINTERRUPT WdfInterrupt,
    ULONG MessageID
    )
{
    UNREFERENCED_PARAMETER(MessageID);

    WDFDEVICE wdfDevice = WdfInterruptGetDevice(WdfInterrupt);
    PL011_DEVICE_EXTENSION* devExtPtr = PL011DeviceGetExtension(wdfDevice);

    //
    // Get and process UART events (ISR level)
    //
    BOOLEAN isUartInterrupt = PL011pInterruptIsr(devExtPtr);
    if (!isUartInterrupt) {

        return FALSE;
    }

    PL011_ASSERT(WdfInterrupt == devExtPtr->WdfUartInterrupt);

    WdfInterruptQueueDpcForIsr(devExtPtr->WdfUartInterrupt);

    PL011_LOG_TRACE(
        "UART ISR, status 0x%04X",
        USHORT(devExtPtr->IntEventsForDpc)
        );

    return TRUE;
}
Example #4
0
BOOLEAN
NICEvtInterruptIsr(
    IN WDFINTERRUPT Interrupt,
    IN ULONG        MessageID
    )
/*++
Routine Description:

    Interrupt handler for the device.

Arguments:

    Interupt - Address of the framework interrupt object
    MessageID -

Return Value:

     TRUE if our device is interrupting, FALSE otherwise.

--*/
{
    BOOLEAN    InterruptRecognized = FALSE;
    PFDO_DATA  FdoData = NULL;
    USHORT     IntStatus;

    UNREFERENCED_PARAMETER( MessageID );

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "--> NICEvtInterruptIsr\n");

    FdoData = FdoGetData(WdfInterruptGetDevice(Interrupt));

    //
    // We process the interrupt if it's not disabled and it's active
    //
    if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
    {
        InterruptRecognized = TRUE;

        //
        // Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
        //
        NICDisableInterrupt(FdoData);

        //
        // Acknowledge the interrupt(s) and get the interrupt status
        //

        NIC_ACK_INTERRUPT(FdoData, IntStatus);

        WdfInterruptQueueDpcForIsr( Interrupt );

    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "<-- NICEvtInterruptIsr\n");

    return InterruptRecognized;
}
Example #5
0
///////////////////////////////////////////////////////////////////////////////
// Interrupt Service Routine (ISR) event callback function 
// processing on IRQL_DIRQL
///////////////////////////////////////////////////////////////////////////////
BOOLEAN SmplInterruptEvtIsr(
  __in  WDFINTERRUPT Interrupt,
  __in  ULONG MessageID
)
{
    WDFDEVICE Device = WdfInterruptGetDevice(Interrupt);
    PDEVICE_CONTEXT pSmplDeviceContext = DeviceGetContext(Device);
    BOOLEAN bReturnValue = FALSE;

#pragma warning(push)
#pragma warning(disable:4127) // warning C4127: conditional expression is constant
    while(TRUE)
#pragma warning(pop)
    {   // First check: Is it ours???
        UCHAR rcvd;
        UCHAR IntId = READ_INTERRUPT_IDENTIFICATION(pSmplDeviceContext->pPortAddress);
        if (IntId & IIR_NOT_FIRED)
        {
            break;
        }

        DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"Interrupt\n");
        bReturnValue = TRUE;

        switch (IntId) 
        {
            case IIR_RECEIVER_FULL: 
                rcvd = READ_RECEIVER_BUFFER (pSmplDeviceContext->pPortAddress);
                if (FALSE == RingbufferInsertCharacter(pSmplDeviceContext->pRingBuffer, rcvd)) 
                {
                    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"Ringbuffer overflow %x\n", rcvd);
                }
                break;
            case IIR_RECEIVER_ERROR:
            case IIR_TRANSMITTER_EMPTY:
            case IIR_STATUS_CHANGE:
            default:
                ;
        } // end switch

    } // end while

    if(TRUE == bReturnValue)
        WdfInterruptQueueDpcForIsr(Interrupt);

    return bReturnValue;

} // end SmplInterruptEvtIsr
BOOLEAN 
DeviceInterrupt_EvtInterruptIsr(
    _In_ WDFINTERRUPT Interrupt,
    _In_ ULONG MessageID
    )
/*++

Routine Description:

    'EvtInterruptIsr' handler for the device interrupt object.
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff541735(v=vs.85).aspx

Arguments:

    Interrupt - Associated interrupt object.

    MessageID - Message IDs for MSI

Return Value:

    Appropriate NTSTATUS value

--*/
{
    BOOLEAN PendingEvents;

    TraceEntry();

    UNREFERENCED_PARAMETER(MessageID);

    //
    // #### TODO: Determine if controller has pending events. ####
    // 
    
    // Sample will assume there is always a pending event for illustration purposes.
    PendingEvents = TRUE;

    if (PendingEvents) {
        //    
        // Enqueue the DPC to handle the events.
        //
        WdfInterruptQueueDpcForIsr(Interrupt);
    }

    TraceExit();
    return TRUE;
}
Example #7
0
/*++
Routine Description:

Interrupt handler for this driver. Called at DIRQL level when the
device or another device sharing the same interrupt line asserts
the interrupt. The driver first checks the device to make sure whether
this interrupt is generated by its device and if so clear the interrupt
register to disable further generation of interrupts and queue a
DPC to do other I/O work related to interrupt - such as reading
the device memory, starting a DMA transaction, coping it to
the request buffer and completing the request, etc.

Arguments:

Interupt   - Handle to WDFINTERRUPT Object for this device.
MessageID  - MSI message ID (always 0 in this configuration)

Return Value:

TRUE   --  This device generated the interrupt.
FALSE  --  This device did not generated this interrupt.

--*/
BOOLEAN PCIEEvtInterruptIsr(IN WDFINTERRUPT Interrupt, IN ULONG MessageID)
{
    PDEVICE_EXTENSION   pDevExt;
    BOOLEAN             IsRecognized = FALSE;

    UNREFERENCED_PARAMETER(MessageID);

    // Our ISR Routine will be called event if the test card hasn't trigger any interrupt signal.
    pDevExt  = PCIEGetDeviceContext(WdfInterruptGetDevice(Interrupt));

    
    if (IsRecognized)
    {
        WdfInterruptQueueDpcForIsr(pDevExt->Interrupt);
    }

    return IsRecognized;
}
BOOLEAN
BalloonInterruptIsr(
    IN WDFINTERRUPT WdfInterrupt,
    IN ULONG        MessageID
    )
{
    PDEVICE_CONTEXT     devCtx = NULL;
    WDFDEVICE           Device;

    UNREFERENCED_PARAMETER( MessageID );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "--> %s\n", __FUNCTION__);
    Device = WdfInterruptGetDevice(WdfInterrupt);
    devCtx = GetDeviceContext(Device);

    if(VirtIODeviceISR(&devCtx->VDevice) > 0)
    {
        WdfInterruptQueueDpcForIsr( WdfInterrupt );
        return TRUE;
    }
    return FALSE;
}
BOOLEAN VioCryptInterruptIsr(IN WDFINTERRUPT Interrupt, IN ULONG MessageId)
{
    PDEVICE_CONTEXT context = GetDeviceContext(
        WdfInterruptGetDevice(Interrupt));
    WDF_INTERRUPT_INFO info;
    BOOLEAN processed;

    WDF_INTERRUPT_INFO_INIT(&info);
    WdfInterruptGetInfo(context->WdfInterrupt, &info);

    processed = ((info.MessageSignaled && (MessageId == 0)) ||
        VirtIOWdfGetISRStatus(&context->VDevice));
    
    if (processed)
    {
        WdfInterruptQueueDpcForIsr(Interrupt);
    }

    Trace(TRACE_LEVEL_VERBOSE, "[%s] %sprocessed", __FUNCTION__, processed ? "" : "not ");

    return processed;
}
Example #10
0
BOOLEAN
PLxEvtInterruptIsr(
    IN WDFINTERRUPT Interrupt,
    IN ULONG        MessageID
    )
/*++
Routine Description:

    Interrupt handler for this driver. Called at DIRQL level when the
    device or another device sharing the same interrupt line asserts
    the interrupt. The driver first checks the device to make sure whether
    this interrupt is generated by its device and if so clear the interrupt
    register to disable further generation of interrupts and queue a
    DPC to do other I/O work related to interrupt - such as reading
    the device memory, starting a DMA transaction, coping it to
    the request buffer and completing the request, etc.

Arguments:

    Interupt   - Handle to WDFINTERRUPT Object for this device.
    MessageID  - MSI message ID (always 0 in this configuration)

Return Value:

     TRUE   --  This device generated the interrupt.
     FALSE  --  This device did not generated this interrupt.

--*/
{
    PDEVICE_EXTENSION   devExt;
    BOOLEAN             isRecognized = FALSE;

    union {
        INT_CSR bits;
        ULONG   ulong;
    } intCsr;

    UNREFERENCED_PARAMETER(MessageID);

    //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
    //            "--> PLxInterruptHandler");

    devExt  = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));

    //
    // Read the Interrupt CSR register (INTCSR)
    //
    intCsr.ulong = READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );

    //
    // Is DMA channel 0 (Write-side) Active?
    //
    if (intCsr.bits.DmaChan0IntActive) {

        TraceEvents(TRACE_LEVEL_INFORMATION,  DBG_INTERRUPT,
                    " Interrupt for DMA Channel 0 (write)");

        devExt->IntCsr.bits.DmaChan0IntActive = TRUE;

        //
        // Clear this interrupt.
        //
        devExt->Dma0Csr.uchar =
            READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr );

        devExt->Dma0Csr.bits.Clear = TRUE;

        WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr,
                              devExt->Dma0Csr.uchar );

        isRecognized = TRUE;
    }

    //
    // Is DMA channel 1 (Read-side) Active?
    //
    if (intCsr.bits.DmaChan1IntActive) {

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
                    " Interrupt for DMA Channel 1 (read)");

        devExt->IntCsr.bits.DmaChan1IntActive = TRUE;

        //
        // Clear this interrupt.
        //
        devExt->Dma1Csr.uchar =
            READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr );

        devExt->Dma1Csr.bits.Clear = TRUE;

        WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr,
                              devExt->Dma1Csr.uchar );

        isRecognized = TRUE;
    }

    if ((isRecognized) &&
        ((devExt->Dma0Csr.bits.Done) ||
         (devExt->Dma1Csr.bits.Done))) {
        //
        // A read or a write or both is done. Queue a DPC.
        //
        WdfInterruptQueueDpcForIsr( devExt->Interrupt );
    }

    //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT,
    //            "<-- PLxInterruptHandler");

    return isRecognized;
}
VOID
VIOSerialHandleCtrlMsg(
    IN WDFDEVICE Device,
    IN PPORT_BUFFER buf
)
{
    PPORTS_DEVICE pContext = GetPortsDevice(Device);
    PVIRTIO_CONSOLE_CONTROL cpkt;
    PVIOSERIAL_PORT port;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);

    cpkt = (PVIRTIO_CONSOLE_CONTROL)((ULONG_PTR)buf->va_buf + buf->offset);

    port = VIOSerialFindPortById(Device, cpkt->id);

    if (!port && (cpkt->event != VIRTIO_CONSOLE_PORT_ADD))
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Invalid index %u in control packet\n", cpkt->id);
    }

    switch (cpkt->event)
    {
        case VIRTIO_CONSOLE_PORT_ADD:
           if (port)
           {
               TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VIRTIO_CONSOLE_PORT_ADD id = %d\n", cpkt->id);
               break;
           }
           if (cpkt->id >= pContext->consoleConfig.max_nr_ports)
           {
               TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Out-of-bound id %u\n", cpkt->id);
               break;
           }
           VIOSerialAddPort(Device, cpkt->id);
        break;

        case VIRTIO_CONSOLE_PORT_REMOVE:
           if (!port)
           {
              TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_REMOVE invalid id = %d\n", cpkt->id);
              break;
           }
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VIRTIO_CONSOLE_PORT_REMOVE id = %d\n", cpkt->id);
           VIOSerialRemovePort(Device, port);
        break;

        case VIRTIO_CONSOLE_CONSOLE_PORT:
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                       "VIRTIO_CONSOLE_CONSOLE_PORT id = %d value = %u\n", cpkt->id, cpkt->value);
           if (cpkt->value)
           {
              VIOSerialInitPortConsole(Device,port);
           }
        break;

        case VIRTIO_CONSOLE_RESIZE:
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VIRTIO_CONSOLE_RESIZE id = %d\n", cpkt->id);
        break;

        case VIRTIO_CONSOLE_PORT_OPEN:
           if (port)
           {
              BOOLEAN  Connected = (BOOLEAN)cpkt->value;
              TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_OPEN id = %d, HostConnected = %d\n", cpkt->id, Connected);
              if (port->HostConnected != Connected)
              {
                 VIOSerialPortPnpNotify(Device, port, Connected);
              }

              // Someone is listening. Trigger a check to see if we have
              // something waiting to be told.
              if (port->HostConnected)
              {
                  WDF_INTERRUPT_INFO info;
                  WDFINTERRUPT *interrupt;

                  WDF_INTERRUPT_INFO_INIT(&info);
                  WdfInterruptGetInfo(pContext->QueuesInterrupt, &info);

                  // Check if MSI is enabled and notify the right interrupt.
                  interrupt = (info.Vector == 0) ? &pContext->WdfInterrupt :
                      &pContext->QueuesInterrupt;

                  WdfInterruptQueueDpcForIsr(*interrupt);
              }
           }
           else
           {
              TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_OPEN invalid id = %d\n", cpkt->id);
           }
        break;

        case VIRTIO_CONSOLE_PORT_NAME:
           if (port)
           {
              VIOSerialPortCreateName(Device, port, buf);
           }
        break;
        default:
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "%s UNKNOWN event = %d\n", __FUNCTION__, cpkt->event);
    }
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
}
Example #12
0
BOOLEAN
AmccPciEvtInterruptIsr(
    __in WDFINTERRUPT Interrupt,
    __in ULONG        MessageID
    )
/*++

Routine Description:

    This routine assumes that only a single I/O can be completed at a
    time on the hardware (i.e. at most one I/O completed per interrupt).

Arguments:

    Interupt - Address of the framework interrupt object
    MessageID -

Return Value:

    TRUE - Interrupt belongs to this device.

--*/
{
    PAMCC_DEVICE_EXTENSION   devExt = NULL;
    WDFDEVICE                hDevice;

    union {
        ULONG      ulong;
        INTCSR_REG bits;
    } intcsr;

    union {
        ULONG      ulong;
        MCSR_REG   bits;
    } mcsr;

    UNREFERENCED_PARAMETER( MessageID );

    hDevice = WdfInterruptGetDevice(Interrupt);
    devExt = AmccPciGetDevExt(hDevice);

    //
    // Read interrupt control/status register and see if an interrupt is pending.
    // If not, return FALSE immediately.
    //
    intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR);

    if (!intcsr.bits.InterruptAsserted) {
        return FALSE;
    }

    //
    // Disable bus-mastering
    //
    mcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->MCSR);

    mcsr.bits.WriteTransferEnable = FALSE;
    mcsr.bits.ReadTransferEnable  = FALSE;

    WRITE_PORT_ULONG((PULONG) &devExt->Regs->MCSR, mcsr.ulong );

    //
    // This will take effect when INTCSR is rewritten later.
    //
    intcsr.bits.IntOnWriteTransferComplete = FALSE;
    intcsr.bits.IntOnReadTransferComplete  = FALSE;

    //
    // Process pending interrupts. We're expecting an interrupt due
    // to a transfer count going to zero, but we might be getting a
    // master or target abort instead.
    //
    while (intcsr.bits.InterruptAsserted) {

        //
        // Merge new interrupts with old
        //
        _InterlockedOr((PLONG) &devExt->Intcsr, (LONG) intcsr.ulong );

        //
        // Interrupt flags on the S5933 are cleared by writing a "1" bit
        // to them, so clear all the interrupts just examined.
        //
        WRITE_PORT_ULONG((PULONG) &devExt->Regs->INTCSR, intcsr.ulong);

        //
        // Check for additional interrupts
        //
        intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR);
    }

    //
    // Check if there is a current Request.  If not, then this interrupt cannot
    // do anything.  This driver design requires an I/O to be pending in order
    // to queue the DPC.  If there is no I/O current, then there is no need
    // to have a DPC queued.  This driver also assumes one I/O per interrupt.
    //
    // IMPORTANT: Before returning TRUE, the interrupt must have been cleared
    // on the device or the system will hang trying to service this level
    // sensitive interrupt.
    //
    if (!devExt->CurrentRequest) {
        TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                    "Hardware generated interrupt with no request pending");
        return TRUE;
    }

    //
    // Request the DPC to complete the transfer.
    //
    WdfInterruptQueueDpcForIsr( Interrupt );

    //
    // Indicate that this adapter was interrupting.
    //
    return TRUE;
}