|
|
1.1 ! root 1: /* ! 2: * VAX 11/780 console driver ! 3: * multiple ID stuff is mostly to aid floppy ! 4: */ ! 5: #include "sys/param.h" ! 6: #include "sys/stream.h" ! 7: #include "sys/ttyio.h" ! 8: #include "sys/cons.h" ! 9: #include "sys/mtpr.h" ! 10: #include "sys/conf.h" ! 11: ! 12: #define NCONS 16 /* possible console IDs */ ! 13: ! 14: #define DATA 0xff ! 15: #define IDMASK 0xff ! 16: #define IDSHIFT 8 ! 17: ! 18: #define CONPRI (PZERO+5) /* something interruptible */ ! 19: ! 20: /* ! 21: * state bits ! 22: */ ! 23: #define TTSTOP 01 ! 24: #define TIMEOUT 04 ! 25: ! 26: /* ! 27: * cnbusy bits ! 28: */ ! 29: #define TXBUSY 01 ! 30: #define IOBUSY 02 /* cninc/cnoutc busy */ ! 31: ! 32: static char cnbusy; ! 33: static char cnonext; ! 34: static char cnstate[NCONS]; ! 35: static struct queue *cnrq[NCONS]; ! 36: static struct queue *cnwq[NCONS]; ! 37: ! 38: /* ! 39: * for internal io without device open ! 40: */ ! 41: struct cnbuf { ! 42: int count; ! 43: char *buf; ! 44: }; ! 45: static struct cnbuf cnibuf[NCONS]; ! 46: static struct cnbuf cnobuf[NCONS]; ! 47: static short cnlastin; /* debugging */ ! 48: ! 49: long cnopen(); ! 50: int cnclose(), cnoput(); ! 51: ! 52: static struct qinit cnrinit = { nulldev, NULL, cnopen, cnclose, 0, 0 }; ! 53: static struct qinit cnwinit = { cnoput, NULL, cnopen, cnclose, 200, 100 }; ! 54: struct streamtab cnstream = { &cnrinit, &cnwinit }; ! 55: struct cdevsw cncdev = cstrinit(&cnstream); ! 56: ! 57: long ! 58: cnopen(qp, dev) ! 59: struct queue *qp; ! 60: dev_t dev; ! 61: { ! 62: register int i; ! 63: ! 64: i = minor(dev); ! 65: if (i >= NCONS) ! 66: return (1); ! 67: cnrq[i] = qp; ! 68: cnwq[i] = WR(qp); ! 69: qp->ptr = (caddr_t)i; ! 70: mtpr(RXCS, mfpr(RXCS)|RXCS_IE); ! 71: return(1); ! 72: } ! 73: ! 74: cnclose(qp) ! 75: struct queue *qp; ! 76: { ! 77: register int i; ! 78: ! 79: i = (int)qp->ptr; ! 80: cnrq[i] = NULL; ! 81: cnwq[i] = NULL; ! 82: } ! 83: ! 84: /* ! 85: * Console write put routine ! 86: */ ! 87: cnoput(q, bp) ! 88: register struct queue *q; ! 89: register struct block *bp; ! 90: { ! 91: register struct ttydevb *sp; ! 92: register int dev; ! 93: ! 94: dev = (int)OTHERQ(q)->ptr; ! 95: switch(bp->type) { ! 96: case M_IOCTL: /* just acknowledge */ ! 97: sp = (struct ttydevb *)stiodata(bp); ! 98: switch (stiocom(bp)) { ! 99: case TIOCGDEV: ! 100: sp->ispeed = sp->ospeed = B9600; ! 101: bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR; ! 102: bp->type = M_IOCACK; ! 103: qreply(q, bp); ! 104: return; ! 105: ! 106: case TIOCSDEV: ! 107: bp->wptr = bp->rptr; ! 108: bp->type = M_IOCACK; ! 109: qreply(q, bp); ! 110: return; ! 111: ! 112: default: ! 113: bp->type = M_IOCNAK; ! 114: bp->wptr = bp->rptr; ! 115: qreply(q, bp); ! 116: return; ! 117: } ! 118: ! 119: case M_STOP: ! 120: cnstate[dev] |= TTSTOP; ! 121: break; ! 122: ! 123: case M_START: ! 124: cnstate[dev] &= ~TTSTOP; ! 125: cnstart(); ! 126: break; ! 127: ! 128: case M_FLUSH: ! 129: flushq(q, 0); ! 130: break; ! 131: ! 132: case M_DELAY: ! 133: case M_DATA: ! 134: if (bp->rptr >= bp->wptr) ! 135: break; ! 136: putq(q, bp); ! 137: cnstart(); ! 138: return; ! 139: ! 140: default: /* not handled; just toss */ ! 141: break; ! 142: } ! 143: freeb(bp); ! 144: } ! 145: ! 146: /* ! 147: * Console receive interrupt ! 148: */ ! 149: ! 150: cnrint() ! 151: { ! 152: register int c, dev; ! 153: register struct queue *qp; ! 154: register struct cnbuf *cp; ! 155: ! 156: c = mfpr(RXDB); ! 157: dev = (c >> IDSHIFT) & IDMASK; ! 158: cp = &cnibuf[dev]; ! 159: if (cp->count) { ! 160: *cp->buf++ = c; ! 161: if (--cp->count == 0) ! 162: wakeup((caddr_t)&cp->count); ! 163: return; ! 164: } ! 165: if ((qp = cnrq[dev])!=NULL) { ! 166: if ((qp->next->flag & QFULL) == 0) ! 167: putd(qp->next->qinfo->putp, qp->next, c); ! 168: return; ! 169: } ! 170: cnlastin = c; /* for debugging */ ! 171: } ! 172: ! 173: /* ! 174: * Transmitter interrupt ! 175: */ ! 176: cnxint() ! 177: { ! 178: cnbusy &=~ TXBUSY; ! 179: mtpr(TXCS, mfpr(TXCS)&~TXCS_IE); ! 180: cnstart(); ! 181: } ! 182: ! 183: cntime(dev) ! 184: caddr_t dev; ! 185: { ! 186: cnstate[(int)dev] &= ~TIMEOUT; ! 187: cnstart(); ! 188: } ! 189: ! 190: #define NEXT(i) (((i)+1)%NCONS) ! 191: ! 192: cnstart() ! 193: { ! 194: register struct block *bp; ! 195: register int i; ! 196: register struct queue *q; ! 197: register struct cnbuf *cp; ! 198: register s, j; ! 199: ! 200: s = spl6(); ! 201: if (cnbusy & TXBUSY) { ! 202: splx(s); ! 203: return; ! 204: } ! 205: i = cnonext; ! 206: for (j = 0; j < NCONS && (cnbusy & TXBUSY) == 0; i = NEXT(i), j++) { ! 207: cp = &cnobuf[i]; ! 208: if (cp->count) { ! 209: mtpr(TXDB, (*cp->buf++&0377) | (i<<IDSHIFT)); ! 210: mtpr(TXCS, mfpr(TXCS)|TXCS_IE); ! 211: cnbusy |= TXBUSY; ! 212: if (--cp->count == 0) ! 213: wakeup((caddr_t)&cp->count); ! 214: continue; ! 215: } ! 216: if ((q = cnwq[i]) == NULL) ! 217: continue; ! 218: if ((cnstate[i] & (TIMEOUT|TTSTOP)) || q->count == 0) ! 219: continue; ! 220: bp = getq(q); ! 221: switch (bp->type) { ! 222: case M_DATA: ! 223: mtpr(TXDB, (i<<IDSHIFT)|*bp->rptr++); ! 224: mtpr(TXCS, mfpr(TXCS)|TXCS_IE); ! 225: cnbusy |= TXBUSY; ! 226: if (bp->rptr >= bp->wptr) ! 227: freeb(bp); ! 228: else ! 229: putbq(q, bp); ! 230: break; ! 231: ! 232: case M_DELAY: ! 233: timeout(cntime, (caddr_t)i, (int)*bp->rptr); ! 234: cnstate[i] |= TIMEOUT; ! 235: default: /* flow through */ ! 236: freeb(bp); ! 237: break; ! 238: } ! 239: } ! 240: cnonext = i; ! 241: splx(s); ! 242: } ! 243: ! 244: /* ! 245: * Print a character on console; for printf. ! 246: * try to preserve things; wait a bit for console to come ready. ! 247: * all fairly hopeless. ! 248: */ ! 249: cnputc(c) ! 250: register c; ! 251: { ! 252: register s, timo; ! 253: ! 254: timo = 3000000; ! 255: while((mfpr(TXCS)&TXCS_RDY) == 0) ! 256: if(--timo == 0) ! 257: return; ! 258: if(c == 0) ! 259: return; ! 260: s = mfpr(TXCS); ! 261: mtpr(TXCS, 0); ! 262: mtpr(TXDB, c&DATA); ! 263: if(c == '\n') ! 264: cnputc('\r'); ! 265: cnputc(0); ! 266: mtpr(TXCS, s); ! 267: } ! 268: ! 269: /* ! 270: * primitives for internal console I/O ! 271: * p = cniwrite(id, buf, count) ! 272: * p = cniread(id, buf, count) ! 273: * p is a pointer to an integer. ! 274: * when the count is satisfied, *p will be zero and p will be awakened ! 275: * *p = 0 aborts the I/O ! 276: * cniwait(p, s) waits for at most s seconds, then aborts ! 277: * ! 278: * only one I/O may be outstanding per id; ! 279: * a new one aborts the previous one, quietly ! 280: * ! 281: * buf had best be static; stacks move, and the process waiting for io ! 282: * will almost certainly go out of context. ! 283: * hence the KSTART checks. ! 284: */ ! 285: ! 286: int * ! 287: cniread(id, buf, count) ! 288: int id, count; ! 289: char *buf; ! 290: { ! 291: register struct cnbuf *cp; ! 292: ! 293: if (id < 0 || id >= NCONS || (int)buf < KSTART) ! 294: panic("cniread"); ! 295: cp = &cnibuf[id]; ! 296: cp->buf = buf; ! 297: cp->count = count; ! 298: mtpr(RXCS, mfpr(RXCS)|RXCS_IE); ! 299: return (&cp->count); ! 300: } ! 301: ! 302: int * ! 303: cniwrite(id, buf, count) ! 304: int id, count; ! 305: char *buf; ! 306: { ! 307: register struct cnbuf *cp; ! 308: ! 309: if (id < 0 || id >= NCONS || (int)buf < KSTART) ! 310: panic("cniwrite"); ! 311: cp = &cnobuf[id]; ! 312: cp->buf = buf; ! 313: cp->count = count; ! 314: cnstart(); ! 315: return (&cp->count); ! 316: } ! 317: ! 318: cniwait(p, t) ! 319: register int *p; ! 320: int t; ! 321: { ! 322: register int s; ! 323: register int sh; ! 324: ! 325: s = spl6(); ! 326: while (*p) ! 327: if (tsleep((caddr_t)p, CONPRI, t) != TS_OK) { ! 328: sh = *p; ! 329: *p = 0; ! 330: splx(s); ! 331: return (sh); ! 332: } ! 333: splx(s); ! 334: return (0); ! 335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.