|
|
1.1 ! root 1: /* ! 2: * driver for comet (and nebula?) console cassette ! 3: */ ! 4: ! 5: #include "sys/param.h" ! 6: #include "sys/user.h" ! 7: #include "sys/buf.h" ! 8: #include "sys/conf.h" ! 9: ! 10: /* ! 11: * registers -- all IPRs ! 12: */ ! 13: #define CSRS 0x1c /* receive status */ ! 14: #define CSRD 0x1d /* receive data */ ! 15: #define CSTS 0x1e /* transmit status */ ! 16: #define CSTD 0x1f /* transmit data */ ! 17: ! 18: /* ! 19: * bits in status registers ! 20: */ ! 21: ! 22: #define DONE 0200 ! 23: #define IE 0100 ! 24: #define BRK 01 /* transmit a break */ ! 25: ! 26: /* ! 27: * packet types ! 28: */ ! 29: ! 30: #define DATA 01 /* data packet */ ! 31: #define CTL 02 /* command */ ! 32: #define INIT 04 /* init handshake */ ! 33: #define CONT 020 /* continue */ ! 34: #define STOP 023 /* stop (flow control) */ ! 35: ! 36: /* ! 37: * opcodes in control packets ! 38: */ ! 39: ! 40: #define RESET 01 /* reset controller */ ! 41: #define READ 02 /* read a block */ ! 42: #define WRITE 03 /* write a block */ ! 43: #define END 0100 /* response from tu58 */ ! 44: ! 45: /* ! 46: * switches ! 47: */ ! 48: ! 49: #define MRSP 010 ! 50: ! 51: /* ! 52: * status codes in END packet ! 53: */ ! 54: ! 55: #define SOK 0 ! 56: #define SSOFT 1 /* ok but had to retry */ ! 57: #define SEOT (-2) /* ran off end of tape */ ! 58: #define SBBLK (-55) /* block number too big */ ! 59: ! 60: /* ! 61: * misc sizes ! 62: */ ! 63: ! 64: #define TBSIZE 512 /* size of a block on the tape */ ! 65: #define PMAX sizeof(struct dpkt) /* biggest packet size */ ! 66: #define DMAX 128 /* max bytes of data per packet */ ! 67: #define CCNT 10 /* count for CTL packets */ ! 68: ! 69: /* ! 70: * prototype control packet ! 71: */ ! 72: ! 73: struct cpkt { ! 74: char cp_flag; /* CTL */ ! 75: unsigned char cp_cnt; /* count == 012 */ ! 76: char cp_op; /* op code */ ! 77: char cp_mod; /* modifiers */ ! 78: char cp_unit; /* unit number */ ! 79: char cp_sw; /* switches (eg MRSP) */ ! 80: u_short cp_seq; /* sequence number (always 0) */ ! 81: u_short cp_bcnt; /* byte count */ ! 82: u_short cp_bno; /* desired block number */ ! 83: }; ! 84: ! 85: #define ce_sts cp_mod /* for END packet, success code */ ! 86: #define ce_xsts cp_bno /* extended status */ ! 87: ! 88: /* ! 89: * data packet ! 90: */ ! 91: ! 92: struct dpkt { ! 93: char cp_flag; /* DATA */ ! 94: unsigned char cp_cnt; /* count of data bytes following */ ! 95: char cd_data[DMAX]; ! 96: }; ! 97: ! 98: typedef union packet { ! 99: struct cpkt C; ! 100: struct dpkt D; ! 101: char B[PMAX]; ! 102: u_short W[PMAX / sizeof(u_short)]; ! 103: } PACKET; ! 104: ! 105: /* ! 106: * quick and dirty pseudo-clist ! 107: */ ! 108: ! 109: #define CBDAT 512 ! 110: #define QHI 400 ! 111: #define QLO 200 ! 112: ! 113: struct cbuf { ! 114: int cb_cc; ! 115: unsigned char *cb_rptr; ! 116: unsigned char *cb_wptr; ! 117: unsigned char cb_data[CBDAT]; ! 118: }; ! 119: ! 120: static struct cbuf ctuin, ctuout; ! 121: static int ctuflag; ! 122: ! 123: int ctuopen(), ctuclose(), cturead(), ctuwrite(); ! 124: struct cdevsw ctucdev = cdinit(ctuopen, ctuclose, cturead, ctuwrite, nodev); ! 125: ! 126: #define TBUSY 01 /* output busy */ ! 127: #define OPEN 02 /* device already open */ ! 128: #define WAIT 04 /* someone waiting for input */ ! 129: #define OSLEEP 010 /* someone waiting for output to drain */ ! 130: ! 131: #define DEBUG 0100000 /* debugging flag */ ! 132: ! 133: #define IPRI 28 ! 134: #define OPRI 29 ! 135: ! 136: #define hibyte(x) (((u_char *)&x)[1]) ! 137: #define lobyte(x) (((u_char *)&x)[0]) ! 138: #define hiword(x) (((u_short *)&x)[1]) ! 139: #define loword(x) (((u_short *)&x)[0]) ! 140: ! 141: ctuopen(dev, mode) ! 142: { ! 143: if (ctuflag & OPEN) { ! 144: u.u_error = EBUSY; ! 145: return; ! 146: } ! 147: ctuflag |= OPEN; ! 148: ctuinit(); ! 149: } ! 150: ! 151: ctuclose(dev) ! 152: { ! 153: ! 154: mtpr(CSTS, 0); ! 155: mtpr(CSRS, 0); ! 156: ctuflag &=~ OPEN; ! 157: } ! 158: ! 159: cturead(dev) ! 160: { ! 161: PACKET pkt; ! 162: register PACKET *pk = &pkt; ! 163: ! 164: if (u.u_count & 01) ! 165: u.u_count--; /* tu58 prefers even byte count */ ! 166: pk->C.cp_flag = CTL; ! 167: pk->C.cp_cnt = CCNT; ! 168: pk->C.cp_op = READ; ! 169: pk->C.cp_mod = 0; ! 170: pk->C.cp_unit = 0; ! 171: pk->C.cp_sw = MRSP; ! 172: pk->C.cp_seq = 0; ! 173: pk->C.cp_bcnt = u.u_count; ! 174: pk->C.cp_bno = Ltol(u.u_offset) / TBSIZE; ! 175: ctuput(pk); ! 176: for (;;) { ! 177: if (ctuget(pk) == 0) { ! 178: u.u_error = EIO; ! 179: break; ! 180: } ! 181: if (u.u_count == 0) ! 182: break; ! 183: if (pk->C.cp_flag != DATA) ! 184: break; ! 185: iomove(pk->D.cd_data, pk->C.cp_cnt, B_READ); ! 186: if (u.u_error) ! 187: break; ! 188: } ! 189: if (pk->C.cp_flag != CTL || pk->C.cp_op != END) ! 190: u.u_error = EIO; ! 191: if (u.u_error) { ! 192: ctuinit(); ! 193: return; ! 194: } ! 195: if (pk->C.ce_sts != SOK ! 196: && pk->C.ce_sts != SSOFT ! 197: && pk->C.ce_sts != SEOT /* operation overlapped end of tape */ ! 198: && pk->C.ce_sts != SBBLK) { /* operation past end of block */ ! 199: u.u_error = EIO; ! 200: printf("err on TU58: %o %o\n", pk->C.ce_sts & 0377, pk->C.ce_xsts); ! 201: return; ! 202: } ! 203: } ! 204: ! 205: ctuwrite(dev) ! 206: { ! 207: PACKET pkt; ! 208: register PACKET *pk = &pkt; ! 209: ! 210: if (u.u_count & 01) ! 211: u.u_count--; ! 212: pk->C.cp_flag = CTL; ! 213: pk->C.cp_cnt = CCNT; ! 214: pk->C.cp_op = WRITE; ! 215: pk->C.cp_mod = 0; ! 216: pk->C.cp_unit = 0; ! 217: pk->C.cp_sw = MRSP; ! 218: pk->C.cp_seq = 0; ! 219: pk->C.cp_bcnt = u.u_count; ! 220: pk->C.cp_bno = Ltol(u.u_offset) / TBSIZE; ! 221: ctuput(pk); ! 222: for (;;) { ! 223: if (ctuget(pk) == 0) { ! 224: u.u_error = EIO; ! 225: break; ! 226: } ! 227: if (pk->C.cp_flag != CONT) ! 228: break; ! 229: if (u.u_count == 0) ! 230: break; ! 231: pk->C.cp_cnt = min(u.u_count, DMAX); ! 232: iomove(pk->D.cd_data, pk->C.cp_cnt, B_WRITE); ! 233: if (u.u_error) ! 234: break; ! 235: pk->C.cp_flag = DATA; ! 236: ctuput(pk); ! 237: } ! 238: if (pk->C.cp_flag != CTL || pk->C.cp_op != END) ! 239: u.u_error = EIO; ! 240: if (u.u_error) { ! 241: ctuinit(); ! 242: return; ! 243: } ! 244: if (pk->C.ce_sts != SOK ! 245: && pk->C.ce_sts != SSOFT ! 246: && pk->C.ce_sts != SEOT) { ! 247: u.u_error = EIO; ! 248: printf("err on TU58: %o %o\n", pk->C.ce_sts & 0377, pk->C.ce_xsts); ! 249: return; ! 250: } ! 251: } ! 252: ! 253: /* ! 254: * send a packet to the tu58 ! 255: */ ! 256: ! 257: ctuput(pk) ! 258: register PACKET *pk; ! 259: { ! 260: register u_short *wp; ! 261: register char *cp; ! 262: register int n; ! 263: long sum; ! 264: ! 265: if (ctusbc(pk->C.cp_flag)) { ! 266: ctputc(pk->C.cp_flag, &ctuout); ! 267: ctustart(); ! 268: return; ! 269: } ! 270: while (ctuout.cb_cc >= QHI) { ! 271: ctuflag |= OSLEEP; ! 272: sleep((caddr_t)&ctuout, OPRI); ! 273: } ! 274: wp = pk->W; ! 275: sum = 0; ! 276: n = (pk->C.cp_cnt / sizeof(u_short)) + 1; ! 277: while (--n >= 0) { ! 278: sum += *wp++; ! 279: if (hiword(sum)) { /* wrap carry around */ ! 280: sum++; ! 281: hiword(sum) = 0; ! 282: } ! 283: } ! 284: cp = pk->B; ! 285: n = pk->C.cp_cnt + 2; ! 286: while (--n >= 0) ! 287: ctputc(*cp++, &ctuout); ! 288: ctputc(lobyte(sum), &ctuout); ! 289: ctputc(hibyte(sum), &ctuout); ! 290: ctustart(); ! 291: } ! 292: ! 293: /* ! 294: * retrieve a packet from the tu58 ! 295: * returns zero if packet is illegal (eg bad checksum) ! 296: * if no packet, wait for one ! 297: */ ! 298: ! 299: ctuget(pk) ! 300: register PACKET *pk; ! 301: { ! 302: register u_short *wp; ! 303: register char *cp; ! 304: register int n; ! 305: long sum; ! 306: u_short xsum; ! 307: ! 308: pk->C.cp_flag = ctuchr(); ! 309: if (ctusbc(pk->C.cp_flag)) ! 310: return (1); ! 311: pk->C.cp_cnt = ctuchr(); ! 312: cp = &pk->B[2]; ! 313: n = pk->C.cp_cnt; ! 314: if (n > PMAX) ! 315: return (0); ! 316: while (--n >= 0) ! 317: *cp++ = ctuchr(); ! 318: lobyte(xsum) = ctuchr(); ! 319: hibyte(xsum) = ctuchr(); ! 320: wp = pk->W; ! 321: n = (pk->C.cp_cnt / sizeof(u_short)) + 1; ! 322: sum = 0; ! 323: while (--n >= 0) { ! 324: sum += *wp++; ! 325: if (hiword(sum)) { /* wrap carry around. ugh. */ ! 326: sum++; ! 327: hiword(sum) = 0; ! 328: } ! 329: } ! 330: if (ctuflag & DEBUG) ! 331: printf("ctu %x\n", pk->C.cp_flag); ! 332: if (sum != xsum) { ! 333: printf("ctu: sum %x is %x\n", xsum, sum); ! 334: return (0); ! 335: } ! 336: return (1); ! 337: } ! 338: ! 339: /* ! 340: * is this type a single byte packet? ! 341: */ ! 342: ! 343: ctusbc(type) ! 344: register int type; ! 345: { ! 346: ! 347: switch (type) { ! 348: case DATA: ! 349: case CTL: ! 350: return (0); ! 351: ! 352: default: ! 353: return (1); ! 354: } ! 355: } ! 356: ! 357: /* ! 358: * hard reset ! 359: * called on open or error ! 360: */ ! 361: ! 362: ctuinit() ! 363: { ! 364: ! 365: mtpr(CSRS, 0); ! 366: mtpr(CSTS, BRK); ! 367: DELAY(250000); ! 368: mtpr(CSTS, 0); ! 369: ctflushq(&ctuin); ! 370: ctflushq(&ctuout); ! 371: mtpr(CSRS, IE); ! 372: ctputc(INIT, &ctuout); ! 373: ctputc(INIT, &ctuout); ! 374: ctustart(); ! 375: while (ctuchr() != CONT) ! 376: ; ! 377: } ! 378: ! 379: /* ! 380: * wait for one character from tu58 ! 381: */ ! 382: ! 383: ctuchr() ! 384: { ! 385: register int s; ! 386: ! 387: s = spl7(); ! 388: while (ctuin.cb_cc == 0) { ! 389: ctuflag |= WAIT; ! 390: sleep((caddr_t)&ctuin, IPRI); ! 391: } ! 392: splx(s); ! 393: return (ctgetc(&ctuin)); ! 394: } ! 395: ! 396: /* ! 397: * start output from queue ! 398: */ ! 399: ! 400: ctustart() ! 401: { ! 402: register int c; ! 403: register int s; ! 404: ! 405: s = spl7(); ! 406: if (ctuflag & TBUSY) ! 407: return; ! 408: if ((c = ctgetc(&ctuout)) >= 0) { ! 409: ctuflag |= TBUSY; ! 410: mtpr(CSTD, c); ! 411: mtpr(CSTS, IE); ! 412: } ! 413: if (ctuflag & OSLEEP && ctuout.cb_cc < QLO) { ! 414: wakeup((caddr_t)&ctuout); ! 415: ctuflag &=~ OSLEEP; ! 416: } ! 417: splx(s); ! 418: } ! 419: ! 420: /* ! 421: * transmitter interrupt ! 422: */ ! 423: ctu1int(dev) ! 424: { ! 425: ! 426: ctuflag &=~ TBUSY; ! 427: ctustart(); ! 428: } ! 429: ! 430: /* ! 431: * receiver interrupt ! 432: */ ! 433: ctu0int(dev) ! 434: { ! 435: static char cont = CONT; ! 436: ! 437: while (mfpr(CSRS) & DONE) { ! 438: ctputc(mfpr(CSRD), &ctuin); ! 439: ctuput((PACKET *)&cont); ! 440: if (ctuin.cb_cc > QHI) { ! 441: printf("ctu input overrun\n"); ! 442: ctflushq(&ctuin); ! 443: } ! 444: } ! 445: if (ctuflag & WAIT) { ! 446: ctuflag &=~ WAIT; ! 447: wakeup((caddr_t)&ctuin); ! 448: } ! 449: } ! 450: ! 451: /* ! 452: * fake clist routines ! 453: */ ! 454: ! 455: ctflushq(q) ! 456: register struct cbuf *q; ! 457: { ! 458: register int s; ! 459: ! 460: s = spl7(); ! 461: q->cb_cc = 0; ! 462: q->cb_rptr = q->cb_wptr = q->cb_data; ! 463: splx(s); ! 464: } ! 465: ! 466: int ! 467: ctgetc(q) ! 468: register struct cbuf *q; ! 469: { ! 470: register int s; ! 471: register int c; ! 472: ! 473: s = spl7(); ! 474: if (q->cb_cc <= 0) ! 475: c = -1; ! 476: else { ! 477: q->cb_cc--; ! 478: c = *q->cb_rptr++; ! 479: if (q->cb_rptr >= &q->cb_data[CBDAT]) ! 480: q->cb_rptr = q->cb_data; ! 481: } ! 482: splx(s); ! 483: return (c); ! 484: } ! 485: ! 486: ctputc(c, q) ! 487: char c; ! 488: register struct cbuf *q; ! 489: { ! 490: register int s; ! 491: ! 492: s = spl7(); ! 493: q->cb_cc++; ! 494: *q->cb_wptr++ = c; ! 495: if (q->cb_wptr >= &q->cb_data[CBDAT]) ! 496: q->cb_wptr = q->cb_data; ! 497: splx(s); ! 498: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.