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

Defined functions

de_setaddr defined in line 760; used 2 times
deattach defined in line 143; used 2 times
deinit defined in line 212; used 5 times
deintr defined in line 360; used 3 times
deioctl defined in line 701; used 2 times
deoutput defined in line 580; used 2 times
deprobe defined in line 114; used 2 times
deread defined in line 488; used 2 times
derecv defined in line 444; used 1 times
dereset defined in line 194; used 2 times
destart defined in line 313; used 3 times
dewait defined in line 784; 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; used 1 times
deinfo defined in line 63; used 7 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 506; used 2 times
ds_addr defined in line 85; used 6 times
ds_if defined in line 84; used 14 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3102
Valid CSS Valid XHTML 1.0 Strict