1 #include "ne.h" 2 #if NNE > 0 3 /* 4 * NE2000 Ethernet driver 5 * Copyright (C) 1990 W. Jolitz 6 * @(#)if_ne.c 1.6 (Berkeley) 01/08/91 7 * 8 * Parts inspired from Tim Tucker's if_wd driver for the wd8003, 9 * insight on the ne2000 gained from Robert Clements PC/FTP driver. 10 */ 11 12 #include "param.h" 13 #include "systm.h" 14 #include "mbuf.h" 15 #include "buf.h" 16 #include "protosw.h" 17 #include "socket.h" 18 #include "ioctl.h" 19 #include "errno.h" 20 #include "syslog.h" 21 22 #include "../net/if.h" 23 #include "../net/netisr.h" 24 #include "../net/route.h" 25 26 #ifdef INET 27 #include "../netinet/in.h" 28 #include "../netinet/in_systm.h" 29 #include "../netinet/in_var.h" 30 #include "../netinet/ip.h" 31 #include "../netinet/if_ether.h" 32 #endif 33 34 #ifdef NS 35 #include "../netns/ns.h" 36 #include "../netns/ns_if.h" 37 #endif 38 39 #include "machine/isa/isa_device.h" 40 #include "if_nereg.h" 41 #include "icu.h" 42 43 int neprobe(), neattach(), neintr(); 44 int neinit(), neoutput(), neioctl(); 45 46 #include "dbg.h" 47 struct isa_driver nedriver = { 48 neprobe, neattach, "ne", 49 }; 50 51 struct mbuf *neget(); 52 53 /* 54 * Ethernet software status per interface. 55 * 56 * Each interface is referenced by a network interface structure, 57 * ns_if, which the routing code uses to locate the interface. 58 * This structure contains the output queue for the interface, its address, ... 59 */ 60 struct ne_softc { 61 struct arpcom ns_ac; /* Ethernet common part */ 62 #define ns_if ns_ac.ac_if /* network-visible interface */ 63 #define ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */ 64 int ns_flags; 65 #define DSF_LOCK 1 /* block re-entering enstart */ 66 int ns_oactive ; 67 int ns_mask ; 68 int ns_ba; /* byte addr in buffer ram of inc pkt */ 69 int ns_cur; /* current page being filled */ 70 struct prhdr ns_ph; /* hardware header of incoming packet*/ 71 struct ether_header ns_eh; /* header of incoming packet */ 72 u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/]; 73 } ne_softc[NNE] ; 74 #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + 64) 75 76 int nec; 77 78 u_short boarddata[16]; 79 80 neprobe(dvp) 81 struct isa_device *dvp; 82 { 83 int val,i,s; 84 register struct ne_softc *ns = &ne_softc[0]; 85 86 #ifdef lint 87 neintr(0); 88 #endif 89 90 nec = dvp->id_iobase; 91 s = splimp(); 92 93 /* reset the bastard */ 94 val = inb(nec+ne_reset); 95 DELAY(2000000); 96 outb(nec+ne_reset,val); 97 98 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA); 99 100 i = 1000000; 101 while ((inb(nec+ds0_isr)&DSIS_RESET) == 0 && i-- > 0) nulldev(); 102 if (i < 0) return (0); 103 104 outb(nec+ds0_isr, 0xff); 105 106 /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ 107 outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); 108 109 outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 110 DELAY(10000); 111 112 /* check cmd reg and fail if not right */ 113 if ((i=inb(nec+ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP)) 114 return(0); 115 116 outb(nec+ds0_tcr, 0); 117 outb(nec+ds0_rcr, DSRC_MON); 118 outb(nec+ds0_pstart, RBUF/DS_PGSIZE); 119 outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE); 120 outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE); 121 outb(nec+ds0_imr, 0); 122 outb(nec+ds0_isr, 0); 123 outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); 124 outb(nec+ds1_curr, RBUF/DS_PGSIZE); 125 outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 126 fetchrom (boarddata, 0, sizeof(boarddata)); 127 #ifdef NEDEBUG 128 /*{ int i,rom; 129 rom=1; 130 printf("ne ram "); 131 for (i = 0; i < 0xfff0; i+=4) { 132 int pat; 133 pat = 0xa55a+i*37; 134 putram(&pat,i,4); 135 fetchram(&pat,i,4); 136 if (pat == 0xa55a+i*37) { 137 if (rom) { rom=0; printf(" %x", i); } 138 } else { 139 if (!rom) { rom=1; printf("..%x ", i); } 140 } 141 pat=0; 142 putram(&pat,i,4); 143 } 144 printf("\n"); 145 }*/ 146 #endif 147 /* checksum data? */ 148 /* extract board address */ 149 for(i=0; i < 6; i++) ns->ns_addr[i] = boarddata[i]; 150 splx(s); 151 return (1); 152 } 153 154 fetchrom (up, ad, len) u_short *up; { 155 u_char cmd; 156 157 cmd = inb(nec+ds_cmd); 158 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 159 outb (nec+ds0_isr, DSIS_RDC); 160 outb (nec+ds0_rbcr0, len&0xff); 161 outb (nec+ds0_rbcr1, (len>>8)&0xff); 162 outb (nec+ds0_rsar0, ad&0xff); 163 outb (nec+ds0_rsar1, (ad>>8)&0xff); 164 outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START); 165 insw (nec+ne_data, up, len/2); 166 pausestr ("x",1); 167 while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) pausestr("fetchrom",0); 168 outb (nec+ds0_isr, DSIS_RDC); 169 outb (nec+ds_cmd, cmd); 170 } 171 172 static recur; 173 fetchram (up, ad, len) caddr_t up; { 174 u_char cmd; 175 176 recur++; 177 cmd = inb(nec+ds_cmd); 178 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 179 outb (nec+ds0_isr, DSIS_RDC); 180 outb (nec+ds0_rbcr0, len&0xff); 181 outb (nec+ds0_rbcr1, (len>>8)&0xff); 182 outb (nec+ds0_rsar0, ad&0xff); 183 outb (nec+ds0_rsar1, (ad>>8)&0xff); 184 outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START); 185 insw (nec+ne_data, up, len/2); 186 pausestr ("x",1); 187 while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) pausestr("fetchram",0); 188 outb (nec+ds0_isr, DSIS_RDC); 189 outb (nec+ds_cmd, cmd); 190 recur--; 191 } 192 193 putram (up, ad, len) caddr_t up; { 194 u_char cmd; 195 196 recur++; 197 cmd = inb(nec+ds_cmd); 198 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 199 outb (nec+ds0_isr, DSIS_RDC); 200 if(len&1) len++; 201 outb (nec+ds0_rbcr0, len&0xff); 202 outb (nec+ds0_rbcr1, (len>>8)&0xff); 203 outb (nec+ds0_rsar0, ad&0xff); 204 outb (nec+ds0_rsar1, (ad>>8)&0xff); 205 outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START); 206 outsw (nec+ne_data, up, len/2); 207 pausestr ("x",1); 208 while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) 209 if(pausestr("putram",0)<0) break; 210 outb (nec+ds0_isr, DSIS_RDC); 211 outb (nec+ds_cmd, cmd); 212 recur--; 213 } 214 215 /* 216 * Reset of interface. 217 */ 218 nereset(unit, uban) 219 int unit, uban; 220 { 221 if (unit >= NNE) 222 return; 223 printf("ne%d: reset\n", unit); 224 ne_softc[unit].ns_flags &= ~DSF_LOCK; 225 neinit(unit); 226 } 227 228 /* 229 * Interface exists: make available by filling in network interface 230 * record. System will initialize the interface when it is ready 231 * to accept packets. We get the ethernet address here. 232 */ 233 neattach(dvp) 234 struct isa_device *dvp; 235 { 236 int unit = dvp->id_unit; 237 register struct ne_softc *ns = &ne_softc[unit]; 238 register struct ifnet *ifp = &ns->ns_if; 239 240 ifp->if_unit = unit; 241 ifp->if_name = nedriver.name ; 242 ifp->if_mtu = ETHERMTU; 243 printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ; 244 ifp->if_flags = IFF_BROADCAST|IFF_NOTRAILERS; 245 ifp->if_init = neinit; 246 ifp->if_output = neoutput; 247 ifp->if_ioctl = neioctl; 248 ifp->if_reset = nereset; 249 ifp->if_watchdog = 0; 250 if_attach(ifp); 251 } 252 253 /* 254 * Initialization of interface; set up initialization block 255 * and transmit/receive descriptor rings. 256 */ 257 neinit(unit) 258 int unit; 259 { 260 register struct ne_softc *ns = &ne_softc[unit]; 261 struct ifnet *ifp = &ns->ns_if; 262 int s; 263 register i; char *cp; 264 265 if (ifp->if_addrlist == (struct ifaddr *)0) return; 266 if (ifp->if_flags & IFF_RUNNING) return; 267 268 s = splimp(); 269 270 /* set physical address on ethernet */ 271 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); 272 for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]); 273 274 /* clr logical address hash filter for now */ 275 for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff); 276 277 /* init regs */ 278 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 279 outb (nec+ds0_rbcr0, 0); 280 outb (nec+ds0_rbcr1, 0); 281 outb (nec+ds0_imr, 0); 282 outb (nec+ds0_isr, 0xff); 283 /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ 284 outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); 285 outb(nec+ds0_tcr, 0); 286 outb (nec+ds0_rcr, DSRC_MON); 287 outb (nec+ds0_tpsr, 0); 288 outb(nec+ds0_pstart, RBUF/DS_PGSIZE); 289 outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE); 290 outb(nec+ds0_bnry, RBUF/DS_PGSIZE); 291 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); 292 outb(nec+ds1_curr, RBUF/DS_PGSIZE); 293 ns->ns_cur = RBUF/DS_PGSIZE; 294 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 295 outb (nec+ds0_rcr, DSRC_AB); 296 outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); 297 outb (nec+ds0_imr, 0xff); 298 299 ns->ns_if.if_flags |= IFF_RUNNING; 300 ns->ns_oactive = 0; ns->ns_mask = ~0; 301 if (ns->ns_if.if_snd.ifq_head) nestart(ns); 302 splx(s); 303 } 304 305 /* 306 * Setup output on interface. 307 * Get another datagram to send off of the interface queue, 308 * and map it to the interface before starting the output. 309 * called only at splimp or interrupt level. 310 */ 311 nestart(ns) 312 register struct ne_softc *ns; 313 { 314 struct mbuf *m0, *m; 315 int buffer; 316 int len = 0, i; 317 318 /* 319 * The DS8390 has only one transmit buffer, if it is busy we 320 * must wait until the transmit interrupt completes. 321 */ 322 outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); 323 324 if (ns->ns_flags & DSF_LOCK) 325 return; 326 327 if (inb(nec+ds_cmd) & DSCM_TRANS) 328 return; 329 330 if ((ns->ns_if.if_flags & IFF_RUNNING) == 0) 331 return; 332 333 IF_DEQUEUE(&ns->ns_if.if_snd, m); 334 335 if (m == 0) 336 return; 337 338 /* 339 * Copy the mbuf chain into the transmit buffer 340 */ 341 342 ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */ 343 buffer = TBUF; len = i = 0; 344 for (m0 = m; m != 0; m = m->m_next) { 345 /*int j;*/ 346 putram(mtod(m, caddr_t), buffer, m->m_len); 347 buffer += m->m_len; 348 len += m->m_len; 349 /*for(j=0; i < len;i++,j++) puthex(mtod(m,u_char *)[j]); 350 printf("|"); */ 351 } 352 353 /* 354 * If this was a broadcast packet loop it 355 * back because the hardware can't hear its own 356 * transmits. 357 */ 358 /*if (bcmp((caddr_t)(mtod(m0, struct ether_header *)->ether_dhost), 359 (caddr_t)etherbroadcastaddr, 360 sizeof(etherbroadcastaddr)) == 0) { 361 neread(ns, m0); 362 } else { 363 */ 364 m_freem(m0); 365 /*}*/ 366 367 /* 368 * Init transmit length registers, and set transmit start flag. 369 */ 370 371 #ifdef NEDEBUGx 372 if(len < 0 || len > 1536) 373 pg("T Bogus Length %d\n", len); 374 dprintf(DEXPAND,"snd %d ", len); 375 #endif 376 if (len < 60) len = 60; 377 outb(nec+ds0_tbcr0,len&0xff); 378 outb(nec+ds0_tbcr1,(len>>8)&0xff); 379 outb(nec+ds0_tpsr, TBUF/DS_PGSIZE); 380 outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); 381 } 382 383 #define succ(n) (((n)+1 >= RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1) 384 #define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE-1 : (n)-1) 385 /* 386 * Controller interrupt. 387 */ 388 neintr(vec, ppl) 389 int vec; 390 { 391 register struct ne_softc *ns = &ne_softc[0]; 392 u_char cmd,isr; 393 static cnt; 394 395 /* save cmd, clear interrupt */ 396 cmd = inb (nec+ds_cmd); 397 loop: 398 isr = inb (nec+ds0_isr); 399 #ifdef NEDEBUGx 400 dprintf(DEXPAND,"|ppl %x isr %x ", ppl, isr); 401 #endif 402 403 outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); 404 outb(nec+ds0_isr, isr); 405 406 407 if (isr & (DSIS_RXE|DSIS_TXE|DSIS_ROVRN)) 408 log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr/*, DSIS_BITS*/); 409 410 #ifdef notdef 411 /* receiver ovverun? */ 412 if (isr & DSIS_ROVRN) { 413 u_char pend,lastfree; 414 415 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA); 416 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA|DSCM_PG1); 417 pend = inb(nec+ds1_curr); 418 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA|DSCM_PG0); 419 lastfree = inb(nec+ds0_bnry); 420 #ifdef NEDEBUG 421 printf("Cur %x pend %x lastfree %x ", ns->ns_cur, pend, lastfree); 422 #endif 423 /* have we wrapped */ 424 if (lastfree >= RBUFEND/DS_PGSIZE) 425 lastfree = RBUF/DS_PGSIZE; 426 /* something in the buffer? */ 427 if (pend != succ(lastfree)) { 428 u_char nxt; 429 430 fetchram(&ns->ns_ph,ns->ns_cur*DS_PGSIZE, sizeof(ns->ns_ph)); 431 ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph); 432 433 if (ns->ns_ph.pr_status & DSRS_RPC) 434 nerecv (ns); 435 436 nxt = ns->ns_ph.pr_nxtpg ; 437 #ifdef NEDEBUG 438 printf("nxt %x ", nxt); 439 #endif 440 /* sanity check */ 441 if ( nxt >= RBUF/DS_PGSIZE 442 && nxt <= RBUFEND/DS_PGSIZE && nxt <= pend) 443 ns->ns_cur = nxt; 444 else ns->ns_cur = nxt = pend; 445 lastfree = pred(nxt); 446 outb(nec+ds0_bnry, lastfree); 447 } else ns->ns_cur = pend; 448 449 outb(nec+ds0_rbcr0,0); 450 outb(nec+ds0_rbcr1,0); 451 outb(nec+ds0_tcr,DSTC_LB0); 452 outb(nec+ds0_rcr, DSRC_MON); 453 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); 454 outb (nec+ds0_rcr, DSRC_AB); 455 outb(nec+ds0_tcr,0); 456 } 457 #endif 458 459 /* receiver error */ 460 if (isr & DSIS_RXE) { 461 /* need to read these registers to clear status */ 462 (void) inb(nec+ ds0_rsr); 463 (void) inb(nec+ 0xD); 464 (void) inb(nec + 0xE); 465 (void) inb(nec + 0xF); 466 ns->ns_if.if_ierrors++; 467 } 468 469 if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) { 470 u_char pend,lastfree; 471 472 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); 473 pend = inb(nec+ds1_curr); 474 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); 475 lastfree = inb(nec+ds0_bnry); 476 #ifdef NEDEBUG 477 dprintf(DEXPAND,"cur %x pnd %x lfr %x ", ns->ns_cur, pend, lastfree); 478 #endif 479 /* have we wrapped */ 480 if (lastfree >= RBUFEND/DS_PGSIZE) 481 lastfree = RBUF/DS_PGSIZE; 482 if (pend < lastfree && ns->ns_cur < pend) 483 lastfree = ns->ns_cur; 484 else if (ns->ns_cur > lastfree) 485 lastfree = ns->ns_cur; 486 487 /* something in the buffer? */ 488 while (pend != lastfree) { 489 u_char nxt; 490 491 fetchram(&ns->ns_ph,lastfree*DS_PGSIZE, 492 sizeof(ns->ns_ph)); 493 ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph); 494 495 /* paranoia */ 496 if (ns->ns_ph.pr_status == DSRS_RPC || 497 ns->ns_ph.pr_status == 0x21) 498 nerecv (ns); 499 #ifdef NEDEBUG 500 else { 501 printf("cur %x pnd %x lfr %x ", ns->ns_cur, pend, lastfree); 502 printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg, (ns->ns_ph.pr_sz1<<8)+ 503 ns->ns_ph.pr_sz0); 504 pg("Bogus Sts %x ", ns->ns_ph.pr_status); 505 } 506 #endif 507 508 nxt = ns->ns_ph.pr_nxtpg ; 509 #ifdef NEDEBUG 510 dprintf(DEXPAND,"nxt %x ", nxt); 511 #endif 512 /* sanity check */ 513 if ( nxt >= RBUF/DS_PGSIZE 514 && nxt <= RBUFEND/DS_PGSIZE && nxt <= pend) 515 ns->ns_cur = nxt; 516 else ns->ns_cur = nxt = pend; 517 lastfree = nxt; 518 outb(nec+ds0_bnry, pred(nxt)); 519 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); 520 pend = inb(nec+ds1_curr); 521 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); 522 } /*else ns->ns_cur = pend;*/ 523 #ifdef NEDEBUG 524 dprintf(DEXPAND,"cur %x pnd %x lfR %x ", ns->ns_cur, pend, lastfree); 525 #endif 526 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); 527 } 528 if (isr & DSIS_TXE) { 529 ns->ns_flags &= ~DSF_LOCK; 530 #ifdef NEDEBUG 531 dprintf(DEXPAND," clsn"); 532 #endif 533 /* need to read these registers to clear status */ 534 ns->ns_if.if_collisions += inb(nec+ds0_tbcr0); 535 ns->ns_if.if_oerrors++; 536 } 537 if (isr & DSIS_TX) { 538 #ifdef NEDEBUGx 539 dprintf(DEXPAND,"tx "); 540 #endif 541 ns->ns_flags &= ~DSF_LOCK; 542 ++ns->ns_if.if_opackets; 543 ns->ns_if.if_collisions += inb(nec+ds0_tbcr0); 544 } 545 546 /* receiver ovverun? */ 547 if (isr & DSIS_ROVRN) { 548 outb(nec+ds0_rbcr0, 0); 549 outb(nec+ds0_rbcr1, 0); 550 outb(nec+ds0_tcr, DSTC_LB0); 551 outb(nec+ds0_rcr, DSRC_MON); 552 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); 553 outb(nec+ds0_rcr, DSRC_AB); 554 outb(nec+ds0_tcr, 0); 555 } 556 557 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 558 nestart(ns); 559 outb (nec+ds_cmd, cmd); 560 outb (nec+ds0_imr, 0xff); 561 isr = inb (nec+ds0_isr); 562 if(isr) goto loop; 563 564 #ifdef NEDEBUG 565 if(++cnt % 10 == 0) dprintf(DEXPAND,"\n"); 566 #endif 567 } 568 569 /* 570 * Ethernet interface receiver interface. 571 * If input error just drop packet. 572 * Otherwise examine packet to determine type. If can't determine length 573 * from type, then have to drop packet. Othewise decapsulate 574 * packet based on type and pass to type specific higher-level 575 * input routine. 576 */ 577 nerecv(ns) 578 register struct ne_softc *ns; 579 { 580 int len,i; 581 582 ns->ns_if.if_ipackets++; 583 len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8); 584 if(len < 60 || len > 1536) { 585 #ifdef NEDEBUG 586 pg(DEXPAND,"R Bogus Length %d", len); 587 #endif 588 return; 589 } 590 fetchram(ns->ns_pb,ns->ns_ba,min(len,DS_PGSIZE-sizeof(ns->ns_ph))); 591 #ifdef NEDEBUG 592 if (!bcmp((caddr_t)ns->ns_pb, (caddr_t)ns->ns_addr, 6) 593 && !bcmp((caddr_t)ns->ns_pb, (caddr_t)etherbroadcastaddr, 6)) { 594 printf("G%x ", ns->ns_cur); 595 return; 596 }/* else 597 printf("P%x ", ns->ns_cur);*/ 598 #endif 599 if(len > DS_PGSIZE-sizeof(ns->ns_ph)) { 600 int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ; 601 u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph)); 602 603 #ifdef NEDEBUG 604 dprintf(DEXPAND,"len %d(%d|", len, p - ns->ns_pb); 605 #endif 606 if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46; 607 b = ns->ns_cur*DS_PGSIZE; 608 609 while (l >= DS_PGSIZE) { 610 fetchram(p,b,DS_PGSIZE); 611 p += DS_PGSIZE; l -= DS_PGSIZE; 612 if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46; 613 b = ns->ns_cur*DS_PGSIZE; 614 #ifdef NEDEBUG 615 dprintf(DEXPAND,"%d|", p - ns->ns_pb); 616 #endif 617 } 618 #ifdef NEDEBUG 619 dprintf(DEXPAND,"%d) ", l); 620 #endif 621 if (l > 0) 622 fetchram(p,b,l); 623 } 624 len -= 625 sizeof(struct ether_header) 626 + sizeof(long); /* don't forget checksum! */ 627 628 629 neread(ns,(caddr_t)(ns->ns_pb), len); 630 } 631 632 pausestr(s,n) char *s; { 633 static downcnt; 634 635 if(n) { downcnt = 0xffff; return(0); } 636 if(--downcnt > 0) return(0); 637 #ifdef NEDEBUG 638 pg(" <%s> recur %d sts %x ", s, recur, inb (nec+ds0_isr)); 639 #endif 640 return(-1); 641 } 642 643 644 /* 645 * Pass a packet to the higher levels. 646 * We deal with the trailer protocol here. 647 */ 648 neread(ns, buf, len) 649 register struct ne_softc *ns; 650 char *buf; 651 int len; 652 { 653 register struct ether_header *eh; 654 struct mbuf *m; 655 int off, resid; 656 register struct ifqueue *inq; 657 658 /* 659 * Deal with trailer protocol: if type is trailer type 660 * get true type from first 16-bit word past data. 661 * Remember that type was trailer by setting off. 662 */ 663 eh = (struct ether_header *)buf; 664 eh->ether_type = ntohs((u_short)eh->ether_type); 665 #define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 666 if (eh->ether_type >= ETHERTYPE_TRAIL && 667 eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 668 off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 669 if (off >= ETHERMTU) return; /* sanity */ 670 eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *)); 671 resid = ntohs(*(nedataaddr(eh, off+2, u_short *))); 672 if (off + resid > len) return; /* sanity */ 673 len = off + resid; 674 } else off = 0; 675 676 if (len == 0) return; 677 678 /* 679 * Pull packet off interface. Off is nonzero if packet 680 * has trailing header; neget will then force this header 681 * information to be at the front, but we still have to drop 682 * the type and length which are at the front of any trailer data. 683 */ 684 m = neget(buf, len, off, &ns->ns_if); 685 if (m == 0) return; 686 687 if (off) { 688 struct ifnet *ifp; 689 690 ifp = *(mtod(m, struct ifnet **)); 691 m->m_off += 2 * sizeof (u_short); 692 m->m_len -= 2 * sizeof (u_short); 693 *(mtod(m, struct ifnet **)) = ifp; 694 } 695 switch (eh->ether_type) { 696 #ifdef INET 697 case ETHERTYPE_IP: 698 /*if (ns->ns_ac.ac_ipaddr == 0) goto raw;*/ 699 schednetisr(NETISR_IP); 700 inq = &ipintrq; 701 break; 702 703 case ETHERTYPE_ARP: 704 arpinput(&ns->ns_ac, m); 705 return; 706 #endif 707 #ifdef NS 708 case ETHERTYPE_NS: 709 schednetisr(NETISR_NS); 710 inq = &nsintrq; 711 break; 712 713 #endif 714 default: 715 m_freem(m); 716 return; 717 } 718 719 if (IF_QFULL(inq)) { 720 IF_DROP(inq); 721 m_freem(m); 722 return; 723 } 724 IF_ENQUEUE(inq, m); 725 } 726 727 /* 728 * Ethernet output routine. 729 * Encapsulate a packet of type family for the local net. 730 * Use trailer local net encapsulation if enough data in first 731 * packet leaves a multiple of 512 bytes of data in remainder. 732 */ 733 neoutput(ifp, m0, dst) 734 struct ifnet *ifp; 735 struct mbuf *m0; 736 struct sockaddr *dst; 737 { 738 int type, s, error; 739 u_char edst[6]; 740 struct in_addr idst; 741 register struct ne_softc *ns = &ne_softc[ifp->if_unit]; 742 register struct mbuf *m = m0; 743 register struct ether_header *eh; 744 register int off; 745 extern struct ifnet loif; 746 struct mbuf *mcopy = (struct mbuf *)0; 747 int usetrailers; 748 749 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 750 error = ENETDOWN; 751 goto bad; 752 } 753 754 switch (dst->sa_family) { 755 #ifdef INET 756 case AF_INET: 757 idst = ((struct sockaddr_in *)dst)->sin_addr; 758 if (!arpresolve(&ns->ns_ac, m, &idst, edst, &usetrailers)) 759 return (0); /* if not yet resolved */ 760 if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, 761 sizeof(edst))) 762 mcopy = m_copy(m, 0, (int)M_COPYALL); 763 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 764 765 766 /* need per host negotiation */ 767 if (usetrailers && off > 0 && (off & 0x1ff) == 0 && 768 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 769 type = ETHERTYPE_TRAIL + (off>>9); 770 m->m_off -= 2 * sizeof (u_short); 771 m->m_len += 2 * sizeof (u_short); 772 *mtod(m, u_short *) = ntohs((u_short)ETHERTYPE_IP); 773 *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); 774 goto gottrailertype; 775 } 776 type = ETHERTYPE_IP; 777 off = 0; 778 goto gottype; 779 #endif 780 #ifdef NS 781 case AF_NS: 782 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 783 (caddr_t)edst, sizeof (edst)); 784 785 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, 786 sizeof(edst))) { 787 788 mcopy = m_copy(m, 0, (int)M_COPYALL); 789 } else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, 790 sizeof(edst))) { 791 792 return(looutput(&loif, m, dst)); 793 } 794 type = ETHERTYPE_NS; 795 off = 0; 796 goto gottype; 797 #endif 798 799 case AF_UNSPEC: 800 eh = (struct ether_header *)dst->sa_data; 801 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 802 type = eh->ether_type; 803 goto gottype; 804 805 default: 806 printf("ne%d: can't handle af%d\n", ifp->if_unit, 807 dst->sa_family); 808 error = EAFNOSUPPORT; 809 goto bad; 810 } 811 812 gottrailertype: 813 /* 814 * Packet to be sent as trailer: move first packet 815 * (control information) to end of chain. 816 */ 817 while (m->m_next) 818 m = m->m_next; 819 m->m_next = m0; 820 m = m0->m_next; 821 m0->m_next = 0; 822 m0 = m; 823 824 gottype: 825 /* 826 * Add local net header. If no space in first mbuf, 827 * allocate another. 828 */ 829 if (m->m_off > MMAXOFF || 830 MMINOFF + sizeof (struct ether_header) > m->m_off) { 831 m = m_get(M_DONTWAIT, MT_HEADER); 832 if (m == 0) { 833 error = ENOBUFS; 834 goto bad; 835 } 836 m->m_next = m0; 837 m->m_off = MMINOFF; 838 m->m_len = sizeof (struct ether_header); 839 } else { 840 m->m_off -= sizeof (struct ether_header); 841 m->m_len += sizeof (struct ether_header); 842 } 843 eh = mtod(m, struct ether_header *); 844 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 845 bcopy((caddr_t)ns->ns_addr, (caddr_t)eh->ether_shost, 846 sizeof (eh->ether_shost)); 847 eh->ether_type = htons((u_short)type); 848 849 /* 850 * Queue message on interface, and start output if interface 851 * not yet active. 852 */ 853 s = splimp(); 854 if (IF_QFULL(&ifp->if_snd)) { 855 IF_DROP(&ifp->if_snd); 856 splx(s); 857 m_freem(m); 858 return (ENOBUFS); 859 } 860 IF_ENQUEUE(&ifp->if_snd, m); 861 nestart(ns); 862 splx(s); 863 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 864 865 bad: 866 m_freem(m0); 867 if (mcopy) 868 m_freem(mcopy); 869 return (error); 870 } 871 872 /* 873 * Supporting routines 874 */ 875 876 /* 877 * Pull read data off a interface. 878 * Len is length of data, with local net header stripped. 879 * Off is non-zero if a trailer protocol was used, and 880 * gives the offset of the trailer information. 881 * We copy the trailer information and then all the normal 882 * data into mbufs. When full cluster sized units are present 883 * we copy into clusters. 884 */ 885 struct mbuf * 886 neget(buf, totlen, off0, ifp) 887 caddr_t buf; 888 int totlen, off0; 889 struct ifnet *ifp; 890 { 891 struct mbuf *top, **mp, *m, *p; 892 int off = off0, len; 893 register caddr_t cp = buf; 894 895 cp = buf + sizeof(struct ether_header); 896 top = 0; 897 mp = ⊤ 898 while (totlen > 0) { 899 u_char *mcp; 900 901 MGET(m, M_DONTWAIT, MT_DATA); 902 if (m == 0) 903 goto bad; 904 if (off) { 905 len = totlen - off; 906 cp = buf + off + sizeof (struct ether_header); 907 } else 908 len = totlen; 909 if (ifp) 910 len += sizeof(ifp); 911 if (len >= NBPG) { 912 MCLGET(m); 913 if (m->m_len == CLBYTES) 914 m->m_len = len = MIN(len, CLBYTES); 915 else 916 m->m_len = len = MIN(MLEN, len); 917 } else { 918 m->m_len = len = MIN(MLEN, len); 919 m->m_off = MMINOFF; 920 } 921 mcp = mtod(m, u_char *); 922 if (ifp) { 923 /* 924 * Prepend interface pointer to first mbuf. 925 */ 926 *(mtod(m, struct ifnet **)) = ifp; 927 mcp += sizeof(ifp); 928 len -= sizeof(ifp); 929 ifp = (struct ifnet *)0; 930 } 931 bcopy(cp, mcp, len); 932 cp += len ; mcp += len ; 933 *mp = m; 934 mp = &m->m_next; 935 if (off == 0) { 936 totlen -= len; 937 continue; 938 } 939 off += len; 940 if (off == totlen) { 941 cp = buf + sizeof (struct ether_header); 942 off = 0; 943 totlen = off0; 944 } 945 } 946 return (top); 947 bad: 948 m_freem(top); 949 return (0); 950 } 951 952 /* 953 * Map a chain of mbufs onto a network interface 954 * in preparation for an i/o operation. 955 * The argument chain of mbufs includes the local network 956 * header which is copied to be in the mapped, aligned 957 * i/o space. 958 */ 959 neput(cp, m) 960 register caddr_t cp; 961 register struct mbuf *m; 962 { 963 register struct mbuf *mp; 964 register int i; 965 int x, cc = 0, t; 966 caddr_t dp; 967 968 while (m) { 969 dp = mtod(m, char *); 970 bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len); 971 cp += m->m_len; 972 cc += m->m_len; 973 MFREE(m, mp); 974 m = mp; 975 } 976 return (max(cc, ETHERMIN + sizeof(struct ether_header))); 977 } 978 979 /* 980 * Process an ioctl request. 981 */ 982 neioctl(ifp, cmd, data) 983 register struct ifnet *ifp; 984 int cmd; 985 caddr_t data; 986 { 987 register struct ifaddr *ifa = (struct ifaddr *)data; 988 struct ne_softc *ns = &ne_softc[ifp->if_unit]; 989 struct ifreq *ifr = (struct ifreq *)data; 990 int s = splimp(), error = 0; 991 992 993 switch (cmd) { 994 995 case SIOCSIFADDR: 996 ifp->if_flags |= IFF_UP; 997 998 switch (ifa->ifa_addr.sa_family) { 999 #ifdef INET 1000 case AF_INET: 1001 neinit(ifp->if_unit); /* before arpwhohas */ 1002 ((struct arpcom *)ifp)->ac_ipaddr = 1003 IA_SIN(ifa)->sin_addr; 1004 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 1005 break; 1006 #endif 1007 #ifdef NS 1008 case AF_NS: 1009 { 1010 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 1011 1012 if (ns_nullhost(*ina)) 1013 ina->x_host = *(union ns_host *)(ns->ns_addr); 1014 else { 1015 /* 1016 * The manual says we can't change the address 1017 * while the receiver is armed, 1018 * so reset everything 1019 */ 1020 ifp->if_flags &= ~IFF_RUNNING; 1021 bcopy((caddr_t)ina->x_host.c_host, 1022 (caddr_t)ns->ns_addr, sizeof(ns->ns_addr)); 1023 } 1024 neinit(ifp->if_unit); /* does ne_setaddr() */ 1025 break; 1026 } 1027 #endif 1028 default: 1029 neinit(ifp->if_unit); 1030 break; 1031 } 1032 break; 1033 1034 case SIOCSIFFLAGS: 1035 if ((ifp->if_flags & IFF_UP) == 0 && 1036 ifp->if_flags & IFF_RUNNING) { 1037 ifp->if_flags &= ~IFF_RUNNING; 1038 outb(nec+ds_cmd,DSCM_STOP|DSCM_NODMA); 1039 } else if (ifp->if_flags & IFF_UP && 1040 (ifp->if_flags & IFF_RUNNING) == 0) 1041 neinit(ifp->if_unit); 1042 break; 1043 1044 #ifdef notdef 1045 case SIOCGHWADDR: 1046 bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data, 1047 sizeof(ns->ns_addr)); 1048 break; 1049 #endif 1050 1051 default: 1052 error = EINVAL; 1053 } 1054 splx(s); 1055 return (error); 1056 } 1057 1058 nesetaddr(ifp, sin) 1059 register struct ifnet *ifp; 1060 register struct sockaddr_in *sin; 1061 { 1062 #ifdef notdef 1063 ifp->if_addr = *(struct sockaddr *)sin; 1064 ifp->if_net = in_netof(sin->sin_addr); 1065 ifp->if_host[0] = in_lnaof(sin->sin_addr); 1066 if (nepaddr[ifp->if_unit][0] == '3') 1067 nepaddr[ifp->if_unit][0] = ifp->if_host[0] << 1; 1068 sin = (struct sockaddr_in *)&ifp->if_broadaddr; 1069 sin->sin_family = AF_INET; 1070 sin->sin_addr = in_makeaddr(ifp->if_net, INADDR_ANY); 1071 ifp->if_flags |= IFF_BROADCAST; 1072 #endif 1073 } 1074 #endif 1075