📄 ne2000end.c
字号:
{
UCHAR rxFilter; /* receiver configuration */
#ifdef DEBUG
static buf [256];
#endif
ENDLOGMSG (("ne2000Config: enter (intEnable=%d)\n",
intEnable, 0, 0, 0, 0, 0));
/* Disable device interrupts */
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
/* Set up address filter for multicasting. */
if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
ne2000AddrFilterSet (pDrvCtrl);
/* preserve END_POLLING and OVERWRITE flags */
pDrvCtrl->flags &= (END_POLLING | END_OVERWRITE | END_OVERWRITE2);
/* 1. program Command Register for page 0 and for no DMA */
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
/* 2. initialize Data Configuration Register:
* 16-bit bus, burst mode, 8-deep FIFO.
* or
* 8-bit bus, burst mode, 8-deep FIFO.
*/
if (pDrvCtrl->byteAccess)
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS_8
| DCON_LOOPBK_OFF);
else
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS16
| DCON_LOOPBK_OFF);
SYS_ENET_ADDR_GET (pDrvCtrl);
/* 3. clear Remote Byte Count Register */
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00);
/* 4. initialize Receive Configuration Register */
/* Always accept broadcast packets. */
rxFilter = RCON_BROAD;
/* Set multicast mode if it's asked for. */
if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
{
rxFilter |= RCON_GROUP;
}
ENDLOGMSG (("\tMulticast mode %s\n",
(rxFilter & RCON_GROUP) ? "on" : "off",
0, 0, 0, 0, 0));
/* Set promiscuous mode if it's asked for. */
if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_PROMISC)
{
rxFilter |= RCON_PROM;
}
ENDLOGMSG (("\tPromiscuous mode %s\n",
(rxFilter & RCON_PROM) ? "on" : "off",
0, 0, 0, 0, 0));
ENDLOGMSG (("\tsetting rxFilter = 0x%x\n", rxFilter,2,3,4,5,6));
SYS_OUT_CHAR (pDrvCtrl, ENE_RCON, rxFilter);
/* 5. place the ENE in LOOPBACK mode 1 or 2 */
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1);
/* 6. initialize Receive Buffer Ring */
SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, NE2000_PSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSTOP, NE2000_PSTOP);
SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND, NE2000_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]);
ENDLOGMSG (("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 */
ne2000AddrFilterSet (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, NE2000_PSTART + 1);
pDrvCtrl->nextPacket = NE2000_PSTART + 1;
/* set memory parameters */
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE2 | CMD_STOP);
/*
* HELP: DP 83905 manual says thas ENE_ENH is address counter lower,
* ENE_BLOCK is address counter upper. not wait states, or anything
* else. What is with these comments?
*/
SYS_OUT_CHAR (pDrvCtrl, ENE_ENH, 0x00); /* 0 wait states */
SYS_OUT_CHAR (pDrvCtrl, ENE_BLOCK, 0x00); /* 0x00xxxx */
/* 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_NORMAL);
ENDLOGMSG (("ne2000Config: done\n", 0, 0, 0, 0, 0, 0));
pDrvCtrl->imask = ((pDrvCtrl->flags & END_POLLING) ? 0 : NE2000_ALL_INTS);
/* Only actually enable interrupts if not polling */
if (intEnable)
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
}
/*******************************************************************************
*
* ne2000OverwriteRecover - 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 ne2000OverwriteRecover
(
NE2000END_DEVICE *pDrvCtrl,
UCHAR cmdStatus
)
{
UCHAR stat;
BOOL reSend;
ENDLOGMSG (("ne2000OverwriteRecover: 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))
{
ENDLOGMSG (("ne2000OverwriteRecover: 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_LB1);
/* 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 = ne2000GetCurr (pDrvCtrl);
ne2000HandleRcvInt (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 = NE2000_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);
ENDLOGMSG (("ne2000OverwriteRecover: done (flags=%x, imask=%x)\n",
pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0));
}
/*******************************************************************************
*
* ne2000Int - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/
LOCAL void ne2000Int
(
NE2000END_DEVICE *pDrvCtrl
)
{
UCHAR val;
UCHAR intStat;
UCHAR txStat;
UCHAR rxStat;
pDrvCtrl->stats.interrupts++;
/* 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 (("ne2000Int: 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_COLCNT, &cmdStat);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
ENDLOGMSG (("ne2000Int: overwrite detected\n",
0, 0, 0, 0, 0, 0));
netJobAdd ((FUNCPTR) ne2000OverwriteRecover, (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 = ne2000GetCurr (pDrvCtrl);
ENDLOGMSG(("ne2000Int: input packet (flags=%x, current=%d)\n",
pDrvCtrl->flags, pDrvCtrl->current, 0, 0, 0, 0));
if (!(pDrvCtrl->flags & END_RECV_HANDLING_FLAG))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -