📄 if_xna.c
字号:
break; } } else { smp_unlock(&sc->lk_xna_softc); error = ENOBUFS; splx(s); } } else { smp_unlock(&sc->lk_xna_softc); splx(s); } break; case SIOCRDZCTRS: /* * Schedule a read-and-clear counters cmd, and report * the most recent version of the counter block for * this unit. xnaintr() will free m. */ if (ifp->if_flags & IFF_RUNNING) { MGET(m, M_DONTWAIT, MT_DATA); if (m) { /* * Point the data region of m to the * ctrblk in the softc for this unit. */ m->m_off = (int)&sc->ctrblk; m->m_len = sizeof(sc->ctrblk.opcode) + sizeof(struct _xnactrs); /* * Lock softc while setting the opcode * to prevent xnawatch() from blowing * away the "CMD_RCCNTR" opcode. */ s = splimp(); smp_lock(&sc->lk_xna_softc, LK_RETRY); sc->ctrblk.opcode = CMD_RCCNTR; xnacmd(sc, m); smp_unlock(&sc->lk_xna_softc); splx(s); xnagetctrs (sc, &ctr->ctr_ether, &sc->ctrblk); ctr->ctr_type = CTR_ETHER; } else error = ENOBUFS; } break; case SIOCRDCTRS: /* * Copyin most recent contents of unit's counter * block. */ if (ifp->if_flags & IFF_RUNNING) { xnagetctrs (sc, &ctr->ctr_ether, &sc->ctrblk); ctr->ctr_type = CTR_ETHER; } break; case SIOCSIFADDR: /* * Init the interface if its not already running */ xnainit(ifp->if_unit); switch(ifa->ifa_addr.sa_family) {#ifdef INET case AF_INET: s = splimp(); smp_lock(&lk_ifnet, LK_RETRY); ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; smp_unlock(&lk_ifnet); splx(s); /* 1st packet out */ arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break;#endif default: if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) error = (*pr->pr_ifioctl)(ifp, cmd, data); break; } break;#ifdef IFF_PROMISC /* IFF_ALLMULTI and NPACKETFILTER, as well */ case SIOCSIFFLAGS: if (ifp->if_flags & IFF_RUNNING) { /* * If we've successfully init'ed the interface, * issue a UCHANGE command to update the ethernet * user's promiscuous bit based upon the interface * flags. */ s = splimp(); smp_lock(&sc->lk_xna_softc, LK_RETRY); if (m = xnamkuser(sc, XNA_ETHERU, CMD_UCHANGE)) { xnacmd(sc, m); smp_unlock(&sc->lk_xna_softc); splx(s); xcmd = mtod(m, struct xnacmd_buf *); XNATIMEOUT(xcmd, CMD_UCHANGE); /* Wait */ switch (xcmd->opcode) { case CMD_COMPLETE: m_freem(m); break; case CMD_INVAL: m_freem(m); case CMD_NOP: default: error = EINVAL; break; } } else { smp_unlock(&sc->lk_xna_softc); error = ENOBUFS; splx(s); } } break;#endif IFF_PROMISC default: error = EINVAL; }done: return (error);}/* * XNA watchdog timer (runs once per second). Schedule a "read counters" * command to update the per-unit counter block. Look at the "p_sbua" * counter in the port data block to determine if we should bump up * (or reduce) the number of active receive descriptors. Descriptors * will be activated/deactivated on the next interrupt service. */xnawatch (unit) int unit;{ register struct xna_softc *sc = &xna_softc[unit]; register struct ifnet *ifp = &sc->is_if; register struct xnapdb *xpdb = sc->xpdb; struct mbuf *m; static int callno = 0; int s; if (ifp->if_flags & IFF_RUNNING) { /* * Lock softc while writing opcode and updating sbua count */ s = splimp(); smp_lock(&sc->lk_xna_softc, LK_RETRY); /* * Schedule a read counters cmd to update the counter * block for this unit. xnaintr() will free m. */ MGET(m, M_DONTWAIT, MT_DATA); if (m) { m->m_off = (int)&sc->ctrblk; m->m_len = sizeof(sc->ctrblk.opcode) + sizeof(struct _xnactrs); sc->ctrblk.opcode = CMD_RDCNTR; xnacmd(sc, m); } /* * Tweak sc->nactv based upon the "potential sbua" * count provided by the adapter. We bump up the number * of active descriptors if the p_sbua count has gone up * during the last second, but bump it down if it has * stayed the same for the last 60 seconds. */ if (*(u_long *)xpdb->p_sbua.lo > *(u_long *)sc->xna_sbuacnt.lo) { if (sc->nactv < XNANMAX) { sc->nactv++; callno = 0; } } else { if ((++callno > 60) && (sc->nactv > XNANMIN)) { sc->nactv--; callno = 0; } } sc->xna_sbuacnt = xpdb->p_sbua; smp_unlock(&sc->lk_xna_softc); splx(s); /* * Get collision count for ifnet readers (i.e. netstat, mon) */ ifp->if_collisions = *(u_long *)sc->ctrblk.xnactrs.single.lo + (*(u_long *)sc->ctrblk.xnactrs.multiple.lo * 2); } ifp->if_timer = 1;}xnainitdesc(rp, m) register struct xnarecv_ring *rp; register struct mbuf *m;{ /* * Tie cluster mbuf to ring descriptor. Bump up m_off by 2 bytes in * order to satisfy NFS, which needs longword-aligned data. * (Otherwise, the 14 byte ethernet header would place the * data at a non-longword alignment. */ m->m_off += 2;#ifdef vax rp->bseg.xaddr_lo = mtod(m, u_long);#endif vax#ifdef mips rp->bseg.xaddr_lo = svtophy(mtod(m, u_long));#endif mips rp->bseg.xaddr_hi = rp->bseg.xmbz = 0; rp->mbuf_recv = m; rp->status &= ~ST_ROWN;} struct mbuf *xnamkparam(sc, ifp) struct xna_softc *sc; struct ifnet *ifp;{ register struct mbuf *m; register struct xnacmd_buf *xparam; /* * Allocate PARAM buffer */ XNAMCLGET(m); if (!m) return (0); xparam = mtod(m, struct xnacmd_buf *); m->m_len = sizeof(xparam->opcode) + sizeof(struct _xnaparam); bzero(xparam, m->m_len); xparam->opcode = CMD_PARAM; /* * Copies 0's if the physical address hasn't been set. This signals * the port to use the default physical address. */ bcopy(sc->is_addr, &xparam->xnaparam.apa, 6); bzero(xparam->xnaparam.bvc, 8); if (ifp->if_flags & IFF_LOOPBACK) xparam->xnaparam.loop_mode = PARAM_ELOOP; else xparam->xnaparam.loop_mode = PARAM_NOLOOP; xparam->xnaparam.flags = 0; /* * Can't support the VMS-style binary quad-word date format. * Just write zero's here. */ xparam->xnaparam.sysdate_lo = xparam->xnaparam.sysdate_hi = 0; return ((struct mbuf *)m);}struct mbuf *xnamkuser(sc, index, opcode) struct xna_softc *sc; int index, opcode;{ register struct mbuf *m; register struct xnacmd_buf *xuser; register int cnt; int i; /* * Allocate USER buffer */ XNAMCLGET(m); if (!m) return (0); xuser = mtod(m, struct xnacmd_buf *); m->m_len = sizeof(xuser->opcode) + sizeof(struct _xnaustart); bzero(xuser, m->m_len); xuser->opcode = opcode; switch (index) { /* * Only handle the "generic ethernet user" for now */ case XNA_ETHERU: xuser->xnaustart.sap_ptt = ETHERTYPE_IP; xuser->xnaustart.mode = (USTART_UNK|USTART_BDC|USTART_BAD); bcopy(sc->is_addr,&xuser->xnaustart.user_phys,6); xuser->xnaustart.user_phys.xlen = ETHERMTU + sizeof(struct ether_header) + 4; xuser->xnaustart.addr_alloc = NMULTI; cnt = 0; for (i = 0; i < NMULTI; i++) { if (sc->is_muse[i] > 0) bcopy(sc->is_multi[i], &xuser->xnaustart.multi_addr[cnt++],6); } xuser->xnaustart.addr_len = cnt;#ifdef IFF_PROMISC if (sc->is_if.if_flags & IFF_PROMISC) xuser->xnaustart.mode |= USTART_PROM;#endif IFF_PROMISC break; default: m_freem(xuser); return (0); } return ((struct mbuf *)m);}xnagetctrs (sc, ctr, xcmd) register struct xna_softc *sc; register struct estat *ctr; register struct xnacmd_buf *xcmd;{ register int seconds; /* * Fill out the ethernet counters based upon the information * returned by the CMD_{RDC,RCC}CNTR command. This is pretty * disgusting, but necessary... */ bzero (ctr, sizeof(struct estat)); seconds = time.tv_sec - sc->ztime; if (seconds & 0xffff0000) ctr->est_seconds = 0xffff; else ctr->est_seconds = seconds & 0xffff; if (*(u_long *)xcmd->xnactrs.bytercvd.hi) ctr->est_bytercvd = 0xffffffff; else ctr->est_bytercvd = *(u_int *)xcmd->xnactrs.bytercvd.lo; if (*(u_long *)xcmd->xnactrs.bytesent.hi) ctr->est_bytesent = 0xffffffff; else ctr->est_bytesent = *(u_int *)xcmd->xnactrs.bytesent.lo; if (*(u_long *)xcmd->xnactrs.blokrcvd.hi) ctr->est_blokrcvd = 0xffffffff; else ctr->est_blokrcvd = *(u_int *)xcmd->xnactrs.blokrcvd.lo; if (*(u_long *)xcmd->xnactrs.bloksent.hi) ctr->est_bloksent = 0xffffffff; else ctr->est_bloksent = *(u_int *)xcmd->xnactrs.bloksent.lo; if (*(u_long *)xcmd->xnactrs.mbytercvd.hi) ctr->est_mbytercvd = 0xffffffff; else ctr->est_mbytercvd = *(u_int *)xcmd->xnactrs.mbytercvd.lo; if (*(u_long *)xcmd->xnactrs.mblokrcvd.hi) ctr->est_mblokrcvd = 0xffffffff; else ctr->est_mblokrcvd = *(u_int *)xcmd->xnactrs.mblokrcvd.lo; if (*(u_long *)xcmd->xnactrs.mbytesent.hi) ctr->est_mbytesent = 0xffffffff; else ctr->est_mbytesent = *(u_int *)xcmd->xnactrs.mbytesent.lo; if (*(u_long *)xcmd->xnactrs.mbloksent.hi) ctr->est_mbloksent = 0xffffffff; else ctr->est_mbloksent = *(u_int *)xcmd->xnactrs.mbloksent.lo; if (*(u_long *)xcmd->xnactrs.deferred.hi) ctr->est_deferred = 0xffffffff; else ctr->est_deferred = *(u_int *)xcmd->xnactrs.deferred.lo; if (*(u_long *)xcmd->xnactrs.single.hi) ctr->est_single = 0xffffffff; else ctr->est_single = *(u_int *)xcmd->xnactrs.single.lo; if (*(u_long *)xcmd->xnactrs.multiple.hi) ctr->est_multiple = 0xffffffff; else ctr->est_multiple = *(u_int *)xcmd->xnactrs.multiple.lo; if ((*(u_long *)xcmd->xnactrs.collis.hi) || (*(u_long *)xcmd->xnactrs.collis.lo & 0xffff0000)) ctr->est_collis = 0xffff; else ctr->est_collis = *(u_short *)xcmd->xnactrs.collis.lo; if ((*(u_long *)xcmd->xnactrs.unrecog.hi) || ((*(u_long *)xcmd->xnactrs.unrecog.lo) & 0xffff0000)) ctr->est_unrecog = 0xffff; else ctr->est_unrecog = *(u_short *)xcmd->xnactrs.unrecog.lo; if ((*(u_long *)xcmd->xnactrs.overrun.hi) || (*(u_long *)xcmd->xnactrs.overrun.lo & 0xffff0000)) ctr->est_overrun = 0xffff; else ctr->est_overrun = *(u_short *)xcmd->xnactrs.overrun.lo; if ((*(u_long *)xcmd->xnactrs.sysbuf.hi) || (*(u_long *)xcmd->xnactrs.sysbuf.lo & 0xffff0000)) ctr->est_sysbuf = 0xffff; else ctr->est_sysbuf = *(u_short *)xcmd->xnactrs.sysbuf.lo; if ((*(u_long *)xcmd->xnactrs.userbuf.hi) || (*(u_long *)xcmd->xnactrs.userbuf.lo & 0xffff0000)) ctr->est_userbuf = 0xffff; else ctr->est_userbuf = *(u_short *)xcmd->xnactrs.userbuf.lo; if ((*(u_long *)xcmd->xnactrs.sendfail_retry.hi) || (*(u_long *)xcmd->xnactrs.sendfail_retry.lo)) { ctr->est_sendfail_bm |= 0x01; ctr->est_sendfail = *(u_long *)xcmd->xnactrs.sendfail_retry.lo; } if ((*(u_long *)xcmd->xnactrs.sendfail_carrier.hi) || (*(u_long *)xcmd->xnactrs.sendfail_carrier.lo)) { ctr->est_sendfail_bm |= 0x02; ctr->est_sendfail += *(u_long *)xcmd->xnactrs.sendfail_carrier.lo; } if ((*(u_long *)xcmd->xnactrs.sendfail_short.hi) || (*(u_long *)xcmd->xnactrs.sendfail_short.lo)) { ctr->est_sendfail_bm |= 0x04; ctr->est_sendfail += *(u_long *)xcmd->xnactrs.sendfail_short.lo; } if ((*(u_long *)xcmd->xnactrs.sendfail_open.hi) || (*(u_long *)xcmd->xnactrs.sendfail_open.lo)) { ctr->est_sendfail_bm |= 0x08; ctr->est_sendfail += *(u_long *)xcmd->xnactrs.sendfail_open.lo; } if ((*(u_long *)xcmd->xnactrs.sendfail_long.hi) || (*(u_long *)xcmd->xnactrs.sendfail_long.lo)) { ctr->est_sendfail_bm |= 0x10; ctr->est_sendfail += *(u_long *)xcmd->xnactrs.sendfail_long.lo; } if ((*(u_long *)xcmd->xnactrs.sendfail_defer.hi) || (*(u_long *)xcmd->xnactrs.sendfail_defer.lo)) { ctr->est_sendfail_bm |= 0x20; ctr->est_sendfail += *(u_long *)xcmd->xnactrs.sendfail_defer.lo; } if ((*(u_long *)xcmd->xnactrs.recvfail_crc.hi) || (*(u_long *)xcmd->xnactrs.recvfail_crc.lo)) { ctr->est_recvfail_bm |= 0x01; ctr->est_recvfail = *(u_long *)xcmd->xnactrs.recvfail_crc.lo; } if ((*(u_long *)xcmd->xnactrs.recvfail_frame.hi) || (*(u_long *)xcmd->xnactrs.recvfail_frame.lo)) { ctr->est_recvfail_bm |= 0x02; ctr->est_recvfail += *(u_long *)xcmd->xnactrs.recvfail_frame.lo; } if ((*(u_long *)xcmd->xnactrs.recvfail_long.hi) || (*(u_long *)xcmd->xnactrs.recvfail_long.lo)) { ctr->est_recvfail_bm |= 0x04; ctr->est_recvfail += *(u_long *)xcmd->xnactrs.recvfail_long.lo; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -