# 2.11BSD#431 - /usr/src/sys/vaxif/if_dmc.c

##### Functions

    dmcattach         X
    dmcinit           X
    dmcioctl          X
    dmcload           X
    dmcoutput         X
    dmcprobe          X
    dmcreset          X
    dmcrestart        X
    dmcrint           X
    dmcstart          X
    dmcwatch          X
    dmcxint           X

##### Variables

    dmc_base          X
    dmc_softc         X
    dmc_timeout       X
    dmcdebug          X
    dmcdriver         X
    dmcinfo           X
    dmcstd            X
    dmctimer          X

##### Macros

    DBUF_DMCS         X
    DBUF_OURS         X
    DBUF_RCV          X
    DBUF_XMIT         X
    DEQUEUE           X
    DMC_ACTIVE        X
    DMC_ALLOC         X
    DMC_BMAPPED       X
    DMC_RESTART       X
    DMC_RPDCK         X
    DMC_RPDSC         X
    DMC_RPNBFS        X
    DMC_RPTMO         X
    DMC_RUNNING       X
    NCMDS             X
    NRCV              X
    NXMT              X
    QUEUE_AT_HEAD     X
    QUEUE_AT_TAIL     X
    dmcdataaddr       X
    printd            X
    sc_datck          X
    sc_disc           X
    sc_nobuf          X
    sc_timeo          X

##### struct's

    dmc_base          X
    dmc_command       X
    dmc_softc         X
    dmcbufs           X

       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

- in line 66-71(2)

dmcinit defined in line 252; used 6 times

- in line 66, 216, 246, 836-841(2), 903

dmcioctl defined in line 823; used 2 times

- in line 66, 218

dmcload defined in line 410; used 9 times

- in line 333-347(5), 357, 400, 624, 703

dmcoutput defined in line 722; used 2 times

- in line 67, 217

dmcprobe defined in line 175; used 2 times

- in line 66-71(2)

dmcreset defined in line 234; used 2 times

- in line 67, 219

dmcrestart defined in line 866; used 3 times

- in line 665, 852, 933

dmcrint defined in line 451; used 2 times

- in line 184, 441

dmcstart defined in line 371; used 2 times

- in line 712, 809

dmcwatch defined in line 912; used 3 times

- in line 61, 225, 937

dmcxint defined in line 504; used 1 times

- in line 184

#### Defined variables

dmc_base defined in line 153; used 2 times

- in line 287, 880

dmc_softc defined in line 142; used 10 times

- in line 211, 238, 255, 375, 418, 460, 521, 829, 869, 920

dmc_timeout defined in line 60; used 1 times

- in line 927

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

- in line 71, 240, 256, 419, 459, 509, 848, 870, 923

dmcstd defined in line 69; used 1 times

- in line 71

dmctimer defined in line 59; used 2 times

- in line 223-224(2)

#### Defined struct's

dmc_base defined in line 151; used 4 times

- in line 287(2), 879(2)

dmc_command defined in line 86; used 28 times

- in line 90(2), 135-140(12), 262(2), 325(2), 416(2), 423(2), 456-461(4), 479(2)

dmc_softc defined in line 117; used 20 times

- in line 211(2), 238(2), 255(2), 375(2), 411(2), 454(2), 507(2), 829(2), 869(2), 915(2)

dmcbufs defined in line 93; used 10 times

- in line 119-120(4), 261(2), 377(2), 515(2)

#### Defined macros

DBUF_DMCS defined in line 99; used 6 times

- in line 356, 387-392(2), 550, 646, 654

DBUF_OURS defined in line 98; used 2 times

- in line 310, 318

DBUF_RCV defined in line 101; used 1 times

- in line 310

DBUF_XMIT defined in line 100; used 1 times

- in line 318

DEQUEUE defined in line 170; used 2 times

- in line 425, 483

DMC_ACTIVE defined in line 148; used 3 times

- in line 350, 657, 921

DMC_ALLOC defined in line 145; never used
DMC_BMAPPED defined in line 146; used 2 times

- in line 285-288(2)

DMC_RESTART defined in line 147; used 3 times

- in line 695, 701, 904

DMC_RPDCK defined in line 84; used 1 times

- in line 685

DMC_RPDSC defined in line 82; used 1 times

- in line 676

DMC_RPNBFS defined in line 81; used 1 times

- in line 672

DMC_RPTMO defined in line 83; used 1 times

- in line 680

DMC_RUNNING defined in line 149; used 4 times

- in line 302, 846-851(3)

NCMDS defined in line 75; used 2 times

- in line 135, 327

NRCV defined in line 73; used 8 times

- in line 75, 119-122(2), 295, 307, 355, 543-548(2)

NXMT defined in line 74; used 9 times

- in line 75, 120-123(2), 295, 315, 385, 636-641(2), 895

QUEUE_AT_HEAD defined in line 156; used 3 times

- in line 328, 434, 470

QUEUE_AT_TAIL defined in line 162; used 1 times

- in line 436

dmcdataaddr defined in line 567; used 2 times

- in line 573-574(2)

printd defined in line 77; used 2 times

- in line 556, 693

sc_datck defined in line 130; used 1 times

- in line 685

sc_disc defined in line 133; used 1 times

- in line 676

sc_nobuf defined in line 132; used 1 times

- in line 672

sc_timeo defined in line 131; used 1 times

- in line 680

Last modified: 1986-06-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 297 |