1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)if_de.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: #include "de.h"
   9: #include "enetfilter.h"
  10: #if NDE > 0
  11: 
  12: /*
  13:  * DEC DEUNA interface
  14:  *
  15:  *	Lou Salkind
  16:  *	New York University
  17:  *
  18:  * TODO:
  19:  *	timeout routine (get statistics)
  20:  */
  21: #include "../machine/pte.h"
  22: 
  23: #include "param.h"
  24: #include "systm.h"
  25: #include "mbuf.h"
  26: #include "buf.h"
  27: #include "protosw.h"
  28: #include "socket.h"
  29: #include "vmmac.h"
  30: #include "ioctl.h"
  31: #include "errno.h"
  32: #include "syslog.h"
  33: 
  34: #include "../net/if.h"
  35: #include "../net/netisr.h"
  36: #include "../net/route.h"
  37: 
  38: #ifdef INET
  39: #include "../netinet/in.h"
  40: #include "../netinet/in_systm.h"
  41: #include "../netinet/in_var.h"
  42: #include "../netinet/ip.h"
  43: #include "../netinet/if_ether.h"
  44: #endif
  45: 
  46: #ifdef NS
  47: #include "../netns/ns.h"
  48: #include "../netns/ns_if.h"
  49: #endif
  50: 
  51: #include "../vax/cpu.h"
  52: #include "../vax/mtpr.h"
  53: #include "if_dereg.h"
  54: #include "if_uba.h"
  55: #if NENETFILTER > 0
  56: #include "../net/enet.h"
  57: #endif	NENETFILTER > 0
  58: #include "../vaxuba/ubareg.h"
  59: #include "../vaxuba/ubavar.h"
  60: 
  61: #define NXMT    3   /* number of transmit buffers */
  62: #define NRCV    7   /* number of receive buffers (must be > 1) */
  63: 
  64: int dedebug = 0;
  65: 
  66: int deprobe(), deattach(), deintr();
  67: struct  uba_device *deinfo[NDE];
  68: u_short destd[] = { 0 };
  69: struct  uba_driver dedriver =
  70:     { deprobe, 0, deattach, 0, destd, "de", deinfo };
  71: int deinit(),deoutput(),deioctl(),dereset();
  72: 
  73: 
  74: /*
  75:  * Ethernet software status per interface.
  76:  *
  77:  * Each interface is referenced by a network interface structure,
  78:  * ds_if, which the routing code uses to locate the interface.
  79:  * This structure contains the output queue for the interface, its address, ...
  80:  * We also have, for each interface, a UBA interface structure, which
  81:  * contains information about the UNIBUS resources held by the interface:
  82:  * map registers, buffered data paths, etc.  Information is cached in this
  83:  * structure for use by the if_uba.c routines in running the interface
  84:  * efficiently.
  85:  */
  86: struct  de_softc {
  87:     struct  arpcom ds_ac;       /* Ethernet common part */
  88: #define ds_if   ds_ac.ac_if     /* network-visible interface */
  89: #define ds_addr ds_ac.ac_enaddr     /* hardware Ethernet address */
  90:     int ds_flags;
  91: #define DSF_LOCK    1       /* lock out destart */
  92: #define DSF_RUNNING 2       /* board is enabled */
  93: #define DSF_SETADDR 4       /* physical address is changed */
  94:     int ds_ubaddr;      /* map info for incore structs */
  95:     struct  ifubinfo ds_deuba;  /* unibus resource structure */
  96:     struct  ifrw ds_ifr[NRCV];  /* unibus receive maps */
  97:     struct  ifxmt ds_ifw[NXMT]; /* unibus xmt maps */
  98:     /* the following structures are always mapped in */
  99:     struct  de_pcbb ds_pcbb;    /* port control block */
 100:     struct  de_ring ds_xrent[NXMT]; /* transmit ring entrys */
 101:     struct  de_ring ds_rrent[NRCV]; /* receive ring entrys */
 102:     struct  de_udbbuf ds_udbbuf;    /* UNIBUS data buffer */
 103:     /* end mapped area */
 104: #define INCORE_BASE(p)  ((char *)&(p)->ds_pcbb)
 105: #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0]))
 106: #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0]))
 107: #define PCBB_OFFSET RVAL_OFF(ds_pcbb)
 108: #define XRENT_OFFSET    LVAL_OFF(ds_xrent)
 109: #define RRENT_OFFSET    LVAL_OFF(ds_rrent)
 110: #define UDBBUF_OFFSET   RVAL_OFF(ds_udbbuf)
 111: #define INCORE_SIZE RVAL_OFF(ds_xindex)
 112:     int ds_xindex;      /* UNA index into transmit chain */
 113:     int ds_rindex;      /* UNA index into receive chain */
 114:     int ds_xfree;       /* index for next transmit buffer */
 115:     int ds_nxmit;       /* # of transmits in progress */
 116: #if NENETFILTER > 0
 117:     short   ds_enetunit;        /* unit number for enet filtering */
 118: #endif	NENETFILTER > 0
 119: } de_softc[NDE];
 120: 
 121: deprobe(reg)
 122:     caddr_t reg;
 123: {
 124:     register int br, cvec;      /* r11, r10 value-result */
 125:     register struct dedevice *addr = (struct dedevice *)reg;
 126:     register i;
 127: 
 128: #ifdef lint
 129:     br = 0; cvec = br; br = cvec;
 130:     i = 0; derint(i); deintr(i);
 131: #endif
 132: 
 133:     addr->pcsr0 = PCSR0_RSET;
 134:     while ((addr->pcsr0 & PCSR0_INTR) == 0)
 135:         ;
 136:     /* make board interrupt by executing a GETPCBB command */
 137:     addr->pcsr0 = PCSR0_INTE;
 138:     addr->pcsr2 = 0;
 139:     addr->pcsr3 = 0;
 140:     addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;
 141:     DELAY(100000);
 142:     return(1);
 143: }
 144: 
 145: /*
 146:  * Interface exists: make available by filling in network interface
 147:  * record.  System will initialize the interface when it is ready
 148:  * to accept packets.  We get the ethernet address here.
 149:  */
 150: deattach(ui)
 151:     struct uba_device *ui;
 152: {
 153:     register struct de_softc *ds = &de_softc[ui->ui_unit];
 154:     register struct ifnet *ifp = &ds->ds_if;
 155:     register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
 156: 
 157:     ifp->if_unit = ui->ui_unit;
 158:     ifp->if_name = "de";
 159:     ifp->if_mtu = ETHERMTU;
 160:     ifp->if_flags = IFF_BROADCAST;
 161: 
 162:     /*
 163: 	 * Reset the board and temporarily map
 164: 	 * the pcbb buffer onto the Unibus.
 165: 	 */
 166:     addr->pcsr0 = PCSR0_RSET;
 167:     (void)dewait(ui, "reset");
 168: 
 169:     ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb,
 170:         sizeof (struct de_pcbb), 0);
 171:     addr->pcsr2 = ds->ds_ubaddr & 0xffff;
 172:     addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
 173:     addr->pclow = CMD_GETPCBB;
 174:     (void)dewait(ui, "pcbb");
 175: 
 176:     ds->ds_pcbb.pcbb0 = FC_RDPHYAD;
 177:     addr->pclow = CMD_GETCMD;
 178:     (void)dewait(ui, "read addr ");
 179: 
 180:     ubarelse(ui->ui_ubanum, &ds->ds_ubaddr);
 181:     bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
 182:         sizeof (ds->ds_addr));
 183:     printf("de%d: hardware address %s\n", ui->ui_unit,
 184:         ether_sprintf(ds->ds_addr));
 185:     ifp->if_init = deinit;
 186:     ifp->if_output = deoutput;
 187:     ifp->if_ioctl = deioctl;
 188:     ifp->if_reset = dereset;
 189:     ds->ds_deuba.iff_flags = UBA_CANTWAIT;
 190: #ifdef notdef
 191:     /* CAN WE USE BDP's ??? */
 192:     ds->ds_deuba.iff_flags |= UBA_NEEDBDP;
 193: #endif
 194: #if NENETFILTER > 0
 195:     {
 196:         struct endevp enp;
 197: 
 198:         enp.end_dev_type = ENDT_10MB;
 199:         enp.end_addr_len = sizeof(ds->ds_addr);
 200:         enp.end_hdr_len = sizeof(struct ether_header);
 201:         enp.end_MTU = ETHERMTU;
 202:         bcopy((caddr_t)ds->ds_addr,
 203:             (caddr_t)(enp.end_addr), sizeof(ds->ds_addr));
 204:         bcopy((caddr_t)etherbroadcastaddr,
 205:                 (caddr_t)(enp.end_broadaddr), sizeof(ds->ds_addr));
 206: 
 207:         ds->ds_enetunit = enetattach(&ds->ds_if, &enp);
 208:     }
 209: #endif NENETFILTER > 0
 210:     if_attach(ifp);
 211: }
 212: 
 213: /*
 214:  * Reset of interface after UNIBUS reset.
 215:  * If interface is on specified uba, reset its state.
 216:  */
 217: dereset(unit, uban)
 218:     int unit, uban;
 219: {
 220:     register struct uba_device *ui;
 221: 
 222:     if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 ||
 223:         ui->ui_ubanum != uban)
 224:         return;
 225:     printf(" de%d", unit);
 226:     de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
 227:     de_softc[unit].ds_flags &= ~(DSF_LOCK | DSF_RUNNING);
 228:     deinit(unit);
 229: }
 230: 
 231: /*
 232:  * Initialization of interface; clear recorded pending
 233:  * operations, and reinitialize UNIBUS usage.
 234:  */
 235: deinit(unit)
 236:     int unit;
 237: {
 238:     register struct de_softc *ds = &de_softc[unit];
 239:     register struct uba_device *ui = deinfo[unit];
 240:     register struct dedevice *addr;
 241:     register struct ifrw *ifrw;
 242:     register struct ifxmt *ifxp;
 243:     struct ifnet *ifp = &ds->ds_if;
 244:     int s;
 245:     struct de_ring *rp;
 246:     int incaddr;
 247: 
 248:     /* not yet, if address still unknown */
 249:     if (ifp->if_addrlist == (struct ifaddr *)0)
 250:         return;
 251: 
 252:     if (ds->ds_flags & DSF_RUNNING)
 253:         return;
 254:     if ((ifp->if_flags & IFF_RUNNING) == 0) {
 255:         if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum,
 256:             sizeof (struct ether_header), (int)btoc(ETHERMTU),
 257:             ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) {
 258:             printf("de%d: can't initialize\n", unit);
 259:             ds->ds_if.if_flags &= ~IFF_UP;
 260:             return;
 261:         }
 262:         ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds),
 263:             INCORE_SIZE, 0);
 264:     }
 265:     addr = (struct dedevice *)ui->ui_addr;
 266: 
 267:     /* set the pcbb block address */
 268:     incaddr = ds->ds_ubaddr + PCBB_OFFSET;
 269:     addr->pcsr2 = incaddr & 0xffff;
 270:     addr->pcsr3 = (incaddr >> 16) & 0x3;
 271:     addr->pclow = CMD_GETPCBB;
 272:     (void)dewait(ui, "pcbb");
 273: 
 274:     /* set the transmit and receive ring header addresses */
 275:     incaddr = ds->ds_ubaddr + UDBBUF_OFFSET;
 276:     ds->ds_pcbb.pcbb0 = FC_WTRING;
 277:     ds->ds_pcbb.pcbb2 = incaddr & 0xffff;
 278:     ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;
 279: 
 280:     incaddr = ds->ds_ubaddr + XRENT_OFFSET;
 281:     ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;
 282:     ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;
 283:     ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);
 284:     ds->ds_udbbuf.b_trlen = NXMT;
 285:     incaddr = ds->ds_ubaddr + RRENT_OFFSET;
 286:     ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;
 287:     ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;
 288:     ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);
 289:     ds->ds_udbbuf.b_rrlen = NRCV;
 290: 
 291:     addr->pclow = CMD_GETCMD;
 292:     (void)dewait(ui, "wtring");
 293: 
 294:     /* initialize the mode - enable hardware padding */
 295:     ds->ds_pcbb.pcbb0 = FC_WTMODE;
 296:     /* let hardware do padding - set MTCH bit on broadcast */
 297:     ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;
 298:     addr->pclow = CMD_GETCMD;
 299:     (void)dewait(ui, "wtmode");
 300: 
 301:     /* set up the receive and transmit ring entries */
 302:     ifxp = &ds->ds_ifw[0];
 303:     for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
 304:         rp->r_segbl = ifxp->ifw_info & 0xffff;
 305:         rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3;
 306:         rp->r_flags = 0;
 307:         ifxp++;
 308:     }
 309:     ifrw = &ds->ds_ifr[0];
 310:     for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
 311:         rp->r_slen = sizeof (struct de_buf);
 312:         rp->r_segbl = ifrw->ifrw_info & 0xffff;
 313:         rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
 314:         rp->r_flags = RFLG_OWN;     /* hang receive */
 315:         ifrw++;
 316:     }
 317: 
 318:     /* start up the board (rah rah) */
 319:     s = splimp();
 320:     ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0;
 321:     ds->ds_if.if_flags |= IFF_RUNNING;
 322:     destart(unit);              /* queue output packets */
 323:     addr->pclow = PCSR0_INTE;       /* avoid interlock */
 324:     ds->ds_flags |= DSF_RUNNING;        /* need before de_setaddr */
 325:     if (ds->ds_flags & DSF_SETADDR)
 326:         de_setaddr(ds->ds_addr, unit);
 327:     addr->pclow = CMD_START | PCSR0_INTE;
 328:     splx(s);
 329: }
 330: 
 331: /*
 332:  * Setup output on interface.
 333:  * Get another datagram to send off of the interface queue,
 334:  * and map it to the interface before starting the output.
 335:  */
 336: destart(unit)
 337:     int unit;
 338: {
 339:         int len;
 340:     struct uba_device *ui = deinfo[unit];
 341:     struct dedevice *addr = (struct dedevice *)ui->ui_addr;
 342:     register struct de_softc *ds = &de_softc[unit];
 343:     register struct de_ring *rp;
 344:     struct mbuf *m;
 345:     register int nxmit;
 346: 
 347:     /*
 348: 	 * the following test is necessary, since
 349: 	 * the code is not reentrant and we have
 350: 	 * multiple transmission buffers.
 351: 	 */
 352:     if (ds->ds_flags & DSF_LOCK)
 353:         return;
 354:     for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {
 355:         IF_DEQUEUE(&ds->ds_if.if_snd, m);
 356:         if (m == 0)
 357:             break;
 358:         rp = &ds->ds_xrent[ds->ds_xfree];
 359:         if (rp->r_flags & XFLG_OWN)
 360:             panic("deuna xmit in progress");
 361:         len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m);
 362:         if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
 363:             UBAPURGE(ds->ds_deuba.iff_uba,
 364:             ds->ds_ifw[ds->ds_xfree].ifw_bdp);
 365:         rp->r_slen = len;
 366:         rp->r_tdrerr = 0;
 367:         rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
 368: 
 369:         ds->ds_xfree++;
 370:         if (ds->ds_xfree == NXMT)
 371:             ds->ds_xfree = 0;
 372:     }
 373:     if (ds->ds_nxmit != nxmit) {
 374:         ds->ds_nxmit = nxmit;
 375:         if (ds->ds_flags & DSF_RUNNING)
 376:             addr->pclow = PCSR0_INTE|CMD_PDMD;
 377:     }
 378: }
 379: 
 380: /*
 381:  * Command done interrupt.
 382:  */
 383: deintr(unit)
 384:     int unit;
 385: {
 386:     struct uba_device *ui = deinfo[unit];
 387:     register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
 388:     register struct de_softc *ds = &de_softc[unit];
 389:     register struct de_ring *rp;
 390:     register struct ifxmt *ifxp;
 391:     short csr0;
 392: 
 393:     /* save flags right away - clear out interrupt bits */
 394:     csr0 = addr->pcsr0;
 395:     addr->pchigh = csr0 >> 8;
 396: 
 397: 
 398:     ds->ds_flags |= DSF_LOCK;   /* prevent entering destart */
 399:     /*
 400: 	 * if receive, put receive buffer on mbuf
 401: 	 * and hang the request again
 402: 	 */
 403:     derecv(unit);
 404: 
 405:     /*
 406: 	 * Poll transmit ring and check status.
 407: 	 * Be careful about loopback requests.
 408: 	 * Then free buffer space and check for
 409: 	 * more transmit requests.
 410: 	 */
 411:     for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {
 412:         rp = &ds->ds_xrent[ds->ds_xindex];
 413:         if (rp->r_flags & XFLG_OWN)
 414:             break;
 415:         ds->ds_if.if_opackets++;
 416:         ifxp = &ds->ds_ifw[ds->ds_xindex];
 417:         /* check for unusual conditions */
 418:         if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
 419:             if (rp->r_flags & XFLG_ERRS) {
 420:                 /* output error */
 421:                 ds->ds_if.if_oerrors++;
 422:                 if (dedebug)
 423:             printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",
 424:                     unit, rp->r_flags, XFLG_BITS,
 425:                     rp->r_tdrerr, XERR_BITS, rp->r_slen);
 426:             } else if (rp->r_flags & XFLG_ONE) {
 427:                 /* one collision */
 428:                 ds->ds_if.if_collisions++;
 429:             } else if (rp->r_flags & XFLG_MORE) {
 430:                 /* more than one collision */
 431:                 ds->ds_if.if_collisions += 2;   /* guess */
 432:             } else if (rp->r_flags & XFLG_MTCH) {
 433:                 /* received our own packet */
 434:                 ds->ds_if.if_ipackets++;
 435:                 deread(ds, &ifxp->ifrw,
 436:                     rp->r_slen - sizeof (struct ether_header));
 437:             }
 438:         }
 439:         if (ifxp->ifw_xtofree) {
 440:             m_freem(ifxp->ifw_xtofree);
 441:             ifxp->ifw_xtofree = 0;
 442:         }
 443:         /* check if next transmit buffer also finished */
 444:         ds->ds_xindex++;
 445:         if (ds->ds_xindex == NXMT)
 446:             ds->ds_xindex = 0;
 447:     }
 448:     ds->ds_flags &= ~DSF_LOCK;
 449:     destart(unit);
 450: 
 451:     if (csr0 & PCSR0_RCBI) {
 452:         if (dedebug)
 453:             log(LOG_WARNING, "de%d: buffer unavailable\n", unit);
 454:         addr->pclow = PCSR0_INTE|CMD_PDMD;
 455:     }
 456: }
 457: 
 458: /*
 459:  * Ethernet interface receiver interface.
 460:  * If input error just drop packet.
 461:  * Otherwise purge input buffered data path and examine
 462:  * packet to determine type.  If can't determine length
 463:  * from type, then have to drop packet.  Othewise decapsulate
 464:  * packet based on type and pass to type specific higher-level
 465:  * input routine.
 466:  */
 467: derecv(unit)
 468:     int unit;
 469: {
 470:     register struct de_softc *ds = &de_softc[unit];
 471:     register struct de_ring *rp;
 472:     int len;
 473: 
 474:     rp = &ds->ds_rrent[ds->ds_rindex];
 475:     while ((rp->r_flags & RFLG_OWN) == 0) {
 476:         ds->ds_if.if_ipackets++;
 477:         if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
 478:             UBAPURGE(ds->ds_deuba.iff_uba,
 479:             ds->ds_ifr[ds->ds_rindex].ifrw_bdp);
 480:         len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
 481:             - 4;    /* don't forget checksum! */
 482:         /* check for errors */
 483:         if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
 484:             (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
 485:             (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
 486:             len < ETHERMIN || len > ETHERMTU) {
 487:             ds->ds_if.if_ierrors++;
 488:             if (dedebug)
 489:             printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",
 490:                 unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,
 491:                 RERR_BITS, len);
 492:         } else
 493:             deread(ds, &ds->ds_ifr[ds->ds_rindex], len);
 494: 
 495:         /* hang the receive buffer again */
 496:         rp->r_lenerr = 0;
 497:         rp->r_flags = RFLG_OWN;
 498: 
 499:         /* check next receive buffer */
 500:         ds->ds_rindex++;
 501:         if (ds->ds_rindex == NRCV)
 502:             ds->ds_rindex = 0;
 503:         rp = &ds->ds_rrent[ds->ds_rindex];
 504:     }
 505: }
 506: 
 507: /*
 508:  * Pass a packet to the higher levels.
 509:  * We deal with the trailer protocol here.
 510:  */
 511: deread(ds, ifrw, len)
 512:     register struct de_softc *ds;
 513:     struct ifrw *ifrw;
 514:     int len;
 515: {
 516:     struct ether_header *eh;
 517:         struct mbuf *m;
 518:     int off, resid;
 519:     int s;
 520:     register struct ifqueue *inq;
 521: 
 522:     /*
 523: 	 * Deal with trailer protocol: if type is trailer type
 524: 	 * get true type from first 16-bit word past data.
 525: 	 * Remember that type was trailer by setting off.
 526: 	 */
 527:     eh = (struct ether_header *)ifrw->ifrw_addr;
 528:     eh->ether_type = ntohs((u_short)eh->ether_type);
 529: #define dedataaddr(eh, off, type)   ((type)(((caddr_t)((eh)+1)+(off))))
 530:     if (eh->ether_type >= ETHERTYPE_TRAIL &&
 531:         eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
 532:         off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
 533:         if (off >= ETHERMTU)
 534:             return;     /* sanity */
 535:         eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
 536:         resid = ntohs(*(dedataaddr(eh, off+2, u_short *)));
 537:         if (off + resid > len)
 538:             return;     /* sanity */
 539:         len = off + resid;
 540:     } else
 541:         off = 0;
 542:     if (len == 0)
 543:         return;
 544: 
 545:     /*
 546: 	 * Pull packet off interface.  Off is nonzero if packet
 547: 	 * has trailing header; if_ubaget will then force this header
 548: 	 * information to be at the front, but we still have to drop
 549: 	 * the type and length which are at the front of any trailer data.
 550: 	 */
 551:     m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if);
 552:     if (m == 0)
 553:         return;
 554:     if (off) {
 555:         struct ifnet *ifp;
 556: 
 557:         ifp = *(mtod(m, struct ifnet **));
 558:         m->m_off += 2 * sizeof (u_short);
 559:         m->m_len -= 2 * sizeof (u_short);
 560:         *(mtod(m, struct ifnet **)) = ifp;
 561:     }
 562:     switch (eh->ether_type) {
 563: 
 564: #ifdef INET
 565:     case ETHERTYPE_IP:
 566:         schednetisr(NETISR_IP);
 567:         inq = &ipintrq;
 568:         break;
 569: 
 570:     case ETHERTYPE_ARP:
 571:         arpinput(&ds->ds_ac, m);
 572:         return;
 573: #endif
 574: #ifdef NS
 575:     case ETHERTYPE_NS:
 576:         schednetisr(NETISR_NS);
 577:         inq = &nsintrq;
 578:         break;
 579: 
 580: #endif
 581: #if NENETFILTER > 0
 582:     default:
 583:     {
 584:         register struct mbuf *mtop;
 585:         register short *sp,*sp2;
 586:         int i;
 587:         /*
 588: 		 * We need the local net header after all.  Oh well,
 589: 		 * this could be improved.
 590: 		 */
 591:         MGET(mtop, M_DONTWAIT, MT_DATA);
 592:         if (mtop == 0) {    /* no more mbufs? */
 593:             m_freem(m);     /* wasted effort */
 594:             return;
 595:         }
 596:         eh->ether_type = htons((u_short)eh->ether_type);
 597:         sp = (short *) eh;
 598:         sp2 = mtod(mtop, short *);
 599:         for (i = 0 ; i < (sizeof(struct ether_header)/2) ; i++)
 600:             *sp2++ = *sp++;
 601:         mtop->m_len = sizeof(struct ether_header);
 602:         IF_ADJ(m);
 603:         mtop->m_next = m;
 604:         enetFilter(ds->ds_enetunit, mtop,
 605:                 (len + sizeof(struct ether_header)) );
 606:         return;
 607:     }
 608: #else
 609:     default:
 610:         m_freem(m);
 611:         return;
 612: #endif NENETFILTER > 0
 613:     }
 614: 
 615:     s = splimp();
 616:     if (IF_QFULL(inq)) {
 617:         IF_DROP(inq);
 618:         splx(s);
 619:         m_freem(m);
 620:         return;
 621:     }
 622:     IF_ENQUEUE(inq, m);
 623:     splx(s);
 624: }
 625: 
 626: /*
 627:  * Ethernet output routine.
 628:  * Encapsulate a packet of type family for the local net.
 629:  * Use trailer local net encapsulation if enough data in first
 630:  * packet leaves a multiple of 512 bytes of data in remainder.
 631:  */
 632: deoutput(ifp, m0, dst)
 633:     struct ifnet *ifp;
 634:     struct mbuf *m0;
 635:     struct sockaddr *dst;
 636: {
 637:     int type, s, error;
 638:     u_char edst[6];
 639:     struct in_addr idst;
 640:     register struct de_softc *ds = &de_softc[ifp->if_unit];
 641:     register struct mbuf *m = m0;
 642:     register struct ether_header *eh;
 643:     register int off;
 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:     switch (dst->sa_family) {
 651: 
 652: #ifdef INET
 653:     case AF_INET:
 654:         idst = ((struct sockaddr_in *)dst)->sin_addr;
 655:         if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers))
 656:             return (0); /* if not yet resolved */
 657:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
 658:         if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
 659:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
 660:             type = ETHERTYPE_TRAIL + (off>>9);
 661:             m->m_off -= 2 * sizeof (u_short);
 662:             m->m_len += 2 * sizeof (u_short);
 663:             *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
 664:             *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
 665:             goto gottrailertype;
 666:         }
 667:         type = ETHERTYPE_IP;
 668:         off = 0;
 669:         goto gottype;
 670: #endif
 671: #ifdef NS
 672:     case AF_NS:
 673:         type = ETHERTYPE_NS;
 674:         bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
 675:         (caddr_t)edst, sizeof (edst));
 676:         off = 0;
 677:         goto gottype;
 678: #endif
 679: 
 680: #if NENETFILTER > 0
 681:     case AF_IMPLINK:
 682:         eh = mtod(m, struct ether_header *);
 683:         goto gotheader;
 684: #endif NENETFILTER > 0
 685: 
 686:     case AF_UNSPEC:
 687:         eh = (struct ether_header *)dst->sa_data;
 688:         bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
 689:         type = eh->ether_type;
 690:         goto gottype;
 691: 
 692:     default:
 693:         printf("de%d: can't handle af%d\n", ifp->if_unit,
 694:             dst->sa_family);
 695:         error = EAFNOSUPPORT;
 696:         goto bad;
 697:     }
 698: 
 699: gottrailertype:
 700:     /*
 701: 	 * Packet to be sent as trailer: move first packet
 702: 	 * (control information) to end of chain.
 703: 	 */
 704:     while (m->m_next)
 705:         m = m->m_next;
 706:     m->m_next = m0;
 707:     m = m0->m_next;
 708:     m0->m_next = 0;
 709:     m0 = m;
 710: 
 711: gottype:
 712:     /*
 713: 	 * Add local net header.  If no space in first mbuf,
 714: 	 * allocate another.
 715: 	 */
 716:     if (m->m_off > MMAXOFF ||
 717:         MMINOFF + sizeof (struct ether_header) > m->m_off) {
 718:         m = m_get(M_DONTWAIT, MT_HEADER);
 719:         if (m == 0) {
 720:             error = ENOBUFS;
 721:             goto bad;
 722:         }
 723:         m->m_next = m0;
 724:         m->m_off = MMINOFF;
 725:         m->m_len = sizeof (struct ether_header);
 726:     } else {
 727:         m->m_off -= sizeof (struct ether_header);
 728:         m->m_len += sizeof (struct ether_header);
 729:     }
 730:     eh = mtod(m, struct ether_header *);
 731:     eh->ether_type = htons((u_short)type);
 732:     bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
 733:     /* DEUNA fills in source address */
 734: 
 735: #if NENETFILTER > 0
 736: gotheader:
 737: #endif NENETFILTER > 0
 738:     /*
 739: 	 * Queue message on interface, and start output if interface
 740: 	 * not yet active.
 741: 	 */
 742:     s = splimp();
 743:     if (IF_QFULL(&ifp->if_snd)) {
 744:         IF_DROP(&ifp->if_snd);
 745:         splx(s);
 746:         m_freem(m);
 747:         return (ENOBUFS);
 748:     }
 749:     IF_ENQUEUE(&ifp->if_snd, m);
 750:     destart(ifp->if_unit);
 751:     splx(s);
 752:     return (0);
 753: 
 754: bad:
 755:     m_freem(m0);
 756:     return (error);
 757: }
 758: 
 759: /*
 760:  * Process an ioctl request.
 761:  */
 762: deioctl(ifp, cmd, data)
 763:     register struct ifnet *ifp;
 764:     int cmd;
 765:     caddr_t data;
 766: {
 767:     register struct ifaddr *ifa = (struct ifaddr *)data;
 768:     register struct de_softc *ds = &de_softc[ifp->if_unit];
 769:     int s = splimp(), error = 0;
 770: 
 771:     switch (cmd) {
 772: 
 773:     case SIOCSIFADDR:
 774:         ifp->if_flags |= IFF_UP;
 775:         deinit(ifp->if_unit);
 776: 
 777:         switch (ifa->ifa_addr.sa_family) {
 778: #ifdef INET
 779:         case AF_INET:
 780:             ((struct arpcom *)ifp)->ac_ipaddr =
 781:                 IA_SIN(ifa)->sin_addr;
 782:             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
 783:             break;
 784: #endif
 785: #ifdef NS
 786:         case AF_NS:
 787:             {
 788:             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 789: 
 790:             if (ns_nullhost(*ina))
 791:                 ina->x_host = *(union ns_host *)(ds->ds_addr);
 792:             else
 793:                 de_setaddr(ina->x_host.c_host,ifp->if_unit);
 794:             break;
 795:             }
 796: #endif
 797:         }
 798:         break;
 799: 
 800:     case SIOCSIFFLAGS:
 801:         if ((ifp->if_flags & IFF_UP) == 0 &&
 802:             ds->ds_flags & DSF_RUNNING) {
 803:             ((struct dedevice *)
 804:                (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET;
 805:             ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING);
 806:         } else if (ifp->if_flags & IFF_UP &&
 807:             (ds->ds_flags & DSF_RUNNING) == 0)
 808:             deinit(ifp->if_unit);
 809:         break;
 810: 
 811:     default:
 812:         error = EINVAL;
 813:     }
 814:     splx(s);
 815:     return (error);
 816: }
 817: 
 818: /*
 819:  * set ethernet address for unit
 820:  */
 821: de_setaddr(physaddr, unit)
 822:     u_char *physaddr;
 823:     int unit;
 824: {
 825:     register struct de_softc *ds = &de_softc[unit];
 826:     struct uba_device *ui = deinfo[unit];
 827:     register struct dedevice *addr= (struct dedevice *)ui->ui_addr;
 828: 
 829:     if (! (ds->ds_flags & DSF_RUNNING))
 830:         return;
 831: 
 832:     bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6);
 833:     ds->ds_pcbb.pcbb0 = FC_WTPHYAD;
 834:     addr->pclow = PCSR0_INTE|CMD_GETCMD;
 835:     if (dewait(ui, "address change") == 0) {
 836:         ds->ds_flags |= DSF_SETADDR;
 837:         bcopy(physaddr, ds->ds_addr, 6);
 838:     }
 839: }
 840: 
 841: /*
 842:  * Await completion of the named function
 843:  * and check for errors.
 844:  */
 845: dewait(ui, fn)
 846:     register struct uba_device *ui;
 847:     char *fn;
 848: {
 849:     register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
 850:     register csr0;
 851: 
 852:     while ((addr->pcsr0 & PCSR0_INTR) == 0)
 853:         ;
 854:     csr0 = addr->pcsr0;
 855:     addr->pchigh = csr0 >> 8;
 856:     if (csr0 & PCSR0_PCEI)
 857:         printf("de%d: %s failed, csr0=%b csr1=%b\n",
 858:             ui->ui_unit, fn, csr0, PCSR0_BITS,
 859:             addr->pcsr1, PCSR1_BITS);
 860:     return (csr0 & PCSR0_PCEI);
 861: }
 862: #endif

Defined functions

de_setaddr defined in line 821; used 2 times
deattach defined in line 150; used 2 times
deinit defined in line 235; used 5 times
deintr defined in line 383; used 2 times
deioctl defined in line 762; used 2 times
deoutput defined in line 632; used 2 times
deprobe defined in line 121; used 2 times
deread defined in line 511; used 2 times
derecv defined in line 467; used 1 times
dereset defined in line 217; used 2 times
destart defined in line 336; used 3 times
dewait defined in line 845; used 7 times

Defined variables

de_softc defined in line 119; used 14 times
dedebug defined in line 64; used 3 times
dedriver defined in line 69; never used
deinfo defined in line 67; used 7 times

Defined struct's

de_softc defined in line 86; used 18 times

Defined macros

DSF_LOCK defined in line 91; used 5 times
DSF_RUNNING defined in line 92; used 8 times
DSF_SETADDR defined in line 93; used 2 times
INCORE_BASE defined in line 104; used 3 times
INCORE_SIZE defined in line 111; used 1 times
LVAL_OFF defined in line 106; used 2 times
NRCV defined in line 62; used 6 times
NXMT defined in line 61; used 8 times
PCBB_OFFSET defined in line 107; used 1 times
RRENT_OFFSET defined in line 109; used 1 times
RVAL_OFF defined in line 105; used 3 times
UDBBUF_OFFSET defined in line 110; used 1 times
XRENT_OFFSET defined in line 108; used 1 times
dedataaddr defined in line 529; used 2 times
ds_addr defined in line 89; used 10 times
ds_if defined in line 88; used 15 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1336
Valid CSS Valid XHTML 1.0 Strict