📄 if_lnsgi.c
字号:
* Kick start the transmitter to avoid the polling interval latency.* This routine is called by lnInit () and lnOutput ().* It is very important that this routine be executed with splimp set.* If this is not done, another task could allocate the same tmd!*/#ifdef BSD43_DRIVERLOCAL void lnStartOutput ( int unit ) { FAST DRV_CTRL * ls = ls_softc [unit];#elseLOCAL void lnStartOutput ( DRV_CTRL * ls ) {#endif FAST struct mbuf *m; FAST ln_tmd *tmd; FAST char *buf; FAST int len; FAST int sx; FAST int oldLevel; sx = splimp (); ls->ls_flags |= LS_START_OUTPUT_FLAG; /* Loop placing message buffers in output ring until no more or no room */ while (ls->ls_if.if_snd.ifq_head != NULL) { /* there is something to send so get a transmit buffer */ if ((tmd = lnGetFreeTMD (ls)) == NULL) break; IF_DEQUEUE (&ls->ls_if.if_snd, m); /* get head of next mbuf chain */ buf = (char *) ((u_int) ls->tmd_ring.t_bufs + (u_int) ((((u_int)tmd - (u_int)ls->ls_tring) / sizeof(ln_tmd)) * ls->bufSize)); /* Copy packet to write buffer */#ifdef BSD43_DRIVER bcopy_from_mbufs (buf, m, len, ls->memWidth);#else copy_from_mbufs (buf, m, len);#endif len = max (ETHERSMALL, len); /* call output hook if any */ if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&ls->ls_if, buf, len)) continue; /* place a transmit request */ oldLevel = intLock (); /* disable ints during update */ tmd->lnTMD3 = 0; /* clear buffer error status */ tmd->tbuf_bcnt = -len; /* negative message byte count */ tmd->lnTMD1 |= lntmd1_ENP; /* buffer is end of packet */ tmd->lnTMD1 |= lntmd1_STP; /* buffer is start of packet */ tmd->lnTMD1 &= ~lntmd1_DEF; /* clear status bit */ tmd->lnTMD1 &= ~lntmd1_MORE; tmd->lnTMD1 &= ~lntmd1_ERR; tmd->lnTMD1 |= lntmd1_OWN; sysWbFlush (); intUnlock (oldLevel); /* now lnInt won't get confused */ ls->ls_tindex = (ls->ls_tindex + 1) & (ls->ls_tsize - 1); sysWbFlush ();#ifndef BSD43_DRIVER /* BSD 4.4 ether_output() doesn't bump statistic. */ ls->ls_if.if_opackets++;#endif }/* * to minimize chip accesses, don't kick start the transmitter. * it will start after the next internal poll. */ ls->ls_flags &= ~LS_START_OUTPUT_FLAG; splx (sx); }/********************************************************************************* lnIoctl -** Process an ioctl request.*/LOCAL int lnIoctl ( FAST struct ifnet *ifp, int cmd, caddr_t data ) { int unit = ifp->if_unit; FAST struct ls_softc *ls = ls_softc [unit]; int s = splimp (); 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 SIOCGIFADDR: bcopy((caddr_t) ls->ls_enaddr, (caddr_t) ((struct ifreq *)data)->ifr_addr.sa_data, 6); break; case SIOCGIFFLAGS: *(short *)data = ifp->if_flags; break; case SIOCSIFFLAGS: ls->ls_if.if_flags = ifp->if_flags; if (ifp->if_flags & IFF_PROMISC) ls->ls_flags |= LS_PROMISCUOUS_FLAG; else ls->ls_flags &= ~LS_PROMISCUOUS_FLAG; if (ifp->if_flags & IFF_UP) ls->ls_if.if_flags |= (IFF_UP|IFF_RUNNING); else ls->ls_if.if_flags &= ~(IFF_UP|IFF_RUNNING); break; default: error = EINVAL; } splx (s); return (error); }/********************************************************************************* lnChipReset - hardware reset of chip (stop it)*/LOCAL void lnChipReset ( struct ls_softc *ls ) { lnCsrWrite (ls, 0, lncsr_STOP); /* set the stop bit */ }/********************************************************************************* lnChipInit - hardware init of chip (init & start it)*/LOCAL void lnChipInit ( FAST struct ls_softc *ls ) { FAST u_short stat; int timeoutCount = 0; lnCsrWrite (ls, 0, lncsr_STOP); /* set the stop bit */ /* can't write csr1..3 if not stopped */ lnCsrWrite (ls, 3, lncsr3_BSWP); lnCsrWrite (ls, 2, (u_short) ((u_int) (LNADDR(IBUF_INDEX, ls->ib) >> 16) & 0xff)); lnCsrWrite (ls, 1, (u_short) (LNADDR(IBUF_INDEX, ls->ib))); lnCsrWrite (ls, 0, lncsr_INIT); /* init chip (read IB) */ /* hang until Initialization done, error, or timeout */ while (((stat = lnCsrRead (ls, 0)) & (lncsr_IDON | lncsr_ERR)) == 0) { if (timeoutCount++ > 0x10000) break; taskDelay(100); } /* log chip initialization failure */ if (stat & lncsr_ERR) { logMsg ("ln%d: ERROR: Lance chip initialization failure, csr0=0x%x\n", ls->ls_if.if_unit, stat, 0, 0, 0, 0); } else if (timeoutCount >= 0x10000) { logMsg ("ln%d: ERROR: Lance chip initialization time-out\n", 0, 0, 0, 0, 0, 0); } /* start chip */ ls->ls_rindex = 0; /* chip will start at beginning */ ls->ls_tindex = 0; ls->ls_dindex = 0; sysWbFlush (); lnCsrWrite(ls, 0, lncsr_IDON | lncsr_INEA | lncsr_STRT); /* reset IDON state */ /* enable interrupts from LANCE */ /* start chip operation */ }/********************************************************************************* lnGetFreeTMD - get next available TMD*/LOCAL ln_tmd *lnGetFreeTMD ( FAST struct ls_softc *ls ) { FAST ln_tmd *tmd; /* check if buffer is available (owned by host) */ /* also check for tindex overrun onto dindex */ tmd = ls->ls_tring + ls->ls_tindex; cacheClearEntry(tmd, sizeof(ln_tmd)); if (((tmd->lnTMD1 & lntmd1_OWN) != 0) || (((ls->ls_tindex + 1) & (ls->ls_tsize - 1)) == ls->ls_dindex)) { tmd = (ln_tmd *) NULL; } return (tmd); }/********************************************************************************* lnGetFullRMD - get next received message RMD*/LOCAL ln_rmd *lnGetFullRMD ( FAST struct ls_softc *ls ) { FAST ln_rmd *rmd; /* check if buffer is full (owned by host) */ rmd = ls->ls_rring + ls->ls_rindex; cacheClearEntry(rmd, sizeof(ln_rmd)); if ((rmd->lnRMD1 & lnrmd1_OWN) == 0) { return (rmd); } else { return ((ln_rmd *) NULL); } }/********************************************************************************* lnCsrRead - select and read a CSR register ** NOTE: LANCE must already be stopped to read CSR1, CSR2 or CSR3.*/LOCAL u_short lnCsrRead ( FAST struct ls_softc *ls, /* LANCE device software structure */ int reg /* which CSR to be selected */ ) { FAST u_short value; FAST u_short *dv = (u_short *)ls->devAdrs; volatile u_short *pRAP; volatile u_short *pCSR0; pRAP = (volatile u_short *) (dv + RAPOffset); pCSR0 = (volatile u_short *) (dv + CSROffset); *pRAP = reg; /* select CSR */ sysWbFlush (); value = *pCSR0; /* get contents of CSR */ return(value); /* return contents of CSR */ }/********************************************************************************* lnCsrWrite - select and write a CSR register **/LOCAL void lnCsrWrite ( FAST struct ls_softc *ls, /* LANCE device software structure */ int reg, /* which CSR to be selected */ u_short value /* value to write */ ) { FAST u_short *dv = (u_short *)ls->devAdrs; volatile u_short *pRAP; volatile u_short *pCSR0; pRAP = (volatile u_short *) (dv + RAPOffset); pCSR0 = (volatile u_short *) (dv + CSROffset); *pRAP = reg; /* select CSR */ sysWbFlush (); *pCSR0 = value; /* write value to CSR */ sysWbFlush (); }/********************************************************************************* lnCsrIntRead - select and read a CSR register in an ISR ** NOTE: LANCE must already be stopped to read CSR1, CSR2 or CSR3.*/LOCAL u_short lnCsrIntRead ( FAST struct ls_softc *ls, /* LANCE device software structure */ FAST int reg /* which CSR to be selected */ ) { FAST u_short value; FAST u_short *dv = (u_short *)ls->devAdrs; volatile u_short *pRAP; volatile u_short *pCSR0; pRAP = (volatile u_short *) (dv + RAPOffset); pCSR0 = (volatile u_short *) (dv + CSROffset); *pRAP = reg; /* select CSR */ sysWbFlush (); value = *pCSR0; /* get contents of CSR */ return(value); /* return contents of CSR */ }/********************************************************************************* lnCsrIntWrite - select and write a CSR register in an ISR.**/LOCAL void lnCsrIntWrite ( FAST struct ls_softc *ls, /* LANCE device software structure */ FAST int reg, /* which CSR to be selected */ FAST u_short value /* value to write */ ) { FAST u_short *dv = (u_short *)ls->devAdrs; volatile u_short *pRAP; volatile u_short *pCSR0; pRAP = (volatile u_short *) (dv + RAPOffset); pCSR0 = (volatile u_short *) (dv + CSROffset); *pRAP = reg; /* select CSR */ sysWbFlush (); *pCSR0 = value; /* write value to CSR */ sysWbFlush (); }/********************************************************************************* lnRmdFree - called when loaned out rbuf is freed by MCLFREE.** Puts the loaned out rbuf into free list to be reused as loan replacements.*/LOCAL void lnRmdFree ( FAST struct ls_softc *ls, FAST char *pBuf ) { ls->freeBufs [ls->nFree++] = pBuf; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -