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/i386/isa/wst.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 Søren Schmidt
    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  * $FreeBSD$
   29  */
   30 
   31 #include "wdc.h"
   32 #include "opt_ddb.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/conf.h>
   38 #include <sys/malloc.h>
   39 #include <sys/buf.h>
   40 #include <sys/mtio.h>
   41 #include <machine/clock.h>
   42 #include <i386/isa/atapi.h>
   43 
   44 static  d_open_t    wstopen;
   45 static  d_close_t   wstclose;
   46 static  d_ioctl_t   wstioctl;
   47 static  d_strategy_t    wststrategy;
   48 
   49 #define CDEV_MAJOR 90
   50 
   51 static struct cdevsw wst_cdevsw = {
   52         /* open */      wstopen,
   53         /* close */     wstclose,
   54         /* read */      physread,
   55         /* write */     physwrite,
   56         /* ioctl */     wstioctl,
   57         /* poll */      nopoll,
   58         /* mmap */      nommap,
   59         /* strategy */  wststrategy,
   60         /* name */      "wst",
   61         /* maj */       CDEV_MAJOR,
   62         /* dump */      nodump,
   63         /* psize */     nopsize,
   64         /* flags */     0,
   65         /* bmaj */      -1
   66 };
   67 
   68 static unsigned int wst_total = 0;
   69 
   70 #define NUNIT                   (NWDC*2)
   71 #define UNIT(d)                 ((minor(d) >> 3) & 3)
   72 
   73 #define WST_OPEN                0x0001  /* The device is opened */
   74 #define WST_MEDIA_CHANGED       0x0002  /* The media have changed */
   75 #define WST_DATA_WRITTEN        0x0004  /* Data has been written */
   76 #define WST_FM_WRITTEN          0x0008  /* Filemark has been written */
   77 #define WST_DEBUG               0x0010  /* Print debug info */
   78 #define WST_CTL_WARN            0x0020  /* Have we warned about CTL wrong? */
   79 
   80 /* ATAPI tape commands not in std ATAPI command set */
   81 #define ATAPI_TAPE_REWIND               0x01
   82 #define ATAPI_TAPE_REQUEST_SENSE        0x03
   83 #define ATAPI_TAPE_READ_CMD             0x08
   84 #define ATAPI_TAPE_WRITE_CMD            0x0a
   85 #define ATAPI_TAPE_WEOF                 0x10
   86 #define     WEOF_WRITE_MASK                     0x01
   87 #define ATAPI_TAPE_SPACE_CMD            0x11
   88 #define     SP_FM                               0x01
   89 #define     SP_EOD                              0x03
   90 #define ATAPI_TAPE_ERASE                0x19
   91 #define ATAPI_TAPE_MODE_SENSE           0x1a
   92 #define ATAPI_TAPE_LOAD_UNLOAD          0x1b
   93 #define     LU_LOAD_MASK                        0x01
   94 #define     LU_RETENSION_MASK                   0x02
   95 #define     LU_EOT_MASK                         0x04
   96 
   97 #define DSC_POLL_INTERVAL       10
   98 
   99 /* 
  100  * MODE SENSE parameter header
  101  */
  102 struct wst_header {
  103     u_char  data_length;                /* Total length of data */
  104     u_char  medium_type;                /* Medium type (if any) */
  105     u_char  dsp;                        /* Device specific parameter */
  106     u_char  bdl;                        /* Block Descriptor Length */
  107 };
  108 
  109 /*
  110  * ATAPI tape drive Capabilities and Mechanical Status Page
  111  */
  112 #define ATAPI_TAPE_CAP_PAGE     0x2a
  113 
  114 struct wst_cappage {
  115     u_int   page_code           :6;     /* Page code == 0x2a */
  116     u_int   reserved1_67        :2;
  117     u_char  page_length;                /* Page Length == 0x12 */
  118     u_char  reserved2;
  119     u_char  reserved3;
  120     u_int   readonly            :1;     /* Read Only Mode */
  121     u_int   reserved4_1234      :4;
  122     u_int   reverse             :1;     /* Supports reverse direction */
  123     u_int   reserved4_67        :2;
  124     u_int   reserved5_012       :3;
  125     u_int   eformat             :1;     /* Supports ERASE formatting */
  126     u_int   reserved5_4         :1;
  127     u_int   qfa                 :1;     /* Supports QFA formats */
  128     u_int   reserved5_67        :2;
  129     u_int   lock                :1;     /* Supports locking media */
  130     u_int   locked              :1;     /* The media is locked */
  131     u_int   prevent             :1;     /* Defaults  to prevent state */
  132     u_int   eject               :1;     /* Supports eject */
  133     u_int   disconnect          :1;     /* Can break request > ctl */
  134     u_int   reserved6_5         :1;
  135     u_int   ecc                 :1;     /* Supports error correction */
  136     u_int   compress            :1;     /* Supports data compression */
  137     u_int   reserved7_0         :1;
  138     u_int   blk512              :1;     /* Supports 512b block size */
  139     u_int   blk1024             :1;     /* Supports 1024b block size */
  140     u_int   reserved7_3456      :4;
  141     u_int   slowb               :1;     /* Restricts byte count */
  142     u_short max_speed;                  /* Supported speed in KBps */
  143     u_short max_defects;                /* Max stored defect entries */
  144     u_short ctl;                        /* Continuous Transfer Limit */
  145     u_short speed;                      /* Current Speed, in KBps */
  146     u_short buffer_size;                /* Buffer Size, in 512 bytes */
  147     u_char  reserved18;
  148     u_char  reserved19;
  149 };
  150 
  151 /*
  152  * REQUEST SENSE structure
  153  */
  154 struct wst_reqsense {
  155     u_int   error_code          :7;     /* Current or deferred errors */
  156     u_int   valid               :1;     /* Follows QIC-157C */
  157     u_char  reserved1;                  /* Segment Number - Reserved */
  158     u_int   sense_key           :4;     /* Sense Key */
  159     u_int   reserved2_4         :1;     /* Reserved */
  160     u_int   ili                 :1;     /* Incorrect Length Indicator */
  161     u_int   eom                 :1;     /* End Of Medium */
  162     u_int   filemark            :1;     /* Filemark */
  163     u_int   info __attribute__((packed)); /* Cmd specific info */
  164     u_char  asl;                        /* Additional sense length (n-7) */
  165     u_int   command_specific;           /* Additional cmd specific info */
  166     u_char  asc;                        /* Additional Sense Code */
  167     u_char  ascq;                       /* Additional Sense Code Qualifier */
  168     u_char  replaceable_unit_code;      /* Field Replaceable Unit Code */
  169     u_int   sk_specific1        :7;     /* Sense Key Specific */
  170     u_int   sksv                :1;     /* Sense Key Specific info valid */
  171     u_char  sk_specific2;               /* Sense Key Specific */
  172     u_char  sk_specific3;               /* Sense Key Specific */
  173     u_char  pad[2];                     /* Padding */
  174 };
  175 
  176 struct wst {
  177     struct atapi *ata;                  /* Controller structure */
  178     int unit;                           /* IDE bus drive unit */
  179     int lun;                            /* Logical device unit */
  180     int flags;                          /* Device state flags */
  181     int blksize;                        /* Block size (512 | 1024) */
  182     struct buf_queue_head buf_queue;    /* Queue of i/o requests */
  183     struct atapi_params *param;         /* Drive parameters table */
  184     struct wst_header header;           /* MODE SENSE param header */
  185     struct wst_cappage cap;             /* Capabilities page info */
  186 };
  187 
  188 static struct wst *wsttab[NUNIT];       /* Drive info by unit number */
  189 static int wstnlun = 0;                 /* Number of config'd drives */
  190 
  191 int wstattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug);
  192 static int wst_sense(struct wst *t);
  193 static void wst_describe(struct wst *t);
  194 static void wst_poll_dsc(struct wst *t);
  195 static void wst_start(struct wst *t);
  196 static void wst_done(struct wst *t, struct buf *bp, int resid, struct atapires result);
  197 static int wst_error(struct wst *t, struct atapires result);
  198 static void wst_drvinit(void *unused);
  199 static int wst_space_cmd(struct wst *t, u_char function, u_int count);
  200 static int wst_write_filemark(struct wst *t, u_char function);
  201 static int wst_erase(struct wst *t);
  202 static int wst_load_unload(struct wst *t, u_char finction);
  203 static int wst_rewind(struct wst *t);
  204 static void wst_reset(struct wst *t);
  205 
  206 #ifdef DDB
  207 void  wst_dump(int lun, char *label, void *data, int len);
  208 
  209 void 
  210 wst_dump(int lun, char *label, void *data, int len)
  211 {
  212     u_char *p = data;
  213 
  214     printf("wst%d: %s %x", lun, label, *p++);
  215     while(--len > 0)
  216         printf("-%x", *p++);
  217     printf("\n");
  218 }
  219 #endif
  220 
  221 int 
  222 wstattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug)
  223 {
  224     struct wst *t;
  225     int lun;
  226 
  227     if (wstnlun >= NUNIT) {
  228         printf("wst: too many units\n");
  229         return(-1);
  230     }
  231     if (!atapi_request_immediate) {
  232         printf("wst: configuration error, ATAPI core code not present!\n");
  233         printf(
  234             "wst: check `options ATAPI_STATIC' in your kernel config file!\n");
  235         return(-1);
  236     }
  237     t = malloc(sizeof(struct wst), M_TEMP, M_NOWAIT);
  238     if (!t) {
  239         printf("wst: out of memory\n");
  240         return(-1);
  241     }
  242     wsttab[wstnlun] = t;
  243     bzero(t, sizeof(struct wst));
  244     bufq_init(&t->buf_queue);
  245     t->ata = ata;
  246     t->unit = unit;
  247     t->ata->use_dsc = 1;
  248     lun = t->lun = wstnlun;
  249     t->param = ap;
  250     t->flags = WST_MEDIA_CHANGED | WST_DEBUG;
  251 
  252     if (wst_sense(t))
  253         return -1;
  254 
  255     wst_describe(t);
  256     wstnlun++;
  257 
  258     make_dev(&wst_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0640, "rwst%d", t->lun);
  259     return(1);
  260 }
  261 
  262 static int 
  263 wst_sense(struct wst *t)
  264 {
  265     struct atapires result;
  266     int count;
  267     char buffer[255];
  268 
  269     /* Get drive capabilities, some drives needs this repeated */
  270     for (count = 0 ; count < 5 ; count++) {
  271         result = atapi_request_immediate(t->ata, t->unit,
  272             ATAPI_TAPE_MODE_SENSE,
  273             8, /* DBD = 1 no block descr */
  274             ATAPI_TAPE_CAP_PAGE,
  275             sizeof(buffer)>>8, sizeof(buffer),
  276             0, 0, 0, 0, 0, 0, 0,
  277             0, 0, 0, 0, buffer, sizeof(buffer));
  278         if (result.code == 0 || result.code == RES_UNDERRUN)
  279             break;
  280     }
  281 
  282     /* Some drives have shorter capabilities page. */
  283     if (result.code == RES_UNDERRUN)
  284         result.code = 0;
  285 
  286     if (result.code == 0) {
  287         bcopy(buffer, &t->header, sizeof(struct wst_header));
  288         bcopy(buffer+sizeof(struct wst_header),
  289             &t->cap, sizeof(struct wst_cappage));
  290         if (t->cap.page_code != ATAPI_TAPE_CAP_PAGE)
  291             return 1;   
  292         t->cap.max_speed = ntohs(t->cap.max_speed);
  293         t->cap.max_defects = ntohs(t->cap.max_defects);
  294         t->cap.ctl = ntohs(t->cap.ctl);
  295         t->cap.speed = ntohs(t->cap.speed);
  296         t->cap.buffer_size = ntohs(t->cap.buffer_size);
  297         t->blksize = (t->cap.blk512 ? 512 : (t->cap.blk1024 ? 1024 : 0));
  298         return 0;
  299     }
  300     return 1;
  301 }
  302 
  303 static void 
  304 wst_describe(struct wst *t)
  305 {
  306     printf("wst%d: ", t->lun);
  307     switch (t->header.medium_type) {
  308         case 0x00:      printf("Drive empty"); break;
  309         case 0x17:      printf("Travan 1 (400 Mbyte) media"); break;
  310         case 0xb6:      printf("Travan 4 (4 Gbyte) media"); break;
  311         default: printf("Unknown media (0x%x)", t->header.medium_type);
  312     }
  313     if (t->cap.readonly) printf(", readonly");
  314     if (t->cap.reverse) printf(", reverse");
  315     if (t->cap.eformat) printf(", eformat");
  316     if (t->cap.qfa) printf(", qfa");
  317     if (t->cap.lock) printf(", lock");
  318     if (t->cap.locked) printf(", locked");
  319     if (t->cap.prevent) printf(", prevent");
  320     if (t->cap.eject) printf(", eject");
  321     if (t->cap.disconnect) printf(", disconnect");
  322     if (t->cap.ecc) printf(", ecc");
  323     if (t->cap.compress) printf(", compress");
  324     if (t->cap.blk512) printf(", 512b");
  325     if (t->cap.blk1024) printf(", 1024b");
  326     if (t->cap.slowb) printf(", slowb");
  327     printf("\nwst%d: ", t->lun);
  328     printf("Max speed=%dKb/s, ", t->cap.max_speed);
  329     printf("Transfer limit=%d blocks, ", t->cap.ctl);
  330     printf("Buffer size=%d blocks", t->cap.buffer_size);
  331     printf("\n");
  332 }
  333 
  334 int
  335 wstopen(dev_t dev, int flags, int fmt, struct proc *p)
  336 {
  337     int lun = UNIT(dev);
  338     struct wst *t;
  339 
  340     /* Check that the device number and that the ATAPI driver is loaded. */
  341     if (lun >= wstnlun || !atapi_request_immediate) {
  342         printf("ENXIO lun=%d, wstnlun=%d, im=%p\n",
  343                lun, wstnlun, (void *)atapi_request_immediate);
  344         return(ENXIO);
  345     }
  346     t = wsttab[lun];
  347     if (t->flags == WST_OPEN)
  348         return EBUSY;
  349     if (wst_sense(t))
  350         printf("wst%d: Sense media type failed\n", t->lun);
  351     t->flags &= ~WST_MEDIA_CHANGED;
  352     t->flags &= ~(WST_DATA_WRITTEN | WST_FM_WRITTEN);
  353     t->flags |= WST_OPEN;
  354     return(0);
  355 }
  356 
  357 int 
  358 wstclose(dev_t dev, int flags, int fmt, struct proc *p)
  359 {
  360     int lun = UNIT(dev);
  361     struct wst *t = wsttab[lun];
  362 
  363     /* Flush buffers, some drives fail here, but they should report ctl = 0 */
  364     if (t->cap.ctl && (t->flags & WST_DATA_WRITTEN))
  365         wst_write_filemark(t, 0);
  366 
  367     /* Write filemark if data written to tape */
  368     if ((t->flags & (WST_DATA_WRITTEN | WST_FM_WRITTEN)) == WST_DATA_WRITTEN)
  369         wst_write_filemark(t, WEOF_WRITE_MASK);
  370 
  371     /* If minor is even rewind on close */
  372     if (!(minor(dev) & 0x01))   
  373         wst_rewind(t);
  374 
  375     t->flags &= ~WST_OPEN;
  376     if (t->flags & WST_DEBUG)
  377         printf("wst%d: %ud total bytes transferred\n", t->lun, wst_total);
  378     t->flags &= ~WST_CTL_WARN;
  379     return(0);
  380 }
  381 
  382 void 
  383 wststrategy(struct buf *bp)
  384 {
  385     int lun = UNIT(bp->b_dev);
  386     struct wst *t = wsttab[lun];
  387     int x;
  388 
  389     /* If it's a null transfer, return immediatly. */
  390     if (bp->b_bcount == 0) {
  391         bp->b_resid = 0;
  392         biodone(bp);
  393         return;
  394     }
  395 
  396     /* Check for != blocksize requests */
  397     if (bp->b_bcount % t->blksize) {
  398         printf("wst%d: bad request, must be multiple of %d\n", lun, t->blksize);
  399         bp->b_error = EIO;
  400         bp->b_flags |= B_ERROR;
  401         biodone(bp);
  402         return;
  403     }
  404 
  405     if (bp->b_bcount > t->blksize*t->cap.ctl) {  
  406         if ((t->flags & WST_CTL_WARN) == 0) {
  407             printf("wst%d: WARNING: CTL exceeded %ld>%d\n", 
  408                     lun, bp->b_bcount, t->blksize*t->cap.ctl);
  409             t->flags |= WST_CTL_WARN;
  410         }
  411     }
  412 
  413     x = splbio();
  414     wst_total += bp->b_bcount;
  415     bufq_insert_tail(&t->buf_queue, bp);
  416     wst_start(t);
  417     splx(x);
  418 }
  419 
  420 static void     
  421 wst_poll_dsc(struct wst *t)
  422 { 
  423     /* We should use a final timeout here SOS XXX */
  424     if (!(inb(t->ata->port + AR_STATUS) & ARS_DSC)) {
  425         timeout((timeout_t*)wst_poll_dsc, t, DSC_POLL_INTERVAL);
  426         return;
  427     }       
  428     t->ata->wait_for_dsc = 0;
  429     wakeup((caddr_t)t);
  430 }
  431 
  432 static void 
  433 wst_start(struct wst *t)
  434 {
  435     struct buf *bp = bufq_first(&t->buf_queue);
  436     u_long blk_count;
  437     u_char op_code;
  438     long byte_count;
  439     
  440     if (!bp)
  441         return;
  442 
  443     if (t->ata->wait_for_dsc)
  444         printf("wst%d: ERROR! allready waiting for DSC\n", t->lun);
  445 
  446     /* Sleep waiting for a ready drive (DSC) */
  447     if (t->ata->use_dsc && !(inb(t->ata->port + AR_STATUS) & ARS_DSC)) {
  448         t->ata->wait_for_dsc = 1;
  449         timeout((timeout_t*)wst_poll_dsc, t, DSC_POLL_INTERVAL);
  450         tsleep((caddr_t) t, 0, "wstdsc", 0);
  451     }
  452 
  453     bufq_remove(&t->buf_queue, bp);
  454     blk_count = bp->b_bcount / t->blksize;
  455 
  456     if (bp->b_flags & B_READ) {
  457         op_code = ATAPI_TAPE_READ_CMD;
  458         byte_count = bp->b_bcount;
  459     } else {
  460         op_code = ATAPI_TAPE_WRITE_CMD;
  461         t->flags |= WST_DATA_WRITTEN;
  462         byte_count = -bp->b_bcount;
  463     }
  464 
  465     atapi_request_callback(t->ata, t->unit, op_code, 1,
  466                            blk_count>>16, blk_count>>8, blk_count,
  467                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  468                            (u_char*) bp->b_data, byte_count, 
  469                            (void*)wst_done, t, bp);
  470 }
  471 
  472 static void 
  473 wst_done(struct wst *t, struct buf *bp, int resid,
  474     struct atapires result)
  475 {
  476     if (result.code) {
  477         printf("wst_done: ");
  478         wst_error(t, result);
  479         bp->b_error = EIO;
  480         bp->b_flags |= B_ERROR;
  481     }
  482     else
  483         bp->b_resid = resid;
  484 
  485     biodone(bp);
  486     /*wst_start(t);*/
  487 }
  488 
  489 static int 
  490 wst_error(struct wst *t, struct atapires result)
  491 {
  492     struct wst_reqsense sense;
  493 
  494     if (result.code != RES_ERR) {
  495         printf("wst%d: ERROR code=%d, status=%b, error=%b\n", t->lun,
  496                result.code, result.status, ARS_BITS, result.error, AER_BITS);
  497         return 1;
  498     }
  499 
  500     if ((result.error & AER_SKEY) && (result.status & ARS_CHECK)) {
  501         atapi_request_immediate(t->ata, t->unit,
  502             ATAPI_TAPE_REQUEST_SENSE,
  503             0, 0, 0, sizeof(sense),
  504             0, 0, 0, 0, 0, 0, 0,
  505             0, 0, 0, 0, (char*) &sense, sizeof(struct wst_reqsense));
  506         /*wst_dump(t->lun, "req_sense", &sense, sizeof(struct wst_reqsense));*/
  507     }
  508     switch (result.error & AER_SKEY) {
  509     case AER_SK_NOT_READY:
  510         if (result.error & ~AER_SKEY) {
  511             if (t->flags & WST_DEBUG)
  512                 printf("wst%d: not ready\n", t->lun);
  513             break;
  514         }
  515         if (!(t->flags & WST_MEDIA_CHANGED))
  516             if (t->flags & WST_DEBUG)
  517                 printf("wst%d: no media\n", t->lun);
  518         t->flags |= WST_MEDIA_CHANGED;
  519         break;
  520 
  521     case AER_SK_BLANK_CHECK:
  522         if (t->flags & WST_DEBUG)
  523             printf("wst%d: EOD encountered\n", t->lun);
  524         break;
  525 
  526     case AER_SK_MEDIUM_ERROR:
  527         if (t->flags & WST_DEBUG)
  528             printf("wst%d: nonrecovered data error\n", t->lun);
  529         break;
  530 
  531     case AER_SK_HARDWARE_ERROR:
  532         if (t->flags & WST_DEBUG)
  533             printf("wst%d: nonrecovered hardware error\n", t->lun);
  534         break;
  535 
  536     case AER_SK_ILLEGAL_REQUEST:
  537         if (t->flags & WST_DEBUG)
  538             printf("wst%d: invalid command\n", t->lun);
  539         break;
  540 
  541     case AER_SK_UNIT_ATTENTION:
  542         if (!(t->flags & WST_MEDIA_CHANGED))
  543             printf("wst%d: media changed\n", t->lun);
  544         t->flags |= WST_MEDIA_CHANGED;
  545         break;
  546 
  547     case AER_SK_DATA_PROTECT:
  548         if (t->flags & WST_DEBUG)
  549             printf("wst%d: reading read protected data\n", t->lun);
  550         break;
  551 
  552     case AER_SK_ABORTED_COMMAND:
  553         if (t->flags & WST_DEBUG)
  554             printf("wst%d: command aborted\n", t->lun);
  555         break;
  556 
  557     case AER_SK_MISCOMPARE:
  558         if (t->flags & WST_DEBUG)
  559             printf("wst%d: data don't match medium\n", t->lun);
  560         break;
  561 
  562     default:
  563         printf("wst%d: i/o error, status=%b, error=%b\n", t->lun,
  564                 result.status, ARS_BITS, result.error, AER_BITS);
  565     }
  566     printf("total=%u ERR=%x len=%ld ASC=%x ASCQ=%x\n", 
  567            wst_total, sense.error_code, (long)ntohl(sense.info), 
  568            sense.asc, sense.ascq);
  569     return 1;
  570 }
  571 
  572 int 
  573 wstioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
  574 {
  575     int lun = UNIT(dev);
  576     int error = 0;
  577     struct wst *t = wsttab[lun];
  578 
  579     switch (cmd) {
  580     case MTIOCGET:
  581         {
  582             struct mtget *g = (struct mtget *) addr;
  583 
  584             bzero(g, sizeof(struct mtget));
  585             g->mt_type = 7;
  586             g->mt_density = 1;
  587             g->mt_blksiz = t->blksize;
  588             g->mt_comp = t->cap.compress;
  589             g->mt_density0 = 0; g->mt_density1 = 0;
  590             g->mt_density2 = 0; g->mt_density3 = 0;
  591             g->mt_blksiz0 = 0; g->mt_blksiz1 = 0;
  592             g->mt_blksiz2 = 0; g->mt_blksiz3 = 0;
  593             g->mt_comp0 = 0; g->mt_comp1 = 0;
  594             g->mt_comp2 = 0; g->mt_comp3 = 0;
  595             break;       
  596         }
  597     case MTIOCTOP:
  598         {       
  599             int i;
  600             struct mtop *mt = (struct mtop *)addr;
  601 
  602             switch ((short) (mt->mt_op)) {
  603             case MTWEOF:
  604                 for (i=0; i < mt->mt_count && !error; i++)
  605                         error = wst_write_filemark(t, WEOF_WRITE_MASK);
  606                 break;
  607             case MTFSF:
  608                 if (mt->mt_count)
  609                         error = wst_space_cmd(t, SP_FM, mt->mt_count);
  610                 break;
  611             case MTBSF:
  612                 if (mt->mt_count)
  613                         error = wst_space_cmd(t, SP_FM, -(mt->mt_count));
  614                 break;
  615             case MTFSR:
  616                 error = EINVAL; break;
  617             case MTBSR:
  618                 error = EINVAL; break;
  619             case MTREW:
  620                 error = wst_rewind(t);
  621                 break;
  622             case MTOFFL:
  623 #if 1                           /* Misuse as a reset func for now */
  624                 wst_reset(t);
  625                 wst_sense(t);
  626                 wst_describe(t);
  627 #else
  628                 if (error = wst_rewind(t))
  629                     break;
  630                 error = wst_load_unload(t, !LU_LOAD_MASK);
  631 #endif
  632                     break;
  633             case MTNOP:
  634                 error = wst_write_filemark(t, 0);
  635                 break;
  636             case MTCACHE:
  637                 error = EINVAL; break;
  638             case MTNOCACHE:
  639                 error = EINVAL; break;
  640             case MTSETBSIZ:
  641                 error = EINVAL; break;
  642             case MTSETDNSTY:
  643                 error = EINVAL; break;
  644             case MTERASE:
  645                 error = wst_erase(t);
  646                 break;
  647             case MTEOD:
  648                 error = wst_space_cmd(t, SP_EOD, 0);
  649                 break;
  650             case MTCOMP:
  651                 error = EINVAL; break;
  652             case MTRETENS:
  653                 error = wst_load_unload(t, LU_RETENSION_MASK|LU_LOAD_MASK);
  654                 break;
  655             default:
  656                 error = EINVAL;
  657             }
  658             return error;
  659         }
  660     default:
  661         return(ENOTTY);
  662     }
  663     return(error);
  664 }
  665 
  666 static int
  667 wst_space_cmd(struct wst *t, u_char function, u_int count)
  668 {
  669     struct atapires result;
  670 
  671     result = atapi_request_wait(t->ata, t->unit, 
  672                                 ATAPI_TAPE_SPACE_CMD, function,
  673                                 count>>16, count>>8, count,
  674                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
  675     if (result.code) {
  676         printf("wst_space_cmd: ");
  677         wst_error(t, result);
  678         return EIO;
  679     }
  680     return 0;
  681 }
  682 
  683 static int
  684 wst_write_filemark(struct wst *t, u_char function)
  685 {
  686     struct atapires result;
  687 
  688     if (function) {
  689         if (t->flags & WST_FM_WRITTEN)
  690             t->flags &= ~WST_DATA_WRITTEN;
  691         else
  692             t->flags |= WST_FM_WRITTEN;
  693     }
  694     result = atapi_request_wait(t->ata, t->unit, 
  695                                 ATAPI_TAPE_WEOF, 0, 0, 0, function,
  696                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
  697     if (result.code) {
  698         printf("wst_write_filemark: ");
  699         wst_error(t, result);
  700         return EIO;
  701     }
  702     return 0;
  703 }
  704 
  705 static int
  706 wst_load_unload(struct wst *t, u_char function)
  707 {
  708     struct atapires result;
  709 
  710     result = atapi_request_wait(t->ata, t->unit, 
  711                                 ATAPI_TAPE_LOAD_UNLOAD, 0, 0, 0, function,
  712                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
  713     if (result.code) {
  714         printf("wst_load_unload: ");
  715         wst_error(t, result);
  716         return EIO;
  717     }
  718     return 0;
  719 }
  720 
  721 static int
  722 wst_erase(struct wst *t)
  723 {
  724     int error;
  725     struct atapires result;
  726 
  727     error = wst_rewind(t);
  728     if (error)
  729         return error;
  730     result = atapi_request_wait(t->ata, t->unit, 
  731                                 ATAPI_TAPE_ERASE, 3, 0, 0, 0,
  732                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  733                                 NULL, 0);
  734     if (result.code) {
  735         printf("wst_erase: ");
  736         wst_error(t, result);
  737         return EIO;
  738     }
  739     return 0;
  740 }
  741 
  742 static int
  743 wst_rewind(struct wst *t)
  744 {
  745     struct atapires result;       
  746 
  747     result = atapi_request_wait(t->ata, t->unit,
  748                                     ATAPI_TAPE_REWIND, 0, 0, 0, 0,
  749                                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  750                                     NULL, 0);
  751     if (result.code) {
  752         printf("wst_rewind: ");
  753         wst_error(t, result);
  754         return EIO;
  755     }
  756     return 0;
  757 }
  758 
  759 static void
  760 wst_reset(struct wst *t)
  761 {
  762     outb(t->ata->port + AR_DRIVE, ARD_DRIVE1);
  763     DELAY(30);
  764     outb(t->ata->port + AR_COMMAND, 0x08);
  765     DELAY(30);
  766 }
  767 
  768 static void 
  769 wst_drvinit(void *unused)
  770 {
  771     cdevsw_add(&wst_cdevsw);
  772 }
  773 
  774 SYSINIT(wstdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,wst_drvinit,NULL)

Cache object: c6d68897a922911347083e027740774e


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