Annotation of researchv10dc/sys/md/ctapecomet.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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