1 /* if_en.c 4.2 81/10/31 */ 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 enstart(dev) 160 dev_t dev; 161 { 162 register struct mbuf *m, *mp; 163 register struct endevice *addr; 164 register caddr_t cp, top; 165 int unit; 166 register int len; 167 u_short uaddr; 168 struct uba_device *ui; 169 int enxswapnow = 0; 170 COUNT(ENSTART); 171 172 unit = ENUNIT(dev); 173 ui = eninfo[unit]; 174 if (ui == 0 || ui->ui_alive == 0) { 175 printf("en%d (imp_output): not alive\n", unit); 176 return; 177 } 178 addr = (struct endevice *)ui->ui_addr; 179 if (!imp_stat.outactive) { 180 if ((m = imp_stat.outq_head) == NULL) 181 return; 182 imp_stat.outactive = 1; /* set myself active */ 183 imp_stat.outq_head = m->m_act; /* -> next packet chain */ 184 /* 185 * Pack mbufs into ethernet packet. 186 */ 187 cp = (caddr_t)xpkt; 188 top = (caddr_t)xpkt + sizeof(struct en_packet); 189 while (m != NULL) { 190 char *dp; 191 if (cp + m->m_len > top) { 192 printf("imp_snd: my packet runneth over\n"); 193 m_freem(m); 194 return; 195 } 196 dp = mtod(m, char *); 197 if (((int)cp&0x3ff)==0 && ((int)dp&0x3ff)==0) { 198 struct pte *pte = &Netmap[mtopf(dp)*2]; 199 *(int *)enxmr = enwproto | pte++->pg_pfnum; 200 *(int *)(enxmr+1) = enwproto | pte->pg_pfnum; 201 enxswapd = enxswapnow = 1; 202 } else 203 bcopy((int)m + m->m_off, cp, m->m_len); 204 cp += m->m_len; 205 /* too soon! */ 206 MFREE(m, mp); 207 m = mp; 208 } 209 } 210 if (enxswapnow == 0 && enxswapd) { 211 enxmr[0] = enxmap[0]; 212 enxmr[1] = enxmap[1]; 213 } 214 len = ntohs(((struct ip *)((int)xpkt + L1822))->ip_len) + L1822; 215 if (len > sizeof(struct en_packet)) { 216 printf("imp_output: ridiculous IP length %d\n", len); 217 return; 218 } 219 #if defined(VAX780) || defined(VAX750) 220 switch (cpu) { 221 #if defined(VAX780) 222 case VAX_780: 223 UBA_PURGE780(enuba, enwbdp); 224 break; 225 #endif 226 #if defined(VAX750) 227 case VAX_750: 228 UBA_PURGE750(enuba, enwbdp); 229 break; 230 #endif 231 } 232 #endif 233 addr->en_oba = imp_stat.oaddr; 234 addr->en_odelay = imp_stat.endelay; 235 addr->en_owc = -((len + 1) >> 1); 236 #ifdef IMPDEBUG 237 printf("en%d: sending packet (%d bytes)\n", unit, len); 238 prt_byte(xpkt, len); 239 #endif 240 addr->en_ostat = IEN|GO; 241 } 242 243 /* 244 * Setup for a read 245 */ 246 ensetup(dev) 247 dev_t dev; 248 { 249 register struct endevice *addr; 250 register struct uba_device *ui; 251 register unsigned ubaddr; 252 register int sps; 253 COUNT(ENSETUP); 254 255 ui = eninfo[ENUNIT(dev)]; 256 if (ui == 0 || ui->ui_alive == 0) { 257 printf("en%d (imp_read): not alive\n", ENUNIT(dev)); 258 return; 259 } 260 addr = (struct endevice *)ui->ui_addr; 261 addr->en_iba = imp_stat.iaddr; 262 addr->en_iwc = -600; /* a little extra to avoid hardware bugs */ 263 addr->en_istat = IEN|GO; 264 } 265 266 /* 267 * Output interrupt handler. 268 */ 269 enxint(unit) 270 int unit; 271 { 272 register struct endevice *addr; 273 register struct uba_device *ui; 274 COUNT(ENXINT); 275 276 ui = eninfo[unit]; 277 addr = (struct endevice *)ui->ui_addr; 278 279 #ifdef IMPDEBUG 280 printf("en%d: enxint ostat=%b\n", unit, addr->en_ostat, EN_BITS); 281 #endif 282 if (!imp_stat.outactive) { 283 printf("en%d: phantom output intr ostat=%b\n", 284 unit, addr->en_ostat, EN_BITS); 285 return; 286 } 287 imp_stat.endelay = 0; 288 imp_stat.enmask = ~0; 289 if (addr->en_ostat&ERROR) 290 printf("en%d: output error ostat=%b\n", unit, 291 addr->en_ostat, EN_BITS); 292 imp_stat.outactive = 0; 293 if (imp_stat.outq_head) 294 enstart(unit); 295 } 296 297 encollide(unit) 298 int unit; 299 { 300 register struct endevice *addr; 301 register struct uba_device *ui; 302 COUNT(ENCOLLIDE); 303 304 ui = eninfo[unit]; 305 addr = (struct endevice *)ui->ui_addr; 306 307 #ifdef IMPDEBUG 308 printf("en%d: collision ostat=%b\n", unit, addr->en_ostat, EN_BITS); 309 #endif 310 if (!imp_stat.outactive) { 311 printf("en%d: phantom collision intr ostat=%b\n", 312 unit, addr->en_ostat, EN_BITS); 313 return; 314 } 315 if (imp_stat.enmask == 0) { 316 printf("en%d: output error ostat=%b\n", unit, 317 addr->en_ostat, EN_BITS); 318 } else { 319 imp_stat.enmask <<= 1; 320 imp_stat.endelay = time & ~imp_stat.enmask; 321 } 322 enstart(unit); 323 } 324 325 enrint(unit) 326 int unit; 327 { 328 register struct mbuf *m; 329 struct mbuf *mp; 330 register struct endevice *addr; 331 register struct uba_device *ui; 332 register int len; 333 register caddr_t cp; 334 struct mbuf *p, *top = 0; 335 struct ip *ip; 336 int j, hlen; 337 COUNT(ENRINT); 338 339 ui = eninfo[unit]; 340 addr = (struct endevice *)ui->ui_addr; 341 #ifdef IMPDEBUG 342 printf("en%d: enrint istat=%b\n", unit, addr->en_istat, EN_BITS); 343 #endif 344 if (imp_stat.flush) 345 goto flush; 346 if (addr->en_istat&ERROR) { 347 #ifdef notdef 348 printf("en%d: input error istat=%b\n", unit, 349 addr->en_istat, EN_BITS); 350 #endif 351 goto flush; 352 } 353 #if defined(VAX780) || defined(VAX750) 354 switch (cpu) { 355 #if defined(VAX780) 356 case VAX_780: 357 UBA_PURGE780(enuba, enrbdp); 358 break; 359 #endif 360 #if defined(VAX750) 361 case VAX_750: 362 UBA_PURGE750(enuba, enrbdp); 363 break; 364 #endif 365 } 366 #endif 367 ip = (struct ip *)((int)rpkt + L1822); 368 len = ntohs(ip->ip_len) + L1822; 369 if (len > sizeof(struct en_packet) || len < sizeof (struct ip)) { 370 printf("enrint: bad ip length %d\n", len); 371 goto flush; 372 } 373 hlen = L1822 + sizeof (struct ip); 374 switch (ip->ip_p) { 375 376 case TCPROTO: 377 hlen += ((struct th *)ip)->t_off * 4; 378 break; 379 } 380 MGET(m, 0); 381 if (m == 0) 382 goto flush; 383 top = m; 384 m->m_off = MMINOFF; 385 m->m_len = hlen; 386 bcopy(rpkt, mtod(m, caddr_t), hlen); 387 len -= hlen; 388 cp = (caddr_t)rpkt + hlen; 389 mp = m; 390 while (len > 0) { 391 MGET(m, 0); 392 if (m == NULL) 393 goto flush; 394 if (len >= PGSIZE) { 395 MPGET(p, 1); 396 if (p == 0) 397 goto nopage; 398 m->m_len = PGSIZE; 399 m->m_off = (int)p - (int)m; 400 if (((int)cp & 0x3ff) == 0) { 401 struct pte *cpte = &Netmap[mtopf(cp)*2]; 402 struct pte *ppte = &Netmap[mtopf(p)*2]; 403 struct pte t; 404 enrswaps++; 405 t = *ppte; *ppte++ = *cpte; *cpte++ = t; 406 t = *ppte; *ppte = *cpte; *cpte = t; 407 mtpr(TBIS, (caddr_t)cp); 408 mtpr(TBIS, (caddr_t)cp+512); 409 mtpr(TBIS, (caddr_t)p); 410 mtpr(TBIS, (caddr_t)p+512); 411 *(int *)(enrmr+1) = 412 cpte[0].pg_pfnum | enrproto; 413 *(int *)(enrmr) = 414 cpte[-1].pg_pfnum | enrproto; 415 goto nocopy; 416 } 417 } else { 418 nopage: 419 m->m_len = MIN(MLEN, len); 420 m->m_off = MMINOFF; 421 } 422 bcopy(cp, (int)m + m->m_off, m->m_len); 423 nocopy: 424 cp += m->m_len; 425 len -= m->m_len; 426 mp->m_next = m; 427 mp = m; 428 } 429 m = top; 430 if (imp_stat.inq_head != NULL) 431 imp_stat.inq_tail->m_act = m; 432 else 433 imp_stat.inq_head = m; 434 imp_stat.inq_tail = m; 435 #ifdef IMPDEBUG 436 printf("en%d: received packet (%d bytes)\n", unit, len); 437 prt_byte(rpkt, len); 438 #endif 439 setsoftnet(); 440 goto setup; 441 flush: 442 m_freem(top); 443 #ifdef IMPDEBUG 444 printf("en%d: flushing packet %x\n", unit, top); 445 #endif 446 setup: 447 addr->en_iba = imp_stat.iaddr; 448 addr->en_iwc = -600; 449 addr->en_istat = IEN|GO; 450 } 451 452 #ifdef IMPDEBUG 453 prt_byte(s, ct) 454 register char *s; 455 int ct; 456 { 457 register i, j, c; 458 459 for (i=0; i<ct; i++) { 460 c = *s++; 461 for (j=0; j<2 ; j++) 462 putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]); 463 putchar(' '); 464 } 465 putchar('\n'); 466 } 467 #endif IMPDEBUG 468