📄 lan8xx.c
字号:
NrBDs++;
if (--TxFreeBDs == 0)
{
/*-------------------------------------------------------------*/
/* If we are using the last BD. */
/*-------------------------------------------------------------*/
if (m->b_cont)
{
/*---------------------------------------------------------*/
/* If there are more buffers after the current one, we */
/* must copy the remaining buffers to a single buffer. */
/* Set length to the size of the current mblk and all the */
/* ones linked after it. */
/*---------------------------------------------------------*/
length = size - FrameLength + 14;
tmp = Ni_funcs.allocb(length, 0);
if (tmp == NULL)
{
Postponed++;
/*-----------------------------------------------------*/
/* If the buffer could not be allocated, clean-up all */
/* the used BDs. This prevents the interrupt clean-up */
/* code from failing. */
/*-----------------------------------------------------*/
TxNewPtr = FirstBdPtr;
TxFreeBDs += NrBDs;
for (; NrBDs > 0; NrBDs--)
{
TxNewPtr->status = 0;
TxNewPtr->address = 0;
IncTxBDptr(TxNewPtr);
}
/*-----------------------------------------------------*/
/* Then queue the frame for later transmission and */
/* return. */
/*-----------------------------------------------------*/
TxNewPtr = FirstBdPtr;
if (TxhOutHead == NULL)
{
TxhOutHead = TxhPtr;
TxhOutTail = TxhPtr;
}
else
{
/*-------------------------------------------------*/
/* The only reason we get here is that the frame */
/* handed down in the call was put at the tail of */
/* the queue. So this block must be the head. Put */
/* it back at the head of the queue to preserve */
/* the order of transmission. */
/*-------------------------------------------------*/
TxhPtr->next = TxhOutHead;
TxhOutHead = TxhPtr;
}
splx(old_level);
return;
}
else
{
CopyFallBack++;
CopiedBytes += length;
/*-----------------------------------------------------*/
/* Walk the original chain and copy data into new */
/* buffer. */
/*-----------------------------------------------------*/
m_prev->b_cont = tmp;
m_prev = m;
while(m != (mblk_t *)0)
{
copy_size = m->b_wptr - m->b_rptr;
src = m->b_rptr;
for (i=0; i<copy_size; i++)
*tmp->b_wptr++ = *src++;
CopiedBuffers++;
m = m->b_cont;
}
Ni_funcs.freemsg(m_prev); /* Free it, (we copied the data) */
tmp->b_cont = NULL;
}
/*---------------------------------------------------------*/
/* Check if the total frame length is less than 64. If so */
/* adjust the last buffer size to bring the frame size up */
/* to 64 bytes. This is for a bug in the 68360. */
/*---------------------------------------------------------*/
FrameLength += length;
if (FrameLength < 64)
length += (64 - FrameLength);
TxNewPtr->address = tmp->b_rptr;
TxNewPtr->length = length;
PrevBdPtr = TxNewPtr;
IncTxBDptr(TxNewPtr);
break; /* This is the last so skip the last two assigns */
}
else
{
/*---------------------------------------------------------*/
/* Last BD and last mblk. Easy case. */
/*---------------------------------------------------------*/
FrameLength += length;
if (FrameLength < 64)
length += (64 - FrameLength);
TxNewPtr->address = m->b_rptr;
TxNewPtr->length = length;
PrevBdPtr = TxNewPtr;
IncTxBDptr(TxNewPtr);
break; /* This is the last so skip the last two assigns */
}
}/* if (--TxFreeBDs == 0) */
else
{
/*-------------------------------------------------------------*/
/* Not the last BD. No need to collapse the Tx. */
/*-------------------------------------------------------------*/
FrameLength += length;
if (m->b_cont)
{
/*---------------------------------------------------------*/
/* Still more on the list after this. Just stuff the BD. */
/*---------------------------------------------------------*/
TxNewPtr->address = m->b_rptr;
TxNewPtr->length = length;
PrevBdPtr = TxNewPtr;
if (TxNewPtr == TxLastBdPtr)
TxNewPtr->status = (USHORT)WRAP | FULL | PAD | TX_CRC;
else
TxNewPtr->status = FULL | PAD | TX_CRC;
IncTxBDptr(TxNewPtr);
}
else
{
/*---------------------------------------------------------*/
/* Last mblk. Stuff the BD and mark as the last. */
/* Compensate for 68360 bug for frames less than 64 bytes. */
/*---------------------------------------------------------*/
if (FrameLength < 64)
length += (64 - FrameLength);
TxNewPtr->address = m->b_rptr;
TxNewPtr->length = length;
PrevBdPtr = TxNewPtr;
IncTxBDptr(TxNewPtr);
break; /* This is the last so skip the last two assigns */
}
}/* if (--TxFreeBDs == 0);else */
m_prev = m;
m = m->b_cont;
}
/*---------------------------------------------------------------------*/
/* pNA+ will sometimes hand down trailing zero length mblks. This */
/* code will take care of that. */
/*---------------------------------------------------------------------*/
if (PrevBdPtr == TxLastBdPtr)
PrevBdPtr->status = (USHORT)WRAP | FULL | PAD | TX_CRC |
LOG_EVENT | LAST_IN_FRAME;
else
PrevBdPtr->status = FULL | PAD | TX_CRC |
LOG_EVENT | LAST_IN_FRAME;
/*---------------------------------------------------------------------*/
/* Update record of total bytes sent. */
/*---------------------------------------------------------------------*/
MG_stat.outoctets += FrameLength + 4;
/*---------------------------------------------------------------------*/
/* Turn on the "FULL" bit in the first buffer descriptor. This */
/* tells the CPM that it can transmit this frame. Also set the */
/* "Transmit on Demand" register so that the CPM starts sending */
/* right away. */
/*---------------------------------------------------------------------*/
FirstBdPtr->status |= (USHORT) FULL;
E_SCC1TmtOnDemandReg = (USHORT) 0x8000;
splx(old_level);
/*---------------------------------------------------------------------*/
/* If there are queued frames and there are now at least 3 BDs */
/* available, try to added the next frame to the BD pool. */
/*---------------------------------------------------------------------*/
if (TxhOutHead && (TxFreeBDs > 2))
FillTxBDs();
}
/***********************************************************************/
/* ni_isr: Acknowledge interrupts and check if any packets have */
/* arrived or are waiting to be sent out. */
/* */
/* RETURNS: 1 if pSOS is running, 0 if pSOS not yet initialized. */
/* */
/***********************************************************************/
static UINT ni_isr(void)
{
ULONG i,j,OldLevel;
BuffDescType *FirstBdPtr;
/* BuffDescType *LastBdPtr; --del by szg */
BuffDescType *PrevBdPtr;
USHORT Events;
TX_HDR *TxhPtr;
Events = E_SCC1EventReg;
E_SCC1EventReg = Events;
/*---------------------------------------------------------------------*/
/* If a receive overflow occurred, there must be packets to process. */
/*---------------------------------------------------------------------*/
if (Events & BUSY_OVERFLOW)
{
ReceivePackets();
}
/*---------------------------------------------------------------------*/
/* Respond to receive interrupts. */
/*---------------------------------------------------------------------*/
if (Events & (GOT_COMPLETE_FRAME | GOT_PARTIAL_FRAME))
{
ReceivePackets();
}
/*---------------------------------------------------------------------*/
/* If there have been transmit errors, restart the transmitter. */
/*---------------------------------------------------------------------*/
if (Events & TX_ERROR)
{
OldLevel = splx(MAX_ILEV);
/*-----------------------------------------------------------------*/
/* If we get here, the SCC has an error xmitting a buffer. The */
/* TBPTR is pointing to the NEXT buffer that will be xmitted. We */
/* get at TBPTR via the macro TxBdPtr(). We want to clean out the */
/* frame that gave us the error, set the SCC to the next place to */
/* start sending, and restart the xmitter. This is somewhat comp- */
/* licated in that messages may be spread across multiple BD's and */
/* we must clean out the message not just the BD that had the error*/
/*-----------------------------------------------------------------*/
FirstBdPtr =
(BuffDescType *)((char *)E_BuffDescr + TxBdPtr(E_SCC1_BASE));
/* LastBdPtr = FirstBdPtr + NrTxBds - 1; --del by szg, err */
/*-----------------------------------------------------------------*/
/* check for a boundary condition */
/*-----------------------------------------------------------------*/
PrevBdPtr = (FirstBdPtr == TxFirstBdPtr) ? TxLastBdPtr : FirstBdPtr - 1;
/*-----------------------------------------------------------------*/
/* Now we want to discard the errored frame. There are two cases */
/* to deal with: */
/* 1. The error happened in the last buffer of the previous */
/* frame then the FULL bit in each of the buffers in the */
/* frame has been cleared by the SCC. */
/* 2. If the error occured in the current frame, we need to */
/* clear the FULL bits in the remaining buffers and reset */
/* the SCC's TBPTR to the next frame to send. */
/*-----------------------------------------------------------------*/
if (PrevBdPtr->status & LAST_IN_FRAME)
{
/*-------------------------------------------------------------*/
/* Easy case, reclaim the buffers and restart the xmitter */
/*-------------------------------------------------------------*/
if (PrevBdPtr->status & CARRIER_LOST)
{
/*---------------------------------------------------------*/
/* If carrier loss happened transmitter is still running. */
/* So there is no need to restart it. */
/*---------------------------------------------------------*/
ReclaimTxFrames();
}
else
{
ReclaimTxFrames();
while (E_CP_CommandReg & SEMAPHORE_FLAG);
E_CP_CommandReg = RESTART_TX + SCC1_CH_NUM + SEMAPHORE_FLAG;
while (E_CP_CommandReg & SEMAPHORE_FLAG);
}
}
else
{
/*-------------------------------------------------------------*/
/* Clear out all FULL bits up to the first non-full or LAST */
/* frame is found. If all goes o/k, we land up pointing to the */
/* LAST BD in the frame. */
/*-------------------------------------------------------------*/
for (i=0;
(i < NrTxBds) &&
((FirstBdPtr->status & FULL)) &&
(!(FirstBdPtr->status & LAST_IN_FRAME)); i++)
{
FirstBdPtr->status &= ~FULL;
IncTxBDptr(FirstBdPtr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -