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