⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isr.c

📁 ir 驱动程序源代码,make成功了,有兴趣的朋友可以看看
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright 2005 OSR, Open Systems Resources, Inc. All rights Reserved.
// 
// Module Name:
// 
//     isr.c
// 
// Abstract:
//
//     Contains routines for interrupts
// 
// Author:
//
// Revision History:
//      
#include "smscir.h"

#ifdef WPP_TRACING
#include "isr.tmh"
#endif


//
// Forward declarations
//

VOID
SmscIrEnableReceiveInterrupts(
    PSMSCIR_DATA DeviceData
    );

VOID
SmscIrEnableTransmitInterrupts(
    PSMSCIR_DATA DeviceData
    );

VOID 
SmscIrEnqueueFifoByte(
    IN PSMSCIR_DATA FdoData,
    UCHAR Byte,
    IN BOOLEAN DataEnd
    );

BOOLEAN
SmscIrProcessRxInterrupt(
    PSMSCIR_DATA DeviceData,
    PINTERRUPT_ID_OR_ENABLE RxIntId
    );

BOOLEAN
SmscIrProcessTxInterrupt(
    PSMSCIR_DATA DeviceData,
    PBIRCC2_INTERRUPT_ID_OR_ENABLE TxIntId
    );


NTSTATUS
SmscIrEvtInterruptEnable(
    IN WDFINTERRUPT Interrupt,
    IN WDFDEVICE    Device
    ) {
/*++

Routine Description.

    Called here to enable interrupts on the device. 

Arguments:

    Interrupt  - Our interrupt object

    Device     - The device to enable interrupts on

--*/
    PSMSCIR_DATA           deviceData;

    UNREFERENCED_PARAMETER(Interrupt);

    SmscIrTracePrint(TRACE_LEVEL_VERBOSE, 
                     SMSCDBG_INIT_INFO, 
                     ("SmscIrEvtInterruptEnable: Entered"));
    
    deviceData = (PSMSCIR_DATA)GetIrData(Device);

    //
    // Setup the device for RECEIVE interrupts
    //
    SmscIrEnableReceiveInterrupts(deviceData);

    //
    // Setup the device for TRANSMIT interrupts
    //
    SmscIrEnableTransmitInterrupts(deviceData);

    SmscIrTracePrint(TRACE_LEVEL_VERBOSE, 
                     SMSCDBG_INIT_INFO, 
                     ("SmscIrEvtInterruptEnable: Exited"));

    return STATUS_SUCCESS;

}


