1*5083Swnj /* if_en.c 4.14 81/11/26 */ 24686Swnj 34686Swnj #include "en.h" 44686Swnj /* 54686Swnj * Ethernet interface driver 64686Swnj */ 74686Swnj 84686Swnj #include "../h/param.h" 94686Swnj #include "../h/systm.h" 104686Swnj #include "../h/mbuf.h" 114686Swnj #include "../h/pte.h" 124686Swnj #include "../h/buf.h" 13*5083Swnj #include "../h/protosw.h" 14*5083Swnj #include "../h/socket.h" 154686Swnj #include "../h/ubareg.h" 164686Swnj #include "../h/ubavar.h" 174686Swnj #include "../h/enreg.h" 18*5083Swnj #include "../h/cpu.h" 194686Swnj #include "../h/mtpr.h" 20*5083Swnj #include "../h/vmmac.h" 21*5083Swnj #include "../net/in.h" 22*5083Swnj #include "../net/in_systm.h" 23*5083Swnj #include "../net/if.h" 24*5083Swnj #include "../net/if_en.h" 25*5083Swnj #include "../net/if_uba.h" 26*5083Swnj #include "../net/ip.h" 27*5083Swnj #include "../net/ip_var.h" 284686Swnj 29*5083Swnj #define ENMTU 1024 30*5083Swnj 314686Swnj int enprobe(), enattach(), enrint(), enxint(), encollide(); 324686Swnj struct uba_device *eninfo[NEN]; 334686Swnj u_short enstd[] = { 0 }; 344686Swnj struct uba_driver endriver = 35*5083Swnj { enprobe, 0, enattach, 0, enstd, "es", eninfo }; 364686Swnj #define ENUNIT(x) minor(x) 374686Swnj 38*5083Swnj struct en_softc { 39*5083Swnj struct ifnet *es_if; 40*5083Swnj struct ifuba *es_ifuba; 41*5083Swnj short es_delay; 42*5083Swnj short es_mask; 43*5083Swnj u_char es_addr; 44*5083Swnj u_char es_lastx; 45*5083Swnj short es_oactive; 46*5083Swnj short es_olen; 47*5083Swnj } en_softc[NEN]; 484686Swnj 494686Swnj enprobe(reg) 504686Swnj caddr_t reg; 514686Swnj { 524686Swnj register int br, cvec; 534686Swnj register struct endevice *addr = (struct endevice *)reg; 544686Swnj 55*5083Swnj COUNT(ENPROBE); 564686Swnj #ifdef lint 574686Swnj br = 0; cvec = br; br = cvec; 584922Swnj enrint(0); enxint(0); encollide(0); 594686Swnj #endif 604686Swnj addr->en_istat = 0; 614686Swnj addr->en_owc = -1; 624686Swnj addr->en_oba = 0; 634771Swnj addr->en_ostat = EN_IEN|EN_GO; 644686Swnj DELAY(100000); 654686Swnj addr->en_ostat = 0; 664686Swnj return (1); 674686Swnj } 684686Swnj 694906Swnj /*ARGSUSED*/ 704686Swnj enattach(ui) 714686Swnj struct uba_device *ui; 724686Swnj { 734688Swnj 74*5083Swnj COUNT(ENATTACH); 75*5083Swnj eninit(ui->ui_unit); 76*5083Swnj /* net initialization, based on ui->ui_flags?!? */ 774686Swnj } 784686Swnj 794688Swnj eninit(unit) 804686Swnj int unit; 81*5083Swnj { 82*5083Swnj register struct uba_device *ui; 834686Swnj register struct endevice *addr; 84*5083Swnj register struct en_softc *es; 854686Swnj 86*5083Swnj COUNT(ENINIT); 874686Swnj if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) { 88*5083Swnj printf("es%d: not alive\n", unit); 894686Swnj return; 904686Swnj } 91*5083Swnj es = &en_softc[unit]; 92*5083Swnj if (if_ubainit(es->es_ifuba, ui->ui_ubanum, 93*5083Swnj sizeof (struct en_header), btop(ENMTU)) == 0) { 94*5083Swnj printf("es%d: can't initialize\n", unit); 95*5083Swnj return; 964686Swnj } 974686Swnj addr = (struct endevice *)ui->ui_addr; 98*5083Swnj addr->en_istat = addr->en_ostat = 0; 994686Swnj } 1004686Swnj 1014686Swnj enreset(uban) 1024686Swnj int uban; 1034686Swnj { 1044686Swnj register int unit; 1054686Swnj struct uba_device *ui; 1064686Swnj 107*5083Swnj COUNT(ENRESET); 1084686Swnj for (unit = 0; unit < NEN; unit++) { 1094686Swnj ui = eninfo[unit]; 1104686Swnj if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 1114686Swnj continue; 1124688Swnj eninit(unit); 113*5083Swnj printf("es%d ", unit); 1144686Swnj } 1154686Swnj } 1164686Swnj 1174717Swnj int enlastdel = 25; 118*5083Swnj 1194688Swnj enstart(dev) 1204686Swnj dev_t dev; 1214686Swnj { 1224686Swnj int unit; 1234686Swnj struct uba_device *ui; 124*5083Swnj register struct endevice *addr; 125*5083Swnj register struct en_softc *es; 126*5083Swnj register struct ifuba *ifu; 127*5083Swnj struct mbuf *m; 128*5083Swnj int dest; 1294688Swnj COUNT(ENSTART); 1304686Swnj 1314686Swnj unit = ENUNIT(dev); 1324686Swnj ui = eninfo[unit]; 133*5083Swnj es = &en_softc[unit]; 134*5083Swnj if (es->es_oactive) 135*5083Swnj goto restart; 136*5083Swnj IF_DEQUEUE(&es->es_if->if_snd, m); 137*5083Swnj if (m == 0) { 138*5083Swnj es->es_oactive = 0; 1394686Swnj return; 1404686Swnj } 141*5083Swnj dest = mtod(m, struct en_header *)->en_dhost; 142*5083Swnj es->es_olen = if_wubaput(&es->es_ifuba, m); 143*5083Swnj if (es->es_lastx && es->es_lastx == dest) 144*5083Swnj es->es_delay = enlastdel; 145*5083Swnj else 146*5083Swnj es->es_lastx = dest; 147*5083Swnj restart: 148*5083Swnj ifu = es->es_ifuba; 149*5083Swnj UBAPURGE(ifu->ifu_uba, ifu->ifu_w.ifrw_bdp); 1504686Swnj addr = (struct endevice *)ui->ui_addr; 151*5083Swnj addr->en_oba = (int)ifu->ifu_w.ifrw_addr; 152*5083Swnj addr->en_odelay = es->es_delay; 153*5083Swnj addr->en_owc = -((es->es_olen + 1) >> 1); 1544771Swnj addr->en_ostat = EN_IEN|EN_GO; 155*5083Swnj es->es_oactive = 1; 1564686Swnj } 1574686Swnj 1584686Swnj enxint(unit) 1594686Swnj int unit; 1604686Swnj { 1614686Swnj register struct endevice *addr; 1624686Swnj register struct uba_device *ui; 163*5083Swnj register struct en_softc *es; 1644686Swnj COUNT(ENXINT); 1654686Swnj 1664686Swnj ui = eninfo[unit]; 167*5083Swnj es = &en_softc[unit]; 168*5083Swnj if (es->es_oactive == 0) 169*5083Swnj return; 1704686Swnj addr = (struct endevice *)ui->ui_addr; 171*5083Swnj es = &en_softc[unit]; 172*5083Swnj es->es_oactive = 0; 173*5083Swnj es->es_delay = 0; 174*5083Swnj es->es_mask = ~0; 175*5083Swnj if (addr->en_ostat&EN_OERROR) 176*5083Swnj printf("es%d: output error\n", unit); 177*5083Swnj if (es->es_if->if_snd.ifq_head == 0) { 178*5083Swnj es->es_lastx = 0; 1794686Swnj return; 1804686Swnj } 181*5083Swnj enstart(unit); 1824686Swnj } 1834686Swnj 1844686Swnj encollide(unit) 1854686Swnj int unit; 1864686Swnj { 187*5083Swnj register struct en_softc *es; 1884686Swnj COUNT(ENCOLLIDE); 1894686Swnj 190*5083Swnj es = &en_softc[unit]; 191*5083Swnj es->es_if->if_collisions++; 192*5083Swnj if (es->es_oactive == 0) 1934686Swnj return; 194*5083Swnj if (es->es_mask == 0) { 195*5083Swnj printf("es%d: send error\n", unit); 196*5083Swnj enxint(unit); 1974686Swnj } else { 198*5083Swnj es->es_mask <<= 1; 199*5083Swnj es->es_delay = mfpr(ICR) &~ es->es_mask; 200*5083Swnj enstart(unit); 2014686Swnj } 2024686Swnj } 2034686Swnj 2044686Swnj enrint(unit) 2054686Swnj int unit; 2064686Swnj { 207*5083Swnj struct endevice *addr; 208*5083Swnj register struct en_softc *es; 209*5083Swnj register struct ifuba *ifu; 210*5083Swnj struct en_header *en; 211*5083Swnj struct mbuf *m; 212*5083Swnj struct ifqueue *inq; 2134686Swnj register int len; 214*5083Swnj int off; 2154686Swnj COUNT(ENRINT); 2164686Swnj 217*5083Swnj addr = (struct endevice *)eninfo[unit]->ui_addr; 2184771Swnj if (addr->en_istat&EN_IERROR) { 219*5083Swnj es->es_if->if_ierrors++; 220*5083Swnj printf("es%d: input error\n", unit); 221*5083Swnj goto setup; 2224686Swnj } 223*5083Swnj ifu = en_softc[unit].es_ifuba; 224*5083Swnj UBAPURGE(ifu->ifu_uba, ifu->ifu_r.ifrw_bdp); 225*5083Swnj en = (struct en_header *)(ifu->ifu_r.ifrw_addr); 226*5083Swnj #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) 227*5083Swnj if (en->en_type >= ENPUP_TRAIL && 228*5083Swnj en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) { 229*5083Swnj off = (en->en_type - ENPUP_TRAIL) * 512; 230*5083Swnj en->en_type = *endataaddr(en, off, u_short *); 231*5083Swnj off += 2; 232*5083Swnj } else 233*5083Swnj off = 0; 234*5083Swnj switch (en->en_type) { 235*5083Swnj 236*5083Swnj #ifdef INET 237*5083Swnj case ENPUP_IPTYPE: 238*5083Swnj len = endataaddr(en, off, struct ip *)->ip_len; 239*5083Swnj setipintr(); 240*5083Swnj inq = &ipintrq; 2414686Swnj break; 2424686Swnj #endif 2434686Swnj 244*5083Swnj default: 245*5083Swnj printf("en%d: unknow pkt type 0x%x\n", en->en_type); 246*5083Swnj goto setup; 2474686Swnj } 248*5083Swnj if (len == 0) 249*5083Swnj goto setup; 250*5083Swnj m = if_rubaget(&ifu->ifu_r, len, off); 251*5083Swnj IF_ENQUEUE(inq, m); 2524688Swnj setup: 253*5083Swnj addr->en_iba = es->es_ifuba->ifu_r.ifrw_info; 254*5083Swnj addr->en_iwc = -(sizeof (struct en_header) + ENMTU) >> 1; 2554771Swnj addr->en_istat = EN_IEN|EN_GO; 2564688Swnj } 2574686Swnj 258*5083Swnj /* 259*5083Swnj * Ethernet output routine. 260*5083Swnj * Encapsulate a packet of type family for the local net. 261*5083Swnj */ 262*5083Swnj enoutput(ifp, m0, pf) 263*5083Swnj struct ifnet *ifp; 264*5083Swnj struct mbuf *m0; 265*5083Swnj int pf; 2664686Swnj { 267*5083Swnj int type, dest; 268*5083Swnj register struct mbuf *m; 269*5083Swnj register struct en_header *en; 270*5083Swnj int s; 2714686Swnj 272*5083Swnj switch (pf) { 273*5083Swnj 274*5083Swnj #ifdef INET 275*5083Swnj case PF_INET: { 276*5083Swnj register struct ip *ip = mtod(m0, struct ip *); 277*5083Swnj int off; 278*5083Swnj 279*5083Swnj off = ip->ip_len - (ip->ip_hl << 2); 280*5083Swnj if (off && off % 512 == 0 && m0->m_off >= MMINOFF + 2) { 281*5083Swnj type = ENPUP_TRAIL + (off>>9); 282*5083Swnj m0->m_off -= 2; 283*5083Swnj m0->m_len += 2; 284*5083Swnj *mtod(m0, u_short *) = ENPUP_IPTYPE; 285*5083Swnj } else { 286*5083Swnj type = ENPUP_IPTYPE; 287*5083Swnj off = 0; 288*5083Swnj } 289*5083Swnj dest = ip->ip_dst.s_addr >> 24; 290*5083Swnj } 291*5083Swnj break; 292*5083Swnj #endif 293*5083Swnj 294*5083Swnj default: 295*5083Swnj printf("en%d: can't encapsulate pf%d\n", ifp->if_unit, pf); 296*5083Swnj m_freem(m0); 297*5083Swnj return (0); 2984686Swnj } 299*5083Swnj if (MMINOFF + sizeof (struct en_header) > m0->m_off) { 300*5083Swnj m = m_get(0); 301*5083Swnj if (m == 0) { 302*5083Swnj m_freem(m0); 303*5083Swnj return (0); 304*5083Swnj } 305*5083Swnj m->m_next = m0; 306*5083Swnj m->m_off = MMINOFF; 307*5083Swnj m->m_len = sizeof (struct en_header); 308*5083Swnj } else { 309*5083Swnj m = m0; 310*5083Swnj m->m_off -= sizeof (struct en_header); 311*5083Swnj m->m_len += sizeof (struct en_header); 312*5083Swnj } 313*5083Swnj en = mtod(m, struct en_header *); 314*5083Swnj en->en_shost = ifp->if_host[0]; 315*5083Swnj en->en_dhost = dest; 316*5083Swnj en->en_type = type; 317*5083Swnj s = splimp(); 318*5083Swnj IF_ENQUEUE(&ifp->if_snd, m); 319*5083Swnj splx(s); 320*5083Swnj if (en_softc[ifp->if_unit].es_oactive == 0) 321*5083Swnj enstart(ifp->if_unit); 3224686Swnj } 323