[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     ! 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