📄 dec21x4xend.c
字号:
msb = crc >> 31; crc <<= 1; if (msb ^ (eAddrByte & 0x1)) { crc ^= DEC_CRC_POLY; crc |= 0x1; } eAddrByte >>= 1; } } /* * return the upper 9 bits of the CRC in a decreasing order of * significance. * crc <31..23> as index <0..8> */ index = 0; for (bit=0; bit<9; bit++) index |= ((crc >> (31-bit)) & 0x1) << bit; return index; }/********************************************************************************* dec21x4xIASetup - set up physical and multicast addresses** This routine sets up a filter frame to filter the physical addresses* and all the current multicast addresses.** While the first call to this routine during chip initialization requires* that the receiver be turned off, subsequent calls do not.* * RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS dec21x4xIASetup ( DRV_CTRL * pDrvCtrl /* pointer to device control structure */ ) { UINT8 ethBcastAdrs[]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; UINT8 * pFltrFrm; UINT8 * pAdrs; ETHER_MULTI * pMCastNode; DEC_TD * pTxD; ULONG csr7Val; char * pBuf; int index; int timeout; DRV_LOG (DRV_DEBUG_IOCTL, "IASetup\n", 0, 0, 0, 0, 0, 0); /* gain exclusive access to transmitter */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* get a free transmit descriptor */ pTxD = dec21x4xTxDGet (pDrvCtrl); if (pTxD == NULL) { END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (ERROR); } /* get a buffer */ pBuf = NET_BUF_ALLOC(); if (pBuf == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "netClusterGet failed\n", 0, 0, 0, 0, 0, 0); END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (ERROR); } /* align the frame */ pFltrFrm = (UINT8 *) (((int)pBuf + 0x3) & ~0x3); /* clear all entries */ memset (pFltrFrm, 0, FLTR_FRM_SIZE); /* install multicast addresses */ for (pMCastNode = END_MULTI_LST_FIRST (&pDrvCtrl->endObj); pMCastNode != NULL; pMCastNode = END_MULTI_LST_NEXT (pMCastNode)) { index = dec21x4xHashIndex (pMCastNode->addr); pFltrFrm [DEC_FLT_INDEX(index/8)] |= 1 << (index % 8); } /* install an ethernet broadcast address */ index = dec21x4xHashIndex (ethBcastAdrs); pFltrFrm [DEC_FLT_INDEX(index/8)] |= 1 << (index % 8); /* install the physical address */ pAdrs = (UINT8 *)END_HADDR (&pDrvCtrl->endObj); for (index=0; index<6; index++) pFltrFrm [FLTR_FRM_PHY_ADRS_OFF + DEC_FLT_INDEX(index)] = pAdrs[index]; /* transmit the frame */ pTxD->tDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pFltrFrm)); pTxD->tDesc3 = 0; /* frame type is SETUP, filtering mode is HASH + 1 perfect */ pTxD->tDesc1 |= PCISWAP (TDESC1_SET | TDESC1_FT0); pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK); pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(FLTR_FRM_SIZE)); pTxD->tDesc1 &= PCISWAP (~(TDESC1_LS|TDESC1_FS)); pTxD->tDesc0 = PCISWAP(TDESC0_OWN); /* ready for transmit */ /* Flush the write pipe */ CACHE_PIPE_FLUSH(); /* Advance our management index */ pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds; /* mask interrupts */ csr7Val = DEC_CSR_READ (CSR7); DEC_CSR_WRITE (CSR7, 0); /* start tx */ if (DRV_FLAGS_ISSET(DEC_TX_KICKSTART)) DEC_CSR_WRITE (CSR1, CSR1_TPD); /* wait for completion */ timeout=0xffffff; while (timeout && (pTxD->tDesc0 != (~PCISWAP (TDESC0_OWN)))) timeout--; /* restore TXD bits */ pTxD->tDesc0 = 0; pTxD->tDesc1 &= PCISWAP (~(TDESC1_SET | TDESC1_FT0)); pTxD->tDesc1 |= PCISWAP (TDESC1_LS | TDESC1_FS); pTxD->tDesc2 = 0; /* restore interrupts */ DEC_CSR_WRITE (CSR7, csr7Val); /* free the buffer */ NET_BUF_FREE (pBuf); /* release exclusive access */ END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* return success */ return (OK); }/********************************************************************************* dec21x4xMCastAddrAdd - add a multicast address** This routine adds a multicast address to whatever the driver* is already listening for.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS dec21x4xMCastAddrAdd ( DRV_CTRL * pDrvCtrl, char * pAddr ) { int retVal; DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrAdd\n", 0, 0, 0, 0, 0, 0); /* add a multicast address to the list */ retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr); /* reconfigure the device */ if (retVal == ENETRESET) return dec21x4xIASetup (pDrvCtrl); return ((retVal == OK) ? OK : ERROR); }/********************************************************************************* dec21x4xMCastAddrDel - remove a multicast address** This routine deletes a multicast address from the current list of* multicast addresses.** RETURNS: OK on success and ERROR otherwise.*/LOCAL STATUS dec21x4xMCastAddrDel ( DRV_CTRL * pDrvCtrl, char * pAddr ) { int retVal; DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrDel\n", 0, 0, 0, 0, 0, 0); /* remove a multicast address from the list */ retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr); /* reconfigure the device */ if (retVal == ENETRESET) return dec21x4xIASetup (pDrvCtrl); return ((retVal == OK) ? OK : ERROR); }/********************************************************************************* dec21x4xMCastAddrGet - retreive current multicast address list** This routine returns the current multicast address list in <pTable>** RETURNS: OK on success; otherwise ERROR.*/LOCAL STATUS dec21x4xMCastAddrGet ( DRV_CTRL * pDrvCtrl, MULTI_TABLE * pTable ) { DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrGet\n", 0, 0, 0, 0, 0, 0); return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable)); }/********************************************************************************* dec21x4xSend - transmit an ethernet packet** This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine.** muxSend() calls this routine each time it wants to send a packet.* Errors are detected at interrupt level.** RETURNS: OK on success; and ERROR otherwise.*/LOCAL STATUS dec21x4xSend ( DRV_CTRL * pDrvCtrl, M_BLK * pMblk ) { DEC_TD * pTxD; char * pBuf; int len; int s; DRV_LOG (DRV_DEBUG_TX, "S:%#x ", pDrvCtrl->txIndex, 0, 0, 0, 0, 0);#if 0 if (pDrvCtrl->txBlocked) return (END_ERR_BLOCK); /* transmitter not ready */#endif /* Gain exclusive access to transmit */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* Get the next TXD */ pTxD = dec21x4xTxDGet (pDrvCtrl); pBuf = NET_BUF_ALLOC(); if ((pTxD == NULL) || (pBuf == NULL)) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_TX_SEM_GIVE (&pDrvCtrl->endObj); if (pBuf) NET_BUF_FREE (pBuf); if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked) dec21x4xTxRingClean (pDrvCtrl); s = intLock(); pDrvCtrl->txBlocked = TRUE; /* transmitter not ready */ intUnlock(s); return (END_ERR_BLOCK); /* just return without freeing mBlk chain */ } /* copy and free the MBLK */ len = netMblkToBufCopy (pMblk, pBuf, NULL); /* setup the transmit buffer pointers */ NET_MBLK_CHAIN_FREE (pMblk); /* setup the transmit buffer pointers */ pTxD->tDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf)); pTxD->tDesc3 = 0; /* setup frame len */ pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK); pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(len)); /* transfer ownership to device */ pTxD->tDesc0 = PCISWAP(TDESC0_OWN); /* Flush the write pipe */ CACHE_PIPE_FLUSH(); /* Save the buf info */ pDrvCtrl->freeBuf[pDrvCtrl->txIndex].pClBuf = pBuf; /* Advance our management index */ pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds; /* start tx */ if (DRV_FLAGS_ISSET(DEC_TX_KICKSTART)) DEC_CSR_WRITE (CSR1, CSR1_TPD); END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* update statistics */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); return (OK); }/********************************************************************************* dec21x4xRecv - pass a received frame to the upper layer** This routine processes an input frame, then passes it up to the higher* level in a form it expects. Buffer loaning, promiscuous mode are all* supported. Trailer protocols is not supported.** RETURNS: OK, always.*/LOCAL STATUS dec21x4xRecv ( DRV_CTRL * pDrvCtrl, DEC_RD * pRxD ) { END_OBJ * pEndObj = &pDrvCtrl->endObj; M_BLK_ID pMblk; /* MBLK to send upstream */ CL_BLK_ID pClBlk; /* pointer to clBlk */ char * pBuf; /* A replacement buffer for the current RxD */ char * pData; /* Data pointer for the current RxD */ char * pTmp; int len; /* Len of the current data */ DRV_LOG (DRV_DEBUG_RX, "R", 0, 0, 0, 0, 0, 0); /* check for errors */ if (pRxD->rDesc0 & PCISWAP(RDESC0_ES)) { DRV_LOG (DRV_DEBUG_RX, "- ",0, 0, 0, 0, 0, 0); END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1); goto cleanRxD; } /* Allocate an MBLK, and a replacement buffer */ pMblk = NET_MBLK_ALLOC(); pBuf = NET_BUF_ALLOC(); pClBlk = NET_CL_BLK_ALLOC(); if ((pMblk == NULL) || (pBuf == NULL) || (pClBlk == NULL)) { END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1); if (pMblk) NET_MBLK_FREE (pMblk); if (pBuf) NET_BUF_FREE (pBuf); if (pClBlk) NET_CL_BLK_FREE (pClBlk); goto cleanRxD; } /* Get the data pointer and len from the current RxD */ len = DEC_FRAME_LEN_GET (PCISWAP (pRxD->rDesc0)) - ETH_CRC_LEN; pData = (char *) DEC_PCI_TO_VIRT (PCISWAP (pRxD->rDesc2)); /* * The code above solves alignment problem when the CPU and the * ethernet chip don't accept longword unaligned addresses. * * Pb: When the ethernet chip receives a packet from the network, * it needs a l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -