X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/f1b2fa5b8a62e80603e6c83b87eaf0b06db3818e..9c8692e90cb380483289c33fb78ee1fabddf3f67:/usr/src/sys/vax/if/if_en.c diff --git a/usr/src/sys/vax/if/if_en.c b/usr/src/sys/vax/if/if_en.c index 9048145123..4df49c8fbf 100644 --- a/usr/src/sys/vax/if/if_en.c +++ b/usr/src/sys/vax/if/if_en.c @@ -1,4 +1,4 @@ -/* if_en.c 4.15 81/11/29 */ +/* if_en.c 4.43 82/03/19 */ #include "en.h" @@ -26,14 +26,15 @@ #include "../net/if_uba.h" #include "../net/ip.h" #include "../net/ip_var.h" +#include "../net/pup.h" -#define ENMTU 1024 +#define ENMTU (1024+512) int enprobe(), enattach(), enrint(), enxint(), encollide(); struct uba_device *eninfo[NEN]; u_short enstd[] = { 0 }; struct uba_driver endriver = - { enprobe, 0, enattach, 0, enstd, "es", eninfo }; + { enprobe, 0, enattach, 0, enstd, "en", eninfo }; #define ENUNIT(x) minor(x) int eninit(),enoutput(),enreset(); @@ -67,7 +68,7 @@ struct en_softc { enprobe(reg) caddr_t reg; { - register int br, cvec; + register int br, cvec; /* r11, r10 value-result */ register struct endevice *addr = (struct endevice *)reg; COUNT(ENPROBE); @@ -96,15 +97,26 @@ enattach(ui) COUNT(ENATTACH); es->es_if.if_unit = ui->ui_unit; + es->es_if.if_name = "en"; es->es_if.if_mtu = ENMTU; es->es_if.if_net = ui->ui_flags; es->es_if.if_host[0] = - ~(((struct endevice *)eninfo[ui->ui_unit])->en_addr) & 0xff; + (~(((struct endevice *)eninfo[ui->ui_unit]->ui_addr)->en_addr)) & 0xff; +#ifdef ENKLUDGE + if (es->es_if.if_net == 10) { + es->es_if.if_host[0] <<= 16; + es->es_if.if_host[0] |= 0x4e; + } +#endif es->es_if.if_addr = if_makeaddr(es->es_if.if_net, es->es_if.if_host[0]); - es->es_if.if_output = enoutput; + es->es_if.if_broadaddr = + if_makeaddr(es->es_if.if_net, 0); es->es_if.if_init = eninit; + es->es_if.if_output = enoutput; es->es_if.if_ubareset = enreset; + es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16; + if_attach(&es->es_if); } /* @@ -117,12 +129,10 @@ enreset(unit, uban) register struct uba_device *ui; COUNT(ENRESET); - if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) { - printf("es%d: not alive\n", unit); - return; - } - if (ui->ui_ubanum != uban) + if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || + ui->ui_ubanum != uban) return; + printf(" en%d", unit); eninit(unit); } @@ -133,26 +143,28 @@ COUNT(ENRESET); eninit(unit) int unit; { - register struct uba_device *ui; + register struct en_softc *es = &en_softc[unit]; + register struct uba_device *ui = eninfo[unit]; register struct endevice *addr; - register struct en_softc *es; int s; - es = &en_softc[unit]; - ui = eninfo[unit]; if (if_ubainit(&es->es_ifuba, ui->ui_ubanum, - sizeof (struct en_header), (int)btop(ENMTU)) == 0) { - printf("es%d: can't initialize\n", unit); + sizeof (struct en_header), (int)btoc(ENMTU)) == 0) { + printf("en%d: can't initialize\n", unit); return; } addr = (struct endevice *)ui->ui_addr; addr->en_istat = addr->en_ostat = 0; /* - * Hang pending read, start any writes. + * Hang a receive and start any + * pending writes by faking a transmit complete. */ s = splimp(); - enstart(unit); + addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; + addr->en_iwc = -(sizeof (struct en_header) + ENMTU) >> 1; + addr->en_istat = EN_IEN|EN_GO; + es->es_oactive = 1; enxint(unit); splx(s); } @@ -170,17 +182,14 @@ int enlastdel = 25; enstart(dev) dev_t dev; { - int unit; - struct uba_device *ui; + int unit = ENUNIT(dev); + struct uba_device *ui = eninfo[unit]; + register struct en_softc *es = &en_softc[unit]; register struct endevice *addr; - register struct en_softc *es; struct mbuf *m; int dest; COUNT(ENSTART); - unit = ENUNIT(dev); - ui = eninfo[unit]; - es = &en_softc[unit]; if (es->es_oactive) goto restart; @@ -194,6 +203,7 @@ COUNT(ENSTART); es->es_oactive = 0; return; } + dest = mtod(m, struct en_header *)->en_dhost; es->es_olen = if_wubaput(&es->es_ifuba, m); /* @@ -202,7 +212,6 @@ COUNT(ENSTART); * receiver, enforce a small delay (about 1ms) in interface * on successive packets sent to same host. */ - dest = mtod(m, struct en_header *)->en_dhost; if (es->es_lastx && es->es_lastx == dest) es->es_delay = enlastdel; else @@ -215,7 +224,7 @@ restart: */ UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp); addr = (struct endevice *)ui->ui_addr; - addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_addr; + addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info; addr->en_odelay = es->es_delay; addr->en_owc = -((es->es_olen + 1) >> 1); addr->en_ostat = EN_IEN|EN_GO; @@ -229,22 +238,28 @@ restart: enxint(unit) int unit; { - register struct endevice *addr; - register struct uba_device *ui; - register struct en_softc *es; + register struct uba_device *ui = eninfo[unit]; + register struct en_softc *es = &en_softc[unit]; + register struct endevice *addr = (struct endevice *)ui->ui_addr; COUNT(ENXINT); - ui = eninfo[unit]; - es = &en_softc[unit]; if (es->es_oactive == 0) return; - addr = (struct endevice *)ui->ui_addr; - es = &en_softc[unit]; + if (es->es_mask && (addr->en_ostat&EN_OERROR)) { + es->es_if.if_oerrors++; + if (es->es_if.if_oerrors % 100 == 0) + printf("en%d: += 100 output errors\n", unit); + endocoll(unit); + return; + } + es->es_if.if_opackets++; es->es_oactive = 0; es->es_delay = 0; es->es_mask = ~0; - if (addr->en_ostat&EN_OERROR) - printf("es%d: output error\n", unit); + if (es->es_ifuba.ifu_xtofree) { + m_freem(es->es_ifuba.ifu_xtofree); + es->es_ifuba.ifu_xtofree = 0; + } if (es->es_if.if_snd.ifq_head == 0) { es->es_lastx = 0; return; @@ -260,23 +275,42 @@ COUNT(ENXINT); encollide(unit) int unit; { - register struct en_softc *es; + struct en_softc *es = &en_softc[unit]; COUNT(ENCOLLIDE); - es = &en_softc[unit]; es->es_if.if_collisions++; if (es->es_oactive == 0) return; + endocoll(unit); +} + +endocoll(unit) + int unit; +{ + register struct en_softc *es = &en_softc[unit]; + + /* + * Es_mask is a 16 bit number with n low zero bits, with + * n the number of backoffs. When es_mask is 0 we have + * backed off 16 times, and give up. + */ if (es->es_mask == 0) { - printf("es%d: send error\n", unit); + printf("en%d: send error\n", unit); enxint(unit); - } else { - es->es_mask <<= 1; - es->es_delay = mfpr(ICR) &~ es->es_mask; - enstart(unit); + return; } + /* + * Another backoff. Restart with delay based on n low bits + * of the interval timer. + */ + es->es_mask <<= 1; + es->es_delay = mfpr(ICR) &~ es->es_mask; + enstart(unit); } +struct sockaddr_pup pupsrc = { AF_PUP }; +struct sockaddr_pup pupdst = { AF_PUP }; +struct sockproto pupproto = { PF_PUP }; /* * Ethernet interface receiver interrupt. * If input error just drop packet. @@ -289,25 +323,25 @@ COUNT(ENCOLLIDE); enrint(unit) int unit; { - struct endevice *addr; - register struct en_softc *es; - struct en_header *en; + register struct en_softc *es = &en_softc[unit]; + struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr; + register struct en_header *en; struct mbuf *m; - struct ifqueue *inq; - register int len; + int len; + register struct ifqueue *inq; int off; COUNT(ENRINT); - es = &en_softc[unit]; - addr = (struct endevice *)eninfo[unit]->ui_addr; + es->es_if.if_ipackets++; /* - * Purge BDP; drop error packets. + * Purge BDP; drop if input error indicated. */ UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp); if (addr->en_istat&EN_IERROR) { es->es_if.if_ierrors++; - printf("es%d: input error\n", unit); + if (es->es_if.if_ierrors % 100 == 0) + printf("en%d: += 100 input errors\n", unit); goto setup; } @@ -322,8 +356,9 @@ COUNT(ENRINT); if (en->en_type >= ENPUP_TRAIL && en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) { off = (en->en_type - ENPUP_TRAIL) * 512; + if (off >= ENMTU) + goto setup; /* sanity */ en->en_type = *endataaddr(en, off, u_short *); - off += 2; } else off = 0; @@ -335,14 +370,21 @@ COUNT(ENRINT); #ifdef INET case ENPUP_IPTYPE: - len = endataaddr(en, off, struct ip *)->ip_len; - setipintr(); - inq = &ipintrq; + len = htons((u_short)endataaddr(en, off ? off+2 : 0, struct ip *)->ip_len); + if (off) + len += 2; break; #endif - +#ifdef PUP + case ENPUP_PUPTYPE: + len = endataaddr(en, off, struct pup_header *)->pup_length; + if (off) + len -= 2; + break; +#endif + default: - printf("en%d: unknow pkt type 0x%x\n", en->en_type); + printf("en%d: unknown pkt type 0x%x\n", unit, en->en_type); goto setup; } if (len == 0) @@ -352,15 +394,39 @@ COUNT(ENRINT); * Pull packet off interface. Off is nonzero if packet * has trailing header; if_rubaget will then force this header * information to be at the front, but we still have to drop - * the two-byte type which is at the front of the trailer data - * (which we ``consumed'' above). + * the two-byte type which is at the front of any trailer data. */ m = if_rubaget(&es->es_ifuba, len, off); + if (m == 0) + goto setup; if (off) { m->m_off += 2; m->m_len -= 2; } - IF_ENQUEUE(inq, m); + switch (en->en_type) { + +#ifdef INET + case ENPUP_IPTYPE: + schednetisr(NETISR_IP); + inq = &ipintrq; + break; +#endif + case ENPUP_PUPTYPE: { + struct pup_header *pup = mtod(m, struct pup_header *); + + pupproto.sp_protocol = pup->pup_type; + pupdst.spup_addr = pup->pup_dport; + pupsrc.spup_addr = pup->pup_sport; + raw_input(m, &pupproto, (struct sockaddr *)&pupdst, + (struct sockaddr *)&pupsrc); + goto setup; + } + } + if (IF_QFULL(inq)) { + IF_DROP(inq); + (void) m_freem(m); + } else + IF_ENQUEUE(inq, m); setup: /* @@ -382,32 +448,55 @@ enoutput(ifp, m0, pf) struct mbuf *m0; int pf; { - int type, dest; + int type, dest, s, off; register struct mbuf *m = m0; register struct en_header *en; - int s; +COUNT(ENOUTPUT); switch (pf) { #ifdef INET case PF_INET: { register struct ip *ip = mtod(m0, struct ip *); - int off; +#ifndef ENKLUDGE dest = ip->ip_dst.s_addr >> 24; - off = ip->ip_len - m->m_len; - if (off && off % 512 == 0 && m->m_off >= MMINOFF + 2) { +#else + dest = (ip->ip_dst.s_addr >> 8) & 0xff; +#endif + off = ntohs((u_short)ip->ip_len) - m->m_len; +#ifndef ENKLUDGE + if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2) { type = ENPUP_TRAIL + (off>>9); m->m_off -= 2; m->m_len += 2; *mtod(m, u_short *) = ENPUP_IPTYPE; goto gottrailertype; } +#endif type = ENPUP_IPTYPE; off = 0; goto gottype; } #endif +#ifdef PUP + case PF_PUP: { + register struct pup_header *pup = mtod(m, struct pup_header *); + + dest = pup->pup_dhost; + off = pup->pup_length - m->m_len; + if (off > 0 && (off & 0x1ff) == 0 && m->m_off >= MMINOFF + 2) { + type = ENPUP_TRAIL + (off>>9); + m->m_off -= 2; + m->m_len += 2; + *mtod(m, u_short *) = ENPUP_PUPTYPE; + goto gottrailertype; + } + type = ENPUP_PUPTYPE; + off = 0; + goto gottype; + } +#endif default: printf("en%d: can't encapsulate pf%d\n", ifp->if_unit, pf); @@ -415,25 +504,26 @@ enoutput(ifp, m0, pf) return (0); } +gottrailertype: /* * Packet to be sent as trailer: move first packet * (control information) to end of chain. */ -gottrailertype: 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 net header. If no space in first mbuf, * allocate another. */ -gottype: - m0 = m; - if (MMINOFF + sizeof (struct en_header) > m->m_off) { - m = m_get(0); + if (m->m_off > MMAXOFF || + MMINOFF + sizeof (struct en_header) > m->m_off) { + m = m_get(M_DONTWAIT); if (m == 0) { m_freem(m0); return (0); @@ -442,7 +532,6 @@ gottype: m->m_off = MMINOFF; m->m_len = sizeof (struct en_header); } else { - m = m0; m->m_off -= sizeof (struct en_header); m->m_len += sizeof (struct en_header); } @@ -456,9 +545,15 @@ gottype: * not yet active. */ s = splimp(); + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + m_freem(m); + splx(s); + return (0); + } IF_ENQUEUE(&ifp->if_snd, m); - splx(s); if (en_softc[ifp->if_unit].es_oactive == 0) enstart(ifp->if_unit); + splx(s); return (1); }