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: }