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/cam/scsi/scsi_da.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  * Implementation of SCSI Direct Access Peripheral driver for CAM.
    3  *
    4  * Copyright (c) 1997 Justin T. Gibbs.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer,
   12  *    without modification, immediately at the beginning of the file.
   13  * 2. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/9.1/sys/cam/scsi/scsi_da.c 239742 2012-08-27 18:12:08Z jimharris $");
   31 
   32 #include <sys/param.h>
   33 
   34 #ifdef _KERNEL
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/bio.h>
   38 #include <sys/sysctl.h>
   39 #include <sys/taskqueue.h>
   40 #include <sys/lock.h>
   41 #include <sys/mutex.h>
   42 #include <sys/conf.h>
   43 #include <sys/devicestat.h>
   44 #include <sys/eventhandler.h>
   45 #include <sys/malloc.h>
   46 #include <sys/cons.h>
   47 #include <geom/geom.h>
   48 #include <geom/geom_disk.h>
   49 #endif /* _KERNEL */
   50 
   51 #ifndef _KERNEL
   52 #include <stdio.h>
   53 #include <string.h>
   54 #endif /* _KERNEL */
   55 
   56 #include <cam/cam.h>
   57 #include <cam/cam_ccb.h>
   58 #include <cam/cam_periph.h>
   59 #include <cam/cam_xpt_periph.h>
   60 #include <cam/cam_sim.h>
   61 
   62 #include <cam/scsi/scsi_message.h>
   63 
   64 #ifndef _KERNEL 
   65 #include <cam/scsi/scsi_da.h>
   66 #endif /* !_KERNEL */
   67 
   68 #ifdef _KERNEL
   69 typedef enum {
   70         DA_STATE_PROBE,
   71         DA_STATE_PROBE2,
   72         DA_STATE_NORMAL
   73 } da_state;
   74 
   75 typedef enum {
   76         DA_FLAG_PACK_INVALID    = 0x001,
   77         DA_FLAG_NEW_PACK        = 0x002,
   78         DA_FLAG_PACK_LOCKED     = 0x004,
   79         DA_FLAG_PACK_REMOVABLE  = 0x008,
   80         DA_FLAG_NEED_OTAG       = 0x020,
   81         DA_FLAG_WENT_IDLE       = 0x040,
   82         DA_FLAG_RETRY_UA        = 0x080,
   83         DA_FLAG_OPEN            = 0x100,
   84         DA_FLAG_SCTX_INIT       = 0x200,
   85         DA_FLAG_CAN_RC16        = 0x400
   86 } da_flags;
   87 
   88 typedef enum {
   89         DA_Q_NONE               = 0x00,
   90         DA_Q_NO_SYNC_CACHE      = 0x01,
   91         DA_Q_NO_6_BYTE          = 0x02,
   92         DA_Q_NO_PREVENT         = 0x04,
   93         DA_Q_4K                 = 0x08
   94 } da_quirks;
   95 
   96 typedef enum {
   97         DA_CCB_PROBE            = 0x01,
   98         DA_CCB_PROBE2           = 0x02,
   99         DA_CCB_BUFFER_IO        = 0x03,
  100         DA_CCB_WAITING          = 0x04,
  101         DA_CCB_DUMP             = 0x05,
  102         DA_CCB_DELETE           = 0x06,
  103         DA_CCB_TYPE_MASK        = 0x0F,
  104         DA_CCB_RETRY_UA         = 0x10
  105 } da_ccb_state;
  106 
  107 typedef enum {
  108         DA_DELETE_NONE,
  109         DA_DELETE_DISABLE,
  110         DA_DELETE_ZERO,
  111         DA_DELETE_WS10,
  112         DA_DELETE_WS16,
  113         DA_DELETE_UNMAP,
  114         DA_DELETE_MAX = DA_DELETE_UNMAP
  115 } da_delete_methods;
  116 
  117 static const char *da_delete_method_names[] =
  118     { "NONE", "DISABLE", "ZERO", "WS10", "WS16", "UNMAP" };
  119 
  120 /* Offsets into our private area for storing information */
  121 #define ccb_state       ppriv_field0
  122 #define ccb_bp          ppriv_ptr1
  123 
  124 struct disk_params {
  125         u_int8_t  heads;
  126         u_int32_t cylinders;
  127         u_int8_t  secs_per_track;
  128         u_int32_t secsize;      /* Number of bytes/sector */
  129         u_int64_t sectors;      /* total number sectors */
  130         u_int     stripesize;
  131         u_int     stripeoffset;
  132 };
  133 
  134 #define UNMAP_MAX_RANGES        512
  135 
  136 struct da_softc {
  137         struct   bio_queue_head bio_queue;
  138         struct   bio_queue_head delete_queue;
  139         struct   bio_queue_head delete_run_queue;
  140         SLIST_ENTRY(da_softc) links;
  141         LIST_HEAD(, ccb_hdr) pending_ccbs;
  142         da_state state;
  143         da_flags flags; 
  144         da_quirks quirks;
  145         int      minimum_cmd_size;
  146         int      error_inject;
  147         int      ordered_tag_count;
  148         int      outstanding_cmds;
  149         int      unmap_max_ranges;
  150         int      unmap_max_lba;
  151         int      delete_running;
  152         da_delete_methods        delete_method;
  153         struct   disk_params params;
  154         struct   disk *disk;
  155         union    ccb saved_ccb;
  156         struct task             sysctl_task;
  157         struct sysctl_ctx_list  sysctl_ctx;
  158         struct sysctl_oid       *sysctl_tree;
  159         struct callout          sendordered_c;
  160         uint64_t wwpn;
  161         uint8_t  unmap_buf[UNMAP_MAX_RANGES * 16 + 8];
  162 };
  163 
  164 struct da_quirk_entry {
  165         struct scsi_inquiry_pattern inq_pat;
  166         da_quirks quirks;
  167 };
  168 
  169 static const char quantum[] = "QUANTUM";
  170 static const char microp[] = "MICROP";
  171 
  172 static struct da_quirk_entry da_quirk_table[] =
  173 {
  174         /* SPI, FC devices */
  175         {
  176                 /*
  177                  * Fujitsu M2513A MO drives.
  178                  * Tested devices: M2513A2 firmware versions 1200 & 1300.
  179                  * (dip switch selects whether T_DIRECT or T_OPTICAL device)
  180                  * Reported by: W.Scholten <whs@xs4all.nl>
  181                  */
  182                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
  183                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  184         },
  185         {
  186                 /* See above. */
  187                 {T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
  188                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  189         },
  190         {
  191                 /*
  192                  * This particular Fujitsu drive doesn't like the
  193                  * synchronize cache command.
  194                  * Reported by: Tom Jackson <toj@gorilla.net>
  195                  */
  196                 {T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
  197                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  198         },
  199         {
  200                 /*
  201                  * This drive doesn't like the synchronize cache command
  202                  * either.  Reported by: Matthew Jacob <mjacob@feral.com>
  203                  * in NetBSD PR kern/6027, August 24, 1998.
  204                  */
  205                 {T_DIRECT, SIP_MEDIA_FIXED, microp, "2217*", "*"},
  206                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  207         },
  208         {
  209                 /*
  210                  * This drive doesn't like the synchronize cache command
  211                  * either.  Reported by: Hellmuth Michaelis (hm@kts.org)
  212                  * (PR 8882).
  213                  */
  214                 {T_DIRECT, SIP_MEDIA_FIXED, microp, "2112*", "*"},
  215                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  216         },
  217         {
  218                 /*
  219                  * Doesn't like the synchronize cache command.
  220                  * Reported by: Blaz Zupan <blaz@gold.amis.net>
  221                  */
  222                 {T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"},
  223                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  224         },
  225         {
  226                 /*
  227                  * Doesn't like the synchronize cache command.
  228                  * Reported by: Blaz Zupan <blaz@gold.amis.net>
  229                  */
  230                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "MAVERICK 540S", "*"},
  231                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  232         },
  233         {
  234                 /*
  235                  * Doesn't like the synchronize cache command.
  236                  */
  237                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"},
  238                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  239         },
  240         {
  241                 /*
  242                  * Doesn't like the synchronize cache command.
  243                  * Reported by: walter@pelissero.de
  244                  */
  245                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS540S", "*"},
  246                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  247         },
  248         {
  249                 /*
  250                  * Doesn't work correctly with 6 byte reads/writes.
  251                  * Returns illegal request, and points to byte 9 of the
  252                  * 6-byte CDB.
  253                  * Reported by:  Adam McDougall <bsdx@spawnet.com>
  254                  */
  255                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 4*", "*"},
  256                 /*quirks*/ DA_Q_NO_6_BYTE
  257         },
  258         {
  259                 /* See above. */
  260                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 2*", "*"},
  261                 /*quirks*/ DA_Q_NO_6_BYTE
  262         },
  263         {
  264                 /*
  265                  * Doesn't like the synchronize cache command.
  266                  * Reported by: walter@pelissero.de
  267                  */
  268                 {T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CP3500*", "*"},
  269                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  270         },
  271         {
  272                 /*
  273                  * The CISS RAID controllers do not support SYNC_CACHE
  274                  */
  275                 {T_DIRECT, SIP_MEDIA_FIXED, "COMPAQ", "RAID*", "*"},
  276                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  277         },
  278         /* USB mass storage devices supported by umass(4) */
  279         {
  280                 /*
  281                  * EXATELECOM (Sigmatel) i-Bead 100/105 USB Flash MP3 Player
  282                  * PR: kern/51675
  283                  */
  284                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "EXATEL", "i-BEAD10*", "*"},
  285                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  286         },
  287         {
  288                 /*
  289                  * Power Quotient Int. (PQI) USB flash key
  290                  * PR: kern/53067
  291                  */
  292                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "USB Flash Disk*",
  293                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  294         },
  295         {
  296                 /*
  297                  * Creative Nomad MUVO mp3 player (USB)
  298                  * PR: kern/53094
  299                  */
  300                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "NOMAD_MUVO", "*"},
  301                 /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  302         },
  303         {
  304                 /*
  305                  * Jungsoft NEXDISK USB flash key
  306                  * PR: kern/54737
  307                  */
  308                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "JUNGSOFT", "NEXDISK*", "*"},
  309                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  310         },
  311         {
  312                 /*
  313                  * FreeDik USB Mini Data Drive
  314                  * PR: kern/54786
  315                  */
  316                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FreeDik*", "Mini Data Drive",
  317                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  318         },
  319         {
  320                 /*
  321                  * Sigmatel USB Flash MP3 Player
  322                  * PR: kern/57046
  323                  */
  324                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SigmaTel", "MSCN", "*"},
  325                 /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  326         },
  327         {
  328                 /*
  329                  * Neuros USB Digital Audio Computer
  330                  * PR: kern/63645
  331                  */
  332                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "NEUROS", "dig. audio comp.",
  333                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  334         },
  335         {
  336                 /*
  337                  * SEAGRAND NP-900 MP3 Player
  338                  * PR: kern/64563
  339                  */
  340                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SEAGRAND", "NP-900*", "*"},
  341                 /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  342         },
  343         {
  344                 /*
  345                  * iRiver iFP MP3 player (with UMS Firmware)
  346                  * PR: kern/54881, i386/63941, kern/66124
  347                  */
  348                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "iRiver", "iFP*", "*"},
  349                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  350         },
  351         {
  352                 /*
  353                  * Frontier Labs NEX IA+ Digital Audio Player, rev 1.10/0.01
  354                  * PR: kern/70158
  355                  */
  356                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FL" , "Nex*", "*"},
  357                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  358         },
  359         {
  360                 /*
  361                  * ZICPlay USB MP3 Player with FM
  362                  * PR: kern/75057
  363                  */
  364                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "ACTIONS*" , "USB DISK*", "*"},
  365                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  366         },
  367         {
  368                 /*
  369                  * TEAC USB floppy mechanisms
  370                  */
  371                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "TEAC" , "FD-05*", "*"},
  372                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  373         },
  374         {
  375                 /*
  376                  * Kingston DataTraveler II+ USB Pen-Drive.
  377                  * Reported by: Pawel Jakub Dawidek <pjd@FreeBSD.org>
  378                  */
  379                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston" , "DataTraveler II+",
  380                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  381         },
  382         {
  383                 /*
  384                  * Motorola E398 Mobile Phone (TransFlash memory card).
  385                  * Reported by: Wojciech A. Koszek <dunstan@FreeBSD.czest.pl>
  386                  * PR: usb/89889
  387                  */
  388                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Motorola" , "Motorola Phone",
  389                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  390         },
  391         {
  392                 /*
  393                  * Qware BeatZkey! Pro
  394                  * PR: usb/79164
  395                  */
  396                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "GENERIC", "USB DISK DEVICE",
  397                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  398         },
  399         {
  400                 /*
  401                  * Time DPA20B 1GB MP3 Player
  402                  * PR: usb/81846
  403                  */
  404                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB2.0*", "(FS) FLASH DISK*",
  405                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  406         },
  407         {
  408                 /*
  409                  * Samsung USB key 128Mb
  410                  * PR: usb/90081
  411                  */
  412                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB-DISK", "FreeDik-FlashUsb",
  413                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  414         },
  415         {
  416                 /*
  417                  * Kingston DataTraveler 2.0 USB Flash memory.
  418                  * PR: usb/89196
  419                  */
  420                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler 2.0",
  421                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  422         },
  423         {
  424                 /*
  425                  * Creative MUVO Slim mp3 player (USB)
  426                  * PR: usb/86131
  427                  */
  428                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "MuVo Slim",
  429                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  430                 },
  431         {
  432                 /*
  433                  * United MP5512 Portable MP3 Player (2-in-1 USB DISK/MP3)
  434                  * PR: usb/80487
  435                  */
  436                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "MUSIC DISK",
  437                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  438         },
  439         {
  440                 /*
  441                  * SanDisk Micro Cruzer 128MB
  442                  * PR: usb/75970
  443                  */
  444                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SanDisk" , "Micro Cruzer",
  445                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  446         },
  447         {
  448                 /*
  449                  * TOSHIBA TransMemory USB sticks
  450                  * PR: kern/94660
  451                  */
  452                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "TOSHIBA", "TransMemory",
  453                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  454         },
  455         {
  456                 /*
  457                  * PNY USB Flash keys
  458                  * PR: usb/75578, usb/72344, usb/65436 
  459                  */
  460                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "*" , "USB DISK*",
  461                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  462         },
  463         {
  464                 /*
  465                  * Genesys 6-in-1 Card Reader
  466                  * PR: usb/94647
  467                  */
  468                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "STORAGE DEVICE*",
  469                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  470         },
  471         {
  472                 /*
  473                  * Rekam Digital CAMERA
  474                  * PR: usb/98713
  475                  */
  476                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "CAMERA*", "4MP-9J6*",
  477                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  478         },
  479         {
  480                 /*
  481                  * iRiver H10 MP3 player
  482                  * PR: usb/102547
  483                  */
  484                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "H10*",
  485                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  486         },
  487         {
  488                 /*
  489                  * iRiver U10 MP3 player
  490                  * PR: usb/92306
  491                  */
  492                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "U10*",
  493                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  494         },
  495         {
  496                 /*
  497                  * X-Micro Flash Disk
  498                  * PR: usb/96901
  499                  */
  500                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "X-Micro", "Flash Disk",
  501                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  502         },
  503         {
  504                 /*
  505                  * EasyMP3 EM732X USB 2.0 Flash MP3 Player
  506                  * PR: usb/96546
  507                  */
  508                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "EM732X", "MP3 Player*",
  509                 "1.00"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  510         },
  511         {
  512                 /*
  513                  * Denver MP3 player
  514                  * PR: usb/107101
  515                  */
  516                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "DENVER", "MP3 PLAYER",
  517                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  518         },
  519         {
  520                 /*
  521                  * Philips USB Key Audio KEY013
  522                  * PR: usb/68412
  523                  */
  524                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "PHILIPS", "Key*", "*"},
  525                 /*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
  526         },
  527         {
  528                 /*
  529                  * JNC MP3 Player
  530                  * PR: usb/94439
  531                  */
  532                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "JNC*" , "MP3 Player*",
  533                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  534         },
  535         {
  536                 /*
  537                  * SAMSUNG MP0402H
  538                  * PR: usb/108427
  539                  */
  540                 {T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "MP0402H", "*"},
  541                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  542         },
  543         {
  544                 /*
  545                  * I/O Magic USB flash - Giga Bank
  546                  * PR: usb/108810
  547                  */
  548                 {T_DIRECT, SIP_MEDIA_FIXED, "GS-Magic", "stor*", "*"},
  549                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  550         },
  551         {
  552                 /*
  553                  * JoyFly 128mb USB Flash Drive
  554                  * PR: 96133
  555                  */
  556                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "Flash Disk*",
  557                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  558         },
  559         {
  560                 /*
  561                  * ChipsBnk usb stick
  562                  * PR: 103702
  563                  */
  564                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "ChipsBnk", "USB*",
  565                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  566         },
  567         {
  568                 /*
  569                  * Storcase (Kingston) InfoStation IFS FC2/SATA-R 201A
  570                  * PR: 129858
  571                  */
  572                 {T_DIRECT, SIP_MEDIA_FIXED, "IFS", "FC2/SATA-R*",
  573                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  574         },
  575         {
  576                 /*
  577                  * Samsung YP-U3 mp3-player
  578                  * PR: 125398
  579                  */
  580                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Samsung", "YP-U3",
  581                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  582         },
  583         {
  584                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Netac", "OnlyDisk*",
  585                  "2000"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  586         },
  587         {
  588                 /*
  589                  * Sony Cyber-Shot DSC cameras
  590                  * PR: usb/137035
  591                  */
  592                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"},
  593                 /*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
  594         },
  595         /* ATA/SATA devices over SAS/USB/... */
  596         {
  597                 /* Hitachi Advanced Format (4k) drives */
  598                 { T_DIRECT, SIP_MEDIA_FIXED, "Hitachi", "H??????????E3*", "*" },
  599                 /*quirks*/DA_Q_4K
  600         },
  601         {
  602                 /* Samsung Advanced Format (4k) drives */
  603                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG HD155UI*", "*" },
  604                 /*quirks*/DA_Q_4K
  605         },
  606         {
  607                 /* Samsung Advanced Format (4k) drives */
  608                 { T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HD155UI*", "*" },
  609                 /*quirks*/DA_Q_4K
  610         },
  611         {
  612                 /* Samsung Advanced Format (4k) drives */
  613                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG HD204UI*", "*" },
  614                 /*quirks*/DA_Q_4K
  615         },
  616         {
  617                 /* Samsung Advanced Format (4k) drives */
  618                 { T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HD204UI*", "*" },
  619                 /*quirks*/DA_Q_4K
  620         },
  621         {
  622                 /* Seagate Barracuda Green Advanced Format (4k) drives */
  623                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST????DL*", "*" },
  624                 /*quirks*/DA_Q_4K
  625         },
  626         {
  627                 /* Seagate Barracuda Green Advanced Format (4k) drives */
  628                 { T_DIRECT, SIP_MEDIA_FIXED, "ST????DL", "*", "*" },
  629                 /*quirks*/DA_Q_4K
  630         },
  631         {
  632                 /* Seagate Barracuda Green Advanced Format (4k) drives */
  633                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST???DM*", "*" },
  634                 /*quirks*/DA_Q_4K
  635         },
  636         {
  637                 /* Seagate Barracuda Green Advanced Format (4k) drives */
  638                 { T_DIRECT, SIP_MEDIA_FIXED, "ST???DM*", "*", "*" },
  639                 /*quirks*/DA_Q_4K
  640         },
  641         {
  642                 /* Seagate Barracuda Green Advanced Format (4k) drives */
  643                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST????DM*", "*" },
  644                 /*quirks*/DA_Q_4K
  645         },
  646         {
  647                 /* Seagate Barracuda Green Advanced Format (4k) drives */
  648                 { T_DIRECT, SIP_MEDIA_FIXED, "ST????DM", "*", "*" },
  649                 /*quirks*/DA_Q_4K
  650         },
  651         {
  652                 /* Seagate Momentus Advanced Format (4k) drives */
  653                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9500423AS*", "*" },
  654                 /*quirks*/DA_Q_4K
  655         },
  656         {
  657                 /* Seagate Momentus Advanced Format (4k) drives */
  658                 { T_DIRECT, SIP_MEDIA_FIXED, "ST950042", "3AS*", "*" },
  659                 /*quirks*/DA_Q_4K
  660         },
  661         {
  662                 /* Seagate Momentus Advanced Format (4k) drives */
  663                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9500424AS*", "*" },
  664                 /*quirks*/DA_Q_4K
  665         },
  666         {
  667                 /* Seagate Momentus Advanced Format (4k) drives */
  668                 { T_DIRECT, SIP_MEDIA_FIXED, "ST950042", "4AS*", "*" },
  669                 /*quirks*/DA_Q_4K
  670         },
  671         {
  672                 /* Seagate Momentus Advanced Format (4k) drives */
  673                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9640423AS*", "*" },
  674                 /*quirks*/DA_Q_4K
  675         },
  676         {
  677                 /* Seagate Momentus Advanced Format (4k) drives */
  678                 { T_DIRECT, SIP_MEDIA_FIXED, "ST964042", "3AS*", "*" },
  679                 /*quirks*/DA_Q_4K
  680         },
  681         {
  682                 /* Seagate Momentus Advanced Format (4k) drives */
  683                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9640424AS*", "*" },
  684                 /*quirks*/DA_Q_4K
  685         },
  686         {
  687                 /* Seagate Momentus Advanced Format (4k) drives */
  688                 { T_DIRECT, SIP_MEDIA_FIXED, "ST964042", "4AS*", "*" },
  689                 /*quirks*/DA_Q_4K
  690         },
  691         {
  692                 /* Seagate Momentus Advanced Format (4k) drives */
  693                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750420AS*", "*" },
  694                 /*quirks*/DA_Q_4K
  695         },
  696         {
  697                 /* Seagate Momentus Advanced Format (4k) drives */
  698                 { T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "0AS*", "*" },
  699                 /*quirks*/DA_Q_4K
  700         },
  701         {
  702                 /* Seagate Momentus Advanced Format (4k) drives */
  703                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750422AS*", "*" },
  704                 /*quirks*/DA_Q_4K
  705         },
  706         {
  707                 /* Seagate Momentus Advanced Format (4k) drives */
  708                 { T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "2AS*", "*" },
  709                 /*quirks*/DA_Q_4K
  710         },
  711         {
  712                 /* Seagate Momentus Advanced Format (4k) drives */
  713                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750423AS*", "*" },
  714                 /*quirks*/DA_Q_4K
  715         },
  716         {
  717                 /* Seagate Momentus Advanced Format (4k) drives */
  718                 { T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "3AS*", "*" },
  719                 /*quirks*/DA_Q_4K
  720         },
  721         {
  722                 /* Seagate Momentus Thin Advanced Format (4k) drives */
  723                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST???LT*", "*" },
  724                 /*quirks*/DA_Q_4K
  725         },
  726         {
  727                 /* Seagate Momentus Thin Advanced Format (4k) drives */
  728                 { T_DIRECT, SIP_MEDIA_FIXED, "ST???LT*", "*", "*" },
  729                 /*quirks*/DA_Q_4K
  730         },
  731         {
  732                 /* WDC Caviar Green Advanced Format (4k) drives */
  733                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD????RS*", "*" },
  734                 /*quirks*/DA_Q_4K
  735         },
  736         {
  737                 /* WDC Caviar Green Advanced Format (4k) drives */
  738                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "??RS*", "*" },
  739                 /*quirks*/DA_Q_4K
  740         },
  741         {
  742                 /* WDC Caviar Green Advanced Format (4k) drives */
  743                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD????RX*", "*" },
  744                 /*quirks*/DA_Q_4K
  745         },
  746         {
  747                 /* WDC Caviar Green Advanced Format (4k) drives */
  748                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "??RX*", "*" },
  749                 /*quirks*/DA_Q_4K
  750         },
  751         {
  752                 /* WDC Caviar Green Advanced Format (4k) drives */
  753                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD??????RS*", "*" },
  754                 /*quirks*/DA_Q_4K
  755         },
  756         {
  757                 /* WDC Caviar Green Advanced Format (4k) drives */
  758                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "????RS*", "*" },
  759                 /*quirks*/DA_Q_4K
  760         },
  761         {
  762                 /* WDC Caviar Green Advanced Format (4k) drives */
  763                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD??????RX*", "*" },
  764                 /*quirks*/DA_Q_4K
  765         },
  766         {
  767                 /* WDC Caviar Green Advanced Format (4k) drives */
  768                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "????RX*", "*" },
  769                 /*quirks*/DA_Q_4K
  770         },
  771         {
  772                 /* WDC Scorpio Black Advanced Format (4k) drives */
  773                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD???PKT*", "*" },
  774                 /*quirks*/DA_Q_4K
  775         },
  776         {
  777                 /* WDC Scorpio Black Advanced Format (4k) drives */
  778                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "?PKT*", "*" },
  779                 /*quirks*/DA_Q_4K
  780         },
  781         {
  782                 /* WDC Scorpio Black Advanced Format (4k) drives */
  783                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD?????PKT*", "*" },
  784                 /*quirks*/DA_Q_4K
  785         },
  786         {
  787                 /* WDC Scorpio Black Advanced Format (4k) drives */
  788                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PKT*", "*" },
  789                 /*quirks*/DA_Q_4K
  790         },
  791         {
  792                 /* WDC Scorpio Blue Advanced Format (4k) drives */
  793                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD???PVT*", "*" },
  794                 /*quirks*/DA_Q_4K
  795         },
  796         {
  797                 /* WDC Scorpio Blue Advanced Format (4k) drives */
  798                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "?PVT*", "*" },
  799                 /*quirks*/DA_Q_4K
  800         },
  801         {
  802                 /* WDC Scorpio Blue Advanced Format (4k) drives */
  803                 { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD?????PVT*", "*" },
  804                 /*quirks*/DA_Q_4K
  805         },
  806         {
  807                 /* WDC Scorpio Blue Advanced Format (4k) drives */
  808                 { T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PVT*", "*" },
  809                 /*quirks*/DA_Q_4K
  810         },
  811         {
  812                 /*
  813                  * Olympus FE-210 camera
  814                  */
  815                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "FE210*",
  816                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  817         },
  818         {
  819                 /*
  820                  * LG UP3S MP3 player
  821                  */
  822                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "LG", "UP3S",
  823                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  824         },
  825         {
  826                 /*
  827                  * Laser MP3-2GA13 MP3 player
  828                  */
  829                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "(HS) Flash Disk",
  830                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  831         },
  832 };
  833 
  834 static  disk_strategy_t dastrategy;
  835 static  dumper_t        dadump;
  836 static  periph_init_t   dainit;
  837 static  void            daasync(void *callback_arg, u_int32_t code,
  838                                 struct cam_path *path, void *arg);
  839 static  void            dasysctlinit(void *context, int pending);
  840 static  int             dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
  841 static  int             dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
  842 static  periph_ctor_t   daregister;
  843 static  periph_dtor_t   dacleanup;
  844 static  periph_start_t  dastart;
  845 static  periph_oninv_t  daoninvalidate;
  846 static  void            dadone(struct cam_periph *periph,
  847                                union ccb *done_ccb);
  848 static  int             daerror(union ccb *ccb, u_int32_t cam_flags,
  849                                 u_int32_t sense_flags);
  850 static void             daprevent(struct cam_periph *periph, int action);
  851 static int              dagetcapacity(struct cam_periph *periph);
  852 static void             dasetgeom(struct cam_periph *periph, uint32_t block_len,
  853                                   uint64_t maxsector, u_int lbppbe, u_int lalba);
  854 static timeout_t        dasendorderedtag;
  855 static void             dashutdown(void *arg, int howto);
  856 
  857 #ifndef DA_DEFAULT_TIMEOUT
  858 #define DA_DEFAULT_TIMEOUT 60   /* Timeout in seconds */
  859 #endif
  860 
  861 #ifndef DA_DEFAULT_RETRY
  862 #define DA_DEFAULT_RETRY        4
  863 #endif
  864 
  865 #ifndef DA_DEFAULT_SEND_ORDERED
  866 #define DA_DEFAULT_SEND_ORDERED 1
  867 #endif
  868 
  869 
  870 static int da_retry_count = DA_DEFAULT_RETRY;
  871 static int da_default_timeout = DA_DEFAULT_TIMEOUT;
  872 static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
  873 
  874 SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
  875             "CAM Direct Access Disk driver");
  876 SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW,
  877            &da_retry_count, 0, "Normal I/O retry count");
  878 TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count);
  879 SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
  880            &da_default_timeout, 0, "Normal I/O timeout (in seconds)");
  881 TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
  882 SYSCTL_INT(_kern_cam_da, OID_AUTO, da_send_ordered, CTLFLAG_RW,
  883            &da_send_ordered, 0, "Send Ordered Tags");
  884 TUNABLE_INT("kern.cam.da.da_send_ordered", &da_send_ordered);
  885 
  886 /*
  887  * DA_ORDEREDTAG_INTERVAL determines how often, relative
  888  * to the default timeout, we check to see whether an ordered
  889  * tagged transaction is appropriate to prevent simple tag
  890  * starvation.  Since we'd like to ensure that there is at least
  891  * 1/2 of the timeout length left for a starved transaction to
  892  * complete after we've sent an ordered tag, we must poll at least
  893  * four times in every timeout period.  This takes care of the worst
  894  * case where a starved transaction starts during an interval that
  895  * meets the requirement "don't send an ordered tag" test so it takes
  896  * us two intervals to determine that a tag must be sent.
  897  */
  898 #ifndef DA_ORDEREDTAG_INTERVAL
  899 #define DA_ORDEREDTAG_INTERVAL 4
  900 #endif
  901 
  902 static struct periph_driver dadriver =
  903 {
  904         dainit, "da",
  905         TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
  906 };
  907 
  908 PERIPHDRIVER_DECLARE(da, dadriver);
  909 
  910 MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
  911 
  912 static int
  913 daopen(struct disk *dp)
  914 {
  915         struct cam_periph *periph;
  916         struct da_softc *softc;
  917         int unit;
  918         int error;
  919 
  920         periph = (struct cam_periph *)dp->d_drv1;
  921         if (periph == NULL) {
  922                 return (ENXIO); 
  923         }
  924 
  925         if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
  926                 return (ENXIO);
  927         }
  928 
  929         cam_periph_lock(periph);
  930         if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
  931                 cam_periph_unlock(periph);
  932                 cam_periph_release(periph);
  933                 return (error);
  934         }
  935 
  936         unit = periph->unit_number;
  937         softc = (struct da_softc *)periph->softc;
  938         softc->flags |= DA_FLAG_OPEN;
  939 
  940         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
  941             ("daopen\n"));
  942 
  943         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
  944                 /* Invalidate our pack information. */
  945                 softc->flags &= ~DA_FLAG_PACK_INVALID;
  946         }
  947 
  948         error = dagetcapacity(periph);
  949 
  950         if (error == 0) {
  951 
  952                 softc->disk->d_sectorsize = softc->params.secsize;
  953                 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
  954                 softc->disk->d_stripesize = softc->params.stripesize;
  955                 softc->disk->d_stripeoffset = softc->params.stripeoffset;
  956                 /* XXX: these are not actually "firmware" values, so they may be wrong */
  957                 softc->disk->d_fwsectors = softc->params.secs_per_track;
  958                 softc->disk->d_fwheads = softc->params.heads;
  959                 softc->disk->d_devstat->block_size = softc->params.secsize;
  960                 softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
  961                 if (softc->delete_method > DA_DELETE_DISABLE)
  962                         softc->disk->d_flags |= DISKFLAG_CANDELETE;
  963                 else
  964                         softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
  965 
  966                 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
  967                     (softc->quirks & DA_Q_NO_PREVENT) == 0)
  968                         daprevent(periph, PR_PREVENT);
  969         } else
  970                 softc->flags &= ~DA_FLAG_OPEN;
  971 
  972         cam_periph_unhold(periph);
  973         cam_periph_unlock(periph);
  974 
  975         if (error != 0) {
  976                 cam_periph_release(periph);
  977         }
  978         return (error);
  979 }
  980 
  981 static int
  982 daclose(struct disk *dp)
  983 {
  984         struct  cam_periph *periph;
  985         struct  da_softc *softc;
  986 
  987         periph = (struct cam_periph *)dp->d_drv1;
  988         if (periph == NULL)
  989                 return (0);     
  990 
  991         cam_periph_lock(periph);
  992         if (cam_periph_hold(periph, PRIBIO) != 0) {
  993                 cam_periph_unlock(periph);
  994                 cam_periph_release(periph);
  995                 return (0);
  996         }
  997 
  998         softc = (struct da_softc *)periph->softc;
  999 
 1000         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
 1001             ("daclose\n"));
 1002 
 1003         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0
 1004          && (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
 1005                 union   ccb *ccb;
 1006 
 1007                 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 1008 
 1009                 scsi_synchronize_cache(&ccb->csio,
 1010                                        /*retries*/1,
 1011                                        /*cbfcnp*/dadone,
 1012                                        MSG_SIMPLE_Q_TAG,
 1013                                        /*begin_lba*/0,/* Cover the whole disk */
 1014                                        /*lb_count*/0,
 1015                                        SSD_FULL_SIZE,
 1016                                        5 * 60 * 1000);
 1017 
 1018                 cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
 1019                                   /*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
 1020                                   softc->disk->d_devstat);
 1021                 xpt_release_ccb(ccb);
 1022 
 1023         }
 1024 
 1025         if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
 1026                 if ((softc->quirks & DA_Q_NO_PREVENT) == 0)
 1027                         daprevent(periph, PR_ALLOW);
 1028                 /*
 1029                  * If we've got removeable media, mark the blocksize as
 1030                  * unavailable, since it could change when new media is
 1031                  * inserted.
 1032                  */
 1033                 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
 1034         }
 1035 
 1036         softc->flags &= ~DA_FLAG_OPEN;
 1037         cam_periph_unhold(periph);
 1038         cam_periph_unlock(periph);
 1039         cam_periph_release(periph);
 1040         return (0);     
 1041 }
 1042 
 1043 static void
 1044 daschedule(struct cam_periph *periph)
 1045 {
 1046         struct da_softc *softc = (struct da_softc *)periph->softc;
 1047         uint32_t prio;
 1048 
 1049         /* Check if cam_periph_getccb() was called. */
 1050         prio = periph->immediate_priority;
 1051 
 1052         /* Check if we have more work to do. */
 1053         if (bioq_first(&softc->bio_queue) ||
 1054             (!softc->delete_running && bioq_first(&softc->delete_queue))) {
 1055                 prio = CAM_PRIORITY_NORMAL;
 1056         }
 1057 
 1058         /* Schedule CCB if any of above is true. */
 1059         if (prio != CAM_PRIORITY_NONE)
 1060                 xpt_schedule(periph, prio);
 1061 }
 1062 
 1063 /*
 1064  * Actually translate the requested transfer into one the physical driver
 1065  * can understand.  The transfer is described by a buf and will include
 1066  * only one physical transfer.
 1067  */
 1068 static void
 1069 dastrategy(struct bio *bp)
 1070 {
 1071         struct cam_periph *periph;
 1072         struct da_softc *softc;
 1073         
 1074         periph = (struct cam_periph *)bp->bio_disk->d_drv1;
 1075         if (periph == NULL) {
 1076                 biofinish(bp, NULL, ENXIO);
 1077                 return;
 1078         }
 1079         softc = (struct da_softc *)periph->softc;
 1080 
 1081         cam_periph_lock(periph);
 1082 
 1083         /*
 1084          * If the device has been made invalid, error out
 1085          */
 1086         if ((softc->flags & DA_FLAG_PACK_INVALID)) {
 1087                 cam_periph_unlock(periph);
 1088                 biofinish(bp, NULL, ENXIO);
 1089                 return;
 1090         }
 1091 
 1092         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastrategy(%p)\n", bp));
 1093 
 1094         /*
 1095          * Place it in the queue of disk activities for this disk
 1096          */
 1097         if (bp->bio_cmd == BIO_DELETE) {
 1098                 if (bp->bio_bcount == 0)
 1099                         biodone(bp);
 1100                 else
 1101                         bioq_disksort(&softc->delete_queue, bp);
 1102         } else
 1103                 bioq_disksort(&softc->bio_queue, bp);
 1104 
 1105         /*
 1106          * Schedule ourselves for performing the work.
 1107          */
 1108         daschedule(periph);
 1109         cam_periph_unlock(periph);
 1110 
 1111         return;
 1112 }
 1113 
 1114 static int
 1115 dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
 1116 {
 1117         struct      cam_periph *periph;
 1118         struct      da_softc *softc;
 1119         u_int       secsize;
 1120         struct      ccb_scsiio csio;
 1121         struct      disk *dp;
 1122         int         error = 0;
 1123 
 1124         dp = arg;
 1125         periph = dp->d_drv1;
 1126         if (periph == NULL)
 1127                 return (ENXIO);
 1128         softc = (struct da_softc *)periph->softc;
 1129         cam_periph_lock(periph);
 1130         secsize = softc->params.secsize;
 1131         
 1132         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
 1133                 cam_periph_unlock(periph);
 1134                 return (ENXIO);
 1135         }
 1136 
 1137         if (length > 0) {
 1138                 xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 1139                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
 1140                 scsi_read_write(&csio,
 1141                                 /*retries*/0,
 1142                                 dadone,
 1143                                 MSG_ORDERED_Q_TAG,
 1144                                 /*read*/FALSE,
 1145                                 /*byte2*/0,
 1146                                 /*minimum_cmd_size*/ softc->minimum_cmd_size,
 1147                                 offset / secsize,
 1148                                 length / secsize,
 1149                                 /*data_ptr*/(u_int8_t *) virtual,
 1150                                 /*dxfer_len*/length,
 1151                                 /*sense_len*/SSD_FULL_SIZE,
 1152                                 da_default_timeout * 1000);
 1153                 xpt_polled_action((union ccb *)&csio);
 1154 
 1155                 error = cam_periph_error((union ccb *)&csio,
 1156                     0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
 1157                 if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
 1158                         cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
 1159                             /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
 1160                 if (error != 0)
 1161                         printf("Aborting dump due to I/O error.\n");
 1162                 cam_periph_unlock(periph);
 1163                 return (error);
 1164         }
 1165                 
 1166         /*
 1167          * Sync the disk cache contents to the physical media.
 1168          */
 1169         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
 1170 
 1171                 xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 1172                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
 1173                 scsi_synchronize_cache(&csio,
 1174                                        /*retries*/0,
 1175                                        /*cbfcnp*/dadone,
 1176                                        MSG_SIMPLE_Q_TAG,
 1177                                        /*begin_lba*/0,/* Cover the whole disk */
 1178                                        /*lb_count*/0,
 1179                                        SSD_FULL_SIZE,
 1180                                        5 * 60 * 1000);
 1181                 xpt_polled_action((union ccb *)&csio);
 1182 
 1183                 error = cam_periph_error((union ccb *)&csio,
 1184                     0, SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR, NULL);
 1185                 if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
 1186                         cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
 1187                             /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
 1188                 if (error != 0)
 1189                         xpt_print(periph->path, "Synchronize cache failed\n");
 1190         }
 1191         cam_periph_unlock(periph);
 1192         return (error);
 1193 }
 1194 
 1195 static int
 1196 dagetattr(struct bio *bp)
 1197 {
 1198         int ret = -1;
 1199         struct cam_periph *periph;
 1200 
 1201         if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
 1202                 return ENXIO;
 1203         periph = (struct cam_periph *)bp->bio_disk->d_drv1;
 1204         if (periph->path == NULL)
 1205                 return ENXIO;
 1206 
 1207         ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute,
 1208             periph->path);
 1209         if (ret == 0)
 1210                 bp->bio_completed = bp->bio_length;
 1211         return ret;
 1212 }
 1213 
 1214 static void
 1215 dainit(void)
 1216 {
 1217         cam_status status;
 1218 
 1219         /*
 1220          * Install a global async callback.  This callback will
 1221          * receive async callbacks like "new device found".
 1222          */
 1223         status = xpt_register_async(AC_FOUND_DEVICE, daasync, NULL, NULL);
 1224 
 1225         if (status != CAM_REQ_CMP) {
 1226                 printf("da: Failed to attach master async callback "
 1227                        "due to status 0x%x!\n", status);
 1228         } else if (da_send_ordered) {
 1229 
 1230                 /* Register our shutdown event handler */
 1231                 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown, 
 1232                                            NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
 1233                     printf("dainit: shutdown event registration failed!\n");
 1234         }
 1235 }
 1236 
 1237 /*
 1238  * Callback from GEOM, called when it has finished cleaning up its
 1239  * resources.
 1240  */
 1241 static void
 1242 dadiskgonecb(struct disk *dp)
 1243 {
 1244         struct cam_periph *periph;
 1245 
 1246         periph = (struct cam_periph *)dp->d_drv1;
 1247 
 1248         cam_periph_release(periph);
 1249 }
 1250 
 1251 static void
 1252 daoninvalidate(struct cam_periph *periph)
 1253 {
 1254         struct da_softc *softc;
 1255 
 1256         softc = (struct da_softc *)periph->softc;
 1257 
 1258         /*
 1259          * De-register any async callbacks.
 1260          */
 1261         xpt_register_async(0, daasync, periph, periph->path);
 1262 
 1263         softc->flags |= DA_FLAG_PACK_INVALID;
 1264 
 1265         /*
 1266          * Return all queued I/O with ENXIO.
 1267          * XXX Handle any transactions queued to the card
 1268          *     with XPT_ABORT_CCB.
 1269          */
 1270         bioq_flush(&softc->bio_queue, NULL, ENXIO);
 1271         bioq_flush(&softc->delete_queue, NULL, ENXIO);
 1272 
 1273         /*
 1274          * Tell GEOM that we've gone away, we'll get a callback when it is
 1275          * done cleaning up its resources.
 1276          */
 1277         disk_gone(softc->disk);
 1278 
 1279         xpt_print(periph->path, "lost device - %d outstanding, %d refs\n",
 1280                   softc->outstanding_cmds, periph->refcount);
 1281 }
 1282 
 1283 static void
 1284 dacleanup(struct cam_periph *periph)
 1285 {
 1286         struct da_softc *softc;
 1287 
 1288         softc = (struct da_softc *)periph->softc;
 1289 
 1290         xpt_print(periph->path, "removing device entry\n");
 1291         cam_periph_unlock(periph);
 1292 
 1293         /*
 1294          * If we can't free the sysctl tree, oh well...
 1295          */
 1296         if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
 1297             && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
 1298                 xpt_print(periph->path, "can't remove sysctl context\n");
 1299         }
 1300 
 1301         disk_destroy(softc->disk);
 1302         callout_drain(&softc->sendordered_c);
 1303         free(softc, M_DEVBUF);
 1304         cam_periph_lock(periph);
 1305 }
 1306 
 1307 static void
 1308 daasync(void *callback_arg, u_int32_t code,
 1309         struct cam_path *path, void *arg)
 1310 {
 1311         struct cam_periph *periph;
 1312 
 1313         periph = (struct cam_periph *)callback_arg;
 1314         switch (code) {
 1315         case AC_FOUND_DEVICE:
 1316         {
 1317                 struct ccb_getdev *cgd;
 1318                 cam_status status;
 1319  
 1320                 cgd = (struct ccb_getdev *)arg;
 1321                 if (cgd == NULL)
 1322                         break;
 1323 
 1324                 if (cgd->protocol != PROTO_SCSI)
 1325                         break;
 1326 
 1327                 if (SID_TYPE(&cgd->inq_data) != T_DIRECT
 1328                     && SID_TYPE(&cgd->inq_data) != T_RBC
 1329                     && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
 1330                         break;
 1331 
 1332                 /*
 1333                  * Allocate a peripheral instance for
 1334                  * this device and start the probe
 1335                  * process.
 1336                  */
 1337                 status = cam_periph_alloc(daregister, daoninvalidate,
 1338                                           dacleanup, dastart,
 1339                                           "da", CAM_PERIPH_BIO,
 1340                                           cgd->ccb_h.path, daasync,
 1341                                           AC_FOUND_DEVICE, cgd);
 1342 
 1343                 if (status != CAM_REQ_CMP
 1344                  && status != CAM_REQ_INPROG)
 1345                         printf("daasync: Unable to attach to new device "
 1346                                 "due to status 0x%x\n", status);
 1347                 return;
 1348         }
 1349         case AC_ADVINFO_CHANGED:
 1350         {
 1351                 uintptr_t buftype;
 1352 
 1353                 buftype = (uintptr_t)arg;
 1354                 if (buftype == CDAI_TYPE_PHYS_PATH) {
 1355                         struct da_softc *softc;
 1356 
 1357                         softc = periph->softc;
 1358                         disk_attr_changed(softc->disk, "GEOM::physpath",
 1359                                           M_NOWAIT);
 1360                 }
 1361                 break;
 1362         }
 1363         case AC_SENT_BDR:
 1364         case AC_BUS_RESET:
 1365         {
 1366                 struct da_softc *softc;
 1367                 struct ccb_hdr *ccbh;
 1368 
 1369                 softc = (struct da_softc *)periph->softc;
 1370                 /*
 1371                  * Don't fail on the expected unit attention
 1372                  * that will occur.
 1373                  */
 1374                 softc->flags |= DA_FLAG_RETRY_UA;
 1375                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
 1376                         ccbh->ccb_state |= DA_CCB_RETRY_UA;
 1377                 break;
 1378         }
 1379         default:
 1380                 break;
 1381         }
 1382         cam_periph_async(periph, code, path, arg);
 1383 }
 1384 
 1385 static void
 1386 dasysctlinit(void *context, int pending)
 1387 {
 1388         struct cam_periph *periph;
 1389         struct da_softc *softc;
 1390         char tmpstr[80], tmpstr2[80];
 1391         struct ccb_trans_settings cts;
 1392 
 1393         periph = (struct cam_periph *)context;
 1394         /*
 1395          * periph was held for us when this task was enqueued
 1396          */
 1397         if (periph->flags & CAM_PERIPH_INVALID) {
 1398                 cam_periph_release(periph);
 1399                 return;
 1400         }
 1401 
 1402         softc = (struct da_softc *)periph->softc;
 1403         snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
 1404         snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
 1405 
 1406         sysctl_ctx_init(&softc->sysctl_ctx);
 1407         softc->flags |= DA_FLAG_SCTX_INIT;
 1408         softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
 1409                 SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
 1410                 CTLFLAG_RD, 0, tmpstr);
 1411         if (softc->sysctl_tree == NULL) {
 1412                 printf("dasysctlinit: unable to allocate sysctl tree\n");
 1413                 cam_periph_release(periph);
 1414                 return;
 1415         }
 1416 
 1417         /*
 1418          * Now register the sysctl handler, so the user can change the value on
 1419          * the fly.
 1420          */
 1421         SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 1422                 OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW,
 1423                 &softc->delete_method, 0, dadeletemethodsysctl, "A",
 1424                 "BIO_DELETE execution method");
 1425         SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 1426                 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
 1427                 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
 1428                 "Minimum CDB size");
 1429 
 1430         SYSCTL_ADD_INT(&softc->sysctl_ctx,
 1431                        SYSCTL_CHILDREN(softc->sysctl_tree),
 1432                        OID_AUTO,
 1433                        "error_inject",
 1434                        CTLFLAG_RW,
 1435                        &softc->error_inject,
 1436                        0,
 1437                        "error_inject leaf");
 1438 
 1439 
 1440         /*
 1441          * Add some addressing info.
 1442          */
 1443         memset(&cts, 0, sizeof (cts));
 1444         xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1);
 1445         cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
 1446         cts.type = CTS_TYPE_CURRENT_SETTINGS;
 1447         cam_periph_lock(periph);
 1448         xpt_action((union ccb *)&cts);
 1449         cam_periph_unlock(periph);
 1450         if (cts.ccb_h.status != CAM_REQ_CMP) {
 1451                 cam_periph_release(periph);
 1452                 return;
 1453         }
 1454         if (cts.protocol == PROTO_SCSI && cts.transport == XPORT_FC) {
 1455                 struct ccb_trans_settings_fc *fc = &cts.xport_specific.fc;
 1456                 if (fc->valid & CTS_FC_VALID_WWPN) {
 1457                         softc->wwpn = fc->wwpn;
 1458                         SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
 1459                             SYSCTL_CHILDREN(softc->sysctl_tree),
 1460                             OID_AUTO, "wwpn", CTLFLAG_RD,
 1461                             &softc->wwpn, "World Wide Port Name");
 1462                 }
 1463         }
 1464         cam_periph_release(periph);
 1465 }
 1466 
 1467 static int
 1468 dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
 1469 {
 1470         int error, value;
 1471 
 1472         value = *(int *)arg1;
 1473 
 1474         error = sysctl_handle_int(oidp, &value, 0, req);
 1475 
 1476         if ((error != 0)
 1477          || (req->newptr == NULL))
 1478                 return (error);
 1479 
 1480         /*
 1481          * Acceptable values here are 6, 10, 12 or 16.
 1482          */
 1483         if (value < 6)
 1484                 value = 6;
 1485         else if ((value > 6)
 1486               && (value <= 10))
 1487                 value = 10;
 1488         else if ((value > 10)
 1489               && (value <= 12))
 1490                 value = 12;
 1491         else if (value > 12)
 1492                 value = 16;
 1493 
 1494         *(int *)arg1 = value;
 1495 
 1496         return (0);
 1497 }
 1498 
 1499 static int
 1500 dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
 1501 {
 1502         char buf[16];
 1503         int error;
 1504         const char *p;
 1505         int i, value;
 1506 
 1507         value = *(int *)arg1;
 1508         if (value < 0 || value > DA_DELETE_MAX)
 1509                 p = "UNKNOWN";
 1510         else
 1511                 p = da_delete_method_names[value];
 1512         strncpy(buf, p, sizeof(buf));
 1513         error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
 1514         if (error != 0 || req->newptr == NULL)
 1515                 return (error);
 1516         for (i = 0; i <= DA_DELETE_MAX; i++) {
 1517                 if (strcmp(buf, da_delete_method_names[i]) != 0)
 1518                         continue;
 1519                 *(int *)arg1 = i;
 1520                 return (0);
 1521         }
 1522         return (EINVAL);
 1523 }
 1524 
 1525 static cam_status
 1526 daregister(struct cam_periph *periph, void *arg)
 1527 {
 1528         struct da_softc *softc;
 1529         struct ccb_pathinq cpi;
 1530         struct ccb_getdev *cgd;
 1531         char tmpstr[80];
 1532         caddr_t match;
 1533 
 1534         cgd = (struct ccb_getdev *)arg;
 1535         if (periph == NULL) {
 1536                 printf("daregister: periph was NULL!!\n");
 1537                 return(CAM_REQ_CMP_ERR);
 1538         }
 1539 
 1540         if (cgd == NULL) {
 1541                 printf("daregister: no getdev CCB, can't register device\n");
 1542                 return(CAM_REQ_CMP_ERR);
 1543         }
 1544 
 1545         softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
 1546             M_NOWAIT|M_ZERO);
 1547 
 1548         if (softc == NULL) {
 1549                 printf("daregister: Unable to probe new device. "
 1550                        "Unable to allocate softc\n");                           
 1551                 return(CAM_REQ_CMP_ERR);
 1552         }
 1553 
 1554         LIST_INIT(&softc->pending_ccbs);
 1555         softc->state = DA_STATE_PROBE;
 1556         bioq_init(&softc->bio_queue);
 1557         bioq_init(&softc->delete_queue);
 1558         bioq_init(&softc->delete_run_queue);
 1559         if (SID_IS_REMOVABLE(&cgd->inq_data))
 1560                 softc->flags |= DA_FLAG_PACK_REMOVABLE;
 1561         softc->unmap_max_ranges = UNMAP_MAX_RANGES;
 1562         softc->unmap_max_lba = 1024*1024*2;
 1563 
 1564         periph->softc = softc;
 1565 
 1566         /*
 1567          * See if this device has any quirks.
 1568          */
 1569         match = cam_quirkmatch((caddr_t)&cgd->inq_data,
 1570                                (caddr_t)da_quirk_table,
 1571                                sizeof(da_quirk_table)/sizeof(*da_quirk_table),
 1572                                sizeof(*da_quirk_table), scsi_inquiry_match);
 1573 
 1574         if (match != NULL)
 1575                 softc->quirks = ((struct da_quirk_entry *)match)->quirks;
 1576         else
 1577                 softc->quirks = DA_Q_NONE;
 1578 
 1579         /* Check if the SIM does not want 6 byte commands */
 1580         bzero(&cpi, sizeof(cpi));
 1581         xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 1582         cpi.ccb_h.func_code = XPT_PATH_INQ;
 1583         xpt_action((union ccb *)&cpi);
 1584         if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
 1585                 softc->quirks |= DA_Q_NO_6_BYTE;
 1586 
 1587         TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
 1588 
 1589         /*
 1590          * Take an exclusive refcount on the periph while dastart is called
 1591          * to finish the probe.  The reference will be dropped in dadone at
 1592          * the end of probe.
 1593          */
 1594         (void)cam_periph_hold(periph, PRIBIO);
 1595 
 1596         /*
 1597          * Schedule a periodic event to occasionally send an
 1598          * ordered tag to a device.
 1599          */
 1600         callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
 1601         callout_reset(&softc->sendordered_c,
 1602             (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
 1603             dasendorderedtag, softc);
 1604 
 1605         mtx_unlock(periph->sim->mtx);
 1606         /*
 1607          * RBC devices don't have to support READ(6), only READ(10).
 1608          */
 1609         if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
 1610                 softc->minimum_cmd_size = 10;
 1611         else
 1612                 softc->minimum_cmd_size = 6;
 1613 
 1614         /*
 1615          * Load the user's default, if any.
 1616          */
 1617         snprintf(tmpstr, sizeof(tmpstr), "kern.cam.da.%d.minimum_cmd_size",
 1618                  periph->unit_number);
 1619         TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
 1620 
 1621         /*
 1622          * 6, 10, 12 and 16 are the currently permissible values.
 1623          */
 1624         if (softc->minimum_cmd_size < 6)
 1625                 softc->minimum_cmd_size = 6;
 1626         else if ((softc->minimum_cmd_size > 6)
 1627               && (softc->minimum_cmd_size <= 10))
 1628                 softc->minimum_cmd_size = 10;
 1629         else if ((softc->minimum_cmd_size > 10)
 1630               && (softc->minimum_cmd_size <= 12))
 1631                 softc->minimum_cmd_size = 12;
 1632         else if (softc->minimum_cmd_size > 12)
 1633                 softc->minimum_cmd_size = 16;
 1634 
 1635         /* Predict whether device may support READ CAPACITY(16). */
 1636         if (SID_ANSI_REV(&cgd->inq_data) >= SCSI_REV_SPC3) {
 1637                 softc->flags |= DA_FLAG_CAN_RC16;
 1638                 softc->state = DA_STATE_PROBE2;
 1639         }
 1640 
 1641         /*
 1642          * Register this media as a disk.
 1643          */
 1644         softc->disk = disk_alloc();
 1645         softc->disk->d_devstat = devstat_new_entry(periph->periph_name,
 1646                           periph->unit_number, 0,
 1647                           DEVSTAT_BS_UNAVAILABLE,
 1648                           SID_TYPE(&cgd->inq_data) |
 1649                           XPORT_DEVSTAT_TYPE(cpi.transport),
 1650                           DEVSTAT_PRIORITY_DISK);
 1651         softc->disk->d_open = daopen;
 1652         softc->disk->d_close = daclose;
 1653         softc->disk->d_strategy = dastrategy;
 1654         softc->disk->d_dump = dadump;
 1655         softc->disk->d_getattr = dagetattr;
 1656         softc->disk->d_gone = dadiskgonecb;
 1657         softc->disk->d_name = "da";
 1658         softc->disk->d_drv1 = periph;
 1659         if (cpi.maxio == 0)
 1660                 softc->disk->d_maxsize = DFLTPHYS;      /* traditional default */
 1661         else if (cpi.maxio > MAXPHYS)
 1662                 softc->disk->d_maxsize = MAXPHYS;       /* for safety */
 1663         else
 1664                 softc->disk->d_maxsize = cpi.maxio;
 1665         softc->disk->d_unit = periph->unit_number;
 1666         softc->disk->d_flags = 0;
 1667         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
 1668                 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
 1669         cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
 1670             sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
 1671         strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
 1672         cam_strvis(&softc->disk->d_descr[strlen(softc->disk->d_descr)],
 1673             cgd->inq_data.product, sizeof(cgd->inq_data.product),
 1674             sizeof(softc->disk->d_descr) - strlen(softc->disk->d_descr));
 1675         softc->disk->d_hba_vendor = cpi.hba_vendor;
 1676         softc->disk->d_hba_device = cpi.hba_device;
 1677         softc->disk->d_hba_subvendor = cpi.hba_subvendor;
 1678         softc->disk->d_hba_subdevice = cpi.hba_subdevice;
 1679 
 1680         /*
 1681          * Acquire a reference to the periph before we register with GEOM.
 1682          * We'll release this reference once GEOM calls us back (via
 1683          * dadiskgonecb()) telling us that our provider has been freed.
 1684          */
 1685         if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
 1686                 xpt_print(periph->path, "%s: lost periph during "
 1687                           "registration!\n", __func__);
 1688                 mtx_lock(periph->sim->mtx);
 1689                 return (CAM_REQ_CMP_ERR);
 1690         }
 1691 
 1692         disk_create(softc->disk, DISK_VERSION);
 1693         mtx_lock(periph->sim->mtx);
 1694 
 1695         /*
 1696          * Add async callbacks for events of interest.
 1697          * I don't bother checking if this fails as,
 1698          * in most cases, the system will function just
 1699          * fine without them and the only alternative
 1700          * would be to not attach the device on failure.
 1701          */
 1702         xpt_register_async(AC_SENT_BDR | AC_BUS_RESET
 1703                          | AC_LOST_DEVICE | AC_ADVINFO_CHANGED,
 1704                            daasync, periph, periph->path);
 1705 
 1706         /*
 1707          * Emit an attribute changed notification just in case 
 1708          * physical path information arrived before our async
 1709          * event handler was registered, but after anyone attaching
 1710          * to our disk device polled it.
 1711          */
 1712         disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT);
 1713 
 1714         xpt_schedule(periph, CAM_PRIORITY_DEV);
 1715 
 1716         return(CAM_REQ_CMP);
 1717 }
 1718 
 1719 static void
 1720 dastart(struct cam_periph *periph, union ccb *start_ccb)
 1721 {
 1722         struct da_softc *softc;
 1723 
 1724         softc = (struct da_softc *)periph->softc;
 1725 
 1726         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastart\n"));
 1727 
 1728         switch (softc->state) {
 1729         case DA_STATE_NORMAL:
 1730         {
 1731                 struct bio *bp, *bp1;
 1732                 uint8_t tag_code;
 1733 
 1734                 /* Execute immediate CCB if waiting. */
 1735                 if (periph->immediate_priority <= periph->pinfo.priority) {
 1736                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 1737                                         ("queuing for immediate ccb\n"));
 1738                         start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
 1739                         SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
 1740                                           periph_links.sle);
 1741                         periph->immediate_priority = CAM_PRIORITY_NONE;
 1742                         wakeup(&periph->ccb_list);
 1743                         /* May have more work to do, so ensure we stay scheduled */
 1744                         daschedule(periph);
 1745                         break;
 1746                 }
 1747 
 1748                 /* Run BIO_DELETE if not running yet. */
 1749                 if (!softc->delete_running &&
 1750                     (bp = bioq_first(&softc->delete_queue)) != NULL) {
 1751                     uint64_t lba;
 1752                     u_int count;
 1753 
 1754                     if (softc->delete_method == DA_DELETE_UNMAP) {
 1755                         uint8_t *buf = softc->unmap_buf;
 1756                         uint64_t lastlba = (uint64_t)-1;
 1757                         uint32_t lastcount = 0;
 1758                         int blocks = 0, off, ranges = 0;
 1759 
 1760                         softc->delete_running = 1;
 1761                         bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
 1762                         bp1 = bp;
 1763                         do {
 1764                                 bioq_remove(&softc->delete_queue, bp1);
 1765                                 if (bp1 != bp)
 1766                                         bioq_insert_tail(&softc->delete_run_queue, bp1);
 1767                                 lba = bp1->bio_pblkno;
 1768                                 count = bp1->bio_bcount / softc->params.secsize;
 1769 
 1770                                 /* Try to extend the previous range. */
 1771                                 if (lba == lastlba) {
 1772                                         lastcount += count;
 1773                                         off = (ranges - 1) * 16 + 8;
 1774                                         scsi_ulto4b(lastcount, &buf[off + 8]);
 1775                                 } else if (count > 0) {
 1776                                         off = ranges * 16 + 8;
 1777                                         scsi_u64to8b(lba, &buf[off + 0]);
 1778                                         scsi_ulto4b(count, &buf[off + 8]);
 1779                                         lastcount = count;
 1780                                         ranges++;
 1781                                 }
 1782                                 blocks += count;
 1783                                 lastlba = lba + count;
 1784                                 bp1 = bioq_first(&softc->delete_queue);
 1785                                 if (bp1 == NULL ||
 1786                                     ranges >= softc->unmap_max_ranges ||
 1787                                     blocks + bp1->bio_bcount /
 1788                                      softc->params.secsize > softc->unmap_max_lba)
 1789                                         break;
 1790                         } while (1);
 1791                         scsi_ulto2b(ranges * 16 + 6, &buf[0]);
 1792                         scsi_ulto2b(ranges * 16, &buf[2]);
 1793 
 1794                         scsi_unmap(&start_ccb->csio,
 1795                                         /*retries*/da_retry_count,
 1796                                         /*cbfcnp*/dadone,
 1797                                         /*tag_action*/MSG_SIMPLE_Q_TAG,
 1798                                         /*byte2*/0,
 1799                                         /*data_ptr*/ buf,
 1800                                         /*dxfer_len*/ ranges * 16 + 8,
 1801                                         /*sense_len*/SSD_FULL_SIZE,
 1802                                         da_default_timeout * 1000);
 1803                         start_ccb->ccb_h.ccb_state = DA_CCB_DELETE;
 1804                         goto out;
 1805                     } else if (softc->delete_method == DA_DELETE_ZERO ||
 1806                                softc->delete_method == DA_DELETE_WS10 ||
 1807                                softc->delete_method == DA_DELETE_WS16) {
 1808                         softc->delete_running = 1;
 1809                         lba = bp->bio_pblkno;
 1810                         count = 0;
 1811                         bp1 = bp;
 1812                         do {
 1813                                 bioq_remove(&softc->delete_queue, bp1);
 1814                                 if (bp1 != bp)
 1815                                         bioq_insert_tail(&softc->delete_run_queue, bp1);
 1816                                 count += bp1->bio_bcount / softc->params.secsize;
 1817                                 bp1 = bioq_first(&softc->delete_queue);
 1818                                 if (bp1 == NULL ||
 1819                                     lba + count != bp1->bio_pblkno ||
 1820                                     count + bp1->bio_bcount /
 1821                                      softc->params.secsize > 0xffff)
 1822                                         break;
 1823                         } while (1);
 1824 
 1825                         scsi_write_same(&start_ccb->csio,
 1826                                         /*retries*/da_retry_count,
 1827                                         /*cbfcnp*/dadone,
 1828                                         /*tag_action*/MSG_SIMPLE_Q_TAG,
 1829                                         /*byte2*/softc->delete_method ==
 1830                                             DA_DELETE_ZERO ? 0 : SWS_UNMAP,
 1831                                         softc->delete_method ==
 1832                                             DA_DELETE_WS16 ? 16 : 10,
 1833                                         /*lba*/lba,
 1834                                         /*block_count*/count,
 1835                                         /*data_ptr*/ __DECONST(void *,
 1836                                             zero_region),
 1837                                         /*dxfer_len*/ softc->params.secsize,
 1838                                         /*sense_len*/SSD_FULL_SIZE,
 1839                                         da_default_timeout * 1000);
 1840                         start_ccb->ccb_h.ccb_state = DA_CCB_DELETE;
 1841                         goto out;
 1842                     } else {
 1843                         bioq_flush(&softc->delete_queue, NULL, 0);
 1844                         /* FALLTHROUGH */
 1845                     }
 1846                 }
 1847 
 1848                 /* Run regular command. */
 1849                 bp = bioq_takefirst(&softc->bio_queue);
 1850                 if (bp == NULL) {
 1851                         xpt_release_ccb(start_ccb);
 1852                         break;
 1853                 }
 1854 
 1855                 if ((bp->bio_flags & BIO_ORDERED) != 0 ||
 1856                     (softc->flags & DA_FLAG_NEED_OTAG) != 0) {
 1857                         softc->flags &= ~DA_FLAG_NEED_OTAG;
 1858                         softc->ordered_tag_count++;
 1859                         tag_code = MSG_ORDERED_Q_TAG;
 1860                 } else {
 1861                         tag_code = MSG_SIMPLE_Q_TAG;
 1862                 }
 1863 
 1864                 switch (bp->bio_cmd) {
 1865                 case BIO_READ:
 1866                 case BIO_WRITE:
 1867                         scsi_read_write(&start_ccb->csio,
 1868                                         /*retries*/da_retry_count,
 1869                                         /*cbfcnp*/dadone,
 1870                                         /*tag_action*/tag_code,
 1871                                         /*read_op*/bp->bio_cmd
 1872                                                 == BIO_READ,
 1873                                         /*byte2*/0,
 1874                                         softc->minimum_cmd_size,
 1875                                         /*lba*/bp->bio_pblkno,
 1876                                         /*block_count*/bp->bio_bcount /
 1877                                         softc->params.secsize,
 1878                                         /*data_ptr*/ bp->bio_data,
 1879                                         /*dxfer_len*/ bp->bio_bcount,
 1880                                         /*sense_len*/SSD_FULL_SIZE,
 1881                                         da_default_timeout * 1000);
 1882                         break;
 1883                 case BIO_FLUSH:
 1884                         /*
 1885                          * BIO_FLUSH doesn't currently communicate
 1886                          * range data, so we synchronize the cache
 1887                          * over the whole disk.  We also force
 1888                          * ordered tag semantics the flush applies
 1889                          * to all previously queued I/O.
 1890                          */
 1891                         scsi_synchronize_cache(&start_ccb->csio,
 1892                                                /*retries*/1,
 1893                                                /*cbfcnp*/dadone,
 1894                                                MSG_ORDERED_Q_TAG,
 1895                                                /*begin_lba*/0,
 1896                                                /*lb_count*/0,
 1897                                                SSD_FULL_SIZE,
 1898                                                da_default_timeout*1000);
 1899                         break;
 1900                 }
 1901                 start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
 1902 
 1903 out:
 1904                 /*
 1905                  * Block out any asyncronous callbacks
 1906                  * while we touch the pending ccb list.
 1907                  */
 1908                 LIST_INSERT_HEAD(&softc->pending_ccbs,
 1909                                  &start_ccb->ccb_h, periph_links.le);
 1910                 softc->outstanding_cmds++;
 1911 
 1912                 /* We expect a unit attention from this device */
 1913                 if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
 1914                         start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
 1915                         softc->flags &= ~DA_FLAG_RETRY_UA;
 1916                 }
 1917 
 1918                 start_ccb->ccb_h.ccb_bp = bp;
 1919                 xpt_action(start_ccb);
 1920 
 1921                 /* May have more work to do, so ensure we stay scheduled */
 1922                 daschedule(periph);
 1923                 break;
 1924         }
 1925         case DA_STATE_PROBE:
 1926         {
 1927                 struct ccb_scsiio *csio;
 1928                 struct scsi_read_capacity_data *rcap;
 1929 
 1930                 rcap = (struct scsi_read_capacity_data *)
 1931                     malloc(sizeof(*rcap), M_SCSIDA, M_NOWAIT|M_ZERO);
 1932                 if (rcap == NULL) {
 1933                         printf("dastart: Couldn't malloc read_capacity data\n");
 1934                         /* da_free_periph??? */
 1935                         break;
 1936                 }
 1937                 csio = &start_ccb->csio;
 1938                 scsi_read_capacity(csio,
 1939                                    /*retries*/4,
 1940                                    dadone,
 1941                                    MSG_SIMPLE_Q_TAG,
 1942                                    rcap,
 1943                                    SSD_FULL_SIZE,
 1944                                    /*timeout*/5000);
 1945                 start_ccb->ccb_h.ccb_bp = NULL;
 1946                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE;
 1947                 xpt_action(start_ccb);
 1948                 break;
 1949         }
 1950         case DA_STATE_PROBE2:
 1951         {
 1952                 struct ccb_scsiio *csio;
 1953                 struct scsi_read_capacity_data_long *rcaplong;
 1954 
 1955                 rcaplong = (struct scsi_read_capacity_data_long *)
 1956                         malloc(sizeof(*rcaplong), M_SCSIDA, M_NOWAIT|M_ZERO);
 1957                 if (rcaplong == NULL) {
 1958                         printf("dastart: Couldn't malloc read_capacity data\n");
 1959                         /* da_free_periph??? */
 1960                         break;
 1961                 }
 1962                 csio = &start_ccb->csio;
 1963                 scsi_read_capacity_16(csio,
 1964                                       /*retries*/ 4,
 1965                                       /*cbfcnp*/ dadone,
 1966                                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1967                                       /*lba*/ 0,
 1968                                       /*reladr*/ 0,
 1969                                       /*pmi*/ 0,
 1970                                       rcaplong,
 1971                                       /*sense_len*/ SSD_FULL_SIZE,
 1972                                       /*timeout*/ 60000);
 1973                 start_ccb->ccb_h.ccb_bp = NULL;
 1974                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2;
 1975                 xpt_action(start_ccb);  
 1976                 break;
 1977         }
 1978         }
 1979 }
 1980 
 1981 static int
 1982 cmd6workaround(union ccb *ccb)
 1983 {
 1984         struct scsi_rw_6 cmd6;
 1985         struct scsi_rw_10 *cmd10;
 1986         struct da_softc *softc;
 1987         u_int8_t *cdb;
 1988         struct bio *bp;
 1989         int frozen;
 1990 
 1991         cdb = ccb->csio.cdb_io.cdb_bytes;
 1992         softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
 1993 
 1994         if (ccb->ccb_h.ccb_state == DA_CCB_DELETE) {
 1995                 if (softc->delete_method == DA_DELETE_UNMAP) {
 1996                         xpt_print(ccb->ccb_h.path, "UNMAP is not supported, "
 1997                             "switching to WRITE SAME(16) with UNMAP.\n");
 1998                         softc->delete_method = DA_DELETE_WS16;
 1999                 } else if (softc->delete_method == DA_DELETE_WS16) {
 2000                         xpt_print(ccb->ccb_h.path,
 2001                             "WRITE SAME(16) with UNMAP is not supported, "
 2002                             "disabling BIO_DELETE.\n");
 2003                         softc->delete_method = DA_DELETE_DISABLE;
 2004                 } else if (softc->delete_method == DA_DELETE_WS10) {
 2005                         xpt_print(ccb->ccb_h.path,
 2006                             "WRITE SAME(10) with UNMAP is not supported, "
 2007                             "disabling BIO_DELETE.\n");
 2008                         softc->delete_method = DA_DELETE_DISABLE;
 2009                 } else if (softc->delete_method == DA_DELETE_ZERO) {
 2010                         xpt_print(ccb->ccb_h.path,
 2011                             "WRITE SAME(10) is not supported, "
 2012                             "disabling BIO_DELETE.\n");
 2013                         softc->delete_method = DA_DELETE_DISABLE;
 2014                 } else
 2015                         softc->delete_method = DA_DELETE_DISABLE;
 2016                 while ((bp = bioq_takefirst(&softc->delete_run_queue))
 2017                     != NULL)
 2018                         bioq_disksort(&softc->delete_queue, bp);
 2019                 bioq_insert_tail(&softc->delete_queue,
 2020                     (struct bio *)ccb->ccb_h.ccb_bp);
 2021                 ccb->ccb_h.ccb_bp = NULL;
 2022                 return (0);
 2023         }
 2024 
 2025         /* Translation only possible if CDB is an array and cmd is R/W6 */
 2026         if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
 2027             (*cdb != READ_6 && *cdb != WRITE_6))
 2028                 return 0;
 2029 
 2030         xpt_print(ccb->ccb_h.path, "READ(6)/WRITE(6) not supported, "
 2031             "increasing minimum_cmd_size to 10.\n");
 2032         softc->minimum_cmd_size = 10;
 2033 
 2034         bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
 2035         cmd10 = (struct scsi_rw_10 *)cdb;
 2036         cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
 2037         cmd10->byte2 = 0;
 2038         scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
 2039         cmd10->reserved = 0;
 2040         scsi_ulto2b(cmd6.length, cmd10->length);
 2041         cmd10->control = cmd6.control;
 2042         ccb->csio.cdb_len = sizeof(*cmd10);
 2043 
 2044         /* Requeue request, unfreezing queue if necessary */
 2045         frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
 2046         ccb->ccb_h.status = CAM_REQUEUE_REQ;
 2047         xpt_action(ccb);
 2048         if (frozen) {
 2049                 cam_release_devq(ccb->ccb_h.path,
 2050                                  /*relsim_flags*/0,
 2051                                  /*reduction*/0,
 2052                                  /*timeout*/0,
 2053                                  /*getcount_only*/0);
 2054         }
 2055         return (ERESTART);
 2056 }
 2057 
 2058 static void
 2059 dadone(struct cam_periph *periph, union ccb *done_ccb)
 2060 {
 2061         struct da_softc *softc;
 2062         struct ccb_scsiio *csio;
 2063         u_int32_t  priority;
 2064 
 2065         softc = (struct da_softc *)periph->softc;
 2066         priority = done_ccb->ccb_h.pinfo.priority;
 2067 
 2068         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
 2069 
 2070         csio = &done_ccb->csio;
 2071         switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
 2072         case DA_CCB_BUFFER_IO:
 2073         case DA_CCB_DELETE:
 2074         {
 2075                 struct bio *bp, *bp1;
 2076 
 2077                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 2078                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 2079                         int error;
 2080                         int sf;
 2081 
 2082                         if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
 2083                                 sf = SF_RETRY_UA;
 2084                         else
 2085                                 sf = 0;
 2086 
 2087                         error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
 2088                         if (error == ERESTART) {
 2089                                 /*
 2090                                  * A retry was scheuled, so
 2091                                  * just return.
 2092                                  */
 2093                                 return;
 2094                         }
 2095                         bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 2096                         if (error != 0) {
 2097                                 int queued_error;
 2098 
 2099                                 /*
 2100                                  * return all queued I/O with EIO, so that
 2101                                  * the client can retry these I/Os in the
 2102                                  * proper order should it attempt to recover.
 2103                                  */
 2104                                 queued_error = EIO;
 2105 
 2106                                 if (error == ENXIO
 2107                                  && (softc->flags & DA_FLAG_PACK_INVALID)== 0) {
 2108                                         /*
 2109                                          * Catastrophic error.  Mark our pack as
 2110                                          * invalid.
 2111                                          */
 2112                                         /*
 2113                                          * XXX See if this is really a media
 2114                                          * XXX change first?
 2115                                          */
 2116                                         xpt_print(periph->path,
 2117                                             "Invalidating pack\n");
 2118                                         softc->flags |= DA_FLAG_PACK_INVALID;
 2119                                         queued_error = ENXIO;
 2120                                 }
 2121                                 bioq_flush(&softc->bio_queue, NULL,
 2122                                            queued_error);
 2123                                 if (bp != NULL) {
 2124                                         bp->bio_error = error;
 2125                                         bp->bio_resid = bp->bio_bcount;
 2126                                         bp->bio_flags |= BIO_ERROR;
 2127                                 }
 2128                         } else if (bp != NULL) {
 2129                                 bp->bio_resid = csio->resid;
 2130                                 bp->bio_error = 0;
 2131                                 if (bp->bio_resid != 0)
 2132                                         bp->bio_flags |= BIO_ERROR;
 2133                         }
 2134                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 2135                                 cam_release_devq(done_ccb->ccb_h.path,
 2136                                                  /*relsim_flags*/0,
 2137                                                  /*reduction*/0,
 2138                                                  /*timeout*/0,
 2139                                                  /*getcount_only*/0);
 2140                 } else if (bp != NULL) {
 2141                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 2142                                 panic("REQ_CMP with QFRZN");
 2143                         bp->bio_resid = csio->resid;
 2144                         if (csio->resid > 0)
 2145                                 bp->bio_flags |= BIO_ERROR;
 2146                         if (softc->error_inject != 0) {
 2147                                 bp->bio_error = softc->error_inject;
 2148                                 bp->bio_resid = bp->bio_bcount;
 2149                                 bp->bio_flags |= BIO_ERROR;
 2150                                 softc->error_inject = 0;
 2151                         }
 2152 
 2153                 }
 2154 
 2155                 /*
 2156                  * Block out any asyncronous callbacks
 2157                  * while we touch the pending ccb list.
 2158                  */
 2159                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
 2160                 softc->outstanding_cmds--;
 2161                 if (softc->outstanding_cmds == 0)
 2162                         softc->flags |= DA_FLAG_WENT_IDLE;
 2163 
 2164                 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
 2165                         xpt_print(periph->path, "oustanding %d\n",
 2166                                   softc->outstanding_cmds);
 2167                 }
 2168 
 2169                 if ((csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) ==
 2170                     DA_CCB_DELETE) {
 2171                         while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
 2172                             != NULL) {
 2173                                 bp1->bio_resid = bp->bio_resid;
 2174                                 bp1->bio_error = bp->bio_error;
 2175                                 if (bp->bio_flags & BIO_ERROR)
 2176                                         bp1->bio_flags |= BIO_ERROR;
 2177                                 biodone(bp1);
 2178                         }
 2179                         softc->delete_running = 0;
 2180                         if (bp != NULL)
 2181                                 biodone(bp);
 2182                         daschedule(periph);
 2183                 } else if (bp != NULL)
 2184                         biodone(bp);
 2185                 break;
 2186         }
 2187         case DA_CCB_PROBE:
 2188         case DA_CCB_PROBE2:
 2189         {
 2190                 struct     scsi_read_capacity_data *rdcap;
 2191                 struct     scsi_read_capacity_data_long *rcaplong;
 2192                 char       announce_buf[80];
 2193 
 2194                 rdcap = NULL;
 2195                 rcaplong = NULL;
 2196                 if (softc->state == DA_STATE_PROBE)
 2197                         rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
 2198                 else
 2199                         rcaplong = (struct scsi_read_capacity_data_long *)
 2200                                 csio->data_ptr;
 2201 
 2202                 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
 2203                         struct disk_params *dp;
 2204                         uint32_t block_size;
 2205                         uint64_t maxsector;
 2206                         u_int lbppbe;   /* LB per physical block exponent. */
 2207                         u_int lalba;    /* Lowest aligned LBA. */
 2208 
 2209                         if (softc->state == DA_STATE_PROBE) {
 2210                                 block_size = scsi_4btoul(rdcap->length);
 2211                                 maxsector = scsi_4btoul(rdcap->addr);
 2212                                 lbppbe = 0;
 2213                                 lalba = 0;
 2214 
 2215                                 /*
 2216                                  * According to SBC-2, if the standard 10
 2217                                  * byte READ CAPACITY command returns 2^32,
 2218                                  * we should issue the 16 byte version of
 2219                                  * the command, since the device in question
 2220                                  * has more sectors than can be represented
 2221                                  * with the short version of the command.
 2222                                  */
 2223                                 if (maxsector == 0xffffffff) {
 2224                                         softc->state = DA_STATE_PROBE2;
 2225                                         free(rdcap, M_SCSIDA);
 2226                                         xpt_release_ccb(done_ccb);
 2227                                         xpt_schedule(periph, priority);
 2228                                         return;
 2229                                 }
 2230                         } else {
 2231                                 block_size = scsi_4btoul(rcaplong->length);
 2232                                 maxsector = scsi_8btou64(rcaplong->addr);
 2233                                 lbppbe = rcaplong->prot_lbppbe & SRC16_LBPPBE;
 2234                                 lalba = scsi_2btoul(rcaplong->lalba_lbp);
 2235                         }
 2236 
 2237                         /*
 2238                          * Because GEOM code just will panic us if we
 2239                          * give them an 'illegal' value we'll avoid that
 2240                          * here.
 2241                          */
 2242                         if (block_size == 0 && maxsector == 0) {
 2243                                 snprintf(announce_buf, sizeof(announce_buf),
 2244                                         "0MB (no media?)");
 2245                         } else if (block_size >= MAXPHYS || block_size == 0) {
 2246                                 xpt_print(periph->path,
 2247                                     "unsupportable block size %ju\n",
 2248                                     (uintmax_t) block_size);
 2249                                 announce_buf[0] = '\0';
 2250                                 cam_periph_invalidate(periph);
 2251                         } else {
 2252                                 dasetgeom(periph, block_size, maxsector,
 2253                                     lbppbe, lalba & SRC16_LALBA);
 2254                                 if ((lalba & SRC16_LBPME) &&
 2255                                     softc->delete_method == DA_DELETE_NONE)
 2256                                         softc->delete_method = DA_DELETE_UNMAP;
 2257                                 dp = &softc->params;
 2258                                 snprintf(announce_buf, sizeof(announce_buf),
 2259                                         "%juMB (%ju %u byte sectors: %dH %dS/T "
 2260                                         "%dC)", (uintmax_t)
 2261                                         (((uintmax_t)dp->secsize *
 2262                                         dp->sectors) / (1024*1024)),
 2263                                         (uintmax_t)dp->sectors,
 2264                                         dp->secsize, dp->heads,
 2265                                         dp->secs_per_track, dp->cylinders);
 2266                         }
 2267                 } else {
 2268                         int     error;
 2269 
 2270                         announce_buf[0] = '\0';
 2271 
 2272                         /*
 2273                          * Retry any UNIT ATTENTION type errors.  They
 2274                          * are expected at boot.
 2275                          */
 2276                         error = daerror(done_ccb, CAM_RETRY_SELTO,
 2277                                         SF_RETRY_UA|SF_NO_PRINT);
 2278                         if (error == ERESTART) {
 2279                                 /*
 2280                                  * A retry was scheuled, so
 2281                                  * just return.
 2282                                  */
 2283                                 return;
 2284                         } else if (error != 0) {
 2285                                 struct scsi_sense_data *sense;
 2286                                 int asc, ascq;
 2287                                 int sense_key, error_code;
 2288                                 int have_sense;
 2289                                 cam_status status;
 2290                                 struct ccb_getdev cgd;
 2291 
 2292                                 /* Don't wedge this device's queue */
 2293                                 status = done_ccb->ccb_h.status;
 2294                                 if ((status & CAM_DEV_QFRZN) != 0)
 2295                                         cam_release_devq(done_ccb->ccb_h.path,
 2296                                                          /*relsim_flags*/0,
 2297                                                          /*reduction*/0,
 2298                                                          /*timeout*/0,
 2299                                                          /*getcount_only*/0);
 2300 
 2301 
 2302                                 xpt_setup_ccb(&cgd.ccb_h, 
 2303                                               done_ccb->ccb_h.path,
 2304                                               CAM_PRIORITY_NORMAL);
 2305                                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 2306                                 xpt_action((union ccb *)&cgd);
 2307 
 2308                                 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
 2309                                  || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
 2310                                  || ((status & CAM_AUTOSNS_VALID) == 0))
 2311                                         have_sense = FALSE;
 2312                                 else
 2313                                         have_sense = TRUE;
 2314 
 2315                                 if (have_sense) {
 2316                                         sense = &csio->sense_data;
 2317                                         scsi_extract_sense_len(sense,
 2318                                             csio->sense_len - csio->sense_resid,
 2319                                             &error_code, &sense_key, &asc,
 2320                                             &ascq, /*show_errors*/ 1);
 2321                                 }
 2322                                 /*
 2323                                  * If we tried READ CAPACITY(16) and failed,
 2324                                  * fallback to READ CAPACITY(10).
 2325                                  */
 2326                                 if ((softc->state == DA_STATE_PROBE2) &&
 2327                                     (softc->flags & DA_FLAG_CAN_RC16) &&
 2328                                     (((csio->ccb_h.status & CAM_STATUS_MASK) ==
 2329                                         CAM_REQ_INVALID) ||
 2330                                      ((have_sense) &&
 2331                                       (error_code == SSD_CURRENT_ERROR) &&
 2332                                       (sense_key == SSD_KEY_ILLEGAL_REQUEST)))) {
 2333                                         softc->flags &= ~DA_FLAG_CAN_RC16;
 2334                                         softc->state = DA_STATE_PROBE;
 2335                                         free(rdcap, M_SCSIDA);
 2336                                         xpt_release_ccb(done_ccb);
 2337                                         xpt_schedule(periph, priority);
 2338                                         return;
 2339                                 } else
 2340                                 /*
 2341                                  * Attach to anything that claims to be a
 2342                                  * direct access or optical disk device,
 2343                                  * as long as it doesn't return a "Logical
 2344                                  * unit not supported" (0x25) error.
 2345                                  */
 2346                                 if ((have_sense) && (asc != 0x25)
 2347                                  && (error_code == SSD_CURRENT_ERROR)) {
 2348                                         const char *sense_key_desc;
 2349                                         const char *asc_desc;
 2350 
 2351                                         scsi_sense_desc(sense_key, asc, ascq,
 2352                                                         &cgd.inq_data,
 2353                                                         &sense_key_desc,
 2354                                                         &asc_desc);
 2355                                         snprintf(announce_buf,
 2356                                             sizeof(announce_buf),
 2357                                                 "Attempt to query device "
 2358                                                 "size failed: %s, %s",
 2359                                                 sense_key_desc,
 2360                                                 asc_desc);
 2361                                 } else { 
 2362                                         if (have_sense)
 2363                                                 scsi_sense_print(
 2364                                                         &done_ccb->csio);
 2365                                         else {
 2366                                                 xpt_print(periph->path,
 2367                                                     "got CAM status %#x\n",
 2368                                                     done_ccb->ccb_h.status);
 2369                                         }
 2370 
 2371                                         xpt_print(periph->path, "fatal error, "
 2372                                             "failed to attach to device\n");
 2373 
 2374                                         /*
 2375                                          * Free up resources.
 2376                                          */
 2377                                         cam_periph_invalidate(periph);
 2378                                 } 
 2379                         }
 2380                 }
 2381                 free(csio->data_ptr, M_SCSIDA);
 2382                 if (announce_buf[0] != '\0') {
 2383                         /*
 2384                          * Create our sysctl variables, now that we know
 2385                          * we have successfully attached.
 2386                          */
 2387                         /* increase the refcount */
 2388                         if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
 2389                                 taskqueue_enqueue(taskqueue_thread,
 2390                                                   &softc->sysctl_task);
 2391                                 xpt_announce_periph(periph, announce_buf);
 2392                         } else {
 2393                                 xpt_print(periph->path, "fatal error, "
 2394                                     "could not acquire reference count\n");
 2395                         }
 2396                                 
 2397                 }
 2398                 softc->state = DA_STATE_NORMAL; 
 2399                 /*
 2400                  * Since our peripheral may be invalidated by an error
 2401                  * above or an external event, we must release our CCB
 2402                  * before releasing the probe lock on the peripheral.
 2403                  * The peripheral will only go away once the last lock
 2404                  * is removed, and we need it around for the CCB release
 2405                  * operation.
 2406                  */
 2407                 xpt_release_ccb(done_ccb);
 2408                 cam_periph_unhold(periph);
 2409                 return;
 2410         }
 2411         case DA_CCB_WAITING:
 2412         {
 2413                 /* Caller will release the CCB */
 2414                 wakeup(&done_ccb->ccb_h.cbfcnp);
 2415                 return;
 2416         }
 2417         case DA_CCB_DUMP:
 2418                 /* No-op.  We're polling */
 2419                 return;
 2420         default:
 2421                 break;
 2422         }
 2423         xpt_release_ccb(done_ccb);
 2424 }
 2425 
 2426 static int
 2427 daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 2428 {
 2429         struct da_softc   *softc;
 2430         struct cam_periph *periph;
 2431         int error;
 2432 
 2433         periph = xpt_path_periph(ccb->ccb_h.path);
 2434         softc = (struct da_softc *)periph->softc;
 2435 
 2436         /*
 2437          * Automatically detect devices that do not support
 2438          * READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
 2439          */
 2440         error = 0;
 2441         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
 2442                 error = cmd6workaround(ccb);
 2443         } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
 2444                    CAM_SCSI_STATUS_ERROR)
 2445          && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)
 2446          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
 2447          && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0)
 2448          && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
 2449                 int sense_key, error_code, asc, ascq;
 2450 
 2451                 scsi_extract_sense(&ccb->csio.sense_data,
 2452                                    &error_code, &sense_key, &asc, &ascq);
 2453                 if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
 2454                         error = cmd6workaround(ccb);
 2455         }
 2456         if (error == ERESTART)
 2457                 return (ERESTART);
 2458 
 2459         /*
 2460          * XXX
 2461          * Until we have a better way of doing pack validation,
 2462          * don't treat UAs as errors.
 2463          */
 2464         sense_flags |= SF_RETRY_UA;
 2465         return(cam_periph_error(ccb, cam_flags, sense_flags,
 2466                                 &softc->saved_ccb));
 2467 }
 2468 
 2469 static void
 2470 daprevent(struct cam_periph *periph, int action)
 2471 {
 2472         struct  da_softc *softc;
 2473         union   ccb *ccb;               
 2474         int     error;
 2475                 
 2476         softc = (struct da_softc *)periph->softc;
 2477 
 2478         if (((action == PR_ALLOW)
 2479           && (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
 2480          || ((action == PR_PREVENT)
 2481           && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
 2482                 return;
 2483         }
 2484 
 2485         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 2486 
 2487         scsi_prevent(&ccb->csio,
 2488                      /*retries*/1,
 2489                      /*cbcfp*/dadone,
 2490                      MSG_SIMPLE_Q_TAG,
 2491                      action,
 2492                      SSD_FULL_SIZE,
 2493                      5000);
 2494 
 2495         error = cam_periph_runccb(ccb, daerror, CAM_RETRY_SELTO,
 2496             SF_RETRY_UA | SF_QUIET_IR, softc->disk->d_devstat);
 2497 
 2498         if (error == 0) {
 2499                 if (action == PR_ALLOW)
 2500                         softc->flags &= ~DA_FLAG_PACK_LOCKED;
 2501                 else
 2502                         softc->flags |= DA_FLAG_PACK_LOCKED;
 2503         }
 2504 
 2505         xpt_release_ccb(ccb);
 2506 }
 2507 
 2508 static int
 2509 dagetcapacity(struct cam_periph *periph)
 2510 {
 2511         struct da_softc *softc;
 2512         union ccb *ccb;
 2513         struct scsi_read_capacity_data *rcap;
 2514         struct scsi_read_capacity_data_long *rcaplong;
 2515         uint32_t block_len;
 2516         uint64_t maxsector;
 2517         int error, rc16failed;
 2518         u_int32_t sense_flags;
 2519         u_int lbppbe;   /* Logical blocks per physical block exponent. */
 2520         u_int lalba;    /* Lowest aligned LBA. */
 2521 
 2522         softc = (struct da_softc *)periph->softc;
 2523         block_len = 0;
 2524         maxsector = 0;
 2525         lbppbe = 0;
 2526         lalba = 0;
 2527         error = 0;
 2528         rc16failed = 0;
 2529         sense_flags = SF_RETRY_UA;
 2530         if (softc->flags & DA_FLAG_PACK_REMOVABLE)
 2531                 sense_flags |= SF_NO_PRINT;
 2532 
 2533         /* Do a read capacity */
 2534         rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
 2535                                                         M_SCSIDA,
 2536                                                         M_NOWAIT | M_ZERO);
 2537         if (rcap == NULL)
 2538                 return (ENOMEM);
 2539         rcaplong = (struct scsi_read_capacity_data_long *)rcap;
 2540 
 2541         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 2542 
 2543         /* Try READ CAPACITY(16) first if we think it should work. */
 2544         if (softc->flags & DA_FLAG_CAN_RC16) {
 2545                 scsi_read_capacity_16(&ccb->csio,
 2546                               /*retries*/ 4,
 2547                               /*cbfcnp*/ dadone,
 2548                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 2549                               /*lba*/ 0,
 2550                               /*reladr*/ 0,
 2551                               /*pmi*/ 0,
 2552                               rcaplong,
 2553                               /*sense_len*/ SSD_FULL_SIZE,
 2554                               /*timeout*/ 60000);
 2555                 ccb->ccb_h.ccb_bp = NULL;
 2556 
 2557                 error = cam_periph_runccb(ccb, daerror,
 2558                                   /*cam_flags*/CAM_RETRY_SELTO,
 2559                                   sense_flags,
 2560                                   softc->disk->d_devstat);
 2561                 if (error == 0)
 2562                         goto rc16ok;
 2563 
 2564                 /* If we got ILLEGAL REQUEST, do not prefer RC16 any more. */
 2565                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
 2566                      CAM_REQ_INVALID) {
 2567                         softc->flags &= ~DA_FLAG_CAN_RC16;
 2568                 } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
 2569                      CAM_SCSI_STATUS_ERROR) &&
 2570                     (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) &&
 2571                     (ccb->ccb_h.status & CAM_AUTOSNS_VALID) &&
 2572                     ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0) &&
 2573                     ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
 2574                         int sense_key, error_code, asc, ascq;
 2575 
 2576                         scsi_extract_sense(&ccb->csio.sense_data,
 2577                                    &error_code, &sense_key, &asc, &ascq);
 2578                         if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
 2579                                 softc->flags &= ~DA_FLAG_CAN_RC16;
 2580                 }
 2581                 rc16failed = 1;
 2582         }
 2583 
 2584         /* Do READ CAPACITY(10). */
 2585         scsi_read_capacity(&ccb->csio,
 2586                            /*retries*/4,
 2587                            /*cbfncp*/dadone,
 2588                            MSG_SIMPLE_Q_TAG,
 2589                            rcap,
 2590                            SSD_FULL_SIZE,
 2591                            /*timeout*/60000);
 2592         ccb->ccb_h.ccb_bp = NULL;
 2593 
 2594         error = cam_periph_runccb(ccb, daerror,
 2595                                   /*cam_flags*/CAM_RETRY_SELTO,
 2596                                   sense_flags,
 2597                                   softc->disk->d_devstat);
 2598         if (error == 0) {
 2599                 block_len = scsi_4btoul(rcap->length);
 2600                 maxsector = scsi_4btoul(rcap->addr);
 2601 
 2602                 if (maxsector != 0xffffffff || rc16failed)
 2603                         goto done;
 2604         } else
 2605                 goto done;
 2606 
 2607         /* If READ CAPACITY(10) returned overflow, use READ CAPACITY(16) */
 2608         scsi_read_capacity_16(&ccb->csio,
 2609                               /*retries*/ 4,
 2610                               /*cbfcnp*/ dadone,
 2611                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 2612                               /*lba*/ 0,
 2613                               /*reladr*/ 0,
 2614                               /*pmi*/ 0,
 2615                               rcaplong,
 2616                               /*sense_len*/ SSD_FULL_SIZE,
 2617                               /*timeout*/ 60000);
 2618         ccb->ccb_h.ccb_bp = NULL;
 2619 
 2620         error = cam_periph_runccb(ccb, daerror,
 2621                                   /*cam_flags*/CAM_RETRY_SELTO,
 2622                                   sense_flags,
 2623                                   softc->disk->d_devstat);
 2624         if (error == 0) {
 2625 rc16ok:
 2626                 block_len = scsi_4btoul(rcaplong->length);
 2627                 maxsector = scsi_8btou64(rcaplong->addr);
 2628                 lbppbe = rcaplong->prot_lbppbe & SRC16_LBPPBE;
 2629                 lalba = scsi_2btoul(rcaplong->lalba_lbp);
 2630         }
 2631 
 2632 done:
 2633 
 2634         if (error == 0) {
 2635                 if (block_len >= MAXPHYS || block_len == 0) {
 2636                         xpt_print(periph->path,
 2637                             "unsupportable block size %ju\n",
 2638                             (uintmax_t) block_len);
 2639                         error = EINVAL;
 2640                 } else {
 2641                         dasetgeom(periph, block_len, maxsector,
 2642                             lbppbe, lalba & SRC16_LALBA);
 2643                         if ((lalba & SRC16_LBPME) &&
 2644                             softc->delete_method == DA_DELETE_NONE)
 2645                                 softc->delete_method = DA_DELETE_UNMAP;
 2646                 }
 2647         }
 2648 
 2649         xpt_release_ccb(ccb);
 2650 
 2651         free(rcap, M_SCSIDA);
 2652 
 2653         return (error);
 2654 }
 2655 
 2656 static void
 2657 dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector,
 2658     u_int lbppbe, u_int lalba)
 2659 {
 2660         struct ccb_calc_geometry ccg;
 2661         struct da_softc *softc;
 2662         struct disk_params *dp;
 2663 
 2664         softc = (struct da_softc *)periph->softc;
 2665 
 2666         dp = &softc->params;
 2667         dp->secsize = block_len;
 2668         dp->sectors = maxsector + 1;
 2669         if (lbppbe > 0) {
 2670                 dp->stripesize = block_len << lbppbe;
 2671                 dp->stripeoffset = (dp->stripesize - block_len * lalba) %
 2672                     dp->stripesize;
 2673         } else if (softc->quirks & DA_Q_4K) {
 2674                 dp->stripesize = 4096;
 2675                 dp->stripeoffset = 0;
 2676         } else {
 2677                 dp->stripesize = 0;
 2678                 dp->stripeoffset = 0;
 2679         }
 2680         /*
 2681          * Have the controller provide us with a geometry
 2682          * for this disk.  The only time the geometry
 2683          * matters is when we boot and the controller
 2684          * is the only one knowledgeable enough to come
 2685          * up with something that will make this a bootable
 2686          * device.
 2687          */
 2688         xpt_setup_ccb(&ccg.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 2689         ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
 2690         ccg.block_size = dp->secsize;
 2691         ccg.volume_size = dp->sectors;
 2692         ccg.heads = 0;
 2693         ccg.secs_per_track = 0;
 2694         ccg.cylinders = 0;
 2695         xpt_action((union ccb*)&ccg);
 2696         if ((ccg.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 2697                 /*
 2698                  * We don't know what went wrong here- but just pick
 2699                  * a geometry so we don't have nasty things like divide
 2700                  * by zero.
 2701                  */
 2702                 dp->heads = 255;
 2703                 dp->secs_per_track = 255;
 2704                 dp->cylinders = dp->sectors / (255 * 255);
 2705                 if (dp->cylinders == 0) {
 2706                         dp->cylinders = 1;
 2707                 }
 2708         } else {
 2709                 dp->heads = ccg.heads;
 2710                 dp->secs_per_track = ccg.secs_per_track;
 2711                 dp->cylinders = ccg.cylinders;
 2712         }
 2713 }
 2714 
 2715 static void
 2716 dasendorderedtag(void *arg)
 2717 {
 2718         struct da_softc *softc = arg;
 2719 
 2720         if (da_send_ordered) {
 2721                 if ((softc->ordered_tag_count == 0) 
 2722                  && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
 2723                         softc->flags |= DA_FLAG_NEED_OTAG;
 2724                 }
 2725                 if (softc->outstanding_cmds > 0)
 2726                         softc->flags &= ~DA_FLAG_WENT_IDLE;
 2727 
 2728                 softc->ordered_tag_count = 0;
 2729         }
 2730         /* Queue us up again */
 2731         callout_reset(&softc->sendordered_c,
 2732             (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
 2733             dasendorderedtag, softc);
 2734 }
 2735 
 2736 /*
 2737  * Step through all DA peripheral drivers, and if the device is still open,
 2738  * sync the disk cache to physical media.
 2739  */
 2740 static void
 2741 dashutdown(void * arg, int howto)
 2742 {
 2743         struct cam_periph *periph;
 2744         struct da_softc *softc;
 2745         int error;
 2746 
 2747         TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
 2748                 union ccb ccb;
 2749 
 2750                 cam_periph_lock(periph);
 2751                 softc = (struct da_softc *)periph->softc;
 2752 
 2753                 /*
 2754                  * We only sync the cache if the drive is still open, and
 2755                  * if the drive is capable of it..
 2756                  */
 2757                 if (((softc->flags & DA_FLAG_OPEN) == 0)
 2758                  || (softc->quirks & DA_Q_NO_SYNC_CACHE)) {
 2759                         cam_periph_unlock(periph);
 2760                         continue;
 2761                 }
 2762 
 2763                 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 2764 
 2765                 ccb.ccb_h.ccb_state = DA_CCB_DUMP;
 2766                 scsi_synchronize_cache(&ccb.csio,
 2767                                        /*retries*/0,
 2768                                        /*cbfcnp*/dadone,
 2769                                        MSG_SIMPLE_Q_TAG,
 2770                                        /*begin_lba*/0, /* whole disk */
 2771                                        /*lb_count*/0,
 2772                                        SSD_FULL_SIZE,
 2773                                        60 * 60 * 1000);
 2774 
 2775                 xpt_polled_action(&ccb);
 2776 
 2777                 error = cam_periph_error(&ccb,
 2778                     0, SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR, NULL);
 2779                 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
 2780                         cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0,
 2781                             /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
 2782                 if (error != 0)
 2783                         xpt_print(periph->path, "Synchronize cache failed\n");
 2784                 cam_periph_unlock(periph);
 2785         }
 2786 }
 2787 
 2788 #else /* !_KERNEL */
 2789 
 2790 /*
 2791  * XXX This is only left out of the kernel build to silence warnings.  If,
 2792  * for some reason this function is used in the kernel, the ifdefs should
 2793  * be moved so it is included both in the kernel and userland.
 2794  */
 2795 void
 2796 scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
 2797                  void (*cbfcnp)(struct cam_periph *, union ccb *),
 2798                  u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
 2799                  u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
 2800                  u_int32_t timeout)
 2801 {
 2802         struct scsi_format_unit *scsi_cmd;
 2803 
 2804         scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
 2805         scsi_cmd->opcode = FORMAT_UNIT;
 2806         scsi_cmd->byte2 = byte2;
 2807         scsi_ulto2b(ileave, scsi_cmd->interleave);
 2808 
 2809         cam_fill_csio(csio,
 2810                       retries,
 2811                       cbfcnp,
 2812                       /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
 2813                       tag_action,
 2814                       data_ptr,
 2815                       dxfer_len,
 2816                       sense_len,
 2817                       sizeof(*scsi_cmd),
 2818                       timeout);
 2819 }
 2820 
 2821 #endif /* _KERNEL */

Cache object: 8062fcc25b93a79587a9df65f0eee429


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