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