VOID
SmscIrEnableReceiveInterrupts(
    PSMSCIR_DATA DeviceData
    ) {
/*++

Routine Description.

    Helper routine to enable receive interrupts

Arguments:

    DeviceData     - The device extension

--*/
    MASTER_BLOCK_CONTROL   mbc;
    INTERRUPT_ID_OR_ENABLE intEnable;
    LINE_CONTROL_B         lcb;
    LINE_CONTROL_A         lca;
    CONSUMER_IR_CTRL       irCtrl;


    //
    // First thing is first, reset the device...
    //
    mbc.AsUChar = 0;
    mbc.MasterReset = TRUE;
    mbc.ErrorReset = TRUE;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_MASTER_BLOCK_CONTROL,
                         mbc.AsUChar);


    mbc.AsUChar = 0;
    mbc.RegisterBlockSelect = 1;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_MASTER_BLOCK_CONTROL,
                         mbc.AsUChar);

    //
    // Setup the receive threshold. We'll get an interrupt
    //  when FIFO_THRESHOLD_FOR_RECEIVE bytes are in the 
    //  FIFO
    //
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_FIFO_THRESHOLD,
                         FIFO_THRESHOLD_FOR_RECEIVE);

    mbc.AsUChar = 0;
    mbc.RegisterBlockSelect = 2;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_MASTER_BLOCK_CONTROL,
                         mbc.AsUChar);


    irCtrl.AsUChar = 0;
    irCtrl.CarrierOff  = TRUE;
    irCtrl.ReceiveSync = TRUE;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_CONSUMER_IR_CTRL,
                         irCtrl.AsUChar);
    
    //
    // RC6 uses a 36kHz carrier, which is the standard
    //  that the class driver uses. So, not matter
    //  what device the IR is coming from the class driver
    //  wants the data modulated at 36kHz
    //
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_CONSUMER_IR_CARRIER,
                         SMSCIR_RC6_CARRIER_DIVIDER);

    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_CONSUMER_IR_BIT_RATE,
                         SMSCIR_BIT_RATE_DIVIDER);


    //
    // Back to register block 0...
    //
    mbc.AsUChar = 0;
    mbc.RegisterBlockSelect = 0;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_MASTER_BLOCK_CONTROL,
                         mbc.AsUChar);

    //
    // It appears that in some cases the master reset
    //  doesn't dump out FIFO garbage, do that now...
    //
    lca.AsUChar = 0;
    lca.FifoReset = TRUE;

    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_LINE_CONTROL_A,
                         lca.AsUChar);

    //
    // Enable interrupt support on the device
    //
    mbc.AsUChar = 0;
    mbc.MasterInterruptEnable = TRUE;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_MASTER_BLOCK_CONTROL,
                         mbc.AsUChar);


    //
    // Enable FIFO interrupts.
    //
    intEnable.AsUChar = 0;
    intEnable.Fifo    = TRUE;
    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_INTERRUPT_ENABLE,
                         intEnable.AsUChar);


    //
    // Set the device to receive.
    //
    lcb.AsUChar = 0;
    lcb.SCEModeBits = SCE_MODE_RECEIVE;

    WRITE_HARDWARE_UCHAR(DeviceData,
                         CIRCC2_LINE_CONTROL_B,
                         lcb.AsUChar);

    return;

}

VOID
SmscIrEnableTransmitInterrupts(
    PSMSCIR_DATA DeviceData
    ) {
/*++

Routine Description.

    Helper routine to enable transmit interrupts

Arguments:

    DeviceData     - The device extension

--*/

    BIRCC2_MASTER_BLOCK_CONTROL   txMbc;
    BIRCC2_MODE                   txMode;


    //
    // First thing is first, reset the device...
    //
    txMbc.AsUChar = 0;
    txMbc.MasterReset = TRUE;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_MASTER_BLOCK_CONTROL_ADDR,
                         txMbc.AsUChar);

    //
    // Now setup the FIFO threshold, which happens in register 1
    //
    txMbc.AsUChar = 0;
    txMbc.RegisterBlockSelect = 1;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_MASTER_BLOCK_CONTROL_ADDR,
                         txMbc.AsUChar);

    //
    // Setup the Tx FIFO threshold
    //
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_FIFO_THRESHOLD_ADDR,
                         FIFO_THRESHOLD_FOR_TRANSMIT);

    //
    // Default to the RC6 carrier
    //
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_CONSUMER_IR_CARRIER,
                         SMSCIR_RC6_CARRIER_DIVIDER);

    //
    // And the standard bit rate divider (to make 50usec
    //  samples)
    //
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_CONSUMER_IR_BIT_RATE,
                         SMSCIR_BIT_RATE_DIVIDER);

    txMode.AsUChar = 0;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_MODE_ADDR,
                         txMode.AsUChar);

    //
    // Back to block zero to set the appropriate interrupt
    //  enable bits
    //
    txMbc.AsUChar = 0;
    txMbc.RegisterBlockSelect = 0;
    txMbc.MasterInterruptEnable = TRUE;
    WRITE_TRANSMIT_UCHAR(DeviceData,
                         BIRCC2_MASTER_BLOCK_CONTROL_ADDR,
                         txMbc.AsUChar);


}


