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