📄 if_dmv.c
字号:
} if ((sc->sc_flag & (DMV_ALLOC | DMV_BMAPPED)) == (DMV_ALLOC | DMV_BMAPPED) && ( sc->sc_flag & DMV_RESTART) == 0 ) { sc->sc_flag |= DMV_RESTART; dmvrestart(sc->sc_if.if_unit); } break; case DMV_PRC_BUF: printdmverr("dmv%d: buffer too small\n", sc->sc_if.if_unit); sc->sc_if.if_ierrors++; sc->sc_dmvcs.if_dstate = IFS_HALTING; sc->sc_if.if_flags &= ~IFF_UP; dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_RQHALT ); break; case DMV_ERR_RXTHRES: printdmverr("dmv%d: receive threshold reported\n", sc->sc_if.if_unit); sc->sc_if.if_oerrors++; sc->sc_dmvcs.if_dstate = IFS_HALTING; sc->sc_if.if_flags &= ~IFF_UP; dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_RQHALT ); break; case DMV_ERR_TXTHRES: printdmverr("dmv%d: transmit threshold reached\n", sc->sc_if.if_unit); goto dmv_rsp_cntl_txtimeo; case DMV_ERR_SETHRES: printdmverr("dmv%d: select threshold reached\n", sc->sc_if.if_unit); goto dmv_rsp_cntl_txtimeo; case DMV_ERR_BABBLE: printdmverr("dmv%d: babbling tributary reported\n", sc->sc_if.if_unit); goto dmv_rsp_cntl_txtimeo; case DMV_ERR_STREAM: printdmverr("dmv%d: streaming tributary reported\n", sc->sc_if.if_unit); dmv_rsp_cntl_txtimeo: sc->sc_timeo++; sc->sc_dmvcs.if_dstate = IFS_HALTING; sc->sc_if.if_flags &= ~IFF_UP; dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_RQHALT ); break; case DMV_EVT_RXMNT_RU: printf("dmv%d: MOP mode entered while DDCMP was running\n", sc->sc_if.if_unit); sc->sc_dmvcs.if_dstate = IFS_ENTEREDMOP; sc->sc_if.if_flags &= ~IFF_UP; dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_RQHALT ); break; case DMV_EVT_RXMNT_HA: printf("dmv%d: MOP mode entered while device was halted\n", sc->sc_if.if_unit); sc->sc_dmvcs.if_dstate = IFS_ENTEREDMOP; sc->sc_dmvcs.if_ustate = IFS_USROFF; if ( sc->sc_if.if_addr.sa_family != AF_UNSPEC ) { if ((pr=iffamily_to_proto(sc->sc_if.if_addr.sa_family)) && pr->pr_ifstate ) (*pr->pr_ifstate)(&sc->sc_if, sc->sc_dmvcs.if_dstate, &sc->sc_dmvcs); } sc->sc_dmvcs.if_dstate = IFS_HALTING; sc->sc_if.if_flags &= ~IFF_UP; dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_RQHALT ); break; case DMV_EVT_RXSTRT_MA: break; case DMV_EVT_RXSTRT_RU: printf("dmv%d: received start while DDCMP running\n", sc->sc_if.if_unit); sc->sc_dmvcs.if_dstate = IFS_HALTING; break; case DMV_EVT_DDCMPRUN: /* * Inform owner that device is up. */ printd("dmv%d: device is up\n", sc->sc_if.if_unit); sc->sc_if.if_flags |= IFF_UP; sc->sc_dmvcs.if_dstate = IFS_RUNNING; sc->sc_dmverrmsg = 0; if ( sc->sc_if.if_addr.sa_family != AF_UNSPEC ) { if ((pr=iffamily_to_proto(sc->sc_if.if_addr.sa_family)) && pr->pr_ifstate ) (*pr->pr_ifstate)(&sc->sc_if, sc->sc_dmvcs.if_dstate, &sc->sc_dmvcs); } break; case DMV_PRC_NXM: printf("dmv%d: non existent memory reported\n", sc->sc_if.if_unit); goto dmv_rsp_cntl_harderr; case DMV_EVT_QOVF: printf("dmv%d: device queue overflow reported\n", sc->sc_if.if_unit); goto dmv_rsp_cntl_harderr; case DMV_PRC_INVMODE: printf("dmv%d: device mode being overridden with an invalid value\n", sc->sc_if.if_unit); break; default: printd("dmv%d: procedure error (0%o) reported\n", sc->sc_if.if_unit, rsp->qp_ctl); dmv_rsp_cntl_harderr: if ((sc->sc_flag & (DMV_ALLOC | DMV_BMAPPED)) == (DMV_ALLOC | DMV_BMAPPED) && ( sc->sc_flag & DMV_RESTART) == 0 ) { sc->sc_flag |= DMV_RESTART; sc->sc_if.if_flags &= ~IFF_UP; sc->sc_dmvcs.if_dstate = IFS_HALTING; dmvrestart(sc->sc_if.if_unit); } break; } return;}/* * DMV counter formatter routine. * This routine stores the counter information in the softc structure. */dmv_format_tgss(sc, rsp)register struct dmv_softc *sc;register struct dmv_command *rsp;{ switch ( rsp->qp_ctl & KEY_MASK ) { case DMV_KEY_SELINT: sc->sc_errctrs.ctr_ddcmp.dst_select = (rsp->qp_data > 0377 ) ? 0377 : rsp->qp_cntlo; sc->sc_ctrmask |= DMV_MSK_SELINT; break; case DMV_KEY_DEOUT: sc->sc_errctrs.ctr_ddcmp.dst_outbound = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_outbound_bm = rsp->qp_cnthi & 0x7; sc->sc_ctrmask |= DMV_MSK_DEOUT; break; case DMV_KEY_DEIN: sc->sc_errctrs.ctr_ddcmp.dst_inbound = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_inbound_bm = rsp->qp_cnthi & 0x7; sc->sc_ctrmask |= DMV_MSK_DEIN; break; case DMV_KEY_LBERR: sc->sc_errctrs.ctr_ddcmp.dst_localbuf = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_localbuf_bm = rsp->qp_cnthi & 0x3; sc->sc_ctrmask |= DMV_MSK_LBERR; break; case DMV_KEY_RBERR: /* also defined as DMV_KEY_RSERR */ if ( rsp->qp_trib ) { sc->sc_errctrs.ctr_ddcmp.dst_remotebuf = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_remotebuf_bm = rsp->qp_cnthi & 0x3; sc->sc_ctrmask |= DMV_MSK_RBERR; } else { sc->sc_errctrs.ctr_ddcmp.dst_remotesta = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_remotesta_bm = rsp->qp_cnthi & 0xf; sc->sc_ctrmask |= DMV_MSK_RSERR; } break; case DMV_KEY_SELTO: /* also defined as DMV_KEY_LSERR */ if ( rsp->qp_trib ) { sc->sc_errctrs.ctr_ddcmp.dst_selecttmo = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_selecttmo_bm = rsp->qp_cnthi & 0x3; sc->sc_ctrmask |= DMV_MSK_SELTO; } else { sc->sc_errctrs.ctr_ddcmp.dst_localsta = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_localsta_bm = rsp->qp_cnthi & 0xf; sc->sc_ctrmask |= DMV_MSK_LSERR; } break; case DMV_KEY_REPTO: sc->sc_errctrs.ctr_ddcmp.dst_localtmo = rsp->qp_cntlo; sc->sc_errctrs.ctr_ddcmp.dst_remotetmo = rsp->qp_cnthi; sc->sc_ctrmask |= DMV_MSK_REPTO; break; default: printd("dmv%d: unexpected information response\n", sc->sc_if.if_unit); break; } if ( sc->sc_ctrmask == DMV_MSK_CMPLT ) { struct ifnet *ifp = &sc->sc_if; int unit = ifp->if_unit; struct protosw *pr; if (!dmv_instack[unit]) wakeup((caddr_t) &sc->sc_ctrmask); else { /* * get counter command was from timer routine * call ifiotctl to pass the counter info */ if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifioctl) (*pr->pr_ifioctl)(ifp, SIOCRDZCTRS, &sc->sc_errctrs.ctr_ddcmp); dmv_instack[unit] = 0; sc->sc_ctrmask = 0; sc->sc_ztime = time.tv_sec; sc->sc_errctrs.ctr_ddcmp.dst_bytercvd = 0; sc->sc_errctrs.ctr_ddcmp.dst_bytesent = 0; sc->sc_errctrs.ctr_ddcmp.dst_blockrcvd = 0; sc->sc_errctrs.ctr_ddcmp.dst_blocksent = 0; } } return;}/* * DMV state routine * This routine either halts the DMV or sets it up to operate * in a particular mode. */dmvstate(ifp, sc, ui) register struct ifnet *ifp; register struct dmv_softc *sc; register struct uba_device *ui;{ ifp->if_addr.sa_family = sc->sc_dmvcs.if_family; if ( sc->sc_dmvcs.if_dstate == IFS_ENTEREDMOP ) { sc->sc_dmvcs.if_dstate = IFS_HALTING; sc->sc_dmvcs.if_ustate = IFS_USRON; } else if ( sc->sc_dmvcs.if_ustate == IFS_USROFF ) { sc->sc_dmvcs.if_mode = ui->ui_flags; sc->sc_dmvcs.if_dstate = IFS_HALTED; } else { sc->sc_dmvcs.if_dstate = IFS_STARTING; }}/* * DMV output routine. * Encapsulate a packet of type family for the dmv. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */dmvoutput(ifp, m0, dst) register struct ifnet *ifp; register struct mbuf *m0; struct sockaddr *dst;{ register struct dmv_softc *sc = &dmv_softc[ifp->if_unit]; int type, error, s; register struct mbuf *m = m0; register struct dmv_header *dh; register int off; struct protosw *pr; struct ifqueue *inq; /* * check to make sure device state is currently on */ if ( (sc->sc_dmvcs.if_dstate == IFS_HALTING) || (sc->sc_dmvcs.if_dstate == IFS_HALTED) ) { error = ENETDOWN; goto bad; } /* * check for device ownership if if_nomuxhdr is asserted! */ if ( (sc->sc_dmvcs.if_nomuxhdr) && (ifp->if_addr.sa_family != dst->sa_family) ) { error = EADDRINUSE; goto bad; } switch (dst->sa_family) {#ifdef INET case AF_INET: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; if ((ifp->if_flags & IFF_NOTRAILERS) == 0) if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2 * sizeof (u_short)) { type = DMV_TRAILER + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)DMV_IPTYPE); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = DMV_IPTYPE; off = 0; goto gottype;#endif case AF_UNSPEC: dh = (struct dmv_header *)dst->sa_data; type = dh->dmv_type; goto gottype; default: if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifoutput) (*pr->pr_ifoutput)(ifp, m, dst, &type, NULL); else { printf("dmv%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); error = EAFNOSUPPORT; goto bad; } goto gottype; }gottrailertype: /* * Packet to be sent as a trailer; move first packet * (control information) to end of chain. */ while (m->m_next) m = m->m_next; m->m_next = m0; m = m0->m_next; m0->m_next = 0; m0 = m;gottype: /* * Add local header only if if_nomuxhdr is NOT asserted! * (there is space for a uba on a vax to step on) */ if ( ! sc->sc_dmvcs.if_nomuxhdr ) { if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct dmv_header) > m->m_off) { m = m_get(M_DONTWAIT, MT_DATA); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof (struct dmv_header); } else { m->m_off -= sizeof (struct dmv_header); m->m_len += sizeof (struct dmv_header); } dh = mtod(m, struct dmv_header *); dh->dmv_type = htons((u_short)type); } /* * Queue message on interface, and start output if interface * not yet active. */ s = splimp(); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); dmvstart(ifp->if_unit); splx(s); return(0);bad: m_freem(m0); return(error);}/* * Process an ioctl request. */dmvioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ int s = splimp(), error = 0; int arg; register struct dmv_softc *sc = &dmv_softc[ifp->if_unit]; register struct uba_device *ui = dmvinfo[ifp->if_unit]; switch (cmd) { case SIOCSTATE: /* * read and/or set current ownership and state of device. */ { register struct ifstate *dmvstate = (struct ifstate *) data; register struct protosw *pr; register struct ifaddr *ifa; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if ((ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family) || ifa->ifa_addr.sa_family == AF_OSI) break; if (ifa == (struct ifaddr *) 0) return(ENETDOWN); if ( ! dmvsuser() ) return(EACCES); /* * If currently owned by another family, request * ownership from that family. */ if (ifp->if_addr.sa_family && (ifp->if_addr.sa_family != dmvstate->if_family)) { if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifstate) { if (! (*pr->pr_ifstate)(ifp, IFS_OWNREQ, dmvstate)) return(EBUSY); else dmvstate->if_next_family = ifp->if_addr.sa_family; } else return(EBUSY); } /* * check validity of ioctl request */ if ( !( dmvstate->if_wrstate | dmvstate->if_rdstate | dmvstate->if_xferctl ) ) return(EINVAL); /* * set line ownership */ if ( dmvstate->if_wrstate ) { u_char save_state = sc->sc_dmvcs.if_dstate; ifp->if_addr.sa_family = dmvstate->if_family; sc->sc_dmvcs = *dmvstate; sc->sc_dmvcs.if_dstate = save_state; sc->sc_dmvcs.if_wrstate = ~IFS_WRSTATE; sc->sc_dmvcs.if_rdstate = ~IFS_RDSTATE; sc->sc_dmvcs.if_xferctl = ~IFS_XFERCTL; } /* * current owner can transfer control to another family */ if ( dmvstate->if_xferctl && dmvstate->if_wrstate ) { ifp->if_addr.sa_family = (sc->sc_dmvcs.if_family = sc->sc_dmvcs.if_next_family); sc->sc_dmvcs.if_next_family = ifp->if_addr.sa_family; } if ( dmvstate->if_wrstate ) { /* * If stopping line, restart device to force dtr drop * Else if currently running, stop device ( to be started again * later). Otherwise, start protocol up. */ if ( dmvstate->if_ustate == IFS_USROFF && (sc->sc_flag & (DMV_ALLOC | DMV_BMAPPED)) == (DMV_ALLOC | DMV_BMAPPED) && ( sc->sc_flag & DMV_RESTART) == 0 ) { sc->sc_flag |= DMV_RESTART; sc->sc_if.if_flags &= ~IFF_UP; sc->sc_dmvcs.if_dstate = IFS_HALTING; dmvrestart(sc->sc_if.if_unit); } else if (sc->sc_dmvcs.if_dstate != IFS_HALTED && sc->sc_dmvcs.if_dstate != IFS_HALTING) { ifp->if_flags &= ~IFF_UP; sc->sc_dmvcs.if_dstate = IFS_HALTING; dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_RQHALT ); } else { dmvinit(ifp->if_unit); } } /* * pass back current state if requested. */ if ( dmvstate->if_rdstate ) { bcopy(&sc->sc_dmvcs, dmvstate, sizeof(struct ifstate)); } break; } case SIOCENABLBACK: /* * place device in loopback */ if ( ! dmvsuser() ) return(EACCES); printf("dmv%d: internal loopback enable requested\n", ifp->if_unit); ifp->if_flags |= IFF_LOOPBACK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -