📄 if_ln.c
字号:
bcopy_from_mbufs (buf, pMbuf, len, pDrvCtrl->memWidth); len = max (ETHERSMALL, len); if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&pDrvCtrl->idr.ac_if,buf,len)) { CACHE_PIPE_FLUSH (); /* done as a safety */ break; } tmd->tbuf_bcnt = -len; tmd->tbuf_err = 0; /* advance our management index */ pDrvCtrl->tmdIndex = ((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1)); tmd->tbuf_stat |= lntmd1_OWN | lntmd1_STP | lntmd1_ENP; tmd->tbuf_stat &= ~lntmd1_DEF & ~lntmd1_MORE & ~lntmd1_ERR; CACHE_PIPE_FLUSH (); /* flush the write pipe */ /* kick start the transmitter, if selected */ if (lnKickStartTx) lnCsr0Write (pDrvCtrl, (lncsr_INEA | lncsr_TDMD)); pDrvCtrl->idr.ac_if.if_opackets++; /* bump the statistic counter. */ } }#endif /* BSD43_DRIVER *//********************************************************************************* lnIoctl - the driver I/O control routine** Process an ioctl request.*/LOCAL int lnIoctl ( IDR *ifp, int cmd, caddr_t data ) { int error = 0; switch (cmd) { case SIOCSIFADDR: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas (ifp, &IA_SIN (data)->sin_addr); break; case SIOCSIFFLAGS: /* No further work to be done */ break; default: error = EINVAL; } return (error); }/********************************************************************************* lnChipReset - hardware reset of chip (stop it)*/LOCAL void lnChipReset ( DRV_CTRL *pDrvCtrl ) { u_short *dv = (u_short *)pDrvCtrl->devAdrs; u_int RAPIndx; u_int CSRIndx; /*@RICK The following loops attempt to magically determine the exact * location of the two LANCE registers. Not only is this algorithm * poorly documented, it is poor practice to poke at unknown memory * locations. This will be revised. */ /* find control registers and stop LANCE */ for (CSRIndx=CSROffset; CSRIndx < 3; CSRIndx++) { for (RAPIndx=CSRIndx+1; RAPIndx <= 4; RAPIndx++) { /* setup CSR0 */ *(dv+RAPIndx) = (u_short)0; if (!(u_short)*(dv+RAPIndx)) { /* write stop */ *(dv+CSRIndx) = (u_short)lncsr_STOP; /* might want to delay here */ } /* check stop condition */ if ((!(u_short)*(dv+RAPIndx)) && ((u_short)*(dv+CSRIndx) == (u_short)lncsr_STOP)) break; } /* check stop condition */ if ((!(u_short)*(dv+RAPIndx)) && ((u_short)*(dv+CSRIndx) == (u_short)lncsr_STOP)) break; } CSROffset = CSRIndx; RAPOffset = RAPIndx; }/********************************************************************************* lnCsr0Read - read CSR 0 register** Assumes normal operation, where the RAP register has been left selecting* CSR0.*/LOCAL u_short lnCsr0Read ( DRV_CTRL * pDrvCtrl /* driver control */ ) { u_short *dv = (u_short *) pDrvCtrl->devAdrs; return (*(dv + CSROffset)); /* get contents of CSR */ }/********************************************************************************* lnCsr0Write - write CSR 0 register** Assumes normal operation, where the RAP register has been left selecting* CSR0.*/LOCAL void lnCsr0Write ( DRV_CTRL * pDrvCtrl, /* driver control */ u_short value /* value to write */ ) { u_short *dv = (u_short *) pDrvCtrl->devAdrs; *(dv + CSROffset) = (u_short) value; /* write value to CSR */ }/********************************************************************************* lnCsrWrite - select and write a CSR register**/LOCAL void lnCsrWrite ( DRV_CTRL * pDrvCtrl, /* driver control */ int reg, /* register to select */ u_short value /* value to write */ ) { u_short *dv = (u_short *) pDrvCtrl->devAdrs; *(dv + RAPOffset) = (u_short) reg; /* select CSR */ *(dv + CSROffset) = (u_short) value; /* write value to CSR */ }/********************************************************************************* lnRestartSetup - setup memory descriptors and turn on chip** Initializes all the shared memory structures and turns on the chip.*/LOCAL void lnRestartSetup ( DRV_CTRL * pDrvCtrl ) { char * buf; void * pTemp; ln_rmd * rmd; ln_tmd * tmd; ln_ib * ib; int ix; int rsize; int tsize; u_short stat; int timeoutCount = 0; /* setup Rx buffer descriptors */ rsize = pDrvCtrl->rringLen; rmd = pDrvCtrl->rring; buf = ( (char *) (rmd + (pDrvCtrl->rringSize + 1))) + 2; rmd = (ln_rmd *) ( ( (int)rmd + 7) & ~7); /* align on 000 boundary */ pDrvCtrl->rring = rmd; pDrvCtrl->rBufBase = buf; for (ix = 0; ix < pDrvCtrl->rringSize; ix++, rmd++, buf += LN_BUFSIZ) { pTemp = LN_CACHE_VIRT_TO_PHYS (buf); /* convert to physical addr */ rmd->rbuf_ladr = (u_long) pTemp; /* bits 15:00 of buffer addr */ rmd->rbuf_hadr = (((u_long) pTemp >> 16) & 0xff) | lnrmd1_OWN; /* bits 23:16 of buffer addr */ rmd->rbuf_bcnt = -(LN_BUFSIZ); /* neg of buffer byte count */ rmd->rbuf_mcnt = 0; /* no message byte count yet */ } /* setup Tx buffer descriptors */ tsize = pDrvCtrl->tringLen; tmd = pDrvCtrl->tring; buf = ( (char *) (tmd + (pDrvCtrl->tringSize + 1))) + 2; tmd = (ln_tmd *) ( ( (int)tmd + 7) & ~7); /* align on 000 boundary */ pDrvCtrl->tring = tmd; pDrvCtrl->tBufBase = buf; for (ix = 0; ix < pDrvCtrl->tringSize; ix++, tmd++, buf += LN_BUFSIZ) { pTemp = LN_CACHE_VIRT_TO_PHYS (buf); /* convert to phys addr */ tmd->tbuf_ladr = (u_long)pTemp; /* bits 15:00 of buf addr */ tmd->tbuf_hadr = (((u_long)pTemp >> 16) & 0xff) | lntmd1_ENP; /* bits 23:16 of buf addr */ tmd->tbuf_bcnt = 0; /* no message byte count yet */ tmd->tbuf_err = 0; /* no error status yet */ } /* setup the initialization block */ ib = (ln_ib *)pDrvCtrl->pMemPool; ib->lnIBMode = 0; /* chip will be in normal receive mode */ swab ((char *) pDrvCtrl->idr.ac_enaddr, ib->lnIBPadr, 6); pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->rring); /* point to Rx ring */ ib->lnIBRdraLow = (u_long) pTemp; ib->lnIBRdraHigh = (((u_long) pTemp >> 16) & 0xff) | (rsize << 13); pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->tring); /* point to Tx ring */ ib->lnIBTdraLow = (u_long) pTemp; ib->lnIBTdraHigh = (((u_long) pTemp >> 16) & 0xff) | (tsize << 13); CACHE_PIPE_FLUSH (); /* Flush the write pipe */ lnCsrWrite (pDrvCtrl, 0, lncsr_STOP); /* set the stop bit */ /* set the bus modes */#if (CPU_FAMILY == SPARC) lnCsrWrite (pDrvCtrl, 3, lncsr3_BSWP | lncsr3_ACON | lncsr3_BCON);#else /* lnCSR_3B is either set above, or overridden externally */ lnCsrWrite (pDrvCtrl, 3, lnCSR_3B);#endif /* point the device to the initialization block */ pTemp = LN_CACHE_VIRT_TO_PHYS (ib); lnCsrWrite (pDrvCtrl, 2, (u_short)(((u_long)pTemp >> 16) & 0xff)); lnCsrWrite (pDrvCtrl, 1, (u_long) pTemp); lnCsrWrite (pDrvCtrl, 0, lncsr_INIT); /* init chip (read IB) */ /* hang until Initialization DONe, ERRor, or timeout */ while (((stat = lnCsr0Read (pDrvCtrl)) & (lncsr_IDON | lncsr_ERR)) == 0) { if (timeoutCount++ > 0x10000) break; taskDelay (100); } /* log chip initialization failure */ if ((stat & lncsr_ERR) || (timeoutCount >= 0x10000) ) { logMsg ("ln%d: Device initialization failed\n", pDrvCtrl->idr.ac_if.if_unit, 0, 0, 0, 0, 0); return; } /* * Device is initialized. Start transmitter and receiver. The device * RAP register is left selecting CSR 0. */ lnCsrWrite (pDrvCtrl, 0, lncsr_IDON | lncsr_INEA | lncsr_STRT); sysLanIntEnable (pDrvCtrl->ilevel); /* enable LANCE interrupts */ pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); }/********************************************************************************* lnRestart - 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 lnRestart ( int unit ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; printf("ln: RESTART called\n"); lnChipReset (pDrvCtrl); lnRestartSetup (pDrvCtrl); /* Set our flag. */ pDrvCtrl->attached = TRUE; return; }#ifdef BSD43_DRIVER/********************************************************************************* convertDestAddr - converts socket addr into enet addr and packet type**/LOCAL BOOL convertDestAddr ( IDR *pIDR, /* ptr to i/f data record */ SOCK *pDestSktAddr, /* ptr to a generic sock addr */ char *pDestEnetAddr, /* where to write enet addr */ u_short *pPacketType, /* where to write packet type */ MBUF *pMbuf /* ptr to mbuf data */ ) { /***** Internet family *****/ { struct in_addr destIPAddr; /* not used */ int trailers; /* not supported */ if (pDestSktAddr->sa_family == AF_INET) { *pPacketType = ETHERTYPE_IP; /* stuff packet type */ destIPAddr = ((struct sockaddr_in *) pDestSktAddr)->sin_addr; if (!arpresolve (pIDR, pMbuf, &destIPAddr, pDestEnetAddr, &trailers)) return (FALSE); /* if not yet resolved */ return (TRUE); } } /***** Generic family *****/ { ETH_HDR *pEnetHdr; if (pDestSktAddr->sa_family == AF_UNSPEC) { pEnetHdr = (ETH_HDR *) pDestSktAddr->sa_data; /* ptr to hdr */ bcopy ((char *) pEnetHdr->ether_dhost, pDestEnetAddr, 6); *pPacketType = pEnetHdr->ether_type; /* copy type */ return (TRUE); } } /* Unsupported family */ return (FALSE); } /* End of convertDestAddr() */#endif /* BSD43_DRIVER *//********************************************************************************* lnLoanFree - 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 lnLoanFree ( DRV_CTRL *pDrvCtrl, char *pRxBuf, UINT8 *pRef ) { /* 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -