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/ata/atapi-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  * Copyright (c) 1998 - 2004 Søren Schmidt <sos@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_ata.h"
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/ata.h>
   36 #include <sys/kernel.h>
   37 #include <sys/conf.h>
   38 #include <sys/malloc.h>
   39 #include <sys/bio.h>
   40 #include <sys/bus.h>
   41 #include <sys/mtio.h>
   42 #include <sys/devicestat.h>
   43 #include <sys/sema.h>
   44 #include <sys/taskqueue.h>
   45 #include <vm/uma.h>
   46 #include <machine/bus.h>
   47 #include <dev/ata/ata-all.h>
   48 #include <dev/ata/atapi-tape.h>
   49 
   50 /* device structures */
   51 static  d_open_t        ast_open;
   52 static  d_close_t       ast_close;
   53 static  d_ioctl_t       ast_ioctl;
   54 static  d_strategy_t    ast_strategy;
   55 static struct cdevsw ast_cdevsw = {
   56         .d_version =    D_VERSION,
   57         .d_open =       ast_open,
   58         .d_close =      ast_close,
   59         .d_read =       physread,
   60         .d_write =      physwrite,
   61         .d_ioctl =      ast_ioctl,
   62         .d_strategy =   ast_strategy,
   63         .d_name =       "ast",
   64         .d_flags =      D_TAPE | D_TRACKCLOSE,
   65 };
   66 
   67 /* prototypes */
   68 static void ast_detach(struct ata_device *);
   69 static void ast_start(struct ata_device *);
   70 static int ast_sense(struct ast_softc *);
   71 static void ast_describe(struct ast_softc *);
   72 static void ast_done(struct ata_request *);
   73 static int ast_mode_sense(struct ast_softc *, int, void *, int); 
   74 static int ast_mode_select(struct ast_softc *, void *, int);
   75 static int ast_write_filemark(struct ast_softc *, u_int8_t);
   76 static int ast_read_position(struct ast_softc *, int, struct ast_readposition *);
   77 static int ast_space(struct ast_softc *, u_int8_t, int32_t);
   78 static int ast_locate(struct ast_softc *, int, u_int32_t);
   79 static int ast_prevent_allow(struct ast_softc *stp, int);
   80 static int ast_load_unload(struct ast_softc *, u_int8_t);
   81 static int ast_rewind(struct ast_softc *);
   82 static int ast_erase(struct ast_softc *);
   83 static int ast_test_ready(struct ata_device *);
   84 static int ast_wait_dsc(struct ata_device *, int);
   85 
   86 /* internal vars */
   87 static u_int32_t ast_lun_map = 0;
   88 static u_int64_t ast_total = 0;
   89 static MALLOC_DEFINE(M_AST, "AST driver", "ATAPI tape driver buffers");
   90 
   91 void 
   92 ast_attach(struct ata_device *atadev)
   93 {
   94     struct ast_softc *stp;
   95     struct ast_readposition position;
   96     struct cdev *dev;
   97 
   98     stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT | M_ZERO);
   99     if (!stp) {
  100         ata_prtdev(atadev, "out of memory\n");
  101         return;
  102     }
  103 
  104     stp->device = atadev;
  105     stp->lun = ata_get_lun(&ast_lun_map);
  106     ata_set_name(atadev, "ast", stp->lun);
  107     bioq_init(&stp->queue);
  108     mtx_init(&stp->queue_mtx, "ATAPI TAPE bioqueue lock", NULL, MTX_DEF);
  109 
  110     if (ast_sense(stp)) {
  111         free(stp, M_AST);
  112         return;
  113     }
  114 
  115     if (!strcmp(atadev->param->model, "OnStream DI-30")) {
  116         struct ast_transferpage transfer;
  117         struct ast_identifypage identify;
  118 
  119         stp->flags |= F_ONSTREAM;
  120         bzero(&transfer, sizeof(struct ast_transferpage));
  121         ast_mode_sense(stp, ATAPI_TAPE_TRANSFER_PAGE,
  122                        &transfer, sizeof(transfer));
  123         bzero(&identify, sizeof(struct ast_identifypage));
  124         ast_mode_sense(stp, ATAPI_TAPE_IDENTIFY_PAGE,
  125                        &identify, sizeof(identify));
  126         strncpy(identify.ident, "FBSD", 4);
  127         ast_mode_select(stp, &identify, sizeof(identify));
  128         ast_read_position(stp, 0, &position);
  129     }
  130 
  131     stp->stats = devstat_new_entry("ast", stp->lun, DEV_BSIZE,
  132                       DEVSTAT_NO_ORDERED_TAGS,
  133                       DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE,
  134                       DEVSTAT_PRIORITY_TAPE);
  135     dev = make_dev(&ast_cdevsw, 2 * stp->lun,
  136                    UID_ROOT, GID_OPERATOR, 0640, "ast%d", stp->lun);
  137     dev->si_drv1 = stp;
  138     if (atadev->channel->dma)
  139         dev->si_iosize_max = atadev->channel->dma->max_iosize;
  140     else
  141         dev->si_iosize_max = DFLTPHYS;
  142     stp->dev1 = dev;
  143     dev = make_dev(&ast_cdevsw, 2 * stp->lun + 1,
  144                    UID_ROOT, GID_OPERATOR, 0640, "nast%d", stp->lun);
  145 
  146     dev->si_drv1 = stp;
  147     if (atadev->channel->dma)
  148         dev->si_iosize_max = atadev->channel->dma->max_iosize;
  149     else
  150         dev->si_iosize_max = DFLTPHYS;
  151     stp->dev2 = dev;
  152 
  153     /* setup the function ptrs */ 
  154     atadev->detach = ast_detach;
  155     atadev->start = ast_start;
  156     atadev->softc = stp;
  157     atadev->flags |= ATA_D_MEDIA_CHANGED;
  158 
  159     /* announce we are here */
  160     ast_describe(stp);
  161 }
  162 
  163 static void     
  164 ast_detach(struct ata_device *atadev)
  165 {   
  166     struct ast_softc *stp = atadev->softc;
  167     
  168     mtx_lock(&stp->queue_mtx);
  169     bioq_flush(&stp->queue, NULL, ENXIO);
  170     mtx_unlock(&stp->queue_mtx);
  171     mtx_destroy(&stp->queue_mtx);
  172     destroy_dev(stp->dev1);
  173     destroy_dev(stp->dev2);
  174     devstat_remove_entry(stp->stats);
  175     ata_prtdev(atadev, "WARNING - removed from configuration\n");
  176     ata_free_name(atadev);
  177     ata_free_lun(&ast_lun_map, stp->lun);
  178     atadev->attach = NULL;
  179     atadev->detach = NULL;
  180     atadev->start = NULL;
  181     atadev->softc = NULL;
  182     atadev->flags = 0;
  183     free(stp, M_AST);
  184 }
  185 
  186 static int
  187 ast_sense(struct ast_softc *stp)
  188 {
  189     int count;
  190 
  191     /* get drive capabilities, some bugridden drives needs this repeated */
  192     for (count = 0 ; count < 5 ; count++) {
  193         if (!ast_mode_sense(stp, ATAPI_TAPE_CAP_PAGE,
  194                             &stp->cap, sizeof(stp->cap)) &&
  195             stp->cap.page_code == ATAPI_TAPE_CAP_PAGE) {
  196             if (stp->cap.blk32k)
  197                 stp->blksize = 32768;
  198             if (stp->cap.blk1024)
  199                 stp->blksize = 1024;
  200             if (stp->cap.blk512)
  201                 stp->blksize = 512;
  202             if (!stp->blksize)
  203                 continue;
  204             stp->cap.max_speed = ntohs(stp->cap.max_speed);
  205             stp->cap.max_defects = ntohs(stp->cap.max_defects);
  206             stp->cap.ctl = ntohs(stp->cap.ctl);
  207             stp->cap.speed = ntohs(stp->cap.speed);
  208             stp->cap.buffer_size = ntohs(stp->cap.buffer_size);
  209             return 0;
  210         }
  211     }
  212     return 1;
  213 }
  214 
  215 static void 
  216 ast_describe(struct ast_softc *stp)
  217 {
  218     if (bootverbose) {
  219         ata_prtdev(stp->device, "<%.40s/%.8s> tape drive at ata%d as %s\n",
  220                    stp->device->param->model, stp->device->param->revision,
  221                    device_get_unit(stp->device->channel->dev),
  222                    (stp->device->unit == ATA_MASTER) ? "master" : "slave");
  223         ata_prtdev(stp->device, "%dKB/s, ", stp->cap.max_speed);
  224         printf("transfer limit %d blk%s, ",
  225                stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
  226         printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
  227         printf("%s\n", ata_mode2str(stp->device->mode));
  228         ata_prtdev(stp->device, "Medium: ");
  229         switch (stp->cap.medium_type) {
  230             case 0x00:
  231                 printf("none"); break;
  232             case 0x17:
  233                 printf("Travan 1 (400 Mbyte)"); break;
  234             case 0xb6:
  235                 printf("Travan 4 (4 Gbyte)"); break;
  236             case 0xda:
  237                 printf("OnStream ADR (15Gyte)"); break;
  238             default:
  239                 printf("unknown (0x%x)", stp->cap.medium_type);
  240         }
  241         if (stp->cap.readonly) printf(", readonly");
  242         if (stp->cap.reverse) printf(", reverse");
  243         if (stp->cap.eformat) printf(", eformat");
  244         if (stp->cap.qfa) printf(", qfa");
  245         if (stp->cap.lock) printf(", lock");
  246         if (stp->cap.locked) printf(", locked");
  247         if (stp->cap.prevent) printf(", prevent");
  248         if (stp->cap.eject) printf(", eject");
  249         if (stp->cap.disconnect) printf(", disconnect");
  250         if (stp->cap.ecc) printf(", ecc");
  251         if (stp->cap.compress) printf(", compress");
  252         if (stp->cap.blk512) printf(", 512b");
  253         if (stp->cap.blk1024) printf(", 1024b");
  254         if (stp->cap.blk32k) printf(", 32kb");
  255         printf("\n");
  256     }
  257     else {
  258         ata_prtdev(stp->device, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
  259                    stp->device->param->model, stp->device->param->revision,
  260                    device_get_unit(stp->device->channel->dev),
  261                    (stp->device->unit == ATA_MASTER) ? "master" : "slave",
  262                    ata_mode2str(stp->device->mode));
  263     }
  264 }
  265 
  266 static int
  267 ast_open(struct cdev *dev, int flags, int fmt, struct thread *td)
  268 {
  269     struct ast_softc *stp = dev->si_drv1;
  270 
  271     if (!stp || stp->device->flags & ATA_D_DETACHING)
  272         return ENXIO;
  273 
  274     if (count_dev(dev) > 1)
  275         return EBUSY;
  276 
  277     ast_test_ready(stp->device);
  278 
  279     if (stp->cap.lock)
  280         ast_prevent_allow(stp, 1);
  281 
  282     if (ast_sense(stp))
  283         ata_prtdev(stp->device, "sense media type failed\n");
  284 
  285     stp->device->flags &= ~ATA_D_MEDIA_CHANGED;
  286     stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
  287     ast_total = 0;
  288     return 0;
  289 }
  290 
  291 static int 
  292 ast_close(struct cdev *dev, int flags, int fmt, struct thread *td)
  293 {
  294     struct ast_softc *stp = dev->si_drv1;
  295 
  296     /* flush buffers, some drives fail here, they should report ctl = 0 */
  297     if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN))
  298         ast_write_filemark(stp, 0);
  299 
  300     /* write filemark if data written to tape */
  301     if (!(stp->flags & F_ONSTREAM) &&
  302         (stp->flags & (F_DATA_WRITTEN | F_FM_WRITTEN)) == F_DATA_WRITTEN)
  303         ast_write_filemark(stp, ATAPI_WF_WRITE);
  304 
  305     /* if minor is even rewind on close */
  306     if (!(minor(dev) & 0x01))
  307         ast_rewind(stp);
  308 
  309     if (stp->cap.lock && count_dev(dev) == 1)
  310         ast_prevent_allow(stp, 0);
  311 
  312     stp->flags &= ~F_CTL_WARN;
  313 #ifdef AST_DEBUG
  314     ata_prtdev(stp->device, "%ju total bytes transferred\n",
  315                (uintmax_t)ast_total);
  316 #endif
  317     return 0;
  318 }
  319 
  320 static int 
  321 ast_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
  322 {
  323     struct ast_softc *stp = dev->si_drv1;
  324     int error = 0;
  325 
  326     switch (cmd) {
  327     case MTIOCGET:
  328         {
  329             struct mtget *g = (struct mtget *) addr;
  330 
  331             bzero(g, sizeof(struct mtget));
  332             g->mt_type = 7;
  333             g->mt_density = 1;
  334             g->mt_blksiz = stp->blksize;
  335             g->mt_comp = stp->cap.compress;
  336             g->mt_density0 = 0; g->mt_density1 = 0;
  337             g->mt_density2 = 0; g->mt_density3 = 0;
  338             g->mt_blksiz0 = 0; g->mt_blksiz1 = 0;
  339             g->mt_blksiz2 = 0; g->mt_blksiz3 = 0;
  340             g->mt_comp0 = 0; g->mt_comp1 = 0;
  341             g->mt_comp2 = 0; g->mt_comp3 = 0;
  342         }
  343         break;   
  344 
  345     case MTIOCTOP:
  346         {       
  347             int i;
  348             struct mtop *mt = (struct mtop *)addr;
  349 
  350             switch ((int16_t) (mt->mt_op)) {
  351 
  352             case MTWEOF:
  353                 for (i=0; i < mt->mt_count && !error; i++)
  354                     error = ast_write_filemark(stp, ATAPI_WF_WRITE);
  355                 break;
  356 
  357             case MTFSF:
  358                 if (mt->mt_count)
  359                     error = ast_space(stp, ATAPI_SP_FM, mt->mt_count);
  360                 break;
  361 
  362             case MTBSF:
  363                 if (mt->mt_count)
  364                     error = ast_space(stp, ATAPI_SP_FM, -(mt->mt_count));
  365                 break;
  366 
  367             case MTREW:
  368                 error = ast_rewind(stp);
  369                 break;
  370 
  371             case MTOFFL:
  372                 error = ast_load_unload(stp, ATAPI_SS_EJECT);
  373                 break;
  374 
  375             case MTNOP:
  376                 error = ast_write_filemark(stp, 0);
  377                 break;
  378 
  379             case MTERASE:
  380                 error = ast_erase(stp);
  381                 break;
  382 
  383             case MTEOD:
  384                 error = ast_space(stp, ATAPI_SP_EOD, 0);
  385                 break;
  386 
  387             case MTRETENS:
  388                 error = ast_load_unload(stp, ATAPI_SS_RETENSION|ATAPI_SS_LOAD);
  389                 break;
  390 
  391             case MTFSR:         
  392             case MTBSR:
  393             case MTCACHE:
  394             case MTNOCACHE:
  395             case MTSETBSIZ:
  396             case MTSETDNSTY:
  397             case MTCOMP:
  398             default:
  399                 error = EINVAL;
  400             }
  401         }
  402         break;
  403 
  404     case MTIOCRDSPOS:
  405         {
  406             struct ast_readposition position;
  407 
  408             if ((error = ast_read_position(stp, 0, &position)))
  409                 break;
  410             *(u_int32_t *)addr = position.tape;
  411         }
  412         break;
  413 
  414     case MTIOCRDHPOS:
  415         {
  416             struct ast_readposition position;
  417 
  418             if ((error = ast_read_position(stp, 1, &position)))
  419                 break;
  420             *(u_int32_t *)addr = position.tape;
  421         }
  422         break;
  423 
  424     case MTIOCSLOCATE:
  425         error = ast_locate(stp, 0, *(u_int32_t *)addr);
  426         break;
  427 
  428     case MTIOCHLOCATE:
  429         error = ast_locate(stp, 1, *(u_int32_t *)addr);
  430         break;
  431 
  432     default:
  433         error = ENOTTY;
  434     }
  435     return error;
  436 }
  437 
  438 static void 
  439 ast_strategy(struct bio *bp)
  440 {
  441     struct ast_softc *stp = bp->bio_dev->si_drv1;
  442 
  443     if (stp->device->flags & ATA_D_DETACHING) {
  444         biofinish(bp, NULL, ENXIO);
  445         return;
  446     }
  447 
  448     /* if it's a null transfer, return immediatly. */
  449     if (bp->bio_bcount == 0) {
  450         bp->bio_resid = 0;
  451         biodone(bp);
  452         return;
  453     }
  454     if (!(bp->bio_cmd == BIO_READ) && stp->flags & F_WRITEPROTECT) {
  455         biofinish(bp, NULL, EPERM);
  456         return;
  457     }
  458         
  459     /* check for != blocksize requests */
  460     if (bp->bio_bcount % stp->blksize) {
  461         ata_prtdev(stp->device, "transfers must be multiple of %d\n",
  462                    stp->blksize);
  463         biofinish(bp, NULL, EIO);
  464         return;
  465     }
  466 
  467     /* warn about transfers bigger than the device suggests */
  468     if (bp->bio_bcount > stp->blksize * stp->cap.ctl) {  
  469         if ((stp->flags & F_CTL_WARN) == 0) {
  470             ata_prtdev(stp->device, "WARNING: CTL exceeded %ld>%d\n",
  471                        bp->bio_bcount, stp->blksize * stp->cap.ctl);
  472             stp->flags |= F_CTL_WARN;
  473         }
  474     }
  475 
  476     mtx_lock(&stp->queue_mtx);
  477     bioq_insert_tail(&stp->queue, bp);
  478     mtx_unlock(&stp->queue_mtx);
  479     ata_start(stp->device->channel);
  480 }
  481 
  482 static void 
  483 ast_start(struct ata_device *atadev)
  484 {
  485     struct ast_softc *stp = atadev->softc;
  486     struct bio *bp;
  487     struct ata_request *request;
  488     u_int32_t blkcount;
  489     int8_t ccb[16];
  490     
  491     mtx_lock(&stp->queue_mtx);
  492     bp = bioq_first(&stp->queue);
  493     if (!bp) {
  494         mtx_unlock(&stp->queue_mtx);
  495         return;
  496     }
  497     bioq_remove(&stp->queue, bp);
  498     mtx_unlock(&stp->queue_mtx);
  499 
  500     bzero(ccb, sizeof(ccb));
  501 
  502     if (bp->bio_cmd == BIO_READ)
  503         ccb[0] = ATAPI_READ;
  504     else
  505         ccb[0] = ATAPI_WRITE;
  506     
  507     blkcount = bp->bio_bcount / stp->blksize;
  508 
  509     ccb[1] = 1;
  510     ccb[2] = blkcount>>16;
  511     ccb[3] = blkcount>>8;
  512     ccb[4] = blkcount;
  513 
  514     if (!(request = ata_alloc_request())) {
  515         biofinish(bp, NULL, ENOMEM);
  516         return;
  517     }
  518     request->device = atadev;
  519     request->driver = bp;
  520     bcopy(ccb, request->u.atapi.ccb,
  521           (request->device->param->config & ATA_PROTO_MASK) == 
  522           ATA_PROTO_ATAPI_12 ? 16 : 12);
  523     request->data = bp->bio_data;
  524     request->bytecount = blkcount * stp->blksize;
  525     request->transfersize = min(request->bytecount, 65534);
  526     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 180 : 120;
  527     request->retries = 2;
  528     request->callback = ast_done;
  529     switch (bp->bio_cmd) {
  530     case BIO_READ:
  531         request->flags |= (ATA_R_ATAPI | ATA_R_READ);
  532         break;
  533     case BIO_WRITE:
  534         request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
  535         break;
  536     default:
  537         ata_prtdev(atadev, "unknown BIO operation\n");
  538         ata_free_request(request);
  539         biofinish(bp, NULL, EIO);
  540         return;
  541     }
  542     devstat_start_transaction_bio(stp->stats, bp);
  543     ata_queue_request(request);
  544 }
  545 
  546 static void 
  547 ast_done(struct ata_request *request)
  548 {
  549     struct bio *bp = request->driver;
  550     struct ast_softc *stp = request->device->softc;
  551 
  552     /* finish up transfer */
  553     if ((bp->bio_error = request->result))
  554         bp->bio_flags |= BIO_ERROR;
  555     if (bp->bio_cmd == BIO_WRITE)
  556         stp->flags |= F_DATA_WRITTEN;
  557     bp->bio_resid = bp->bio_bcount - request->donecount;
  558     ast_total += (bp->bio_bcount - bp->bio_resid);
  559     biofinish(bp, stp->stats, 0);
  560     ata_free_request(request);
  561 }
  562 
  563 static int
  564 ast_mode_sense(struct ast_softc *stp, int page, void *pagebuf, int pagesize)
  565 {
  566     int8_t ccb[16] = { ATAPI_MODE_SENSE, 0x08, page, pagesize>>8, pagesize,
  567                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  568     int error;
  569  
  570     error = ata_atapicmd(stp->device, ccb, pagebuf, pagesize, ATA_R_READ, 10);
  571 #ifdef AST_DEBUG
  572     atapi_dump("ast: mode sense ", pagebuf, pagesize);
  573 #endif
  574     return error;
  575 }
  576 
  577 static int       
  578 ast_mode_select(struct ast_softc *stp, void *pagebuf, int pagesize)
  579 {
  580     int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, pagesize>>8, pagesize,
  581                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  582      
  583 #ifdef AST_DEBUG
  584     ata_prtdev(stp->device, "modeselect pagesize=%d\n", pagesize);
  585     atapi_dump("mode select ", pagebuf, pagesize);
  586 #endif
  587     return ata_atapicmd(stp->device, ccb, pagebuf, pagesize, 0, 10);
  588 }
  589 
  590 static int
  591 ast_write_filemark(struct ast_softc *stp, u_int8_t function)
  592 {
  593     int8_t ccb[16] = { ATAPI_WEOF, 0x01, 0, 0, function, 0, 0, 0,
  594                        0, 0, 0, 0, 0, 0, 0, 0 };
  595     int error;
  596 
  597     if (stp->flags & F_ONSTREAM)
  598         ccb[4] = 0x00;          /* only flush buffers supported */
  599     else {
  600         if (function) {
  601             if (stp->flags & F_FM_WRITTEN)
  602                 stp->flags &= ~F_DATA_WRITTEN;
  603             else
  604                 stp->flags |= F_FM_WRITTEN;
  605         }
  606     }
  607     error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
  608     if (error)
  609         return error;
  610     return ast_wait_dsc(stp->device, 10*60);
  611 }
  612 
  613 static int
  614 ast_read_position(struct ast_softc *stp, int hard,
  615                   struct ast_readposition *position)
  616 {
  617     int8_t ccb[16] = { ATAPI_READ_POSITION, (hard ? 0x01 : 0), 0, 0, 0, 0, 0, 0,
  618                        0, 0, 0, 0, 0, 0, 0, 0 };
  619     int error;
  620 
  621     error = ata_atapicmd(stp->device, ccb, (caddr_t)position, 
  622                          sizeof(struct ast_readposition), ATA_R_READ, 10);
  623     position->tape = ntohl(position->tape);
  624     position->host = ntohl(position->host);
  625     return error;
  626 }
  627 
  628 static int
  629 ast_space(struct ast_softc *stp, u_int8_t function, int32_t count)
  630 {
  631     int8_t ccb[16] = { ATAPI_SPACE, function, count>>16, count>>8, count,
  632                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  633 
  634     return ata_atapicmd(stp->device, ccb, NULL, 0, 0, 60*60);
  635 }
  636 
  637 static int
  638 ast_locate(struct ast_softc *stp, int hard, u_int32_t pos)
  639 {
  640     int8_t ccb[16] = { ATAPI_LOCATE, 0x01 | (hard ? 0x4 : 0), 0,
  641                        pos>>24, pos>>16, pos>>8, pos,
  642                        0, 0, 0, 0, 0, 0, 0, 0, 0 };
  643     int error;
  644 
  645     error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
  646     if (error)
  647         return error;
  648     return ast_wait_dsc(stp->device, 60*60);
  649 }
  650 
  651 static int
  652 ast_prevent_allow(struct ast_softc *stp, int lock)
  653 {
  654     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
  655                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  656 
  657     return ata_atapicmd(stp->device, ccb, NULL, 0, 0, 30);
  658 }
  659 
  660 static int
  661 ast_load_unload(struct ast_softc *stp, u_int8_t function)
  662 {
  663     int8_t ccb[16] = { ATAPI_START_STOP, 0x01, 0, 0, function, 0, 0, 0,
  664                        0, 0, 0, 0, 0, 0, 0, 0 };
  665     int error;
  666 
  667     if ((function & ATAPI_SS_EJECT) && !stp->cap.eject)
  668         return 0;
  669     error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
  670     if (error)
  671         return error;
  672     tsleep((caddr_t)&error, PRIBIO, "astlu", 1 * hz);
  673     if (function == ATAPI_SS_EJECT)
  674         return 0;
  675     return ast_wait_dsc(stp->device, 60*60);
  676 }
  677 
  678 static int
  679 ast_rewind(struct ast_softc *stp)
  680 {
  681     int8_t ccb[16] = { ATAPI_REZERO, 0x01, 0, 0, 0, 0, 0, 0,
  682                        0, 0, 0, 0, 0, 0, 0, 0 };
  683     int error;
  684 
  685     error = ata_atapicmd(stp->device, ccb, NULL, 0, 0, 10);
  686     if (error)
  687         return error;
  688     return ast_wait_dsc(stp->device, 60*60);
  689 }
  690 
  691 static int
  692 ast_erase(struct ast_softc *stp)
  693 {
  694     int8_t ccb[16] = { ATAPI_ERASE, 3, 0, 0, 0, 0, 0, 0,
  695                        0, 0, 0, 0, 0, 0, 0, 0 };
  696     int error;
  697 
  698     if ((error = ast_rewind(stp)))
  699         return error;
  700 
  701     return ata_atapicmd(stp->device, ccb, NULL, 0, 0, 60*60);
  702 }
  703 
  704 static int
  705 ast_test_ready(struct ata_device *atadev)
  706 {
  707     int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
  708                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  709 
  710     return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
  711 }
  712 
  713 static int
  714 ast_wait_dsc(struct ata_device *atadev, int timeout)
  715 {
  716     int error = 0;
  717     int8_t ccb[16] = { ATAPI_POLL_DSC, 0, 0, 0, 0,
  718                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  719 
  720     timeout *= hz;
  721     while (timeout > 0) {
  722         error = ata_atapicmd(atadev, ccb, NULL, 0, 0, 0);
  723         if (error != EBUSY)
  724             break;
  725         tsleep(&error, PRIBIO, "atpwt", hz / 2);
  726         timeout -= (hz / 2);
  727     }
  728     return error;
  729 }

Cache object: 4a7022ffc917dee175f83242dc70b056


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