⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lan8xx.c

📁 这是单板上DPRAM的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -