📄 if_dcfast.c
字号:
dcCsrWrite (devAdrs, CSR12, INIT_CSR12); dcCsrWrite (devAdrs, CSR12, SYM_MODE); if ((pDrvCtrl->dcOpMode & DC_HBE_FLAG) && (pDrvCtrl->dcOpMode != NONE)) uTemp = (uTemp & ~CSR6_TTM) | CSR6_PS; else uTemp = (uTemp & ~CSR6_TTM) | CSR6_PS | CSR6_HBD ; uTemp = uTemp | (((pDrvCtrl->dcOpMode & DC_SCRAMBLER_FLAG) && (pDrvCtrl->dcOpMode != NONE)) ? CSR6_SCR : 0) | (((pDrvCtrl->dcOpMode & DC_PCS_FLAG) && (pDrvCtrl->dcOpMode != NONE)) ? CSR6_PCS : 0); } dcCsrWrite (devAdrs, CSR6, uTemp); }/* RCP: End of DEC21140 Code Addition */ /* clear the status register */ dcCsrWrite (devAdrs, CSR5, 0xffffffff); /* set the operating mode to start Xmitter only *//* RCP: Modify this call to accomodate DEC21140 , add the Setting of Bit 25*/ dcCsrWrite (devAdrs, CSR6, (dcCsrRead (devAdrs, CSR6) | CSR6_ST | CSR6_BIT25));/* RCP: Added Loopback modes */ if ((pDrvCtrl->dcOpMode & DC_ILOOPB_FLAG) && (pDrvCtrl->dcOpMode != NONE))/* RCP: Internal loopback selected */ dcCsrWrite (devAdrs, CSR6, (dcCsrRead(devAdrs, CSR6) | CSR6_OM_ILB)); else if ((pDrvCtrl->dcOpMode & DC_ELOOPB_FLAG) && (pDrvCtrl->dcOpMode != NONE))/* RCP: External loopback selected */ dcCsrWrite (devAdrs, CSR6, (dcCsrRead(devAdrs, CSR6) | CSR6_OM_ELB)); /* Xmit a Filter Setup Frame */ dcFltrFrmXmit (pDrvCtrl, (char *) pDrvCtrl->idr.ac_enaddr, 1); /* set operating mode any additional operational mode set by user */ dcCsrWrite (devAdrs, CSR6, (dcCsrRead(devAdrs, CSR6) | CSR6_SR | /* start receiver */ (((pDrvCtrl->dcOpMode & DC_MULTICAST_FLAG) && (pDrvCtrl->dcOpMode != NONE)) ? CSR6_PM: 0) | (((pDrvCtrl->dcOpMode & DC_PROMISCUOUS_FLAG) && (pDrvCtrl->dcOpMode != NONE)) ? CSR6_PR: 0) )); /* set up the interrupts *//* RCP: Modified to accomodate DEC21140 */ if (!DEC21140(pDrvCtrl->dcOpMode)) dcCsrWrite (devAdrs, 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_LFM | /* link fail mask */ CSR7_RUM /* rcv buff unavailable mask */ ));/* RCP: Removed CSR7_LFM for DEC21140 */ else dcCsrWrite (devAdrs, 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 */ )); sysLanIntEnable (ilevel); /* enable LANCE interrupts */ pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); /* Set our flag */ pDrvCtrl->attached = TRUE; return (OK); }/********************************************************************************* dcReset - reset the interface** Mark interface as inactive & reset the chip*/LOCAL void dcReset ( int unit ) { DRV_CTRL *pDrvCtrl = & drvCtrl [unit]; pDrvCtrl->idr.ac_if.if_flags = 0; dcChipReset (pDrvCtrl); /* reset LANCE */ }/********************************************************************************* dcInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/LOCAL void dcInt ( DRV_CTRL * pDrvCtrl /* pointer to device control struct */ ) { DC_TDE * tmd; /* pointer to Xmit ring descriptor */ ULONG stat; /* status register */ ULONG devAdrs; /* device address */ devAdrs = pDrvCtrl->devAdrs; /* Read the device status register */ stat = dcCsrRead(devAdrs, CSR5); /* clear the interrupts */ dcCsrWrite(devAdrs, CSR5, stat); /* If false interrupt, return. */ if ( ! (stat & (CSR5_NIS | CSR5_AIS)) ) return; /* Check for system error */ if (stat & CSR5_SE) { ++pDrvCtrl->idr.ac_if.if_ierrors; /* restart chip on fatal error */ pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING); (void) netJobAdd ( (FUNCPTR)dcRestart, pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0 ); return; } /* Have netTask handle any input packets */ if ((stat & CSR5_RI) && (!(stat & CSR5_RPS))) { (void) netJobAdd ( (FUNCPTR)dcHandleRecvInt, (int)pDrvCtrl, 0,0,0,0 ); /* disable the Rx intr, re-enable in dcHandleRecvInt() */ dcCsrWrite(devAdrs, CSR7, (stat & ~CSR7_RIM)); } /* * Did LANCE update any of the TMD's? * If not then don't bother continuing with transmitter stuff */ if (!(stat & CSR5_TI)) return; while (pDrvCtrl->txDiIndex != pDrvCtrl->txIndex) { /* disposal has not caught up */ tmd = pDrvCtrl->txRing + pDrvCtrl->txDiIndex; /* if the buffer is still owned by LANCE, don't touch it */ DC_CACHE_INVALIDATE (tmd, TMD_SIZ); if (tmd->tDesc0 & PCISWAP(TDESC0_OWN)) break; /* now bump the tmd disposal index pointer around the ring */ pDrvCtrl->txDiIndex = (pDrvCtrl->txDiIndex + 1) % pDrvCtrl->dcNumTds; /* * TDESC0.ES is an "OR" of LC, NC, UF, EC. * here for error conditions. */ if (tmd->tDesc0 & PCISWAP(TDESC0_ES)) { pDrvCtrl->idr.ac_if.if_oerrors++; /* output error */ pDrvCtrl->idr.ac_if.if_opackets--; /* If error was due to excess collisions, bump the collision * counter. */ if (tmd->tDesc0 & PCISWAP(TDESC0_EC)) pDrvCtrl->idr.ac_if.if_collisions += 16; /* bump the collision counter if late collision */ if (tmd->tDesc0 & PCISWAP(TDESC0_LC)) pDrvCtrl->idr.ac_if.if_collisions++; /* check for no carrier */ if (tmd->tDesc0 & PCISWAP(TDESC0_NC | TDESC0_LO | TDESC0_LF)) logMsg ("dc%d: no carrier\n", pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0,0); /* Restart chip on fatal errors. * The following code handles the situation where the transmitter * shuts down due to an underflow error. This is a situation that * will occur if the DMA cannot keep up with the transmitter. * It will occur if the LANCE is being held off from DMA access * for too long or due to significant memory latency. DRAM * refresh or slow memory could influence this. Many * implementation use a dedicated LANCE buffer. This can be * static RAM to eliminate refresh conflicts; or dual-port RAM * so that the LANCE can have free run of this memory during its * DMA transfers. */ if (tmd->tDesc0 & PCISWAP(TDESC0_UF)) { pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING); (void) netJobAdd ( (FUNCPTR)dcRestart, pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0 ); return; } } tmd->tDesc0 = 0; /* clear all error & stat stuff */ } /* Flush the write pipe */ CACHE_PIPE_FLUSH (); }/********************************************************************************* dcHandleRecvInt - 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.*/LOCAL void dcHandleRecvInt ( DRV_CTRL * pDrvCtrl /* pointer to device control struct */ ) { DC_RDE * rmd; /* pointer to Rx ring descriptor */ while ((rmd = dcGetFullRMD (pDrvCtrl)) != NULL) dcRecv (pDrvCtrl, rmd); /* re-enable the Rx interrupt */ dcCsrWrite (pDrvCtrl->devAdrs, CSR7, (dcCsrRead (pDrvCtrl->devAdrs, CSR7) | CSR7_RIM)); }/********************************************************************************* dcGetFullRMD - get next received message RMD** Returns ptr to next Rx desc to process, or NULL if none ready.*/LOCAL DC_RDE * dcGetFullRMD ( DRV_CTRL * pDrvCtrl /* pointer to device control struct */ ) { DC_RDE * rmd; /* pointer to Rx ring descriptor */ /* Refuse to do anything if flags are down */ if ( (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING) ) != (IFF_UP | IFF_RUNNING) ) return ((DC_RDE *) NULL); rmd = pDrvCtrl->rxRing + pDrvCtrl->rxIndex; /* form ptr to Rx desc */ DC_CACHE_INVALIDATE (rmd, RMD_SIZ); if ((rmd->rDesc0 & PCISWAP(RDESC0_OWN)) == 0) return (rmd); else return ((DC_RDE *) NULL); }/********************************************************************************* dcRecv - process the next incoming packet**/LOCAL STATUS dcRecv ( DRV_CTRL * pDrvCtrl, /* pointer to device control struct */ DC_RDE * rmd /* pointer to Rx ring descriptor */ ) { ENET_HDR * pEnetHdr; /* pointer to ethernet header */ MBUF * pMbuf = NULL; /* pointer to mbuf */ u_long pPhys; UCHAR * pData; /* pointer to data */ int len; /* length */ USHORT ether_type; /* ether packet type */ /* Packet must be checked for errors. */ if (rmd->rDesc0 & PCISWAP(RDESC0_ES)) /* If error flag */ { /* error can occur on overflow, crc error, collision, * frame too long, runt frame or length error */ ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */ goto cleanRXD; /* skip to clean up */ } ++pDrvCtrl->idr.ac_if.if_ipackets; /* bump statistic */ len = RDESC0_FL_GET(PCISWAP(rmd->rDesc0)); /* frame length */ len -= 4; /* Frame length includes CRC in it so subtract it */ /* Get pointer to packet */ pEnetHdr = DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS(PCISWAP(rmd->rDesc2))); DC_CACHE_INVALIDATE (pEnetHdr, len); /* make the packet data coherent */ /* call input hook if any */ if ((etherInputHookRtn == NULL) || ((*etherInputHookRtn) (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len)) == 0) { /* Adjust length to size of data only */ len -= SIZEOF_ETHERHEADER; /* Get pointer to packet data */ pData = ((u_char *) pEnetHdr) + SIZEOF_ETHERHEADER; ether_type = ntohs ( pEnetHdr->type ); /* OK to loan out buffer ? -> build an mbuf cluster */ if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len)) && ((pMbuf = build_cluster (pData, len, & pDrvCtrl->idr, MC_LANCE, pDrvCtrl->pRefCnt [(pDrvCtrl->nLoanRx - 1)], dcLoanFree, (int) pDrvCtrl, (int) pEnetHdr, (int) pDrvCtrl->pRefCnt [(pDrvCtrl->nLoanRx - 1)])) != NULL)) { pPhys = (u_long) DC_CACHE_VIRT_TO_PHYS(MEM_TO_PCI_PHYS( (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx]))); rmd->rDesc2 = PCISWAP(pPhys); } else { if ((pMbuf = bcopy_to_mbufs (pData, len, 0, & pDrvCtrl->idr.ac_if, pDrvCtrl->memWidth)) == NULL) { ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */ goto cleanRXD; } } /* send on up... */ do_protocol_with_type (ether_type, pMbuf, & pDrvCtrl->idr, len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -