📄 lan8xx.c
字号:
}
if (FirstBdPtr->status & LAST_IN_FRAME)
{
/*---------------------------------------------------------*/
/* We should always get here since every frame does have a */
/* buffer with the LAST bit set. */
/* 1. Mark last frame as !FULL so ReclaimFrames will work */
/* correctly. */
/* 2. Increment to the next buffer. This is the next one */
/* for the SCC to process. */
/* 3. Set the offset to this next frame in TBPTR */
/* 4. Restart the Xmitter. */
/*---------------------------------------------------------*/
FirstBdPtr->status &= ~FULL;
IncTxBDptr(FirstBdPtr);
/*---------------------------------------------------------*/
/* Set TBPTR */
/*---------------------------------------------------------*/
TxBdPtr(E_SCC1_BASE) = (ULONG)FirstBdPtr - (ULONG)E_BuffDescr;
ReclaimTxFrames();
while (E_CP_CommandReg & SEMAPHORE_FLAG);
E_CP_CommandReg = RESTART_TX + SCC1_CH_NUM + SEMAPHORE_FLAG;
while (E_CP_CommandReg & SEMAPHORE_FLAG);
}
else
{
/*---------------------------------------------------------*/
/* Hopefully this does not happen. The code is left here */
/* to deal with anything completely unexpected. The only */
/* solution here is to completely reset the TX BD list. */
/* It's brutal but it will unhang the xmitter. */
/*---------------------------------------------------------*/
CleanUpTx();
}
}
splx(OldLevel);
}
/*---------------------------------------------------------------------*/
/* If frames were sent out, refill empty transmit buffer descriptors. */
/*---------------------------------------------------------------------*/
if (Events & BUFFER_SENT)
{
FillTxBDs();
}
return pSOS_Is_Up;
}
/***********************************************************************/
/* ReceivePackets: Process all received packets. */
/* */
/***********************************************************************/
static void ReceivePackets(void)
{
USHORT length, good, type;
RX_BUFF *ep;
mblk_t *m;
frtn_t frtn;
ULONG OldLevel;
USHORT status;
long index;
for (;;)
{
OldLevel = splx(MAX_ILEV);
/*-----------------------------------------------------------------*/
/* Stop when we hit a buffer with no data, or a BD w/ no buffer */
/*-----------------------------------------------------------------*/
if ((RxNewPtr->status & EMPTY) || (RxNewPtr->address == NULL))
{
splx(OldLevel);
break;
}
/*-----------------------------------------------------------------*/
/* Per packet initialization. */
/*-----------------------------------------------------------------*/
length = RxNewPtr->length - 18;
status = RxNewPtr->status;
ep = RxNewPtr->address;
type = ep->type;
good = TRUE;
/*-----------------------------------------------------------------*/
/* Remove this buffer from the BD ring by clearing the BD's */
/* address field and advancing the BD ptr to the next buffer. */
/* Then reenable interrupts. */
/*-----------------------------------------------------------------*/
RxNewPtr->address = NULL;
if (RxNewPtr >= RxLastBdPtr)
RxNewPtr = RxFirstBdPtr;
else
RxNewPtr++;
splx(OldLevel);
/*-----------------------------------------------------------------*/
/* Determine if this packet is okay. */
/*-----------------------------------------------------------------*/
if ((status & (CRC_ERROR | OVERRUN | COLLISION)) || (length > 1500))
good = FALSE;
#if ((BSP_LAN1_FLAGS) & (IFF_MULTICAST))
/*-------------------------------------------------------------*/
/* The MC68360 uses a hash table of 64 bits to filter out */
/* multicast addresses. Unwanted multicast packets may be */
/* received as a result. If the received packet is a multicast */
/* packet, verify that it is in the table before passing it up */
/* the protocol stack. It's better to reject unwanted packets */
/* as soon as possible. */
/* */
/* Setting the BSP_LAN1_FLAGS so that the IFF_MULTICAST bit is */
/* reset and re-compiling will remove all multicast address */
/* code from the BSP. If multicast addressing is desired, but */
/* filtering out multicast addresses in the driver is not */
/* desired simply comment out the if statement and recompile. */
/* As the number of different multicast addresses in the table */
/* and on the network increases there is a greater chance that */
/* unwanted packets will be received. If the number of */
/* addresses wanted is small and known not to collide with */
/* multicast addresses in use on the network then this if */
/* statement can be removed to shorten the time spent in the */
/* ISR. */
/* */
/* If the address is multicast and there is a multicast table */
/* defined, do the filtering. */
/*-------------------------------------------------------------*/
if (ep->daddr.byte[0] & 1)
{
for (index = 0; index < 6; index++)
if (((unsigned char)ep->daddr.byte[index]) != 0xFF)
break;
/*---------------------------------------------------------*/
/* If the destination is not the broadcast address and it */
/* is not in the multicast table, return it and get the */
/* next packet. */
/*---------------------------------------------------------*/
if (index < 6)
{
if (lan_mcast.mc_addr)
{
OldLevel = splx(MAX_ILEV);
index =
lan_lookup_mcast((UCHAR *)&ep->daddr.byte[0]);
splx(OldLevel);
if (index < 0)
{
ReturnBuffer(ep);
continue;
}
}
else
{
ReturnBuffer(ep);
continue;
}
}
}
#endif
/*-----------------------------------------------------------------*/
/* Collect stats for MIB on broadcast and unicast packets. */
/*-----------------------------------------------------------------*/
if (ep->daddr.byte[0] & 1)
MG_stat.innucastpkts++;
else
MG_stat.inucastpkts++;
/*-----------------------------------------------------------------*/
/* If the packet is acceptable, pass it to pNA+. Otherwise, count */
/* the receive error and return envelope to the free queue. */
/*-----------------------------------------------------------------*/
if (good)
{
MG_stat.inoctets += length + 18;
frtn.free_arg = (void *)ep;
frtn.free_func = (void (*)())ReturnBuffer;
if (Announce && (m = Ni_funcs.esballoc((UCHAR *)ep->buffer,
length, 0, &frtn)))
{
m->b_wptr += length;
pSOS_Is_Up = (*Announce)(type, (char *)m, length, If_Num,
(char *)(&ep->saddr), (char *)(&ep->daddr));
}
else
ReturnBuffer(ep);
}
else
{
inerrors++;
ReturnBuffer(ep);
}
}
/*---------------------------------------------------------------------*/
/* Replenish the receive ring's supply of receive buffers. */
/*---------------------------------------------------------------------*/
AssignRxBuffers();
}
/***********************************************************************/
/* FillTxBDs: Move outgoing packets from the outgoing queue to */
/* the transmit buffer descriptor ring, if possible. */
/* */
/* NOTE: This includes a workaround for the padding problem */
/* on the 68360 */
/***********************************************************************/
static void FillTxBDs(void)
{
ULONG old_level;
USHORT FrameLength;
TX_HDR *TxhPtr;
mblk_t *m, *tmp, *m_prev;
BuffDescType *FirstBdPtr;
BuffDescType *PrevBdPtr=NULL;
UINT NrBDs;
int i, copy_size, length;
UCHAR *src;
old_level = splx(MAX_ILEV);
/*---------------------------------------------------------------------*/
/* Free up some BDs if possible. */
/*---------------------------------------------------------------------*/
ReclaimTxFrames();
for (;;)
{
/*-----------------------------------------------------------------*/
/* If there are no outgoing messages queued, or if there are not */
/* enough descriptors available for the first queued frame, we */
/* can't do anything. */
/*-----------------------------------------------------------------*/
if ((TxhOutHead == NULL) || (TxFreeBDs < 3))
break;
/*-----------------------------------------------------------------*/
/* Extract the top message. If queue is left empty, assign NULL */
/* to the queue tail as well as to the queue head. */
/*-----------------------------------------------------------------*/
TxhPtr = TxhOutHead;
TxhOutHead = TxhOutHead->next;
if (TxhOutHead == NULL)
TxhOutTail = NULL;
/*-----------------------------------------------------------------*/
/* Put the transmit header into the descriptor ring. Note that */
/* we save a pointer to this first buffer descriptor, and we don't */
/* set the "FULL" bit for this first buffer descriptor yet. After */
/* all of the other buffer descriptors for this frame are set up, */
/* we will turn on the "FULL" bit in this descriptor. That way */
/* we prevent the CPM from transmitting the frame before we have */
/* all of the descriptors in place. */
/*-----------------------------------------------------------------*/
FirstBdPtr = TxNewPtr;
/*-----------------------------------------------------------------*/
/* Add the transmit header to the BD list. */
/*-----------------------------------------------------------------*/
TxNewPtr->address = TxhPtr;
TxNewPtr->length = 14;
if (TxNewPtr == TxLastBdPtr)
TxNewPtr->status = (USHORT)WRAP | PAD | TX_CRC;
else
TxNewPtr->status = PAD | TX_CRC;
IncTxBDptr(TxNewPtr);
TxFreeBDs--;
FrameLength = 14;
NrBDs = 1;
/*-----------------------------------------------------------------*/
/* Now put the buffers pointed to by the message block triplet in. */
/*-----------------------------------------------------------------*/
m = TxhPtr->msg_ptr;
m_prev = m;
while (m)
{
/*-------------------------------------------------------------*/
/* Skip all zero length elements in the mblk list, since */
/* adding a buffer of length zero to the BD pool is bad. Free */
/* the zero length element and "close" the hole in the chain. */
/*-------------------------------------------------------------*/
length = m->b_wptr - m->b_r
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -