📄 if_dcfast.c
字号:
/* RCP: This is a redundant increment of incoming packets, removed from original driver *//* ++pDrvCtrl->idr.ac_if.if_ipackets;*/ /* bump statistic */ } /* Done with descriptor, clean up and give it to the device. */ cleanRXD: /* clear status bits and give ownership to device */ rmd->rDesc0 = PCISWAP(RDESC0_OWN); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* Advance our management index */ pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->dcNumRds; return (OK); }/********************************************************************************* dcOutput - the driver output routine**/LOCAL int dcOutput ( IDR * pIDR, /* pointer to interface data record */ MBUF * pMbuf, /* pointer to mbuf */ SOCK * pDest /* pointer to destination sock */ ) { char destEnetAddr [6]; /* space for enet addr */ USHORT packetType; /* type field for the packet */ DRV_CTRL * pDrvCtrl; /* pointer to device control struct */ DC_TDE * tmd; /* pointer to Tx ring descriptor */ char * buf; /* pointer to buffer */ int len; /* length */ /* Check ifnet flags. Return error if incorrect. */ if ( (pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING) ) return (ENETDOWN); /* Attempt to convert socket addr into enet addr and packet type. * Note that if ARP resolution of the address is required, the ARP * module will call our routine again to transmit the ARP request * packet. This means we may actually call ourselves recursively! */ if (convertDestAddr (pIDR,pDest, destEnetAddr, &packetType, pMbuf) == FALSE) return (OK); /* I KNOW returning OK is stupid, but it is correct */ /* Get driver control pointer */ pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit]; /* Obtain exclusive access to transmitter. This is necessary because * certain events can cause netTask to run a job that attempts to transmit * a packet. We can only allow one task here at a time. */ semTake (pDrvCtrl->TxSem, WAIT_FOREVER); /* See if next TXD is available */ tmd = pDrvCtrl->txRing + pDrvCtrl->txIndex; DC_CACHE_INVALIDATE (tmd, TMD_SIZ); if ( ((tmd->tDesc0 & PCISWAP(TDESC0_OWN)) != 0) || ( ((pDrvCtrl->txIndex + 1) % pDrvCtrl->dcNumTds) == pDrvCtrl->txDiIndex ) ) { m_freem (pMbuf); /* Discard data */ goto outputDone; } /* Get pointer to transmit buffer */ buf = (char *)DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS(PCISWAP(tmd->tDesc2))); /* Copy packet from MBUFs to our transmit buffer. MBUFs are * transparently freed. */ bcopy_from_mbufs ((buf + SIZEOF_ETHERHEADER), pMbuf, len, pDrvCtrl->memWidth); /* Fill in the Ethernet header */ bcopy (destEnetAddr, buf, 6); bcopy ( (char *) pIDR->ac_enaddr, (buf + 6), 6); ((ENET_HDR *)buf)->type = packetType; tmd->tDesc0 = 0; /* clear buffer error status */ tmd->tDesc1 &= PCISWAP(~TDESC1_TBS1_MSK); tmd->tDesc1 |= PCISWAP(TDESC1_TBS1_PUT(max (ETHERSMALL, (len + SIZEOF_ETHERHEADER)))); tmd->tDesc0 = PCISWAP(TDESC0_OWN); /* give ownership to device */ CACHE_PIPE_FLUSH (); /* Flush the write pipe */ /* Advance our management index */ pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->dcNumTds; if (dcKickStartTx) dcCsrWrite(pDrvCtrl->devAdrs, CSR1, CSR1_TPD); /* xmit poll demand */ /* Bump the statistic counter. */ pIDR->ac_if.if_opackets++; outputDone: /* Release exclusive access. */ semGive (pDrvCtrl->TxSem); return (OK); }/********************************************************************************* dcIoctl - the driver I/O control routine** Process an ioctl request.*/LOCAL int dcIoctl ( IDR * ifp, /* pointer interface data record */ int cmd, /* command */ caddr_t data /* data */ ) { int error = 0; DRV_CTRL * pDrvCtrl = (DRV_CTRL *)ifp; /* pointer to device */ switch (cmd) { case SIOCSIFADDR: ifp->ac_ipaddr = IA_SIN (data)->sin_addr; break; case SIOCSIFFLAGS: /* No further work to be done */ break; case IFF_PROMISC: /* set device in promiscuous mode */ dcCsrWrite (pDrvCtrl->devAdrs, CSR6, (dcCsrRead(pDrvCtrl->devAdrs, CSR6) | CSR6_PR)); break; default: error = EINVAL; } return (error); }/********************************************************************************* dcChipReset - hardware reset of chip (stop it)*/LOCAL int dcChipReset ( DRV_CTRL * pDrvCtrl /* pointer to device control structure */ ) { ULONG devAdrs = pDrvCtrl->devAdrs; /* device base address */ ULONG ix; /* index */ dcCsrWrite(devAdrs, CSR6, 0); /* stop rcvr & xmitter */ dcCsrWrite(devAdrs, CSR7, 0); /* mask interrupts */ dcCsrWrite(devAdrs, CSR0, CSR0_SWR); /* Wait Loop, Loop for at least 50 PCI cycles according to chip spec */ for (ix = 0; ix < 0x1000; ix++) ; /* any additional bus mode | give xmit & rcv process equal priority */ dcCsrWrite (devAdrs, CSR0, dcCSR0Bmr | CSR0_BAR); for (ix = 0; ix < 0x1000; ix++) /* loop for some cycles */ ; return (OK); }/********************************************************************************* dcAuiTpInit - initialize either AUI or 10BASE-T connection** This function configures 10BASE-T interface. If the link pass state is * not achieved within two seconds then the AUI interface is initialized.*/LOCAL void dcAuiTpInit ( ULONG devAdrs /* device base I/O address */ ) { /* reset the SIA registers */ dcCsrWrite (devAdrs, CSR13, 0); dcCsrWrite (devAdrs, CSR14, 0); dcCsrWrite (devAdrs, CSR15, 0); /* configure for the 10BASE-T */ dcCsrWrite (devAdrs, CSR13, CSR13_CAC_CSR); /* 10BT auto configuration */ taskDelay (sysClkRateGet() * 2); /* 2 second delay */ if (dcCsrRead (devAdrs, CSR12) & (CSR12_LKF | CSR12_NCR)) { /* 10BASE-T not connected initialize interface for AUI */ dcCsrWrite (devAdrs, CSR13, 0); /* reset SIA registers */ dcCsrWrite (devAdrs, CSR14, 0); dcCsrWrite (devAdrs, CSR15, 0); /* AUI auto configuration */ dcCsrWrite (devAdrs, CSR13, (CSR13_AUI_TP | CSR13_CAC_CSR)); } }/********************************************************************************* dcCsrWrite - select and write a CSR register**/LOCAL void dcCsrWrite ( ULONG devAdrs, /* device address base */ int reg, /* register to select */ ULONG value /* value to write */ ) { ULONG * csrReg; csrReg = (ULONG *)(devAdrs + (reg * DECPCI_REG_OFFSET)); /* write val to CSR */ *(csrReg) = PCISWAP(value); }/********************************************************************************* dcCsrRead - select and read a CSR register**/LOCAL ULONG dcCsrRead ( ULONG devAdrs, /* device address base */ int reg /* register to select */ ) { ULONG * csrReg; /* csr register */ ULONG csrData; /* data in csr register */ csrReg = (ULONG *)(devAdrs + (reg * DECPCI_REG_OFFSET)); csrData = *csrReg; /* get contents of CSR */ return ( PCISWAP(csrData)); }/********************************************************************************* dcRestart - restart the device after a fatal error** This routine takes care of all the messy details of a restart. The device* is reset and re-initialized. The driver state is re-synchronized.*/LOCAL void dcRestart ( int unit /* unit to restart */ ) { ULONG status; /* status register */ int ix; /* index variable */ DC_RDE * rmd; /* pointer to receive descriptor */ DC_TDE * tmd; /* pointer to Xmit descriptor */ DRV_CTRL * pDrvCtrl = & drvCtrl [unit]; rmd = pDrvCtrl->rxRing; /* receive ring */ tmd = pDrvCtrl->txRing; /* transmit ring */ pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING ); fprintf (stderr, "Fatal Error. DEC Ethernet Chip Restarted\n"); status = dcCsrRead(pDrvCtrl->devAdrs, CSR6); dcCsrWrite (pDrvCtrl->devAdrs, CSR6, 0); /* reset mode register */ for (ix = 0; ix < pDrvCtrl->dcNumRds; ix++, rmd++) { /* buffer size */ rmd->rDesc1 = PCISWAP(RDESC1_RBS1_VAL(DC_BUFSIZ) | RDESC1_RBS2_VAL(0)); if (ix == (pDrvCtrl->dcNumRds - 1)) /* if its is last one */ rmd->rDesc1 |= PCISWAP(RDESC1_RER); /* end of receive ring */ rmd->rDesc0 = PCISWAP(RDESC0_OWN); /* give ownership to lance */ } for (ix = 0; ix < pDrvCtrl->dcNumTds; ix++, tmd++) { tmd->tDesc1 = PCISWAP((TDESC1_TBS1_PUT(0) | TDESC1_TBS2_PUT(0) | TDESC1_IC | /* intrpt on xmit */ TDESC1_LS | /* last segment */ TDESC1_FS)); /* first segment */ if (ix == (pDrvCtrl->dcNumTds - 1)) /* if its is last one */ tmd->tDesc1 |= PCISWAP(TDESC1_TER); /* end of Xmit ring */ tmd->tDesc0 = 0 ; /* clear status */ } /* clear the status register */ dcCsrWrite (pDrvCtrl->devAdrs, CSR5, 0xffffffff); dcCsrWrite (pDrvCtrl->devAdrs, CSR6, status); /* restore mode */ pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); }/********************************************************************************* dcLoanFree - return the given buffer to loaner pool** This routine returns <pRxBuf> to the pool of available loaner buffers.* It also returns <pRef> to the pool of available loaner reference counters,* then zeroes the reference count.** RETURNS: N/A*/ LOCAL void dcLoanFree ( DRV_CTRL * pDrvCtrl, /* pointer to device control structure */ char * pRxBuf, /* pointer to receive buffer to free */ UINT8 * pRef /* pointer to reference count */ ) { /* return loaned buffer to pool */ pDrvCtrl->lPool[pDrvCtrl->nLoanRx] = pRxBuf; /* return loaned reference count to pool */ pDrvCtrl->pRefCnt[pDrvCtrl->nLoanRx++] = pRef; /* reset reference count - should have been done from above, but... */ *pRef = 0; }/********************************************************************************* dcEnetAddrGet - gets the ethernet address from the ROM register.** This routine gets the ethernet address from the ROM register.* This routine returns the ethernet address into the pointer supplied to it.* * RETURNS: OK/ERROR*/LOCAL STATUS dcEnetAddrGet ( ULONG devAdrs, /* device base I/O address */ char * enetAdrs, /* pointer to the ethernet address */ int len /* number of bytes to read */ ) { FAST ULONG csr9Value; /* register to hold CSR9 */ int ix; /* index register */ BOOL eRomReady = FALSE; /* ethernet ROM register state */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -