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