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

📄 fir.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
        goto done;
    }

    pPut = pIrPacket;

    // Put in data.
    while (pNdisBuffer)
    {
        LPBYTE pData;
        DWORD  cbData;

        NdisQueryBuffer(pNdisBuffer, &pData, &cbData);
        NdisMoveMemory((PVOID)pPut,(PVOID)pData,cbData);
        pPut += cbData;
        NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
    }

    // Calculate length.
    *lpcbIrPacket = cbNdisPacket;

done:

    return (status);
}

/*++

 Function:       SendFIR

 Description:    Send FIR frame.

 Arguments:

    pIrDevice - Pointer to IR device object.

 Returns:

    NDIS_STATUS

--*/

NDIS_STATUS
SendFIR(
    IN PIR_DEVICE pIrDevice
    )
{
    NDIS_STATUS             status = NDIS_STATUS_SUCCESS;
    PNDIS_IRDA_PACKET_INFO  pIrdaInfo;
    USHORT                  dummy;
    DWORD                   dwRes;

    DEBUGMSG(ZONE_SEND, (TEXT("Enter SendFIR(0x%.8X)\r\n"), pIrDevice));

    pIrdaInfo = GetIrdaPacketInfo(pIrDevice->pSendActive);

    ASSERT(pIrdaInfo != NULL);
    ASSERT(pIrdaInfo->MinTurnAroundTime <= MAX_TAT_usec);

    pIrDevice->cbSendBuf = MAX_IRDA_DATA_SIZE;

    if (GetIrPacket(pIrDevice->pSendActive,
                    pIrDevice->pSendBuf,
                    &pIrDevice->cbSendBuf
        ) == TRUE)
    {
        int msecMinTAT;
        int cbWritten;
        int cbTotalWritten;

        NdisAcquireSpinLock(&pIrDevice->slDevice);
        if ((pIrDevice->fMinTATRequired == TRUE) &&
            (pIrdaInfo->MinTurnAroundTime > 0))
        {
            msecMinTAT = (pIrdaInfo->MinTurnAroundTime+999) / 1000;
            pIrDevice->fMinTATRequired = FALSE;
        }
        else
        {
            msecMinTAT = 0;
        }
        NdisReleaseSpinLock(&pIrDevice->slDevice);
        
        for (cbWritten = 0,cbTotalWritten = 0;
             cbTotalWritten < msecMinTAT;
             cbTotalWritten += cbWritten
             )
        {
            if (WriteFile(pIrDevice->hSerial,
                          pIrDevice->pSendBuf,
                          msecMinTAT - cbTotalWritten,
                          &cbWritten,
                          NULL) == FALSE)
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("WriteFile failed to make MinTAT.\r\n")));
            }
        }

        EnterCriticalSection(&fircs);

        // Disable interrupes
        FIRREG16(FIRIMRREG) = 0x0000;

        // Stop DMA
        FIRREG16(FIRFSRREG) = FIRFSRREG_TX_STOP;

        tx_buffer_ptr = pIrDevice->pSendBuf;
        tx_left_size = pIrDevice->cbSendBuf;
        dma_page_current = dma_page_1;
        if(tx_left_size > IRDA_DMA_BUF_SIZE){
            memcpy(dma_buf_log, tx_buffer_ptr,IRDA_DMA_BUF_SIZE);
            tx_buffer_ptr += IRDA_DMA_BUF_SIZE;
            tx_left_size -= IRDA_DMA_BUF_SIZE;
        }
        else {
            memcpy(dma_buf_log,tx_buffer_ptr,tx_left_size);
            tx_left_size = 0;
        }

        FIRREG16(FIRIRSR1REG) = tx_irsr1;
        FIRREG16(FIRFIRCRREG) = tx_fircr;
        FIRREG16(FIRMIRCRREG) = tx_mircr;

        // Max frame size
        FIRREG16(FIRMRXFREG) = RX_BUFFER_SIZE - 1;

        // Set TX FIFO
        FIRREG16(FIRFSRREG) = FIRFSRREG_TX_TH | FIRFSRREG_F_SIZE;

        // Set DMA mode
        FIRREG16(FIRDMACRREG) = FIRDMACRREG_TRANS_MD_MEM2TDR | FIRDMACRREG_DEMAND;

        // Set Crcreg
        FIRREG16(FIRCRCSRREG) = tx_crcsr;

        // Set IRDA_EN
        FIRREG16(FIRIRSR1REG) |= FIRIRSR1REG_IRDA_EN;

        // Clear TX FIFO
        FIRREG16(FIRFSRREG) |= FIRFSRREG_TXF_CLR;

        // Set TX FRAME size
        FIRREG16(FIRTXFLREG) = (USHORT)pIrDevice->cbSendBuf - 1 ;

        // Clear IFR
        dummy = FIRREG16(FIRIFRREG);

        // Setup send DMA address
        DMAREG32(FIRBALREG) = dma_buf_phy;
        DMAREG32(FIRALREG) = dma_buf_phy;

        // Set DMA MEM to I/O
        DMAREG16(DMATDREG) = 0x0000;

        // Enable interrupts
        FIRREG16(FIRIMRREG) = FIRIMRREG_TX_ABORT | FIRIMRREG_TX_ERR;

        // Set DMA enable
        FIRREG16(FIRDMAERREG) = 0x0001;

        LeaveCriticalSection(&fircs);

        // Wait for transmit complete
        dwRes = WaitForSingleObject(TxEvent, 500);
        if (dwRes == WAIT_FAILED || dwRes == WAIT_TIMEOUT)
        {
            DEBUGMSG(ZONE_ERROR,
                (TEXT("SendFIR: WaitForSingleObject failure = %x\r\n"),
                GetLastError())
            );
            status = NDIS_STATUS_FAILURE;
        }

        // Log packet after it has gone out...less time critical now.
        IRSIR_LOG_NDIS_PACKET(LOG_TXFRAME, pIrDevice->pSendActive);
    }
    else
    {
        IRSIR_LOG_DATA(LOG_TXFRAME,
                       LOG_DTYPE_ASCII,
                       0,
                       "Failed to convert NDIS packet to IR packet");
        DEBUGMSG(ZONE_ERROR, (TEXT("NdisToIrPacket failed to convert packet.\r\n")));
        status = NDIS_STATUS_FAILURE;
    }

    DEBUGMSG(ZONE_SEND, (TEXT("Leave SendFIR [0x%.8X]\r\n"), status));

    return (status);
}

/*++

 Function:       RecvFIR

 Description:    Receive FIR frame.

 Arguments:

    pIrDevice - Pointer to IR device object.

 Returns:

    BOOL

        Success - TRUE.

        Failure - FALSE.

--*/

BOOL
RecvFIR(
    PIR_DEVICE pIrDevice,
    PRX_BUFFER pRxBuf
    )
{
    BOOL    fSuccess = TRUE;
    UINT    size;
    USHORT  rxsts;
    PUCHAR  ptr;
    DWORD   dwRes;

    SetReceive();

    // Wait for receive frame
    dwRes = WaitForSingleObject(RxEvent, INFINITE);
    if (dwRes == WAIT_FAILED)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("SendFIR: WaitForSingleObject failure = %x\r\n"),
            GetLastError())
        );
        fSuccess = FALSE;
    }

    if (pIrDevice->RxState == RX_STATE_SHUTDOWN) {
        fSuccess = FALSE;
    }

    if (fSuccess)
    {
        pIrDevice->fMediaBusy = TRUE;
        EnterCriticalSection(&fircs);

        size = 0;
        while ((rxsts = FIRREG16(FIRRXSTSREG)) & FIRRXSTSREG_VALID)
        {
            if (rxsts & (FIRRXSTSREG_MRXF_OV | FIRRXSTSREG_ABORT | FIRRXSTSREG_CRC_ERR | FIRRXSTSREG_RXF_OV))
            {
                // Purge error frame
                DEBUGMSG(ZONE_RECV, (TEXT("      VrFIR_GetRxFrame : RXSTS = %04x"),rxsts));
                rx_frame_ptr += FIRREG16(FIRRXFLREG) + 1;
                continue;
            }
            ptr = rx_frame_ptr;
            size = FIRREG16(FIRRXFLREG) + 1;
            rx_frame_ptr += size;
            if (size > pRxBuf->cbBuffer)
            {
                DEBUGMSG(ZONE_RECV, (TEXT("Abort VrFIR_GetRxFrame : max < size = %d"),size));
                fSuccess = FALSE;
                break;
            }
            memcpy(pRxBuf->pbBuffer,ptr,size);
            pRxBuf->cbData = size;
            break;
        }

        LeaveCriticalSection(&fircs);
    }

    //DEBUGMSG(ZONE_RECV, (TEXT("Leave RecvFIR [0x%.8X]\r\n"), status));

    return (fSuccess);
}

NDIS_STATUS
FIRSetSpeed(
    IN     DWORD   dwNewSpeed
    )
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;

    DEBUGMSG(ZONE_DONGLE, (TEXT("Enter FIRSetSpeed(%d)\r\n"), dwNewSpeed));

    EnterCriticalSection(&fircs);

    if (IS_SIR(dwNewSpeed))
    {
        //
        // SIR mode
        //

        // TMICMODE = 0 / TMICTX = 0 / IRMSEL = 10 / IRUSESEL = 0 / SIRSEL = 1
        SIUREG8(SIUIRSELREG) = 0x0009;
    }
    else if (IS_MIR(dwNewSpeed))
    {
        //
        // MIR mode
        //

        if (IS_MIR_HALF(dwNewSpeed))
        {
            rx_irsr1 = FIRIRSR1REG_MIR_H;
            rx_fircr = FIRFIRCRREG_PA_LEN | FIRFIRCRREG_W_PULSE | FIRFIRCRREG_F_WIDTH;
            rx_mircr = FIRMIRCRREG_STA_LEN_H | FIRMIRCRREG_M_WIDTH_H;
            rx_crcsr = FIRCRCSRREG_RX_EN | 0x0001;  //DATA_INV = 1;

            tx_irsr1 = FIRIRSR1REG_MIR_H;
            tx_fircr = FIRFIRCRREG_PA_LEN | FIRFIRCRREG_W_PULSE | FIRFIRCRREG_F_WIDTH;
            tx_mircr = FIRMIRCRREG_STA_LEN_H | FIRMIRCRREG_M_WIDTH_H;
            tx_crcsr = FIRCRCSRREG_TX_EN | 0x0001;  //DATA_INV = 1;
        }
        else if (IS_MIR_FULL(dwNewSpeed))
        {
            rx_irsr1 = FIRIRSR1REG_MIR_F;
            rx_fircr = FIRFIRCRREG_PA_LEN | FIRFIRCRREG_W_PULSE | FIRFIRCRREG_F_WIDTH;
            rx_mircr = FIRMIRCRREG_STA_LEN_F | FIRMIRCRREG_M_WIDTH_F;
            rx_crcsr = FIRCRCSRREG_RX_EN | 0x0001;  //DATA_INV = 1;

            tx_irsr1 = FIRIRSR1REG_MIR_F;
            tx_fircr = FIRFIRCRREG_PA_LEN | FIRFIRCRREG_W_PULSE | FIRFIRCRREG_F_WIDTH;
            tx_mircr = FIRMIRCRREG_STA_LEN_F | FIRMIRCRREG_M_WIDTH_F;
            tx_crcsr = FIRCRCSRREG_TX_EN | 0x0001;  //DATA_INV = 1;
        }

        // TEMICMODE = 0 / TMICTX = 0 / IRMSEL = 10 / IRUSESEL = 1 / SIRSEL = 1
        SIUREG8(SIUIRSELREG) = 0x000B;
    }
    else if (IS_FIR(dwNewSpeed))
    {
        //
        // FIR mode
        //

        rx_irsr1 = FIRIRSR1REG_FIR;
        rx_fircr = FIRFIRCRREG_PA_LEN | FIRFIRCRREG_W_PULSE | FIRFIRCRREG_F_WIDTH;
        rx_mircr = FIRMIRCRREG_STA_LEN_F | FIRMIRCRREG_M_WIDTH_F;
        rx_crcsr = FIRCRCSRREG_RX_EN | 0x0000;  //DATA_INV = 0

        tx_irsr1 = FIRIRSR1REG_FIR;
        tx_fircr = FIRFIRCRREG_PA_LEN | FIRFIRCRREG_W_PULSE | FIRFIRCRREG_F_WIDTH;
        tx_mircr = FIRMIRCRREG_STA_LEN_F | FIRMIRCRREG_M_WIDTH_F;
        tx_crcsr = FIRCRCSRREG_TX_EN | 0x0000;  //DATA_INV = 0

        // TEMICMODE = 0 / TMICTX = 0 / IRMSEL = 10 / IRUSESEL = 1 / SIRSEL = 1
        SIUREG8(SIUIRSELREG) = 0x000B;
    }
    else
    {
        status = NDIS_STATUS_NOT_SUPPORTED;
    }

    LeaveCriticalSection(&fircs);

    DEBUGMSG(ZONE_DONGLE, (TEXT("Leave FIRSetSpeed [0x%.8X]\r\n"), status));

    return (status);
}


static void
FIRISR(void)
{
    USHORT ifr;
    USHORT dpintr;

    dpintr = FIRREG16(FIRDPINTRREG);

    if (dpintr & FIRDPINTRREG_FDPINT1)
    {
        // Tx DMA page boundary intr
        if(tx_left_size > 0){
            if(tx_left_size > IRDA_DMA_PAGE_SIZE){
                memcpy(dma_page_current, tx_buffer_ptr, IRDA_DMA_PAGE_SIZE);
                tx_buffer_ptr += IRDA_DMA_PAGE_SIZE;
                tx_left_size -= IRDA_DMA_PAGE_SIZE;
            }
            else {
                memcpy(dma_page_current,tx_buffer_ptr,tx_left_size);
                tx_left_size = 0;
            }
        }

        FIRREG16(FIRDPINTRREG) = FIRDPINTRREG_FDPINT1;

        // flip page
        if (dma_page_current == dma_page_1) {
            dma_page_current = dma_page_2;
        } else {
            dma_page_current = dma_page_1;
        }
    }

    if (dpintr & FIRDPINTRREG_FDPINT2)
    {
        // Rx DMA page boundary intr
        if (rx_left_size >= IRDA_DMA_PAGE_SIZE)
        {
            memcpy(rx_buffer_ptr, dma_page_current, IRDA_DMA_PAGE_SIZE);
            rx_buffer_ptr += IRDA_DMA_PAGE_SIZE;
            rx_left_size -= IRDA_DMA_PAGE_SIZE;
        }
        else
        {
            memcpy(rx_buffer_ptr, dma_page_current, rx_left_size);
            rx_left_size = 0;
        }

        FIRREG16(FIRDPINTRREG) = FIRDPINTRREG_FDPINT2;

        // flip page
        if (dma_page_current == dma_page_1) {
            dma_page_current = dma_page_2;
        } else {
            dma_page_current = dma_page_1;
        }
    }

    if (dpintr & FIRDPINTRREG_FDPINT3)
    {
        // Tx DMA underrun
        FIRREG16(FIRDPINTRREG) = FIRDPINTRREG_FDPINT3;

        // TODO: error recovery
    }

    if (dpintr & FIRDPINTRREG_FDPINT4)
    {
        // Rx DMA overrun
        FIRREG16(FIRDPINTRREG) = FIRDPINTRREG_FDPINT4;

        // TODO: error recovery
        SetReceive();
    }

    if (dpintr & FIRDPINTRREG_FDPINT5)
    {
        ifr = FIRREG16(FIRIFRREG);

        if (ifr & FIRIFRREG_TX_ERR)
        {
            SetReceive();
        }

        if (ifr & FIRIFRREG_TX_ABORT)
        {
            SetReceive();
            SetEvent(TxEvent);
        }

        if (ifr & FIRIFRREG_RX_VALID)
        {
            UINT size = DMAREG32(FIRALREG) & (IRDA_DMA_PAGE_SIZE - 1);

            if (rx_left_size > size)
            {
                memcpy(rx_buffer_ptr,dma_page_current,size);
            }
            else {
                memcpy(rx_buffer_ptr,dma_page_current,rx_left_size);
            }
            SetEvent(RxEvent);
        }
    }
}


static void
FIRInterruptThread(void)
{
    while (TRUE)  {
        WaitForSingleObject(hFIRintr, INFINITE);
        FIRISR();
        InterruptDone(dwSysIntrIr);
    }
}

VOID
FIRMediaBusy(
    IN PIR_DEVICE pIrDevice
    )
{
    if (FIRREG16(FIRRXIRREG) & 0x80)
    {
        pIrDevice->fMediaBusy = TRUE;
    }
}

⌨️ 快捷键说明

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