1: /*
   2:  * Copyright (c) 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	1.1 (2.10BSD Berkeley) 12/1/86
   7:  */
   8: 
   9: #include "dmc.h"
  10: #if NDMC > 0
  11: 
  12: #define printd if(dmcdebug)printf
  13: int dmcdebug = 1;
  14: /*
  15:  * DMC11 device driver, internet version
  16:  *
  17:  * TODO
  18:  *	allow more than one outstanding read or write.
  19:  */
  20: 
  21: #include "param.h"
  22: #include "systm.h"
  23: #include "mbuf.h"
  24: #include "buf.h"
  25: #include "ioctl.h"
  26: #include "tty.h"
  27: #include "domain.h"
  28: #include "protosw.h"
  29: #include "socket.h"
  30: #include "pdpuba/ubavar.h"
  31: #include "netinet/in.h"
  32: #include "netinet/in_systm.h"
  33: #include "net/if.h"
  34: #include "pdpif/if_uba.h"
  35: #include "pdpif/if_dmc.h"
  36: #include "netinet/ip.h"
  37: #include "netinet/in_var.h"
  38: #include "netinet/ip_var.h"
  39: #include "net/route.h"
  40: #include "net/netisr.h"
  41: #include "errno.h"
  42: 
  43: /*
  44:  * Driver information for auto-configuration stuff.
  45:  */
  46: int dmcprobe(), dmcattach(), dmcinit(), dmcoutput();
  47: struct  uba_device *dmcinfo[NDMC];
  48: u_short dmcstd[] = { 0 };
  49: struct  uba_driver dmcdriver =
  50:     { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
  51: 
  52: #define DMC_AF  0xff        /* 8 bits of address type in ui_flags */
  53: #define DMC_NET 0xffffff00  /* 24 bits of net number in ui_flags */
  54: 
  55: /*
  56:  * DMC software status per interface.
  57:  *
  58:  * Each interface is referenced by a network interface structure,
  59:  * sc_if, which the routing code uses to locate the interface.
  60:  * This structure contains the output queue for the interface, its address, ...
  61:  * We also have, for each interface, a UBA interface structure, which
  62:  * contains information about the UNIBUS resources held by the interface:
  63:  * map registers, buffered data paths, etc.  Information is cached in this
  64:  * structure for use by the if_uba.c routines in running the interface
  65:  * efficiently.
  66:  */
  67: struct dmc_softc {
  68:     struct  ifnet sc_if;        /* network-visible interface */
  69:     struct  ifuba sc_ifuba;     /* UNIBUS resources */
  70:     short   sc_flag;        /* flags */
  71:     short   sc_oactive;     /* output active */
  72:     int sc_ubinfo;      /* UBA mapping info for base table */
  73:     struct clist sc_que;        /* command queue */
  74: } dmc_softc[NDMC];
  75: 
  76: /* flags */
  77: #define DMCRUN      01
  78: #define DMCBMAPPED  02      /* base table mapped */
  79: 
  80: struct dmc_base {
  81:     short   d_base[128];        /* DMC base table */
  82: } dmc_base[NDMC];
  83: 
  84: #define loword(x)   ((short *)&x)[0]
  85: #define hiword(x)   ((short *)&x)[1]
  86: 
  87: dmcprobe(reg)
  88:     caddr_t reg;
  89: {
  90:     register int br, cvec;
  91:     register struct dmcdevice *addr = (struct dmcdevice *)reg;
  92:     register int i;
  93: 
  94: #ifdef lint
  95:     br = 0; cvec = br; br = cvec;
  96:     dmcrint(0); dmcxint(0);
  97: #endif
  98:     addr->bsel1 = DMC_MCLR;
  99:     for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
 100:         ;
 101:     if ((addr->bsel1 & DMC_RUN) == 0)
 102:         return (0);
 103:     addr->bsel1 &= ~DMC_MCLR;
 104:     addr->bsel0 = DMC_RQI|DMC_IEI;
 105:     DELAY(100000L);
 106:     addr->bsel1 = DMC_MCLR;
 107:     for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
 108:         ;
 109: #ifdef ECHACK
 110:     br = 0x16;
 111: #endif
 112:     return (1);
 113: }
 114: 
 115: /*
 116:  * Interface exists: make available by filling in network interface
 117:  * record.  System will initialize the interface when it is ready
 118:  * to accept packets.
 119:  */
 120: dmcattach(ui)
 121:     register struct uba_device *ui;
 122: {
 123:     register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
 124:     register struct sockaddr_in *sin;
 125: 
 126:     sc->sc_if.if_unit = ui->ui_unit;
 127:     sc->sc_if.if_name = "dmc";
 128:     sc->sc_if.if_mtu = DMCMTU;
 129:     sc->sc_if.if_init = dmcinit;
 130:     sc->sc_if.if_output = dmcoutput;
 131:     sc->sc_if.if_reset = 0;
 132:     sc->sc_if.if_flags = IFF_POINTOPOINT;
 133:     /* DON'T KNOW IF THIS WILL WORK WITH A BDP AT HIGH SPEEDS */
 134:     sc->sc_ifuba.ifu_flags = UBA_NEEDBDP | UBA_CANTWAIT;
 135:     if_attach(&sc->sc_if);
 136: }
 137: 
 138: /*
 139:  * Initialization of interface; reinitialize UNIBUS usage.
 140:  */
 141: dmcinit(unit)
 142:     int unit;
 143: {
 144:     register struct dmc_softc *sc = &dmc_softc[unit];
 145:     register struct uba_device *ui = dmcinfo[unit];
 146:     register struct dmcdevice *addr;
 147:     int base;
 148: 
 149:     printd("dmcinit\n");
 150:     if ((sc->sc_flag&DMCBMAPPED) == 0) {
 151:         sc->sc_ubinfo = uballoc((caddr_t)&dmc_base[unit],
 152:                     sizeof (struct dmc_base));
 153:         sc->sc_flag |= DMCBMAPPED;
 154:     }
 155:     if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0,
 156:         (int)btoc(DMCMTU)) == 0) {
 157:         printf("dmc%d: can't initialize\n", unit);
 158:         sc->sc_if.if_flags &= ~IFF_UP;
 159:         return;
 160:     }
 161:     addr = (struct dmcdevice *)ui->ui_addr;
 162:     addr->bsel2 |= DMC_IEO;
 163:     base = sc->sc_ubinfo & 0x3ffff;
 164:     printd("  base 0x%x\n", base);
 165:     dmcload(sc, DMC_BASEI, base, (base>>2)&DMC_XMEM);
 166:     dmcload(sc, DMC_CNTLI, 0, 0);
 167:     base = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff;
 168:     dmcload(sc, DMC_READ, base, ((base>>2)&DMC_XMEM)|DMCMTU);
 169:     printd("  first read queued, addr 0x%x\n", base);
 170:     sc->sc_if.if_flags |= IFF_UP;
 171: }
 172: 
 173: /*
 174:  * Start output on interface.  Get another datagram
 175:  * to send from the interface queue and map it to
 176:  * the interface before starting output.
 177:  */
 178: dmcstart(dev)
 179:     dev_t dev;
 180: {
 181:     int unit = minor(dev);
 182:     struct uba_device *ui = dmcinfo[unit];
 183:     register struct dmc_softc *sc = &dmc_softc[unit];
 184:     int addr, len;
 185:     struct mbuf *m;
 186: 
 187:     printd("dmcstart\n");
 188:     /*
 189: 	 * Dequeue a request and map it to the UNIBUS.
 190: 	 * If no more requests, just return.
 191: 	 */
 192:     IF_DEQUEUE(&sc->sc_if.if_snd, m);
 193:     if (m == 0)
 194:         return;
 195:     len = if_wubaput(&sc->sc_ifuba, m);
 196: 
 197:     addr = sc->sc_ifuba.ifu_w.ifrw_info & 0x3ffff;
 198:     printd("  len %d, addr 0x%x, ", len, addr);
 199:     printd("mr 0x%lx\n", sc->sc_ifuba.ifu_w.ifrw_info);
 200:     dmcload(sc, DMC_WRITE, addr, (len&DMC_CCOUNT)|((addr>>2)&DMC_XMEM));
 201:     sc->sc_oactive = 1;
 202: }
 203: 
 204: /*
 205:  * Utility routine to load the DMC device registers.
 206:  */
 207: dmcload(sc, type, w0, w1)
 208:     register struct dmc_softc *sc;
 209:     int type, w0, w1;
 210: {
 211:     register struct dmcdevice *addr;
 212:     register int unit, sps, n;
 213: 
 214:     printd("dmcload: 0x%x 0x%x 0x%x\n", type, w0, w1);
 215:     unit = sc - dmc_softc;
 216:     addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
 217:     sps = splimp();
 218:     if ((n = sc->sc_que.c_cc) == 0)
 219:         addr->bsel0 = type | DMC_RQI;
 220:     else
 221:         (void) putc(type | DMC_RQI, &sc->sc_que);
 222:     (void) putw(w0, &sc->sc_que);
 223:     (void) putw(w1, &sc->sc_que);
 224:     if (n == 0)
 225:         dmcrint(unit);
 226:     splx(sps);
 227: }
 228: 
 229: /*
 230:  * DMC interface receiver interrupt.
 231:  * Ready to accept another command,
 232:  * pull one off the command queue.
 233:  */
 234: dmcrint(unit)
 235:     int unit;
 236: {
 237:     register struct dmc_softc *sc;
 238:     register struct dmcdevice *addr;
 239:     register int n;
 240: 
 241:     addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
 242:     sc = &dmc_softc[unit];
 243:     while (addr->bsel0&DMC_RDYI) {
 244:         addr->sel4 = getw(&sc->sc_que);
 245:         addr->sel6 = getw(&sc->sc_que);
 246:         addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
 247:         while (addr->bsel0&DMC_RDYI)
 248:             ;
 249:         if (sc->sc_que.c_cc == 0)
 250:             return;
 251:         addr->bsel0 = getc(&sc->sc_que);
 252:         n = RDYSCAN;
 253:         while (n-- && (addr->bsel0&DMC_RDYI) == 0)
 254:             ;
 255:     }
 256:     if (sc->sc_que.c_cc)
 257:         addr->bsel0 |= DMC_IEI;
 258: }
 259: 
 260: /*
 261:  * DMC interface transmitter interrupt.
 262:  * A transfer has completed, check for errors.
 263:  * If it was a read, notify appropriate protocol.
 264:  * If it was a write, pull the next one off the queue.
 265:  */
 266: dmcxint(unit)
 267:     int unit;
 268: {
 269:     register struct dmc_softc *sc;
 270:     struct uba_device *ui = dmcinfo[unit];
 271:     struct dmcdevice *addr;
 272:     struct mbuf *m;
 273:     register struct ifqueue *inq;
 274:     int arg, cmd, len;
 275: 
 276:     addr = (struct dmcdevice *)ui->ui_addr;
 277:     arg = addr->sel6;
 278:     cmd = addr->bsel2&7;
 279:     addr->bsel2 &= ~DMC_RDYO;
 280:     sc = &dmc_softc[unit];
 281:     printd("dmcxint\n");
 282:     switch (cmd) {
 283: 
 284:     case DMC_OUR:
 285:         /*
 286: 		 * A read has completed.  Purge input buffered
 287: 		 * data path.  Pass packet to type specific
 288: 		 * higher-level input routine.
 289: 		 */
 290:         sc->sc_if.if_ipackets++;
 291:         len = arg & DMC_CCOUNT;
 292:         printd("  read done, len %d\n", len);
 293:         switch (sc->sc_flag & DMC_AF) {
 294: #ifdef INET
 295:         case AF_INET:
 296:             schednetisr(NETISR_IP);
 297:             inq = &ipintrq;
 298:             break;
 299: #endif
 300: 
 301:         default:
 302:             printf("dmc%d: unknown address type %d\n", unit,
 303:                 sc->sc_flag & DMC_AF);
 304:             goto setup;
 305:         }
 306:         m = if_rubaget(&sc->sc_ifuba, len, 0, &sc->sc_if);
 307:         if (m == 0)
 308:             goto setup;
 309:         if (IF_QFULL(inq)) {
 310:             IF_DROP(inq);
 311:             (void) m_freem(m);
 312:         } else
 313:             IF_ENQUEUE(inq, m);
 314: 
 315: setup:
 316:         arg = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff;
 317:         dmcload(sc, DMC_READ, arg, ((arg >> 2) & DMC_XMEM) | DMCMTU);
 318:         return;
 319: 
 320:     case DMC_OUX:
 321:         /*
 322: 		 * A write has completed, start another
 323: 		 * transfer if there is more data to send.
 324: 		 */
 325:         if (sc->sc_oactive == 0)
 326:             return;     /* SHOULD IT BE A FATAL ERROR? */
 327:         printd("  write done\n");
 328:         sc->sc_if.if_opackets++;
 329:         sc->sc_oactive = 0;
 330:         if (sc->sc_ifuba.ifu_xtofree) {
 331:             (void) m_freem(sc->sc_ifuba.ifu_xtofree);
 332:             sc->sc_ifuba.ifu_xtofree = 0;
 333:         }
 334:         if (sc->sc_if.if_snd.ifq_head == 0)
 335:             return;
 336:         dmcstart(unit);
 337:         return;
 338: 
 339:     case DMC_CNTLO:
 340:         arg &= DMC_CNTMASK;
 341:         if (arg&DMC_FATAL) {
 342:             addr->bsel1 = DMC_MCLR;
 343:             sc->sc_flag &= ~DMCRUN;
 344:             /*** DO SOMETHING TO RESTART DEVICE ***/
 345:             printf("DMC FATAL ERROR 0%o\n", arg);
 346:         } else {
 347:             /* ACCUMULATE STATISTICS */
 348:             printf("DMC SOFT ERROR 0%o\n", arg);
 349:         }
 350:         return;
 351: 
 352:     default:
 353:         printf("dmc%d: bad control %o\n", unit, cmd);
 354:     }
 355: }
 356: 
 357: /*
 358:  * DMC output routine.
 359:  * Just send the data, header was supplied by
 360:  * upper level protocol routines.
 361:  */
 362: dmcoutput(ifp, m, dst)
 363:     register struct ifnet *ifp;
 364:     register struct mbuf *m;
 365:     struct sockaddr *dst;
 366: {
 367:     struct uba_device *ui = dmcinfo[ifp->if_unit];
 368:     int s;
 369: 
 370:     printd("dmcoutput\n");
 371:     if (dst->sa_family != AF_INET) {
 372:         printf("dmc%d: af%d not supported\n", ifp->if_unit, AF_INET);
 373:         m_freem(m);
 374:         return (EAFNOSUPPORT);
 375:     }
 376:     s = splimp();
 377:     if (IF_QFULL(&ifp->if_snd)) {
 378:         IF_DROP(&ifp->if_snd);
 379:         m_freem(m);
 380:         splx(s);
 381:         return (ENOBUFS);
 382:     }
 383:     IF_ENQUEUE(&ifp->if_snd, m);
 384:     if (dmc_softc[ifp->if_unit].sc_oactive == 0)
 385:         dmcstart(ifp->if_unit);
 386:     splx(s);
 387:     return (0);
 388: }
 389: #endif NDMC

Defined functions

dmcattach defined in line 120; used 2 times
dmcinit defined in line 141; used 2 times
dmcload defined in line 207; used 5 times
dmcoutput defined in line 362; used 2 times
dmcprobe defined in line 87; used 2 times
dmcrint defined in line 234; used 2 times
dmcstart defined in line 178; used 2 times
dmcxint defined in line 266; used 1 times
  • in line 96

Defined variables

dmc_base defined in line 82; used 1 times
dmc_softc defined in line 74; used 7 times
dmcdebug defined in line 13; used 1 times
  • in line 12
dmcdriver defined in line 49; never used
dmcinfo defined in line 47; used 7 times
dmcstd defined in line 48; used 1 times
  • in line 50

Defined struct's

dmc_base defined in line 80; used 2 times
  • in line 152(2)
dmc_softc defined in line 67; used 12 times

Defined macros

DMCBMAPPED defined in line 78; used 2 times
DMCRUN defined in line 77; used 1 times
DMC_AF defined in line 52; used 2 times
DMC_NET defined in line 53; never used
hiword defined in line 85; never used
loword defined in line 84; never used
printd defined in line 12; used 11 times
Last modified: 1990-09-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4116
Valid CSS Valid XHTML 1.0 Strict