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