📄 comm.c
字号:
case 150: val = 769; break;
case 300: val = 384; break;
case 600: val = 192; break;
case 1200: val = 96; break;
case 1800: val = 64; break;
case 2000: val = 58; break;
case 2400: val = 48; break;
case 3600: val = 32; break;
case 4800: val = 24; break;
case 7200: val = 16; break;
case 9600: val = 12; break;
case 12800: val = 9; break;
case 14400: val = 8; break;
case 19200: val = 6; break;
case 23040: val = 5; break;
case 28800: val = 4; break;
case 38400: val = 3; break;
case 57600: val = 2; break;
case 115200: val = 1; break;
default:
*pErrorCode = (ULONG)-1;
val = 0;
}
DEBUGMSG(ZONE_FIRMODE, (TEXT("LookUpValue <--\r\n")));
return val;
}
/*
*************************************************************************
* SetSpeed
*************************************************************************
*
*
*/
BOOLEAN SetSpeed(IrDevice *thisDev)
{
UINT bitsPerSec = thisDev->linkSpeedInfo->bitsPerSec;
BOOLEAN dongleSet, result = TRUE;
DBGWARN((TEXT(" **** SetSpeed(%xh, %d bps) ***************************"), thisDev->portInfo.ioBase, bitsPerSec));
DEBUGMSG(ZONE_FIRMODE, (TEXT("SetSpeed -->\r\n")));
NdisAcquireSpinLock(&thisDev->QueueLock);
if (!IsListEmpty(&thisDev->SendQueue)){
/*
* We can't set speed in the hardware while
* send packets are queued.
*/
DEBUGMSG(DBG_ERR, (TEXT("Warning: delaying set speed until all packets sent!\r\n")));
if (thisDev->SendQueue.Blink==thisDev->SendQueue.Flink)
{
// Only one. We need to change after this one.
thisDev->setSpeedAfterCurrentSendPacket = TRUE;
}
else
{
thisDev->lastPacketAtOldSpeed = CONTAINING_RECORD(thisDev->SendQueue.Blink,
NDIS_PACKET,
MiniportReserved);
}
NdisReleaseSpinLock(&thisDev->QueueLock);
DBGOUT((TEXT("delaying set-speed because send pkts queued")));
return TRUE;
}
else if (thisDev->portInfo.writePending){
thisDev->setSpeedAfterCurrentSendPacket = TRUE;
NdisReleaseSpinLock(&thisDev->QueueLock);
DBGOUT((TEXT("will set speed after current write pkt")));
return TRUE;
}
else
{
NdisReleaseSpinLock(&thisDev->QueueLock);
}
/*
* Disable interrupts while changing speed.
* (This is especially important for the ADAPTEC dongle;
* we may get interrupted while setting command mode
* between writing 0xff and reading 0xc3).
*/
SetCOMInterrupts(thisDev, FALSE);
/*
* First, set the UART's speed to 9600 baud.
* Some of the dongles need to receive their command sequences at this speed.
*/
// SetUARTSpeed(thisDev, 9600);
dongleSet = NSC_DEMO_SetSpeed(thisDev, thisDev->portInfo.ioBase, bitsPerSec, thisDev->portInfo.dongleContext);
//
// debug info.
//
thisDev->portInfo.PacketsReceived_DEBUG = 0;
if (!dongleSet){
DBGERR((TEXT("Dongle set-speed failed")));
result = FALSE;
}
/*
* Now set the speed for the COM port
*/
SetUARTSpeed(thisDev, bitsPerSec);
thisDev->currentSpeed = bitsPerSec;
#ifdef OUTMSG
RETAILMSG(1,(TEXT("%d bps\r\n"), bitsPerSec));
#endif
if(thisDev->currentSpeed > MAX_SIR_SPEED) {
SetFirMode();
} else {
SetSirMode();
}
SetCOMInterrupts(thisDev, TRUE);
DEBUGMSG(ZONE_FIRMODE, (TEXT("SetSpeed <--\r\n")));
return result;
}
/*
*************************************************************************
* DoSend
*************************************************************************
*
*
* Send an IR packet which has already been formatted with IR header
* and escape sequences.
*
* Return TRUE iff the send succeeded.
*/
BOOLEAN DoSend(IrDevice *thisDev, PNDIS_PACKET packetToSend)
{
BOOLEAN convertedPacket;
LOG(TEXT("DoSend, poll bit:"), 0);
DBGOUT((TEXT("DoSend(%xh)"), thisDev->portInfo.ioBase));
DEBUGMSG(ZONE_FIRMODE, (TEXT("DoSend -->\r\n")));
/*
* Convert the NDIS packet to an IRDA packet.
*/
convertedPacket = NdisToIrPacket(thisDev,
packetToSend,
(UCHAR *)thisDev->portInfo.writeBuf,
MAX_IRDA_DATA_SIZE,
&thisDev->portInfo.writeBufLen);
if (convertedPacket){
LOG(TEXT("Send conversion complete; bytes: "), thisDev->portInfo.writeBufLen);
DBGPRINTBUF(thisDev->portInfo.writeBuf, thisDev->portInfo.writeBufLen);
/*
* Disable interrupts while setting up the send FSM.
*/
SetCOMInterrupts(thisDev, FALSE);
/*
* Finish initializing the send FSM.
*/
thisDev->portInfo.writeBufPos = 0;
thisDev->portInfo.writePending = TRUE;
DBGOUT((TEXT("writePending = TRUE")));
thisDev->nowReceiving = FALSE;
SetCOMInterrupts(thisDev, TRUE);
/*
* Just enable transmit interrupts to start the ball rolling.
*/
LOG(TEXT("DoSend - staging complete; POLL bit:"), (UINT)(thisDev->portInfo.writeBuf[1] & (UCHAR)0x10));
}
else {
DBGERR((TEXT("Couldn't convert packet in DoSend()")));
}
DEBUGMSG(ZONE_FIRMODE, (TEXT("DoSend <--\r\n")));
return convertedPacket;
}
/*
*************************************************************************
* StepSendFSM
*************************************************************************
*
*
* Step the send fsm to send a few more bytes of an IR frame.
* Return TRUE only after an entire frame has been sent.
*
*/
BOOLEAN StepSendFSM(IrDevice *thisDev)
{
UINT i, bytesAtATime, startPos = thisDev->portInfo.writeBufPos;
UCHAR lineStatReg;
BOOLEAN result;
UINT maxLoops;
DEBUGMSG(ZONE_FIRMODE, (TEXT("StepSendFSM -->\r\n")));
/*
* Ordinarily, we want to fill the send FIFO once per interrupt.
* However, at high speeds the interrupt latency is too slow and
* we need to poll inside the ISR to send the whole packet during
* the first interrupt.
*/
if (thisDev->currentSpeed > 115200){
maxLoops = REG_TIMEOUT_LOOPS;
}
else {
maxLoops = REG_POLL_LOOPS;
}
/*
* Write databytes as long as we have them and the UART's FIFO hasn't filled up.
*/
while (thisDev->portInfo.writeBufPos < thisDev->portInfo.writeBufLen){
/*
* If this COM port has a FIFO, we'll send up to the FIFO size (16 bytes).
* Otherwise, we can only send one byte at a time.
*/
if (thisDev->portInfo.haveFIFO){
bytesAtATime = MIN(FIFO_SIZE, (thisDev->portInfo.writeBufLen - thisDev->portInfo.writeBufPos));
}
else {
bytesAtATime = 1;
}
/*
* Wait for ready-to-send.
*/
i = 0;
do {
lineStatReg = READ_REGISTER_UCHAR(pIrLSR);
} while (!(lineStatReg & LINESTAT_XMIT_HOLDING_REG_EMPTY) && (++i < maxLoops));
if (!(lineStatReg & LINESTAT_XMIT_HOLDING_REG_EMPTY)){
break;
}
/*
* Send the next byte or FIFO-volume of bytes.
*/
for (i = 0; i < bytesAtATime; i++){
WRITE_REGISTER_UCHAR(pIrTBR,
thisDev->portInfo.writeBuf[thisDev->portInfo.writeBufPos++]);
}
}
/*
* The return value will indicate whether we've sent the entire frame.
*/
if (thisDev->portInfo.writeBufPos >= thisDev->portInfo.writeBufLen){
if (thisDev->setSpeedAfterCurrentSendPacket){
/*
* We'll be changing speeds after this packet,
* so poll until the packet bytes have been completely sent out the FIFO.
* After the 16550 says that it is empty, there may still be one remaining
* byte in the FIFO, so flush it out by sending one more BOF.
*/
i = 0;
do {
lineStatReg = (UCHAR)READ_REGISTER_UCHAR(pIrLSR);
} while (!(lineStatReg & SERIAL_LSR_THRE) && (++i < REG_TIMEOUT_LOOPS));
WRITE_REGISTER_UCHAR(pIrTBR,(UCHAR)SLOW_IR_EXTRA_BOF);
i = 0;
do {
lineStatReg = (UCHAR)READ_REGISTER_UCHAR(pIrLSR);
} while (!(lineStatReg & SERIAL_LSR_THRE) && (++i < REG_TIMEOUT_LOOPS));
}
result = TRUE;
}
else {
result = FALSE;
}
RETAILMSG(0, (TEXT("StepSendFSM wrote %d bytes (%s):\r\n"), (UINT)(thisDev->portInfo.writeBufPos-startPos), (PUCHAR)(result ? "DONE" : "not done")));
DEBUGMSG(ZONE_FIRMODE, (TEXT("StepSendFSM <--\r\n")));
return result;
}
/*
*************************************************************************
* StepReceiveFSM
*************************************************************************
*
*
* Step the receive fsm to read in a piece of an IR frame;
* strip the BOFs and EOF, and eliminate escape sequences.
* Return TRUE only after an entire frame has been read in.
*
*/
BOOLEAN StepReceiveFSM(IrDevice *thisDev)
{
UINT rawBufPos, rawBytesRead;
BOOLEAN result;
UCHAR thisch;
PLIST_ENTRY pListEntry;
DBGOUT((TEXT("StepReceiveFSM(%xh)"), thisDev->portInfo.ioBase));
DEBUGMSG(ZONE_FIRMODE, (TEXT("StepReceiveFSM -->\r\n")));
/*
* Read in and process groups of incoming bytes from the FIFO.
* NOTE: We have to loop once more after getting MAX_RCV_DATA_SIZE
* bytes so that we can see the 'EOF'; hence <= and not <.
*/
while ((thisDev->portInfo.rcvState != STATE_SAW_EOF) && (thisDev->portInfo.readBufPos <= MAX_RCV_DATA_SIZE)){
if (thisDev->portInfo.rcvState == STATE_CLEANUP){
/*
* We returned a complete packet last time, but we had read some
* extra bytes, which we stored into the rawBuf after returning
* the previous complete buffer to the user.
* So instead of calling DoRcvDirect in this first execution of this loop,
* we just use these previously-read bytes.
* (This is typically only 1 or 2 bytes).
*/
rawBytesRead = thisDev->portInfo.readBufPos;
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
}
else {
rawBytesRead = DoRcvDirect(thisDev->portInfo.ioBase, thisDev->portInfo.rawBuf, FIFO_SIZE);
if (rawBytesRead == (UINT)-1){
/*
* Receive error occurred. Go back to INIT state.
*/
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
continue;
}
else if (rawBytesRead == 0){
/*
* No more receive bytes. Break out.
*/
break;
}
}
/*
* Let the receive state machine process this group of characters
* we got from the FIFO.
*
* NOTE: We have to loop once more after getting MAX_RCV_DATA_SIZE
* bytes so that we can see the 'EOF'; hence <= and not <.
*/
for (rawBufPos = 0;
((thisDev->portInfo.rcvState != STATE_SAW_EOF) &&
(rawBufPos < rawBytesRead) &&
(thisDev->portInfo.readBufPos <= MAX_RCV_DATA_SIZE));
rawBufPos++){
thisch = thisDev->portInfo.rawBuf[rawBufPos];
switch (thisDev->portInfo.rcvState){
case STATE_INIT:
switch (thisch){
case SLOW_IR_BOF:
thisDev->portInfo.rcvState = STATE_GOT_BOF;
break;
case SLOW_IR_EOF:
case SLOW_IR_ESC:
default:
/*
* This is meaningless garbage. Scan past it.
*/
break;
}
break;
case STATE_GOT_BOF:
switch (thisch){
case SLOW_IR_BOF:
break;
case SLOW_IR_EOF:
/*
* Garbage
*/
DBGERR((TEXT("EOF in absorbing-BOFs state in DoRcv")));
thisDev->portInfo.rcvState = STATE_INIT;
break;
case SLOW_IR_ESC:
/*
* Start of data.
* Our first data byte happens to be an ESC sequence.
*/
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[0] = thisch;
thisDev->portInfo.readBufPos = 1;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_ACCEPTING:
switch (thisch){
case SLOW_IR_BOF:
/*
* Meaningless garbage
*/
DBGWARN((TEXT("WARNING: BOF during accepting state in DoRcv")));
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
break;
case SLOW_IR_EOF:
if (thisDev->portInfo.readBufPos <
IR_ADDR_SIZE+IR_CONTROL_SIZE+SLOW_IR_FCS_SIZE){
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
}
else {
thisDev->portInfo.rcvState = STATE_SAW_EOF;
}
break;
case SLOW_IR_ESC:
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch;
break;
}
break;
case STATE_ESC_SEQUENCE:
switch (thisch){
case SLOW_IR_EOF:
case SLOW_IR_BOF:
case SLOW_IR_ESC:
/*
* ESC + {EOF|BOF|ESC} is an abort sequence
*/
DBGERR((TEXT("DoRcv - abort sequence; ")
TEXT("ABORTING IR PACKET: (got following ")
TEXT("packet + ESC,%xh)"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -