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_dmc.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "dmc.h"
  10: #if NDMC > 0
  11: 
  12: /*
  13:  * DMC11 device driver, internet version
  14:  *
  15:  *	Bill Nesheim
  16:  *	Cornell University
  17:  *
  18:  *	Lou Salkind
  19:  *	New York University
  20:  */
  21: 
  22: /* #define DEBUG	/* for base table dump on fatal error */
  23: 
  24: #include "../machine/pte.h"
  25: 
  26: #include "param.h"
  27: #include "systm.h"
  28: #include "mbuf.h"
  29: #include "buf.h"
  30: #include "ioctl.h"      /* must precede tty.h */
  31: #include "tty.h"
  32: #include "protosw.h"
  33: #include "socket.h"
  34: #include "syslog.h"
  35: #include "vmmac.h"
  36: #include "errno.h"
  37: 
  38: #include "../net/if.h"
  39: #include "../net/netisr.h"
  40: #include "../net/route.h"
  41: 
  42: #ifdef  INET
  43: #include "../netinet/in.h"
  44: #include "../netinet/in_systm.h"
  45: #include "../netinet/in_var.h"
  46: #include "../netinet/ip.h"
  47: #endif
  48: 
  49: #include "../vax/cpu.h"
  50: #include "../vax/mtpr.h"
  51: #include "if_uba.h"
  52: #include "if_dmc.h"
  53: #include "../vaxuba/ubareg.h"
  54: #include "../vaxuba/ubavar.h"
  55: 
  56: #include "../h/time.h"
  57: #include "../h/kernel.h"
  58: 
  59: int dmctimer;           /* timer started? */
  60: int dmc_timeout = 8;        /* timeout value */
  61: int dmcwatch();
  62: 
  63: /*
  64:  * Driver information for auto-configuration stuff.
  65:  */
  66: int dmcprobe(), dmcattach(), dmcinit(), dmcioctl();
  67: int dmcoutput(), dmcreset();
  68: struct  uba_device *dmcinfo[NDMC];
  69: u_short dmcstd[] = { 0 };
  70: struct  uba_driver dmcdriver =
  71:     { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
  72: 
  73: #define NRCV 7
  74: #define NXMT 3
  75: #define NCMDS   (NRCV+NXMT+4)   /* size of command queue */
  76: 
  77: #define printd if(dmcdebug)printf
  78: int dmcdebug = 0;
  79: 
  80: /* error reporting intervals */
  81: #define DMC_RPNBFS  50
  82: #define DMC_RPDSC   1
  83: #define DMC_RPTMO   10
  84: #define DMC_RPDCK   10
  85: 
  86: struct  dmc_command {
  87:     char    qp_cmd;     /* command */
  88:     short   qp_ubaddr;  /* buffer address */
  89:     short   qp_cc;      /* character count || XMEM */
  90:     struct  dmc_command *qp_next;   /* next command on queue */
  91: };
  92: 
  93: struct dmcbufs {
  94:     int ubinfo;     /* from uballoc */
  95:     short   cc;     /* buffer size */
  96:     short   flags;      /* access control */
  97: };
  98: #define DBUF_OURS   0   /* buffer is available */
  99: #define DBUF_DMCS   1   /* buffer claimed by somebody */
 100: #define DBUF_XMIT   4   /* transmit buffer */
 101: #define DBUF_RCV    8   /* receive buffer */
 102: 
 103: 
 104: /*
 105:  * DMC software status per interface.
 106:  *
 107:  * Each interface is referenced by a network interface structure,
 108:  * sc_if, which the routing code uses to locate the interface.
 109:  * This structure contains the output queue for the interface, its address, ...
 110:  * We also have, for each interface, a  set of 7 UBA interface structures
 111:  * for each, which
 112:  * contain information about the UNIBUS resources held by the interface:
 113:  * map registers, buffered data paths, etc.  Information is cached in this
 114:  * structure for use by the if_uba.c routines in running the interface
 115:  * efficiently.
 116:  */
 117: struct dmc_softc {
 118:     struct  ifnet sc_if;        /* network-visible interface */
 119:     struct  dmcbufs sc_rbufs[NRCV]; /* receive buffer info */
 120:     struct  dmcbufs sc_xbufs[NXMT]; /* transmit buffer info */
 121:     struct  ifubinfo sc_ifuba;  /* UNIBUS resources */
 122:     struct  ifrw sc_ifr[NRCV];  /* UNIBUS receive buffer maps */
 123:     struct  ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */
 124:     short   sc_oused;       /* output buffers currently in use */
 125:     short   sc_iused;       /* input buffers given to DMC */
 126:     short   sc_flag;        /* flags */
 127:     int sc_nticks;      /* seconds since last interrupt */
 128:     int sc_ubinfo;      /* UBA mapping info for base table */
 129:     int sc_errors[4];       /* non-fatal error counters */
 130: #define sc_datck sc_errors[0]
 131: #define sc_timeo sc_errors[1]
 132: #define sc_nobuf sc_errors[2]
 133: #define sc_disc  sc_errors[3]
 134:     /* command queue stuff */
 135:     struct  dmc_command sc_cmdbuf[NCMDS];
 136:     struct  dmc_command *sc_qhead;  /* head of command queue */
 137:     struct  dmc_command *sc_qtail;  /* tail of command queue */
 138:     struct  dmc_command *sc_qactive;    /* command in progress */
 139:     struct  dmc_command *sc_qfreeh; /* head of list of free cmd buffers */
 140:     struct  dmc_command *sc_qfreet; /* tail of list of free cmd buffers */
 141:     /* end command queue stuff */
 142: } dmc_softc[NDMC];
 143: 
 144: /* flags */
 145: #define DMC_ALLOC   0x01        /* unibus resources allocated */
 146: #define DMC_BMAPPED 0x02        /* base table mapped */
 147: #define DMC_RESTART 0x04        /* software restart in progress */
 148: #define DMC_ACTIVE  0x08        /* device active */
 149: #define DMC_RUNNING 0x20        /* device initialized */
 150: 
 151: struct dmc_base {
 152:     short   d_base[128];        /* DMC base table */
 153: } dmc_base[NDMC];
 154: 
 155: /* queue manipulation macros */
 156: #define QUEUE_AT_HEAD(qp, head, tail) \
 157:     (qp)->qp_next = (head); \
 158:     (head) = (qp); \
 159:     if ((tail) == (struct dmc_command *) 0) \
 160:         (tail) = (head)
 161: 
 162: #define QUEUE_AT_TAIL(qp, head, tail) \
 163:     if ((tail)) \
 164:         (tail)->qp_next = (qp); \
 165:     else \
 166:         (head) = (qp); \
 167:     (qp)->qp_next = (struct dmc_command *) 0; \
 168:     (tail) = (qp)
 169: 
 170: #define DEQUEUE(head, tail) \
 171:     (head) = (head)->qp_next;\
 172:     if ((head) == (struct dmc_command *) 0)\
 173:         (tail) = (head)
 174: 
 175: dmcprobe(reg)
 176:     caddr_t reg;
 177: {
 178:     register int br, cvec;
 179:     register struct dmcdevice *addr = (struct dmcdevice *)reg;
 180:     register int i;
 181: 
 182: #ifdef lint
 183:     br = 0; cvec = br; br = cvec;
 184:     dmcrint(0); dmcxint(0);
 185: #endif
 186:     addr->bsel1 = DMC_MCLR;
 187:     for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
 188:         ;
 189:     if ((addr->bsel1 & DMC_RUN) == 0) {
 190:         printf("dmcprobe: can't start device\n" );
 191:         return (0);
 192:     }
 193:     addr->bsel0 = DMC_RQI|DMC_IEI;
 194:     /* let's be paranoid */
 195:     addr->bsel0 |= DMC_RQI|DMC_IEI;
 196:     DELAY(1000000);
 197:     addr->bsel1 = DMC_MCLR;
 198:     for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
 199:         ;
 200:     return (1);
 201: }
 202: 
 203: /*
 204:  * Interface exists: make available by filling in network interface
 205:  * record.  System will initialize the interface when it is ready
 206:  * to accept packets.
 207:  */
 208: dmcattach(ui)
 209:     register struct uba_device *ui;
 210: {
 211:     register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
 212: 
 213:     sc->sc_if.if_unit = ui->ui_unit;
 214:     sc->sc_if.if_name = "dmc";
 215:     sc->sc_if.if_mtu = DMCMTU;
 216:     sc->sc_if.if_init = dmcinit;
 217:     sc->sc_if.if_output = dmcoutput;
 218:     sc->sc_if.if_ioctl = dmcioctl;
 219:     sc->sc_if.if_reset = dmcreset;
 220:     sc->sc_if.if_flags = IFF_POINTOPOINT;
 221:     sc->sc_ifuba.iff_flags = UBA_CANTWAIT;
 222: 
 223:     if (dmctimer == 0) {
 224:         dmctimer = 1;
 225:         timeout(dmcwatch, (caddr_t) 0, hz);
 226:     }
 227:     if_attach(&sc->sc_if);
 228: }
 229: 
 230: /*
 231:  * Reset of interface after UNIBUS reset.
 232:  * If interface is on specified UBA, reset its state.
 233:  */
 234: dmcreset(unit, uban)
 235:     int unit, uban;
 236: {
 237:     register struct uba_device *ui;
 238:     register struct dmc_softc *sc = &dmc_softc[unit];
 239: 
 240:     if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 ||
 241:         ui->ui_ubanum != uban)
 242:         return;
 243:     printf(" dmc%d", unit);
 244:     sc->sc_flag = 0;
 245:     sc->sc_if.if_flags &= ~IFF_RUNNING;
 246:     dmcinit(unit);
 247: }
 248: 
 249: /*
 250:  * Initialization of interface; reinitialize UNIBUS usage.
 251:  */
 252: dmcinit(unit)
 253:     int unit;
 254: {
 255:     register struct dmc_softc *sc = &dmc_softc[unit];
 256:     register struct uba_device *ui = dmcinfo[unit];
 257:     register struct dmcdevice *addr;
 258:     register struct ifnet *ifp = &sc->sc_if;
 259:     register struct ifrw *ifrw;
 260:     register struct ifxmt *ifxp;
 261:     register struct dmcbufs *rp;
 262:     register struct dmc_command *qp;
 263:     struct ifaddr *ifa;
 264:     int base;
 265:     int s;
 266: 
 267:     addr = (struct dmcdevice *)ui->ui_addr;
 268: 
 269:     /*
 270: 	 * Check to see that an address has been set
 271: 	 * (both local and destination for an address family).
 272: 	 */
 273:     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
 274:         if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family)
 275:             break;
 276:     if (ifa == (struct ifaddr *) 0)
 277:         return;
 278: 
 279:     if ((addr->bsel1&DMC_RUN) == 0) {
 280:         printf("dmcinit: DMC not running\n");
 281:         ifp->if_flags &= ~IFF_UP;
 282:         return;
 283:     }
 284:     /* map base table */
 285:     if ((sc->sc_flag & DMC_BMAPPED) == 0) {
 286:         sc->sc_ubinfo = uballoc(ui->ui_ubanum,
 287:             (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0);
 288:         sc->sc_flag |= DMC_BMAPPED;
 289:     }
 290:     /* initialize UNIBUS resources */
 291:     sc->sc_iused = sc->sc_oused = 0;
 292:     if ((ifp->if_flags & IFF_RUNNING) == 0) {
 293:         if (if_ubaminit(&sc->sc_ifuba, ui->ui_ubanum,
 294:             sizeof(struct dmc_header), (int)btoc(DMCMTU),
 295:             sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) {
 296:             printf("dmc%d: can't allocate uba resources\n", unit);
 297:             ifp->if_flags &= ~IFF_UP;
 298:             return;
 299:         }
 300:         ifp->if_flags |= IFF_RUNNING;
 301:     }
 302:     sc->sc_flag |= DMC_RUNNING;
 303: 
 304:     /* initialize buffer pool */
 305:     /* receives */
 306:     ifrw = &sc->sc_ifr[0];
 307:     for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
 308:         rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
 309:         rp->cc = DMCMTU + sizeof (struct dmc_header);
 310:         rp->flags = DBUF_OURS|DBUF_RCV;
 311:         ifrw++;
 312:     }
 313:     /* transmits */
 314:     ifxp = &sc->sc_ifw[0];
 315:     for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
 316:         rp->ubinfo = ifxp->ifw_info & 0x3ffff;
 317:         rp->cc = 0;
 318:         rp->flags = DBUF_OURS|DBUF_XMIT;
 319:         ifxp++;
 320:     }
 321: 
 322:     /* set up command queues */
 323:     sc->sc_qfreeh = sc->sc_qfreet
 324:          = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive =
 325:         (struct dmc_command *)0;
 326:     /* set up free command buffer list */
 327:     for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) {
 328:         QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
 329:     }
 330: 
 331:     /* base in */
 332:     base = sc->sc_ubinfo & 0x3ffff;
 333:     dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM);
 334:     /* specify half duplex operation, flags tell if primary */
 335:     /* or secondary station */
 336:     if (ui->ui_flags == 0)
 337:         /* use DDCMP mode in full duplex */
 338:         dmcload(sc, DMC_CNTLI, 0, 0);
 339:     else if (ui->ui_flags == 1)
 340:         /* use MAINTENENCE mode */
 341:         dmcload(sc, DMC_CNTLI, 0, DMC_MAINT );
 342:     else if (ui->ui_flags == 2)
 343:         /* use DDCMP half duplex as primary station */
 344:         dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX);
 345:     else if (ui->ui_flags == 3)
 346:         /* use DDCMP half duplex as secondary station */
 347:         dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC);
 348: 
 349:     /* enable operation done interrupts */
 350:     sc->sc_flag &= ~DMC_ACTIVE;
 351:     while ((addr->bsel2 & DMC_IEO) == 0)
 352:         addr->bsel2 |= DMC_IEO;
 353:     s = spl5();
 354:     /* queue first NRCV buffers for DMC to fill */
 355:     for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
 356:         rp->flags |= DBUF_DMCS;
 357:         dmcload(sc, DMC_READ, rp->ubinfo,
 358:             (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc));
 359:         sc->sc_iused++;
 360:     }
 361:     splx(s);
 362: }
 363: 
 364: /*
 365:  * Start output on interface.  Get another datagram
 366:  * to send from the interface queue and map it to
 367:  * the interface before starting output.
 368:  *
 369:  * Must be called at spl 5
 370:  */
 371: dmcstart(dev)
 372:     dev_t dev;
 373: {
 374:     int unit = minor(dev);
 375:     register struct dmc_softc *sc = &dmc_softc[unit];
 376:     struct mbuf *m;
 377:     register struct dmcbufs *rp;
 378:     register int n;
 379: 
 380:     /*
 381: 	 * Dequeue up to NXMT requests and map them to the UNIBUS.
 382: 	 * If no more requests, or no dmc buffers available, just return.
 383: 	 */
 384:     n = 0;
 385:     for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) {
 386:         /* find an available buffer */
 387:         if ((rp->flags & DBUF_DMCS) == 0) {
 388:             IF_DEQUEUE(&sc->sc_if.if_snd, m);
 389:             if (m == 0)
 390:                 return;
 391:             /* mark it dmcs */
 392:             rp->flags |= (DBUF_DMCS);
 393:             /*
 394: 			 * Have request mapped to UNIBUS for transmission
 395: 			 * and start the output.
 396: 			 */
 397:             rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m);
 398:             rp->cc &= DMC_CCOUNT;
 399:             sc->sc_oused++;
 400:             dmcload(sc, DMC_WRITE, rp->ubinfo,
 401:                 rp->cc | ((rp->ubinfo>>2)&DMC_XMEM));
 402:         }
 403:         n++;
 404:     }
 405: }
 406: 
 407: /*
 408:  * Utility routine to load the DMC device registers.
 409:  */
 410: dmcload(sc, type, w0, w1)
 411:     register struct dmc_softc *sc;
 412:     int type, w0, w1;
 413: {
 414:     register struct dmcdevice *addr;
 415:     register int unit, sps;
 416:     register struct dmc_command *qp;
 417: 
 418:     unit = sc - dmc_softc;
 419:     addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
 420:     sps = spl5();
 421: 
 422:     /* grab a command buffer from the free list */
 423:     if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0)
 424:         panic("dmc command queue overflow");
 425:     DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);
 426: 
 427:     /* fill in requested info */
 428:     qp->qp_cmd = (type | DMC_RQI);
 429:     qp->qp_ubaddr = w0;
 430:     qp->qp_cc = w1;
 431: 
 432:     if (sc->sc_qactive) {   /* command in progress */
 433:         if (type == DMC_READ) {
 434:             QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail);
 435:         } else {
 436:             QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail);
 437:         }
 438:     } else {    /* command port free */
 439:         sc->sc_qactive = qp;
 440:         addr->bsel0 = qp->qp_cmd;
 441:         dmcrint(unit);
 442:     }
 443:     splx(sps);
 444: }
 445: 
 446: /*
 447:  * DMC interface receiver interrupt.
 448:  * Ready to accept another command,
 449:  * pull one off the command queue.
 450:  */
 451: dmcrint(unit)
 452:     int unit;
 453: {
 454:     register struct dmc_softc *sc;
 455:     register struct dmcdevice *addr;
 456:     register struct dmc_command *qp;
 457:     register int n;
 458: 
 459:     addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
 460:     sc = &dmc_softc[unit];
 461:     if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) {
 462:         printf("dmc%d: dmcrint no command\n", unit);
 463:         return;
 464:     }
 465:     while (addr->bsel0&DMC_RDYI) {
 466:         addr->sel4 = qp->qp_ubaddr;
 467:         addr->sel6 = qp->qp_cc;
 468:         addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
 469:         /* free command buffer */
 470:         QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
 471:         while (addr->bsel0 & DMC_RDYI) {
 472:             /*
 473: 			 * Can't check for RDYO here 'cause
 474: 			 * this routine isn't reentrant!
 475: 			 */
 476:             DELAY(5);
 477:         }
 478:         /* move on to next command */
 479:         if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0)
 480:             break;      /* all done */
 481:         /* more commands to do, start the next one */
 482:         qp = sc->sc_qactive;
 483:         DEQUEUE(sc->sc_qhead, sc->sc_qtail);
 484:         addr->bsel0 = qp->qp_cmd;
 485:         n = RDYSCAN;
 486:         while (n-- > 0)
 487:             if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO))
 488:                 break;
 489:     }
 490:     if (sc->sc_qactive) {
 491:         addr->bsel0 |= DMC_IEI|DMC_RQI;
 492:         /* VMS does it twice !*$%@# */
 493:         addr->bsel0 |= DMC_IEI|DMC_RQI;
 494:     }
 495: 
 496: }
 497: 
 498: /*
 499:  * DMC interface transmitter interrupt.
 500:  * A transfer may have completed, check for errors.
 501:  * If it was a read, notify appropriate protocol.
 502:  * If it was a write, pull the next one off the queue.
 503:  */
 504: dmcxint(unit)
 505:     int unit;
 506: {
 507:     register struct dmc_softc *sc;
 508:     register struct ifnet *ifp;
 509:     struct uba_device *ui = dmcinfo[unit];
 510:     struct dmcdevice *addr;
 511:     struct mbuf *m;
 512:     struct ifqueue *inq;
 513:     int arg, pkaddr, cmd, len, s;
 514:     register struct ifrw *ifrw;
 515:     register struct dmcbufs *rp;
 516:     register struct ifxmt *ifxp;
 517:     struct dmc_header *dh;
 518:     int off, resid;
 519: 
 520:     addr = (struct dmcdevice *)ui->ui_addr;
 521:     sc = &dmc_softc[unit];
 522:     ifp = &sc->sc_if;
 523: 
 524:     while (addr->bsel2 & DMC_RDYO) {
 525: 
 526:         cmd = addr->bsel2 & 0xff;
 527:         arg = addr->sel6 & 0xffff;
 528:         /* reconstruct UNIBUS address of buffer returned to us */
 529:         pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff);
 530:         /* release port */
 531:         addr->bsel2 &= ~DMC_RDYO;
 532:         switch (cmd & 07) {
 533: 
 534:         case DMC_OUR:
 535:             /*
 536: 			 * A read has completed.
 537: 			 * Pass packet to type specific
 538: 			 * higher-level input routine.
 539: 			 */
 540:             ifp->if_ipackets++;
 541:             /* find location in dmcuba struct */
 542:             ifrw= &sc->sc_ifr[0];
 543:             for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
 544:                 if(rp->ubinfo == pkaddr)
 545:                     break;
 546:                 ifrw++;
 547:             }
 548:             if (rp >= &sc->sc_rbufs[NRCV])
 549:                 panic("dmc rcv");
 550:             if ((rp->flags & DBUF_DMCS) == 0)
 551:                 printf("dmc%d: done unalloc rbuf\n", unit);
 552: 
 553:             len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header);
 554:             if (len < 0 || len > DMCMTU) {
 555:                 ifp->if_ierrors++;
 556:                 printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n",
 557:                     unit, pkaddr, len);
 558:                 goto setup;
 559:             }
 560:             /*
 561: 			 * Deal with trailer protocol: if type is trailer
 562: 			 * get true type from first 16-bit word past data.
 563: 			 * Remember that type was trailer by setting off.
 564: 			 */
 565:             dh = (struct dmc_header *)ifrw->ifrw_addr;
 566:             dh->dmc_type = ntohs((u_short)dh->dmc_type);
 567: #define dmcdataaddr(dh, off, type)  ((type)(((caddr_t)((dh)+1)+(off))))
 568:             if (dh->dmc_type >= DMC_TRAILER &&
 569:                 dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) {
 570:                 off = (dh->dmc_type - DMC_TRAILER) * 512;
 571:                 if (off >= DMCMTU)
 572:                     goto setup;     /* sanity */
 573:                 dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *));
 574:                 resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *)));
 575:                 if (off + resid > len)
 576:                     goto setup;     /* sanity */
 577:                 len = off + resid;
 578:             } else
 579:                 off = 0;
 580:             if (len == 0)
 581:                 goto setup;
 582: 
 583:             /*
 584: 			 * Pull packet off interface.  Off is nonzero if
 585: 			 * packet has trailing header; dmc_get will then
 586: 			 * force this header information to be at the front,
 587: 			 * but we still have to drop the type and length
 588: 			 * which are at the front of any trailer data.
 589: 			 */
 590:             m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp);
 591:             if (m == 0)
 592:                 goto setup;
 593:             if (off) {
 594:                 ifp = *(mtod(m, struct ifnet **));
 595:                 m->m_off += 2 * sizeof (u_short);
 596:                 m->m_len -= 2 * sizeof (u_short);
 597:                 *(mtod(m, struct ifnet **)) = ifp;
 598:             }
 599:             switch (dh->dmc_type) {
 600: 
 601: #ifdef INET
 602:             case DMC_IPTYPE:
 603:                 schednetisr(NETISR_IP);
 604:                 inq = &ipintrq;
 605:                 break;
 606: #endif
 607:             default:
 608:                 m_freem(m);
 609:                 goto setup;
 610:             }
 611: 
 612:             s = splimp();
 613:             if (IF_QFULL(inq)) {
 614:                 IF_DROP(inq);
 615:                 m_freem(m);
 616:             } else
 617:                 IF_ENQUEUE(inq, m);
 618:             splx(s);
 619: 
 620:     setup:
 621:             /* is this needed? */
 622:             rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
 623: 
 624:             dmcload(sc, DMC_READ, rp->ubinfo,
 625:                 ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc);
 626:             break;
 627: 
 628:         case DMC_OUX:
 629:             /*
 630: 			 * A write has completed, start another
 631: 			 * transfer if there is more data to send.
 632: 			 */
 633:             ifp->if_opackets++;
 634:             /* find associated dmcbuf structure */
 635:             ifxp = &sc->sc_ifw[0];
 636:             for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
 637:                 if(rp->ubinfo == pkaddr)
 638:                     break;
 639:                 ifxp++;
 640:             }
 641:             if (rp >= &sc->sc_xbufs[NXMT]) {
 642:                 printf("dmc%d: bad packet address 0x%x\n",
 643:                     unit, pkaddr);
 644:                 break;
 645:             }
 646:             if ((rp->flags & DBUF_DMCS) == 0)
 647:                 printf("dmc%d: unallocated packet 0x%x\n",
 648:                     unit, pkaddr);
 649:             /* mark buffer free */
 650:             if (ifxp->ifw_xtofree) {
 651:                 (void)m_freem(ifxp->ifw_xtofree);
 652:                 ifxp->ifw_xtofree = 0;
 653:             }
 654:             rp->flags &= ~DBUF_DMCS;
 655:             sc->sc_oused--;
 656:             sc->sc_nticks = 0;
 657:             sc->sc_flag |= DMC_ACTIVE;
 658:             break;
 659: 
 660:         case DMC_CNTLO:
 661:             arg &= DMC_CNTMASK;
 662:             if (arg & DMC_FATAL) {
 663:                 log(LOG_ERR, "dmc%d: fatal error, flags=%b\n",
 664:                     unit, arg, CNTLO_BITS);
 665:                 dmcrestart(unit);
 666:                 break;
 667:             }
 668:             /* ACCUMULATE STATISTICS */
 669:             switch(arg) {
 670:             case DMC_NOBUFS:
 671:                 ifp->if_ierrors++;
 672:                 if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0)
 673:                     goto report;
 674:                 break;
 675:             case DMC_DISCONN:
 676:                 if ((sc->sc_disc++ % DMC_RPDSC) == 0)
 677:                     goto report;
 678:                 break;
 679:             case DMC_TIMEOUT:
 680:                 if ((sc->sc_timeo++ % DMC_RPTMO) == 0)
 681:                     goto report;
 682:                 break;
 683:             case DMC_DATACK:
 684:                 ifp->if_oerrors++;
 685:                 if ((sc->sc_datck++ % DMC_RPDCK) == 0)
 686:                     goto report;
 687:                 break;
 688:             default:
 689:                 goto report;
 690:             }
 691:             break;
 692:         report:
 693:             printd("dmc%d: soft error, flags=%b\n", unit,
 694:                 arg, CNTLO_BITS);
 695:             if ((sc->sc_flag & DMC_RESTART) == 0) {
 696:                 /*
 697: 				 * kill off the dmc to get things
 698: 				 * going again by generating a
 699: 				 * procedure error
 700: 				 */
 701:                 sc->sc_flag |= DMC_RESTART;
 702:                 arg = sc->sc_ubinfo & 0x3ffff;
 703:                 dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);
 704:             }
 705:             break;
 706: 
 707:         default:
 708:             printf("dmc%d: bad control %o\n", unit, cmd);
 709:             break;
 710:         }
 711:     }
 712:     dmcstart(unit);
 713:     return;
 714: }
 715: 
 716: /*
 717:  * DMC output routine.
 718:  * Encapsulate a packet of type family for the dmc.
 719:  * Use trailer local net encapsulation if enough data in first
 720:  * packet leaves a multiple of 512 bytes of data in remainder.
 721:  */
 722: dmcoutput(ifp, m0, dst)
 723:     register struct ifnet *ifp;
 724:     register struct mbuf *m0;
 725:     struct sockaddr *dst;
 726: {
 727:     int type, error, s;
 728:     register struct mbuf *m = m0;
 729:     register struct dmc_header *dh;
 730:     register int off;
 731: 
 732:     switch (dst->sa_family) {
 733: #ifdef  INET
 734:     case AF_INET:
 735:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
 736:         if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
 737:         if (off > 0 && (off & 0x1ff) == 0 &&
 738:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
 739:             type = DMC_TRAILER + (off>>9);
 740:             m->m_off -= 2 * sizeof (u_short);
 741:             m->m_len += 2 * sizeof (u_short);
 742:             *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE);
 743:             *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
 744:             goto gottrailertype;
 745:         }
 746:         type = DMC_IPTYPE;
 747:         off = 0;
 748:         goto gottype;
 749: #endif
 750: 
 751:     case AF_UNSPEC:
 752:         dh = (struct dmc_header *)dst->sa_data;
 753:         type = dh->dmc_type;
 754:         goto gottype;
 755: 
 756:     default:
 757:         printf("dmc%d: can't handle af%d\n", ifp->if_unit,
 758:             dst->sa_family);
 759:         error = EAFNOSUPPORT;
 760:         goto bad;
 761:     }
 762: 
 763: gottrailertype:
 764:     /*
 765: 	 * Packet to be sent as a trailer; move first packet
 766: 	 * (control information) to end of chain.
 767: 	 */
 768:     while (m->m_next)
 769:         m = m->m_next;
 770:     m->m_next = m0;
 771:     m = m0->m_next;
 772:     m0->m_next = 0;
 773:     m0 = m;
 774: 
 775: gottype:
 776:     /*
 777: 	 * Add local network header
 778: 	 * (there is space for a uba on a vax to step on)
 779: 	 */
 780:     if (m->m_off > MMAXOFF ||
 781:         MMINOFF + sizeof(struct dmc_header) > m->m_off) {
 782:         m = m_get(M_DONTWAIT, MT_HEADER);
 783:         if (m == 0) {
 784:             error = ENOBUFS;
 785:             goto bad;
 786:         }
 787:         m->m_next = m0;
 788:         m->m_off = MMINOFF;
 789:         m->m_len = sizeof (struct dmc_header);
 790:     } else {
 791:         m->m_off -= sizeof (struct dmc_header);
 792:         m->m_len += sizeof (struct dmc_header);
 793:     }
 794:     dh = mtod(m, struct dmc_header *);
 795:     dh->dmc_type = htons((u_short)type);
 796: 
 797:     /*
 798: 	 * Queue message on interface, and start output if interface
 799: 	 * not yet active.
 800: 	 */
 801:     s = splimp();
 802:     if (IF_QFULL(&ifp->if_snd)) {
 803:         IF_DROP(&ifp->if_snd);
 804:         m_freem(m);
 805:         splx(s);
 806:         return (ENOBUFS);
 807:     }
 808:     IF_ENQUEUE(&ifp->if_snd, m);
 809:     dmcstart(ifp->if_unit);
 810:     splx(s);
 811:     return (0);
 812: 
 813: bad:
 814:     m_freem(m0);
 815:     return (error);
 816: }
 817: 
 818: 
 819: /*
 820:  * Process an ioctl request.
 821:  */
 822: /* ARGSUSED */
 823: dmcioctl(ifp, cmd, data)
 824:     register struct ifnet *ifp;
 825:     int cmd;
 826:     caddr_t data;
 827: {
 828:     int s = splimp(), error = 0;
 829:     register struct dmc_softc *sc = &dmc_softc[ifp->if_unit];
 830: 
 831:     switch (cmd) {
 832: 
 833:     case SIOCSIFADDR:
 834:         ifp->if_flags |= IFF_UP;
 835:         if ((ifp->if_flags & IFF_RUNNING) == 0)
 836:             dmcinit(ifp->if_unit);
 837:         break;
 838: 
 839:     case SIOCSIFDSTADDR:
 840:         if ((ifp->if_flags & IFF_RUNNING) == 0)
 841:             dmcinit(ifp->if_unit);
 842:         break;
 843: 
 844:     case SIOCSIFFLAGS:
 845:         if ((ifp->if_flags & IFF_UP) == 0 &&
 846:             sc->sc_flag & DMC_RUNNING) {
 847:             ((struct dmcdevice *)
 848:                (dmcinfo[ifp->if_unit]->ui_addr))->bsel1 = DMC_MCLR;
 849:             sc->sc_flag &= ~DMC_RUNNING;
 850:         } else if (ifp->if_flags & IFF_UP &&
 851:             (sc->sc_flag & DMC_RUNNING) == 0)
 852:             dmcrestart(ifp->if_unit);
 853:         break;
 854: 
 855:     default:
 856:         error = EINVAL;
 857:     }
 858:     splx(s);
 859:     return (error);
 860: }
 861: 
 862: /*
 863:  * Restart after a fatal error.
 864:  * Clear device and reinitialize.
 865:  */
 866: dmcrestart(unit)
 867:     int unit;
 868: {
 869:     register struct dmc_softc *sc = &dmc_softc[unit];
 870:     register struct uba_device *ui = dmcinfo[unit];
 871:     register struct dmcdevice *addr;
 872:     register struct ifxmt *ifxp;
 873:     register int i;
 874: 
 875:     addr = (struct dmcdevice *)ui->ui_addr;
 876: #ifdef DEBUG
 877:     /* dump base table */
 878:     printf("dmc%d base table:\n", unit);
 879:     for (i = 0; i < sizeof (struct dmc_base); i++)
 880:         printf("%o\n" ,dmc_base[unit].d_base[i]);
 881: #endif
 882:     /*
 883: 	 * Let the DMR finish the MCLR.	 At 1 Mbit, it should do so
 884: 	 * in about a max of 6.4 milliseconds with diagnostics enabled.
 885: 	 */
 886:     addr->bsel1 = DMC_MCLR;
 887:     for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
 888:         ;
 889:     /* Did the timer expire or did the DMR finish? */
 890:     if ((addr->bsel1 & DMC_RUN) == 0) {
 891:         log(LOG_ERR, "dmc%d: M820 Test Failed\n", unit);
 892:         return;
 893:     }
 894: 
 895:     for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) {
 896:         if (ifxp->ifw_xtofree) {
 897:             (void) m_freem(ifxp->ifw_xtofree);
 898:             ifxp->ifw_xtofree = 0;
 899:         }
 900:     }
 901: 
 902:     /* restart DMC */
 903:     dmcinit(unit);
 904:     sc->sc_flag &= ~DMC_RESTART;
 905:     sc->sc_if.if_collisions++;  /* why not? */
 906: }
 907: 
 908: /*
 909:  * Check to see that transmitted packets don't
 910:  * lose interrupts.  The device has to be active.
 911:  */
 912: dmcwatch()
 913: {
 914:     register struct uba_device *ui;
 915:     register struct dmc_softc *sc;
 916:     struct dmcdevice *addr;
 917:     register int i;
 918: 
 919:     for (i = 0; i < NDMC; i++) {
 920:         sc = &dmc_softc[i];
 921:         if ((sc->sc_flag & DMC_ACTIVE) == 0)
 922:             continue;
 923:         if ((ui = dmcinfo[i]) == 0 || ui->ui_alive == 0)
 924:             continue;
 925:         if (sc->sc_oused) {
 926:             sc->sc_nticks++;
 927:             if (sc->sc_nticks > dmc_timeout) {
 928:                 sc->sc_nticks = 0;
 929:                 addr = (struct dmcdevice *)ui->ui_addr;
 930:                 log(LOG_ERR, "dmc%d hung: bsel0=%b bsel2=%b\n",
 931:                     i, addr->bsel0 & 0xff, DMC0BITS,
 932:                     addr->bsel2 & 0xff, DMC2BITS);
 933:                 dmcrestart(i);
 934:             }
 935:         }
 936:     }
 937:     timeout(dmcwatch, (caddr_t) 0, hz);
 938: }
 939: #endif

Defined functions

dmcattach defined in line 208; used 2 times
dmcinit defined in line 252; used 6 times
dmcioctl defined in line 823; used 2 times
dmcload defined in line 410; used 9 times
dmcoutput defined in line 722; used 2 times
dmcprobe defined in line 175; used 2 times
dmcreset defined in line 234; used 2 times
dmcrestart defined in line 866; used 3 times
dmcrint defined in line 451; used 2 times
dmcstart defined in line 371; used 2 times
dmcwatch defined in line 912; used 3 times
dmcxint defined in line 504; used 1 times

Defined variables

dmc_base defined in line 153; used 2 times
dmc_softc defined in line 142; used 10 times
dmc_timeout defined in line 60; used 1 times
dmcdebug defined in line 78; used 1 times
  • in line 77
dmcdriver defined in line 70; never used
dmcinfo defined in line 68; used 9 times
dmcstd defined in line 69; used 1 times
  • in line 71
dmctimer defined in line 59; used 2 times

Defined struct's

dmc_base defined in line 151; used 4 times
dmc_command defined in line 86; used 28 times
dmc_softc defined in line 117; used 20 times
dmcbufs defined in line 93; used 10 times

Defined macros

DBUF_DMCS defined in line 99; used 6 times
DBUF_OURS defined in line 98; used 2 times
DBUF_RCV defined in line 101; used 1 times
DBUF_XMIT defined in line 100; used 1 times
DEQUEUE defined in line 170; used 2 times
DMC_ACTIVE defined in line 148; used 3 times
DMC_ALLOC defined in line 145; never used
DMC_BMAPPED defined in line 146; used 2 times
DMC_RESTART defined in line 147; used 3 times
DMC_RPDCK defined in line 84; used 1 times
DMC_RPDSC defined in line 82; used 1 times
DMC_RPNBFS defined in line 81; used 1 times
DMC_RPTMO defined in line 83; used 1 times
DMC_RUNNING defined in line 149; used 4 times
NCMDS defined in line 75; used 2 times
NRCV defined in line 73; used 8 times
NXMT defined in line 74; used 9 times
QUEUE_AT_HEAD defined in line 156; used 3 times
QUEUE_AT_TAIL defined in line 162; used 1 times
dmcdataaddr defined in line 567; used 2 times
printd defined in line 77; used 2 times
sc_datck defined in line 130; used 1 times
sc_disc defined in line 133; used 1 times
sc_nobuf defined in line 132; used 1 times
sc_timeo defined in line 131; used 1 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1895
Valid CSS Valid XHTML 1.0 Strict