From a2cd4df767910f9e0027c19e429d75826e5eb021 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Fri, 12 Feb 1982 23:17:41 -0800 Subject: [PATCH] closer to a working imp driver SCCS-vsn: sys/deprecated/netimp/if_imphost.c 4.2 SCCS-vsn: sys/deprecated/netimp/if_imphost.h 4.2 SCCS-vsn: sys/vax/if/if_acc.c 4.3 SCCS-vsn: sys/deprecated/netimp/if_imp.c 4.4 SCCS-vsn: sys/deprecated/netimp/if_imp.h 4.3 SCCS-vsn: sys/deprecated/netimp/raw_imp.c 4.3 SCCS-vsn: sys/net/raw_cb.c 4.3 --- usr/src/sys/deprecated/netimp/if_imp.c | 222 +++++++++++++++------ usr/src/sys/deprecated/netimp/if_imp.h | 58 ++++-- usr/src/sys/deprecated/netimp/if_imphost.c | 54 ++--- usr/src/sys/deprecated/netimp/if_imphost.h | 6 +- usr/src/sys/deprecated/netimp/raw_imp.c | 42 ++-- usr/src/sys/net/raw_cb.c | 3 +- usr/src/sys/vax/if/if_acc.c | 172 ++++++++++------ 7 files changed, 366 insertions(+), 191 deletions(-) diff --git a/usr/src/sys/deprecated/netimp/if_imp.c b/usr/src/sys/deprecated/netimp/if_imp.c index 455c31a23d..1fafca9d83 100644 --- a/usr/src/sys/deprecated/netimp/if_imp.c +++ b/usr/src/sys/deprecated/netimp/if_imp.c @@ -1,4 +1,4 @@ -/* if_imp.c 4.3 82/02/01 */ +/* if_imp.c 4.4 82/02/12 */ #include "imp.h" #if NIMP > 0 @@ -7,6 +7,11 @@ * * The IMP-host protocol is handled here, leaving * hardware specifics to the lower level interface driver. + * + * TODO: + * rethink coupling between this module and device driver + * pass more error indications up to protocol modules + * test raw imp interface */ #include "../h/param.h" #include "../h/systm.h" @@ -23,6 +28,7 @@ #include "../net/in.h" #include "../net/in_systm.h" #include "../net/if.h" +#define IMPLEADERS #include "../net/if_imp.h" #include "../net/host.h" #include "../net/ip.h" @@ -37,8 +43,9 @@ * This structure contains the output queue for the interface, its * address, ... IMP specific structures used in connecting the * IMP software modules to the hardware specific interface routines - * are also stored here. These structures are visible in the interface - * driver through back pointers set up in the hardware's attach routine. + * are stored here. The common structures are made visible to the + * interface driver by passing a pointer to the hardware routine + * at "attach" time. * * NOTE: imp_if and imp_cb are assumed adjacent in hardware code. */ @@ -47,7 +54,6 @@ struct imp_softc { struct impcb imp_cb; /* hooks to hardware module */ u_char imp_state; /* current state of IMP */ char imp_dropcnt; /* used during initialization */ - short imp_timer; /* going down timer */ } imp_softc[NIMP]; /* @@ -61,6 +67,8 @@ static char *impmsg[] = { "for emergency reset" }; +int impdown(), impinit(), impoutput(); + /* * IMP attach routine. Called from hardware device attach routine * at configuration time with a pointer to the UNIBUS device structure. @@ -80,8 +88,13 @@ COUNT(IMPATTACH); ifp->if_name = "imp"; ifp->if_mtu = IMP_MTU; ifp->if_net = ui->ui_flags; -/* ifp->if_host = ... */ -/* ifp->if_addr = if_makeaddr(ifp->if_net, ifp->if_host); */ +#ifdef notdef + /* this should get cleaned after we talk to the imp */ + ifp->if_addr = if_makeaddr(ifp->if_net, ifp->if_host); +#endif + ifp->if_init = impinit; + ifp->if_output = impoutput; + /* reset is handled at the hardware level */ if_attach(ifp); /* kludge to hand pointers back to hardware attach routine */ return ((int)&sc->imp_if); @@ -97,9 +110,13 @@ impinit(unit) { register struct imp_softc *sc = &imp_softc[unit]; - (*sc->imp_cb.ic_init)(unit); + if ((*sc->imp_cb.ic_init)(unit) == 0) { + sc->imp_state = IMPS_DOWN; + return; + } sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; + impnoops(sc); } struct sockproto impproto = { PF_IMPLINK }; @@ -113,36 +130,45 @@ struct sockaddr_in impsrc = { AF_IMPLINK }; * passed to higher level protocol processors on the basis * of link number. Other type messages (control) are handled here. */ -impinput(unit, m0) +impinput(unit, m) int unit; - struct mbuf *m0; + register struct mbuf *m; { int s; - register struct mbuf *m; register struct imp_leader *ip; register struct imp_softc *sc = &imp_softc[unit]; register struct host *hp; register struct ifqueue *inq; + struct control_leader *cp; struct in_addr addr; COUNT(IMP_INPUT); - m = m0; - +printf("impinput(%d, %x), len=%d\n", unit, m, m->m_len); +printleader("impinput", mtod(m, struct imp_leader *)); /* + * Verify leader length. Be careful with control + * message which don't get a length included. * We should generate a "bad leader" message * to the IMP about messages too short. */ - if (m->m_len < sizeof(struct imp_leader) && - m_pullup(m, sizeof(struct imp_leader)) == 0) - goto drop; + if (m->m_len < sizeof(struct control_leader) && + (m = m_pullup(m, sizeof(struct control_leader))) == 0) + return; + cp = mtod(m, struct control_leader *); + if (cp->dl_mtype == IMPTYPE_DATA) + if (m->m_len < sizeof(struct imp_leader) && + (m = m_pullup(m, sizeof(struct imp_leader))) == 0) + return; ip = mtod(m, struct imp_leader *); /* * Check leader type -- should notify IMP * in case of failure... */ - if (ip->il_format != IMP_NFF) + if (ip->il_format != IMP_NFF) { + sc->imp_if.if_collisions++; /* XXX */ goto drop; + } /* * Certain messages require a host structure. @@ -155,8 +181,10 @@ COUNT(IMP_INPUT); case IMPTYPE_HOSTDEAD: case IMPTYPE_HOSTUNREACH: case IMPTYPE_BADDATA: - addr.s_host = ntohs(ip->il_host); /* XXX */ - hp = h_lookup(addr); + addr.s_net = ip->il_network; + addr.s_imp = ip->il_imp; + addr.s_host = ip->il_host; + hp = hostlookup(addr); break; } @@ -169,7 +197,8 @@ COUNT(IMP_INPUT); * into mbuf past leader (done below). */ case IMPTYPE_DATA: - ip->il_length = ntohs(ip->il_length) >> 3; + ip->il_length = + (ntohs(ip->il_length) >> 3) - sizeof(struct imp_leader); break; /* @@ -182,9 +211,9 @@ COUNT(IMP_INPUT); * first noop sent to the IMP after * the host resets the IMP interface. */ - if (sc->imp_state != IMPS_RESET) { + if (sc->imp_state != IMPS_INIT) { imperr(sc, "leader error"); - h_reset(sc->imp_if.if_net); /* XXX */ + hostreset(sc->imp_if.if_net); /* XXX */ impnoops(sc); } goto drop; @@ -197,7 +226,7 @@ COUNT(IMP_INPUT); case IMPTYPE_DOWN: if ((ip->il_link & IMP_DMASK) == 0) { sc->imp_state = IMPS_GOINGDOWN; - timeout(impdown, sc, 30 * 60 * HZ); + timeout(impdown, sc, 30 * hz); } imperr(sc, "going down %s", impmsg[ip->il_link & IMP_DMASK]); goto drop; @@ -207,24 +236,27 @@ COUNT(IMP_INPUT); * Compare the local address with that in the message. * Reset the local address notion if it doesn't match. */ - case IMPTYPE_NOOP: + case IMPTYPE_NOOP: { + register struct in_addr *sin; + if (sc->imp_state == IMPS_DOWN) { sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; } - if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt == 0) { - sc->imp_state = IMPS_UP; - /* restart output in case something was q'd */ - (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); - } - if (ip->il_host != sc->imp_if.if_addr.s_host || - ip->il_impno != sc->imp_if.if_addr.s_imp) { - sc->imp_if.if_addr.s_host = ip->il_host; - sc->imp_if.if_addr.s_imp = ip->il_imp; - imperr(sc, "imp%d: address set to %d/%d\n", - ip->il_host, ip->il_impno); - } + if (sc->imp_state != IMPS_INIT) + goto drop; + if (--sc->imp_dropcnt > 0) + goto drop; + sc->imp_state = IMPS_UP; + sin = &sc->imp_if.if_addr; + sc->imp_if.if_host[0] = sin->s_host = ip->il_host; + sin->s_imp = ip->il_imp; + imperr(sc, "reset (host %d/imp %d)", ip->il_host, + ntohs(ip->il_imp)); + /* restart output in case something was q'd */ + (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); goto drop; + } /* * RFNM or INCOMPLETE message, record in @@ -240,14 +272,17 @@ COUNT(IMP_INPUT); hp->h_rfnm--; /* poke holding queue */ if (n = hp->h_q) { - if (n->m_act == n) + if (n->m_next == n) hp->h_q = 0; else { - n = n->m_act; - hp->h_q->m_act = n->m_act; + n = n->m_next; + hp->h_q->m_next = n->m_next; } - (void) impsnd(n, sc); + (void) impsnd(sc, n); + break; } + if (hp->h_rfnm == 0) + hostfree(hp); } break; @@ -255,13 +290,18 @@ COUNT(IMP_INPUT); * Host or IMP can't be reached. Flush any packets * awaiting transmission and release the host structure. * - * HOW DO WE NOTIFY THE PROTOCOL? - * HOW DO WE AGE THE HOST STRUCTURE TO SAVE STATUS? + * TODO: NOTIFY THE PROTOCOL */ case IMPTYPE_HOSTDEAD: + imperr(sc, "host dead"); /* XXX */ + goto common; /* XXX */ + + /* SHOULD SIGNAL ROUTING DAEMON */ case IMPTYPE_HOSTUNREACH: + imperr(sc, "host unreachable"); /* XXX */ + common: if (hp) - h_free(hp); /* won't work right */ + hostfree(hp); /* won't work right */ break; /* @@ -280,7 +320,6 @@ COUNT(IMP_INPUT); */ case IMPTYPE_RESET: imperr(sc, "interface reset"); - sc->imp_state = IMPS_RESET; impnoops(sc); goto drop; @@ -309,7 +348,7 @@ COUNT(IMP_INPUT); impsrc.sin_addr.s_net = ip->il_network; impsrc.sin_addr.s_host = ip->il_host; impsrc.sin_addr.s_imp = ip->il_imp; - raw_input(m, impproto, impdst, impsrc); + raw_input(m, &impproto, &impdst, &impsrc); return; } IF_ENQUEUE(inq, m); @@ -326,6 +365,7 @@ impdown(sc) struct imp_softc *sc; { sc->imp_state = IMPS_DOWN; + imperr(sc, "marked down"); /* notify protocols with messages waiting? */ } @@ -351,14 +391,19 @@ impoutput(ifp, m0, pf) { register struct imp_leader *imp; register struct mbuf *m = m0; - int x, dhost, dimp, dlink, len; + int x, dhost, dimp, dlink, len, dnet; +COUNT(IMPOUTPUT); +printf("impoutput(%x, %x, %x)\n", ifp, m0, pf); + +#ifdef notdef /* * Don't even try if the IMP is unavailable. */ x = imp_softc[ifp->if_unit].imp_state; if (x == IMPS_DOWN || x == IMPS_GOINGDOWN) goto drop; +#endif switch (pf) { @@ -366,10 +411,12 @@ impoutput(ifp, m0, pf) case PF_INET: { register struct ip *ip = mtod(m0, struct ip *); + dnet = ip->ip_dst.s_net; dhost = ip->ip_dst.s_host; dimp = ip->ip_dst.s_imp; dlink = IMPLINK_IP; len = ntohs(ip->ip_len); +printf("impoutput: net=%d,host=%d,imp=%d,len=%d\n",dnet,dhost,dimp,len); break; } #endif @@ -400,9 +447,10 @@ impoutput(ifp, m0, pf) } imp = mtod(m, struct imp_leader *); imp->il_format = IMP_NFF; + imp->il_network = dnet; imp->il_host = dhost; - imp->il_impno = dimp; - imp->il_length = (len + sizeof(struct imp_leader)) << 3; + imp->il_imp = dimp; + imp->il_length = htons((len + sizeof(struct imp_leader)) << 3); imp->il_link = dlink; leaderexists: @@ -430,6 +478,8 @@ impsnd(ifp, m) struct impcb *icp; int x; +COUNT(IMPSND); +printf("impsnd(%x, %x)\n", ifp, m); ip = mtod(m, struct imp_leader *); /* @@ -439,10 +489,11 @@ impsnd(ifp, m) if (ip->il_mtype == IMPTYPE_DATA) { struct in_addr addr; - addr.s_net = ifp->if_net; + addr.s_net = ip->il_network; addr.s_host = ip->il_host; addr.s_imp = ip->il_imp; - hp = h_enter(addr); + if ((hp = hostlookup(addr)) == 0) + hp = hostenter(addr); /* * If IMP would block, queue until RFNM @@ -459,21 +510,22 @@ impsnd(ifp, m) * Keeping the count in the host structure * causes the packing scheme to lose too much. */ - cnt = 0, n = hp->h_q; - for (; n != (struct mbuf *)hp; n = n->m_act) - cnt++; + cnt = 0; + if (n = hp->h_q) + for (; n != hp->h_q; n = n->m_next) + cnt++; if (cnt >= 8) goto drop; /* - * Q is kept as circulare list with h_q + * Q is kept as circular list with h_q * (head) pointing to the last entry. */ if ((n = hp->h_q) == 0) - hp->h_q = m->m_act = m; + hp->h_q = m->m_next = m; else { - m->m_act = n->m_act; - hp->h_q = n->m_act = m; + m->m_next = n->m_next; + hp->h_q = n->m_next = m; } goto start; } @@ -482,6 +534,7 @@ drop: return (0); } enque: +printleader("impsnd", mtod(m, struct imp_leader *)); x = splimp(); IF_ENQUEUE(&ifp->if_snd, m); splx(x); @@ -504,20 +557,27 @@ impnoops(sc) { register i; register struct mbuf *m; - register struct imp_leader *ip; + register struct control_leader *cp; int x; +COUNT(IMPNOOPS); sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; - for (i = 0; i < IMP_DROPCNT; i++ ) { + for (i = 0; i < IMP_DROPCNT + 1; i++ ) { if ((m = m_getclr(M_DONTWAIT)) == 0) return; m->m_off = MMINOFF; - m->m_len = sizeof(struct imp_leader); - ip = mtod(m, struct imp_leader *); - ip->il_format = IMP_NFF; - ip->il_link = i; - ip->il_mtype = IMPTYPE_NOOP; + m->m_len = sizeof(struct control_leader); + cp = mtod(m, struct control_leader *); + cp->dl_format = IMP_NFF; + cp->dl_link = i; + cp->dl_mtype = IMPTYPE_NOOP; +#ifdef notdef + cp->dl_network = sc->imp_if.if_net; /* XXX */ + cp->dl_host = sc->imp_if.if_addr.s_host;/* XXX */ + cp->dl_imp = sc->imp_if.if_addr.s_imp; /* XXX */ +#endif +printleader("impnoops", cp); x = splimp(); IF_PREPEND(&sc->imp_if.if_snd, m); splx(x); @@ -525,4 +585,40 @@ impnoops(sc) if (sc->imp_cb.ic_oactive == 0) (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); } + +printleader(routine, ip) + char *routine; + register struct imp_leader *ip; +{ + printf("%s: ", routine); + printbyte((char *)ip, 12); + printf("il_format, ip->il_network, + ip->il_flags); + if (ip->il_mtype <= IMPTYPE_READY) + printf("%s,", impleaders[ip->il_mtype]); + else + printf("%x,", ip->il_mtype); + printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host, + ip->il_impno); + if (ip->il_link == IMPLINK_IP) + printf("ip,"); + else + printf("%x,", ip->il_link); + printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3); +} + +printbyte(cp, n) + register char *cp; + int n; +{ + register i, j, c; + + for (i=0; i>((1-j)*4))&0xf]); + putchar(' '); + } + putchar('\n'); +} #endif diff --git a/usr/src/sys/deprecated/netimp/if_imp.h b/usr/src/sys/deprecated/netimp/if_imp.h index f2f9c501a4..27cfc553a8 100644 --- a/usr/src/sys/deprecated/netimp/if_imp.h +++ b/usr/src/sys/deprecated/netimp/if_imp.h @@ -1,29 +1,45 @@ -/* if_imp.h 4.2 82/02/03 */ +/* if_imp.h 4.3 82/02/12 */ /* * Structure of IMP 1822 long leader. */ -struct imp_leader { - u_char il_format; /* leader format */ - u_char il_network; /* src/dest network */ - u_char il_flags; /* leader flags */ - u_char il_mtype; /* message type */ - u_char il_htype; /* handling type */ - u_char il_host; /* host number */ +struct control_leader { + u_char dl_format; /* leader format */ + u_char dl_network; /* src/dest network */ + u_char dl_flags; /* leader flags */ + u_char dl_mtype; /* message type */ + u_char dl_htype; /* handling type */ + u_char dl_host; /* host number */ union { - u_short il_short; - u_char il_char[2]; - } ilun; -#define il_imp ilun.il_short /* imp field */ -#define il_impno ilun.il_char[1] /* imp number */ -#define il_lh ilun.il_char[0] /* logical host */ - u_char il_link; /* link number */ - u_char il_subtype; /* message subtype */ + u_short dl_short; + u_char dl_char[2]; + } dlun; +#define dl_imp dlun.dl_short /* imp field */ +#define dl_impno dlun.dl_char[1] /* imp number */ +#define dl_lh dlun.dl_char[0] /* logical host */ + u_char dl_link; /* link number */ + u_char dl_subtype; /* message subtype */ +}; + +struct imp_leader { + struct control_leader il_dl; +#define il_format il_dl.dl_format +#define il_network il_dl.dl_network +#define il_flags il_dl.dl_flags +#define il_mtype il_dl.dl_mtype +#define il_htype il_dl.dl_htype +#define il_host il_dl.dl_host +#define il_imp il_dl.dl_imp +#define il_impno il_dl.dl_impno +#define il_lh il_dl.dl_lh +#define il_link il_dl.dl_link +#define il_subtype il_dl.dl_subtype u_short il_length; /* message length */ }; #define IMP_DROPCNT 2 /* # of noops from imp to ignore */ -#define IMP_MTU 1019 /* max message size (bytes) */ +/* don't use 1019 here, 'cuz odd numbers and word counts are confusing */ +#define IMP_MTU (sizeof (struct imp_leader) + 1018) /* * IMP-host flags @@ -136,3 +152,11 @@ struct impcb { #define IMPS_RESET 4 /* reset in progress */ #define IMPTV_DOWN (30*60) /* going down timer 30 secs */ + +#ifdef IMPLEADERS +char * impleaders[IMPTYPE_READY+1] = { + "DATA", "BADLEADER", "DOWN", "bad", "NOOP", "RFNM", "HOSTDEAD", + "HOSTUNREACH", "BADDATA", "INCOMPLETE", "RESET", "RETRY", + "NOTIFY", "TRYING", "READY" +}; +#endif diff --git a/usr/src/sys/deprecated/netimp/if_imphost.c b/usr/src/sys/deprecated/netimp/if_imphost.c index 3a7af5d308..6231182ab7 100644 --- a/usr/src/sys/deprecated/netimp/if_imphost.c +++ b/usr/src/sys/deprecated/netimp/if_imphost.c @@ -1,4 +1,4 @@ -/* if_imphost.c 4.1 82/02/06 */ +/* if_imphost.c 4.2 82/02/12 */ #include "imp.h" #if NIMP > 0 @@ -24,20 +24,20 @@ struct mbuf hosttable = { 0, MMINOFF }; * return a host structure (if it exists). */ struct host * -h_lookup(addr) +hostlookup(addr) struct in_addr addr; { register struct host *hp; register struct mbuf *m; register int hash = HOSTHASH(addr); -COUNT(H_LOOKUP); -printf("h_lookup(%x)\n", addr); +COUNT(HOSTLOOKUP); +printf("hostlookup(%x)\n", addr); for (m = &hosttable; m; m = m->m_next) { hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; if (hp->h_refcnt == 0) break; -printf("h_lookup: addr=%x\n", hp->h_addr.s_addr); +printf("hostlookup: addr=%x\n", hp->h_addr.s_addr); if (hp->h_addr.s_addr == addr.s_addr) return (hp); } @@ -50,20 +50,20 @@ printf("h_lookup: addr=%x\n", hp->h_addr.s_addr); * one and hook it into the host database. */ struct host * -h_enter(addr) +hostenter(addr) struct in_addr addr; { register struct mbuf *m, *mprev; register struct host *hp; register int hash = HOSTHASH(addr); -COUNT(H_ENTER); -printf("h_enter(%x)\n", addr); +COUNT(HOSTENTER); +printf("hostenter(%x)\n", addr); for (m = &hosttable; m; mprev = m, m = m->m_next) { hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; if (hp->h_refcnt == 0) break; -printf("h_enter: addr=%x\n", addr); +printf("hostenter: addr=%x\n", addr); if (hp->h_addr.s_addr == addr.s_addr) goto foundhost; } @@ -73,7 +73,7 @@ printf("h_enter: addr=%x\n", addr); * If our search ran off the end of the * chain of mbuf's, allocate another. */ -printf("h_enter: new host\n"); +printf("hostenter: new host\n"); if (m == 0) { m = m_getclr(M_DONTWAIT); if (m == 0) @@ -95,26 +95,26 @@ foundhost: * Free a reference to a host. If this causes the * host structure to be released do so. */ -h_free(addr) +hostfree(addr) struct in_addr addr; { register struct mbuf *m; register struct host *hp; register int hash = HOSTHASH(addr); -COUNT(H_FREE); -printf("h_free(%x)\n", addr); +COUNT(HOSTFREE); +printf("hostfree(%x)\n", addr); for (m = &hosttable; m; m = m->m_next) { hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; if (hp->h_refcnt == 0) return; if (hp->h_addr.s_addr == addr.s_addr) { if (--hp->h_refcnt == 0) - h_release(mtod(m, struct hmbuf *), hp); + hostrelease(mtod(m, struct hmbuf *), hp); return; } } - panic("h_free"); + panic("hostfree"); } /* @@ -122,20 +122,20 @@ printf("h_free(%x)\n", addr); * This involves clearing all packet queue's * and releasing host structures. */ -h_reset(net) +hostreset(net) int net; { register struct mbuf *m; register struct host *hp, *lp; -COUNT(H_RESET); -printf("h_reset(%x)\n", net); +COUNT(HOSTRESET); +printf("hostreset(%x)\n", net); for (m = &hosttable; m; m = m->m_next) { hp = mtod(m, struct hmbuf *)->hm_hosts; lp = hp + HPMBUF; while (hp < lp) { if (hp->h_addr.s_net == net) - h_release(mtod(m, struct hmbuf *), hp); + hostrelease(mtod(m, struct hmbuf *), hp); hp++; } } @@ -145,19 +145,21 @@ printf("h_reset(%x)\n", net); * Remove a host structure and release * any resources it's accumulated. */ -h_release(hm, hp) +hostrelease(hm, hp) struct hmbuf *hm; register struct host *hp; { register struct mbuf *m; -COUNT(H_RELEASE); -printf("h_release(%x,%x)\n", hm, hp); +COUNT(HOSTRELEASE); +printf("hostrelease(%x,%x)\n", hm, hp); /* * Discard any packets left on the waiting q */ - while (m = hp->h_q) { - hp->h_q = m->m_act; + if (m = hp->h_q) { + m = m->m_next; + hp->h_q->m_next = 0; + hp->h_q = 0; m_freem(m); } /* @@ -165,10 +167,10 @@ printf("h_release(%x,%x)\n", hm, hp); * it worth it? For now we assume not and just * handle the simple case. */ -printf("h_releasse: count=%d\n", hm->h_count); +printf("hostrelease: count=%d\n", hm->hm_count); if (--hm->hm_count || (m = dtom(hm)) == &hosttable) return; m->m_act->m_next = m->m_next; m->m_next->m_act = m->m_act; - m_freem(m); + (void) m_free(m); } diff --git a/usr/src/sys/deprecated/netimp/if_imphost.h b/usr/src/sys/deprecated/netimp/if_imphost.h index f0f1ee81c3..b97d1f6cd3 100644 --- a/usr/src/sys/deprecated/netimp/if_imphost.h +++ b/usr/src/sys/deprecated/netimp/if_imphost.h @@ -1,4 +1,4 @@ -/* if_imphost.h 4.1 82/02/06 */ +/* if_imphost.h 4.2 82/02/12 */ /* * Host structure used with IMP's. @@ -36,6 +36,6 @@ struct hmbuf { }; #ifdef KERNEL -struct host *h_lookup(); -struct host *h_enter(); +struct host *hostlookup(); +struct host *hostenter(); #endif diff --git a/usr/src/sys/deprecated/netimp/raw_imp.c b/usr/src/sys/deprecated/netimp/raw_imp.c index d29c0043af..71c7536f7e 100644 --- a/usr/src/sys/deprecated/netimp/raw_imp.c +++ b/usr/src/sys/deprecated/netimp/raw_imp.c @@ -1,4 +1,4 @@ -/* raw_imp.c 4.2 82/02/01 */ +/* raw_imp.c 4.3 82/02/12 */ #include "../h/param.h" #include "../h/mbuf.h" @@ -39,15 +39,22 @@ imp_output(m, so) /* too close to impoutput */ register struct imp_leader *ip; register struct sockaddr_in *sin; register struct rawcb *rp = sotorawcb(so); + struct ifnet *ifp; + struct control_leader *cp; COUNT(IMP_OUTPUT); /* * Verify user has supplied necessary space * for the leader and check parameters in it. */ - if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct imp_leader)) && - (m = m_pullup(m, sizeof(struct imp_leader))) == 0) - goto bad; + if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) && + (m = m_pullup(m, sizeof(struct control_leader))) == 0) + return (0); + cp = mtod(m, struct control_leader *); + if (cp->dl_mtype == IMPTYPE_DATA) + if (m->m_len < sizeof(struct imp_leader) && + (m = m_pullup(m, sizeof(struct imp_leader))) == 0) + return (0); ip = mtod(m, struct imp_leader *); if (ip->il_format != IMP_NFF) goto bad; @@ -62,13 +69,20 @@ COUNT(IMP_OUTPUT); */ for (len = 0, n = m; n; n = n->m_next) len += n->m_len; - ip->il_length = len << 3; + ip->il_length = htons(len << 3); sin = (struct sockaddr_in *)&rp->rcb_addr; ip->il_network = sin->sin_addr.s_net; ip->il_host = sin->sin_addr.s_host; ip->il_imp = sin->sin_addr.s_imp; - - return (impoutput((struct ifnet *)rp->rcb_pcb, m, PF_IMPLINK)); +printf("imp_output: net=%x, host=%x, imp=%x\n", ip->il_network, ip->il_host, +ip->il_impno); + ifp = if_ifonnetof(sin->sin_addr); + if (ifp == 0) { + ifp = if_gatewayfor(sin->sin_addr); + if (ifp == 0) + goto bad; + } + return (impoutput(ifp, m, PF_IMPLINK)); bad: m_freem(m); @@ -86,6 +100,8 @@ imp_usrreq(so, req, m, addr) caddr_t addr; { register struct rawcb *rp = sotorawcb(so); + register struct sockaddr_in *sin; + register struct ifnet *ifp; COUNT(IMP_USRREQ); if (rp == 0 && req != PRU_ATTACH) @@ -94,14 +110,11 @@ COUNT(IMP_USRREQ); switch (req) { /* - * Verify address has an interface to go with it - * and record information for use in output routine. + * Verify address has an interface to go with it. */ - case PRU_SEND: - case PRU_CONNECT: { - register struct sockaddr_in *sin; - register struct ifnet *ifp; - + case PRU_CONNECT: + if (rp->rcb_pcb) + return (EISCONN); sin = (struct sockaddr_in *)addr; ifp = if_ifonnetof(sin->sin_addr); if (ifp == 0) { @@ -111,7 +124,6 @@ COUNT(IMP_USRREQ); } rp->rcb_pcb = (caddr_t)ifp; break; - } case PRU_DISCONNECT: rp->rcb_pcb = 0; diff --git a/usr/src/sys/net/raw_cb.c b/usr/src/sys/net/raw_cb.c index d1f28a9131..9b77724671 100644 --- a/usr/src/sys/net/raw_cb.c +++ b/usr/src/sys/net/raw_cb.c @@ -1,4 +1,4 @@ -/* raw_cb.c 4.2 82/02/01 */ +/* raw_cb.c 4.3 82/02/12 */ #include "../h/param.h" #include "../h/systm.h" @@ -39,6 +39,7 @@ COUNT(RAW_ATTACH); */ if (addr) switch (addr->sa_family) { + case AF_IMPLINK: case AF_INET: { register struct sockaddr_in *sin = (struct sockaddr_in *)addr; diff --git a/usr/src/sys/vax/if/if_acc.c b/usr/src/sys/vax/if/if_acc.c index 836c1d4631..ab84f9fa1b 100644 --- a/usr/src/sys/vax/if/if_acc.c +++ b/usr/src/sys/vax/if/if_acc.c @@ -1,4 +1,4 @@ -/* if_acc.c 4.2 82/02/01 */ +/* if_acc.c 4.3 82/02/12 */ #include "acc.h" #ifdef NACC > 0 @@ -16,13 +16,13 @@ #include "../h/socket.h" #include "../h/ubareg.h" #include "../h/ubavar.h" -#include "../h/accreg.h" #include "../h/cpu.h" #include "../h/mtpr.h" #include "../h/vmmac.h" #include "../net/in.h" #include "../net/in_systm.h" #include "../net/if.h" +#include "../net/if_acc.h" #include "../net/if_imp.h" #include "../net/if_uba.h" @@ -76,19 +76,13 @@ COUNT(ACCPROBE); br = 0; cvec = br; br = cvec; accrint(0); accxint(0); #endif - addr->acc_icsr = ACC_RESET; - DELAY(500000); - addr->acc_ocsr = ACC_RESET; - DELAY(500000); - - addr->acc_ocsr = OUT_BBACK; - DELAY(500000); - addr->acc_owc = 0; - addr->acc_ocsr = ACC_IE | ACC_GO; - DELAY(500000); - addr->acc_ocsr = 0; - /* interrupt was for transmit, push back to receive vector */ - if (cvec && cvec != 0x200) + addr->icsr = ACC_RESET; DELAY(5000); + addr->ocsr = ACC_RESET; DELAY(5000); + addr->ocsr = OUT_BBACK; DELAY(5000); + addr->owc = 0; + addr->ocsr = ACC_IE | ACC_GO; DELAY(5000); + addr->ocsr = 0; + if (cvec && cvec != 0x200) /* transmit -> receive */ cvec -= 4; return (1); } @@ -110,12 +104,15 @@ accattach(ui) COUNT(ACCATTACH); if ((ifimp = (struct ifimpcb *)impattach(ui)) == 0) - panic("accattach"); /* XXX */ + panic("accattach"); sc->acc_if = &ifimp->ifimp_if; ip = &ifimp->ifimp_impcb; sc->acc_ic = ip; ip->ic_init = accinit; ip->ic_start = accstart; +#ifdef notdef + sc->acc_ifuba.ifu_flags = UBA_NEEDBDP; +#endif } /* @@ -140,59 +137,83 @@ COUNT(ACCRESET); /* * Initialize interface: clear recorded pending operations, - * and retrieve, and reinitialize UNIBUS resources. + * and retrieve, and initialize UNIBUS resources. Note + * return value is used by IMP init routine to mark IMP + * unavailable for outgoing traffic. */ accinit(unit) int unit; { - register struct acc_softc *sc = &acc_softc[unit]; - register struct uba_device *ui = accinfo[unit]; + register struct acc_softc *sc; + register struct uba_device *ui; register struct accdevice *addr; int x, info; COUNT(ACCINIT); - if (if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, - sizeof(struct imp_leader), (int)btop(IMP_MTU)) == 0) { + if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0) { + printf("acc%d: not alive\n", unit); + return (0); + } + sc = &acc_softc[unit]; + /* + * Header length is 0 since we have to passs + * the IMP leader up to the protocol interpretation + * routines. If we had the header length as + * sizeof(struct imp_leader), then the if_ routines + * would asssume we handle it on input and output. + */ + if (if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, 0, btoc(IMP_MTU)) == 0) { printf("acc%d: can't initialize\n", unit); - return; + goto down; } addr = (struct accdevice *)ui->ui_addr; /* - * Reset the imp interface. - * the delays are totally guesses + * Reset the imp interface; + * the delays are pure guesswork. */ x = spl5(); - addr->acc_icsr = ACC_RESET; - DELAY(100); - addr->acc_ocsr = ACC_RESET; - DELAY(1000); - addr->acc_ocsr = OUT_BBACK; /* reset host master ready */ - DELAY(1000); - addr->acc_ocsr = 0; - addr->acc_icsr = IN_MRDY; /* close the relay */ + addr->icsr = ACC_RESET; DELAY(5000); + addr->ocsr = ACC_RESET; DELAY(5000); + addr->ocsr = OUT_BBACK; DELAY(1000); /* reset host master ready */ + addr->ocsr = 0; splx(x); + addr->icsr = IN_MRDY; /* close the relay */ /* YECH!!! */ - while ((addr->acc_icsr & IN_HRDY) == 0 || - (addr->acc_icsr & (IN_RMR | IN_IMPBSY))) { - /* keep turning IN_RMR off */ - addr->acc_icsr = IN_MRDY; - sleep((caddr_t)&lbolt, PZERO); /* ??? */ + x = 500; + while (x-- > 0) { + if ((addr->icsr & IN_HRDY) || + (addr->icsr & (IN_RMR | IN_IMPBSY) == 0)) + break; + addr->icsr = IN_MRDY; DELAY(5000); /* keep turning IN_RMR off */ + } + if (x <= 0) { + printf("acc%d: imp doesn't respond, icsr=%b\n", unit, + addr->icsr, ACC_INBITS); + goto down; } /* * Put up a read. We can't restart any outstanding writes * until we're back in synch with the IMP (i.e. we've flushed * the NOOPs it throws at us). + * Note: IMP_MTU includes the leader. */ x = spl5(); info = sc->acc_ifuba.ifu_r.ifrw_info; - addr->acc_iba = (u_short)info; - addr->acc_iwc = -(sizeof(struct imp_leader) + IMP_MTU) >> 1; - addr->acc_icsr = + addr->iba = (u_short)info; + addr->iwc = -(IMP_MTU >> 1); +#ifdef LOOPBACK + addr->ocsr |= OUT_BBACK; +#endif + addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; splx(x); + return (1); +down: + ui->ui_alive = 0; + return (0); } /* @@ -206,9 +227,11 @@ accstart(dev) register struct acc_softc *sc = &acc_softc[unit]; register struct accdevice *addr; struct mbuf *m; + struct imp_leader *ip; u_short cmd; COUNT(ACCSTART); +printf("accstart: active=%d\n", sc->acc_ic->ic_oactive); if (sc->acc_ic->ic_oactive) goto restart; @@ -218,24 +241,30 @@ COUNT(ACCSTART); * requeusts, just return. */ IF_DEQUEUE(&sc->acc_if->if_snd, m); +printf("accstart: dequeue m=%x\n", m); if (m == 0) { sc->acc_ic->ic_oactive = 0; return; } sc->acc_olen = if_wubaput(&sc->acc_ifuba, m); +printf("accstart: olen=%d\n", sc->acc_olen); restart: /* - * Have request mapped to UNIBUS for transmission. - * Purge any stale data from the BDP, and start the output. + * Have request mapped to UNIBUS for + * transmission; start the output. */ - UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_w.ifrw_bdp); + if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP) + UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_w.ifrw_bdp); addr = (struct accdevice *)ui->ui_addr; info = sc->acc_ifuba.ifu_w.ifrw_info; - addr->acc_oba = (u_short)info; - addr->acc_owc = -((sc->acc_olen + 1) >> 1); + addr->oba = (u_short)info; + addr->owc = -((sc->acc_olen + 1) >> 1); cmd = ACC_IE | OUT_ENLB | ((info & 0x30000) >> 12) | ACC_GO; - addr->acc_ocsr = cmd; +#ifdef LOOPBACK + cmd |= OUT_BBACK; +#endif + addr->ocsr = cmd; sc->acc_ic->ic_oactive = 1; } @@ -250,24 +279,24 @@ accxint(unit) COUNT(ACCXINT); if (sc->acc_ic->ic_oactive == 0) { - printf("acc%d: stray send interrupt\n", unit); + printf("acc%d: stray xmit interrupt\n", unit); return; } addr = (struct accdevice *)ui->ui_addr; +printf("accxint: ocsr=%b\n", addr->ocsr, ACC_OUTBITS); sc->acc_if->if_opackets++; sc->acc_ic->ic_oactive = 0; - if (addr->acc_ocsr & ACC_ERR) { - printf("acc%d: send error, csr=%b\n", unit, - addr->acc_ocsr, ACC_OUTBITS); + if (addr->ocsr & ACC_ERR) { + printf("acc%d: output error, csr=%b\n", unit, + addr->ocsr, ACC_OUTBITS); sc->acc_if->if_oerrors++; } - if (sc->acc_if->if_snd.ifq_head == 0) { - if (sc->acc_ifuba.ifu_xtofree) { - m_freem(sc->acc_ifuba.ifu_xtofree); - sc->acc_ifuba.ifu_xtofree = 0; - } - return; + if (sc->acc_ifuba.ifu_xtofree) { + m_freem(sc->acc_ifuba.ifu_xtofree); + sc->acc_ifuba.ifu_xtofree = 0; } + if (sc->acc_if->if_snd.ifq_head == 0) + return; accstart(unit); } @@ -288,30 +317,39 @@ COUNT(ACCRINT); /* * Purge BDP; flush message if error indicated. */ - UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_r.ifrw_bdp); + if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP) + UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_r.ifrw_bdp); addr = (struct accdevice *)accinfo[unit]->ui_addr; - if (addr->acc_icsr & ACC_ERR) { - printf("acc%d: recv error, csr=%b\n", unit, - addr->acc_icsr, ACC_INBITS); +printf("accrint: icsr=%b, flush=%d\n", addr->icsr, ACC_INBITS, sc->acc_flush); + if (addr->icsr & ACC_ERR) { + printf("acc%d: input error, csr=%b\n", unit, + addr->icsr, ACC_INBITS); sc->acc_if->if_ierrors++; sc->acc_flush = 1; } if (sc->acc_flush) { - if (addr->acc_icsr & IN_EOM) + if (addr->icsr & IN_EOM) sc->acc_flush = 0; goto setup; } - len = sizeof(struct imp_leader) + (addr->acc_iwc << 1); + len = IMP_MTU + (addr->iwc << 1); +printf("accrint: len=%d\n", len); + if (len < 0 || len > IMP_MTU) { + printf("acc%d: bad length=%d\n", len); + sc->acc_if->if_ierrors++; + goto setup; + } /* * The last parameter is always 0 since using * trailers on the ARPAnet is insane. */ m = if_rubaget(&sc->acc_ifuba, len, 0); +printf("accrint: m=%x\n", m); if (m == 0) goto setup; - if ((addr->acc_icsr & IN_EOM) == 0) { + if ((addr->icsr & IN_EOM) == 0) { if (sc->acc_iq) m_cat(sc->acc_iq, m); else @@ -319,7 +357,9 @@ COUNT(ACCRINT); goto setup; } /* adjust message length for padding. */ +#ifdef notdef m->m_len -= 2; +#endif if (sc->acc_iq) { m_cat(sc->acc_iq, m); m = sc->acc_iq; @@ -332,9 +372,9 @@ setup: * Setup for next message. */ info = sc->acc_ifuba.ifu_r.ifrw_info; - addr->acc_iba = (u_short)info; - addr->acc_iwc = - (sizeof(struct imp_leader) + IMP_MTU) >> 1; - addr->acc_icsr = + addr->iba = (u_short)info; + addr->iwc = -(IMP_MTU >> 1); + addr->icsr = IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO; } #endif -- 2.20.1