VOID
SerialSaveDeviceState(IN PSERIAL_DEVICE_EXTENSION PDevExt)
/*++

Routine Description:

    This routine saves the device state of the UART

Arguments:

    PDevExt - Pointer to the device extension for the devobj to save the state
              for.

Return Value:

    VOID


--*/
{
   PSERIAL_DEVICE_STATE pDevState = &PDevExt->DeviceState;

   PAGED_CODE();

   SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Entering SerialSaveDeviceState\n");

   //
   // Read necessary registers direct
   //

   pDevState->IER = READ_INTERRUPT_ENABLE(PDevExt, PDevExt->Controller);
   pDevState->MCR = READ_MODEM_CONTROL(PDevExt, PDevExt->Controller);
   pDevState->LCR = READ_LINE_CONTROL(PDevExt, PDevExt->Controller);

   SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Leaving SerialSaveDeviceState\n");
}
Exemple #2
0
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;
}
Exemple #3
0
/*++

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;
}