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

Defined functions

de_setaddr defined in line 797; used 2 times
deattach defined in line 159; used 2 times
deinit defined in line 244; used 5 times
deintr defined in line 394; used 2 times
deioctl defined in line 735; used 2 times
deoutput defined in line 614; used 2 times
deprobe defined in line 114; used 2 times
deread defined in line 522; used 2 times
derecv defined in line 478; used 1 times
dereset defined in line 226; used 2 times
destart defined in line 347; used 3 times
dewait defined in line 821; used 7 times

Defined variables

de_softc defined in line 112; used 14 times
dedebug defined in line 60; used 3 times
dedriver defined in line 65; never used
deinfo defined in line 63; used 8 times
destd defined in line 64; used 1 times
  • in line 66

Defined struct's

de_softc defined in line 82; used 18 times

Defined macros

DSF_LOCK defined in line 87; used 5 times
DSF_RUNNING defined in line 88; used 8 times
DSF_SETADDR defined in line 89; used 2 times
INCORE_BASE defined in line 100; used 3 times
INCORE_SIZE defined in line 107; used 1 times
LVAL_OFF defined in line 102; used 2 times
NRCV defined in line 58; used 6 times
NXMT defined in line 57; used 8 times
PCBB_OFFSET defined in line 103; used 1 times
RRENT_OFFSET defined in line 105; used 1 times
RVAL_OFF defined in line 101; used 3 times
UDBBUF_OFFSET defined in line 106; used 1 times
XRENT_OFFSET defined in line 104; used 1 times
dedataaddr defined in line 540; used 2 times
ds_addr defined in line 85; used 6 times
ds_if defined in line 84; used 14 times
Last modified: 1987-08-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1805
Valid CSS Valid XHTML 1.0 Strict