📄 dec21140.c
字号:
intRESTORE_IEN(ien);
/*-------------------------------------------------------------------*/
/* If buffers were attached, issue receive poll demand. */
/*-------------------------------------------------------------------*/
if (attachFlag)
ioLongWrite(CSR2, 1);
}
/***********************************************************************/
/* RxBufRcv: Process all received packets */
/* */
/***********************************************************************/
static void RxBufRcv(void)
{
LAN_RX_BUF *pktAddr;
mblk_t *msgBlk;
frtn_t frtn;
ULONG dataLen, good, status;
USHORT type;
Bool ien;
for (;;)
{
/*-----------------------------------------------------------------*/
/* Disable Interrupts */
/*-----------------------------------------------------------------*/
ien = intCLEAR_IEN();
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
INVALIDATE((void *)RxNextBD, 1);
/*-----------------------------------------------------------------*/
/* Stop when we hit a descriptor owned by the MAC, or a descriptor */
/* with a NULL buffer pointer. */
/*-----------------------------------------------------------------*/
if ((RxNextBD->status & MAC_OWNS_DESC)
|| (RxNextBD->buffAddr1 == NULL))
{
intRESTORE_IEN(ien);
break;
}
/*-----------------------------------------------------------------*/
/* Per packet initialization. */
/*-----------------------------------------------------------------*/
status = RxNextBD->status;
dataLen = ((status & LAN_RCVD_FL) >> LAN_RCVD_FLOFF) - 18;
pktAddr = RxNextBD->buffAddr1;
good = TRUE;
/*-----------------------------------------------------------------*/
/* Clear buffer address, advance RxNextBD, reenable interrupts. */
/*-----------------------------------------------------------------*/
RxNextBD->buffAddr1 = NULL;
RxNextBD = RxNextBD->nextDesc;
intRESTORE_IEN(ien);
/*-----------------------------------------------------------------*/
/* Verify received length is legal. */
/*-----------------------------------------------------------------*/
if (dataLen > 1500)
{
dataLen = 1500;
good = FALSE;
}
/*-----------------------------------------------------------------*/
/* Cache invalidate the received buffer.
/*-----------------------------------------------------------------*/
_cache_invalidate((void *)pktAddr, dataLen + 14);
/*-----------------------------------------------------------------*/
/* Determine if packet is okay. Expect to recieve entire packet */
/* in one descriptor so first descriptor and last descriptor bits */
/* must be set. If so, check for other errors. */
/*-----------------------------------------------------------------*/
if (RdPciCfg16(CF_STATUS) & (LAN_DS_PER | LAN_DS_SERR | LAN_DS_MA |
LAN_DS_RTA | LAN_DS_STA | LAN_DS_DPAR))
{
WrPciCfg16(CF_STATUS, LAN_DS_PER | LAN_DS_SERR | LAN_DS_MA |
LAN_DS_RTA | LAN_DS_STA | LAN_DS_DPAR);
good = FALSE;
}
if (((status & LAN_RCVD_FS) == 0) ||
((status & LAN_RCVD_LS) == 0) ||
((status & (LAN_RCVD_ES | LAN_RCVD_DB | LAN_RCVD_RJ)) != 0))
{
good = FALSE;
}
/*-----------------------------------------------------------------*/
/* Update count of packets received with unknown protocol. */
/*-----------------------------------------------------------------*/
type = ntohs(pktAddr->type);
if ((type != LAN_IP) && (type != LAN_ARP) && (type != LAN_RARP))
++InUnknownProtos;
/*-----------------------------------------------------------------*/
/* Collect stats for MIB on broadcast and unicast packets. */
/*-----------------------------------------------------------------*/
if ((pktAddr->daddr.word1 == 0xFFFF) &&
(pktAddr->daddr.word2 == 0xFFFF) &&
(pktAddr->daddr.word3 == 0xFFFF))
++innucastpkts;
else
++InUcastPkts;
/*-----------------------------------------------------------------*/
/* If the packet is acceptable, pass it to pNA+. Otherwise, count */
/* the receive error and return envelope to the free queue. */
/*-----------------------------------------------------------------*/
if (good == TRUE)
{
InOctets += dataLen + 18;
frtn.free_arg = (void *) pktAddr;
frtn.free_func = (void (*)()) RxBufDetach;
/*------------------------------------------------------------------*/
/* Announce packet to pNA if able to create a message block. */
/* */
/* NB: the following magic is because both the dec21140 and */
/* pna require longword alignment of their recieve buffers; */
/* after stripping the 14 byte header, the rest of the message */
/* would become unaligned, and therefore the message is shifted */
/* over the type field. */
/* However, this practice results in copying of all data that */
/* comes in over Ethernet, something we should do without. */
/* Fixing this requires correcting all places in pNA where */
/* longword alignment of incoming packets is assumed. */
/*------------------------------------------------------------------*/
memmove(&pktAddr->type, &pktAddr->data, dataLen);
msgBlk = NiFuncs.esballoc((void *)&pktAddr->type, dataLen, 0, &frtn);
if (msgBlk)
{
msgBlk->b_wptr += dataLen;
Announce(type, msgBlk, dataLen, IfNum);
}
else
RxBufDetach(pktAddr);
}
else
{
++InErrors;
RxBufDetach(pktAddr);
}
}
/*-------------------------------------------------------------------*/
/* Replenish receive descriptor ring's supply of receive buffers. */
/*-------------------------------------------------------------------*/
RxBufAttach();
}
/***********************************************************************/
/* TxBufAttach: Fill transmit descriptor */
/* */
/* INPUTS: addr = address of buffer 1 */
/* len = length of buffer 1 */
/* ctrl = control bits for the descriptor */
/* status = status word for descriptor */
/* */
/* NOTE: Must be called with interrupts disabled */
/* */
/***********************************************************************/
static void TxBufAttach(void *addr, int len, ULONG ctrl, ULONG status)
{
/*-------------------------------------------------------------------*/
/* Flush buffer contents from cache. */
/*-------------------------------------------------------------------*/
_cache_copyback(addr, len);
/*-------------------------------------------------------------------*/
/* Prepare descriptor and flush contents from cache. */
/*-------------------------------------------------------------------*/
TxNewBD->buffAddr1 = addr;
TxNewBD->ctrlNsize = LAN_XMTD_TCH | ctrl | len;
TxNewBD->status = status;
COPYBACK((void *)TxNewBD, 1);
/*-------------------------------------------------------------------*/
/* Advance transmit descriptor and decrement free descriptor count. */
/*-------------------------------------------------------------------*/
TxNewBD = TxNewBD->nextDesc;
--TxFreeDesc;
}
/***********************************************************************/
/* TxBufDetach: Reclaim transmit frames that have been transmitted */
/* */
/* OUTPUTS: TxUsedBD is updated */
/* */
/* NOTES: TxUsedBD points to first buffer descriptor of next frame */
/* to be reclaimed. */
/* */
/***********************************************************************/
static void TxBufDetach(void)
{
LAN_BUFF_DESC *last_in_frame;
LAN_TX_HDR *tx_hdr;
int i;
Bool ien;
ien = intCLEAR_IEN();
for (;;)
{
/*-----------------------------------------------------------------*/
/* If an ISR came and reclaimed everything already get out! */
/*-----------------------------------------------------------------*/
if ((TxUsedBD == TxNewBD) && (TxFreeDesc == TxNumDesc))
break;
/*-----------------------------------------------------------------*/
/* Find last descriptor used for frame begun at TxUsedBD. */
/*-----------------------------------------------------------------*/
last_in_frame = TxUsedBD;
INVALIDATE((void *)last_in_frame, 1);
while ((last_in_frame->ctrlNsize & LAN_XMTD_LS) == 0)
{
last_in_frame = last_in_frame->nextDesc;
INVALIDATE((void *)last_in_frame, 1);
}
/*-----------------------------------------------------------------*/
/* If the last buffer in the current frame has not been sent, we */
/* cannot reclaim the buffers and should exit the loop. */
/*-----------------------------------------------------------------*/
if (last_in_frame->status & MAC_OWNS_DESC)
break;
/*-----------------------------------------------------------------*/
/* If an outbound buffer had an error, update MIB statics. */
/*-----------------------------------------------------------------*/
if (last_in_frame->status & LAN_XMTD_ES)
{
++outerrors;
/*---------------------------------------------------------------*/
/* If a late collision occurs this could be a sign of problems */
/* display an error message. */
/*---------------------------------------------------------------*/
if (last_in_frame->status & LAN_XMTD_LC)
/*Print("Late Collision: %x\n", ++lc_err); */
++lc_err;
}
/*-----------------------------------------------------------------*/
/* Frame has been sent. Set tx_hdr to the transmit header */
/* associated with the frame, and return message block triplet. */
/*-----------------------------------------------------------------*/
tx_hdr = TxUsedBD->buffAddr1;
if (tx_hdr->NoRetFlag == 0)
NiFuncs.freemsg(tx_hdr->msg_ptr);
/*-----------------------------------------------------------------*/
/* Advance TxUsedBD to next descriptor following this frame. */
/*-----------------------------------------------------------------*/
for (i = 0; i < tx_hdr->num_desc; ++i)
{
TxUsedBD->buffAddr1 = NULL;
TxUsedBD = TxUsedBD->nextDesc;
++TxFreeDesc;
}
/*-----------------------------------------------------------------*/
/* Finally, return the transmit header to the free list. */
/*-----------------------------------------------------------------*/
tx_hdr->next = TxHdrFreeHead;
TxHdrFreeHead = tx_hdr;
}
intRESTORE_IEN(ien);
}
/***********************************************************************/
/* TxBufThrowAway: Free everything in transmit buffer descriptor ring */
/* */
/***********************************************************************/
static void TxBufThrowAway(void)
{
Bool ien = intCLEAR_IEN();
while (TxFreeDesc != TxNumDesc)
{
LAN_TX_HDR *tx_hdr;
int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -