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

📄 fir.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "irsirp.h"

#define FIRFSRREG_F_SIZE        FIRFSRREG_F_SIZE_64
//#define FIRFSRREG_TX_TH           FIRFSRREG_TX_TH_8_16
#define FIRFSRREG_TX_TH         FIRFSRREG_TX_TH_26_48
#define FIRFSRREG_RX_TH         FIRFSRREG_RX_TH_26_48

#define FIRFIRCRREG_F_WIDTH     FIRFIRCRREG_F_WIDTH_S6_D12
#define FIRFIRCRREG_W_PULSE     FIRFIRCRREG_W_PULSE_8_9
#define FIRFIRCRREG_PA_LEN      FIRFIRCRREG_PA_LEN_16

#define FIRMIRCRREG_M_WIDTH_F   FIRMIRCRREG_M_WIDTH_9
#define FIRMIRCRREG_STA_LEN_F   FIRMIRCRREG_STA_LEN_2
#define FIRMIRCRREG_M_WIDTH_H   FIRMIRCRREG_M_WIDTH_21
#define FIRMIRCRREG_STA_LEN_H   FIRMIRCRREG_STA_LEN_2

//#define FIRDMACRREG_DEMAND        FIRDMACRREG_DEMAND_1
#define FIRDMACRREG_DEMAND      FIRDMACRREG_DEMAND_7

#define RX_PACKET_BUFFER_SIZE   (MAX_RX_DATA_SIZE * MAX_RX_PACKETS)
static UCHAR            rx_buffer[RX_PACKET_BUFFER_SIZE];

static volatile PUCHAR  tx_buffer_ptr ;
static volatile UINT    tx_left_size;
static volatile PUCHAR  rx_buffer_ptr ;
static volatile UINT    rx_left_size;
static volatile PUCHAR  rx_frame_ptr ;

static ULONG    dma_buf_phy;
static PUCHAR   dma_buf_log;
static PUCHAR   dma_page_current;
static PUCHAR   dma_page_1;
static PUCHAR   dma_page_2;

static USHORT   tx_irsr1;
static USHORT   tx_fircr;
static USHORT   tx_mircr;
static USHORT   tx_crcsr;

static USHORT   rx_irsr1;
static USHORT   rx_fircr;
static USHORT   rx_mircr;
static USHORT   rx_crcsr;

static HANDLE   TxEvent;
static HANDLE   RxEvent;

static CRITICAL_SECTION fircs;

static HANDLE   hFIRist;    // FIR interrupt thread
static HANDLE   hFIRintr=NULL;   // FIR interrupt event

#define IS_SIR(speed)       ((speed) <= 115200)
#define IS_MIR_HALF(speed)  ((speed) == 576000)
#define IS_MIR_FULL(speed)  ((speed) == 1152000)
#define IS_MIR(speed)       (IS_MIR_HALF(speed) || IS_MIR_FULL(speed))
#define IS_FIR(speed)       ((speed) == 4000000)

static void FIRInterruptThread(void);
extern DWORD dwSysIntrIr;
/*++

 Function:       InitializeFIR

 Description:    Initializes the FIR resouces.

 Arguments:

    pIrDevice - Pointer to the device object to free.

 Returns:

    NDIS_STATUS

 Comments:

--*/

NDIS_STATUS
InitializeFIR(
    IN OUT PIR_DEVICE pIrDevice
    )
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;

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

    ASSERT(pIrDevice != NULL);

    //
    // Map in the internal I/O space
    //
    if (!MapVR4122intio())
    {
        DEBUGMSG(ZONE_ERROR,
                  (TEXT("Abort VrIRDA_Initialize : pVRIO map failed\r\n"))
                 );

        status = NDIS_STATUS_RESOURCES;
        goto done;
    }

    //
    // Get DMA buffer physical address
    // HAL sets initial values to registers at OEMInit()
    //
    dma_buf_phy = DMAREG32(FIRBALREG) & 0x01fff800;

    //
    // Map DMA page into the local address space
    //
    dma_buf_log = VirtualAlloc(0,IRDA_DMA_BUF_SIZE,MEM_RESERVE,PAGE_NOACCESS);
    if (dma_buf_log == NULL)
    {
        DEBUGMSG(ZONE_ERROR,
                  (TEXT("Abort VrIRDA_Initialize : DMA buffer allocation failed\r\n"))
                 );

        status = NDIS_STATUS_RESOURCES;
        goto done;
    }

    if (VirtualCopy((PVOID)dma_buf_log,
                    (PVOID)(dma_buf_phy>>8),
                    IRDA_DMA_BUF_SIZE,
                    PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL
        ) == FALSE)
    {
        DEBUGMSG(ZONE_ERROR,
                  (TEXT("Abort VrIRDA_Initialize : DMA buffer VirtualCopy failed\r\n"))
                 );

        status = NDIS_STATUS_FAILURE;
        goto done;
    }

    DEBUGMSG(ZONE_INIT,
             (TEXT("      VrIRDA_Initialize : dmapage = 0x%08x"),
               dma_buf_log)
             );

    dma_page_1 = dma_buf_log;
    dma_page_2 = dma_page_1 + IRDA_DMA_PAGE_SIZE;

    //
    // Initialize DMA address
    //
    DMAREG32(FIRBALREG) = dma_buf_phy;
    DMAREG32(FIRALREG)  = dma_buf_phy;

    // Create Tx/Rx complete events
    TxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    RxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    // Initialize FIR critical section
    InitializeCriticalSection(&fircs);

    // Create FIR interrupt event
	if (hFIRintr==NULL) { // Create Thread only if first time
		hFIRintr = CreateEvent(NULL, FALSE, FALSE, NULL);
		
		if (!hFIRintr) {
			status = NDIS_STATUS_RESOURCES;
			goto done;
		}
		
		// Associate interrupt ID with event.
		if (!InterruptInitialize(dwSysIntrIr, hFIRintr, NULL, 0)) {
			//      status = NDIS_STATUS_FAILURE;
			//      goto done;
		}
		// Clear pending interrupts
		InterruptDone(dwSysIntrIr);
		
		// Create FIR interrupt service thread
		hFIRist = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
			(LPTHREAD_START_ROUTINE)FIRInterruptThread,
			NULL, 0, NULL);
		
		if (!hFIRist) {
			status = NDIS_STATUS_RESOURCES;
			goto done;
		}
		
		SetThreadPriority(hFIRist, THREAD_PRIORITY_HIGHEST);
	}

done:

    if (status != NDIS_STATUS_SUCCESS)
    {
        DeinitializeFIR(pIrDevice);
    }

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

    return (status);
}

/*++

 Function:       DeinitializeFIR

 Description:    Releases all memory associated.

 Arguments:

    pIrDevice - Pointer to the device object to free.

 Returns:

    NDIS_STATUS

 Comments:

--*/

NDIS_STATUS
DeinitializeFIR(
    IN OUT PIR_DEVICE pIrDevice
    )
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;

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

    ASSERT(pIrDevice != NULL);

    // Disable FIR interrupt
    InterruptDisable(dwSysIntrIr);

    // Delete FIR interrupt service thread
/* Do not need, Because Thread does not dye after Reset Cycle.
    if (hFIRist) {
        CloseHandle(hFIRist);
        hFIRist = NULL;
    }
*/
    // DeInitialize FIR critical section
    DeleteCriticalSection(&fircs);

    //
    // Free up memory.
    //
    if (dma_buf_log != NULL)
    {
        VirtualFree((void *)dma_buf_log,0,MEM_RELEASE);
    }

    //
    // The driver is being unloaded. Deinitialize. Free up memory, etc.
    //

    FreeVR4122intio();

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

    return (status);
}

/*++

 Function:       StartFIR

 Description:    Start the FIR logic.

 Arguments:

    pIrDevice - Pointer to IR device object.

 Returns:

    NDIS_STATUS

--*/

NDIS_STATUS
StartFIR(
    IN PIR_DEVICE pIrDevice
    )
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;

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

    EnterCriticalSection(&fircs);

    // Turn on FIR clock
    InterlockedAndOr16(PCMUREG16(CMUCLKMSK),0xffff,(MSKFIR | MSKFFIR));

    // Reset FIR
    FIRREG16(FIRFRSTRREG) = FIRFRSTRREG_FRST;
    FIRREG16(FIRFRSTRREG) = 0x0000;

    // Set 4Mbps mode
    FIRREG16(FIRIRSR1REG) = FIRIRSR1REG_FIR;

    // Set FIR mode
    FIRREG16(FIRFIRCRREG) = FIRFIRCRREG_PA_LEN
                          | FIRFIRCRREG_W_PULSE
                          | FIRFIRCRREG_F_WIDTH;

    // Set MIR mode
    FIRREG16(FIRMIRCRREG) = FIRMIRCRREG_STA_LEN_F
                          | FIRMIRCRREG_M_WIDTH_F;

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

    // Unmask DMA request
    InterlockedAndOr16(PDMAREG16(DMAMSKREG),0xffff,DMAMSKREG_DMAMSKFOUT);

    LeaveCriticalSection(&fircs);

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

    return (status);
}

/*++

 Function:       StopFIR

 Description:    Stop the FIR logic.

 Arguments:

    pIrDevice - Pointer to IR device object.

 Returns:

    NDIS_STATUS

--*/

NDIS_STATUS
StopFIR(
    IN PIR_DEVICE pIrDevice
    )
{
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;

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

    EnterCriticalSection(&fircs);

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

    // Stop DMA
    FIRREG16(FIRFSRREG) = FIRFSRREG_TX_STOP;
    InterlockedAndOr16(PDMAREG16(DMAMSKREG),~DMAMSKREG_DMAMSKFOUT,0x0000);

    // Reset FIR
    FIRREG16(FIRFRSTRREG) = FIRFRSTRREG_FRST;
    FIRREG16(FIRFRSTRREG) = 0x0000;

    // Turn off FIR clock
    InterlockedAndOr16(PCMUREG16(CMUCLKMSK),~(MSKFIR | MSKFFIR),0x0000);

    LeaveCriticalSection(&fircs);

    SetEvent(RxEvent);

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

    return (status);
}

static void
SetReceive(void)
{
    USHORT  dummy;

    EnterCriticalSection(&fircs);

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

    // Stop DMA
    FIRREG16(FIRFSRREG) = FIRFSRREG_TX_STOP;

    rx_frame_ptr = rx_buffer_ptr = rx_buffer;
    rx_left_size = RX_PACKET_BUFFER_SIZE;
    dma_page_current = dma_page_1;

    FIRREG16(FIRIRSR1REG) = rx_irsr1;
    FIRREG16(FIRFIRCRREG) = rx_fircr;
    FIRREG16(FIRMIRCRREG) = rx_mircr;

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

    // Set RX FIFO
    FIRREG16(FIRFSRREG) = FIRFSRREG_RX_TH | FIRFSRREG_F_SIZE;

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

    // Set Crcreg
    FIRREG16(FIRCRCSRREG) = rx_crcsr;

    // Clear RX FIFO
    FIRREG16(FIRFSRREG) |= FIRFSRREG_RXF_CLR;

    // Clear IFR
    dummy = FIRREG16(FIRIFRREG);

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

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

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

    // Enable interrupts
    FIRREG16(FIRIMRREG) = FIRIMRREG_RX_VALID;

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

    LeaveCriticalSection(&fircs);
}

/*++

 Function:       GetIrPacket

 Description:    Get NDIS Packet and make into FIR Packet.

 Arguments:

    pNdisPacket     - Ndis packet to convert to IR packet.

    pIrPacket       - IR packet buffer to copy IR frame into.

    lpcbIrPacket    - IN:  Size of IR packet buffer.
                      OUT: Count of bytes copied into IR packet buffer.

 Returns:

    BOOL

        Success - TRUE.

        Failure - FALSE.

 Comments:

 On failure, *lpcbIrPacket will contain the buffer size required to convert
 the packet, or 0 if a corruption was detected.

--*/

static BOOL
GetIrPacket(
    IN     PNDIS_PACKET pNdisPacket,
       OUT LPBYTE       pIrPacket,
    IN OUT LPDWORD      lpcbIrPacket
    )
{
    BOOL                    status = TRUE;
    DWORD                   cbNdisPacket;
    PNDIS_BUFFER            pNdisBuffer;
    LPBYTE                  pPut;

    ASSERT(lpcbIrPacket != NULL);

    //
    // Get size of the NDIS packet.
    //

    NdisQueryPacket(pNdisPacket, NULL, NULL, &pNdisBuffer, &cbNdisPacket);

    // Is the packet legal? Must be at least size of address and control fields.
    if (cbNdisPacket < (SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE))
    {
        *lpcbIrPacket = 0;
        status = FALSE;
        goto done;
    }

    // Is NDIS packet too large?
    if (cbNdisPacket > *lpcbIrPacket)
    {
        *lpcbIrPacket = 0;
        status = FALSE;

⌨️ 快捷键说明

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