📄 if_dmc.c
字号:
break; report: printd("dmc%d: soft error, flags=%b\n", unit, arg, CNTLO_BITS); if ((sc->sc_flag & DMC_RESTART) == 0) { /* * kill off the dmc to get things * going again by generating a * procedure error */ sc->sc_flag |= DMC_RESTART; arg = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); } break; default: printf("dmc%d: bad control %o\n", unit, cmd); break; } } dmcstart(unit); return;}/* * DMC state routine * This routine either halts the DMC or sets it up to operate * in a particular mode. */dmcstate(ifp, sc, ui) register struct ifnet *ifp; register struct dmc_softc *sc; register struct uba_device *ui;{ ifp->if_addr.sa_family = sc->sc_dmccs.if_family; if ( sc->sc_dmccs.if_ustate == IFS_USROFF ) { sc->sc_dmccs.if_mode = ui->ui_flags; sc->sc_dmccs.if_dstate = IFS_HALTED; } else { sc->sc_dmccs.if_dstate = IFS_STARTING; }}/* * DMC output routine. * Encapsulate a packet of type family for the dmc. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */dmcoutput(ifp, m0, dst) register struct ifnet *ifp; register struct mbuf *m0; struct sockaddr *dst;{ register struct dmc_softc *sc = &dmc_softc[ifp->if_unit]; int type, error, s; register struct mbuf *m = m0; register struct dmc_header *dh; register int off; struct protosw *pr; struct ifqueue *inq; /* * check for device ownership if if_nomuxhdr is asserted! */ if ( (sc->sc_dmccs.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 = DMC_TRAILER + (off>>9); m->m_off -= 2 * sizeof (u_short); m->m_len += 2 * sizeof (u_short); *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE); *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); goto gottrailertype; } type = DMC_IPTYPE; off = 0; goto gottype;#endif case AF_UNSPEC: dh = (struct dmc_header *)dst->sa_data; type = dh->dmc_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("dmc%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_dmccs.if_nomuxhdr ) { if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct dmc_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 dmc_header); } else { m->m_off -= sizeof (struct dmc_header); m->m_len += sizeof (struct dmc_header); } dh = mtod(m, struct dmc_header *); dh->dmc_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); dmcstart(ifp->if_unit); splx(s); return(0);bad: m_freem(m0); return(error);}/* * Process an ioctl request. */dmcioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ int s = splimp(), error = 0; int arg; register struct dmc_softc *sc = &dmc_softc[ifp->if_unit]; register struct uba_device *ui = dmcinfo[ifp->if_unit]; switch (cmd) { case SIOCSTATE: /* * read and/or set current ownership and state of device. */ { register struct ifstate *dmcstate = (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) break; if (ifa == (struct ifaddr *) 0) return(ENETDOWN); if ( ! dmcsuser() ) return(EACCES); /* * If currently owned by another family, request * ownership from that family. */ if (ifp->if_addr.sa_family && (ifp->if_addr.sa_family != dmcstate->if_family)) { if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifstate) { if (! (*pr->pr_ifstate)(ifp, IFS_OWNREQ, dmcstate)) return(EBUSY); else dmcstate->if_next_family = ifp->if_addr.sa_family; } else return(EBUSY); } /* * check validity of ioctl request */ if ( !( dmcstate->if_wrstate | dmcstate->if_rdstate | dmcstate->if_xferctl ) ) return(EINVAL); /* * set line ownership */ if ( dmcstate->if_wrstate ) { ifp->if_addr.sa_family = dmcstate->if_family; bcopy(dmcstate, &sc->sc_dmccs, sizeof(struct ifstate)); sc->sc_dmccs.if_wrstate = ~IFS_WRSTATE; sc->sc_dmccs.if_rdstate = ~IFS_RDSTATE; sc->sc_dmccs.if_xferctl = ~IFS_XFERCTL; } /* * current owner can transfer control to another family */ if ( dmcstate->if_xferctl && dmcstate->if_wrstate ) { ifp->if_addr.sa_family = (sc->sc_dmccs.if_family = sc->sc_dmccs.if_next_family); sc->sc_dmccs.if_next_family = ifp->if_addr.sa_family; } if ( dmcstate->if_wrstate ) { /* * If stopping line, force procedure error in * order to drop dtr and restart device. * Else if currently running, just restart device. * Otherwise start protocol. */ if ( dmcstate->if_ustate == IFS_USROFF && (sc->sc_flag & (DMC_ALLOC | DMC_BMAPPED)) == (DMC_ALLOC | DMC_BMAPPED) && (sc->sc_flag & DMC_RESTART) == 0 ) { sc->sc_flag |= DMC_RESTART; ifp->if_flags &= ~IFF_UP; sc->sc_dmccs.if_dstate = IFS_HALTING; arg = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); } else { if ( (sc->sc_flag & DMC_RESTART) == 0 ) { sc->sc_flag |= DMC_RESTART; ifp->if_flags &= ~IFF_UP; sc->sc_dmccs.if_dstate = IFS_HALTING; dmcrestart(ifp->if_unit); } } } /* * pass back current state if requested. */ if ( dmcstate->if_rdstate ) { bcopy(&sc->sc_dmccs, dmcstate, sizeof(struct ifstate)); } break; } case SIOCENABLBACK: /* * place device in loopback */ if ( ! dmcsuser() ) return(EACCES); printf("dmc%d: internal loopback enable requested\n", ifp->if_unit); ifp->if_flags |= IFF_LOOPBACK; /* * kill off the dmc to reset state * by generating a procedure error */ if ((sc->sc_flag & DMC_RESTART) == 0) { sc->sc_dmccs.if_dstate = IFS_HALTING; ifp->if_flags &= ~IFF_UP; sc->sc_flag |= DMC_RESTART; arg = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); } else { if ( sc->sc_dmccs.if_dstate == IFS_HALTED ) dmcrestart(ifp->if_unit); } break; case SIOCDISABLBACK: /* * place device out of loopback */ if ( ! dmcsuser() ) return(EACCES); printf("dmc%d: internal loopback disable requested\n", ifp->if_unit); ifp->if_flags &= ~IFF_LOOPBACK; /* * kill off the dmc to reset state * by generating a procedure error */ if ((sc->sc_flag & DMC_RESTART) == 0) { sc->sc_dmccs.if_dstate = IFS_HALTING; ifp->if_flags &= ~IFF_UP; sc->sc_flag |= DMC_RESTART; arg = sc->sc_ubinfo & 0x3ffff; dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); } else { if ( sc->sc_dmccs.if_dstate == IFS_HALTED ) dmcrestart(ifp->if_unit); } break; case SIOCRDCTRS: case SIOCRDZCTRS: /* * reading and zeroing line counters */ { int unit = ifp->if_unit; register struct ctrreq *ctr = (struct ctrreq *)data; dmc_update_errctrs(sc, (u_char *) &dmc_base[unit].d_base[0]); bzero(&ctr->ctr_ctrs, sizeof(struct dstat)); ctr->ctr_type = CTR_DDCMP; ctr->ctr_ddcmp.dst_seconds = (time.tv_sec - sc->sc_ztime) > 0xfffe ? 0xffff : (time.tv_sec - sc->sc_ztime); ctr->ctr_ddcmp.dst_bytercvd = sc->sc_rxtxctrs[DMCZ_RXBYTE]; ctr->ctr_ddcmp.dst_bytesent = sc->sc_rxtxctrs[DMCZ_TXBYTE]; ctr->ctr_ddcmp.dst_blockrcvd = sc->sc_rxtxctrs[DMCZ_RXBLOK]; ctr->ctr_ddcmp.dst_blocksent = sc->sc_rxtxctrs[DMCZ_TXBLOK]; /* outbound erros */ if ( sc->sc_errctrs[DMCZ_RXHCRC] ) { ctr->ctr_ddcmp.dst_outbound_bm |= (1 << CTR_HDRCRC); } if ( sc->sc_errctrs[DMCZ_RXDCRC] ) { ctr->ctr_ddcmp.dst_outbound_bm |= (1 << CTR_DATCRC); } if ( (short) (ctr->ctr_ddcmp.dst_outbound = (sc->sc_errctrs[DMCZ_RXHCRC] + sc->sc_errctrs[DMCZ_RXDCRC])) > 0x0ff ) ctr->ctr_ddcmp.dst_outbound = 0x0ff; /* inbound errors */ if ( sc->sc_errctrs[DMCZ_TXHCRC] ) { ctr->ctr_ddcmp.dst_inbound_bm |= (1 << CTR_HDRCRC); } if ( sc->sc_errctrs[DMCZ_TXDCRC] ) { ctr->ctr_ddcmp.dst_inbound_bm |= (1<< CTR_DATCRC); } if ( (short) (ctr->ctr_ddcmp.dst_inbound = (sc->sc_errctrs[DMCZ_TXHCRC] + sc->sc_errctrs[DMCZ_TXDCRC])) > 0x0ff ) ctr->ctr_ddcmp.dst_outbound = 0x0ff; /* buffer unavailable */ if (ctr->ctr_ddcmp.dst_remotebuf = sc->sc_errctrs[DMCZ_RXNOBUF] ) { ctr->ctr_ddcmp.dst_remotebuf_bm |= (1 << CTR_BUFUNAVAIL); } if (ctr->ctr_ddcmp.dst_localbuf = sc->sc_errctrs[DMCZ_TXNOBUF] ) { ctr->ctr_ddcmp.dst_localbuf_bm |= (1 << CTR_BUFUNAVAIL); } ctr->ctr_ddcmp.dst_remotetmo = sc->sc_errctrs[DMCZ_REMOTETMO]; ctr->ctr_ddcmp.dst_localtmo = sc->sc_errctrs[DMCZ_LOCALTMO]; if ( cmd == SIOCRDZCTRS ) { sc->sc_ztime = time.tv_sec; bzero(&sc->sc_rxtxctrs[DMCZ_RXBYTE], sizeof(sc->sc_rxtxctrs)); bzero(sc->sc_errctrs, sizeof(sc->sc_errctrs)); } break; } case SIOCSIFADDR: ifp->if_flags |= IFF_UP; if ((ifp->if_flags & IFF_RUNNING) == 0) dmcinit(ifp->if_unit); break; case SIOCSIFDSTADDR: if ((ifp->if_flags & IFF_RUNNING) == 0) dmcinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return(error);}/* * update drivers copy of line error counters */dmc_update_errctrs(sc, base_table)register struct dmc_softc *sc;register u_char *base_table;{ short tmp_cnt; if ( (tmp_cnt = base_table[DMCD_RXHCRC] - sc->sc_basectrs[DMCZ_RXHCRC]) ) { if ( tmp_cnt < 0 || (sc->sc_errctrs[DMCZ_RXHCRC] + tmp_cnt) > 0x0ff ) sc->sc_errctrs[DMCZ_RXHCRC] = 0xff; else sc->sc_errctrs[DMCZ_RXHCRC] += tmp_cnt; } if ( (tmp_cnt = base_table[DMCD_RXDCRC] - sc->sc_basectrs[DMCZ_RXDCRC]) ) { if ( tmp_cnt < 0 || (sc->sc_errctrs[DMCZ_RXDCRC] + tmp_cnt) > 0x0ff )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -