コード例 #1
0
ファイル: Interrupt.c プロジェクト: uri247/kmdf
///////////////////////////////////////////////////////////////////////////////
// SmplInterruptEvtDisable 
///////////////////////////////////////////////////////////////////////////////
NTSTATUS SmplInterruptEvtDisable(
  __in  WDFINTERRUPT Interrupt,
  __in  WDFDEVICE AssociatedDevice
)
{
    PDEVICE_CONTEXT pDeviceContext = DeviceGetContext(WdfInterruptGetDevice(Interrupt));
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"SmplInterruptEvtDisable\n");
    WRITE_INTERRUPT_ENABLE( pDeviceContext->pPortAddress, 0);
    return STATUS_SUCCESS;

} // end SmplInterruptEvtDisable
コード例 #2
0
ファイル: Hw8250.c プロジェクト: uri247/kmdf
///////////////////////////////////////////////////////////////////////////////
// Does           : Initializes the device.
// Parameters     : port           - Port of a 8250
//                  baudrate       - Baudrate to init 8250 to
//                  dataBits       - Number of data bits (5..8)
//                  stopBits       - Number of stop bits (1..2)
//                  parity         - 0 == NONE, 1 == ODD, 2 == EVEN
// Returns        : Status of the operation.
// Postcondition  : Ready to start interrupt processing when returning
//                  STATUS_SUCCESS.
///////////////////////////////////////////////////////////////////////////////
NTSTATUS Hw8250Init(PUCHAR port, ULONG baudRate, ULONG dataBits,
                        ULONG stopBits, ULONG parity)
{
    NTSTATUS result = STATUS_SUCCESS;
    ULONG divisor;
    UCHAR dataFormat;

    // disable all interrupts
    WRITE_INTERRUPT_ENABLE(port, 0x00);

    // set up baudrate
    divisor = Hw8550InternalGetDivisor(baudRate);
    WRITE_LINE_CONTROL(port, LCR_DLAB);
    WRITE_DIVISOR_LATCH(port, divisor);

    // set up data bits (defaults to 8 data bits)
    switch(dataBits) {
        case 5:
            dataFormat = LCR_DATA_5;
            break;

        case 6:
            dataFormat = LCR_DATA_6;
            break;

        case 7:
            dataFormat = LCR_DATA_7;
            break;

        case 8:
        default:
            dataFormat = LCR_DATA_8;
            break;
    }

    // set up stop bits (defaults to 1 stop bit)
    if(stopBits == 2) {
        dataFormat |= LCR_STOP_2;
    }
    else {
        dataFormat |= LCR_STOP_1;
    }

    // set up parity (defaults to none)
    switch(parity) {
        case 4:
            dataFormat |= LCR_PARITY_SPACE;
            break;
        
        case 3:
            dataFormat |= LCR_PARITY_MARK;
            break;
        
        case 2:
            dataFormat |= LCR_PARITY_EVEN;
            break;
        
        case 1:
            dataFormat |= LCR_PARITY_ODD;
            break;

        case 0:
        default:
            dataFormat |= LCR_PARITY_NONE;
            break;
    }

    WRITE_LINE_CONTROL(port, dataFormat);
    WRITE_MODEM_CONTROL(port, MCR_GPO1 | MCR_RTS | MCR_DTR);

    return result;

} // end Hw8250Init
コード例 #3
0
NTSTATUS
SerialEvtDeviceD0Entry(
    IN  WDFDEVICE Device,
    IN  WDF_POWER_DEVICE_STATE PreviousState
    )
/*++

Routine Description:

    EvtDeviceD0Entry event callback must perform any operations that are
    necessary before the specified device is used.  It will be called every
    time the hardware needs to be (re-)initialized.  This includes after
    IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,
    IRP_MN_SET_POWER-D0.

    This function is not marked pageable because this function is in the
    device power up path. When a function is marked pagable and the code
    section is paged out, it will generate a page fault which could impact
    the fast resume behavior because the client driver will have to wait
    until the system drivers can service this page fault.

    This function runs at PASSIVE_LEVEL, even though it is not paged.  A
    driver can optionally make this function pageable if DO_POWER_PAGABLE
    is set.  Even if DO_POWER_PAGABLE isn't set, this function still runs
    at PASSIVE_LEVEL.  In this case, though, the function absolutely must
    not do anything that will cause a page fault.

Arguments:

    Device - Handle to a framework device object.

    PreviousState - Device power state which the device was in most recently.
        If the device is being newly started, this will be
        PowerDeviceUnspecified.

Return Value:

    NTSTATUS

--*/
{
    PSERIAL_DEVICE_EXTENSION deviceExtension;
    PSERIAL_DEVICE_STATE pDevState;
    SHORT divisor;
    SERIAL_IOCTL_SYNC S;

    SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER,
                "-->SerialEvtDeviceD0Entry - coming from %s\n", DbgDevicePowerString(PreviousState));

    deviceExtension = SerialGetDeviceExtension (Device);
    pDevState = &deviceExtension->DeviceState;

    //
    // Restore the state of the UART.  First, that involves disabling
    // interrupts both via OUT2 and IER.
    //

    WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller, 0);
    DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller);

    //
    // Set the baud rate
    //

    SerialGetDivisorFromBaud(deviceExtension->ClockRate, deviceExtension->CurrentBaud, &divisor);
    S.Extension = deviceExtension;
    S.Data = (PVOID) (ULONG_PTR) divisor;

