📄 dec21x4xend.c
字号:
LOCAL STATUS dec21x4xStart ( DRV_CTRL * pDrvCtrl ) { int retVal; UINT csr6Val=0; UINT usrFlags = pDrvCtrl->usrFlags; DRV_LOG (DRV_DEBUG_LOAD, "Start\n", 0, 0, 0, 0, 0, 0); /* Reset the device */ dec21x4xChipReset (pDrvCtrl); /* Select the media */ if (! DRV_FLAGS_ISSET (DEC_21040)) { if (_func_dec2114xMediaSelect != NULL) retVal = (* _func_dec2114xMediaSelect) (pDrvCtrl, &csr6Val); else if (DRV_FLAGS_ISSET (DEC_21140)) retVal = dec21140MediaSelect (pDrvCtrl, &csr6Val); else retVal = dec21143MediaSelect (pDrvCtrl, &csr6Val); if (retVal == ERROR) return (ERROR); if (csr6Val & CSR6_2114X_PS) { DEC_CSR_UPDATE (CSR6, CSR6_2114X_PS); dec21x4xChipReset (pDrvCtrl); csr6Val |= CSR6_2114X_HBD; } csr6Val &= DEC_USR_CSR6_MSK; csr6Val |= CSR6_2114X_MB1; /* decode CSR6 specific options from userFlags */ if (usrFlags & DEC_USR_SF) csr6Val |= CSR6_2114X_SF; if (usrFlags & DEC_USR_THR_MSK) csr6Val |= (usrFlags & DEC_USR_THR_MSK) >> DEC_USR_THR_SHF; if (usrFlags & DEC_USR_SB) csr6Val |= CSR6_SB; if (usrFlags & DEC_USR_PB) csr6Val |= CSR6_PB; if (usrFlags & DEC_USR_SC) csr6Val |= CSR6_2114X_SC; if (usrFlags & DEC_USR_CA) csr6Val |= CSR6_CAE; } else dec21040AuiTpInit (pDrvCtrl); /* Write start of receive ring */ DEC_CSR_WRITE (CSR3, DEC_VIRT_TO_PCI(pDrvCtrl->rxRing)); /* Write start of transmit ring */ DEC_CSR_WRITE (CSR4, DEC_VIRT_TO_PCI(pDrvCtrl->txRing)); /* clear the status register */ DEC_CSR_WRITE (CSR5, 0xffffffff); /* setup CSR6 - start transmitter */ DEC_CSR_WRITE (CSR6, csr6Val | CSR6_ST); /* setup ethernet address and filtering mode */ dec21x4xIASetup (pDrvCtrl); /* set operating mode and start the receiver */ dec21x4xModeSet (pDrvCtrl); /* set up the interrupts */ DEC_CSR_WRITE (CSR7, (CSR7_NIM | /* normal interrupt mask */ CSR7_RIM | /* rcv interrupt mask */ CSR7_TIM | /* xmit interrupt mask */ CSR7_TUM | /* xmit buff unavailble mask */ CSR7_AIM | /* abnormal interrupt mask */ CSR7_SEM | /* system error mask */ CSR7_RUM )); /* rcv buff unavailable mask */ if (! DRV_FLAGS_ISSET (DEC_21140)) DEC_CSR_UPDATE (CSR7, CSR7_21X4X_LFM); /* link fail mask */ /* Connect the interrupt handler */ SYS_INT_CONNECT (pDrvCtrl, dec21x4xInt, pDrvCtrl, &retVal); if (retVal == ERROR) return (ERROR); pDrvCtrl->txBlocked = FALSE; /* mark the interface -- up */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* Enable LAN interrupts */ SYS_INT_ENABLE (pDrvCtrl); return (OK); }/********************************************************************************* dec21x4xStop - stop the device** This routine marks the interface as down and resets the device. This* includes disabling interrupts, stopping the transmitter and receiver.** The complement of this routine is dec21x4xStart. Once a unit is* stop in this routine, it may be re-initialized to a running state by* dec21x4xStart.** RETURNS: OK or ERROR*/LOCAL STATUS dec21x4xStop ( DRV_CTRL * pDrvCtrl ) { int retVal=OK; DRV_LOG (DRV_DEBUG_LOAD, "Stop\n", 0, 0, 0, 0, 0, 0); /* mark the interface down */ END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING); /* Reset the device */ dec21x4xChipReset (pDrvCtrl); /* Disable LAN interrupts */ SYS_INT_DISABLE (pDrvCtrl); /* disconnect interrupt */ SYS_INT_DISCONNECT (pDrvCtrl, dec21x4xInt, (int)pDrvCtrl, &retVal); return (retVal); }/********************************************************************************* dec21x4xRestart - restart the device** Restarts the device after cleaning up the transmit and receive queues. This* routine should be called only after dec21x4xStop().** RETURNS: OK or ERROR*/LOCAL void dec21x4xRestart ( DRV_CTRL * pDrvCtrl ) { DEC_TD * pTxD = pDrvCtrl->txRing; FREE_BUF * pFreeBuf = pDrvCtrl->freeBuf; int count; LOG_MSG ("%s%d - restarting device.\n", (int) DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); /* cleanup the tx and rx queues */ dec21x4xTxRingClean (pDrvCtrl); dec21x4xRxIntHandle (pDrvCtrl); /* drop rest of the queued tx packets */ for (count = pDrvCtrl->numTds; count; count--, pTxD++, pFreeBuf++) { if (pFreeBuf->pClBuf != NULL) { NET_BUF_FREE(pFreeBuf->pClBuf); pFreeBuf->pClBuf = NULL; } DEC_CACHE_INVALIDATE (pTxD, TD_SIZ); if (pTxD->tDesc1 & PCISWAP(TDESC1_SET)) { pTxD->tDesc1 &= PCISWAP(~(TDESC1_SET | TDESC1_FT0)); pTxD->tDesc0 = 0; } else if (pTxD->tDesc0 & PCISWAP(TDESC0_OWN|TDESC0_ES)) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1); pTxD->tDesc0 = 0; } } /* Reset indices */ pDrvCtrl->rxIndex=0; pDrvCtrl->txIndex=0; pDrvCtrl->txDiIndex=0; /* Restart the device */ dec21x4xStart (pDrvCtrl); }/********************************************************************************* dec21x4xIoctl - interface ioctl procedure** Process an interface ioctl request.** This routine implements the network interface control functions.* It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS, EIOCMULTIADD,* EIOCMULTIDEL, EIOCMULTIGET, EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 commands.** RETURNS: OK if successful, otherwise EINVAL.*/LOCAL int dec21x4xIoctl ( DRV_CTRL * pDrvCtrl, int cmd, caddr_t data ) { int error=0; long value; int savedFlags; END_OBJ * pEndObj=&pDrvCtrl->endObj; DRV_LOG (DRV_DEBUG_IOCTL, "Ioctl unit=%#x cmd=%d data=%#x\n", pDrvCtrl->unit, cmd, (int)data, 0, 0, 0); switch (cmd) { case EIOCSADDR: if (data == NULL) error = EINVAL; else { /* Copy and install the new address */ memcpy ((char *)END_HADDR(pEndObj), (char *)data, END_HADDR_LEN(pEndObj)); dec21x4xIASetup (pDrvCtrl); } break; case EIOCGADDR: /* HELP: move to mux */ if (data == NULL) error = EINVAL; else memcpy ((char *)data, (char *)END_HADDR(pEndObj), END_HADDR_LEN(pEndObj));#ifdef DRV_DEBUG { char *cp = (char *)data; DRV_LOG (DRV_DEBUG_IOCTL, "EIOCGADDR: %x:%x:%x:%x:%x:%x\n", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); }#endif /*DRV_DEBUG*/ break; case EIOCSFLAGS: value = (long) data; if (value < 0) { value = -value; value--; END_FLAGS_CLR (pEndObj, value); } else END_FLAGS_SET (pEndObj, value); /* handle IIF_PROMISC and IFF_ALLMULTI */ savedFlags = DRV_FLAGS_GET(); if (END_FLAGS_ISSET (pEndObj, IFF_PROMISC)) DRV_FLAGS_SET (DEC_PROMISC); else DRV_FLAGS_CLR (DEC_PROMISC); if (END_FLAGS_GET (pEndObj) & (IFF_ALLMULTI | IFF_MULTICAST)) DRV_FLAGS_SET (DEC_MCAST); else DRV_FLAGS_CLR (DEC_MCAST); DRV_LOG (DRV_DEBUG_IOCTL, "endFlags=%#x savedFlags=%#x newFlags=%#x\n", END_FLAGS_GET(pEndObj), savedFlags, DRV_FLAGS_GET(), 0, 0, 0); if ((DRV_FLAGS_GET() != savedFlags) && (END_FLAGS_GET(pEndObj) & IFF_UP)) dec21x4xModeSet (pDrvCtrl); break; case EIOCGFLAGS: /* move to mux */ DRV_LOG (DRV_DEBUG_IOCTL, "EIOCGFLAGS: 0x%x: 0x%x\n", pEndObj->flags, *(long *)data, 0, 0, 0, 0); if (data == NULL) error = EINVAL; else *(long *)data = END_FLAGS_GET(pEndObj); break; case EIOCMULTIADD: /* move to mux */ error = dec21x4xMCastAddrAdd (pDrvCtrl, (char *)data); break; case EIOCMULTIDEL: /* move to mux */ error = dec21x4xMCastAddrDel (pDrvCtrl, (char *)data); break; case EIOCMULTIGET: /* move to mux */ error = dec21x4xMCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data); break; case EIOCPOLLSTART: /* move to mux */ dec21x4xPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: /* move to mux */ dec21x4xPollStop (pDrvCtrl); break; case EIOCGMIB2: /* move to mux */ if (data == NULL) error=EINVAL; else memcpy((char *)data, (char *)&pEndObj->mib2Tbl, sizeof(pEndObj->mib2Tbl)); break; default: error = EINVAL; } return (error); }/********************************************************************************* dec21x4xModeSet - promiscuous & multicast operation and start receiver** This routine enables promiscuous and multicast mode if corresponding flags * are set and starts the receiver.** RETURNS: N/A*/LOCAL void dec21x4xModeSet ( DRV_CTRL * pDrvCtrl ) { int opMode = CSR6_SR; /* start receiver */ DRV_LOG (DRV_DEBUG_IOCTL, "ModeSet\n", 0, 0, 0, 0, 0, 0); if (DRV_FLAGS_ISSET (DEC_MCAST)) opMode |= CSR6_PM; /* rx multicast */ if (DRV_FLAGS_ISSET (DEC_PROMISC)) opMode |= CSR6_PR; /* rx promiscuous */ DEC_CSR_WRITE (CSR6, (DEC_CSR_READ (CSR6) & ~(CSR6_PM|CSR6_PR)) | opMode); return; }/********************************************************************************* dec21x4xHashIndex - compute the hash index for an ethernet address** This routine provides the hash index for an given ethernet address. The bit* position in the hash table is taken from the CRC32 checksum derived from* the first 6 bytes.** RETURNS: hash index for an ethernet address.*/LOCAL int dec21x4xHashIndex ( char * eAddr ) { UINT8 eAddrByte; int index; /* hash index - return value */ int byte; /* loop - counter */ int bit; /* loop - counter */ UINT crc = 0xffffffff; UINT8 msb; for (byte=0; byte<6; byte++) { eAddrByte = eAddr[byte]; for (bit=0; bit<8; bit++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -