📄 fir.c
字号:
#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 + -