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

Annotation of sys/arch/vax/uba/ts.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ts.c,v 1.17 2007/06/06 17:15:13 deraadt Exp $ */
                      2: /*     $NetBSD: ts.c,v 1.11 1997/01/11 11:34:43 ragge Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1991 The Regents of the University of California.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the University nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  *
                     32:  *     @(#)tmscp.c     7.16 (Berkeley) 5/9/91
                     33:  */
                     34:
                     35: /*
                     36:  * sccsid = "@(#)tmscp.c       1.24    (ULTRIX)        1/21/86";
                     37:  */
                     38:
                     39: /************************************************************************
                     40:  *                                                                     *
                     41:  *       Licensed from Digital Equipment Corporation                   *
                     42:  *                      Copyright (c)                                  *
                     43:  *              Digital Equipment Corporation                          *
                     44:  *                  Maynard, Massachusetts                             *
                     45:  *                        1985, 1986                                   *
                     46:  *                   All rights reserved.                              *
                     47:  *                                                                     *
                     48:  *       The Information in this software is subject to change         *
                     49:  *   without notice and should not be construed as a commitment                *
                     50:  *   by         Digital  Equipment  Corporation.   Digital   makes  no         *
                     51:  *   representations about the suitability of this software for                *
                     52:  *   any purpose.  It is supplied "As Is" without expressed  or                *
                     53:  *   implied  warranty.                                                        *
                     54:  *                                                                     *
                     55:  *       If the Regents of the University of California or its         *
                     56:  *   licensees modify the software in a manner creating                        *
                     57:  *   diriviative copyright rights, appropriate copyright               *
                     58:  *   legends may be placed on  the drivative work in addition          *
                     59:  *   to that set forth above.                                          *
                     60:  *                                                                     *
                     61:  ************************************************************************/
                     62:
                     63: /*
                     64:  * TSV05/TS05 device driver, written by Bertram Barth.
                     65:  *
                     66:  * should be TS11 compatible (untested)
                     67:  */
                     68:
                     69: #define TS11_COMPAT    /* don't use extended features provided by TS05 */
                     70:
                     71: #ifdef NEED_18BIT
                     72: #define TS_UBAFLAGS    UBA_NEED16
                     73: #else
                     74: #define TS_UBAFLAGS    0
                     75: #endif
                     76:
                     77: #define ENABLE_ESS
                     78: #define ENABLE_END
                     79:
                     80: #define ENABLE_EAI     /* enable Attention-Interrupts */
                     81: #undef ENABLE_EAI
                     82:
                     83: #define ENABLE_ERI     /* Enable Release Buffer Interrupts */
                     84: #undef ENABLE_ERI
                     85:
                     86: #ifdef DEBUG
                     87: int tsdebug = 1;
                     88: # define debug(x)      if (tsdebug > 0) {DELAY(2000); printf x; DELAY(3000);}
                     89: # define debug10(x)    if (tsdebug > 9) printf x
                     90: #else
                     91: # define debug(x)      /* just ignore it */
                     92: # define debug10(x)    /* just ignore it */
                     93: #endif
                     94:
                     95: #ifdef TRACE
                     96: int tstrace = 1;
                     97: # define trace(x)      if (tstrace > 0) {DELAY(2000); printf x; DELAY(3000);}
                     98: #else
                     99: # define trace(x)      /* just ignore it */
                    100: #endif
                    101:
                    102: /*
                    103:  * TODO: most :-)
                    104:  *
                    105:  * include uba-mapping into tsinit();
                    106:  * merge tsinit(), tsreset() and tsprobe();
                    107:  * complete tsintr();
                    108:  * add proper error/status messages
                    109:  * make messages appear where they are intended to.
                    110:  * check for termination-classes and appropriate actions.
                    111:  * check if flags like CVC and ATTN should be used.
                    112:  * look for correct handling of attentions.
                    113:  * check for correct usage of retry-commands.
                    114:  * ...
                    115:  */
                    116:
                    117:
                    118: #include <sys/param.h>
                    119: #include <sys/systm.h>
                    120: #include <sys/kernel.h>
                    121: #include <sys/buf.h>
                    122: #include <sys/conf.h>
                    123: #include <sys/errno.h>
                    124: #include <sys/file.h>
                    125: #include <sys/syslog.h>
                    126: #include <sys/ioctl.h>
                    127: #include <sys/mtio.h>
                    128: #include <sys/uio.h>
                    129: #include <sys/proc.h>
                    130:
                    131: #include <machine/pte.h>
                    132: #include <machine/sid.h>
                    133: #include <machine/cpu.h>
                    134: #include <machine/mtpr.h>
                    135:
                    136: #include <vax/uba/ubareg.h>
                    137: #include <vax/uba/ubavar.h>
                    138:
                    139: #include <vax/uba/tsreg.h>
                    140:
                    141: #include "ts.h"
                    142:
                    143: /*
                    144:  * ts command packets and communication area (per controller)
                    145:  */
                    146: struct ts {
                    147:        struct  tsdevice *reg;          /* address of i/o-registers */
                    148:        struct  tscmd     cmd;          /* command packet(s) */
                    149:        struct  tsmsg     msg;          /* message packet(s) */
                    150: } ts[NTS];
                    151:
                    152: /*
                    153:  * Software status, per controller.
                    154:  * also status per tape-unit, since only one unit per controller
                    155:  * (thus we have no struct ts_info)
                    156:  */
                    157: struct ts_softc {
                    158:        struct  device sc_dev;          /* Autoconf ... */
                    159:        struct  uba_unit sc_unit;       /* Struct common for UBA to talk */
                    160:        struct  ts *sc_ts;              /* Unibus address of uda struct */
                    161:        short   sc_mapped;              /* Unibus map allocated ? */
                    162:        int     sc_ubainfo;             /* Unibus mapping info */
                    163:        short   sc_state;               /* see below: ST_xxx */
                    164:        short   sc_flags;               /* see below: FL_xxx */
                    165:        short   sc_lcmd;                /* last command word */
                    166:        short   sc_rtc;                 /* retry count for lcmd */
                    167:        short   sc_lssr;                /* last status register */
                    168:        short   sc_lmsgh;               /* last message header */
                    169:        short   sc_lxst0;               /* last status word */
                    170:        short   sc_cmdf;                /* command flags (ack,cvc,ie) */
                    171:        short   sc_openf;               /* lock against multiple opens */
                    172:        short   sc_liowf;               /* last operation was write */
                    173:        int     sc_micro;               /* microcode revision */
                    174:        int     sc_ivec;                /* interrupt vector address */
                    175:        short   sc_ipl;                 /* interrupt priority, Q-bus */
                    176: };
                    177:
                    178: void   tsintr(int);
                    179: int    tsinit(struct ts_softc *);
                    180: void   tscommand(dev_t, int, int);
                    181: int    tsstatus(int);
                    182: int    tsexec(int, int);
                    183: int    tsstart(struct ts_softc *, struct buf *);
                    184: int    tswchar(int);
                    185: void   tsreset(int);
                    186: void   tsxstatus(struct tsmsg *);
                    187: int    tsmatch(struct device *, void *, void *);
                    188: void   tsattach(struct device *, struct device *, void *);
                    189: void   tsstrategy(struct buf *);
                    190:
                    191: int    tsopen(dev_t, int, int, struct proc *);
                    192: int    tsclose(dev_t, int, int, struct proc *);
                    193: int    tsioctl(dev_t, u_long, caddr_t, int, struct proc *);
                    194: int    tsread(dev_t, struct uio *);
                    195: int    tswrite(dev_t, struct uio *);
                    196: int    tsdump(dev_t, daddr64_t, caddr_t, size_t);
                    197:
                    198: struct cfdriver ts_cd = {
                    199:        NULL, "ts", DV_DULL
                    200: };
                    201:
                    202: struct cfattach ts_ca = {
                    203:        sizeof(struct ts_softc), tsmatch, tsattach
                    204: };
                    205:
                    206:
                    207: #define ST_INVALID     0       /* uninitialized, before probe */
                    208: #define ST_PROBE       1       /* during tsprobe(), not used */
                    209: #define ST_SLAVE       2       /* in tsslave(), init almost complete */
                    210: #define ST_ATTACH      3       /* during tsattach(), not used */
                    211: #define ST_INITIALIZED 4       /* init completed, set by tsintr() */
                    212: #define ST_RUNNING     5
                    213: #define ST_IDLE                6
                    214: #define ST_BUSY                7
                    215:
                    216: /* Bits in minor device */
                    217: #define TS_UNIT(dev)   (minor(dev)&03)
                    218: #define TS_HIDENSITY   010
                    219:
                    220: #define TS_PRI LOG_INFO
                    221:
                    222:
                    223: /*
                    224:  * Since we don't have credits and thus only one operation per time,
                    225:  * we don't have and don't need queues like MSCP/TMSCP use them.
                    226:  * Per controller we only need one internal buffer for ioctls and
                    227:  * two pointers to buffers to simulate similar behaviour ...
                    228:  */
                    229: struct buf      ts_cbuf[NTS];          /* internal cmd buffer (for ioctls) */
                    230: struct buf     *ts_wtab[NTS];          /* dummy I/O wait queue */
                    231: #define b_ubinfo       b_resid         /* Unibus mapping info, per buffer */
                    232:
                    233: /*----------------------------------------------------------------------*/
                    234:
                    235: /*
                    236:  * Initialize a TS device. Set up UBA mapping registers,
                    237:  * initialize data structures, what else ???
                    238:  */
                    239: int
                    240: tsinit (sc)
                    241:        struct ts_softc *sc;
                    242: {
                    243:        volatile struct tsdevice *tsregs;
                    244:        int unit = sc->sc_dev.dv_unit;
                    245:        struct uba_unit *uu;
                    246:
                    247:        uu = &sc->sc_unit;
                    248:        tsregs = (struct tsdevice *)ts[unit].reg;
                    249:        if (sc->sc_mapped == 0) {
                    250:                /*
                    251:                 * Map the communications area and command and message
                    252:                 * buffer into Unibus address space.
                    253:                 */
                    254:                sc->sc_ubainfo = uballoc((struct uba_softc *)
                    255:                    sc->sc_dev.dv_parent,
                    256:                    (caddr_t)&ts[unit], sizeof (struct ts), TS_UBAFLAGS);
                    257:                sc->sc_ts = (struct ts *)(UBAI_ADDR(sc->sc_ubainfo));
                    258:                sc->sc_mapped = 1;
                    259:        }
                    260:
                    261:        /*
                    262:         * bertram: start hardware initialization ??????
                    263:         */
                    264:
                    265:        /* tsreset(unit); */
                    266:
                    267:        return (1);
                    268: }
                    269:
                    270: /*
                    271:  * send a command using the default command-buffer for this unit/controller.
                    272:  * If a command-word is given, then assemble a one-word command.
                    273:  * other words in command-buffer are unchanged and must thus be initialized
                    274:  * before calling this function.
                    275:  */
                    276: int
                    277: tsexec (ctlr, cmd)
                    278:        int ctlr;
                    279:        int cmd;
                    280: {
                    281:        register struct ts_softc *sc = ts_cd.cd_devs[ctlr];
                    282:        register struct tscmd *tscmdp = &ts[ctlr].cmd;
                    283:        register long tscmdma = (long)&sc->sc_ts->cmd;  /* mapped address */
                    284:        volatile struct tsdevice *tsreg = ts[ctlr].reg;
                    285:        volatile char *dbx = ((char *)tsreg) + 3;
                    286:        volatile short sr;
                    287:
                    288:        sc->sc_cmdf |= TS_CF_ACK | TS_CF_IE;
                    289:        tscmdp->cmdr = sc->sc_cmdf | cmd;
                    290:        tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | sc->sc_cmdf | cmd;
                    291:        sc->sc_cmdf = 0;                /* XXX */
                    292:
                    293: #ifdef DEBUG
                    294:        switch (tscmdp->cmdr & TS_CF_CMASK) {
                    295:        case TS_CMD_RNF:        cmdName = "Read Next (Forward)";        break;
                    296:        case TS_CMD_RPR:        cmdName = "Read Previous (Reverse)";    break;
                    297:        case TS_CMD_WCHAR:      cmdName = "Write Characteristics";      break;
                    298:        case TS_CMD_WD:         cmdName = "Write Data (Next)";          break;
                    299:        case TS_CMD_WDR:        cmdName = "Write Data (Retry)";         break;
                    300:        case TS_CMD_SRF:        cmdName = "Space Records Forward";      break;
                    301:        case TS_CMD_SRR:        cmdName = "Space Records Reverse";      break;
                    302:        case TS_CMD_STMF:       cmdName = "Skip Tape Marks Forward";    break;
                    303:        case TS_CMD_STMR:       cmdName = "Skip Tape Marks Reverse";    break;
                    304:        case TS_CMD_RWND:       cmdName = "Rewind";                     break;
                    305:        case TS_CMD_WTM:        cmdName = "Write Tape Mark";            break;
                    306:        case TS_CMD_WTMR:       cmdName = "Write Tape Mark (Retry)";    break;
                    307:        case TS_CMD_STAT:       cmdName = "Get Status (END)";           break;
                    308:        default:                cmdName = "Unexpected Command";         break;
                    309:        }
                    310: #endif
                    311:
                    312:        sr = tsreg->tssr;
                    313:        if ((sr & TS_SSR) == 0) {       /* subsystem NOT ready */
                    314:                printf ("%s%d: subsystem not ready [%x]\n",
                    315:                    sc->sc_dev.dv_xname, sr);
                    316:                return (-1);
                    317:        }
                    318:        dbx = ((char *)tsreg) + 3;      /* dbx is located at the fourth byte */
                    319:        *dbx = (tscmdma >> 18) & 0x0F;  /* load bits 18-21 into dbx */
                    320:
                    321:        /* possible race-condition with ATTN !!! */
                    322:
                    323:        sr = tsreg->tssr;
                    324:        if ((sr & TS_RMR) != 0) {       /* Register modification Refused */
                    325:                printf ("ts: error writing TSDBX\n");
                    326:                return (-1);
                    327:        }
                    328:        /* now load bits 15-2 at pos 15-2 and bits 17,16 at pos 1,0 of TSDB */
                    329:        tsreg->tsdb = (tscmdma & 0xfffc) | ((tscmdma >> 16) & 0x03);
                    330:
                    331:        /*
                    332:         * wait for SSR or RMR to show up
                    333:         */
                    334:        sr = tsreg->tssr;
                    335:        if ((sr & TS_SSR) != 0) {       /* something went wrong .. */
                    336:                if (sr & TS_RMR) {
                    337:                        printf ("ts: error writing TSDB (RMR)\n");
                    338:                        return (-1);
                    339:                }
                    340:                if (sr & TS_NXM) {
                    341:                        printf ("ts: error writing TSDB (NXM)\n");
                    342:                        return (-1);
                    343:                }
                    344:                printf ("ts: error 0x%x while writing TSDB\n", sr);
                    345:                tsstatus (sr);
                    346:                return (-1);
                    347:        }
                    348:
                    349:        return (0);      /* completed successfully */
                    350: }
                    351:
                    352: /*
                    353:  * Execute a (ioctl) command on the tape drive a specified number of times.
                    354:  * This routine sets up a buffer and calls the strategy routine which
                    355:  * issues the command to the controller.
                    356:  */
                    357: void
                    358: tscommand (dev, cmd, count)
                    359:        register dev_t dev;
                    360:        int cmd;
                    361:        int count;
                    362: {
                    363:        register struct buf *bp;
                    364:        register int s;
                    365:
                    366:        trace (("tscommand (%d, %x, %d)\n", TS_UNIT(dev), cmd, count));
                    367:
                    368:        s = splbio();
                    369:        bp = &ts_cbuf[TS_UNIT(dev)];
                    370:
                    371:        while (bp->b_flags & B_BUSY) {
                    372:                /*
                    373:                 * This special check is because B_BUSY never
                    374:                 * gets cleared in the non-waiting rewind case. ???
                    375:                 */
                    376:                if (bp->b_bcount == 0 && (bp->b_flags & B_DONE))
                    377:                        break;
                    378:                bp->b_flags |= B_WANTED;
                    379:                tsleep ((caddr_t)bp, PRIBIO, "tscommand", 0);
                    380:                /* check MOT-flag !!! */
                    381:        }
                    382:        bp->b_flags = B_BUSY | B_READ;
                    383:
                    384:        splx(s);
                    385:
                    386:        /*
                    387:         * Load the buffer.  The b_count field gets used to hold the command
                    388:         * count.  the b_resid field gets used to hold the command mneumonic.
                    389:         * These 2 fields are "known" to be "safe" to use for this purpose.
                    390:         * (Most other drivers also use these fields in this way.)
                    391:         */
                    392:        bp->b_dev = dev;
                    393:        bp->b_bcount = count;
                    394:        bp->b_resid = cmd;
                    395:        bp->b_blkno = 0;
                    396:        tsstrategy (bp);
                    397:        /*
                    398:         * In case of rewind from close, don't wait.
                    399:         * This is the only case where count can be 0.
                    400:         */
                    401:        if (count == 0) {
                    402:                debug (("tscommand: direct return, no biowait.\n"));
                    403:                return;
                    404:        }
                    405:        debug (("tscommand: calling biowait ...\n"));
                    406:        biowait (bp);
                    407:        if (bp->b_flags & B_WANTED)
                    408:                wakeup ((caddr_t)bp);
                    409:        bp->b_flags &= B_ERROR;
                    410: }
                    411:
                    412: /*
                    413:  * Start an I/O operation on TS05 controller
                    414:  */
                    415: int
                    416: tsstart (sc, bp)
                    417:        register struct ts_softc *sc;
                    418:        register struct buf *bp;
                    419: {
                    420:        int ctlr = sc->sc_dev.dv_unit;
                    421:        volatile struct tsdevice *tsreg = ts[ctlr].reg;
                    422:        register struct tscmd *tscmdp = &ts[ctlr].cmd;
                    423:        register struct buf *dp;
                    424:        volatile int i, itmp;
                    425:        int ioctl;
                    426:        int cmd;
                    427:        int s;
                    428:
                    429:        if ((dp = ts_wtab[ctlr]) != NULL) {
                    430:                /*
                    431:                 * There's already a command pending ...
                    432:                 * Either we are called by tsintr or we have missed
                    433:                 * something important (race condition).
                    434:                 */
                    435:
                    436:                /* bertram: ubarelse ??? */
                    437:                ts_wtab[ctlr] = NULL;
                    438:                dp->b_flags |= B_ERROR;
                    439:                s = splbio();
                    440:                biodone (dp);
                    441:                splx(s);
                    442:
                    443:                if (tsreg->tssr & TS_SC) {      /* Special Condition; Error */
                    444:                        log (TS_PRI, "%s: tssr 0x%x, state %d\n",
                    445:                                sc->sc_dev.dv_xname, tsreg->tssr, sc->sc_state);
                    446:                        tsinit (sc);
                    447:                        return (-1);
                    448:                }
                    449:                /* XXX */
                    450:        }
                    451:
                    452:        /*
                    453:         * Check if command is an ioctl or not (ie. read or write).
                    454:         * If it's an ioctl then just set the flags for later use;
                    455:         * For other commands attempt to setup a buffer pointer.
                    456:         */
                    457:        if (bp == &ts_cbuf[ctlr]) {
                    458:                ioctl = 1;
                    459:        } else {
                    460:                ioctl = 0;
                    461:
                    462:                /*
                    463:                 * now we try to map the buffer into uba map space (???)
                    464:                 */
                    465:                i = TS_UBAFLAGS;
                    466:                switch (vax_cputype) {
                    467:                case VAX_8600:
                    468:                case VAX_780:
                    469:                        i |= UBA_CANTWAIT;
                    470:                        break;
                    471:                case VAX_750:
                    472:                        i |= sc->sc_unit.uu_ubinfo | UBA_CANTWAIT;
                    473:                        break;
                    474:                case VAX_730:
                    475:                case VAX_78032:
                    476:                        i |= UBA_CANTWAIT;
                    477:                        break;
                    478:                default:
                    479:                        printf ("unsupported cpu %d in tsstart.\n", vax_cputype);
                    480:                } /* end switch (vax_cputype) */
                    481:
                    482:                if ((i = ubasetup(sc->sc_dev.dv_parent->dv_unit, bp, i)) == 0) {
                    483:                        /*
                    484:                         * For some reasons which I don't (yet? :) understand,
                    485:                         * tmscp.c initiates in this situation a GET-UNIT
                    486:                         * command. (Because no data-buffers are necessary?)
                    487:                         */
                    488:                        cmd = TS_CMD_STAT;
                    489:                        goto do_cmd;
                    490:                        return (-1);    /* ??? */
                    491:                }
                    492: #if defined(VAX750)
                    493:                if (vax_cputype == VAX_750)
                    494:                        itmp = i & 0xfffffff;           /* mask off bdp */
                    495:                else
                    496: #endif
                    497:                        itmp = i;
                    498:
                    499:                /* XXX */
                    500:        }
                    501:
                    502:        /*
                    503:         * If it's an ioctl command, then assemble the command.
                    504:         * The "b_resid" field holds the command-number as defined
                    505:         * in <sys/mtio.h>
                    506:         */
                    507:        if (ioctl) {
                    508:                switch ((int)bp->b_resid) {
                    509:                case MTWEOF:
                    510:                        cmd = TS_CMD_WTM;
                    511:                        break;
                    512:                case MTFSF:
                    513:                        cmd = TS_CMD_STMF;
                    514:                        tscmdp->cw1 = bp->b_bcount;
                    515:                        break;
                    516:                case MTBSF:
                    517:                        cmd = TS_CMD_STMR;
                    518:                        tscmdp->cw1 = bp->b_bcount;
                    519:                        break;
                    520:                case MTFSR:
                    521:                        cmd = TS_CMD_SRF;
                    522:                        tscmdp->cw1 = bp->b_bcount;
                    523:                        break;
                    524:                case MTBSR:
                    525:                        cmd = TS_CMD_SRR;
                    526:                        tscmdp->cw1 = bp->b_bcount;
                    527:                        break;
                    528:                case MTREW:
                    529:                        cmd = TS_CMD_RWND;
                    530: #ifndef TS11_COMPAT
                    531:                        if (bp->b_bcount == 0) {
                    532:                                cmd = TS_CMD_RWII;
                    533:                        }
                    534: #endif
                    535:                        break;
                    536:                case MTOFFL:
                    537:                        cmd = TS_CMD_RWUL;
                    538:                        break;
                    539:                case MTNOP:
                    540:                        cmd = TS_CMD_STAT;
                    541:                        break;
                    542:                default:
                    543:                        printf ("%s: bad ioctl %d\n", sc->sc_dev.dv_xname,
                    544:                                (int)bp->b_resid);
                    545:                        /* Need a no-op. get status */
                    546:                        cmd = TS_CMD_STAT;
                    547:                } /* end switch (bp->b_resid) */
                    548:        } else {        /* Its a read/write command (not an ioctl) */
                    549:                tscmdp->cw1 = UBAI_ADDR(i) & 0xffff;
                    550:                tscmdp->cw2 = (UBAI_ADDR(i) >> 16) & 0x3f;
                    551:                tscmdp->cw3 = bp->b_bcount;
                    552:
                    553:                if (bp->b_flags & B_READ) {
                    554:                        cmd = TS_CMD_RNF;
                    555:                }
                    556:                else {
                    557:                        cmd = TS_CMD_WD;
                    558:                }
                    559:                bp->b_ubinfo = itmp;                    /* save mapping info */
                    560:        }
                    561:
                    562:        /*
                    563:         * Move buffer to I/O wait pseudo-queue
                    564:         */
                    565:        if (ts_wtab[ctlr]) {
                    566:                /*
                    567:                 * we are already waiting for something ...
                    568:                 * this should not happen, so we have a problem now.
                    569:                 * bertram: set error-flag and call biodone() ???
                    570:                 */
                    571:        }
                    572:        ts_wtab[ctlr] = bp;
                    573:
                    574:        /*
                    575:         * Now that the command-buffer is setup, give it to the controller
                    576:         */
                    577: do_cmd:
                    578:        return (tsexec(ctlr, cmd));
                    579: }
                    580:
                    581: /*
                    582:  * initialize the controller by sending WRITE CHARACTERISTICS command.
                    583:  * contents of command- and message-buffer are assembled during this
                    584:  * function.
                    585:  */
                    586: int
                    587: tswchar (ctlr)
                    588:        int ctlr;
                    589: {
                    590:        struct ts_softc *sc = ts_cd.cd_devs[ctlr];
                    591:        volatile struct tsdevice *tsregs = ts[ctlr].reg;
                    592:        volatile struct tscmd *tscmdp = &ts[ctlr].cmd;
                    593:        volatile struct tsmsg *tsmsgp = &ts[ctlr].msg;
                    594:        volatile unsigned int sr, ma, timeout;
                    595:
                    596:        /*
                    597:         * assemble and send "WRITE CHARACTERISTICS" command
                    598:         */
                    599:        ma = (long)tsmsgp;
                    600:        if (ma & 0x7FC00001) {  /* address must be even and 22-bit */
                    601:                printf ("invalid address 0x%0x for msg-buffer.\n", ma);
                    602:                return (-1);
                    603:        }
                    604:
                    605:        tsmsgp->hdr = ma & 0xFFFF;              /* low order addr. bits */
                    606:        tsmsgp->dfl = (ma >> 16) & 0x003F;      /* high order addr. bits */
                    607:        tsmsgp->rbpcr = 16;                     /* size of message-buffer */
                    608:        tsmsgp->xst0 = 0;                       /* chacacteristics mode word */
                    609:        tsmsgp->xst1 = 0;                       /* control word (ext.feat.) */
                    610:
                    611: #ifdef TS11_COMPAT
                    612:        tsmsgp->rbpcr = 14;             /* size of message-buffer */
                    613:        tsmsgp->xst0  = 0;              /* chacacteristics mode word */
                    614:        tsmsgp->xst1  = 0;              /* control word (ext.feat.) */
                    615: #else
                    616:        tsmsgp->rbpcr = 16;             /* size of extended message buffer */
                    617:        tsmsgp->xst0  = 0;              /* chacacteristics mode word */
                    618:        tsmsgp->xst1  = 0;              /* unit-select */
                    619:        tsmsgp->xst1 |= TS_WC_HSP;      /* high speed */
                    620: #endif
                    621:
                    622: #ifdef ENABLE_ESS
                    623:        tsmsgp->xst0 |= TS_WC_ESS;
                    624: #ifdef ENABLE_ENB
                    625:        tsmsgp->xst0 |= TS_WC_ENB;
                    626: #endif
                    627: #endif
                    628:
                    629: #ifdef ENABLE_EAI
                    630:        tsmsgp->xst0 |= TS_WC_EAI;
                    631: #ifdef ENABLE_ERI
                    632:        tsmsgp->xst0 |= TS_WC_ERI;
                    633: #endif
                    634: #endif
                    635:
                    636:        tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR;     /* obsolete */
                    637:        tscmdp->cw1  = ma & 0xFFFF;
                    638:        tscmdp->cw2  = (ma >> 16) & 0x003F;
                    639:        tscmdp->cw3  = 10;                 /* size of charact.-data */
                    640:
                    641:        if (tsexec (ctlr, TS_CMD_WCHAR) < 0) {
                    642:                printf ("%s: write characteristics command failed [%x]\n",
                    643:                    sc->sc_dev.dv_xname, tsregs->tssr);
                    644:                return (-1);
                    645:        }
                    646:
                    647:        timeout = 1000;                /* timeout in 10 seconds */
                    648:        do {
                    649:                DELAY(10000);
                    650:                sr = tsregs->tssr;
                    651:                debug10 (("\ttssr: 0x%x\n", sr));
                    652:                if (timeout-- > 0) {
                    653:                        printf ("timeout during initialize.");
                    654:                        tsstatus (sr);
                    655:                        return (-1);
                    656:                }
                    657:        } while ((sr & TS_SSR) == 0);
                    658:        tsstatus (sr);
                    659:
                    660:        return (0);
                    661: }
                    662:
                    663: /*
                    664:  *
                    665:  */
                    666: void
                    667: tsreset(ctlr)
                    668:        int ctlr;
                    669: {
                    670:        struct ts_softc *sc = ts_cd.cd_devs[ctlr];
                    671:        volatile struct tsdevice *tsreg = ts[ctlr].reg;
                    672:        volatile unsigned int sr, timeout;
                    673:
                    674:        /*
                    675:         * reset ctlr by writing into TSSR, then write characteristics
                    676:         */
                    677:        timeout = 1000;         /* timeout in 10 seconds */
                    678:        tsreg->tssr = 0;                        /* start initialization */
                    679:        do {
                    680:                DELAY(10000);
                    681:                sr = tsreg->tssr;
                    682:                debug10 (("\ttssr: 0x%x\n", sr));
                    683:                if (timeout-- > 0) {
                    684:                        if (sr != 0)
                    685:                                printf ("%s: timeout waiting for TS_SSR\n",
                    686:                                        sc->sc_dev.dv_xname);
                    687:                        tsstatus (sr);
                    688:                        return;
                    689:                }
                    690:        } while ((sr & TS_SSR) == 0);   /* wait until subsystem ready */
                    691:        tsstatus (sr);
                    692:
                    693:        return;
                    694: }
                    695:
                    696: /*
                    697:  * probe for device. If found, try to raise an interrupt.
                    698:  * XXX - most of this should be done in the attach routine.
                    699:  */
                    700: int
                    701: tsmatch(parent, match, aux)
                    702:        struct  device *parent;
                    703:        void    *match, *aux;
                    704: {
                    705:        struct ts_softc *sc = match;
                    706:        struct uba_softc *uh = (void *)parent;
                    707:        struct uba_attach_args *ua = aux;
                    708:        struct tsdevice *tsregs = (struct tsdevice*)ua->ua_addr;
                    709:        volatile unsigned int sr, timeout, count;
                    710:        int ctlr = sc->sc_dev.dv_unit;
                    711:
                    712:        ts_wtab[ctlr] = NULL;
                    713:        sc->sc_ts = &ts[ctlr];
                    714:        sc->sc_state = ST_PROBE;
                    715:        sc->sc_flags = 0;
                    716:        ts[ctlr].reg = (struct tsdevice*)ua->ua_addr;
                    717:
                    718:        /*
                    719:         * Set host-settable interrupt vector.
                    720:         * Assign 0 to the TSSR register to start the ts-device initialization.
                    721:         * The device is not really initialized at this point, this is just to
                    722:         * find out if the device exists.
                    723:         */
                    724:        sc->sc_ivec = (uh->uh_lastiv -= 4);
                    725:
                    726:        count = 0;
                    727: again:
                    728:        timeout = 1000;         /* timeout in 10 seconds */
                    729:        tsregs->tssr = 0;                       /* start initialization */
                    730:        do {
                    731:                DELAY(10000);
                    732:                sr = tsregs->tssr;
                    733:                debug10 (("\ttssr-1: 0x%x\n", sr));
                    734:                if (timeout-- > 0) {
                    735:                        if (sr != 0)    /* the device exists !!! */
                    736:                                printf ("%s: timeout waiting for TS_SSR\n",
                    737:                                        sc->sc_dev.dv_xname);
                    738:                        tsstatus (sr);
                    739:                        goto bad;
                    740:                }
                    741:        } while ((sr & TS_SSR) == 0);   /* wait until subsystem ready */
                    742:        tsstatus (sr);
                    743:
                    744:        tswchar (ctlr);         /* write charact. to enable interrupts */
                    745:                                /* completion of this will raise the intr. */
                    746:
                    747: #ifdef notyet
                    748:        sc->sc_ipl = br = qbgetpri();
                    749: #else
                    750:        sc->sc_ipl = 0x15;
                    751: #endif
                    752:        return (sizeof (struct tsdevice));
                    753:
                    754: bad:   if (++count < 3)
                    755:                goto again;
                    756:
                    757: #ifdef notyet
                    758:        splx(s);
                    759: #endif
                    760:        return (0);
                    761: }
                    762:
                    763:
                    764: /*
                    765:  * Try to find a slave (a drive) on the controller.
                    766:  * Since there's only one drive per controller there's nothing to do.
                    767:  * (we could check the status of the drive (online/offline/...)
                    768:  */
                    769: void
                    770: tsattach(parent, self, aux)
                    771:        struct device *parent, *self;
                    772:        void *aux;
                    773: {
                    774:        struct ts_softc *sc = (void *)self;
                    775:        int ctlr = sc->sc_dev.dv_unit;
                    776:        struct tsmsg *tsmsgp = &ts[ctlr].msg;
                    777:
                    778:        trace (("tsslave (%x, %x)\n", ui, reg));
                    779:
                    780:        /*
                    781:         * write the characteristics (again)
                    782:         * This will raise an interrupt during ST_SLAVE which indicates
                    783:         * completion of initialization ...
                    784:         */
                    785:        sc->sc_state = ST_SLAVE;        /* tsintr() checks this ... */
                    786:        if (tswchar (ctlr) < 0) {
                    787:                printf ("%s: cannot initialize", sc->sc_dev.dv_xname);
                    788:        }
                    789:        sc->sc_micro = (tsmsgp->xst2 & TS_SF_MCRL) >> 2;
                    790:        printf ("%s: rev %d, extended features %s, transport %s\n",
                    791:                sc->sc_dev.dv_xname, sc->sc_micro,
                    792:                (tsmsgp->xst2 & TS_SF_EFES ? "enabled" : "disabled"),
                    793:                (ts[ctlr].reg->tssr & TS_OFL ? "offline" : "online"));
                    794:
                    795:        tsinit (sc);            /* must be called once, why not here ? */
                    796: }
                    797:
                    798:
                    799: /*
                    800:  * TSV05/TS05 interrupt routine
                    801:  */
                    802: void
                    803: tsintr(ctlr)
                    804:        int ctlr;
                    805: {
                    806:        register struct ts_softc *sc = ts_cd.cd_devs[ctlr];
                    807:        register struct tsmsg *tsmsgp = &ts[ctlr].msg;
                    808:        register struct tscmd *tscmdp = &ts[ctlr].cmd;
                    809:        volatile struct tsdevice *tsreg = ts[ctlr].reg;
                    810:        struct uba_unit *um = &sc->sc_unit;
                    811:        register struct buf *bp;
                    812:
                    813:        unsigned short sr = tsreg->tssr;        /* save TSSR */
                    814:        unsigned short mh = tsmsgp->hdr;        /* and msg-header */
                    815:                /* clear the message header ??? */
                    816:
                    817:        short ccode = tscmdp->cmdr & TS_CF_CCODE;
                    818:        short cmask = tscmdp->cmdr & TS_CF_CMASK;
                    819:
                    820: #ifdef DEBUG
                    821:        {
                    822:                char bits[64];
                    823:                printf ("TSSR: %s, MSG: %x ", bitmask_snprintf(sr,
                    824:                    TS_TSSR_BITS, bits, sizeof(bits)), mh);
                    825:        }
                    826:        switch (tsmsgp->hdr & 0x001F) {
                    827:        case 16:        printf ("(End)");       break;
                    828:        case 17:        printf ("(Fail)");      break;
                    829:        case 18:        printf ("(Error)");     break;
                    830:        case 19:        printf ("(Attention)"); break;
                    831:        }
                    832: #endif
                    833:
                    834:        trace (("  tsintr (%d, %d, %d, %x)\n", uba, vector, level, ctlr));
                    835:
                    836:        if (tsmsgp->xst0 & TS_SF_VCK)
                    837:                sc->sc_cmdf |= TS_CF_CVC;
                    838:
                    839: #ifdef QBA                             /* copied from uda.c */
                    840:        if(vax_cputype == VAX_78032)
                    841:                splx(sc->sc_ipl);       /* Qbus interrupt protocol is odd */
                    842: #endif
                    843:
                    844:        /*
                    845:         * There are two different things which can (and should) be checked:
                    846:         * the actual (internal) state and the device's result (tssr/msg.hdr)
                    847:         *
                    848:         * For each state there's only one "normal" interrupt. Anything else
                    849:         * has to be checked more intensively. Thus in a first run according
                    850:         * to the internal state the expected interrupt is checked/handled.
                    851:         *
                    852:         * In a second run the remaining (not yet handled) interrupts are
                    853:         * checked according to the drive's result.
                    854:         */
                    855:        switch (sc->sc_state) {
                    856:
                    857:        case ST_INVALID:
                    858:                /*
                    859:                 * Ignore unsolicited interrupts.
                    860:                 */
                    861:                log (LOG_WARNING, "%s: stray intr [%x,%x]\n",
                    862:                        sc->sc_dev.dv_xname, sr, mh);
                    863:                return;
                    864:
                    865:        case ST_SLAVE:
                    866:                /*
                    867:                 * this interrupt was caused by write-charact. command
                    868:                 * issued by tsslave() and indicates the end of the
                    869:                 * initialization phase. Just ignore it ...
                    870:                 */
                    871:                if ((sr & TS_SC) != 0 || (sr & TS_TC) != TS_TC_NORM) {
                    872:                        printf("%s: problem during init [%x,%x]\n",
                    873:                                sc->sc_dev.dv_xname, sr, mh);
                    874:                        /* return here ??? */
                    875:                        /* break and check the error outside switch ??? */
                    876:                        break;
                    877:                }
                    878:                sc->sc_state = ST_RUNNING;
                    879:                return;
                    880:
                    881:
                    882:        case ST_RUNNING:
                    883:                /*
                    884:                 * Here we expect interrupts indicating the end of
                    885:                 * commands or indicating problems.
                    886:                 */
                    887:                /*
                    888:                 * Anything else is handled outside this switch ...
                    889:                 */
                    890:                break;
                    891:
                    892:        case ST_IDLE:
                    893:                break;
                    894:
                    895:
                    896:        default:
                    897:                printf ("%s: unexpected interrupt during state %d [%x,%x]\n",
                    898:                        sc->sc_dev.dv_xname, sc->sc_state, sr, mh);
                    899:                return;
                    900:        }
                    901:
                    902:        /*
                    903:         * now we check the termination class.
                    904:         */
                    905:        switch (sr & TS_TC) {
                    906:
                    907:        case TS_TC_NORM:
                    908:                /*
                    909:                 * Normal termination -- The operation is completed
                    910:                 * witout incident.
                    911:                 */
                    912:                sc->sc_state = ST_IDLE;         /* XXX ??? */
                    913:                sc->sc_state = ST_RUNNING;
                    914:                sc->sc_liowf = (ccode == TS_CC_WRITE);
                    915:                sc->sc_rtc = 0;
                    916:                if ((bp = ts_wtab[ctlr]) != NULL) {
                    917:                        ts_wtab[ctlr] = NULL;   /* pseudo-unlink */
                    918:
                    919:                        if (bp != &ts_cbuf[ctlr]) {     /* no ioctl */
                    920:                                ubarelse((struct uba_softc *)
                    921:                                    sc->sc_dev.dv_parent,
                    922:                                    (int *)&bp->b_ubinfo);
                    923: #if defined(VAX750)
                    924:                                if (vax_cputype == VAX_750 &&
                    925:                                    sc->sc_unit.uu_ubinfo != 0)
                    926:                                        ubarelse((struct uba_softc *)
                    927:                                            sc->sc_dev.dv_parent,
                    928:                                            &sc->sc_unit.uu_ubinfo);
                    929:                                        /* XXX */
                    930: #endif
                    931:                        }
                    932:                        bp->b_resid = tsmsgp->rbpcr;
                    933:                        debug (("tsintr: biodone(NORM) [%d,%d,%d]\n",
                    934:                                bp->b_resid, bp->b_bcount, tsmsgp->rbpcr));
                    935:                        biodone (bp); /* bertram: ioctl ??? */
                    936:                }
                    937:                return;
                    938:
                    939:        case TS_TC_ATTN:
                    940:                /*
                    941:                 * Attention condition -- this code indicates that the
                    942:                 * drive has undergone a status change, such as going
                    943:                 * off-line or coming on-line.
                    944:                 * (Without EAI enabled, no Attention interrupts occur.
                    945:                 * drive status changes are signaled by the VCK flag.)
                    946:                 */
                    947:                return;
                    948:
                    949:        case TS_TC_TSA:
                    950:                /*
                    951:                 * Tape Status Alert -- A status condition is encountered
                    952:                 * that may have significance to the program. Bits of
                    953:                 * interest in the extended status registers include
                    954:                 * TMK, EOT and RLL.
                    955:                 */
                    956:                debug (("Tape Status Alert\n"));
                    957:                tsxstatus (tsmsgp);
                    958:                if (tsmsgp->xst0 & TS_SF_TMK) {
                    959:                        debug (("Tape Mark detected"));
                    960:                }
                    961:                if (tsmsgp->xst0 & TS_SF_EOT) {
                    962:                        debug (("End of Tape"));
                    963:                }
                    964:                break;
                    965:
                    966:        case TS_TC_FR:
                    967:                /*
                    968:                 * Function Reject -- The specified function was not
                    969:                 * initiated. Bits of interest include OFL, VCK, BOT,
                    970:                 * WLE, ILC and ILA.
                    971:                 */
                    972:                debug (("Function reject\n"));
                    973:                tsxstatus (tsmsgp);
                    974:                if (sr & TS_OFL) {
                    975:                        printf ("tape is off-line.\n");
                    976:                        break;
                    977:                }
                    978:                if (tsmsgp->xst0 & TS_SF_VCK) {
                    979:                        printf ("Volume check: repeating command ...\n");
                    980:                        tsexec (ctlr, tscmdp->cmdr);
                    981:                        return;
                    982:                }
                    983:                if (tsmsgp->xst0 & TS_SF_BOT) {
                    984:                        printf ("bottom of tape.\n");
                    985:                }
                    986:                if (tsmsgp->xst0 & TS_SF_WLE) {
                    987:                        printf ("Write Lock Error\n");
                    988:                }
                    989:                break;
                    990:
                    991:        case TS_TC_TPD:
                    992:                /*
                    993:                 * Recoverable Error -- Tape position is a record beyond
                    994:                 * what its position was when the function was initiated.
                    995:                 * Suggested recovery procedure is to log the error and
                    996:                 * issue the appropriate retry command.
                    997:                 */
                    998:                debug (("Tape position down\n"));
                    999:                switch (cmask) {
                   1000:                case TS_CMD_RNF:        /* Read Next (forward) */
                   1001:                        debug (("retry read forward ...\n"));
                   1002:                        sc->sc_rtc = 1;
                   1003:                        tsexec (ctlr, TS_CMD_RPF);
                   1004:                        return;
                   1005:                case TS_CMD_RPR:        /* Read Previous (Reverse) */
                   1006:                        debug (("retry read reverse ...\n"));
                   1007:                        sc->sc_rtc = 1;
                   1008:                        tsexec (ctlr, TS_CMD_RNR);
                   1009:                        return;
                   1010:                case TS_CMD_WD:         /* Write Data (Next) */
                   1011:                        debug (("retry write data ...\n"));
                   1012:                        sc->sc_rtc = 1;
                   1013:                        tsexec (ctlr, TS_CMD_WDR);
                   1014:                        return;
                   1015:                case TS_CMD_WTM:
                   1016:                        debug (("retry write tape mark ...\n"));
                   1017:                        sc->sc_rtc = 1;
                   1018:                        tsexec (ctlr, TS_CMD_WTMR);
                   1019:                        return;
                   1020:                default:
                   1021:                        debug (("TPD in command %x\n", cmask));
                   1022:                }
                   1023:                break;
                   1024:
                   1025:        case TS_TC_TNM:
                   1026:                /*
                   1027:                 * Recoverable Error -- Tape position has not changed.
                   1028:                 * Suggested recovery procedure is to log the error and
                   1029:                 * reissue the original command.
                   1030:                 */
                   1031:                printf ("Tape not moved\n");
                   1032:                if (sc->sc_rtc < 3) {
                   1033:                        sc->sc_rtc++;
                   1034:                        /* bertram: log the error !!! */
                   1035:                        printf ("retrying command %x (%d)\n",
                   1036:                                tscmdp->cmdr, sc->sc_rtc);
                   1037:                        tsexec (ctlr, tscmdp->cmdr);
                   1038:                        return;
                   1039:                }
                   1040:                break;
                   1041:
                   1042:        case TS_TC_TPL:
                   1043:                /*
                   1044:                 * Unrecoverable Error -- Tape position has been lost.
                   1045:                 * No valid recovery procedures exist unless the tape
                   1046:                 * has labels or sequence numbers.
                   1047:                 */
                   1048:                printf ("Tape position lost\n");
                   1049:                break;
                   1050:
                   1051:        case TS_TC_FCE:
                   1052:                /*
                   1053:                 * Fatal subsytem Error -- The subsytem is incapable
                   1054:                 * of properly performing commands, or at least its
                   1055:                 * integrity is seriously questionable. Refer to the
                   1056:                 * fatal class code field in the TSSR register for
                   1057:                 * additional information on the type of fatal error.
                   1058:                 */
                   1059:                printf ("Fatal Controller Error\n");
                   1060:
                   1061:        default:
                   1062:                printf ("%s: error 0x%x, resetting controller\n",
                   1063:                        sc->sc_dev.dv_xname, sr & TS_TC);
                   1064:                tsreset (ctlr);
                   1065:        }
                   1066:
                   1067:        /*
                   1068:         * reset controller ?? call tsinit() ???
                   1069:         */
                   1070:        if ((bp = ts_wtab[ctlr]) != NULL) {
                   1071:                ts_wtab[ctlr] = NULL;           /* pseudo unlink */
                   1072:
                   1073:                if (bp != &ts_cbuf[ctlr])       /* no ioctl */
                   1074:                        ubarelse((struct uba_softc *)sc->sc_dev.dv_parent,
                   1075:                            (int *)&bp->b_ubinfo);
                   1076:
                   1077:                if ((sr & TS_TC) != TS_TC_NORM)
                   1078:                        bp->b_flags |= B_ERROR;
                   1079:
                   1080:                debug (("resid:%d, count:%d, rbpcr:%d\n",
                   1081:                        bp->b_resid, bp->b_bcount, tsmsgp->rbpcr));
                   1082:                bp->b_resid = tsmsgp->rbpcr; /* XXX */
                   1083:                debug (("tsintr: biodone(%x)\n", bp->b_flags));
                   1084:                biodone (bp);
                   1085:        }
                   1086:        if ((sr & TS_TC) > TS_TC_FR)
                   1087:                tsreset (ctlr);
                   1088:
                   1089:        return;
                   1090: }
                   1091:
                   1092:
                   1093: /*
                   1094:  * Open a ts device and set the unit online.  If the controller is not
                   1095:  * in the run state, call init to initialize the ts controller first.
                   1096:  */
                   1097: int
                   1098: tsopen (dev, flag, type, p)
                   1099:        dev_t dev;
                   1100:        int flag, type;
                   1101:        struct proc *p;
                   1102: {
                   1103:        register struct uba_device *ui;
                   1104:        register struct uba_ctlr *um;
                   1105:        register struct ts_softc *sc;
                   1106:        register int unit = TS_UNIT(dev);
                   1107:        int s;
                   1108:
                   1109:        trace (("tsopen (%x, %x)\n", dev, flag));
                   1110:
                   1111:        if (unit >= ts_cd.cd_ndevs)
                   1112:                return ENXIO;
                   1113:
                   1114:        sc = ts_cd.cd_devs[unit];
                   1115:        if (sc == 0)
                   1116:                return ENXIO;
                   1117:
                   1118:        if (sc->sc_openf)
                   1119:                return EBUSY;
                   1120:
                   1121:        sc->sc_openf = 1;
                   1122:
                   1123:        s = splbio ();
                   1124:        if (sc->sc_state < ST_RUNNING) {                /* XXX */
                   1125:                printf ("%s not running.\n", sc->sc_dev.dv_xname);
                   1126:                splx(s);
                   1127:                sc->sc_openf = 0;
                   1128:                return (ENXIO);
                   1129:        }
                   1130:        splx(s);
                   1131:
                   1132:        /*
                   1133:         * check if transport is really online.
                   1134:         * (without attention-interrupts enabled, we really don't know
                   1135:         * the actual state of the transport. Thus we call get-status
                   1136:         * (ie. MTNOP) once and check the actual status.)
                   1137:         */
                   1138:        tscommand (dev, MTNOP, 1);
                   1139:        if (ts[unit].reg->tssr & TS_OFL) {
                   1140:                printf ("%s: transport is offline.\n", sc->sc_dev.dv_xname);
                   1141:                sc->sc_openf = 0;
                   1142:                return EIO;             /* transport is offline */
                   1143:        }
                   1144:
                   1145:        sc->sc_liowf = 0;
                   1146:        return 0;
                   1147: }
                   1148:
                   1149:
                   1150: /*
                   1151:  * Close tape device.
                   1152:  *
                   1153:  * If tape was open for writing or last operation was
                   1154:  * a write, then write two EOF's and backspace over the last one.
                   1155:  * Unless this is a non-rewinding special file, rewind the tape.
                   1156:  *
                   1157:  * Make the tape available to others, by clearing openf flag.
                   1158:  */
                   1159: int
                   1160: tsclose (dev, flag, type, p)
                   1161:        dev_t dev;
                   1162:        int flag, type;
                   1163:        struct proc *p;
                   1164: {
                   1165:        register struct ts_softc *sc = ts_cd.cd_devs[TS_UNIT(dev)];
                   1166:
                   1167:        if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) {
                   1168:                /*
                   1169:                 * We are writing two tape marks (EOT), but place the tape
                   1170:                 * before the second one, so that another write operation
                   1171:                 * will overwrite the second one and leave and EOF-mark.
                   1172:                 */
                   1173:                tscommand (dev, MTWEOF, 1);     /* Write Tape Mark */
                   1174:                tscommand (dev, MTWEOF, 1);     /* Write Tape Mark */
                   1175:                tscommand (dev, MTBSF,  1);     /* Skip Tape Marks Reverse */
                   1176:        }
                   1177:
                   1178:        if ((dev & T_NOREWIND) == 0)
                   1179:                tscommand (dev, MTREW, 0);
                   1180:
                   1181:        sc->sc_openf = 0;
                   1182:        sc->sc_liowf = 0;
                   1183:        return 0;
                   1184: }
                   1185:
                   1186:
                   1187: /*
                   1188:  * Manage buffers and perform block mode read and write operations.
                   1189:  */
                   1190: void
                   1191: tsstrategy (bp)
                   1192:        register struct buf *bp;
                   1193: {
                   1194:        register int unit = TS_UNIT(bp->b_dev);
                   1195:        struct ts_softc *sc = (void *)ts_cd.cd_devs[unit];
                   1196:        int s;
                   1197:
                   1198:        s = splbio ();
                   1199:        /*
                   1200:         * we have only one command at one time, no credits.
                   1201:         * thus we don't need buffer management and controller queue
                   1202:         * just try to execute the command ...
                   1203:         */
                   1204:
                   1205:        tsstart (sc, bp);
                   1206:        splx(s);
                   1207:        return;
                   1208: }
                   1209:
                   1210:
                   1211: /*
                   1212:  * Catch ioctl commands, and call the "command" routine to do them.
                   1213:  */
                   1214: int
                   1215: tsioctl (dev, cmd, data, flag, p)
                   1216:        dev_t dev;
                   1217:        u_long cmd;
                   1218:        caddr_t data;
                   1219:        int flag;
                   1220:        struct proc *p;
                   1221: {
                   1222:        register struct buf *bp = &ts_cbuf[TS_UNIT(dev)];
                   1223:        register struct ts_softc *sc;
                   1224:        register struct mtop *mtop;     /* mag tape cmd op to perform */
                   1225:        register struct mtget *mtget;   /* mag tape struct to get info in */
                   1226:        register callcount;             /* number of times to call routine */
                   1227:        int scount;                     /* number of files/records to space */
                   1228:        int spaceop = 0;                /* flag for skip/space operation */
                   1229:        int error = 0;
                   1230:
                   1231:        trace (("tsioctl (%x, %x, %x, %d)\n", dev, cmd, data, flag));
                   1232:
                   1233:        switch (cmd) {
                   1234:        case MTIOCTOP:                  /* do a mag tape op */
                   1235:                mtop = (struct mtop *)data;
                   1236:                switch (mtop->mt_op) {
                   1237:                case MTWEOF:            /* write an end-of-file record */
                   1238:                        callcount = mtop->mt_count;
                   1239:                        scount = 1;
                   1240:                        break;
                   1241:                case MTFSF:             /* forward space file */
                   1242:                case MTBSF:             /* backward space file */
                   1243:                case MTFSR:             /* forward space record */
                   1244:                case MTBSR:             /* backward space record */
                   1245:                        spaceop = 1;
                   1246:                        callcount = 1;
                   1247:                        scount = mtop->mt_count;
                   1248:                        break;
                   1249:                case MTREW:             /* rewind */
                   1250:                case MTOFFL:            /* rewind and put the drive offline */
                   1251:                case MTNOP:             /* no operation, sets status only */
                   1252:                        callcount = 1;
                   1253:                        scount = 1;             /* wait for this rewind */
                   1254:                        break;
                   1255:                case MTRETEN:           /* retension */
                   1256:                case MTERASE:           /* erase entire tape */
                   1257:                case MTEOM:             /* forward to end of media */
                   1258:                case MTNBSF:            /* backward space to begin of file */
                   1259:                case MTCACHE:           /* enable controller cache */
                   1260:                case MTNOCACHE:         /* disable controller cache */
                   1261:                case MTSETBSIZ:         /* set block size; 0 for variable */
                   1262:                case MTSETDNSTY:        /* set density code for current mode */
                   1263:                        debug (("ioctl %d not implemented.\n", mtop->mt_op));
                   1264:                        return (ENXIO);
                   1265:                default:
                   1266:                        debug (("invalid ioctl %d\n", mtop->mt_op));
                   1267:                        return (ENXIO);
                   1268:                }       /* switch (mtop->mt_op) */
                   1269:
                   1270:                if (callcount <= 0 || scount <= 0) {
                   1271:                        debug (("invalid values %d/%d\n", callcount, scount));
                   1272:                        return (EINVAL);
                   1273:                }
                   1274:                do {
                   1275:                        tscommand (dev, mtop->mt_op, scount);
                   1276:                        if (spaceop && bp->b_resid) {
                   1277:                                debug (("spaceop didn't complete\n"));
                   1278:                                return (EIO);
                   1279:                        }
                   1280:                        if (bp->b_flags & B_ERROR) {
                   1281:                                debug (("error in ioctl %d\n", mtop->mt_op));
                   1282:                                break;
                   1283:                        }
                   1284:                } while (--callcount > 0);
                   1285:                if (bp->b_flags & B_ERROR)
                   1286:                        if ((error = bp->b_error) == 0)
                   1287:                                return (EIO);
                   1288:                return (error);
                   1289:
                   1290:        case MTIOCGET:                  /* get tape status */
                   1291:                sc = ts_cd.cd_devs[TS_UNIT(dev)];
                   1292:                mtget = (struct mtget *)data;
                   1293:                mtget->mt_type = MT_ISTS;
                   1294:                mtget->mt_dsreg = (unsigned)(ts[TS_UNIT(dev)].reg->tssr);
                   1295:                mtget->mt_erreg = (unsigned)(ts[TS_UNIT(dev)].msg.hdr);
                   1296:                mtget->mt_resid = 0;            /* ??? */
                   1297:                mtget->mt_density = 0;          /* ??? */
                   1298:                break;
                   1299:
                   1300:        case MTIOCIEOT:                 /* ignore EOT error */
                   1301:                debug (("MTIOCIEOT not implemented.\n"));
                   1302:                return (ENXIO);
                   1303:
                   1304:        case MTIOCEEOT:                 /* enable EOT error */
                   1305:                debug (("MTIOCEEOT not implemented.\n"));
                   1306:                return (ENXIO);
                   1307:
                   1308:        default:
                   1309:                debug (("invalid ioctl cmd 0x%x\n", cmd));
                   1310:                return (ENXIO);
                   1311:        }
                   1312:
                   1313:        return (0);
                   1314: }
                   1315:
                   1316:
                   1317: /*
                   1318:  *
                   1319:  */
                   1320: int
                   1321: tsread (dev, uio)
                   1322:        dev_t dev;
                   1323:        struct uio *uio;
                   1324: {
                   1325:        return (physio (tsstrategy, NULL, dev, B_READ, minphys, uio));
                   1326: }
                   1327:
                   1328: /*
                   1329:  *
                   1330:  */
                   1331: int
                   1332: tswrite (dev, uio)
                   1333:        dev_t dev;
                   1334:        struct uio *uio;
                   1335: {
                   1336:        return (physio (tsstrategy, NULL, dev, B_WRITE, minphys, uio));
                   1337: }
                   1338:
                   1339: /*
                   1340:  *
                   1341:  */
                   1342: int
                   1343: tsdump(dev, blkno, va, size)
                   1344:        dev_t dev;
                   1345:        daddr64_t blkno;
                   1346:        caddr_t va;
                   1347:        size_t size;
                   1348: {
                   1349:        trace (("tsdump (%x)\n", dev));
                   1350:        return 0;
                   1351: }
                   1352:
                   1353: /*----------------------------------------------------------------------*/
                   1354:
                   1355: int
                   1356: tsstatus (sr)
                   1357:        int sr;
                   1358: {
                   1359: #ifdef DEBUG
                   1360:        char bits[64];
                   1361:
                   1362:        debug (("status: TSSR=%s\n", bitmask_snprintf(sr, TS_TSSR_BITS,
                   1363:            bits, sizeof(bits))));
                   1364:
                   1365:        if (tsdebug < 5)
                   1366:                return (0);
                   1367:
                   1368:        if (sr & TS_SC)         printf ("special condition\n");
                   1369:        if (sr & TS_UPE)        printf ("UPE\n");
                   1370:        if (sr & TS_SCE)        printf ("Sanity Check Error\n");
                   1371:        if (sr & TS_RMR)        printf ("Register Modification Refused\n");
                   1372:        if (sr & TS_NXM)        printf ("Nonexistent Memory\n");
                   1373:        if (sr & TS_NBA)        printf ("Need Buffer Address\n");
                   1374:        if (sr & TS_A11)        printf ("Address Bits 17-16\n");
                   1375:        if (sr & TS_SSR)        printf ("Subsystem Ready\n");
                   1376:        if (sr & TS_OFL)        printf ("Off Line\n");
                   1377:        if (sr & TS_FTC)        printf ("Fatal Termination Class Code\n");
                   1378:        switch (sr & TS_TC) {
                   1379:        case TS_TC_NORM:        printf ("Normal Termination\n"); break;
                   1380:        case TS_TC_ATTN:        printf ("Attention Condition\n"); break;
                   1381:        case TS_TC_TSA:         printf ("Tape status \n"); break;
                   1382:        case TS_TC_FR:          printf ("Function reject\n"); break;
                   1383:        case TS_TC_TPD:         printf ("Tape position down\n"); break;
                   1384:        case TS_TC_TNM:         printf ("Tape not moved\n"); break;
                   1385:        case TS_TC_TPL:         printf ("Tape position lost\n"); break;
                   1386:        case TS_TC_FCE:         printf ("Fatal Controller Error\n"); break;
                   1387:        }
                   1388: #endif
                   1389:        return (0);
                   1390: }
                   1391:
                   1392: void
                   1393: tsxstatus (mp)
                   1394:        struct tsmsg *mp;
                   1395: {
                   1396: #ifdef DEBUG
                   1397:        char bits[64];
                   1398:
                   1399:        debug (("tsxstatus: xst0=%s, ", bitmask_snprintf(mp->xst0,
                   1400:            TS_XST0_BITS, bits, sizeof(bits))));
                   1401:        debug (("xst1=%s, ", bitmask_snprintf(mp->xst1, TS_XST1_BITS,
                   1402:            bits, sizeof(bits))));
                   1403:        debug (("xst2=%s, ", bitmask_snprintf(mp->xst2, TS_XST2_BITS,
                   1404:            bits, sizeof(bits))));
                   1405:        debug (("xst3=%s, ", bitmask_snprintf(mp->xst3, TS_XST3_BITS,
                   1406:            bits, sizeof(bits))));
                   1407:        debug (("xst4=%s\n", bitmask_snprintf(mp->xst4, "\20",
                   1408:            bits, sizeof(bits))));
                   1409:
                   1410:        if (tsdebug < 10)
                   1411:                return (0);
                   1412:
                   1413:        if (mp->xst0 & TS_SF_TMK)       printf ("Tape Mark Detected\n");
                   1414:        if (mp->xst0 & TS_SF_RLS)       printf ("Record Length Short\n");
                   1415:        if (mp->xst0 & TS_SF_LET)       printf ("Logical End of Tape\n");
                   1416:        if (mp->xst0 & TS_SF_RLL)       printf ("Record Length Long\n");
                   1417:        if (mp->xst0 & TS_SF_WLE)       printf ("Write Lock Error\n");
                   1418:        if (mp->xst0 & TS_SF_NEF)       printf ("Nonexecutable Function\n");
                   1419:        if (mp->xst0 & TS_SF_ILC)       printf ("Illegal Command\n");
                   1420:        if (mp->xst0 & TS_SF_ILA)       printf ("Illegal Address\n");
                   1421:        if (mp->xst0 & TS_SF_MOT)       printf ("Motion\n");
                   1422:        if (mp->xst0 & TS_SF_ONL)       printf ("On-Line\n");
                   1423:        if (mp->xst0 & TS_SF_IE)        printf ("Interrupt Enable\n");
                   1424:        if (mp->xst0 & TS_SF_VCK)       printf ("Volume Check\n");
                   1425:        if (mp->xst0 & TS_SF_PED)       printf ("Phase Encoded Drive\n");
                   1426:        if (mp->xst0 & TS_SF_WLK)       printf ("Write Locked\n");
                   1427:        if (mp->xst0 & TS_SF_BOT)       printf ("Beginning of Tape\n");
                   1428:        if (mp->xst0 & TS_SF_EOT)       printf ("End of Tape\n");
                   1429:
                   1430:        if (mp->xst1 & TS_SF_DLT)       printf ("Data Late\n");
                   1431:        if (mp->xst1 & TS_SF_COR)       printf ("Correctable Data\n");
                   1432:        if (mp->xst1 & TS_SF_RBP)       printf ("Read Bus Parity Error\n");
                   1433:        if (mp->xst1 & TS_SF_UNC)       printf ("Uncorrectable Data or Hard Error\n");
                   1434:
                   1435:        if (mp->xst2 & TS_SF_OPM)       printf ("Operation in Progress\n");
                   1436:        if (mp->xst2 & TS_SF_RCE)       printf ("RAM Checksum Error\n");
                   1437:        if (mp->xst2 & TS_SF_WCF)       printf ("Write Clock Failure\n");
                   1438:        if (mp->xst2 & TS_SF_EFES)      printf ("extended features enabled\n");
                   1439:        if (mp->xst2 & TS_SF_BES)       printf ("Buffering enabled\n");
                   1440:
                   1441:        printf ("micro-code revision level: %d\n", (mp->xst2 & TS_SF_MCRL)>>2);
                   1442:        printf ("unit number: %d\n", (mp->xst2 & TS_SF_UNIT));
                   1443:
                   1444:        if (mp->xst3 & TS_SF_MDE)
                   1445:                printf ("Micro-Diagnostics Error Code: 0x%x\n", mp->xst3 >> 8);
                   1446:        if (mp->xst3 & TS_SF_OPI)       printf ("Operation Incomplete\n");
                   1447:        if (mp->xst3 & TS_SF_REV)       printf ("Revers\n");
                   1448:        if (mp->xst3 & TS_SF_DCK)       printf ("Density Check\n");
                   1449:        if (mp->xst3 & TS_SF_RIB)       printf ("Reverse into BOT\n");
                   1450:
                   1451:        if (mp->xst4 & TS_SF_HSP)       printf ("High Speed\n");
                   1452:        if (mp->xst4 & TS_SF_RCX)       printf ("Retry Count Exceeded\n");
                   1453: #endif
                   1454: }

CVSweb