1*4686Swnj /* if_en.c 4.1 81/10/31 */ 2*4686Swnj 3*4686Swnj #include "en.h" 4*4686Swnj /* 5*4686Swnj * Ethernet interface driver 6*4686Swnj */ 7*4686Swnj 8*4686Swnj #include "../h/param.h" 9*4686Swnj #include "../h/systm.h" 10*4686Swnj #include "../h/mbuf.h" 11*4686Swnj #include "../inet/inet.h" 12*4686Swnj #include "../inet/inet_systm.h" 13*4686Swnj #include "../inet/imp.h" 14*4686Swnj #include "../inet/ip.h" 15*4686Swnj #include "../inet/tcp.h" /* ### */ 16*4686Swnj #include "../h/map.h" 17*4686Swnj #include "../h/pte.h" 18*4686Swnj #include "../h/buf.h" 19*4686Swnj #include "../h/ubareg.h" 20*4686Swnj #include "../h/ubavar.h" 21*4686Swnj #include "../h/conf.h" 22*4686Swnj #include "../h/dir.h" 23*4686Swnj #include "../h/user.h" 24*4686Swnj #include "../h/proc.h" 25*4686Swnj #include "../h/enreg.h" 26*4686Swnj #include "../h/mtpr.h" 27*4686Swnj #include "../h/cpu.h" 28*4686Swnj #include "../h/cmap.h" 29*4686Swnj 30*4686Swnj int enrswaps, enwswaps; 31*4686Swnj int enprobe(), enattach(), enrint(), enxint(), encollide(); 32*4686Swnj struct uba_device *eninfo[NEN]; 33*4686Swnj u_short enstd[] = { 0 }; 34*4686Swnj struct uba_driver endriver = 35*4686Swnj { enprobe, 0, enattach, 0, enstd, "en", eninfo }; 36*4686Swnj 37*4686Swnj #define ENUNIT(x) minor(x) 38*4686Swnj 39*4686Swnj struct en_packet *xpkt, *rpkt; 40*4686Swnj struct en_prefix { 41*4686Swnj struct en_header enp_h; 42*4686Swnj struct th enp_th; 43*4686Swnj }; 44*4686Swnj struct uba_regs *enuba; 45*4686Swnj struct pte *enrmr; 46*4686Swnj int enrbdp, enwbdp; 47*4686Swnj int enrproto, enwproto; 48*4686Swnj int enxmap[1]; 49*4686Swnj 50*4686Swnj enprobe(reg) 51*4686Swnj caddr_t reg; 52*4686Swnj { 53*4686Swnj register int br, cvec; 54*4686Swnj register struct endevice *addr = (struct endevice *)reg; 55*4686Swnj 56*4686Swnj #ifdef lint 57*4686Swnj br = 0; cvec = br; br = cvec; 58*4686Swnj #endif 59*4686Swnj 60*4686Swnj addr->en_istat = 0; 61*4686Swnj addr->en_ostat = 0; 62*4686Swnj addr->en_owc = -1; 63*4686Swnj addr->en_oba = 0; 64*4686Swnj addr->en_ostat = IEN|GO; 65*4686Swnj DELAY(100000); 66*4686Swnj addr->en_ostat = 0; 67*4686Swnj printf("ethernet address %d\n", ~addr->en_addr&0xff); 68*4686Swnj return (1); 69*4686Swnj } 70*4686Swnj 71*4686Swnj enattach(ui) 72*4686Swnj struct uba_device *ui; 73*4686Swnj { 74*4686Swnj /* no local state to set up */ 75*4686Swnj } 76*4686Swnj 77*4686Swnj imp_init(unit) 78*4686Swnj int unit; 79*4686Swnj { 80*4686Swnj register struct endevice *addr; 81*4686Swnj register struct uba_device *ui; 82*4686Swnj int uban, x; 83*4686Swnj static reenter; 84*4686Swnj 85*4686Swnj if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) { 86*4686Swnj printf("en%d: not alive\n", unit); 87*4686Swnj return; 88*4686Swnj } 89*4686Swnj x = splimp(); 90*4686Swnj if (reenter == 0) { 91*4686Swnj int n, j, i, k; char *cp; 92*4686Swnj reenter = 1; 93*4686Swnj n = 10; 94*4686Swnj k = n<<1; 95*4686Swnj i = rmalloc(netmap, n*2); 96*4686Swnj if (i == 0) 97*4686Swnj panic("imp_init"); 98*4686Swnj j = i << 1; 99*4686Swnj cp = (char *)pftom(i); 100*4686Swnj if (memall(&Netmap[j], k, proc, CSYS) == 0) 101*4686Swnj return (0); 102*4686Swnj vmaccess(&Netmap[j], (caddr_t)cp, k); 103*4686Swnj rpkt = (struct en_packet *) 104*4686Swnj (cp + 1024 - sizeof (struct en_prefix)); 105*4686Swnj xpkt = (struct en_packet *) 106*4686Swnj (cp + 5 * 1024 + 1024 - sizeof (struct en_prefix)); 107*4686Swnj for (j = 0; j < n; j++) 108*4686Swnj mprefcnt[i+j] = 1; 109*4686Swnj } 110*4686Swnj uban = ui->ui_ubanum; 111*4686Swnj addr = (struct endevice *)ui->ui_addr; 112*4686Swnj addr->en_istat = 0; 113*4686Swnj addr->en_ostat = 0; 114*4686Swnj imp_stat.iaddr = 115*4686Swnj uballoc(uban, (caddr_t)rpkt, 1024+512, UBA_NEED16|UBA_NEEDBDP); 116*4686Swnj imp_stat.oaddr = 117*4686Swnj uballoc(uban, (caddr_t)xpkt, 1024+512, UBA_NEED16|UBA_NEEDBDP); 118*4686Swnj enuba = ui->ui_hd->uh_uba; 119*4686Swnj enrbdp = (imp_stat.iaddr >> 28) & 0xf; 120*4686Swnj enwbdp = (imp_stat.oaddr >> 28) & 0xf; 121*4686Swnj enrproto = UBAMR_MRV | (enrbdp << 21); 122*4686Swnj enwproto = UBAMR_MRV | (enwbdp << 21); 123*4686Swnj enrmr = &enuba->uba_map[((imp_stat.iaddr>>9)&0x1ff) + 1]; 124*4686Swnj printf("enrbdp %x enrproto %x enrmr %x imp_stat.iaddr %x\n", 125*4686Swnj enrbdp, enrproto, enrmr, imp_stat.iaddr); 126*4686Swnj imp_stat.impopen = 1; 127*4686Swnj imp_stat.flush = 0; 128*4686Swnj splx(x); 129*4686Swnj #ifdef IMPDEBUG 130*4686Swnj printf("eninit(%d): iaddr = %x, oaddr = %x\n", 131*4686Swnj unit, imp_stat.iaddr, imp_stat.oaddr); 132*4686Swnj #endif 133*4686Swnj } 134*4686Swnj 135*4686Swnj enreset(uban) 136*4686Swnj int uban; 137*4686Swnj { 138*4686Swnj register int unit; 139*4686Swnj struct uba_device *ui; 140*4686Swnj 141*4686Swnj for (unit = 0; unit < NEN; unit++) { 142*4686Swnj ui = eninfo[unit]; 143*4686Swnj if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 144*4686Swnj continue; 145*4686Swnj if (imp_stat.iaddr) 146*4686Swnj ubarelse(uban, imp_stat.iaddr); 147*4686Swnj if (imp_stat.oaddr) 148*4686Swnj ubarelse(uban, imp_stat.oaddr); 149*4686Swnj imp_init(unit); 150*4686Swnj printf("en%d ", unit); 151*4686Swnj } 152*4686Swnj } 153*4686Swnj 154*4686Swnj imp_output(dev) 155*4686Swnj dev_t dev; 156*4686Swnj { 157*4686Swnj register struct mbuf *m, *mp; 158*4686Swnj register struct endevice *addr; 159*4686Swnj register caddr_t cp, top; 160*4686Swnj int unit; 161*4686Swnj register int len; 162*4686Swnj u_short uaddr; 163*4686Swnj struct uba_device *ui; 164*4686Swnj COUNT(IMP_OUTPUT); 165*4686Swnj 166*4686Swnj unit = ENUNIT(dev); 167*4686Swnj ui = eninfo[unit]; 168*4686Swnj if (ui == 0 || ui->ui_alive == 0) { 169*4686Swnj printf("en%d (imp_output): not alive\n", unit); 170*4686Swnj return; 171*4686Swnj } 172*4686Swnj addr = (struct endevice *)ui->ui_addr; 173*4686Swnj if (!imp_stat.outactive) { 174*4686Swnj if ((m = imp_stat.outq_head) == NULL) 175*4686Swnj return; 176*4686Swnj imp_stat.outactive = 1; /* set myself active */ 177*4686Swnj imp_stat.outq_head = m->m_act; /* -> next packet chain */ 178*4686Swnj /* 179*4686Swnj * Pack mbufs into ethernet packet. 180*4686Swnj */ 181*4686Swnj cp = (caddr_t)xpkt; 182*4686Swnj top = (caddr_t)xpkt + sizeof(struct en_packet); 183*4686Swnj while (m != NULL) { 184*4686Swnj if (cp + m->m_len > top) { 185*4686Swnj printf("imp_snd: my packet runneth over\n"); 186*4686Swnj m_freem(m); 187*4686Swnj return; 188*4686Swnj } 189*4686Swnj bcopy((int)m + m->m_off, cp, m->m_len); 190*4686Swnj cp += m->m_len; 191*4686Swnj MFREE(m, mp); 192*4686Swnj m = mp; 193*4686Swnj } 194*4686Swnj } 195*4686Swnj len = ntohs(((struct ip *)((int)xpkt + L1822))->ip_len) + L1822; 196*4686Swnj if (len > sizeof(struct en_packet)) { 197*4686Swnj printf("imp_output: ridiculous IP length %d\n", len); 198*4686Swnj return; 199*4686Swnj } 200*4686Swnj #if defined(VAX780) || defined(VAX750) 201*4686Swnj switch (cpu) { 202*4686Swnj #if defined(VAX780) 203*4686Swnj case VAX_780: 204*4686Swnj UBA_PURGE780(ui->ui_hd->uh_uba, imp_stat.oaddr>>28); 205*4686Swnj break; 206*4686Swnj #endif 207*4686Swnj #if defined(VAX750) 208*4686Swnj case VAX_750: 209*4686Swnj UBA_PURGE750(ui->ui_hd->uh_uba, imp_stat.oaddr>>28); 210*4686Swnj break; 211*4686Swnj #endif 212*4686Swnj } 213*4686Swnj #endif 214*4686Swnj addr->en_oba = imp_stat.oaddr; 215*4686Swnj addr->en_odelay = imp_stat.endelay; 216*4686Swnj addr->en_owc = -((len + 1) >> 1); 217*4686Swnj #ifdef IMPDEBUG 218*4686Swnj printf("en%d: sending packet (%d bytes)\n", unit, len); 219*4686Swnj prt_byte(xpkt, len); 220*4686Swnj #endif 221*4686Swnj addr->en_ostat = IEN|GO; 222*4686Swnj } 223*4686Swnj 224*4686Swnj /* 225*4686Swnj * Start a read operation. 226*4686Swnj */ 227*4686Swnj imp_read(dev) 228*4686Swnj dev_t dev; 229*4686Swnj { 230*4686Swnj register struct endevice *addr; 231*4686Swnj register struct uba_device *ui; 232*4686Swnj register unsigned ubaddr; 233*4686Swnj register int sps; 234*4686Swnj COUNT(IMP_READ); 235*4686Swnj 236*4686Swnj ui = eninfo[ENUNIT(dev)]; 237*4686Swnj if (ui == 0 || ui->ui_alive == 0) { 238*4686Swnj printf("en%d (imp_read): not alive\n", ENUNIT(dev)); 239*4686Swnj return; 240*4686Swnj } 241*4686Swnj addr = (struct endevice *)ui->ui_addr; 242*4686Swnj addr->en_iba = imp_stat.iaddr; 243*4686Swnj addr->en_iwc = -600; /* a little extra to avoid hardware bugs */ 244*4686Swnj addr->en_istat = IEN|GO; 245*4686Swnj } 246*4686Swnj 247*4686Swnj /* 248*4686Swnj * Output interrupt handler. 249*4686Swnj */ 250*4686Swnj enxint(unit) 251*4686Swnj int unit; 252*4686Swnj { 253*4686Swnj register struct endevice *addr; 254*4686Swnj register struct uba_device *ui; 255*4686Swnj COUNT(ENXINT); 256*4686Swnj 257*4686Swnj ui = eninfo[unit]; 258*4686Swnj addr = (struct endevice *)ui->ui_addr; 259*4686Swnj 260*4686Swnj #ifdef IMPDEBUG 261*4686Swnj printf("en%d: enxint ostat=%b\n", unit, addr->en_ostat, EN_BITS); 262*4686Swnj #endif 263*4686Swnj if (!imp_stat.outactive) { 264*4686Swnj printf("en%d: phantom output intr ostat=%b\n", 265*4686Swnj unit, addr->en_ostat, EN_BITS); 266*4686Swnj return; 267*4686Swnj } 268*4686Swnj imp_stat.endelay = 0; 269*4686Swnj imp_stat.enmask = ~0; 270*4686Swnj if (addr->en_ostat&ERROR) 271*4686Swnj printf("en%d: output error ostat=%b\n", unit, 272*4686Swnj addr->en_ostat, EN_BITS); 273*4686Swnj imp_stat.outactive = 0; 274*4686Swnj imp_output(unit); 275*4686Swnj } 276*4686Swnj 277*4686Swnj encollide(unit) 278*4686Swnj int unit; 279*4686Swnj { 280*4686Swnj register struct endevice *addr; 281*4686Swnj register struct uba_device *ui; 282*4686Swnj COUNT(ENCOLLIDE); 283*4686Swnj 284*4686Swnj ui = eninfo[unit]; 285*4686Swnj addr = (struct endevice *)ui->ui_addr; 286*4686Swnj 287*4686Swnj #ifdef IMPDEBUG 288*4686Swnj printf("en%d: collision ostat=%b\n", unit, addr->en_ostat, EN_BITS); 289*4686Swnj #endif 290*4686Swnj if (!imp_stat.outactive) { 291*4686Swnj printf("en%d: phantom collision intr ostat=%b\n", 292*4686Swnj unit, addr->en_ostat, EN_BITS); 293*4686Swnj return; 294*4686Swnj } 295*4686Swnj if (imp_stat.enmask == 0) { 296*4686Swnj printf("en%d: output error ostat=%b\n", unit, 297*4686Swnj addr->en_ostat, EN_BITS); 298*4686Swnj } else { 299*4686Swnj imp_stat.enmask <<= 1; 300*4686Swnj imp_stat.endelay = time & ~imp_stat.enmask; 301*4686Swnj } 302*4686Swnj imp_output(unit); 303*4686Swnj } 304*4686Swnj 305*4686Swnj enrint(unit) 306*4686Swnj int unit; 307*4686Swnj { 308*4686Swnj register struct mbuf *m; 309*4686Swnj struct mbuf *mp; 310*4686Swnj register struct endevice *addr; 311*4686Swnj register struct uba_device *ui; 312*4686Swnj register int len; 313*4686Swnj register caddr_t cp; 314*4686Swnj struct mbuf *p, *top = 0; 315*4686Swnj struct ip *ip; 316*4686Swnj int j, hlen; 317*4686Swnj COUNT(ENRINT); 318*4686Swnj 319*4686Swnj ui = eninfo[unit]; 320*4686Swnj addr = (struct endevice *)ui->ui_addr; 321*4686Swnj #ifdef IMPDEBUG 322*4686Swnj printf("en%d: enrint istat=%b\n", unit, addr->en_istat, EN_BITS); 323*4686Swnj #endif 324*4686Swnj if (imp_stat.flush) 325*4686Swnj goto flush; 326*4686Swnj if (addr->en_istat&ERROR) { 327*4686Swnj #ifdef notdef 328*4686Swnj printf("en%d: input error istat=%b\n", unit, 329*4686Swnj addr->en_istat, EN_BITS); 330*4686Swnj #endif 331*4686Swnj goto flush; 332*4686Swnj } 333*4686Swnj #if defined(VAX780) || defined(VAX750) 334*4686Swnj switch (cpu) { 335*4686Swnj #if defined(VAX780) 336*4686Swnj case VAX_780: 337*4686Swnj UBA_PURGE780(enuba, enrbdp); 338*4686Swnj break; 339*4686Swnj #endif 340*4686Swnj #if defined(VAX750) 341*4686Swnj case VAX_750: 342*4686Swnj UBA_PURGE750(enuba, enrbdp); 343*4686Swnj break; 344*4686Swnj #endif 345*4686Swnj } 346*4686Swnj #endif 347*4686Swnj ip = (struct ip *)((int)rpkt + L1822); 348*4686Swnj len = ntohs(ip->ip_len) + L1822; 349*4686Swnj if (len > sizeof(struct en_packet) || len < sizeof (struct ip)) { 350*4686Swnj printf("enrint: bad ip length %d\n", len); 351*4686Swnj goto flush; 352*4686Swnj } 353*4686Swnj hlen = L1822 + sizeof (struct ip); 354*4686Swnj switch (ip->ip_p) { 355*4686Swnj 356*4686Swnj case TCPROTO: 357*4686Swnj hlen += ((struct th *)ip)->t_off * 4; 358*4686Swnj break; 359*4686Swnj } 360*4686Swnj MGET(m, 0); 361*4686Swnj if (m == 0) 362*4686Swnj goto flush; 363*4686Swnj top = m; 364*4686Swnj m->m_off = MMINOFF; 365*4686Swnj m->m_len = hlen; 366*4686Swnj bcopy(rpkt, mtod(m, caddr_t), hlen); 367*4686Swnj len -= hlen; 368*4686Swnj cp = (caddr_t)rpkt + hlen; 369*4686Swnj mp = m; 370*4686Swnj while (len > 0) { 371*4686Swnj MGET(m, 0); 372*4686Swnj if (m == NULL) 373*4686Swnj goto flush; 374*4686Swnj if (len >= PGSIZE) { 375*4686Swnj MPGET(p, 1); 376*4686Swnj if (p == 0) 377*4686Swnj goto nopage; 378*4686Swnj m->m_len = PGSIZE; 379*4686Swnj m->m_off = (int)p - (int)m; 380*4686Swnj if (((int)cp & 0x3ff) == 0) { 381*4686Swnj struct pte *cpte = &Netmap[mtopf(cp)*2]; 382*4686Swnj struct pte *ppte = &Netmap[mtopf(p)*2]; 383*4686Swnj struct pte t; 384*4686Swnj enrswaps++; 385*4686Swnj t = *ppte; *ppte++ = *cpte; *cpte++ = t; 386*4686Swnj t = *ppte; *ppte = *cpte; *cpte = t; 387*4686Swnj mtpr(TBIS, (caddr_t)cp); 388*4686Swnj mtpr(TBIS, (caddr_t)cp+512); 389*4686Swnj mtpr(TBIS, (caddr_t)p); 390*4686Swnj mtpr(TBIS, (caddr_t)p+512); 391*4686Swnj *(int *)(enrmr+1) = 392*4686Swnj cpte[0].pg_pfnum | enrproto; 393*4686Swnj *(int *)(enrmr) = 394*4686Swnj cpte[-1].pg_pfnum | enrproto; 395*4686Swnj goto nocopy; 396*4686Swnj } 397*4686Swnj } else { 398*4686Swnj nopage: 399*4686Swnj m->m_len = MIN(MLEN, len); 400*4686Swnj m->m_off = MMINOFF; 401*4686Swnj } 402*4686Swnj bcopy(cp, (int)m + m->m_off, m->m_len); 403*4686Swnj nocopy: 404*4686Swnj cp += m->m_len; 405*4686Swnj len -= m->m_len; 406*4686Swnj mp->m_next = m; 407*4686Swnj mp = m; 408*4686Swnj } 409*4686Swnj m = top; 410*4686Swnj if (imp_stat.inq_head != NULL) 411*4686Swnj imp_stat.inq_tail->m_act = m; 412*4686Swnj else 413*4686Swnj imp_stat.inq_head = m; 414*4686Swnj imp_stat.inq_tail = m; 415*4686Swnj #ifdef IMPDEBUG 416*4686Swnj printf("en%d: received packet (%d bytes)\n", unit, len); 417*4686Swnj prt_byte(rpkt, len); 418*4686Swnj #endif 419*4686Swnj setsoftnet(); 420*4686Swnj imp_read(0); /* begin next read */ 421*4686Swnj return; 422*4686Swnj flush: 423*4686Swnj m_freem(top); 424*4686Swnj #ifdef IMPDEBUG 425*4686Swnj printf("en%d: flushing packet %x\n", unit, top); 426*4686Swnj #endif 427*4686Swnj imp_read(0); /* begin next read */ 428*4686Swnj } 429*4686Swnj 430*4686Swnj #ifdef IMPDEBUG 431*4686Swnj prt_byte(s, ct) 432*4686Swnj register char *s; 433*4686Swnj int ct; 434*4686Swnj { 435*4686Swnj register i, j, c; 436*4686Swnj 437*4686Swnj for (i=0; i<ct; i++) { 438*4686Swnj c = *s++; 439*4686Swnj for (j=0; j<2 ; j++) 440*4686Swnj putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]); 441*4686Swnj putchar(' '); 442*4686Swnj } 443*4686Swnj putchar('\n'); 444*4686Swnj } 445*4686Swnj #endif IMPDEBUG 446