Annotation of researchv8dc/sys/dev/ctu.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.