#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "PFD warning that we are calling interrupt synchronize routine directly. Suppress it because interrupt is disabled above.")
    SerialSetBaud(deviceExtension->WdfInterrupt, &S);

    //
    // Reset / Re-enable the FIFO's
    //

    if (deviceExtension->FifoPresent) {
       WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0);
       READ_RECEIVE_BUFFER(deviceExtension, deviceExtension->Controller);
       WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller,
                          (UCHAR)(SERIAL_FCR_ENABLE | deviceExtension->RxFifoTrigger
                                  | SERIAL_FCR_RCVR_RESET
                                  | SERIAL_FCR_TXMT_RESET));
    } else {
       WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0);
    }

    //
    // Restore a couple more registers
    //

    WRITE_INTERRUPT_ENABLE(deviceExtension, deviceExtension->Controller, pDevState->IER);
    WRITE_LINE_CONTROL(deviceExtension, deviceExtension->Controller, pDevState->LCR);

    //
    // Clear out any stale interrupts
    //

    READ_INTERRUPT_ID_REG(deviceExtension, deviceExtension->Controller);
    READ_LINE_STATUS(deviceExtension, deviceExtension->Controller);
    READ_MODEM_STATUS(deviceExtension, deviceExtension->Controller);

    //
    // TODO:  move this code to EvtInterruptEnable.
    //

    if (deviceExtension->DeviceState.Reopen == TRUE) {
       SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Reopening device\n");

       SetDeviceIsOpened(deviceExtension, TRUE, FALSE);

       //
       // This enables interrupts on the device!
       //

       WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller,
                           (UCHAR)(pDevState->MCR | SERIAL_MCR_OUT2));

       //
       // Refire the state machine
       //

       DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller);
       ENABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller);
    }

    SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--SerialEvtDeviceD0Entry\n");

    return STATUS_SUCCESS;
}
コード例 #4
0
ファイル: regutils.cpp プロジェクト: uri247/wdk80
BOOLEAN
UartRecordInterrupt(
    _In_ WDFDEVICE Device
    )
{
    BOOLEAN servicedAnInterrupt = FALSE;
    UCHAR regInterruptId = 0;
    UCHAR regLineStatus = 0;
    UCHAR regModemStatus = 0;
    UCHAR oldErrorBits = 0;
    PUART_DEVICE_EXTENSION pDevExt;

    FuncEntry(TRACE_FLAG_REGUTIL);

    pDevExt = UartGetDeviceExtension(Device);

    regInterruptId = READ_INTERRUPT_ID_REG(pDevExt, pDevExt->Controller);

    // If an interrupt actually happened, record the registers...
    // While the NO_INTERRUPT_PENDING bit is NOT set,
    while ((regInterruptId & SERIAL_IIR_NO_INTERRUPT_PENDING) == 0)
    {
        BYTE ier = 0x00;
        servicedAnInterrupt = TRUE;
        
        pDevExt->InterruptIdentifier = regInterruptId;

        // TODO: Fix
        //       IIR indicates a single interrupt ordered by priority.
        //       This switch statement ensures that interrupts are not
        //       confused with one another.
        switch (regInterruptId & SERIAL_IIR_MASK)
        {
        case SERIAL_IIR_RLS:
            regLineStatus = READ_LINE_STATUS(pDevExt, pDevExt->Controller);
            oldErrorBits = pDevExt->LineStatus & SERIAL_LSR_ERROR;
            pDevExt->LineStatus = regLineStatus | oldErrorBits;
            break;

        case SERIAL_IIR_RDA:
        case SERIAL_IIR_CTI:
            // Issue flow control
            UartFlowReceiveFull(Device);

            // Clear the RDA interrupt for now. We will
            // read the data in the DPC.
            ier = READ_INTERRUPT_ENABLE(pDevExt, pDevExt->Controller);
            ier &= (~SERIAL_IER_RDA);
            WRITE_INTERRUPT_ENABLE(pDevExt, pDevExt->Controller, ier);
            break;

        case SERIAL_IIR_THR:
            pDevExt->HoldingEmpty = TRUE;

            // Clear the THR interrupt for now
            ier = READ_INTERRUPT_ENABLE(pDevExt, pDevExt->Controller);
            ier &= ~(SERIAL_IER_THR);
            WRITE_INTERRUPT_ENABLE(pDevExt, pDevExt->Controller, ier);
            break;

        case SERIAL_IIR_MS:
            regModemStatus = READ_MODEM_STATUS(pDevExt, pDevExt->Controller);
            pDevExt->ModemStatus = (pDevExt->ModemStatus & SERIAL_MSR_EVENTS) |
                regModemStatus;
            break;

        default:
            break;
        }

        regInterruptId = READ_INTERRUPT_ID_REG(pDevExt, pDevExt->Controller);
    }

    FuncExit(TRACE_FLAG_REGUTIL);

    return servicedAnInterrupt;
}
コード例 #5
0
ファイル: write.c プロジェクト: ms-iot/bsp
/*++

Routine Description:

    This is the dispatch routine for write.  It validates the parameters
    for the write request and if all is ok then it places the request
    on the work queue.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Pointer to the WDFREQUEST for the current request

    Length - Length of the IO operation
                 The default property of the queue is to not dispatch
                 zero lenght read & write requests to the driver and
                 complete is with status success. So we will never get
                 a zero length request.

Return Value:

--*/
_Use_decl_annotations_
VOID
SerialEvtIoWrite(
    WDFQUEUE Queue,
    WDFREQUEST Request,
    size_t Length
    )
{
    PSERIAL_DEVICE_EXTENSION extension;
    NTSTATUS status;
    WDFDEVICE hDevice;
    WDF_REQUEST_PARAMETERS params;
    PREQUEST_CONTEXT reqContext;
    size_t bufLen;
    UCHAR tempIER=0x00;

    hDevice = WdfIoQueueGetDevice(Queue);
    extension = SerialGetDeviceExtension(hDevice);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                "++SerialEvtIoWrite(%p, 0x%I64x)\r\n", 
                Request,
                Length);

    if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) {

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                    "--SerialEvtIoWrite 1 %Xh\r\n",
                    (ULONG)STATUS_CANCELLED);
        return;
    }

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(Request, &params);

    // Initialize the scratch area of the request.

    reqContext = SerialGetRequestContext(Request);
    reqContext->MajorFunction = params.Type;
    reqContext->Length = (ULONG) Length;

    status = WdfRequestRetrieveInputBuffer (Request,
                                            Length,
                                            &reqContext->SystemBuffer,
                                            &bufLen);

    if (!NT_SUCCESS (status)) {

        SerialCompleteRequest(Request , status, 0);
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                    "--SerialEvtIoWrite 2 %Xh\r\n", 
                    status);
        return;
    }

   SerialStartOrQueue(extension,
                        Request,
                        extension->WriteQueue,
                        &extension->CurrentWriteRequest,
                        SerialStartWrite);

    // enable mini Uart Tx interrupt

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "SerialEvtIoWrite() - enable Tx interrupt\r\n");

    tempIER=READ_INTERRUPT_ENABLE(extension, extension->Controller);
    WRITE_INTERRUPT_ENABLE(extension, extension->Controller, (tempIER | SERIAL_IER_THR));

   TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "--SerialEvtIoWrite()=%X\r\n", status);
   return;
}