BOOLEAN
SmscIrEvtInterruptIsr(
    IN WDFINTERRUPT Interrupt,
    IN ULONG        MessageID
    ) {
/*++

Routine Description.

    The interrupt service routine for the 
    SMSC CIRCC2 device. This ISR fires every
    time there is a FIFO interrupt, which means
    that there is data to receive in Rx mode
    or that more data needs to be moved into the
    FIFO in Tx mode

Arguments:

    Interrupt       - Our interrupt object

    MessageID       - For MSI interrupts. Not used.

--*/

    PSMSCIR_DATA           deviceData;
    INTERRUPT_ID_OR_ENABLE rxIntId;
    BOOLEAN                requestDpc = FALSE;
    BIRCC2_INTERRUPT_ID_OR_ENABLE txIntId;

    UNREFERENCED_PARAMETER(MessageID);
    
    deviceData = (PSMSCIR_DATA)GetIrData(WdfInterruptGetDevice(Interrupt));


    //
    // Check for Rx interrupt
    //
    rxIntId.AsUChar = READ_HARDWARE_UCHAR(deviceData,
                                          CIRCC2_INTERRUPT_ID);

    //
    // Receive interrupt?
    // 
    if (SmscIrProcessRxInterrupt(deviceData, &rxIntId)) {
        
        //
        // We'll need a DPC to complete any outstanding
        //  receive requests that his might fulfill...
        //
        requestDpc = TRUE;
        
    }
    
    //
    // And check for Tx interrupt
    //
    txIntId.AsUChar = READ_TRANSMIT_UCHAR(deviceData,
                                          BIRCC2_INTERRUPT_ID_ADDR);

    if (SmscIrProcessTxInterrupt(deviceData, &txIntId)) {

        //
        // We'll need a DPC to continue the blasting...
        //
        requestDpc = TRUE;

    }


    if (requestDpc) {

        WdfInterruptQueueDpcForIsr(Interrupt);

    }



    //
    // We're an ISA interrupt and therefore we are NOT
    //  shared. If we're interrupting here then it
    //  was definitely our interrupt...
    //
    return TRUE;

}



BOOLEAN
__forceinline
SmscIrProcessRxInterrupt(
    PSMSCIR_DATA DeviceData,
    PINTERRUPT_ID_OR_ENABLE RxIntId
    ) {
/*++

Routine Description.

    Helper routine to check for and process receive interrupts
    one the device.


    returns TRUE if the RX interrupt is active and a DPC is 
    required.

Arguments:

    DeviceData      - Our device extension

    RxIntId         - The contents of the CIRCC2_INTERRUPT_ID register

--*/

    LINE_CONTROL_B          lcb;
    MASTER_BLOCK_CONTROL    mbc;
    INTERRUPT_ID_OR_ENABLE  intEnable;
    LINE_CONTROL_A          lca;
    LINE_STATUS_READ        lsr;
    UCHAR                   byte;
    BOOLEAN                 bytesDequeued;
    UCHAR                   carrierMeasure;
    CARRIER_CAPTURE_CONTROL captureControl;

    if (RxIntId->Fifo) {

        //
        // Clear the FIFO interrupt by disabling FIFO
        //  interrupts. We'll enable it again before we
        //  leave
        //
        intEnable.AsUChar = 0;
        intEnable.Fifo    = FALSE;
        WRITE_HARDWARE_UCHAR(DeviceData,
                             CIRCC2_INTERRUPT_ENABLE,
                             intEnable.AsUChar);

        //
        // We set the trigger to fire when there is SIZE-1 bytes in the
        //  FIFO (cuz that's the highest watermark allowed). Copy all
        //  of those bytes out.
        //
        for (bytesDequeued = 0; 
                    bytesDequeued < (SMSCIR_FIFO_SIZE-1); 
                                            bytesDequeued++) {


            byte = READ_HARDWARE_UCHAR(DeviceData,
                                       CIRCC2_DATA);

            
            //
            // Enqueue the byte to be picked up by the DPC. FALSE
            //  because this is not a data end 
            //
            SmscIrEnqueueFifoByte(DeviceData,
                                  byte,
                                  FALSE); 

            //
            // Do we have an FF?
            //
            if (byte == 0xFF) {
            
                //
                // Update the number that we've seen so far...
                //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -