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