1: /*
   2:  *  DMC-11 device driver
   3:  *
   4:  *  NOTE:
   5:  *	This driver uses the old, in-address-space abuffers.
   6:  *	Since those buffers no longer exist, this driver would
   7:  *	need to be converted to use its own, local buffers
   8:  *	before it could be used.
   9:  */
  10: 
  11: /*
  12:  *	SCCS id	@(#)dmc.c	2.1 (Berkeley)	8/5/83
  13:  */
  14: 
  15: #include "param.h"
  16: #include <sys/conf.h>
  17: #include <sys/dir.h>
  18: #include <sys/user.h>
  19: #include <sys/buf.h>
  20: #include <sys/proc.h>
  21: 
  22: #define CLOSE           /* include ioctl(NETCLOSE,,) */
  23: 
  24: #define DMCPRI  PZERO-1
  25: #define NDMC    1
  26: 
  27: #define BUFSIZ  256     /* size of buffers */
  28: #define NRBUFS  (int)(BSIZE/BUFSIZ-1) /* # of extra receive buffer headers */
  29: #define NTBUFS  1       /* number of transmit buffer headers */
  30:         /*
  31:          * note: dmc only allows 7 receive, 7 transmit buffers to be queued,
  32:          * thus NRBUFS and NTBUFS must be <= 7.
  33:          * On an 11/70 the Unibus map must be allocated; if mapalloc() is
  34:          * used, only one buffer can have the map.  NTBUFS might as
  35:          * well be 1 so the next (only) write outstanding is the one
  36:          * with the map allocated.
  37:          */
  38: #define LOOPCNT 10      /* max time waiting for ~RDYI */
  39: #define MAXERRS 7       /* number of DCK or TIMEOUTs before fail */
  40: 
  41: struct device {
  42:         char    inctrl;
  43:         char    mstrctrl;
  44:         char    outctrl;
  45:         char    bsel3;
  46:         unsigned bufad;
  47:         unsigned port1;
  48: };
  49: 
  50: struct device *dmcaddr[] = {
  51:         (struct device *)0160200,
  52:         (struct device *)0160210
  53: };
  54: 
  55: 
  56: struct buf dmctbufs[NDMC][NTBUFS];
  57: struct buf dmcrbufs[NDMC][NRBUFS];
  58: 
  59: struct dmcinfo {
  60:         struct buf *bp; /* system receive buffer to relse */
  61:         caddr_t addr;           /* saved addr for dmcitrans */
  62:         unsigned cnt;           /* saved xmem + count for dmcitrans */
  63: } dmcinfo[NDMC];
  64: 
  65: struct buf dmcutab[NDMC];
  66: 
  67: #define MCLR    0100    /* mstrctrl -- master clear */
  68: #define RDYI    0200    /* inctrl -- port avail */
  69: #define RQI     0040    /* inctrl -- request input transfer */
  70: #define IEI     0100    /* inctrl -- interrupt enable, input */
  71: #define RDYO    0200    /* outctrl -- output transfer ready */
  72: #define IEO     0100    /* outctrl -- output interrupt enable */
  73: #define TRBIT   0004    /* inctrl, outctrl -- mask for t/r flag */
  74: #define TFLAG   0000    /* inctrl, outctrl -- flag indicates transmission */
  75: #define RFLAG   0004    /* inctrl, outctrl -- flag indicates reception */
  76: #define TTYPE   0003    /* inctrl, outctrl -- mask for transfer type */
  77: #define BACC    0000    /* inctrl, outctrl -- buf addr, char count */
  78: #define CTRL    0001    /* inctrl, outctrl -- control in/out */
  79: #define INVAL   0002    /* inctrl -- invalid (to shut down gracefully) */
  80: #define BASEI   0003    /* inctrl -- base in */
  81: 
  82: #define FDUP    00000   /* port1 (control in) -- full duplex operation */
  83: #define HDUP    02000   /* port1 (control in) -- half duplex operation */
  84: 
  85:         /* control out error states: */
  86: #define FATAL   01630   /* fatal errors */
  87: #define DCK     00001   /* data check */
  88: #define TIMEOUT 00002   /* no response, 21 sec. */
  89: #define ORUN    00004   /* overun error (waiting for recv buffer) */
  90: #define MAINT   00010   /* maintenance mesg recd */
  91: #define DLOST   00020   /* data lost (recv buffer too small) */
  92: #define DISCON  00100   /* DSR transition */
  93: #define RESTART 00200   /* DDCMP start received */
  94: #define NXM     00400   /* non-existent memory */
  95: #define PROCERR 01000   /* procedure error */
  96: 
  97: #define OPEN    001
  98: #define CLOSING 002     /* closing gracefully */
  99: #define STATE   003
 100: #define ERROR   004     /* fatal line error */
 101: #define TOLD    010     /* console message already printed */
 102: #define R_WAITING 0100  /* read waiting */
 103: #define W_WAITING 0200  /* write waiting */
 104: #define TR_WAITING 0400 /* itrans waiting */
 105: #define WAITING   0700
 106: 
 107: #define EXTSHFT 14
 108: 
 109: #ifndef hiint
 110: #define hiint(x) (int)(x>>16)
 111: #define loint(x) (int)(x&177777)
 112: #endif
 113: 
 114: 
 115: #define tbufq   b_forw          /* empty transmit buffer headers */
 116: #define outbufq b_back          /* filled transmit buffers */
 117: #define rbufq   av_forw         /* empty receive buffers */
 118: #define inbufq  av_back         /* filled receive buffers */
 119: 
 120: /* redeclarations for dmcutab: */
 121: 
 122: #define xcnt    b_resid         /* saved port1 (xmem+char cnt) */
 123: #define state   b_flags
 124: 
 125: 
 126: int     dmcbase[NDMC][64];
 127: 
 128: dmcopen(dev)
 129: dev_t dev;
 130: {
 131:         register int unit;
 132:         register struct buf *dp, *bp, *hp;
 133:         long base;
 134:         if ((unit=minor(dev)) >= NDMC || unit < 0) {
 135:                 u.u_error = ENXIO;
 136:                 return;
 137:         }
 138:         dp = &dmcutab[unit];
 139:         if (dp->state & OPEN)
 140:                 return;
 141: 
 142:         dp->state = 0;
 143: 
 144:         dp->rbufq = bp = getiblk();
 145:         dmcinfo[unit].bp = bp;
 146:         bp->b_dev = dev;
 147:         dmcinit(unit);
 148: 
 149:         dp->tbufq = dmctbufs[unit];
 150:         for (hp = dp->tbufq; hp < &dmctbufs[unit][NTBUFS-1]; hp++)
 151:                 hp->tbufq = hp + 1;
 152:         hp->tbufq = 0;
 153:         dp->outbufq = 0;
 154:         dp->state = OPEN;
 155: }
 156: 
 157: dmcclose(dev)
 158: dev_t dev;
 159: {
 160:         register int unit;
 161:         register struct buf *dp;
 162: 
 163:         unit = minor(dev);
 164:         dp = &dmcutab[unit];
 165:         dmcaddr[unit]->outctrl &= ~IEO;
 166:         brelse(dmcinfo[unit].bp);
 167:         dp->state = 0;
 168: }
 169: 
 170: dmcread(dev)
 171: dev_t dev;
 172: {
 173:         register struct buf *dp;
 174:         register struct buf *bp, *pbp;
 175:         register int unit;
 176: 
 177:         unit=minor(dev);
 178:         dp = &dmcutab[unit];
 179: 
 180:         if ((!(dp->state & OPEN))       /* last read after NETCLOSE */
 181:             || (u.u_count < bp->b_bcount)) {
 182:                 u.u_error = EINVAL;
 183:                 return;
 184:         }
 185: 
 186:         for (;;) {
 187:                 (void) _spl5();
 188:                 if ((bp = dp->inbufq) != 0)
 189:                         break;
 190:                 if (dp->state & ERROR) {
 191:                         u.u_error = EIO;
 192:                         dp->state &= ~(ERROR|TOLD);
 193:                         dmcinit(unit);
 194:             (void) _spl0();
 195:                         return;
 196:                 }
 197:                 dp->state |= R_WAITING;
 198:                 sleep((caddr_t)dp, DMCPRI);
 199:         }
 200:         (void) _spl0();
 201: 
 202:         if (bp->b_bcount > 0) {
 203:                 iomove(mapin(bp), bp->b_bcount, B_READ);
 204:                 mapout(bp);
 205:         }
 206:         dp->inbufq = bp->inbufq;
 207:         for (pbp=dp; pbp->rbufq; pbp=pbp->rbufq)
 208:                 ;
 209:         pbp->rbufq = bp;
 210:         bp->rbufq = 0;
 211:         dmcitrans(unit,BACC | RFLAG, bp->b_un.b_addr, bp->xcnt);
 212: }
 213: 
 214: dmcwrite(dev)
 215: dev_t dev;
 216: {
 217:         register struct buf *bp, *dp, *pbp;
 218:         register int unit;
 219: 
 220:         if (chkphys(BYTE))
 221:                 return;
 222:         unit = minor(dev);
 223:         if (u.u_count > BUFSIZ) {
 224:                 u.u_error = EINVAL;
 225:                 return;
 226:         }
 227:         dp = &dmcutab[unit];
 228: 
 229:         for (;;) {
 230:                 (void) _spl5();
 231:                 if (dp->state & ERROR) {
 232:                         u.u_error = EIO;
 233:                         /*
 234:                          * If it is not necessary to report all errors
 235:                          * on reads (presumably to one read process)
 236:                          * the error could be cleared here.  However,
 237:                          * dmcinit should not be called until the outbufq
 238:                          * is empty, which is easiest to do by reading
 239:                          * until a read returns -1, at which point the error
 240:                          * is cleared.  Otherwise, do:
 241:                          * dp->state &= ~(ERROR|TOLD);
 242:                          * dmcinit(unit);
 243:                          */
 244:             (void) _spl0();
 245:                         return;
 246:                 }
 247:                 if (bp = dp->tbufq)
 248:                         break;
 249:                 dp->state |= W_WAITING;
 250:                 sleep((caddr_t)dp, DMCPRI);
 251:         }
 252:         (void) _spl0();
 253:         physbuf(bp,dev,B_WRITE);
 254:         u.u_procp->p_flag |= SLOCK;
 255:         mapalloc(bp);
 256:         dp->tbufq = bp->tbufq;
 257:         for (pbp=dp; pbp->outbufq; pbp=pbp->outbufq)
 258:                 ;
 259:         pbp->outbufq = bp;
 260:         bp->outbufq = 0;
 261: 
 262:         dmcitrans(unit, BACC|TFLAG, bp->b_un.b_addr,
 263:                 ((unsigned)bp->b_xmem<<EXTSHFT)|bp->b_bcount);
 264:         iowait(bp);
 265:         u.u_count = 0;
 266:         bp->b_flags = 0;
 267:         u.u_procp->p_flag &= ~SLOCK;
 268:         bp->tbufq = dp->tbufq;
 269:         dp->tbufq = bp;
 270:         if (dp->state & W_WAITING) {
 271:                 dp->state &= ~W_WAITING;
 272:                 wakeup((caddr_t)dp);
 273:         }
 274: }
 275: 
 276: #ifdef CLOSE
 277: #define NETCLOSE (('n'<<8)|1)
 278: 
 279: dmcioctl(dev,cmd,addr,flag)
 280: dev_t dev;
 281: caddr_t addr;
 282: {
 283:         register unit;
 284:         unit = minor(dev);
 285:         if (cmd == NETCLOSE) {
 286:                 dmcutab[unit].state |= CLOSING | ERROR;
 287:                 dmcitrans(unit,INVAL,(caddr_t)0,0);
 288:         }
 289:         else u.u_error = ENOTTY;
 290: }
 291: #endif
 292: 
 293: dmcoint(unit)
 294: {
 295:         register struct device *dmc;
 296:         register struct buf *bp, *dp, *pbp;
 297:         int errflgs;
 298: 
 299:         dp = &dmcutab[unit];
 300:         dmc = dmcaddr[unit];
 301:         if ((dmc->outctrl & TTYPE) == BACC) {
 302:                 if ((dmc->outctrl & TRBIT) == RFLAG) {
 303:                         bp = dp->rbufq;
 304: #ifdef DIAG
 305:                         if (bp == 0) {
 306:                                 printf("dmc rbufq missing\n");
 307:                                 goto error;
 308:                         }
 309:                         if (bp->b_un.b_addr != dmc->bufad) {
 310:                                 printf("dmc receive out of order\n");
 311:                                 goto error;
 312:                         }
 313: #endif
 314:                         bp->b_bcount = dmc->port1;
 315:                         for (pbp=dp; pbp->inbufq; pbp=pbp->inbufq)
 316:                                 ;
 317:                         pbp->inbufq = bp;
 318:                         bp->inbufq = 0;
 319:                         dp->rbufq = bp->rbufq;
 320:                         if (dp->state & R_WAITING) {
 321:                                 dp->state &= ~R_WAITING;
 322:                                 wakeup((caddr_t)dp);
 323:                         }
 324:                 } else {
 325:                         bp = dp->outbufq;
 326: #ifdef DIAG
 327:                         if  (bp == 0) {
 328:                                 printf("dmc outbufq missing\n");
 329:                                 goto error;
 330:                         }
 331:                         if (bp->b_un.b_addr != dmc->bufad) {
 332:                                 printf("dmc transmit out of order\n");
 333:                                 goto error;
 334:                         }
 335: #endif
 336:                         dp->outbufq = bp->outbufq;
 337:                         iodone(bp);
 338:                 }
 339:                 dp->state &= ~(ERROR | TOLD);
 340:                 dp->b_errcnt = 0;
 341:         } else {
 342:                 errflgs = dmc->port1;
 343: #ifdef CLOSE
 344:                 if ((errflgs & PROCERR) && (dp->state & CLOSING)){
 345:                         /* shutting down gracefully */
 346:                         dp->state &= ~(CLOSING|OPEN);
 347:                         dmc->outctrl &= ~IEO;
 348:                         goto error;
 349:                 }
 350: #endif
 351:                 if (((errflgs & (FATAL|TIMEOUT)) || ((errflgs&DCK) &&
 352:                     ++dp->b_errcnt>MAXERRS)) && ((dp->state & TOLD)==0)) {
 353:                         printf("DMC/%d error=%o\n",unit,errflgs);
 354:                         goto error;
 355:                 }
 356: #ifdef DIAG
 357:                 else if (dp->state & TOLD == 0) {
 358:                         printf("dmc nonfatal error %o\n",errflgs);
 359:                         dp->state &= TOLD;
 360:                 }
 361: #endif
 362:         }
 363:         dmc->outctrl &= ~RDYO;
 364:         return;
 365: error:
 366:         dmc->outctrl &= ~RDYO;
 367:         dp->state |= ERROR|TOLD;
 368:         for (bp=dp->outbufq; bp; bp=bp->outbufq) {
 369:                 bp->b_flags = B_ERROR | B_DONE;
 370:                 wakeup((caddr_t)bp);
 371:         }
 372:         if (dp->state & WAITING) {
 373:                 dp->state &= ~WAITING;
 374:                 wakeup((caddr_t)dp);
 375:         }
 376: }
 377: 
 378: dmciint(unit)
 379: {
 380:         register struct buf *dp;
 381:         register struct device *dmc;
 382:         register struct dmcinfo *infp;
 383: 
 384:         dp = &dmcutab[unit];
 385:         dmc = dmcaddr[unit];
 386:         infp = &dmcinfo[unit];
 387: 
 388:         if (dp->b_active) {
 389:                 dmc->bufad = infp->addr;
 390:                 dmc->port1 = infp->cnt;
 391:                 dmc->inctrl &= ~RQI;
 392:                 dp->b_active = 0;
 393:                 if (dp->state & TR_WAITING) {
 394:                         dp->state &= ~TR_WAITING;
 395:                         wakeup((caddr_t)dp);
 396:                 }
 397: #ifdef DIAG
 398:         } else {
 399:                 printf("bad DMC/%d input interrupt\n",unit);
 400:                 dp->state |= TOLD;
 401: #endif
 402:         }
 403: }
 404: 
 405: dmcinit(unit)
 406: {
 407:         register struct buf *bp, *dp, *hp;
 408:         long base;
 409: 
 410:         dp = &dmcutab[unit];
 411:         dmcaddr[unit]->mstrctrl |= MCLR;
 412:         dmcitrans(unit,BASEI, (caddr_t)dmcbase[unit], 0);
 413:         dmcitrans(unit,CTRL, (caddr_t)0, FDUP);
 414:         dmcaddr[unit]->outctrl |= IEO;
 415: 
 416:         bp = dmcinfo[unit].bp;
 417:         base = (long)bp->b_un.b_addr + (((long)bp->b_xmem)<<16);
 418:         bp->xcnt = ((unsigned)hiint(base)<<EXTSHFT) | BUFSIZ;
 419:         dmcitrans(unit, BACC|RFLAG,  bp->b_un.b_addr, bp->xcnt);
 420:         for (hp = &dmcrbufs[unit][0]; hp <= &dmcrbufs[unit][NRBUFS-1]; hp++) {
 421:                 bp->rbufq = hp;
 422:                 base += BUFSIZ;
 423:                 hp->b_un.b_addr = (caddr_t)loint(base);
 424:                 hp->b_xmem = (char)hiint(base);
 425:                 hp->xcnt = ((unsigned)hiint(base)<<EXTSHFT) | BUFSIZ;
 426:                 dmcitrans(unit,BACC | RFLAG, hp->b_un.b_addr, hp->xcnt);
 427:                 bp = hp;
 428:         }
 429:         bp->rbufq = 0;
 430:         dp->b_errcnt = 0;
 431:         dp->inbufq = 0;
 432: }
 433: 
 434: dmcitrans(unit, ttype, addr, cnt)
 435: caddr_t addr;
 436: unsigned cnt;
 437: {
 438:         register struct buf *dp;
 439:         register struct device *dmc;
 440:         register int i;
 441:         register struct dmcinfo *infp;
 442: 
 443:         dp = &dmcutab[unit];
 444:         infp = &dmcinfo[unit];
 445:         for (;;) {
 446:                 if (dp->state & ERROR)
 447:                         return;
 448:                 (void) _spl5();
 449:                 if (!dp->b_active)
 450:                         break;
 451:                 dp->state |= TR_WAITING;
 452:                 sleep((caddr_t)dp,DMCPRI);
 453:         }
 454:         (void) _spl0();
 455:         infp->addr = addr;
 456:         infp->cnt = cnt;
 457:         dp->b_active++;
 458: 
 459:         /* start transfer */
 460:         i = 0;
 461:         dmc = dmcaddr[unit];
 462:         while (dmc->inctrl & RDYI)
 463:                 if (++i > LOOPCNT) {
 464:                         /*
 465:                          * This shouldn't happen; if it does, it
 466:                          * will cause a spurious initialization.
 467:                          */
 468: #ifdef DIAG
 469:                         printf("dmc missed RDYI going off\n");
 470: #endif
 471:                         dp->state |= ERROR;
 472:                         return;
 473:                 }
 474:         dmc->inctrl |= RQI|ttype|IEI;
 475: }

Defined functions

dmcclose defined in line 157; never used
dmciint defined in line 378; never used
dmcinit defined in line 405; used 2 times
dmcioctl defined in line 279; never used
dmcitrans defined in line 434; used 7 times
dmcoint defined in line 293; never used
dmcopen defined in line 128; never used
dmcread defined in line 170; never used
dmcwrite defined in line 214; never used

Defined variables

dmcaddr defined in line 50; used 6 times
dmcbase defined in line 126; used 1 times
dmcinfo defined in line 63; used 5 times
dmcrbufs defined in line 57; used 2 times
  • in line 420(2)
dmctbufs defined in line 56; used 2 times
dmcutab defined in line 65; used 9 times

Defined struct's

device defined in line 41; used 12 times
dmcinfo defined in line 59; used 4 times

Defined macros

BACC defined in line 77; used 5 times
BASEI defined in line 80; used 1 times
BUFSIZ defined in line 27; used 5 times
CLOSE defined in line 22; used 2 times
CLOSING defined in line 98; used 3 times
CTRL defined in line 78; used 1 times
DCK defined in line 87; used 1 times
DISCON defined in line 92; never used
DLOST defined in line 91; never used
DMCPRI defined in line 24; used 3 times
ERROR defined in line 100; used 8 times
EXTSHFT defined in line 107; used 3 times
FATAL defined in line 86; used 1 times
FDUP defined in line 82; used 1 times
HDUP defined in line 83; never used
IEI defined in line 70; used 1 times
IEO defined in line 72; used 3 times
INVAL defined in line 79; used 1 times
LOOPCNT defined in line 38; used 1 times
MAINT defined in line 90; never used
MAXERRS defined in line 39; used 1 times
MCLR defined in line 67; used 1 times
NDMC defined in line 25; used 6 times
NETCLOSE defined in line 277; used 1 times
NRBUFS defined in line 28; used 2 times
NTBUFS defined in line 29; used 2 times
NXM defined in line 94; never used
OPEN defined in line 97; used 4 times
ORUN defined in line 89; never used
PROCERR defined in line 95; used 1 times
RDYI defined in line 68; used 1 times
RDYO defined in line 71; used 2 times
RESTART defined in line 93; never used
RFLAG defined in line 75; used 4 times
RQI defined in line 69; used 2 times
R_WAITING defined in line 102; used 3 times
STATE defined in line 99; never used
TFLAG defined in line 74; used 1 times
TIMEOUT defined in line 88; used 1 times
TOLD defined in line 101; used 7 times
TRBIT defined in line 73; used 1 times
TR_WAITING defined in line 104; used 3 times
TTYPE defined in line 76; used 1 times
WAITING defined in line 105; used 2 times
W_WAITING defined in line 103; used 3 times
hiint defined in line 110; used 4 times
inbufq defined in line 118; used 8 times
loint defined in line 111; used 1 times
outbufq defined in line 116; used 10 times
rbufq defined in line 117; used 10 times
state defined in line 123; used 30 times
tbufq defined in line 115; used 10 times
xcnt defined in line 122; used 5 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1864
Valid CSS Valid XHTML 1.0 Strict