[BACK]Return to ctu.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / vax

Annotation of sys/arch/vax/vax/ctu.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ctu.c,v 1.10 2007/06/06 17:15:13 deraadt Exp $ */
                      2: /*     $NetBSD: ctu.c,v 1.10 2000/03/23 06:46:44 thorpej Exp $ */
                      3: /*
                      4:  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed at Ludd, University of
                     18:  *      Lule}, Sweden and its contributors.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: /*
                     35:  * Device driver for 11/750 Console TU58.
                     36:  *
                     37:  * Error checking is almost nonexistent, the driver should be
                     38:  * fixed to at least calculate checksum on incoming packets.
                     39:  * Writing of tapes does not work, by some unknown reason so far.
                     40:  * It is almost useless to try to use this driver when running
                     41:  * multiuser, because the serial device don't have any buffers
                     42:  * so we will lose interrupts.
                     43:  */
                     44:
                     45: #include <sys/param.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/callout.h>
                     48: #include <sys/kernel.h>
                     49: #include <sys/buf.h>
                     50: #include <sys/fcntl.h>
                     51: #include <sys/malloc.h>
                     52: #include <sys/ioctl.h>
                     53: #include <sys/device.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/disklabel.h>     /* For disklabel prototype */
                     56:
                     57: #include <machine/mtpr.h>
                     58: #include <machine/rsp.h>
                     59: #include <machine/scb.h>
                     60: #include <machine/trap.h>
                     61:
                     62: enum tu_state {
                     63:        SC_UNUSED,
                     64:        SC_INIT,
                     65:        SC_READY,
                     66:        SC_SEND_CMD,
                     67:        SC_GET_RESP,
                     68:        SC_GET_WCONT,
                     69:        SC_GET_END,
                     70:        SC_RESTART,
                     71: };
                     72:
                     73: struct tu_softc {
                     74:        enum    tu_state sc_state;
                     75:        int     sc_error;
                     76:        char    sc_rsp[15];     /* Should be struct rsb; but don't work */
                     77:        u_char  *sc_xfptr;      /* Current char to xfer */
                     78:        u_char  *sc_blk;        /* Base of current 128b block */
                     79:        int     sc_tpblk;       /* Start block number */
                     80:        int     sc_nbytes;      /* Number of bytes to xfer */
                     81:        int     sc_xbytes;      /* Number of xfer'd bytes */
                     82:        int     sc_bbytes;      /* Number of xfer'd bytes this block */
                     83:        int     sc_op;          /* Read/write */
                     84:        int     sc_xmtok;       /* set if OK to xmit */
                     85:        struct  buf_queue sc_q; /* pending I/O requests */
                     86: } tu_sc;
                     87:
                     88: struct ivec_dsp tu_recv, tu_xmit;
                     89:
                     90: void   ctutintr(void *);
                     91: void   cturintr(void *);
                     92: void   ctuattach(void);
                     93: void   ctustart(struct buf *);
                     94: void   ctuwatch(void *);
                     95: short  ctu_cksum(unsigned short *, int);
                     96:
                     97: int    ctuopen(dev_t, int, int, struct proc *);
                     98: int    ctuclose(dev_t, int, int, struct proc *);
                     99: void   ctustrategy(struct buf *);
                    100: int    ctuioctl(dev_t, u_long, caddr_t, int, struct proc *);
                    101: int    ctudump(dev_t, daddr64_t, caddr_t, size_t);
                    102:
                    103: static struct callout ctu_watch_ch = CALLOUT_INITIALIZER;
                    104:
                    105: void
                    106: ctuattach()
                    107: {
                    108:        BUFQ_INIT(&tu_sc.sc_q);
                    109:
                    110:        tu_recv = idsptch;
                    111:        tu_recv.hoppaddr = cturintr;
                    112:        scb->scb_csrint = (void *)&tu_recv;
                    113:
                    114:        tu_xmit = idsptch;
                    115:        tu_xmit.hoppaddr = ctutintr;
                    116:        scb->scb_cstint = (void *)&tu_xmit;
                    117: }
                    118:
                    119: int
                    120: ctuopen(dev, oflags, devtype, p)
                    121:        dev_t dev;
                    122:        int oflags, devtype;
                    123:        struct proc *p;
                    124: {
                    125:        int unit, error;
                    126:
                    127:        unit = minor(dev);
                    128:
                    129:        if (unit)
                    130:                return ENXIO;
                    131:
                    132:        if (tu_sc.sc_state != SC_UNUSED)
                    133:                return EBUSY;
                    134:
                    135:        tu_sc.sc_error = 0;
                    136:        mtpr(0100, PR_CSRS);    /* Enable receive interrupt */
                    137:        callout_reset(&ctu_watch_ch, hz, ctuwatch, NULL);
                    138:
                    139:        tu_sc.sc_state = SC_INIT;
                    140:
                    141:        mtpr(RSP_TYP_INIT, PR_CSTD);
                    142:
                    143:         if ((error = tsleep((caddr_t)&tu_sc, (PZERO + 10)|PCATCH,
                    144:            "ctuopen", 0)))
                    145:                 return (error);
                    146:
                    147:        if (tu_sc.sc_error)
                    148:                return tu_sc.sc_error;
                    149:
                    150:        tu_sc.sc_state = SC_READY;
                    151:        tu_sc.sc_xmtok = 1;
                    152:
                    153:        mtpr(0100, PR_CSTS);
                    154:        return 0;
                    155:
                    156: }
                    157:
                    158: int
                    159: ctuclose(dev, oflags, devtype, p)
                    160:        dev_t dev;
                    161:        int oflags, devtype;
                    162:        struct proc *p;
                    163: {
                    164:        mtpr(0, PR_CSRS);
                    165:        mtpr(0, PR_CSTS);
                    166:        tu_sc.sc_state = SC_UNUSED;
                    167:        callout_stop(&ctu_watch_ch);
                    168:        return 0;
                    169: }
                    170:
                    171: void
                    172: ctustrategy(bp)
                    173:        struct buf *bp;
                    174: {
                    175:        int     s;
                    176:
                    177: #ifdef TUDEBUG
                    178:        printf("addr %x, block %x, nblock %x, read %x\n",
                    179:                bp->b_data, bp->b_blkno, bp->b_bcount,
                    180:                bp->b_flags & B_READ);
                    181: #endif
                    182:
                    183:        if (bp->b_blkno >= 512) {
                    184:                s = splbio();
                    185:                biodone(bp);
                    186:                splx(s);
                    187:                return;
                    188:        }
                    189:        bp->b_rawblkno = bp->b_blkno;
                    190:        s = splbio();
                    191:        disksort_blkno(&tu_sc.sc_q, bp); /* Why not use disksort? */
                    192:        if (tu_sc.sc_state == SC_READY)
                    193:                ctustart(bp);
                    194:        splx(s);
                    195: }
                    196:
                    197: void
                    198: ctustart(bp)
                    199:        struct  buf *bp;
                    200: {
                    201:        struct rsp *rsp = (struct rsp *)tu_sc.sc_rsp;
                    202:
                    203:
                    204:        tu_sc.sc_xfptr = tu_sc.sc_blk = bp->b_data;
                    205:        tu_sc.sc_tpblk = bp->b_blkno;
                    206:        tu_sc.sc_nbytes = bp->b_bcount;
                    207:        tu_sc.sc_xbytes = tu_sc.sc_bbytes = 0;
                    208:        tu_sc.sc_op = bp->b_flags & B_READ ? RSP_OP_READ : RSP_OP_WRITE;
                    209:
                    210:        rsp->rsp_typ = RSP_TYP_COMMAND;
                    211:        rsp->rsp_sz = 012;
                    212:        rsp->rsp_op = tu_sc.sc_op;
                    213:        rsp->rsp_mod = 0;
                    214:        rsp->rsp_drv = 0;
                    215:        rsp->rsp_sw = rsp->rsp_xx1 = rsp->rsp_xx2 = 0;
                    216:        rsp->rsp_cnt = tu_sc.sc_nbytes;
                    217:        rsp->rsp_blk = tu_sc.sc_tpblk;
                    218:        rsp->rsp_sum = ctu_cksum((unsigned short *)rsp, 6);
                    219:        tu_sc.sc_state = SC_SEND_CMD;
                    220:        if (tu_sc.sc_xmtok) {
                    221:                tu_sc.sc_xmtok = 0;
                    222:                ctutintr(NULL);
                    223:        }
                    224: }
                    225:
                    226: int
                    227: ctuioctl(dev, cmd, data, fflag, p)
                    228:        dev_t dev;
                    229:        u_long cmd;
                    230:        caddr_t data;
                    231:        int fflag;
                    232:        struct proc *p;
                    233: {
                    234:        return 0;
                    235: }
                    236:
                    237: /*
                    238:  * Not bloody likely...
                    239:  */
                    240: int
                    241: ctudump(dev, blkno, va, size)
                    242:        dev_t dev;
                    243:        daddr64_t blkno;
                    244:        caddr_t va;
                    245:        size_t size;
                    246: {
                    247:        return 0;
                    248: }
                    249:
                    250: void
                    251: cturintr(arg)
                    252:        void *arg;
                    253: {
                    254:        int     status = mfpr(PR_CSRD);
                    255:        struct  buf *bp;
                    256:
                    257:        bp = BUFQ_FIRST(&tu_sc.sc_q);
                    258:        switch (tu_sc.sc_state) {
                    259:
                    260:        case SC_UNUSED:
                    261:                printf("stray console storage interrupt, got %o\n", status);
                    262:                break;
                    263:
                    264:        case SC_INIT:
                    265:                if (status != RSP_TYP_CONTINUE)
                    266:                        tu_sc.sc_error = EIO;
                    267:                wakeup((void *)&tu_sc);
                    268:                break;
                    269:        case SC_GET_RESP:
                    270:                tu_sc.sc_tpblk++;
                    271:                if (tu_sc.sc_xbytes == tu_sc.sc_nbytes) {
                    272:                        tu_sc.sc_bbytes++;
                    273:                        if (tu_sc.sc_bbytes == 146) { /* We're finished! */
                    274: #ifdef TUDEBUG
                    275:                                printf("Xfer ok\n");
                    276: #endif
                    277:                                BUFQ_REMOVE(&tu_sc.sc_q, bp);
                    278:                                biodone(bp);
                    279:                                tu_sc.sc_xmtok = 1;
                    280:                                tu_sc.sc_state = SC_READY;
                    281:                                if (BUFQ_FIRST(&tu_sc.sc_q) != NULL)
                    282:                                        ctustart(BUFQ_FIRST(&tu_sc.sc_q));
                    283:                        }
                    284:                        break;
                    285:                }
                    286:                tu_sc.sc_bbytes++;
                    287:                if (tu_sc.sc_bbytes <  3) /* Data header */
                    288:                        break;
                    289:                if (tu_sc.sc_bbytes == 132) { /* Finished */
                    290:                        tu_sc.sc_bbytes = 0;
                    291:                        break;
                    292:                }
                    293:                if (tu_sc.sc_bbytes == 131) /* First checksum */
                    294:                        break;
                    295:                tu_sc.sc_xfptr[tu_sc.sc_xbytes++] = status;
                    296:                break;
                    297:
                    298:        case SC_GET_WCONT:
                    299:                if (status != 020)
                    300:                        printf("SC_GET_WCONT: status %o\n", status);
                    301:                else
                    302:                        ctutintr(NULL);
                    303:                tu_sc.sc_xmtok = 0;
                    304:                break;
                    305:
                    306:        case SC_RESTART:
                    307:                ctustart(BUFQ_FIRST(&tu_sc.sc_q));
                    308:                break;
                    309:
                    310:        default:
                    311:                if (status == 4) { /* Protocol error, or something */
                    312:                        tu_sc.sc_state = SC_RESTART;
                    313:                        mtpr(RSP_TYP_INIT, PR_CSTD);
                    314:                        return;
                    315:                }
                    316:                printf("Unknown receive ctuintr state %d, pack %o\n",
                    317:                    tu_sc.sc_state, status);
                    318:        }
                    319:
                    320: }
                    321:
                    322: void
                    323: ctutintr(arg)
                    324:        void *arg;
                    325: {
                    326:        int     c;
                    327:
                    328:        if (tu_sc.sc_xmtok)
                    329:                return;
                    330:
                    331:        switch (tu_sc.sc_state) {
                    332:        case SC_SEND_CMD:
                    333:                c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff;
                    334:                mtpr(c, PR_CSTD);
                    335:                if (tu_sc.sc_xbytes > 13) {
                    336:                        tu_sc.sc_state = (tu_sc.sc_op == RSP_OP_READ ?
                    337:                            SC_GET_RESP : SC_GET_WCONT);
                    338:                        tu_sc.sc_xbytes = 0;
                    339:                        tu_sc.sc_xmtok++;
                    340:                }
                    341:                break;
                    342:
                    343:        case SC_GET_WCONT:
                    344:                switch (tu_sc.sc_bbytes) {
                    345:                case 0:
                    346:                        mtpr(1, PR_CSTD); /* This is a data packet */
                    347:                        break;
                    348:
                    349:                case 1:
                    350:                        mtpr(128, PR_CSTD); /* # of bytes to send */
                    351:                        break;
                    352:
                    353:                case 130:
                    354:                        mtpr(0, PR_CSTD); /* First checksum */
                    355:                        break;
                    356:
                    357:                case 131:
                    358:                        mtpr(0, PR_CSTD); /* Second checksum */
                    359:                        break;
                    360:
                    361:                case 132: /* Nothing to send... */
                    362:                        tu_sc.sc_bbytes = -1;
                    363:                        if (tu_sc.sc_xbytes == tu_sc.sc_nbytes + 1)
                    364:                                tu_sc.sc_op = SC_GET_END;
                    365:                        break;
                    366:                default:
                    367:                        c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff;
                    368:                        mtpr(c, PR_CSTD);
                    369:                        break;
                    370:                }
                    371:                tu_sc.sc_bbytes++;
                    372:                break;
                    373:
                    374:        default:
                    375:                printf("Unknown xmit ctuintr state %d\n",tu_sc.sc_state);
                    376:        }
                    377: }
                    378:
                    379: short
                    380: ctu_cksum(buf, words)
                    381:        unsigned short *buf;
                    382:        int words;
                    383: {
                    384:        int i, cksum;
                    385:
                    386:        for (i = cksum = 0; i < words; i++)
                    387:                cksum += buf[i];
                    388:
                    389: hej:   if (cksum > 65535) {
                    390:                cksum = (cksum & 65535) + (cksum >> 16);
                    391:                goto hej;
                    392:        }
                    393:        return cksum;
                    394: }
                    395:
                    396: int    oldtp;
                    397:
                    398: /*
                    399:  * Watch so that we don't get blocked unnecessary due to lost int's.
                    400:  */
                    401: void
                    402: ctuwatch(arg)
                    403:        void *arg;
                    404: {
                    405:
                    406:        callout_reset(&ctu_watch_ch, hz, ctuwatch, NULL);
                    407:
                    408:        if (tu_sc.sc_state == SC_GET_RESP && tu_sc.sc_tpblk != 0 &&
                    409:            tu_sc.sc_tpblk == oldtp && (tu_sc.sc_tpblk % 128 != 0)) {
                    410:                printf("tu0: lost recv interrupt\n");
                    411:                ctustart(BUFQ_FIRST(&tu_sc.sc_q));
                    412:                return;
                    413:        }
                    414:        if (tu_sc.sc_state == SC_RESTART)
                    415:                mtpr(RSP_TYP_INIT, PR_CSTS);
                    416:        oldtp = tu_sc.sc_tpblk;
                    417: }

CVSweb