📄 if_qe.c
字号:
register struct qe_softc *sc = qe_softc[unit]; register struct uba_device *ui = qeinfo[unit];#ifdef vax register struct qedevice *addr = (struct qedevice *)ui->ui_addr;#endif vax#ifdef mips volatile struct qedevice *addr = (struct qedevice *)ui->ui_addr;#endif mips register struct ifnet *ifp = &sc->is_if; register int i; int s; /* address not known */ /* DECnet must set this somewhere to make device happy */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (ifp->if_flags & IFF_RUNNING) return; /* * map the communications area onto the device */ sc->rringaddr = (struct qe_ring *)((int)qballoc(0, sc->rring, sizeof(struct qe_ring)*(nNTOT+2),0)&mask); sc->tringaddr = sc->rringaddr+nNRCV+1; sc->setupaddr = qballoc(0, sc->setup_pkt, sizeof(sc->setup_pkt), 0) & mask; /* * init buffers and maps */ if (qe_ubainit(&sc->qeuba, ui->ui_ubanum, sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), sc->buffers,unit) == 0) { printf("qe%d: can't initialize\n", unit); sc->is_if.if_flags &= ~IFF_UP; return; } /* * Init the buffer descriptors and indexes for each of the lists and * loop them back to form a ring. */ for( i = 0 ; i < nNRCV ; i++ ){ qeinitdesc( &sc->rring[i], sc->qeuba.ifu_r[i].ifrw_info & mask, MAXPACKETSIZE); sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; } qeinitdesc( &sc->rring[i], NULL, 0 ); sc->rring[i].qe_addr_lo = (short)sc->rringaddr; sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16); sc->rring[i].qe_chain = 1; sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; sc->rring[i].qe_valid = 1; for( i = 0 ; i <= nNXMT ; i++ ) qeinitdesc( &sc->tring[i], NULL, 0 ); i--; sc->tring[i].qe_addr_lo = (short)sc->tringaddr; sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16); sc->tring[i].qe_chain = 1; sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET; sc->tring[i].qe_valid = 1; sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; /* * Take the interface out of reset, program the vector, * enable interrupts, and tell the world we are up. */ s = splimp(); addr->qe_vector = (u_short)sc->qe_intvec; sc->addr = (struct qedevice *) addr; if ( ifp->if_flags & IFF_LOOPBACK ) addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ELOOP; else addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; addr->qe_rcvlist_lo = (short)sc->rringaddr; addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); ifp->if_flags |= IFF_UP | IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; qesetup( sc ); qestart( unit ); sc->ztime = time.tv_sec; splx( s );} /* * Start output on interface. * */qestart(unit) int unit;{ register struct qe_softc *sc = qe_softc[unit]; register struct qedevice *addr; register struct qe_ring *rp; register int index; struct mbuf *m; int buf_addr, len, s; struct uba_device *ui = qeinfo[unit]; s = splimp(); addr = (struct qedevice *)ui->ui_addr; /* * The deqna doesn't look at anything but the valid bit * to determine if it should transmit this packet. If you have * a ring and fill it the device will loop indefinately on the * packet and continue to flood the net with packets until you * break the ring. For this reason we never queue more than n-1 * packets in the transmit ring. * * The microcoders should have obeyed their own defination of the * flag and status words, but instead we have to compensate. */ for( index = sc->tindex; sc->tring[index].qe_valid == 0 && sc->nxmit < (nNXMT-1) ; sc->tindex = index = ++index % nNXMT){ rp = &sc->tring[index]; if( sc->setupqueued ) { buf_addr = sc->setupaddr; len = 128; rp->qe_setup = 1; sc->setupqueued = 0; } else { IF_DEQUEUE(&sc->is_if.if_snd, m); if( m == 0 ){ splx(s); return; } buf_addr = sc->qeuba.ifu_w[index].x_ifrw.ifrw_info; len = qeput(&sc->qeuba, index, m); } /* * Does buffer end on odd byte ? */ if( len & 1 ) { len++; rp->qe_odd_end = 1; }#ifdef IFF_PROMISC if (rp->qe_setup && (sc->is_if.if_flags & IFF_PROMISC)) { len |= QE_PROMISCUOUS; }#endif IFF_PROMISC#ifdef IFF_ALLMULTI if (rp->qe_setup && (sc->is_if.if_flags & IFF_ALLMULTI)) len |= QE_MULTICAST;#endif IFF_ALLMULTI rp->qe_buf_len = -(len/2); buf_addr &= mask; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_addr_lo = (short)buf_addr; rp->qe_addr_hi = (short)(buf_addr >> 16); rp->qe_eomsg = 1; rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 1; sc->nxmit++; sc->is_if.if_flags |= IFF_OACTIVE; /* * If the watchdog time isn't running kick it. */ sc->timeout=1; if( !qewatchrun++ ) timeout(qewatch,0,QE_TIMEO); /* * See if the xmit list is invalid. */ if( (addr->qe_csr & QE_XL_INVALID) && (rp->qe_status1 == QE_NOTYET)) { buf_addr = (int)(sc->tringaddr+index); addr->qe_xmtlist_lo = (short)buf_addr; addr->qe_xmtlist_hi = (short)(buf_addr >> 16); } } splx( s );} /* * Ethernet interface interrupt processor */qeintr(unit) int unit;{ register struct qe_softc *sc = qe_softc[unit];#ifdef vax struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr;#endif vax#ifdef mips volatile struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr;#endif mips int s, buf_addr; u_short csr; s = splimp(); csr = addr->qe_csr; addr->qe_csr = csr; if( csr & QE_RCV_INT ) qerint( unit ); if( csr & QE_XMIT_INT ) qetint( unit ); if( csr & QE_NEX_MEM_INT ) { if ( qe_show_restarts ) mprintf("qe%d: non-existant memory \n", unit); qerestart( sc ); } if( addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 == QE_NOTYET ) { buf_addr = (int)&sc->rringaddr[sc->rindex]; addr->qe_rcvlist_lo = (short)buf_addr; addr->qe_rcvlist_hi = (short)(buf_addr >> 16); } if( addr->qe_csr & QE_XL_INVALID && sc->tring[sc->otindex].qe_status1 == QE_NOTYET && sc->nxmit > 0 ) { buf_addr = (int)&sc->tringaddr[sc->otindex]; addr->qe_xmtlist_lo = (short)buf_addr; addr->qe_xmtlist_hi = (short)(buf_addr >> 16); } splx( s );} /* * Ethernet interface transmit interrupt. */qetint(unit) int unit;{ register struct qe_softc *sc = qe_softc[unit]; register struct qe_ring *rp; register struct ifrw *ifrw; register struct ifxmt *ifxp; register struct ether_header *eh; register int status1, setupflag; short len; sc->qe_rl_invalid = 0; /* dallas */#ifdef mips /* * Flush the cache for the transmit ring descriptor */ clean_dcache(PHYS_TO_K0(svtophy(&sc->tring[0])), sizeof(struct qe_ring)* nNXMT); #endif mips while( sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1 != QE_NOTYET && sc->nxmit > 0 ) { /* * Save the status words from the descriptor so that it can * be released. */ rp = &sc->tring[sc->otindex]; status1 = rp->qe_status1; setupflag = rp->qe_setup; len = (-rp->qe_buf_len) * 2; if( rp->qe_odd_end ) len++; /* * Init the buffer descriptor */ bzero( rp, sizeof(struct qe_ring)); if( --sc->nxmit == 0 ) { sc->timeout = 0; sc->is_if.if_flags &= ~IFF_OACTIVE; } if( !setupflag ) { /* * Do some statistics. */ sc->is_if.if_opackets++; sc->is_if.if_collisions += ( status1 & QE_CCNT ) >> 4; /* * Accumulate DECnet statistics */ if (status1 & QE_CCNT) { if (((status1 & QE_CCNT) >> 4) == 1) { if (sc->ctrblk.est_single != 0xffffffff) sc->ctrblk.est_single++; } else { if (sc->ctrblk.est_multiple != 0xffffffff) sc->ctrblk.est_multiple++; } } if (status1 & QE_FAIL) if (sc->ctrblk.est_collis != 0xffff) sc->ctrblk.est_collis++; if( status1 & QE_ERROR ) { sc->is_if.if_oerrors++; if (sc->ctrblk.est_sendfail != 0xffff) sc->ctrblk.est_sendfail++; sc->ctrblk.est_sendfail_bm = 0; if (status1 & QE_ABORT) sc->ctrblk.est_sendfail_bm |= 1; if (status1 & (QE_NOCAR | QE_LOSS)) sc->ctrblk.est_sendfail_bm |= 2; } else { /* * Accumulate statistics for DECnet */ sc->ctrblk.est_bytesent += len; if (sc->ctrblk.est_bloksent != (unsigned) 0xffffffff) sc->ctrblk.est_bloksent++; } /* * If this was a broadcast packet loop it * back because the hardware can't hear it's own * transmits and the rwho deamon expects to see them. * This code will have to be expanded to include multi- * cast if the same situation developes. */ ifxp = &sc->qeuba.ifu_w[sc->otindex]; ifrw = &sc->qeuba.ifu_w[sc->otindex].x_ifrw; eh = (struct ether_header *)ifrw->ifrw_addr; /* * Accumulate statistics for DECnet */ if(eh->ether_dhost[0] & 1) { sc->ctrblk.est_mbytesent += len; if (sc->ctrblk.est_mbloksent != (unsigned) 0xffffffff) sc->ctrblk.est_mbloksent++; }/* * This is a Kludge to do a fast check to see if the ethernet * address is all 1's, the ethernet broadcast addr, and loop the * packet back. */ if((!(bcmp(eh->ether_dhost,qe_multi,6))) || (sc->is_if.if_flags & IFF_PFCOPYALL)) { qeread(sc, ifrw, len, ifxp->x_xtofree); ifxp->x_xtofree =0; }else if( ifxp->x_xtofree ) { m_freem( ifxp->x_xtofree ); ifxp->x_xtofree = 0; } } sc->otindex = ++sc->otindex % nNXMT; } if (!(sc->is_if.if_flags & IFF_OACTIVE)) qestart( unit );} /* * Ethernet interface receiver interrupt. * If can't determine length from type, then have to drop packet. * Othewise decapsulate packet based on type and pass to type specific * higher-level input routine. */qerint(unit) int unit;{ register struct qe_softc *sc = qe_softc[unit]; register struct ifnet *ifp = &sc->is_if; register struct qe_ring *rp; register int last; u_short status1, status2; short len; int bufaddr; struct ether_header *eh; /* * Traverse the receive ring looking for packets to pass back. * The search is complete when we find a descriptor not in use. * * As in the transmit case the deqna doesn't honor it's own protocols * so there exists the possibility that the device can beat us around * the ring. The proper way to guard against this is to insure that * there is always at least one invalid descriptor. We chose instead * to make the ring large enough to minimize the problem. With a ring * size of 4 we haven't been able to see the problem. To be safe we * doubled that to 8. * */#ifdef mips /* * Flush the cache for the receive ring descriptor */ clean_dcache(PHYS_TO_K0(svtophy(&sc->rring[0])), sizeof(struct qe_ring)* nNRCV); #endif mips for( last = sc->rindex; sc->rring[sc->rindex].qe_status1 != QE_NOTYET ; last = sc->rindex = ++sc->rindex % nNRCV ){ rp = &sc->rring[sc->rindex]; status1 = rp->qe_status1; status2 = rp->qe_status2; bzero( rp, sizeof(struct qe_ring)); /* Discard chained packets */ while( (status1 & QE_MASK) == QE_MASK ) { last = ++last % nNRCV; rp = &sc->rring[last]; status1 = rp->qe_status1; bzero( rp, sizeof(struct qe_ring)); if ((status1 & QE_MASK) != QE_MASK) { if (status1 == QE_NOTYET) /* Should NEVER happen */ panic("qe: chained packet"); else goto drop; } } len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)); if( ! (ifp->if_flags & IFF_LOOPBACK) ) { if( status1 & QE_ERROR ) { if (status1 & QE_RUNT ) qe_runt++; if ((status1 & QE_DISCARD) && (status1&(QE_OVF|QE_CRCERR|QE_FRAME))){ /* A real error */ ifp->if_ierrors++; ifp->if_ipackets++; /* Bump up receive fails */ if (sc->ctrblk.est_recvfail != 0xffff) sc->ctrblk.est_recvfail++; /* Clear previous bitmask; set bits */ sc->ctrblk.est_recvfail_bm = 0; if (status1 & QE_OVF) { sc->ctrblk.est_recvfail_bm |= 4;#if NPACKETFILTER > 0 sc->qe_ed.ess_missed++;#endif NPACKETFILTER } if (status1 & QE_CRCERR) sc->ctrblk.est_recvfail_bm |= 1; if (status1 & QE_FRAME) sc->ctrblk.est_recvfail_bm |= 2; } } else { /* * We don't process setup packets. */ if( !(status1 & QE_ESETUP) ) { len += 60;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -