|
|
1.1 ! root 1: /* ! 2: * DZ-11 Driver ! 3: */ ! 4: ! 5: /* Modified 4/84 by J. Wolitzky to allow dialout operation with smart modems */ ! 6: ! 7: #define TRC(c) ! 8: ! 9: #include "sys/param.h" ! 10: #include "sys/stream.h" ! 11: #include "sys/ttyio.h" ! 12: #include "sys/ttyld.h" ! 13: #include "sys/ubaddr.h" ! 14: #include "sys/dz.h" ! 15: #include "sys/conf.h" ! 16: ! 17: #define LPB 8 /* lines per board */ ! 18: #define BOARD(d) ((d)>>3) ! 19: #define LINE(d) ((d)&07) ! 20: ! 21: #define BITS7 020 ! 22: #define BITS8 030 ! 23: #define TWOSB 040 ! 24: #define PENABLE 0100 ! 25: #define OPAR 0200 ! 26: #define CLR 020 /* Clear */ ! 27: #define MSE 040 /* Master Scan Enable */ ! 28: #define RIE 0100 /* Receiver Interrupt Enable */ ! 29: #define SAE 010000 /* Silo Alarm Enable */ ! 30: #define TIE 040000 /* Transmit Interrupt Enable */ ! 31: #define TRDY 0100000 /* Transmitter ready */ ! 32: #define DZ_IEN (MSE+RIE+TIE) ! 33: #define PERROR 010000 ! 34: #define FRERROR 020000 ! 35: #define OVERRUN 040000 ! 36: #define SSPEED B1200 /* std speed = 1200 baud */ ! 37: ! 38: #define ISOPEN 02 ! 39: #define WOPEN 04 ! 40: #define TIMEOUT 010 ! 41: #define CARR_ON 020 ! 42: #define DZSTOP 040 ! 43: #define HPCL 0100 ! 44: #define BRKING 0200 ! 45: #define DIALOUT 0400 /* set when used as dialout with smart modems */ ! 46: ! 47: #define DZPRI 30 ! 48: ! 49: struct device { ! 50: short dzcsr; ! 51: short dzrbuf; ! 52: #define dzlpr dzrbuf ! 53: char dztcr; ! 54: char dzdtr; ! 55: char dztbuf; ! 56: #define dzrind dztbuf ! 57: char dzbrk; ! 58: #define dzmsr dzbrk ! 59: }; ! 60: ! 61: extern struct dz dz[]; /* one per line */ ! 62: extern struct ubaddr dzaddr[]; /* one per board */ ! 63: extern int dzcnt; /* number of lines */ ! 64: int dzoverrun; ! 65: ! 66: char dz_speeds[] = { ! 67: 0, 020, 021, 022, 023, 024, 0, 025, ! 68: 026, 027, 030, 032, 034, 036, 037, 0 ! 69: }; ! 70: ! 71: long dzopen(); ! 72: int dzclose(), dzoput(); ! 73: ! 74: static struct qinit dzrinit = { noput, NULL, dzopen, dzclose, 0, 0 }; ! 75: struct qinit dzwinit = { dzoput, NULL, dzopen, dzclose, 200, 100 }; ! 76: struct streamtab dzinfo = { &dzrinit, &dzwinit }; ! 77: struct cdevsw dzcdev = cstrinit(&dzinfo); ! 78: ! 79: int dzmiss; ! 80: ! 81: long ! 82: dzopen(q, d) ! 83: register struct queue *q; ! 84: dev_t d; ! 85: { ! 86: register dev; ! 87: register struct dz *dzp; ! 88: register int s; ! 89: static int onceinit = 0; ! 90: ! 91: dev = minor(d); ! 92: if (dev >= dzcnt) ! 93: return(0); ! 94: dzp = &dz[dev]; ! 95: if ((dzp->addr = (struct device *)ubaddr(&dzaddr[BOARD(dev)])) == NULL ! 96: || ubbadaddr(dzaddr[BOARD(dev)].ubno, dzp->addr, sizeof(short))) { ! 97: printf("dz%d absent\n", BOARD(dev)); ! 98: return (0); ! 99: } ! 100: dz[BOARD(dev)*LPB].addr = dzp->addr; /* see intr code */ ! 101: if (onceinit == 0) { ! 102: onceinit++; ! 103: dzscan((caddr_t)0); ! 104: } ! 105: dzp->board = BOARD(dev); ! 106: dzp->line = LINE(dev); ! 107: q->ptr = (caddr_t)dzp; ! 108: WR(q)->ptr = (caddr_t)dzp; ! 109: dzscan((caddr_t)1); /* update CARR_ON */ ! 110: if ((dzp->state&ISOPEN)==0 || (dzp->state&CARR_ON)==0) { ! 111: s = spl5(); ! 112: for (;;) { ! 113: dzp->flags = F8BIT|ODDP|EVENP; ! 114: dzp->speed = SSPEED; ! 115: dzparam(dzp); ! 116: if (dzp->state & CARR_ON) ! 117: break; ! 118: #if NOTDEF ! 119: dzflag = dzboard[BOARD(dev)]->ui_flags; ! 120: /* ignore carrier? */ ! 121: if (dzflag & (1 << (LINE(dev)))) { ! 122: dzp->state |= (DIALOUT | CARR_ON); ! 123: break; ! 124: } ! 125: #endif ! 126: if (tsleep((caddr_t)dzp, DZPRI, 0) != TS_OK) { ! 127: wakeup((caddr_t)dzp); ! 128: dzp->speed = 0; ! 129: dzparam(dzp); ! 130: splx(s); ! 131: return(0); ! 132: } ! 133: } ! 134: dzp->rdq = q; ! 135: dzp->state |= ISOPEN; ! 136: splx(s); ! 137: } ! 138: TRC('o'); ! 139: return(1); ! 140: } ! 141: ! 142: dzclose(q) ! 143: register struct queue *q; ! 144: { ! 145: register struct dz *dzp; ! 146: register s; ! 147: ! 148: dzp = (struct dz *)q->ptr; ! 149: s = spl5(); ! 150: if (dzp->oblock) { ! 151: register struct block *bp = dzp->oblock; ! 152: dzp->oblock = NULL; ! 153: freeb(bp); ! 154: } ! 155: flushq(WR(q), 1); ! 156: dzp->rdq = NULL; ! 157: if (dzp->state&HPCL || (dzp->state&CARR_ON)==0) { ! 158: dzp->speed = 0; ! 159: dzparam(dzp); ! 160: } ! 161: dzp->state = 0; ! 162: splx(s); ! 163: TRC('c'); ! 164: } ! 165: ! 166: /* ! 167: * DZ write put routine ! 168: */ ! 169: dzoput(q, bp) ! 170: register struct queue *q; ! 171: register struct block *bp; ! 172: { ! 173: register struct dz *dzp = (struct dz *)q->ptr; ! 174: register s; ! 175: register struct ttydevb *tb; ! 176: register delaytime; ! 177: ! 178: TRC('p'); ! 179: switch(bp->type) { ! 180: ! 181: case M_IOCTL: ! 182: TRC('i'); ! 183: switch (stiocom(bp)) { ! 184: ! 185: case TIOCSDEV: ! 186: tb = (struct ttydevb *)stiodata(bp); ! 187: delaytime = 0; ! 188: if (dzp->speed != tb->ispeed) ! 189: delaytime = 20; ! 190: dzp->speed = tb->ispeed; ! 191: dzp->flags = tb->flags; ! 192: bp->type = M_IOCACK; ! 193: bp->wptr = bp->rptr; ! 194: qreply(q, bp); ! 195: qpctl1(q, M_DELAY, delaytime); /* wait a bit */ ! 196: qpctl(q, M_CTL); /* means do dzparam */ ! 197: dzstart(dzp); ! 198: return; ! 199: ! 200: case TIOCGDEV: ! 201: tb = (struct ttydevb *)stiodata(bp); ! 202: tb->ispeed = tb->ospeed = dzp->speed; ! 203: tb->flags = dzp->flags; ! 204: bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR; ! 205: bp->type = M_IOCACK; ! 206: qreply(q, bp); ! 207: return; ! 208: ! 209: case TIOCHPCL: ! 210: dzp->state |= HPCL; ! 211: bp->type = M_IOCACK; ! 212: bp->wptr = bp->rptr; ! 213: qreply(q, bp); ! 214: return; ! 215: ! 216: default: ! 217: bp->wptr = bp->rptr; ! 218: bp->type = M_IOCNAK; ! 219: qreply(q, bp); ! 220: return; ! 221: } ! 222: ! 223: case M_STOP: ! 224: s = spl5(); ! 225: dzp->state |= DZSTOP; ! 226: freeb(bp); ! 227: if (bp = dzp->oblock) { ! 228: dzp->oblock = NULL; ! 229: putbq(q, bp); ! 230: } ! 231: splx(s); ! 232: return; ! 233: ! 234: case M_START: ! 235: dzp->state &= ~DZSTOP; ! 236: dzstart(dzp); ! 237: break; ! 238: ! 239: case M_FLUSH: ! 240: flushq(q, 1); ! 241: freeb(bp); ! 242: s = spl5(); ! 243: if (bp = dzp->oblock) { ! 244: dzp->oblock = NULL; ! 245: freeb(bp); ! 246: } ! 247: splx(s); ! 248: return; ! 249: ! 250: case M_BREAK: ! 251: qpctl1(q, M_DELAY, 10); ! 252: putq(q, bp); ! 253: qpctl1(q, M_DELAY, 10); ! 254: dzstart(dzp); ! 255: return; ! 256: ! 257: case M_HANGUP: ! 258: dzp->state &= ~DZSTOP; ! 259: case M_DELAY: ! 260: case M_DATA: ! 261: putq(q, bp); ! 262: TRC('d'); ! 263: dzstart(dzp); ! 264: return; ! 265: ! 266: default: /* not handled; just toss */ ! 267: break; ! 268: } ! 269: freeb(bp); ! 270: } ! 271: ! 272: /* ! 273: * Receive interrupt. Argument is DZ board number ! 274: */ ! 275: dz0int(dev) ! 276: { ! 277: register struct dz *dzp; ! 278: register struct block *bp; ! 279: register struct device *dzaddr; ! 280: register int c; ! 281: ! 282: if (dev >= BOARD(dzcnt)) { ! 283: printf("dz%d bad rcv int\n", dev); ! 284: return; ! 285: } ! 286: dzaddr = dz[dev*LPB].addr; ! 287: while ((c = dzaddr->dzrbuf) < 0) { /* char present */ ! 288: dzp = &dz[dev*LPB + ((c>>8)&07)]; ! 289: if (c&(OVERRUN/*|PERROR*/)) { ! 290: if (c&OVERRUN) ! 291: dzoverrun++; ! 292: continue; ! 293: } ! 294: if (dzp->rdq == NULL) ! 295: continue; ! 296: if (dzp->rdq->next->flag&QFULL) { ! 297: dzmiss++; ! 298: continue; ! 299: } ! 300: if ((bp = allocb(16)) == NULL) ! 301: continue; /* no space */ ! 302: if (c&FRERROR) /* frame err (break) */ ! 303: bp->type = M_BREAK; ! 304: else ! 305: *bp->wptr++ = c; ! 306: (*dzp->rdq->next->qinfo->putp)(dzp->rdq->next, bp); ! 307: } ! 308: } ! 309: ! 310: /* ! 311: * set device parameters ! 312: */ ! 313: dzparam(dzp) ! 314: register struct dz *dzp; ! 315: { ! 316: register short lpr; ! 317: register struct device *dzaddr; ! 318: ! 319: dzaddr = dzp->addr; ! 320: dzaddr->dzcsr = DZ_IEN; ! 321: if (dzp->speed == 0) { ! 322: dzaddr->dzdtr &= ~(1 << dzp->line); /* hang up */ ! 323: return; ! 324: } ! 325: dzaddr->dzdtr |= 1 << dzp->line; ! 326: lpr = (dz_speeds[dzp->speed]<<8) | dzp->line; ! 327: if (dzp->flags & F8BIT) ! 328: lpr |= BITS8; ! 329: else ! 330: lpr |= (BITS7|PENABLE); ! 331: if ((dzp->flags & EVENP) == 0) ! 332: lpr |= OPAR; ! 333: if (dzp->speed == 3) ! 334: lpr |= TWOSB; /* 110 baud: 2 stop bits */ ! 335: dzaddr->dzlpr = lpr; ! 336: } ! 337: ! 338: /* ! 339: * Transmitter interrupt. dev is board number. ! 340: */ ! 341: dz1int(dev) ! 342: { ! 343: register struct device *dzaddr; ! 344: register struct dz *dzp; ! 345: register struct block *bp; ! 346: register sts; ! 347: ! 348: if (dev >= BOARD(dzcnt)) { ! 349: printf("dz%d bad xmt int\n", dev); ! 350: return; ! 351: } ! 352: dzaddr = dz[dev*LPB].addr; ! 353: while ((sts = dzaddr->dzcsr) & TRDY) { ! 354: dzp = &dz[dev*LPB + ((sts>>8)&07)]; ! 355: if (bp = dzp->oblock) { ! 356: if (bp->rptr < bp->wptr) { ! 357: dzaddr->dztbuf = *bp->rptr++; ! 358: continue; ! 359: } ! 360: freeb(bp); ! 361: dzp->oblock = NULL; ! 362: } ! 363: dzaddr->dztcr &= ~(1 << (dzp->line)); ! 364: dzstart(dzp); ! 365: } ! 366: } ! 367: ! 368: dztimo(dzp) ! 369: register struct dz *dzp; ! 370: { ! 371: if (dzp->state&BRKING) { ! 372: dzp->brking &= ~(1 << dzp->line); ! 373: dzp->addr->dzbrk = dzp->brking; ! 374: } ! 375: dzp->state &= ~(TIMEOUT|BRKING); ! 376: dzstart(dzp); ! 377: } ! 378: ! 379: dzstart(dzp) ! 380: register struct dz *dzp; ! 381: { ! 382: register s = spl5(); ! 383: register struct block *bp; ! 384: register struct device *dzaddr; ! 385: ! 386: TRC('s'); ! 387: again: ! 388: if (dzp->state & (TIMEOUT|DZSTOP|BRKING) || dzp->oblock) { ! 389: TRC('t'); ! 390: goto out; ! 391: } ! 392: if (dzp->rdq == NULL) ! 393: goto out; ! 394: if ((bp = getq(WR(dzp->rdq))) == NULL) { ! 395: TRC('n'); ! 396: goto out; ! 397: } ! 398: switch (bp->type) { ! 399: ! 400: case M_DATA: ! 401: dzp->oblock = bp; ! 402: dzaddr = dzp->addr; ! 403: dzaddr->dztcr |= 1 << (dzp->line); ! 404: break; ! 405: ! 406: case M_BREAK: ! 407: dzaddr = dzp->addr; ! 408: dzp->brking |= 1 << dzp->line; ! 409: dzaddr->dzbrk = dzp->brking; ! 410: dzp->state |= BRKING|TIMEOUT; ! 411: timeout(dztimo, (caddr_t)dzp, HZ/4); /* about 250 ms */ ! 412: freeb(bp); ! 413: break; ! 414: ! 415: case M_DELAY: ! 416: dzp->state |= TIMEOUT; ! 417: timeout(dztimo, (caddr_t)dzp, (int)*bp->rptr + 6); ! 418: freeb(bp); ! 419: break; ! 420: ! 421: case M_HANGUP: ! 422: dzp->speed = 0; ! 423: case M_CTL: ! 424: freeb(bp); ! 425: dzparam(dzp); ! 426: goto again; ! 427: ! 428: } ! 429: out: ! 430: splx(s); ! 431: } ! 432: ! 433: dzscan(timo) ! 434: caddr_t timo; ! 435: { ! 436: register struct device *dzaddr; ! 437: register struct dz *dzp; ! 438: register i; ! 439: ! 440: for (i=0, dzp=dz; i<dzcnt; dzp++, i++) { ! 441: if (dzp->addr == 0) ! 442: continue; ! 443: dzaddr = dzp->addr; ! 444: if (dzaddr->dzmsr & (1<<dzp->line)) { ! 445: /* carrier present */ ! 446: if ((dzp->state & CARR_ON)==0) ! 447: wakeup((caddr_t)dzp); ! 448: dzp->state |= CARR_ON; ! 449: } else if ((dzp->state & CARR_ON) && !(dzp->state & DIALOUT)) { ! 450: /* carrier lost */ ! 451: if (dzp->state&ISOPEN) { ! 452: dzaddr->dzdtr &= ~(1<<dzp->line); ! 453: if (dzp->rdq) ! 454: putctl(dzp->rdq->next,M_HANGUP); ! 455: } ! 456: dzp->state &= ~CARR_ON; ! 457: } ! 458: } ! 459: if (timo == 0) ! 460: timeout(dzscan, (caddr_t)0, 2*HZ); ! 461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.