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

Cache object: f8fdc48fcd84754e022d876b97802acd


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