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