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

Cache object: 19c3eda66188b8f1a9e0863785b2cab5


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