📄 if_fza.c
字号:
/* * Trim off fddi header */ m->m_off += sizeof (struct fddi_header); m->m_len -= sizeof (struct fddi_header); } /* * Subtract length of header from len */ len -= sizeof (struct fddi_header); /* * feed the ehter struct by the fddi struct */ /* bcopy(&eptr->fddi_dhost[0],&eh.ether_dhost[0],6); */ /* bcopy(&eptr->fddi_shost[0],&eh.ether_shost[0],6); */ /* eh.ether_type = len; */ /* * Bunp up the DECnet counter */ sc->is_if.if_ipackets++; fstc_bytercvd += len; if ( fstc_pdurcvd != (unsigned) 0xffffffff) fstc_pdurcvd++; if( eptr->fddi_dhost[0] & 1 ) { fstc_mbytercvd += len; if(fstc_mpdurcvd != 0xffffffff) fstc_mpdurcvd++; } /* Dispatch this packet */ net_read(&(sc->is_ed), (struct ether_header *)eptr, m, len, (swloop != NULL), 0 );}/* * Perform a node halt/reset (SOFT reset) due to the HALT state change * interrupt. */fzareset(unit) int unit;{ register struct fza_softc *sc = &fza_softc[unit]; struct ifnet *ifp = &sc->is_if; struct mbuf *mp, *m, *m1; struct rmbuf *bp; FZAXMTRING *tp; FZARCVRING *rp; int i; /* * release all of the receive mbufs, transmit mbufs , and then reset * the adapter */ for (i = 0, bp = &sc->rmbuf[0]; i < NFZARCV ; i++ ,bp++) { if(bp->mbufa) m_freem(bp->mbufa); if(bp->mbufb) m_freem(bp->mbufb); bp->mbufa = bp->mbufb = 0; bp->phymbufa = bp->phymbufb = 0; } for ( i=0, tp = &sc->tring[0]; i < sc->nrmcxmt && tp->xmt_mbuf ; i++, tp++ ) { m_freem(tp->xmt_mbuf); } /* * If the adapter is in SHUT state, don't do the selftest */ if((sc->flag == FZA_NORMAL || sc->flag == FZA_PC_TRACED )) { /* * take out this because it may happen FZAMAXRESET * times per year; the best way is use a ratio of * how many times per hour . */ /* if (!(sc->flag & FZA_PC_TRACED) && (++fzanreset > FZAMAXRESET)) { ifp->if_flags &= ~IFF_UP; printf("fza %d: exceed the maximum number of reset\n",unit); return(0); } */ /* * do the adapter selftest */ if(!(fzaselftest(sc,unit))) { printf("fza%d: fzareset selftest fail \n",unit); return(0); } /* set the interrup mask */ sc->reg_mask = FZA_INTR_MASK; } sc->tindex = sc->nxmit = sc->rindex = 0; sc->tsmtindex = sc->rsmtindex = 0; sc->cmdindex = sc->unsindex = 0; sc->ltindex = sc->lcmdindex = -1; sc->smtrmcindex = sc->lsmtrmcindex = 0; if(!fzacmdinit(sc,unit)) { printf("fza%d: fzrestart init command fail \n",unit); return(0); } /* * fill the information */ fzafillinit(sc,sc->initblk); /* set the interrup mask */ sc->reg_mask = FZA_INTR_MASK; if(sc->flag == FZA_DLU) { printf("fza%d: Firmware revision %c%c%c%c \n",unit, sc->fw_rev[0],sc->fw_rev[1],sc->fw_rev[2], sc->fw_rev[3]); if(sc->nduflag & IFF_UP ) /* turn on this device */ ifp->if_flags |= IFF_RUNNING ; else /* turn off this device */ ifp->if_flags &= ~IFF_RUNNING ; } /* * clean the flag */ sc->flag = FZA_NORMAL; /* * allocate mbufs for receive ring */ for (i = 0, rp = &sc->rring[0], bp = &sc->rmbuf[0] ; (i < NFZARCV ); i++, rp++ , bp++) { FZAMCLGET(m) if(m) { FZAMCLGET(m1) if (m1) fzainitdesc(rp,bp, m, m1); else goto free; } else goto free; } /* * clear the transmit ring mbuf entry */ for ( i=0, tp = &sc->tring[0]; i < sc->nrmcxmt ; i++, tp++) tp->xmt_mbuf = (struct mbuf *)0; if(ifp->if_flags & IFF_RUNNING) { ifp->if_flags &= ~(IFF_RUNNING); untimeout(fzainit, unit); timeout(fzainit, unit, 1); } return(1);free: for (i = 0, bp = &sc->rmbuf[i]; (i < NFZARCV ); i++, rp++) { if(bp->mbufa) m_freem(bp->mbufa); if(bp->mbufb) m_freem(bp->mbufb); } printf("fza%d: fzareset fail - can not allocate enough receive buffer \n",unit); return(0); }/* * Process an ioctl request. */fzaioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ register struct fza_softc *sc = &fza_softc[ifp->if_unit]; register struct fzacmd_buf *xcmd; struct protosw *pr; struct mbuf *m; struct ifreq *ifr = (struct ifreq *)data; struct ifdevea *ifd = (struct ifdevea *)data; register struct ifaddr *ifa = (struct ifaddr *)data; struct ctrreq *ctr = (struct ctrreq *)data; struct ifeeprom *ife = (struct ifeeprom *)data; int s, delay, error = 0, timeout = 0; switch (cmd) { case SIOCENABLBACK: case SIOCDISABLBACK: if (cmd == SIOCENABLBACK) { if(fzadebug) printf("SIOCENABLBACK"); ifp->if_flags |= IFF_LOOPBACK; } else { if(fzadebug) printf("SIOCDISABLBACK"); ifp->if_flags &= ~IFF_LOOPBACK; } if (ifp->if_flags & IFF_RUNNING) { /* * Lock softc. issue a SHUT command * to cause a state change and then * bring down the adapter and reset it */ s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); sc->reg_ctla = SHUT; sc->flag = FZA_SHUT; /* * Wait 30 seconds for FZA change to Uninitialized state */ for (delay = 3000; delay > 0 && ((sc->reg_status & ADAPTER_STATE) != STATE_UNINITIALIZED) ; delay--) DELAY(10000); if((sc->reg_status & ADAPTER_STATE) == STATE_UNINITIALIZED) fzareset(ifp->if_unit); else printf("fza%d: Can't transition to Uninitialize State \n",ifp->if_unit); smp_unlock(&sc->lk_fza_softc); splx(s); } break; case SIOCRPHYSADDR: /* * read default hardware address. Lock softc while accessing * per-unit physical address info. */ s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); bcopy(sc->is_dpaddr, ifd->default_pa, 6); bcopy(sc->is_addr, ifd->current_pa, 6); smp_unlock(&sc->lk_fza_softc); splx(s); break; case SIOCSPHYSADDR: case SIOCDELMULTI: case SIOCADDMULTI: /* * Lock softc while updating per-unit multicast address * list and for command processing as in "fzainit()". */ s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); if (cmd == SIOCDELMULTI) { int i; if(fzadebug > 1 ) printf("SIOCDELMULTI"); /* * If we're deleting a multicast address, decrement * the is_muse count and invalidate the address if * count goes to zero. */ for (i = 0; i < NMULTI; i++) { if (bcmp(sc->is_multi[i], ifr->ifr_addr.sa_data,6) == 0) break; } if ((i < NMULTI) && (--sc->is_muse[i] == 0)) bcopy(etherbroadcastaddr,sc->is_multi[i],6); else { smp_unlock(&sc->lk_fza_softc); splx(s); goto done; } } else { int i, j = -1; if( cmd == SIOCSPHYSADDR ) { /* * we can not change the physical station * address; just add an entry to the CAM as * an alais address */ if(fzadebug > 1) printf("SIOCSPHYSADDR"); bcopy(ifr->ifr_addr.sa_data, sc->is_addr, 6);#if NPACKETFILTER > 0 pfilt_newaddress(sc->is_ed.ess_enetunit, ifr->ifr_addr.sa_data);#endif NPACKETFILTER > 0 } else { if(fzadebug > 1 ) printf("SIOCADDMULTI"); } /* * If we're adding a multicat address, increment the * is_muse count if it's already in our table, and * return. Otherwise, add it to the table or return * ENOBUFS if we're out of entries. */ for (i = 0; i < NMULTI; i++) { if (bcmp(sc->is_multi[i], ifr->ifr_addr.sa_data,6) == 0) { sc->is_muse[i]++; smp_unlock(&sc->lk_fza_softc); splx(s); goto done; } if ((j < 0) && (bcmp(sc->is_multi[i], etherbroadcastaddr,6) == 0)) j = i; } if (j < 0) { printf("fza%d: addmulti failed, multicast list full: %d\n", ifp->if_unit, NMULTI); smp_unlock(&sc->lk_fza_softc); error = ENOBUFS; splx(s); goto done; } else { bcopy(ifr->ifr_addr.sa_data, sc->is_multi[j], 6); sc->is_muse[j]++; } } if (ifp->if_flags & IFF_RUNNING) { /* * If we've successfully init'ed the interface, * issue a MODCAM command to update the fddi * user's multicast address list. Otherwise, the * list will be initialized upon the first call * to "fzainit()". */ FZACMDRING *cp; if (cp=fzamkcmd(sc, CMD_MODCAM,ifp->if_unit)) { smp_unlock(&sc->lk_fza_softc); splx(s); FZATIMEOUT(cp,timeout)/* Wait */ if(timeout || (cp->status_id != CMD_SUCCESS)) error = EINVAL; } else { smp_unlock(&sc->lk_fza_softc); error = ENOBUFS; splx(s); } } else { smp_unlock(&sc->lk_fza_softc); splx(s); } break; case SIOCRDZCTRS: case SIOCRDCTRS: if(fzadebug) { if (cmd == SIOCRDZCTRS) printf("SIOCRDZCTRS"); else printf("SIOCRDCTRS"); } /* * The adapter does not support clear counter command. * So, we only support read counter. * * Copyin most recent contents of unit's counter * block. */ if ((ifp->if_flags & IFF_RUNNING) || (sc->reg_status & ADAPTER_STATE) == STATE_RUNNING || (sc->reg_status & ADAPTER_STATE) == STATE_MAINTENANCE || (sc->reg_status & ADAPTER_STATE) == STATE_INITIALIZED ) { switch (ctr->ctr_type) { case FDDIMIB_SMT: case FDDIMIB_MAC: case FDDIMIB_PATH: case FDDIMIB_PORT: case FDDIMIB_ATTA: fmib_fill(sc,ctr,ctr->ctr_type); break; case FDDI_STATUS: fzagetstatus(sc, &ctr->sts_fddi,sc->statusblk); break; default: fzagetctrs(sc, &ctr->ctr_fddi,sc->ctrblk); ctr->ctr_type = CTR_FDDI; break; } } break; case SIOCSIFADDR: /* * Init the interface if its not already running */ if(fzadebug) printf("SIOCSIFADDR"); fzainit(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 INET 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 MODPROM command to update the ethernet * user's promiscuous bit based upon the interface * flags. * * Only support LLC promiscuous mode for now */ FZACMDRING *cp; s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); if (cp =fzamkcmd(sc, CMD_MODPROM,ifp->if_unit)) { smp_unlock(&sc->lk_fza_softc); splx(s); FZATIMEOUT(cp,timeout) if(timeout || (cp->status_id != CMD_SUCCESS)) error = EINVAL; } else { smp_unlock(&sc->lk_fza_softc); error = ENOBUFS; splx(s); } } break;#endif IFF_PROMISC case SIOCIFRESET: /* reset the adapter */ if(fzadebug) printf ("SIOCIFRESET \n"); s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); if(!fzaselftest(sc,ifp->if_unit)) { printf(" SIOCIFRESET selftest fail \n"); smp_unlock(&sc->lk_fza_softc); splx(s); return(sc->reg_status & ID_FIELD); } else /* * self test successed the adapter is in * Uninitialized state, do the driver * reset. */ sc->flag = FZA_DLU; fzareset(ifp->if_unit); /* * turn on the timer */ ifp->if_timer = 1; smp_unlock(&sc->lk_fza_softc); splx(s); return(0); break; case SIOCEEUPDATE: /* EEPROM update */ if(fzadebug) printf("SIOCEEUPDATE \n"); s = splimp(); smp_lock(&sc->lk_fza_softc, LK_RETRY); /* * if the adapter is not in the uninitialized mode, force it * to that mode. */ if(((sc->reg_status & ADAPTER_STATE) != STATE_UNINITIALIZED) && ((sc->reg_status & ADAPTER_STATE) != STATE_RESET )) { /*turn off the read counters routine */ ifp->if_timer = 0; /* save the original state */ sc->nduflag = ifp->if_flags ; /* disable the interface */ ifp->if_flags &= ~IFF_UP; sc->reg_intr = sc->reg_intr ; sc->reg_ctla = SHUT; /* * Wait 30 seconds for FZA state change */ for (delay = 3000; delay > 0 && !(sc->reg_intr & STATE_CHG); delay-- ) DELAY(10000); /* * check for state change */ if(!(sc->reg_intr & STATE_CHG)) { printf("fza%d: Down Line Upgrade state change time out\n",ifp->if_unit); smp_unlock(&sc->lk_fza_softc); splx(s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -