-/* if_imp.c 4.3 82/02/01 */
+/* if_imp.c 4.4 82/02/12 */
#include "imp.h"
#if NIMP > 0
*
* 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"
#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"
* 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.
*/
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];
/*
"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.
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);
{
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 };
* 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.
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;
}
* 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;
/*
* 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;
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;
* 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
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;
* 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;
/*
*/
case IMPTYPE_RESET:
imperr(sc, "interface reset");
- sc->imp_state = IMPS_RESET;
impnoops(sc);
goto drop;
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);
struct imp_softc *sc;
{
sc->imp_state = IMPS_DOWN;
+ imperr(sc, "marked down");
/* notify protocols with messages waiting? */
}
{
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) {
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
}
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:
struct impcb *icp;
int x;
+COUNT(IMPSND);
+printf("impsnd(%x, %x)\n", ifp, m);
ip = mtod(m, struct imp_leader *);
/*
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
* 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;
}
return (0);
}
enque:
+printleader("impsnd", mtod(m, struct imp_leader *));
x = splimp();
IF_ENQUEUE(&ifp->if_snd, m);
splx(x);
{
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);
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("<fmt=%x,net=%x,flags=%x,mtype=", ip->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<n; i++) {
+ c = *cp++;
+ for (j=0; j<2; j++)
+ putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]);
+ putchar(' ');
+ }
+ putchar('\n');
+}
#endif
-/* 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
#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
-/* if_imphost.c 4.1 82/02/06 */
+/* if_imphost.c 4.2 82/02/12 */
#include "imp.h"
#if NIMP > 0
* 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);
}
* 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;
}
* 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)
* 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");
}
/*
* 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++;
}
}
* 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);
}
/*
* 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);
}
-/* if_imphost.h 4.1 82/02/06 */
+/* if_imphost.h 4.2 82/02/12 */
/*
* Host structure used with IMP's.
};
#ifdef KERNEL
-struct host *h_lookup();
-struct host *h_enter();
+struct host *hostlookup();
+struct host *hostenter();
#endif
-/* raw_imp.c 4.2 82/02/01 */
+/* raw_imp.c 4.3 82/02/12 */
#include "../h/param.h"
#include "../h/mbuf.h"
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;
*/
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);
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)
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) {
}
rp->rcb_pcb = (caddr_t)ifp;
break;
- }
case PRU_DISCONNECT:
rp->rcb_pcb = 0;
-/* raw_cb.c 4.2 82/02/01 */
+/* raw_cb.c 4.3 82/02/12 */
#include "../h/param.h"
#include "../h/systm.h"
*/
if (addr) switch (addr->sa_family) {
+ case AF_IMPLINK:
case AF_INET: {
register struct sockaddr_in *sin = (struct sockaddr_in *)addr;
-/* if_acc.c 4.2 82/02/01 */
+/* if_acc.c 4.3 82/02/12 */
#include "acc.h"
#ifdef NACC > 0
#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"
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);
}
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
}
/*
/*
* 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);
}
/*
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;
* 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;
}
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);
}
/*
* 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
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;
* 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