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

📄 ax88796end.c

📁 操作系统vxworks
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* 5. place the ENE in LOOPBACK mode 1 or 2 */

    SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB0);

    /* 6. initialize Receive Buffer Ring */

    SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, AX88796_PSTART);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, AX88796_PSTART);
    SYS_IN_CHAR (pDrvCtrl, ENE_RSTART, &pStart);
    
    logMsg("pStart = %x\n", pStart, 2, 3, 4, 5, 6);
    
    SYS_OUT_CHAR (pDrvCtrl, ENE_RSTOP, AX88796_PSTOP);
    SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND, AX88796_PSTART);

    /* 7. clear Interrupt Status Register */

    SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, (char)0xff);

    /* 8. initialize Interrupt Mask Register */

    pDrvCtrl->imask = 0;
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

    /* 9. program Command Register for page 1 */

    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE1 | CMD_STOP);

    /* i) initialize physical address registers */

    SYS_OUT_CHAR (pDrvCtrl, ENE_STA0, pDrvCtrl->enetAddr[0]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_STA1, pDrvCtrl->enetAddr[1]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_STA2, pDrvCtrl->enetAddr[2]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_STA3, pDrvCtrl->enetAddr[3]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_STA4, pDrvCtrl->enetAddr[4]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_STA5, pDrvCtrl->enetAddr[5]);

    logMsg ("enet addr %02x:%02x:%02x:%02x:%02x:%02x\n",
		pDrvCtrl->enetAddr[0] & 0xff,
		pDrvCtrl->enetAddr[1] & 0xff,
		pDrvCtrl->enetAddr[2] & 0xff,
		pDrvCtrl->enetAddr[3] & 0xff,
		pDrvCtrl->enetAddr[4] & 0xff,
		pDrvCtrl->enetAddr[5] & 0xff);

    /* ii) initialize multicast address registers */

    ax88796AddrFilterSet (pDrvCtrl);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR0, pDrvCtrl->mcastFilter[0]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR1, pDrvCtrl->mcastFilter[1]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR2, pDrvCtrl->mcastFilter[2]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR3, pDrvCtrl->mcastFilter[3]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR4, pDrvCtrl->mcastFilter[4]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR5, pDrvCtrl->mcastFilter[5]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR6, pDrvCtrl->mcastFilter[6]);
    SYS_OUT_CHAR (pDrvCtrl, ENE_MAR7, pDrvCtrl->mcastFilter[7]);


#ifdef DEBUG
   ENDLOGMSG ((("Setting multicast addresses to:\n"),1,2,3,4,5,6));
    sprintf(buf, "enet mcast %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
	    pDrvCtrl->mcastFilter[0] & 0xff,
	    pDrvCtrl->mcastFilter[1] & 0xff,
	    pDrvCtrl->mcastFilter[2] & 0xff,
	    pDrvCtrl->mcastFilter[3] & 0xff,
	    pDrvCtrl->mcastFilter[4] & 0xff,
	    pDrvCtrl->mcastFilter[5] & 0xff,
	    pDrvCtrl->mcastFilter[6] & 0xff,
	    pDrvCtrl->mcastFilter[7] & 0xff);
    ENDLOGMSG (((buf),1,2,3,4,5,6));
#endif /* DEBUG */

    /* iii) initialize current page pointer */

    SYS_OUT_CHAR (pDrvCtrl, ENE_CURR, AX88796_PSTART + 1);
    pDrvCtrl->nextPacket = AX88796_PSTART + 1;

    /* 10. put the ENE in START mode */

    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);

    /* 11. initialize Transmit Configuration Register */

    SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_FDU | TCON_NORMAL);

    ENDLOGMSG (("ax88796Config: done\n", 0, 0, 0, 0, 0, 0));

    pDrvCtrl->imask = ((pDrvCtrl->flags & END_POLLING) ? 0 : AX88796_ALL_INTS);

    /* Only actually enable interrupts if not polling */
    if (intEnable)
	SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
    }

/*******************************************************************************
*
* ax88796OverwriteRecover - recover from receive buffer ring overflow
*
* This procedure is mandated by National Semiconductor as the only safe
* way to recover from an Overwrite Warning Error.  The first two steps
* of their procedure, reading the Command Register and stopping the NIC,
* were accomplished in the interrupt handler.  The rest occurs here.
*
* This routine is scheduled to run in the net task since it must delay
* to allow the STOP command to take effect.
*/

LOCAL void ax88796OverwriteRecover
    (
    AX88796END_DEVICE  *pDrvCtrl,
    UCHAR cmdStatus
    )
    {
    UCHAR stat;
    BOOL  reSend;

    logMsg ("ax88796OverwriteRecover: enter (flags=%x, imask=%x)\n",
		pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0);

    /* We shouldn't get here without the OVERWRITE flags set */
    if (!(pDrvCtrl->flags & END_OVERWRITE2))
	{
	logMsg ("ax88796OverwriteRecover: bad flags\n",
		    0,0,0,0,0,0);
#ifdef DEBUG
	SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
	taskSuspend (0);
#else
	return;
#endif
	}

    /* 1. read the TXP bit in the command register (already in cmdStatus) */

    /* 2. issue the STOP command (done in the interrupt handler) */

    /* 3. delay at least 1.6 milliseconds (1/625 second) */

    taskDelay ((sysClkRateGet() + 624)/ 625);

    /* we are now supposedly sure the NIC is stopped */

    /* 4. clear Remote Byte Count Register */

    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00);

    /* 5. read the stored value of the TXP bit (in cmdStatus) */

    if ((cmdStatus & CMD_TXP) == 0)
        reSend = FALSE;
    else
        {
	SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat);
        if ((stat & (ISTAT_PTX | ISTAT_TXE)) == 0)
	    {
	    /* transmit was in progress but probably deferring */
            reSend = TRUE;
	    }
        else
	    {
            /* transmit was completed (probably), don't repeat it */
            reSend = FALSE;
	    }
        }

    /* 6. place the NIC in loopback mode */

    SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_FDU | TCON_LB0);

    /* 7. issue the START command to the NIC */

    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);

    /* 8. remove one or more packets from the receive buffer ring */

    /* clear overwrite flag */
    pDrvCtrl->flags &= ~END_OVERWRITE;
    pDrvCtrl->current = ax88796GetCurr (pDrvCtrl);
    
    ax88796OverWiteRcvInt (pDrvCtrl);
    
    /* 9. reset the overwrite warning bit in the ISR */

    /* reset all active interrupt conditions */

    SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat);
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, stat);

    /* 10. take the NIC out of loopback */

    SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, 0x00);

    /* 10a. re-enable all device interrupts */

    pDrvCtrl->imask = AX88796_ALL_INTS;
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

    /* 11. if need to resend, do so, otherwise if anything queued, send that */

    pDrvCtrl->flags &= ~END_OVERWRITE2;
    if (reSend)
        SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP);
    else
	muxTxRestart (&pDrvCtrl->endObj);
    }

/*******************************************************************************
*
* ax88796Int - handle controller interrupt (for MPC8XX)
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/

LOCAL void ax88796Int
    (
    AX88796END_DEVICE  *pDrvCtrl
    )
    {
    UCHAR val;
    UCHAR intStat;
    UCHAR txStat;
    UCHAR rxStat;
    
    pDrvCtrl->stats.interrupts++;
    
    *SIPEND(vxImmrIsbGet()) = SIPEND_IRQ0>>(pDrvCtrl->ivec);

    /* Read status and Acknowlegde interrupt */

    SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &intStat);
    intStat &= pDrvCtrl->imask;
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, intStat);

    /* Get TX and RX status */

    SYS_IN_CHAR (pDrvCtrl, ENE_TSTAT, &txStat);
    SYS_IN_CHAR (pDrvCtrl, ENE_RSTAT, &rxStat);

    ENDLOGMSG (("ax88796Int: intStat=%02x imask=%02x txStat=%02x rxStat=%02x\n",
		intStat, pDrvCtrl->imask, txStat, rxStat, 0, 0));

    /* Update count registers */
    SYS_IN_CHAR (pDrvCtrl, ENE_COLCNT, &val);
    pDrvCtrl->stats.collisions += val;
    SYS_IN_CHAR (pDrvCtrl, ENE_ALICNT, &val);
    pDrvCtrl->stats.aligns += val;
    SYS_IN_CHAR (pDrvCtrl, ENE_CRCCNT, &val);
    pDrvCtrl->stats.crcs += val;
    SYS_IN_CHAR (pDrvCtrl, ENE_MPCNT, &val);
    pDrvCtrl->stats.missed += val;
    
    /*
     * enable interrupts, clear receive and/or transmit interrupts, and clear
     * any errors that may be set.
     */

    /* Check for errors */

    if (intStat & ISTAT_OVW) /* Overwrite */
        {
	UCHAR cmdStat;

	END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
	if (!(pDrvCtrl->flags & END_OVERWRITE2))
	    {
	    pDrvCtrl->flags |= (END_OVERWRITE | END_OVERWRITE2);
	    pDrvCtrl->lastError.errCode = END_ERR_WARN;
	    pDrvCtrl->lastError.pMesg = "Overwrite";
	    netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
		       (int) &pDrvCtrl->lastError,
		       0, 0, 0);
	    pDrvCtrl->stats.overwrite++;
	    SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
	    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
	    ENDLOGMSG (("ax88796Int: overwrite detected\n",
			0, 0, 0, 0, 0, 0));
	    netJobAdd ((FUNCPTR) ax88796OverwriteRecover, (int) pDrvCtrl,
			      cmdStat, 0, 0, 0);
	    }
	/* no further interrupt processing */
	pDrvCtrl->imask = 0;
	SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
	return;
        }

    /* Receive handling */

    if (intStat & ISTAT_RXE) /* Receive-error */
        {
	if (!pDrvCtrl->lastIntError)
	    {
	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
	    pDrvCtrl->lastError.errCode = END_ERR_WARN;
	    pDrvCtrl->lastError.pMesg = "receive error";
	    netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
		       (int) &pDrvCtrl->lastError,
		       0, 0, 0);
	    }
	++pDrvCtrl->lastIntError;
        pDrvCtrl->stats.rerror++;
        if (rxStat & RSTAT_OVER)
            pDrvCtrl->stats.overruns++;
        if (rxStat & RSTAT_DIS)
            pDrvCtrl->stats.disabled++;
        if (rxStat & RSTAT_DFR)
            pDrvCtrl->stats.deferring++;
        }
    if (intStat & ISTAT_TXE)    /* Transmit error-packet not sent */
        {
	if (!pDrvCtrl->lastIntError)
	    {
	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS,  +1);
	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
	    pDrvCtrl->lastError.errCode = END_ERR_WARN;
	    pDrvCtrl->lastError.pMesg = "transmit error";
	    netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
		       (int) &pDrvCtrl->lastError,
		       0, 0, 0);
	    }
	++pDrvCtrl->lastIntError;
        pDrvCtrl->stats.terror++;
        if (txStat & TSTAT_ABORT)
            {
            pDrvCtrl->stats.aborts++;
            pDrvCtrl->stats.collisions += 16;
            }
        if (txStat & TSTAT_UNDER)
            pDrvCtrl->stats.underruns++;
        }

    /* Transmit handling */

    if (intStat & ISTAT_PTX)    /* Transmit-packet sent */
        {
	END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
        if (txStat & TSTAT_CDH)
            pDrvCtrl->stats.heartbeats++;
        if (txStat & TSTAT_OWC)
            pDrvCtrl->stats.outofwindow++;
        if (txStat & TSTAT_PTX)
            pDrvCtrl->stats.tnoerror++;
        }

    /* Check for lack of errors */
    if (!(intStat & (ISTAT_RXE | ISTAT_TXE)))
	pDrvCtrl->lastIntError = 0;

    /* Have netTask handle any input packets */

    if (intStat & ISTAT_PRX)
        {
        pDrvCtrl->current = ax88796GetCurr (pDrvCtrl);
	ENDLOGMSG(("ax88796Int: input packet (flags=%x, current=%x)\n",
		   pDrvCtrl->flags, pDrvCtrl->current, 0, 0, 0, 0));
        if (!(pDrvCtrl->flags & END_RECV_HANDLING_FLAG))
            {
	    /* Disable RX int */
	    pDrvCtrl->imask &= ~IM_PRXE;
	    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

            pDrvCtrl->flags |= END_RECV_HANDLING_FLAG;
            (void)netJobAdd ((FUNCPTR)ax88796HandleRcvInt, (int)pDrvCtrl,
                              0,0,0,0);
            }
        }

    /* Check for transmit complete */

    if ((intStat & (ISTAT_TXE | ISTAT_PTX)) != 0)
	{
	pDrvCtrl->flags &= ~END_TX_IN_PROGRESS;
	ENDLOGMSG (("ax88796Int: Tx complete, blocked=%d\n",
		    (pDrvCtrl->flags & END_TX_BLOCKED) ? 1 : 0,0,0,0,0,0));
	if (pDrvCtrl->flags & END_TX_BLOCKED)
	    {
	    /* Disable TX ints */
	    pDrvCtrl->imask &= ~(IM_TXEE | IM_PTXE);
	    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

	    pDrvCtrl->flags &= ~END_TX_BLOCKED;
	    netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj,
		       0, 0, 0, 0);
	    }
	}
	
    /* Flush the write pipe */

    CACHE_PIPE_FLUSH ();
    }


/*******************************************************************************
*
* ax88796HandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* RETURNS: N/A.
*/

LOCAL void ax88796HandleRcvInt
    (
    AX88796END_DEVICE *pDrvCtrl
    )
    {
    int oldLevel;
    char *pBuf;

    /* END_RECV_HANDLING_FLAG set by ISR */

    ENDLOGMSG (("ax88796HandleRcvInt(%x): enter (flags=%x)\n",
		pDrvCtrl,pDrvCtrl->flags,0,0,0,0));
    pBuf = NULL;
    while (pDrvCtrl->flags & END_RECV_HANDLING_FLAG)
	{
	int	len;
	CL_BLK_ID	pClBlk;
	M_BLK_ID	pMblk;      /* MBLK to send upstream */

	ENDLOGMSG (("ax88796HandleRcvInt: flags=%x imask=%x cur=%x next=%x\n",
		    pDrvCtrl->flags, pDrvCtrl->imask,
		    pDrvCtrl->current, pDrvCtrl->nextPacket,
		    0, 0));
	/* check if all packets removed */
	if (pDrvCtrl->nextPacket == pDrvCtrl->current)
	    break;

	/* Break out if we get an overwrite condition */
	if (pDrvCtrl->flags & END_OVERWRITE)
	    break;

	/* Allocate an MBLK, and a replacement buffer */
	if (!pBuf)
	    {
	    pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool,
				  pDrvCtrl->clPoolId);
	    if (!pBuf)
		{
		ENDLOGMSG (("ax88796HandleRcvInt: Out of clusters!\n",
			    0, 0, 0, 0, 0, 0));
		break;
		}
	    }
	/* Read packet in offset so IP header is long-aligned */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -