The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/gpib/mt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: mt.c,v 1.2 2003/08/07 16:30:56 agc Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1996-2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 1982, 1990, 1993
   41  *      The Regents of the University of California.  All rights reserved.
   42  *
   43  * This code is derived from software contributed to Berkeley by
   44  * the Systems Programming Group of the University of Utah Computer
   45  * Science Department.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  * 3. Neither the name of the University nor the names of its contributors
   56  *    may be used to endorse or promote products derived from this software
   57  *    without specific prior written permission.
   58  *
   59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   69  * SUCH DAMAGE.
   70  *
   71  * from: Utah $Hdr: rd.c 1.44 92/12/26$
   72  *
   73  *      @(#)rd.c        8.2 (Berkeley) 5/19/94
   74  */
   75 
   76 /*
   77  * Copyright (c) 1988 University of Utah.
   78  *
   79  * This code is derived from software contributed to Berkeley by
   80  * the Systems Programming Group of the University of Utah Computer
   81  * Science Department.
   82  *
   83  * Redistribution and use in source and binary forms, with or without
   84  * modification, are permitted provided that the following conditions
   85  * are met:
   86  * 1. Redistributions of source code must retain the above copyright
   87  *    notice, this list of conditions and the following disclaimer.
   88  * 2. Redistributions in binary form must reproduce the above copyright
   89  *    notice, this list of conditions and the following disclaimer in the
   90  *    documentation and/or other materials provided with the distribution.
   91  * 3. All advertising materials mentioning features or use of this software
   92  *    must display the following acknowledgement:
   93  *      This product includes software developed by the University of
   94  *      California, Berkeley and its contributors.
   95  * 4. Neither the name of the University nor the names of its contributors
   96  *    may be used to endorse or promote products derived from this software
   97  *    without specific prior written permission.
   98  *
   99  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  100  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  101  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  102  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  103  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  104  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  105  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  106  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  107  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  108  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  109  * SUCH DAMAGE.
  110  *
  111  * from: Utah $Hdr: rd.c 1.44 92/12/26$
  112  *
  113  *      @(#)rd.c        8.2 (Berkeley) 5/19/94
  114  */
  115 
  116 /*
  117  * Magnetic tape driver (HP7974a, HP7978a/b, HP7979a, HP7980a, HP7980xc)
  118  * Original version contributed by Mt. Xinu.
  119  * Modified for 4.4BSD by Mark Davies and Andrew Vignaux, Department of
  120  * Computer Science, Victoria University of Wellington
  121  */
  122 
  123 #include <sys/cdefs.h>
  124 __KERNEL_RCSID(0, "$NetBSD: mt.c,v 1.2 2003/08/07 16:30:56 agc Exp $");
  125 
  126 #include <sys/param.h>
  127 #include <sys/systm.h>
  128 #include <sys/callout.h>
  129 #include <sys/buf.h>
  130 #include <sys/ioctl.h>
  131 #include <sys/mtio.h>
  132 #include <sys/file.h>
  133 #include <sys/proc.h>
  134 #include <sys/tty.h>
  135 #include <sys/kernel.h>
  136 #include <sys/tprintf.h>
  137 #include <sys/device.h>
  138 #include <sys/conf.h>
  139 
  140 #include <dev/gpib/gpibvar.h>
  141 #include <dev/gpib/cs80busvar.h>
  142 
  143 #include <dev/gpib/mtreg.h>
  144 
  145 #ifdef DEBUG
  146 int     mtdebug = 0;
  147 #define MDB_ANY         0xff
  148 #define MDB_FOLLOW      0x01
  149 #define DPRINTF(mask, str)      if (mtdebug & (mask)) printf str
  150 #else
  151 #define DPRINTF(mask, str)      /* nothing */
  152 #endif
  153 
  154 struct  mt_softc {
  155         struct  device sc_dev;
  156 
  157         gpib_chipset_tag_t sc_ic;
  158         gpib_handle_t sc_hdl;
  159 
  160         int     sc_slave;       /* GPIB slave address (0-6) */
  161         short   sc_flags;       /* see below */
  162         u_char  sc_lastdsj;     /* place for DSJ in mtreaddsj() */
  163         u_char  sc_lastecmd;    /* place for End Command in mtreaddsj() */
  164         short   sc_recvtimeo;   /* count of gpibsend timeouts to prevent hang */
  165         short   sc_statindex;   /* index for next sc_stat when MTF_STATTIMEO */
  166         struct  mt_stat sc_stat;/* status bytes last read from device */
  167         short   sc_density;     /* current density of tape (mtio.h format) */
  168         short   sc_type;        /* tape drive model (hardware IDs) */
  169         tpr_t   sc_ttyp;
  170         struct bufq_state sc_tab;/* buf queue */
  171         int     sc_active;
  172         struct buf sc_bufstore; /* XXX buffer storage */
  173 
  174         struct  callout sc_start_ch;
  175         struct  callout sc_intr_ch;
  176 };
  177 
  178 #define MTUNIT(x)       (minor(x) & 0x03)
  179 
  180 #define B_CMD           B_XXX           /* command buf instead of data */
  181 #define b_cmd           b_blkno         /* blkno holds cmd when B_CMD */
  182 
  183 int     mtmatch(struct device *, struct cfdata *, void *);
  184 void    mtattach(struct device *, struct device *, void *);
  185 
  186 CFATTACH_DECL(mt, sizeof(struct mt_softc),
  187         mtmatch, mtattach, NULL, NULL);
  188 
  189 int     mtlookup(int, int, int);
  190 void    mtustart(struct mt_softc *);
  191 int     mtreaddsj(struct mt_softc *, int);
  192 int     mtcommand(dev_t, int, int);
  193 
  194 void    mtintr_callout(void *);
  195 void    mtstart_callout(void *);
  196 
  197 void    mtcallback(void *, int);
  198 void    mtstart(struct mt_softc *);
  199 void    mtintr(struct mt_softc  *);
  200 
  201 dev_type_open(mtopen);
  202 dev_type_close(mtclose);
  203 dev_type_read(mtread);
  204 dev_type_write(mtwrite);
  205 dev_type_ioctl(mtioctl);
  206 dev_type_strategy(mtstrategy);
  207 
  208 const struct bdevsw mt_bdevsw = {
  209         mtopen, mtclose, mtstrategy, mtioctl, nodump, nosize, D_TAPE
  210 };
  211 
  212 const struct cdevsw mt_cdevsw = {
  213         mtopen, mtclose, mtread, mtwrite, mtioctl,
  214         nostop, notty, nopoll, nommap, nokqfilter, D_TAPE
  215 };
  216 
  217 
  218 extern struct cfdriver mt_cd;
  219 
  220 struct  mtinfo {
  221         u_short hwid;
  222         char    *desc;
  223 } mtinfo[] = {
  224         { MT7978ID,     "7978"  },
  225         { MT7979AID,    "7979A" },
  226         { MT7980ID,     "7980"  },
  227         { MT7974AID,    "7974A" },
  228 };
  229 int     nmtinfo = sizeof(mtinfo) / sizeof(mtinfo[0]);
  230 
  231 
  232 int
  233 mtlookup(id, slave, punit)
  234         int id;
  235         int slave;
  236         int punit;
  237 {
  238         int i;
  239 
  240         for (i = 0; i < nmtinfo; i++)
  241                 if (mtinfo[i].hwid == id)
  242                         break;
  243         if (i == nmtinfo)
  244                 return (-1);
  245         return (0);
  246 }
  247 
  248 int
  249 mtmatch(parent, match, aux)
  250         struct device *parent;
  251         struct cfdata *match;
  252         void *aux;
  253 {
  254         struct cs80bus_attach_args *ca = aux;
  255 
  256         ca->ca_punit = 0;
  257         return (mtlookup(ca->ca_id, ca->ca_slave, ca->ca_punit) == 0);
  258 }
  259 
  260 void
  261 mtattach(parent, self, aux)
  262         struct device *parent, *self;
  263         void *aux;
  264 {
  265         struct mt_softc *sc = (struct mt_softc *)self;
  266         struct cs80bus_attach_args *ca = aux;
  267         int type;
  268 
  269         sc->sc_ic = ca->ca_ic;
  270         sc->sc_slave = ca->ca_slave;
  271 
  272         if ((type = mtlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0)
  273                 return;
  274 
  275         printf(": %s tape\n", mtinfo[type].desc);
  276 
  277         sc->sc_type = type;
  278         sc->sc_flags = MTF_EXISTS;
  279 
  280         bufq_alloc(&sc->sc_tab, BUFQ_FCFS);
  281         callout_init(&sc->sc_start_ch);
  282         callout_init(&sc->sc_intr_ch);
  283 
  284         if (gpibregister(sc->sc_ic, sc->sc_slave, mtcallback, sc,
  285             &sc->sc_hdl)) {
  286                 printf("%s: can't register callback\n", sc->sc_dev.dv_xname);
  287                 return;
  288         }
  289 }
  290 
  291 /*
  292  * Perform a read of "Device Status Jump" register and update the
  293  * status if necessary.  If status is read, the given "ecmd" is also
  294  * performed, unless "ecmd" is zero.  Returns DSJ value, -1 on failure
  295  * and -2 on "temporary" failure.
  296  */
  297 int
  298 mtreaddsj(sc, ecmd)
  299         struct mt_softc *sc;
  300         int ecmd;
  301 {
  302         int retval;
  303 
  304         if (sc->sc_flags & MTF_STATTIMEO)
  305                 goto getstats;
  306         retval = gpibrecv(sc->sc_ic,
  307             (sc->sc_flags & MTF_DSJTIMEO) ? -1 : sc->sc_slave,
  308             MTT_DSJ, &(sc->sc_lastdsj), 1);
  309         sc->sc_flags &= ~MTF_DSJTIMEO;
  310         if (retval != 1) {
  311                 DPRINTF(MDB_ANY, ("%s can't gpibrecv DSJ",
  312                     sc->sc_dev.dv_xname));
  313                 if (sc->sc_recvtimeo == 0)
  314                         sc->sc_recvtimeo = hz;
  315                 if (--sc->sc_recvtimeo == 0)
  316                         return (-1);
  317                 if (retval == 0)
  318                         sc->sc_flags |= MTF_DSJTIMEO;
  319                 return (-2);
  320         }
  321         sc->sc_recvtimeo = 0;
  322         sc->sc_statindex = 0;
  323         DPRINTF(MDB_ANY, ("%s readdsj: 0x%x", sc->sc_dev.dv_xname,
  324             sc->sc_lastdsj));
  325         sc->sc_lastecmd = ecmd;
  326         switch (sc->sc_lastdsj) {
  327             case 0:
  328                 if (ecmd & MTE_DSJ_FORCE)
  329                         break;
  330                 return (0);
  331 
  332             case 2:
  333                 sc->sc_lastecmd = MTE_COMPLETE;
  334             case 1:
  335                 break;
  336 
  337             default:
  338                 printf("%s readdsj: DSJ 0x%x\n", sc->sc_dev.dv_xname,
  339                     sc->sc_lastdsj);
  340                 return (-1);
  341         }
  342 
  343 getstats:
  344         retval = gpibrecv(sc->sc_ic,
  345             (sc->sc_flags & MTF_STATCONT) ? -1 : sc->sc_slave, MTT_STAT,
  346              ((char *)&(sc->sc_stat)) + sc->sc_statindex,
  347             sizeof(sc->sc_stat) - sc->sc_statindex);
  348         sc->sc_flags &= ~(MTF_STATTIMEO | MTF_STATCONT);
  349         if (retval != sizeof(sc->sc_stat) - sc->sc_statindex) {
  350                 if (sc->sc_recvtimeo == 0)
  351                         sc->sc_recvtimeo = hz;
  352                 if (--sc->sc_recvtimeo != 0) {
  353                         if (retval >= 0) {
  354                                 sc->sc_statindex += retval;
  355                                 sc->sc_flags |= MTF_STATCONT;
  356                         }
  357                         sc->sc_flags |= MTF_STATTIMEO;
  358                         return (-2);
  359                 }
  360                 printf("%s readdsj: can't read status", sc->sc_dev.dv_xname);
  361                 return (-1);
  362         }
  363         sc->sc_recvtimeo = 0;
  364         sc->sc_statindex = 0;
  365         DPRINTF(MDB_ANY, ("%s readdsj: status is %x %x %x %x %x %x",
  366             sc->sc_dev.dv_xname,
  367             sc->sc_stat1, sc->sc_stat2, sc->sc_stat3,
  368             sc->sc_stat4, sc->sc_stat5, sc->sc_stat6));
  369         if (sc->sc_lastecmd)
  370                 (void) gpibsend(sc->sc_ic, sc->sc_slave,
  371                     MTL_ECMD, &(sc->sc_lastecmd), 1);
  372         return ((int) sc->sc_lastdsj);
  373 }
  374 
  375 int
  376 mtopen(dev, flag, mode, p)
  377         dev_t dev;
  378         int flag, mode;
  379         struct proc *p;
  380 {
  381         struct mt_softc *sc;
  382         int req_den;
  383         int error;
  384 
  385         sc = device_lookup(&mt_cd, MTUNIT(dev));
  386         if (sc == NULL || (sc->sc_flags & MTF_EXISTS) == 0)
  387                 return (ENXIO);
  388 
  389         if (sc->sc_flags & MTF_OPEN)
  390                 return (EBUSY);
  391 
  392         DPRINTF(MDB_ANY, ("%s open: flags 0x%x", sc->sc_dev.dv_xname,
  393             sc->sc_flags));
  394 
  395         sc->sc_flags |= MTF_OPEN;
  396         sc->sc_ttyp = tprintf_open(p);
  397         if ((sc->sc_flags & MTF_ALIVE) == 0) {
  398                 error = mtcommand(dev, MTRESET, 0);
  399                 if (error != 0 || (sc->sc_flags & MTF_ALIVE) == 0)
  400                         goto errout;
  401                 if ((sc->sc_stat1 & (SR1_BOT | SR1_ONLINE)) == SR1_ONLINE)
  402                         (void) mtcommand(dev, MTREW, 0);
  403         }
  404         for (;;) {
  405                 if ((error = mtcommand(dev, MTNOP, 0)) != 0)
  406                         goto errout;
  407                 if (!(sc->sc_flags & MTF_REW))
  408                         break;
  409                 if (tsleep((caddr_t) &lbolt, PCATCH | (PZERO + 1),
  410                     "mt", 0) != 0) {
  411                         error = EINTR;
  412                         goto errout;
  413                 }
  414         }
  415         if ((flag & FWRITE) && (sc->sc_stat1 & SR1_RO)) {
  416                 error = EROFS;
  417                 goto errout;
  418         }
  419         if (!(sc->sc_stat1 & SR1_ONLINE)) {
  420                 uprintf("%s: not online\n", sc->sc_dev.dv_xname);
  421                 error = EIO;
  422                 goto errout;
  423         }
  424         /*
  425          * Select density:
  426          *  - find out what density the drive is set to
  427          *      (i.e. the density of the current tape)
  428          *  - if we are going to write
  429          *    - if we're not at the beginning of the tape
  430          *      - complain if we want to change densities
  431          *    - otherwise, select the mtcommand to set the density
  432          *
  433          * If the drive doesn't support it then don't change the recorded
  434          * density.
  435          *
  436          * The original MOREbsd code had these additional conditions
  437          * for the mid-tape change
  438          *
  439          *      req_den != T_BADBPI &&
  440          *      sc->sc_density != T_6250BPI
  441          *
  442          * which suggests that it would be possible to write multiple
  443          * densities if req_den == T_BAD_BPI or the current tape
  444          * density was 6250.  Testing of our 7980 suggests that the
  445          * device cannot change densities mid-tape.
  446          *
  447          * ajv@comp.vuw.ac.nz
  448          */
  449         sc->sc_density = (sc->sc_stat2 & SR2_6250) ? T_6250BPI : (
  450                          (sc->sc_stat3 & SR3_1600) ? T_1600BPI : (
  451                          (sc->sc_stat3 & SR3_800) ? T_800BPI : -1));
  452         req_den = (dev & T_DENSEL);
  453 
  454         if (flag & FWRITE) {
  455                 if (!(sc->sc_stat1 & SR1_BOT)) {
  456                         if (sc->sc_density != req_den) {
  457                                 uprintf("%s: can't change density mid-tape\n",
  458                                     sc->sc_dev.dv_xname);
  459                                 error = EIO;
  460                                 goto errout;
  461                         }
  462                 }
  463                 else {
  464                         int mtset_density =
  465                             (req_den == T_800BPI  ? MTSET800BPI : (
  466                              req_den == T_1600BPI ? MTSET1600BPI : (
  467                              req_den == T_6250BPI ? MTSET6250BPI : (
  468                              sc->sc_type == MT7980ID
  469                                                   ? MTSET6250DC
  470                                                   : MTSET6250BPI))));
  471                         if (mtcommand(dev, mtset_density, 0) == 0)
  472                                 sc->sc_density = req_den;
  473                 }
  474         }
  475         return (0);
  476 errout:
  477         sc->sc_flags &= ~MTF_OPEN;
  478         return (error);
  479 }
  480 
  481 int
  482 mtclose(dev, flag, fmt, p)
  483         dev_t dev;
  484         int flag, fmt;
  485         struct proc *p;
  486 {
  487         struct mt_softc *sc;
  488 
  489         sc = device_lookup(&mt_cd, MTUNIT(dev));
  490         if (sc == NULL)
  491                 return (ENXIO);
  492 
  493         if (sc->sc_flags & MTF_WRT) {
  494                 (void) mtcommand(dev, MTWEOF, 2);
  495                 (void) mtcommand(dev, MTBSF, 0);
  496         }
  497         if ((minor(dev) & T_NOREWIND) == 0)
  498                 (void) mtcommand(dev, MTREW, 0);
  499         sc->sc_flags &= ~MTF_OPEN;
  500         tprintf_close(sc->sc_ttyp);
  501         return (0);
  502 }
  503 
  504 int
  505 mtcommand(dev, cmd, cnt)
  506         dev_t dev;
  507         int cmd;
  508         int cnt;
  509 {
  510         struct mt_softc *sc;
  511         struct buf *bp;
  512         int error = 0;
  513 
  514         sc = device_lookup(&mt_cd, MTUNIT(dev));
  515         bp = &sc->sc_bufstore;
  516 
  517         if (bp->b_flags & B_BUSY)
  518                 return (EBUSY);
  519 
  520         bp->b_cmd = cmd;
  521         bp->b_dev = dev;
  522         do {
  523                 bp->b_flags = B_BUSY | B_CMD;
  524                 mtstrategy(bp);
  525                 biowait(bp);
  526                 if (bp->b_flags & B_ERROR) {
  527                         error = (int) (unsigned) bp->b_error;
  528                         break;
  529                 }
  530         } while (--cnt > 0);
  531 #if 0
  532         bp->b_flags = 0 /*&= ~B_BUSY*/;
  533 #else
  534         bp->b_flags &= ~B_BUSY;
  535 #endif
  536         return (error);
  537 }
  538 
  539 /*
  540  * Only thing to check here is for legal record lengths (writes only).
  541  */
  542 void
  543 mtstrategy(bp)
  544         struct buf *bp;
  545 {
  546         struct mt_softc *sc;
  547         int s;
  548 
  549         sc = device_lookup(&mt_cd, MTUNIT(bp->b_dev));
  550 
  551         DPRINTF(MDB_ANY, ("%s strategy", sc->sc_dev.dv_xname));
  552 
  553         if ((bp->b_flags & (B_CMD | B_READ)) == 0) {
  554 #define WRITE_BITS_IGNORED      8
  555 #if 0
  556                 if (bp->b_bcount & ((1 << WRITE_BITS_IGNORED) - 1)) {
  557                         tprintf(sc->sc_ttyp,
  558                                 "%s: write record must be multiple of %d\n",
  559                                 sc->sc_dev.dv_xname, 1 << WRITE_BITS_IGNORED);
  560                         goto error;
  561                 }
  562 #endif
  563                 s = 16 * 1024;
  564                 if (sc->sc_stat2 & SR2_LONGREC) {
  565                         switch (sc->sc_density) {
  566                             case T_1600BPI:
  567                                 s = 32 * 1024;
  568                                 break;
  569 
  570                             case T_6250BPI:
  571                             case T_BADBPI:
  572                                 s = 60 * 1024;
  573                                 break;
  574                         }
  575                 }
  576                 if (bp->b_bcount > s) {
  577                         tprintf(sc->sc_ttyp,
  578                                 "%s: write record (%ld) too big: limit (%d)\n",
  579                                 sc->sc_dev.dv_xname, bp->b_bcount, s);
  580 #if 0 /* XXX see above */
  581             error:
  582 #endif
  583                         bp->b_flags |= B_ERROR;
  584                         bp->b_error = EIO;
  585                         biodone(bp);
  586                         return;
  587                 }
  588         }
  589         s = splbio();
  590         BUFQ_PUT(&sc->sc_tab, bp);
  591         if (sc->sc_active == 0) {
  592                 sc->sc_active = 1;
  593                 mtustart(sc);
  594         }
  595         splx(s);
  596 }
  597 
  598 void
  599 mtustart(sc)
  600         struct mt_softc *sc;
  601 {
  602 
  603         DPRINTF(MDB_ANY, ("%s ustart", sc->sc_dev.dv_xname));
  604         if (gpibrequest(sc->sc_ic, sc->sc_hdl))
  605                 mtstart(sc);
  606 }
  607 
  608 void
  609 mtcallback(v, action)
  610         void *v;
  611         int action;
  612 {
  613         struct mt_softc *sc = v;
  614 
  615         DPRINTF(MDB_FOLLOW, ("mtcallback: v=%p, action=%d\n", v, action));
  616 
  617         switch (action) {
  618         case GPIBCBF_START:
  619                 mtstart(sc);
  620                 break;
  621         case GPIBCBF_INTR:
  622                 mtintr(sc);
  623                 break;
  624 #ifdef DEBUG
  625         default:
  626                 printf("mtcallback: unknown action %d\n", action);
  627                 break;
  628 #endif
  629         }
  630 }
  631 
  632 void
  633 mtintr_callout(arg)
  634         void *arg;
  635 {
  636         struct mt_softc *sc = arg;
  637         int s = splbio();
  638 
  639         gpibppclear(sc->sc_ic);
  640         mtintr(sc);
  641         splx(s);
  642 }
  643 
  644 void
  645 mtstart_callout(arg)
  646         void *arg;
  647 {
  648         int s = splbio();
  649 
  650         mtstart((struct mt_softc *)arg);
  651         splx(s);
  652 }
  653 
  654 void
  655 mtstart(sc)
  656         struct mt_softc *sc;
  657 {
  658         struct buf *bp;
  659         short   cmdcount = 1;
  660         u_char  cmdbuf[2];
  661 
  662         DPRINTF(MDB_ANY, ("%s start", sc->sc_dev.dv_xname));
  663         sc->sc_flags &= ~MTF_WRT;
  664         bp = BUFQ_PEEK(&sc->sc_tab);
  665         if ((sc->sc_flags & MTF_ALIVE) == 0 &&
  666             ((bp->b_flags & B_CMD) == 0 || bp->b_cmd != MTRESET))
  667                 goto fatalerror;
  668 
  669         if (sc->sc_flags & MTF_REW) {
  670                 if (!gpibpptest(sc->sc_ic, sc->sc_slave))
  671                         goto stillrew;
  672                 switch (mtreaddsj(sc, MTE_DSJ_FORCE|MTE_COMPLETE|MTE_IDLE)) {
  673                     case 0:
  674                     case 1:
  675                 stillrew:
  676                         if ((sc->sc_stat1 & SR1_BOT) ||
  677                             !(sc->sc_stat1 & SR1_ONLINE)) {
  678                                 sc->sc_flags &= ~MTF_REW;
  679                                 break;
  680                         }
  681                     case -2:
  682                         /*
  683                          * -2 means "timeout" reading DSJ, which is probably
  684                          * temporary.  This is considered OK when doing a NOP,
  685                          * but not otherwise.
  686                          */
  687                         if (sc->sc_flags & (MTF_DSJTIMEO | MTF_STATTIMEO)) {
  688                                 callout_reset(&sc->sc_start_ch, hz >> 5,
  689                                     mtstart_callout, sc);
  690                                 return;
  691                         }
  692                     case 2:
  693                         if (bp->b_cmd != MTNOP || !(bp->b_flags & B_CMD)) {
  694                                 bp->b_error = EBUSY;
  695                                 goto errdone;
  696                         }
  697                         goto done;
  698 
  699                     default:
  700                         goto fatalerror;
  701                 }
  702         }
  703         if (bp->b_flags & B_CMD) {
  704                 if (sc->sc_flags & MTF_PASTEOT) {
  705                         switch(bp->b_cmd) {
  706                             case MTFSF:
  707                             case MTWEOF:
  708                             case MTFSR:
  709                                 bp->b_error = ENOSPC;
  710                                 goto errdone;
  711 
  712                             case MTBSF:
  713                             case MTOFFL:
  714                             case MTBSR:
  715                             case MTREW:
  716                                 sc->sc_flags &= ~(MTF_PASTEOT | MTF_ATEOT);
  717                                 break;
  718                         }
  719                 }
  720                 switch(bp->b_cmd) {
  721                     case MTFSF:
  722                         if (sc->sc_flags & MTF_HITEOF)
  723                                 goto done;
  724                         cmdbuf[0] = MTTC_FSF;
  725                         break;
  726 
  727                     case MTBSF:
  728                         if (sc->sc_flags & MTF_HITBOF)
  729                                 goto done;
  730                         cmdbuf[0] = MTTC_BSF;
  731                         break;
  732 
  733                     case MTOFFL:
  734                         sc->sc_flags |= MTF_REW;
  735                         cmdbuf[0] = MTTC_REWOFF;
  736                         break;
  737 
  738                     case MTWEOF:
  739                         cmdbuf[0] = MTTC_WFM;
  740                         break;
  741 
  742                     case MTBSR:
  743                         cmdbuf[0] = MTTC_BSR;
  744                         break;
  745 
  746                     case MTFSR:
  747                         cmdbuf[0] = MTTC_FSR;
  748                         break;
  749 
  750                     case MTREW:
  751                         sc->sc_flags |= MTF_REW;
  752                         cmdbuf[0] = MTTC_REW;
  753                         break;
  754 
  755                     case MTNOP:
  756                         /*
  757                          * NOP is supposed to set status bits.
  758                          * Force readdsj to do it.
  759                          */
  760                         switch (mtreaddsj(sc,
  761                           MTE_DSJ_FORCE | MTE_COMPLETE | MTE_IDLE)) {
  762                             default:
  763                                 goto done;
  764 
  765                             case -1:
  766                                 /*
  767                                  * If this fails, perform a device clear
  768                                  * to fix any protocol problems and (most
  769                                  * likely) get the status.
  770                                  */
  771                                 bp->b_cmd = MTRESET;
  772                                 break;
  773 
  774                             case -2:
  775                                 callout_reset(&sc->sc_start_ch, hz >> 5,
  776                                     mtstart_callout, sc);
  777                                 return;
  778                         }
  779 
  780                     case MTRESET:
  781                         /*
  782                          * 1) selected device clear (send with "-2" secondary)
  783                          * 2) set timeout, then wait for "service request"
  784                          * 3) interrupt will read DSJ (and END COMPLETE-IDLE)
  785                          */
  786                         if (gpibsend(sc->sc_ic, sc->sc_slave, -2, NULL, 0)){
  787                                 printf("%s can't reset", sc->sc_dev.dv_xname);
  788                                 goto fatalerror;
  789                         }
  790                         callout_reset(&sc->sc_intr_ch, 4*hz, mtintr_callout,
  791                             sc);
  792                         gpibawait(sc->sc_ic);
  793                         return;
  794 
  795                     case MTSET800BPI:
  796                         cmdbuf[0] = MTTC_800;
  797                         break;
  798 
  799                     case MTSET1600BPI:
  800                         cmdbuf[0] = MTTC_1600;
  801                         break;
  802 
  803                     case MTSET6250BPI:
  804                         cmdbuf[0] = MTTC_6250;
  805                         break;
  806 
  807                     case MTSET6250DC:
  808                         cmdbuf[0] = MTTC_DC6250;
  809                         break;
  810                 }
  811         } else {
  812                 if (sc->sc_flags & MTF_PASTEOT) {
  813                         bp->b_error = ENOSPC;
  814                         goto errdone;
  815                 }
  816                 if (bp->b_flags & B_READ) {
  817                         sc->sc_flags |= MTF_IO;
  818                         cmdbuf[0] = MTTC_READ;
  819                 } else {
  820                         sc->sc_flags |= MTF_WRT | MTF_IO;
  821                         cmdbuf[0] = MTTC_WRITE;
  822                         cmdbuf[1] = (bp->b_bcount +((1 << WRITE_BITS_IGNORED) - 1)) >> WRITE_BITS_IGNORED;
  823                         cmdcount = 2;
  824                 }
  825         }
  826         if (gpibsend(sc->sc_ic, sc->sc_slave, MTL_TCMD, cmdbuf, cmdcount)
  827             == cmdcount) {
  828                 if (sc->sc_flags & MTF_REW)
  829                         goto done;
  830                 gpibawait(sc->sc_ic);
  831                 return;
  832         }
  833 fatalerror:
  834         /*
  835          * If anything fails, the drive is probably hosed, so mark it not
  836          * "ALIVE" (but it EXISTS and is OPEN or we wouldn't be here, and
  837          * if, last we heard, it was REWinding, remember that).
  838          */
  839         sc->sc_flags &= MTF_EXISTS | MTF_OPEN | MTF_REW;
  840         bp->b_error = EIO;
  841 errdone:
  842         bp->b_flags |= B_ERROR;
  843 done:
  844         sc->sc_flags &= ~(MTF_HITEOF | MTF_HITBOF);
  845         (void)BUFQ_GET(&sc->sc_tab);
  846         biodone(bp);
  847         gpibrelease(sc->sc_ic, sc->sc_hdl);
  848         if ((bp = BUFQ_PEEK(&sc->sc_tab)) == NULL)
  849                 sc->sc_active = 0;
  850         else
  851                 mtustart(sc);
  852 }
  853 
  854 void
  855 mtintr(sc)
  856         struct mt_softc *sc;
  857 {
  858         struct buf *bp;
  859         int slave, dir, i;
  860         u_char cmdbuf[4];
  861 
  862         slave = sc->sc_slave;
  863 
  864         bp = BUFQ_PEEK(&sc->sc_tab);
  865         if (bp == NULL) {
  866                 printf("%s intr: bp == NULL", sc->sc_dev.dv_xname);
  867                 return;
  868         }
  869 
  870         DPRINTF(MDB_ANY, ("%s intr", sc->sc_dev.dv_xname));
  871 
  872         /*
  873          * Some operation completed.  Read status bytes and report errors.
  874          * Clear EOF flags here `cause they're set once on specific conditions
  875          * below when a command succeeds.
  876          * A DSJ of 2 always means keep waiting.  If the command was READ
  877          * (and we're in data DMA phase) stop data transfer first.
  878          */
  879         sc->sc_flags &= ~(MTF_HITEOF | MTF_HITBOF);
  880         if ((bp->b_flags & (B_CMD|B_READ)) == B_READ &&
  881             !(sc->sc_flags & (MTF_IO | MTF_STATTIMEO | MTF_DSJTIMEO))){
  882                 cmdbuf[0] = MTE_STOP;
  883                 (void) gpibsend(sc->sc_ic, slave, MTL_ECMD,cmdbuf,1);
  884         }
  885         switch (mtreaddsj(sc, 0)) {
  886             case 0:
  887                 break;
  888 
  889             case 1:
  890                 /*
  891                  * If we're in the middle of a READ/WRITE and have yet to
  892                  * start the data transfer, a DSJ of one should terminate it.
  893                  */
  894                 sc->sc_flags &= ~MTF_IO;
  895                 break;
  896 
  897             case 2:
  898                 (void) gpibawait(sc->sc_ic);
  899                 return;
  900 
  901             case -2:
  902                 /*
  903                  * -2 means that the drive failed to respond quickly enough
  904                  * to the request for DSJ.  It's probably just "busy" figuring
  905                  * it out and will know in a little bit...
  906                  */
  907                 callout_reset(&sc->sc_intr_ch, hz >> 5, mtintr_callout, sc);
  908                 return;
  909 
  910             default:
  911                 printf("%s intr: can't get drive stat", sc->sc_dev.dv_xname);
  912                 goto error;
  913         }
  914         if (sc->sc_stat1 & (SR1_ERR | SR1_REJECT)) {
  915                 i = sc->sc_stat4 & SR4_ERCLMASK;
  916                 printf("%s: %s error, retry %d, SR2/3 %x/%x, code %d",
  917                         sc->sc_dev.dv_xname, i == SR4_DEVICE ? "device" :
  918                         (i == SR4_PROTOCOL ? "protocol" :
  919                         (i == SR4_SELFTEST ? "selftest" : "unknown")),
  920                         sc->sc_stat4 & SR4_RETRYMASK, sc->sc_stat2,
  921                         sc->sc_stat3, sc->sc_stat5);
  922 
  923                 if ((bp->b_flags & B_CMD) && bp->b_cmd == MTRESET)
  924                         callout_stop(&sc->sc_intr_ch);
  925                 if (sc->sc_stat3 & SR3_POWERUP)
  926                         sc->sc_flags &= MTF_OPEN | MTF_EXISTS;
  927                 goto error;
  928         }
  929         /*
  930          * Report and clear any soft errors.
  931          */
  932         if (sc->sc_stat1 & SR1_SOFTERR) {
  933                 printf("%s: soft error, retry %d\n", sc->sc_dev.dv_xname,
  934                     sc->sc_stat4 & SR4_RETRYMASK);
  935                 sc->sc_stat1 &= ~SR1_SOFTERR;
  936         }
  937         /*
  938          * We've initiated a read or write, but haven't actually started to
  939          * DMA the data yet.  At this point, the drive's ready.
  940          */
  941         if (sc->sc_flags & MTF_IO) {
  942                 sc->sc_flags &= ~MTF_IO;
  943                 dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE);
  944                 gpibxfer(sc->sc_ic, slave,
  945                     dir == GPIB_READ ? MTT_READ : MTL_WRITE,
  946                     bp->b_data, bp->b_bcount, dir, dir == GPIB_READ);
  947                 return;
  948         }
  949         /*
  950          * Check for End Of Tape - we're allowed to hit EOT and then write (or
  951          * read) one more record.  If we get here and have not already hit EOT,
  952          * return ENOSPC to inform the process that it's hit it.  If we get
  953          * here and HAVE already hit EOT, don't allow any more operations that
  954          * move the tape forward.
  955          */
  956         if (sc->sc_stat1 & SR1_EOT) {
  957                 if (sc->sc_flags & MTF_ATEOT)
  958                         sc->sc_flags |= MTF_PASTEOT;
  959                 else {
  960                         bp->b_flags |= B_ERROR;
  961                         bp->b_error = ENOSPC;
  962                         sc->sc_flags |= MTF_ATEOT;
  963                 }
  964         }
  965         /*
  966          * If a motion command was being executed, check for Tape Marks.
  967          * If we were doing data, make sure we got the right amount, and
  968          * check for hitting tape marks on reads.
  969          */
  970         if (bp->b_flags & B_CMD) {
  971                 if (sc->sc_stat1 & SR1_EOF) {
  972                         if (bp->b_cmd == MTFSR)
  973                                 sc->sc_flags |= MTF_HITEOF;
  974                         if (bp->b_cmd == MTBSR)
  975                                 sc->sc_flags |= MTF_HITBOF;
  976                 }
  977                 if (bp->b_cmd == MTRESET) {
  978                         callout_stop(&sc->sc_intr_ch);
  979                         sc->sc_flags |= MTF_ALIVE;
  980                 }
  981         } else {
  982                 i = gpibrecv(sc->sc_ic, slave, MTT_BCNT, cmdbuf, 2);
  983                 if (i != 2) {
  984                         printf("%s intr: can't get xfer length\n",
  985                             sc->sc_dev.dv_xname);
  986                         goto error;
  987                 }
  988                 i = (int) *((u_short *) cmdbuf);
  989                 if (i <= bp->b_bcount) {
  990                         if (i == 0)
  991                                 sc->sc_flags |= MTF_HITEOF;
  992                         bp->b_resid = bp->b_bcount - i;
  993                         DPRINTF(MDB_ANY, ("%s intr: bcount %ld, resid %ld",
  994                             sc->sc_dev.dv_xname, bp->b_bcount, bp->b_resid));
  995                 } else {
  996                         tprintf(sc->sc_ttyp,
  997                                 "%s: record (%d) larger than wanted (%ld)\n",
  998                                 sc->sc_dev.dv_xname, i, bp->b_bcount);
  999 error:
 1000                         sc->sc_flags &= ~MTF_IO;
 1001                         bp->b_error = EIO;
 1002                         bp->b_flags |= B_ERROR;
 1003                 }
 1004         }
 1005         /*
 1006          * The operation is completely done.
 1007          * Let the drive know with an END command.
 1008          */
 1009         cmdbuf[0] = MTE_COMPLETE | MTE_IDLE;
 1010         (void) gpibsend(sc->sc_ic, slave, MTL_ECMD, cmdbuf, 1);
 1011         bp->b_flags &= ~B_CMD;
 1012         (void)BUFQ_GET(&sc->sc_tab);
 1013         biodone(bp);
 1014         gpibrelease(sc->sc_ic, sc->sc_hdl);
 1015         if (BUFQ_PEEK(&sc->sc_tab) == NULL)
 1016                 sc->sc_active = 0;
 1017         else
 1018                 mtustart(sc);
 1019 }
 1020 
 1021 int
 1022 mtread(dev, uio, flags)
 1023         dev_t dev;
 1024         struct uio *uio;
 1025         int flags;
 1026 {
 1027         struct mt_softc *sc;
 1028 
 1029         sc = device_lookup(&mt_cd, MTUNIT(dev));
 1030 
 1031         return (physio(mtstrategy, &sc->sc_bufstore,
 1032             dev, B_READ, minphys, uio));
 1033 }
 1034 
 1035 int
 1036 mtwrite(dev, uio, flags)
 1037         dev_t dev;
 1038         struct uio *uio;
 1039         int flags;
 1040 {
 1041         struct mt_softc *sc;
 1042 
 1043         sc = device_lookup(&mt_cd, MTUNIT(dev));
 1044 
 1045         return (physio(mtstrategy, &sc->sc_bufstore,
 1046             dev, B_WRITE, minphys, uio));
 1047 }
 1048 
 1049 int
 1050 mtioctl(dev, cmd, data, flag, p)
 1051         dev_t dev;
 1052         u_long cmd;
 1053         caddr_t data;
 1054         int flag;
 1055         struct proc *p;
 1056 {
 1057         struct mtop *op;
 1058         int cnt;
 1059 
 1060         switch (cmd) {
 1061             case MTIOCTOP:
 1062                 op = (struct mtop *)data;
 1063                 switch(op->mt_op) {
 1064                     case MTWEOF:
 1065                     case MTFSF:
 1066                     case MTBSR:
 1067                     case MTBSF:
 1068                     case MTFSR:
 1069                         cnt = op->mt_count;
 1070                         break;
 1071 
 1072                     case MTOFFL:
 1073                     case MTREW:
 1074                     case MTNOP:
 1075                         cnt = 0;
 1076                         break;
 1077 
 1078                     default:
 1079                         return (EINVAL);
 1080                 }
 1081                 return (mtcommand(dev, op->mt_op, cnt));
 1082 
 1083             case MTIOCGET:
 1084                 break;
 1085 
 1086             default:
 1087                 return (EINVAL);
 1088         }
 1089         return (0);
 1090 }

Cache object: eced6cc52dbfb370e6f09f990472d75b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.