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