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/scsi/rz_tape.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 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        rz_tape.c,v $
   29  * Revision 2.16  93/05/10  21:22:44  rvb
   30  *      Added GET_SIZE ioctl. 
   31  *      Fixed log and a couple of comments.
   32  *      [93/04/09            af]
   33  * 
   34  * Revision 2.15  93/01/14  17:55:39  danner
   35  *      Changed to use common strategy routine.
   36  *      Handle fixed tape errors better (idall is happy).
   37  *      64bit cleanup.
   38  *      [92/12/01            af]
   39  * 
   40  * Revision 2.14  92/08/03  17:54:05  jfriedl
   41  *      removed silly prototypes
   42  *      [92/08/02            jfriedl]
   43  * 
   44  * Revision 2.13  92/05/21  17:23:52  jfriedl
   45  *      Cleanup to quiet gcc warnings.
   46  *      [92/05/18            jfriedl]
   47  * 
   48  * Revision 2.12  92/04/06  23:23:09  rpd
   49  *      Use scsi_print_sense_data where applicable.
   50  *      [92/04/06            af]
   51  * 
   52  * Revision 2.11  92/02/23  22:44:37  elf
   53  *      Changed the interface of a number of functions not to
   54  *      require the scsi_softc pointer any longer.  It was
   55  *      mostly unused, now it can be found via tgt->masterno.
   56  *      [92/02/22  19:30:10  af]
   57  * 
   58  * Revision 2.10  91/10/09  16:17:19  af
   59  *       Revision 2.9.1.2  91/09/01  17:16:50  af
   60  *              Zero io_error before using the ior.
   61  *       Revision 2.9.1.1  91/08/29  18:08:50  af
   62  *              Fixed to compile again under 2.5.
   63  * 
   64  * Revision 2.9  91/08/24  12:28:15  af
   65  *      Flag tapes as exclusive open, Spl defs, now we
   66  *      understand fixed-size tapes (QIC-11), multiP locks.
   67  *      [91/08/02  03:56:41  af]
   68  * 
   69  *      Cast args for bcopy.
   70  * 
   71  * Revision 2.8  91/06/25  20:56:33  rpd
   72  *      Tweaks to make gcc happy.
   73  * 
   74  * Revision 2.7  91/06/19  11:57:12  rvb
   75  *      File moved here from mips/PMAX since it is now "MI" code, also
   76  *      used by Vax3100 and soon -- the omron luna88k.
   77  *      [91/06/04            rvb]
   78  * 
   79  * Revision 2.6  91/05/14  17:27:00  mrt
   80  *      Correcting copyright
   81  * 
   82  * Revision 2.5  91/05/13  06:34:29  af
   83  *      Do not say we failed to bspfile when the target really was
   84  *      only busy.
   85  *      Retrieve from mode_sense speed, density and writeprotect info.
   86  *      Deal with targets that are busy, note when we get confused due
   87  *      to a scsi bus reset.  Set speed and density if user asks to.
   88  *      Generally, made it work properly [it passes Rudy's tests].
   89  *      Tapes really work now.
   90  * 
   91  * Revision 2.4  91/02/05  17:44:01  mrt
   92  *      Added author notices
   93  *      [91/02/04  11:17:11  mrt]
   94  * 
   95  *      Changed to use new Mach copyright
   96  *      [91/02/02  12:15:49  mrt]
   97  * 
   98  * Revision 2.3  90/12/05  23:34:04  af
   99  *      Mild attempt to get it working.  Needs lots of work still.
  100  *      [90/12/03  23:34:27  af]
  101  * 
  102  * Revision 2.1.1.1  90/11/01  03:44:11  af
  103  *      Created.
  104  *      [90/10/21            af]
  105  */
  106 /*
  107  *      File: rz_tape.c
  108  *      Author: Alessandro Forin, Carnegie Mellon University
  109  *      Date:   10/90
  110  *
  111  *      Top layer of the SCSI driver: interface with the MI.
  112  *      This file contains operations specific to TAPE-like devices.
  113  */
  114 
  115 #include <mach/std_types.h>
  116 #include <scsi/compat_30.h>
  117 
  118 #include <sys/ioctl.h>
  119 #ifdef  MACH_KERNEL
  120 #include <device/tape_status.h>
  121 #else   /*MACH_KERNEL*/
  122 #include <mips/PMAX/tape_status.h>
  123 #endif  /*MACH_KERNEL*/
  124 
  125 #include <scsi/scsi.h>
  126 #include <scsi/scsi_defs.h>
  127 #include <scsi/rz.h>
  128 
  129 
  130 
  131 void sctape_start(); /* forward */
  132 
  133 int scsi_tape_timeout = 5*60;   /* secs, tk50 is slow when positioning far apart */
  134 
  135 int sctape_open(tgt, req)
  136         target_info_t   *tgt;
  137         io_req_t        req;
  138 {
  139         io_return_t     ret;
  140         io_req_t        ior;
  141         int             i;
  142         scsi_mode_sense_data_t *mod;
  143 
  144 #ifdef  MACH_KERNEL
  145         req->io_device->flag |= D_EXCL_OPEN;
  146 #endif  /*MACH_KERNEL*/
  147 
  148         /* Preferably allow tapes to disconnect */
  149         if (BGET(scsi_might_disconnect,(unsigned char)tgt->masterno,tgt->target_id))
  150                 BSET(scsi_should_disconnect,(unsigned char)tgt->masterno,tgt->target_id);
  151 
  152         /*
  153          * Dummy ior for proper sync purposes
  154          */
  155         io_req_alloc(ior,0);
  156         ior->io_count = 0;
  157 
  158         /*
  159          * Do a mode sense first, some drives might be picky
  160          * about changing params [even if the standard might
  161          * say otherwise, sigh.]
  162          */
  163         do {
  164                 ior->io_op = IO_INTERNAL;
  165                 ior->io_next = 0;
  166                 ior->io_error = 0;
  167                 ret = scsi_mode_sense(tgt, 0, 32, ior);
  168         } while (ret == SCSI_RET_RETRY);
  169 
  170         mod = (scsi_mode_sense_data_t *)tgt->cmd_ptr;
  171         if (scsi_debug) {
  172                 int     p[5];
  173                 bcopy((char*)mod, (char*)p, sizeof(p));
  174                 printf("[modsns(%x): x%x x%x x%x x%x x%x]", ret,
  175                         p[0], p[1], p[2], p[3], p[4]);
  176         }
  177         if (ret == SCSI_RET_DEVICE_DOWN)
  178                 goto out;
  179         if (ret == SCSI_RET_SUCCESS) {
  180                 tgt->dev_info.tape.read_only = mod->wp;
  181                 tgt->dev_info.tape.speed = mod->speed;
  182                 tgt->dev_info.tape.density = mod->bdesc[0].density_code;
  183         } /* else they all default sensibly, using zeroes */
  184 
  185         /* Some tapes have limits on record-length */
  186 again:
  187         ior->io_op = IO_INTERNAL;
  188         ior->io_next = 0;
  189         ior->io_error = 0;
  190         ret = scsi_read_block_limits( tgt, ior);
  191         if (ret == SCSI_RET_RETRY) goto again;
  192         if (!ior->io_error && (ret == SCSI_RET_SUCCESS)) {
  193                 scsi_blimits_data_t     *lim;
  194                 int                     maxl;
  195 
  196                 lim = (scsi_blimits_data_t *) tgt->cmd_ptr;
  197 
  198                 tgt->block_size = (lim->minlen_msb << 8) |
  199                                    lim->minlen_lsb;
  200 
  201                 maxl =  (lim->maxlen_msb << 16) |
  202                         (lim->maxlen_sb  <<  8) |
  203                          lim->maxlen_lsb;
  204                 if (maxl == 0)
  205                         maxl = (unsigned)-1;
  206                 tgt->dev_info.tape.maxreclen = maxl;
  207                 tgt->dev_info.tape.fixed_size = (maxl == tgt->block_size);
  208         } else {
  209                 /* let the user worry about it */
  210                 /* default: tgt->block_size = 1; */
  211                 tgt->dev_info.tape.maxreclen = (unsigned)-1;
  212                 tgt->dev_info.tape.fixed_size = FALSE;
  213         }
  214 
  215         /* Try hard to do a mode select */
  216         for (i = 0; i < 5; i++) {
  217                 ior->io_op = IO_INTERNAL;
  218                 ior->io_error = 0;
  219                 ret = sctape_mode_select(tgt, 0, 0, FALSE, ior);
  220                 if (ret == SCSI_RET_SUCCESS)
  221                         break;
  222         }
  223         if (scsi_watchdog_period < scsi_tape_timeout)
  224                 scsi_watchdog_period += scsi_tape_timeout;
  225 
  226 #if 0   /* this might imply rewind, which we do not want, although yes, .. */
  227         /* we want the tape loaded */
  228         ior->io_op = IO_INTERNAL;
  229         ior->io_next = 0;
  230         ior->io_error = 0;
  231         ret = scsi_start_unit(tgt, SCSI_CMD_SS_START, ior);
  232 #endif
  233         req->io_device->bsize = tgt->block_size;
  234 out:
  235         io_req_free(ior);
  236         return ret;
  237 }
  238 
  239 
  240 io_return_t sctape_close(tgt)
  241         target_info_t   *tgt;
  242 {
  243         io_return_t     ret = SCSI_RET_SUCCESS;
  244         io_req_t        ior;
  245 
  246         /*
  247          * Dummy ior for proper sync purposes
  248          */
  249         io_req_alloc(ior,0);
  250         ior->io_op = IO_INTERNAL;
  251         ior->io_next = 0;
  252         ior->io_count = 0;
  253 
  254         if (tgt->ior) printf("TAPE: Close with pending requests ?? \n");
  255 
  256         /* write a filemark if we xtnded/truncated the tape */
  257         if (tgt->flags & TGT_WRITTEN_TO) {
  258                 tgt->ior = ior;
  259                 ior->io_error = 0;
  260                 ret = scsi_write_filemarks(tgt, 2, ior);
  261                 if (ret != SCSI_RET_SUCCESS)
  262                          printf("%s%d: wfmark failed x%x\n",
  263                          (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret);
  264                 /*
  265                  * Don't bother repositioning if we'll rewind it
  266                  */
  267                 if (tgt->flags & TGT_REWIND_ON_CLOSE)
  268                         goto rew;
  269 retry:
  270                 tgt->ior = ior;
  271                 ior->io_op = IO_INTERNAL;
  272                 ior->io_error = 0;
  273                 ior->io_next = 0;
  274                 ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -1, ior);
  275                 if (ret != SCSI_RET_SUCCESS) {
  276                         if (ret == SCSI_RET_RETRY) {
  277                                 timeout(wakeup, tgt, hz);
  278                                 await(tgt);
  279                                 goto retry;
  280                         }
  281                         printf("%s%d: bspfile failed x%x\n",
  282                          (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret);
  283                 }
  284         }
  285 rew:
  286         if (tgt->flags & TGT_REWIND_ON_CLOSE) {
  287                 /* Rewind tape */
  288                 ior->io_error = 0;
  289                 ior->io_op = IO_INTERNAL;
  290                 ior->io_error = 0;
  291                 tgt->ior = ior;
  292                 (void) scsi_rewind(tgt, ior, FALSE);
  293                 iowait(ior);
  294                 if (tgt->done == SCSI_RET_RETRY) {
  295                         timeout(wakeup, tgt, 5*hz);
  296                         await(tgt);
  297                         goto rew;
  298                 }
  299         }
  300                 io_req_free(ior);
  301 
  302         tgt->flags &= ~(TGT_ONLINE|TGT_WRITTEN_TO|TGT_REWIND_ON_CLOSE);
  303         return ret;
  304 }
  305 
  306 int sctape_strategy(ior)
  307         register io_req_t       ior;
  308 {
  309         target_info_t  *tgt;
  310         register int    i = ior->io_unit;
  311 
  312         tgt = scsi_softc[rzcontroller(i)]->target[rzslave(i)];
  313 
  314         if (((ior->io_op & IO_READ) == 0) &&
  315             tgt->dev_info.tape.read_only) {
  316                 ior->io_error = D_INVALID_OPERATION;
  317                 ior->io_op |= IO_ERROR;
  318                 ior->io_residual = ior->io_count;
  319                 iodone(ior);
  320                 return ior->io_error;
  321         }
  322 
  323         return rz_simpleq_strategy( ior, sctape_start);
  324 }
  325 
  326 static void
  327 do_residue(ior, sns, bsize)
  328         io_req_t          ior;
  329         scsi_sense_data_t *sns;
  330         int               bsize;
  331 {
  332         int residue;
  333 
  334         /* Not an error situation */
  335         ior->io_error = 0;
  336         ior->io_op &= ~IO_ERROR;
  337 
  338         if (!sns->addr_valid) {
  339                 ior->io_residual = ior->io_count;
  340                 return;
  341         }
  342 
  343         residue = sns->u.xtended.info0 << 24 |
  344                   sns->u.xtended.info1 << 16 |
  345                   sns->u.xtended.info2 <<  8 |
  346                   sns->u.xtended.info3;
  347         /* fixed ? */
  348         residue *= bsize;
  349         /*
  350          * NOTE: residue == requested - actual
  351          * We only care if > 0
  352          */
  353         if (residue < 0) residue = 0;/* sanity */
  354         ior->io_residual += residue;
  355 }
  356 
  357 void sctape_start( tgt, done)
  358         target_info_t   *tgt;
  359         boolean_t       done;
  360 {
  361         io_req_t                head, ior = tgt->ior;
  362 
  363         if (ior == 0)
  364                 return;
  365 
  366         if (done) {
  367 
  368                 /* see if we must retry */
  369                 if ((tgt->done == SCSI_RET_RETRY) &&
  370                     ((ior->io_op & IO_INTERNAL) == 0)) {
  371                         delay(1000000);/*XXX*/
  372                         goto start;
  373                 } else
  374                 /* got a bus reset ? ouch, that hurts */
  375                 if (tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) {
  376                         /*
  377                          * we really cannot retry because the tape position
  378                          * is lost.
  379                          */
  380                         printf("Lost tape position\n");
  381                         ior->io_error = D_IO_ERROR;
  382                         ior->io_op |= IO_ERROR;
  383                 } else
  384 
  385                 /* check completion status */
  386 
  387                 if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
  388                         scsi_sense_data_t *sns;
  389 
  390                         ior->io_op = ior->io_temporary;
  391                         ior->io_error = D_IO_ERROR;
  392                         ior->io_op |= IO_ERROR;
  393 
  394                         sns = (scsi_sense_data_t *)tgt->cmd_ptr;
  395 
  396                         if (scsi_debug)
  397                                 scsi_print_sense_data(sns);
  398 
  399                         if (scsi_check_sense_data(tgt, sns)) {
  400                             if (sns->u.xtended.ili) {
  401                                 if (ior->io_op & IO_READ) {
  402                                     do_residue(ior, sns, tgt->block_size);
  403                                     if (scsi_debug)
  404                                         printf("Tape Short Read (%d)\n",
  405                                                 ior->io_residual);
  406                                 }
  407                             } else if (sns->u.xtended.eom) {
  408                                 do_residue(ior, sns, tgt->block_size);
  409                                 if (scsi_debug)
  410                                         printf("End of Physical Tape!\n");
  411                             } else if (sns->u.xtended.fm) {
  412                                 do_residue(ior, sns, tgt->block_size);
  413                                 if (scsi_debug)
  414                                         printf("File Mark\n");
  415                             }
  416                         }
  417                 }
  418 
  419                 else if (tgt->done != SCSI_RET_SUCCESS) {
  420 
  421                     if (tgt->done == SCSI_RET_NEED_SENSE) {
  422 
  423                         ior->io_temporary = ior->io_op;
  424                         ior->io_op = IO_INTERNAL;
  425                         if (scsi_debug)
  426                                 printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count);
  427                         scsi_request_sense(tgt, ior, 0);
  428                         return;
  429 
  430                     } else if (tgt->done == SCSI_RET_RETRY) {
  431                         /* only retry here READs and WRITEs */
  432                         if ((ior->io_op & IO_INTERNAL) == 0) {
  433                                 ior->io_residual = 0;
  434                                 goto start;
  435                         } else{
  436                                 ior->io_error = D_WOULD_BLOCK;
  437                                 ior->io_op |= IO_ERROR;
  438                         }
  439                     } else {
  440                         ior->io_error = D_IO_ERROR;
  441                         ior->io_op |= IO_ERROR;
  442                     }
  443                 }
  444 
  445                 if (scsi_debug)
  446                         printf("[Resid x%x]", ior->io_residual);
  447 
  448                 /* dequeue next one */
  449                 head = ior;
  450 
  451                 simple_lock(&tgt->target_lock);
  452                 ior = head->io_next;
  453                 tgt->ior = ior;
  454                 if (ior)
  455                         ior->io_prev = head->io_prev;
  456                 simple_unlock(&tgt->target_lock);
  457 
  458                 iodone(head);
  459 
  460                 if (ior == 0)
  461                         return;
  462         }
  463         ior->io_residual = 0;
  464 start:
  465         if (ior->io_op & IO_READ) {
  466                 tgt->flags &= ~TGT_WRITTEN_TO;
  467                 sctape_read( tgt, ior );
  468         } else if ((ior->io_op & IO_INTERNAL) == 0) {
  469                 tgt->flags |= TGT_WRITTEN_TO;
  470                 sctape_write( tgt, ior );
  471         }
  472 }
  473 
  474 io_return_t
  475 sctape_get_status( dev, tgt, flavor, status, status_count)
  476         int             dev;
  477         target_info_t   *tgt;
  478         dev_flavor_t    flavor;
  479         dev_status_t    status;
  480         natural_t       *status_count;
  481 {
  482         switch (flavor) {
  483         case DEV_GET_SIZE:
  484                 
  485                 status[DEV_GET_SIZE_DEVICE_SIZE] = 0;
  486                 status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size;
  487                 *status_count = DEV_GET_SIZE_COUNT;
  488                 break;
  489         case TAPE_STATUS: {
  490                 struct tape_status *ts = (struct tape_status *) status;
  491 
  492                 ts->mt_type             = MT_ISSCSI;
  493                 ts->speed               = tgt->dev_info.tape.speed;
  494                 ts->density             = tgt->dev_info.tape.density;
  495                 ts->flags               = (tgt->flags & TGT_REWIND_ON_CLOSE) ?
  496                                                 TAPE_FLG_REWIND : 0;
  497                 if (tgt->dev_info.tape.read_only)
  498                         ts->flags |= TAPE_FLG_WP;
  499 #ifdef  MACH_KERNEL
  500                 *status_count = TAPE_STATUS_COUNT;
  501 #endif
  502 
  503                 break;
  504             }
  505         /* U*x compat */
  506         case MTIOCGET: {
  507                 struct mtget *g = (struct mtget *) status;
  508 
  509                 bzero(g, sizeof(struct mtget));
  510                 g->mt_type = 0x7;       /* Ultrix compat */
  511 #ifdef  MACH_KERNEL
  512                 *status_count = sizeof(struct mtget)/sizeof(int);
  513 #endif
  514                 break;
  515             }
  516         default:
  517                 return D_INVALID_OPERATION;
  518         }
  519         return D_SUCCESS;
  520 }
  521 
  522 io_return_t
  523 sctape_set_status( dev, tgt, flavor, status, status_count)
  524         int             dev;
  525         target_info_t   *tgt;
  526         dev_flavor_t    flavor;
  527         dev_status_t    status;
  528         natural_t       status_count;
  529 {
  530         scsi_ret_t              ret;
  531 
  532         switch (flavor) {
  533         case TAPE_STATUS: {
  534                 struct tape_status *ts = (struct tape_status *) status;
  535                 if (ts->flags & TAPE_FLG_REWIND)
  536                         tgt->flags |= TGT_REWIND_ON_CLOSE;
  537                 else
  538                         tgt->flags &= ~TGT_REWIND_ON_CLOSE;
  539 
  540                 if (ts->speed || ts->density) {
  541                         unsigned int ospeed, odensity;
  542                         io_req_t        ior;
  543 
  544                         io_req_alloc(ior,0);
  545                         ior->io_op = IO_INTERNAL;
  546                         ior->io_error = 0;
  547                         ior->io_next = 0;
  548                         ior->io_count = 0;
  549 
  550                         ospeed = tgt->dev_info.tape.speed;
  551                         odensity = tgt->dev_info.tape.density;
  552                         tgt->dev_info.tape.speed = ts->speed;
  553                         tgt->dev_info.tape.density = ts->density;
  554 
  555                         ret = sctape_mode_select(tgt, 0, 0, (ospeed == ts->speed), ior);
  556                         if (ret != SCSI_RET_SUCCESS) {
  557                                 tgt->dev_info.tape.speed = ospeed;
  558                                 tgt->dev_info.tape.density = odensity;
  559                         }
  560 
  561                         io_req_free(ior);
  562                 }
  563 
  564                 break;
  565             }
  566         /* U*x compat */
  567         case MTIOCTOP: {
  568                 struct tape_params *mt = (struct tape_params *) status;
  569                 io_req_t        ior;
  570 
  571                 if (scsi_debug)
  572                         printf("[sctape_sstatus: %x %x %x]\n",
  573                                 flavor, mt->mt_operation, mt->mt_repeat_count);
  574 
  575                 io_req_alloc(ior,0);
  576 retry:
  577                 ior->io_count = 0;
  578                 ior->io_op = IO_INTERNAL;
  579                 ior->io_error = 0;
  580                 ior->io_next = 0;
  581                 tgt->ior = ior;
  582 
  583                 /* compat: in U*x it is a short */
  584                 switch ((short)(mt->mt_operation)) {
  585                 case MTWEOF:    /* write an end-of-file record */
  586                         ret = scsi_write_filemarks(tgt, mt->mt_repeat_count, ior);
  587                         break;
  588                 case MTFSF:     /* forward space file */
  589                         ret = scsi_space(tgt, SCSI_CMD_SP_FIL, mt->mt_repeat_count, ior);
  590                         break;
  591                 case MTBSF:     /* backward space file */
  592                         ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -mt->mt_repeat_count,ior);
  593                         break;
  594                 case MTFSR:     /* forward space record */
  595                         ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, mt->mt_repeat_count, ior);
  596                         break;
  597                 case MTBSR:     /* backward space record */
  598                         ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, -mt->mt_repeat_count, ior);
  599                         break;
  600                 case MTREW:     /* rewind */
  601                 case MTOFFL:    /* rewind and put the drive offline */
  602                         ret = scsi_rewind(tgt, ior, TRUE);
  603                         iowait(ior);
  604                         if ((short)(mt->mt_operation) == MTREW) break;
  605                         ior->io_op = 0;
  606                         ior->io_next = 0;
  607                         ior->io_error = 0;
  608                         (void) scsi_start_unit(tgt, 0, ior);
  609                         break;
  610                 case MTNOP:     /* no operation, sets status only */
  611                 case MTCACHE:   /* enable controller cache */
  612                 case MTNOCACHE: /* disable controller cache */
  613                         ret = SCSI_RET_SUCCESS;
  614                         break;
  615                 default:
  616                         tgt->ior = 0;
  617                         io_req_free(ior);
  618                         return D_INVALID_OPERATION;
  619                 }
  620 
  621                 if (ret == SCSI_RET_RETRY) {
  622                         timeout(wakeup, ior, 5*hz);
  623                         await(ior);
  624                         goto retry;
  625                 }
  626 
  627                 io_req_free(ior);
  628                 if (ret != SCSI_RET_SUCCESS)
  629                         return D_IO_ERROR;
  630                 break;
  631         }
  632         case MTIOCIEOT:
  633         case MTIOCEEOT:
  634         default:
  635                 return D_INVALID_OPERATION;
  636         }
  637         return D_SUCCESS;
  638 }

Cache object: ed0ebbc376b6d96a5a7cb75e2bfe50e8


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