📄 irdahw.cpp
字号:
// 2. If we are in Send mode, send bytes and discard bytes received.
// 3. If we are in recieve mode, recieve bytes and give the bytes
// back to the OS.
//
DWORD WINAPI SIRInterruptHandler(LPVOID Handle)
{
DEBUGMSG(ZONE_IRDAHW, (TEXT("+SIRInterruptHandler")));
DWORD ulUART2FLAGS;
UCHAR ucRecievedByte;
IRMiniport *pIrMiniport = (IRMiniport *)Handle;
PRX_BUFFER pRxBuf;
//
// Get the first free item.
//
pRxBuf = pIrMiniport->m_ReceivePacketList.GetFree();
//
// Set the next buffer location.
//
pIrMiniport->m_SirState.SetNextBuffer(pRxBuf);
while(1)
{
//
// Wait until the interrupt for the serial port occurs.
//
WaitForSingleObject(pIrMiniport->m_hSirEvent, INFINITE);
//
// Set the Media busy flag.
//
pIrMiniport->m_fMediaBusy = TRUE;
//
// Check if we are exiting the loop.
//
if(pIrMiniport->m_bSirExiting)
{
break;
}
//
// If we have bytes to send and the fifo is not full,
// then fill up the fifo.
//
while(pIrMiniport->m_pSIRTransmitNDisPacket && !(*UART2_FR & FR_TXFF))
{
//
// Send the next byte out.
//
*UART2_DR = pIrMiniport->m_pSendBuf[pIrMiniport->m_ulSendCurPos++];
//
// Check to see if the packet has been completely transmitted.
//
if(pIrMiniport->m_ulSendCurPos == pIrMiniport->m_ulSendBufSize)
{
//
// This is to protect the transmit list and when baud
// rates are changed.
//
EnterCriticalSection( &pIrMiniport->m_ListCriticalSection);
//
// Send the packet back to the OS.
//
CompleteSentPacket
(
pIrMiniport->m_pSIRTransmitNDisPacket,
pIrMiniport->m_hNdisAdapter,
NDIS_STATUS_SUCCESS
);
//
// Really, All I need to zero out is the first item.
// Lets Zero out all the items just in case.
//
pIrMiniport->m_pSIRTransmitNDisPacket = 0;
pIrMiniport->m_ulSendCurPos = 0;
//
// Incremented the transmited packet count.
//
pIrMiniport->m_ulPacketsTx++;
DEBUGMSG(ZONE_SEND,
(TEXT("Tx: sent %d byte IR packet.\r\n"),
pIrMiniport->m_ulSendBufSize)
);
//
// We need to change the baud rate at the end of
// a frame.
//
if(pIrMiniport->m_ulNextBaudRate)
{
pIrMiniport->SetHWBaudRate( pIrMiniport->m_ulNextBaudRate);
pIrMiniport->m_fMinTATRequired = TRUE;
}
//
// Get the next SIR packet if there is one.
//
pIrMiniport->GetNextSirPacket();
//
// This is to protect the transmit list and when baud
// rates are changed.
//
LeaveCriticalSection( &pIrMiniport->m_ListCriticalSection);
}
}
//
// Check to see if we have bytes in the recieve queue.
//
while(!(*UART2_FR & FR_RXFE))
{
//
// Get the next byte.
//
ucRecievedByte = (UCHAR) *UART2_DR;
//
// Process the byte through the SIR state machine.
//
pIrMiniport->m_SirState.ProcessByte(ucRecievedByte);
//
// Check to see if we have a packet.
//
if(pIrMiniport->m_SirState.PacketAvailable())
{
//
// Fix up some packet fields.
//
NDIS_SET_PACKET_HEADER_SIZE
(
pRxBuf->pPacket,
SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE
);
//
// Process the frame
//
pIrMiniport->m_ReceivePacketList.ProcessFrame( pRxBuf );
//
// Get the next free item.
//
pRxBuf = pIrMiniport->m_ReceivePacketList.GetFree();
//
// Set the next buffer location.
//
pIrMiniport->m_SirState.SetNextBuffer(pRxBuf);
}
}
//
// Renable the UART interrupt.
//
InterruptDone(SYSINTR_UART2);
}
DEBUGMSG(ZONE_IRDAHW, (TEXT("-SIRInterruptHandler")));
return(0);
}
//****************************************************************************
// IRMiniport::GetNextSirPacket
//****************************************************************************
// Get the next SIR packet. This function must be protected by the
// Critical Section.
//
//
void IRMiniport::GetNextSirPacket()
{
PNDIS_IRDA_PACKET_INFO pIrdaInfo;
DWORD cbTatBofs;
ULONG ulTemp;
while(!m_pSIRTransmitNDisPacket)
{
//
// Get the next item on the list.
//
if(m_SendPacketList.MorePackets())
{
//
// Remove the next packet and put it into the current packet.
//
m_pSIRTransmitNDisPacket = m_SendPacketList.RemoveNextPacket();
//
// Get irda media specific info.
//
pIrdaInfo = GetIrdaPacketInfo( m_pSIRTransmitNDisPacket );
ASSERT(pIrdaInfo != NULL);
ASSERT(pIrdaInfo->MinTurnAroundTime <= MAX_TAT_usec);
//
// TAT BOFS.
//
if ((m_fMinTATRequired == TRUE) &&
(pIrdaInfo->MinTurnAroundTime > 0))
{
// BitsPerSecond uSecDelay
// TAT = ------------- * --------------
// BitsPerChar uSecPerSecond
cbTatBofs = (GetCurrentBaudRate() * pIrdaInfo->MinTurnAroundTime)/8000000;
m_fMinTATRequired = FALSE;
}
else
{
cbTatBofs = 0;
}
//
// Need to convert NdisPacket to an IR packet.
//
if (!NdisToIrPacket(
m_pSIRTransmitNDisPacket,
cbTatBofs,
m_pSendBuf,
&m_ulSendBufSize))
{
//
// Complete the packet with a failure.
//
CompleteSentPacket
(
m_pSIRTransmitNDisPacket,
m_hNdisAdapter,
NDIS_STATUS_FAILURE
);
//
// Increment the packets dropped count.
//
m_ulPacketsTxDropped++;
DEBUGMSG(ZONE_WARN,
(TEXT("Tx:Packets dropped = %d\r\n"),
m_ulPacketsTxDropped)
);
//
// Really, All I need to zero out is the first item.
// Lets Zero out all the items just in case.
//
m_pSIRTransmitNDisPacket = 0;
m_ulSendCurPos = 0;
}
else
{
//
// Enable the interrupt for transmitting.
//
*UART2_CR |= CR_TIE;
//ulTemp = *UART2_CR;
//*UART2_CR = (ulTemp & ~CR_RIE) | CR_TIE;
//ulTemp = *IRDA_IRCON;
//*IRDA_IRCON = (ulTemp *~IRCON_RXE) | IRCON_TXE;
}
}
else
{
//
// We are switching from sending to recieving
// packets.
//
// Set Flag to send out BOFs packets for timing purposes.
//
m_fMinTATRequired = TRUE;
//
// Disable the interrupt for transmitting.
//
*UART2_CR &= ~CR_TIE;
break;
//ulTemp = *UART2_CR;
//*UART2_CR = (ulTemp & ~CR_TIE) | CR_RIE;
//ulTemp = *IRDA_IRCON;
//*IRDA_IRCON = (ulTemp *~IRCON_TXE) | IRCON_RXE;
}
}
}
//****************************************************************************
// CompleteSentPacket
//****************************************************************************
// This completes a sent packet.
//
//
void CompleteSentPacket
(
PNDIS_PACKET pNdisPacket,
NDIS_HANDLE hNdisAdapter,
NDIS_STATUS status
)
{
DEBUGMSG(ZONE_SEND, (TEXT("+CompleteSentPacket")));
NDIS_HANDLE hSwitchToMiniport;
BOOL fSwitchSuccessful;
//
// Need to give the NDIS packet back to the protocol.
// Since this is an intermediate miniport, we must call
// NdisIMSwitchToMiniport to grab the NDIS miniport lock.
//
fSwitchSuccessful = NdisIMSwitchToMiniport
(
hNdisAdapter,
&hSwitchToMiniport
);
if (fSwitchSuccessful == FALSE)
{
// WinCE's NdisIMSwitchToMiniport should not fail.
ASSERT(FALSE);
}
//
// Indicate ownership of packet along with status of send.
//
NdisMSendComplete
(
hNdisAdapter,
pNdisPacket,
status
);
NdisIMRevertBack
(
hNdisAdapter,
hSwitchToMiniport
);
DEBUGMSG(ZONE_SEND, (TEXT("-CompleteSentPacket")));
}
#if 0
#define IRDA_GPIO_A_DATA_REG 0x80840000 // GPIO A Data port.
#define IRDA_GPIO_A_DATA_TYPE_IR 1
#define IRDA_GPIO_A_DATA_DIR_REG 0x80840008
#define IRDA_GPIO_A_DATA_REG_OUT 0x1
#define IRDA_GPIO_LOCK_REG 0x80840120
#define IRDA_GPIO_LOCK_KEY 0xaa
//****************************************************************************
// InitIrdaGPIO
//****************************************************************************
//
// Notice: This may be board specific. Also the GPIO bits should be a seprate
// driver to prevent contention!
//
// The TFDS6501E does not power on with a default mode, therefore the data
// transfer rate has to be set by a pro-gramming sequence using the Txd and
// SD/ Mode inputs as described below or selected by setting the Mode Pin.
// The Mode Pin can be used to statically set the mode
// (Mode Pin: LOW: SIR, HIGH: 0.576 Mbit/s to 4.0 Mbit/s). When using the Mode
// Pin, the standby current may increase to about 50 to 60 A when high
// or low. If not used or in standby mode, the mode input should float to
// minimize standby current. The low frequency mode covers speeds up to
// 115.2 kbit/s. Signals with higher data rates should be detected in the
// high frequency mode. Lower frequency data can also be received in the
// high frequency mode but with reduced sensitivity. To switch the transceivers
// from low frequency mode to the high frequency mode and vice versa,
// the programming sequences described below are required.
//
void InitIrdaGPIO(void)
{
unsigned int ulPortDirection;
//
// Make port output. Set output bit to a "1".
// Lock bit. The LOCK bit is set to one when this register is written
// with a value of 0xAA. The lock bit is cleared by any access to the
// GPIO address space. When the LOCK bit is one, the GPIO direction
// register are unlocked for write access. The write operation to the
// direction registers will clear the LOCK bit.
//
ulPortDirection = *((unsigned int *)IRDA_GPIO_A_DATA_DIR_REG);
ulPortDirection |= IRDA_GPIO_A_DATA_REG_OUT;
*((unsigned int *)IRDA_GPIO_LOCK_REG) = IRDA_GPIO_LOCK_KEY;
*((unsigned int *)IRDA_GPIO_A_DATA_DIR_REG) = ulPortDirection;
}
//****************************************************************************
//
//****************************************************************************
//
//
//
//
//
// Synopsis: Init GPIO registers for the IRDA interface.
void Set_IrDA_With_GPIO(unsigned int value)
{
if(value)
*((unsigned int *)IRDA_GPIO_A_DATA_REG) |= 0x000000001;
else
*((unsigned int *)IRDA_GPIO_A_DATA_REG) &= 0x0FFFFFFFE;
// GPIO Port A data register. GPIO Port A corresponds to EGPIO[7:0] pins.
// bit 0 = 1
}
#endif // 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -