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/6.3/sys/cam/scsi/scsi_da.c 169996 2007-05-25 20:14:02Z mjacob $");
   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 #endif /* _KERNEL */
   41 
   42 #include <sys/devicestat.h>
   43 #include <sys/conf.h>
   44 #include <sys/eventhandler.h>
   45 #include <sys/malloc.h>
   46 #include <sys/cons.h>
   47 
   48 #include <machine/md_var.h>
   49 
   50 #include <vm/vm.h>
   51 #include <vm/pmap.h>
   52 
   53 #include <geom/geom_disk.h>
   54 
   55 #ifndef _KERNEL
   56 #include <stdio.h>
   57 #include <string.h>
   58 #endif /* _KERNEL */
   59 
   60 #include <cam/cam.h>
   61 #include <cam/cam_ccb.h>
   62 #include <cam/cam_periph.h>
   63 #include <cam/cam_xpt_periph.h>
   64 
   65 #include <cam/scsi/scsi_message.h>
   66 
   67 #ifndef _KERNEL 
   68 #include <cam/scsi/scsi_da.h>
   69 #endif /* !_KERNEL */
   70 
   71 #ifdef _KERNEL
   72 typedef enum {
   73         DA_STATE_PROBE,
   74         DA_STATE_PROBE2,
   75         DA_STATE_NORMAL
   76 } da_state;
   77 
   78 typedef enum {
   79         DA_FLAG_PACK_INVALID    = 0x001,
   80         DA_FLAG_NEW_PACK        = 0x002,
   81         DA_FLAG_PACK_LOCKED     = 0x004,
   82         DA_FLAG_PACK_REMOVABLE  = 0x008,
   83         DA_FLAG_TAGGED_QUEUING  = 0x010,
   84         DA_FLAG_NEED_OTAG       = 0x020,
   85         DA_FLAG_WENT_IDLE       = 0x040,
   86         DA_FLAG_RETRY_UA        = 0x080,
   87         DA_FLAG_OPEN            = 0x100,
   88         DA_FLAG_SCTX_INIT       = 0x200
   89 } da_flags;
   90 
   91 typedef enum {
   92         DA_Q_NONE               = 0x00,
   93         DA_Q_NO_SYNC_CACHE      = 0x01,
   94         DA_Q_NO_6_BYTE          = 0x02,
   95         DA_Q_NO_PREVENT         = 0x04
   96 } da_quirks;
   97 
   98 typedef enum {
   99         DA_CCB_PROBE            = 0x01,
  100         DA_CCB_PROBE2           = 0x02,
  101         DA_CCB_BUFFER_IO        = 0x03,
  102         DA_CCB_WAITING          = 0x04,
  103         DA_CCB_DUMP             = 0x05,
  104         DA_CCB_TYPE_MASK        = 0x0F,
  105         DA_CCB_RETRY_UA         = 0x10
  106 } da_ccb_state;
  107 
  108 /* Offsets into our private area for storing information */
  109 #define ccb_state       ppriv_field0
  110 #define ccb_bp          ppriv_ptr1
  111 
  112 struct disk_params {
  113         u_int8_t  heads;
  114         u_int32_t cylinders;
  115         u_int8_t  secs_per_track;
  116         u_int32_t secsize;      /* Number of bytes/sector */
  117         u_int64_t sectors;      /* total number sectors */
  118 };
  119 
  120 struct da_softc {
  121         struct   bio_queue_head bio_queue;
  122         SLIST_ENTRY(da_softc) links;
  123         LIST_HEAD(, ccb_hdr) pending_ccbs;
  124         da_state state;
  125         da_flags flags; 
  126         da_quirks quirks;
  127         int      minimum_cmd_size;
  128         int      ordered_tag_count;
  129         int      outstanding_cmds;
  130         struct   disk_params params;
  131         struct   disk *disk;
  132         union    ccb saved_ccb;
  133         struct task             sysctl_task;
  134         struct sysctl_ctx_list  sysctl_ctx;
  135         struct sysctl_oid       *sysctl_tree;
  136 };
  137 
  138 struct da_quirk_entry {
  139         struct scsi_inquiry_pattern inq_pat;
  140         da_quirks quirks;
  141 };
  142 
  143 static const char quantum[] = "QUANTUM";
  144 static const char microp[] = "MICROP";
  145 
  146 static struct da_quirk_entry da_quirk_table[] =
  147 {
  148         /* SPI, FC devices */
  149         {
  150                 /*
  151                  * Fujitsu M2513A MO drives.
  152                  * Tested devices: M2513A2 firmware versions 1200 & 1300.
  153                  * (dip switch selects whether T_DIRECT or T_OPTICAL device)
  154                  * Reported by: W.Scholten <whs@xs4all.nl>
  155                  */
  156                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
  157                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  158         },
  159         {
  160                 /* See above. */
  161                 {T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
  162                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  163         },
  164         {
  165                 /*
  166                  * This particular Fujitsu drive doesn't like the
  167                  * synchronize cache command.
  168                  * Reported by: Tom Jackson <toj@gorilla.net>
  169                  */
  170                 {T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
  171                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  172         
  173         },
  174         {
  175                 /*
  176                  * This drive doesn't like the synchronize cache command
  177                  * either.  Reported by: Matthew Jacob <mjacob@feral.com>
  178                  * in NetBSD PR kern/6027, August 24, 1998.
  179                  */
  180                 {T_DIRECT, SIP_MEDIA_FIXED, microp, "2217*", "*"},
  181                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  182         },
  183         {
  184                 /*
  185                  * This drive doesn't like the synchronize cache command
  186                  * either.  Reported by: Hellmuth Michaelis (hm@kts.org)
  187                  * (PR 8882).
  188                  */
  189                 {T_DIRECT, SIP_MEDIA_FIXED, microp, "2112*", "*"},
  190                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  191         },
  192         {
  193                 /*
  194                  * Doesn't like the synchronize cache command.
  195                  * Reported by: Blaz Zupan <blaz@gold.amis.net>
  196                  */
  197                 {T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"},
  198                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  199         },
  200         {
  201                 /*
  202                  * Doesn't like the synchronize cache command.
  203                  * Reported by: Blaz Zupan <blaz@gold.amis.net>
  204                  */
  205                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "MAVERICK 540S", "*"},
  206                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  207         },
  208         {
  209                 /*
  210                  * Doesn't like the synchronize cache command.
  211                  */
  212                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"},
  213                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  214         },
  215         {
  216                 /*
  217                  * Doesn't like the synchronize cache command.
  218                  * Reported by: walter@pelissero.de
  219                  */
  220                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS540S", "*"},
  221                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  222         },
  223         {
  224                 /*
  225                  * Doesn't work correctly with 6 byte reads/writes.
  226                  * Returns illegal request, and points to byte 9 of the
  227                  * 6-byte CDB.
  228                  * Reported by:  Adam McDougall <bsdx@spawnet.com>
  229                  */
  230                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 4*", "*"},
  231                 /*quirks*/ DA_Q_NO_6_BYTE
  232         },
  233         {
  234                 /* See above. */
  235                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 2*", "*"},
  236                 /*quirks*/ DA_Q_NO_6_BYTE
  237         },
  238         {
  239                 /*
  240                  * Doesn't like the synchronize cache command.
  241                  * Reported by: walter@pelissero.de
  242                  */
  243                 {T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CP3500*", "*"},
  244                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  245         },
  246         {
  247                 /*
  248                  * The CISS RAID controllers do not support SYNC_CACHE
  249                  */
  250                 {T_DIRECT, SIP_MEDIA_FIXED, "COMPAQ", "RAID*", "*"},
  251                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  252         },
  253         /* USB mass storage devices supported by umass(4) */
  254         {
  255                 /*
  256                  * EXATELECOM (Sigmatel) i-Bead 100/105 USB Flash MP3 Player
  257                  * PR: kern/51675
  258                  */
  259                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "EXATEL", "i-BEAD10*", "*"},
  260                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  261         },
  262         {
  263                 /*
  264                  * Power Quotient Int. (PQI) USB flash key
  265                  * PR: kern/53067
  266                  */
  267                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "USB Flash Disk*",
  268                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  269         }, 
  270         {
  271                 /*
  272                  * Creative Nomad MUVO mp3 player (USB)
  273                  * PR: kern/53094
  274                  */
  275                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "NOMAD_MUVO", "*"},
  276                 /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  277         },
  278         {
  279                 /*
  280                  * Jungsoft NEXDISK USB flash key
  281                  * PR: kern/54737
  282                  */
  283                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "JUNGSOFT", "NEXDISK*", "*"},
  284                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  285         },
  286         {
  287                 /*
  288                  * FreeDik USB Mini Data Drive
  289                  * PR: kern/54786
  290                  */
  291                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FreeDik*", "Mini Data Drive",
  292                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  293         },
  294         {
  295                 /*
  296                  * Sigmatel USB Flash MP3 Player
  297                  * PR: kern/57046
  298                  */
  299                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SigmaTel", "MSCN", "*"},
  300                 /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  301         },
  302         {
  303                 /*
  304                  * Neuros USB Digital Audio Computer
  305                  * PR: kern/63645
  306                  */
  307                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "NEUROS", "dig. audio comp.",
  308                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  309         },
  310         {
  311                 /*
  312                  * SEAGRAND NP-900 MP3 Player
  313                  * PR: kern/64563
  314                  */
  315                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SEAGRAND", "NP-900*", "*"},
  316                 /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  317         },
  318         {
  319                 /*
  320                  * iRiver iFP MP3 player (with UMS Firmware)
  321                  * PR: kern/54881, i386/63941, kern/66124
  322                  */
  323                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "iRiver", "iFP*", "*"},
  324                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  325         },
  326         {
  327                 /*
  328                  * Frontier Labs NEX IA+ Digital Audio Player, rev 1.10/0.01
  329                  * PR: kern/70158
  330                  */
  331                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FL" , "Nex*", "*"},
  332                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  333         },
  334         {
  335                 /*
  336                  * ZICPlay USB MP3 Player with FM
  337                  * PR: kern/75057
  338                  */
  339                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "ACTIONS*" , "USB DISK*", "*"},
  340                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  341         },
  342         {
  343                 /*
  344                  * TEAC USB floppy mechanisms
  345                  */
  346                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "TEAC" , "FD-05*", "*"},
  347                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  348         },
  349         {
  350                 /*
  351                  * Kingston DataTraveler II+ USB Pen-Drive.
  352                  * Reported by: Pawel Jakub Dawidek <pjd@FreeBSD.org>
  353                  */
  354                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston" , "DataTraveler II+", "*"},
  355                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  356         },
  357         {
  358                 /*
  359                  * Motorola E398 Mobile Phone (TransFlash memory card).
  360                  * Reported by: Wojciech A. Koszek <dunstan@FreeBSD.czest.pl>
  361                  * PR: usb/89889
  362                  */
  363                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Motorola" , "Motorola Phone",
  364                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  365         },
  366         {
  367                 /*
  368                  * Qware BeatZkey! Pro
  369                  * PR: usb/79164
  370                  */
  371                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "GENERIC", "USB DISK DEVICE",
  372                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  373         },
  374         {
  375                 /*
  376                  * Time DPA20B 1GB MP3 Player
  377                  * PR: usb/81846
  378                  */
  379                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB2.0*", "(FS) FLASH DISK*",
  380                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  381         },
  382         {
  383                 /*
  384                  * Samsung USB key 128Mb
  385                  * PR: usb/90081
  386                  */
  387                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB-DISK", "FreeDik-FlashUsb",
  388                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  389         },
  390         {
  391                 /*
  392                  * Kingston DataTraveler 2.0 USB Flash memory.
  393                  * PR: usb/89196
  394                  */
  395                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler 2.0",
  396                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  397         },
  398         {
  399                 /*
  400                  * Creative MUVO Slim mp3 player (USB)
  401                  * PR: usb/86131
  402                  */
  403                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "MuVo Slim",
  404                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
  405                 },
  406         {
  407                 /*
  408                  * United MP5512 Portable MP3 Player (2-in-1 USB DISK/MP3)
  409                  * PR: usb/80487
  410                  */
  411                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "MUSIC DISK",
  412                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  413         },
  414         {
  415                 /*
  416                  * SanDisk Micro Cruzer 128MB
  417                  * PR: usb/75970
  418                  */
  419                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SanDisk" , "Micro Cruzer",
  420                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  421         },
  422         {
  423                 /*
  424                  * TOSHIBA TransMemory USB sticks
  425                  * PR: kern/94660
  426                  */
  427                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "TOSHIBA", "TransMemory",
  428                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  429         },
  430         {
  431                 /*
  432                  * PNY USB Flash keys
  433                  * PR: usb/75578, usb/72344, usb/65436 
  434                  */
  435                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "*" , "USB DISK*",
  436                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  437         },
  438         {
  439                 /*
  440                  * Genesys 6-in-1 Card Reader
  441                  * PR: usb/94647
  442                  */
  443                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "STORAGE DEVICE*",
  444                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  445         },
  446         {
  447                 /*
  448                  * Rekam Digital CAMERA
  449                  * PR: usb/98713
  450                  */
  451                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "CAMERA*", "4MP-9J6*",
  452                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  453         },
  454         {
  455                 /*
  456                  * iRiver H10 MP3 player
  457                  * PR: usb/102547
  458                  */
  459                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "H10*",
  460                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  461        },
  462         {
  463                 /*
  464                  * X-Micro Flash Disk
  465                  * PR: usb/96901
  466                  */
  467                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "X-Micro" , "Flash Disk",
  468                 "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  469         },
  470         {
  471                 /*
  472                  * EasyMP3 EM732X USB 2.0 Flash MP3 Player
  473                  * PR: usb/96546
  474                  */
  475                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "EM732X", "MP3 Player*",
  476                 "1.0"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  477         },
  478 };
  479 
  480 static  disk_strategy_t dastrategy;
  481 static  dumper_t        dadump;
  482 static  periph_init_t   dainit;
  483 static  void            daasync(void *callback_arg, u_int32_t code,
  484                                 struct cam_path *path, void *arg);
  485 static  void            dasysctlinit(void *context, int pending);
  486 static  int             dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
  487 static  periph_ctor_t   daregister;
  488 static  periph_dtor_t   dacleanup;
  489 static  periph_start_t  dastart;
  490 static  periph_oninv_t  daoninvalidate;
  491 static  void            dadone(struct cam_periph *periph,
  492                                union ccb *done_ccb);
  493 static  int             daerror(union ccb *ccb, u_int32_t cam_flags,
  494                                 u_int32_t sense_flags);
  495 static void             daprevent(struct cam_periph *periph, int action);
  496 static int              dagetcapacity(struct cam_periph *periph);
  497 static void             dasetgeom(struct cam_periph *periph, uint32_t block_len,
  498                                   uint64_t maxsector);
  499 static timeout_t        dasendorderedtag;
  500 static void             dashutdown(void *arg, int howto);
  501 
  502 #ifndef DA_DEFAULT_TIMEOUT
  503 #define DA_DEFAULT_TIMEOUT 60   /* Timeout in seconds */
  504 #endif
  505 
  506 #ifndef DA_DEFAULT_RETRY
  507 #define DA_DEFAULT_RETRY        4
  508 #endif
  509 
  510 #ifndef DA_DEFAULT_SEND_ORDERED
  511 #define DA_DEFAULT_SEND_ORDERED 1
  512 #endif
  513 
  514 
  515 static int da_retry_count = DA_DEFAULT_RETRY;
  516 static int da_default_timeout = DA_DEFAULT_TIMEOUT;
  517 static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
  518 
  519 SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
  520             "CAM Direct Access Disk driver");
  521 SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW,
  522            &da_retry_count, 0, "Normal I/O retry count");
  523 TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count);
  524 SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
  525            &da_default_timeout, 0, "Normal I/O timeout (in seconds)");
  526 TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
  527 SYSCTL_INT(_kern_cam_da, OID_AUTO, da_send_ordered, CTLFLAG_RW,
  528            &da_send_ordered, 0, "Send Ordered Tags");
  529 TUNABLE_INT("kern.cam.da.da_send_ordered", &da_send_ordered);
  530 
  531 /*
  532  * DA_ORDEREDTAG_INTERVAL determines how often, relative
  533  * to the default timeout, we check to see whether an ordered
  534  * tagged transaction is appropriate to prevent simple tag
  535  * starvation.  Since we'd like to ensure that there is at least
  536  * 1/2 of the timeout length left for a starved transaction to
  537  * complete after we've sent an ordered tag, we must poll at least
  538  * four times in every timeout period.  This takes care of the worst
  539  * case where a starved transaction starts during an interval that
  540  * meets the requirement "don't send an ordered tag" test so it takes
  541  * us two intervals to determine that a tag must be sent.
  542  */
  543 #ifndef DA_ORDEREDTAG_INTERVAL
  544 #define DA_ORDEREDTAG_INTERVAL 4
  545 #endif
  546 
  547 static struct periph_driver dadriver =
  548 {
  549         dainit, "da",
  550         TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
  551 };
  552 
  553 PERIPHDRIVER_DECLARE(da, dadriver);
  554 
  555 static SLIST_HEAD(,da_softc) softc_list;
  556 
  557 static int
  558 daopen(struct disk *dp)
  559 {
  560         struct cam_periph *periph;
  561         struct da_softc *softc;
  562         int unit;
  563         int error;
  564         int s;
  565 
  566         s = splsoftcam();
  567         periph = (struct cam_periph *)dp->d_drv1;
  568         if (periph == NULL) {
  569                 splx(s);
  570                 return (ENXIO); 
  571         }
  572         unit = periph->unit_number;
  573 
  574         softc = (struct da_softc *)periph->softc;
  575 
  576         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
  577             ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
  578              unit));
  579 
  580         if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
  581                 return (error); /* error code from tsleep */
  582 
  583         if (cam_periph_acquire(periph) != CAM_REQ_CMP)
  584                 return(ENXIO);
  585         softc->flags |= DA_FLAG_OPEN;
  586 
  587         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
  588                 /* Invalidate our pack information. */
  589                 softc->flags &= ~DA_FLAG_PACK_INVALID;
  590         }
  591         splx(s);
  592 
  593         error = dagetcapacity(periph);
  594 
  595         if (error == 0) {
  596 
  597                 softc->disk->d_sectorsize = softc->params.secsize;
  598                 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
  599                 /* XXX: these are not actually "firmware" values, so they may be wrong */
  600                 softc->disk->d_fwsectors = softc->params.secs_per_track;
  601                 softc->disk->d_fwheads = softc->params.heads;
  602                 softc->disk->d_devstat->block_size = softc->params.secsize;
  603                 softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
  604         }
  605         
  606         if (error == 0) {
  607                 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
  608                     (softc->quirks & DA_Q_NO_PREVENT) == 0)
  609                         daprevent(periph, PR_PREVENT);
  610         } else {
  611                 softc->flags &= ~DA_FLAG_OPEN;
  612                 cam_periph_release(periph);
  613         }
  614         cam_periph_unlock(periph);
  615         return (error);
  616 }
  617 
  618 static int
  619 daclose(struct disk *dp)
  620 {
  621         struct  cam_periph *periph;
  622         struct  da_softc *softc;
  623         int     error;
  624 
  625         periph = (struct cam_periph *)dp->d_drv1;
  626         if (periph == NULL)
  627                 return (ENXIO); 
  628 
  629         softc = (struct da_softc *)periph->softc;
  630 
  631         if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
  632                 return (error); /* error code from tsleep */
  633         }
  634 
  635         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
  636                 union   ccb *ccb;
  637 
  638                 ccb = cam_periph_getccb(periph, /*priority*/1);
  639 
  640                 scsi_synchronize_cache(&ccb->csio,
  641                                        /*retries*/1,
  642                                        /*cbfcnp*/dadone,
  643                                        MSG_SIMPLE_Q_TAG,
  644                                        /*begin_lba*/0,/* Cover the whole disk */
  645                                        /*lb_count*/0,
  646                                        SSD_FULL_SIZE,
  647                                        5 * 60 * 1000);
  648 
  649                 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
  650                                   /*sense_flags*/SF_RETRY_UA,
  651                                   softc->disk->d_devstat);
  652 
  653                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  654                         if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
  655                              CAM_SCSI_STATUS_ERROR) {
  656                                 int asc, ascq;
  657                                 int sense_key, error_code;
  658 
  659                                 scsi_extract_sense(&ccb->csio.sense_data,
  660                                                    &error_code,
  661                                                    &sense_key, 
  662                                                    &asc, &ascq);
  663                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
  664                                         scsi_sense_print(&ccb->csio);
  665                         } else {
  666                                 xpt_print_path(periph->path);
  667                                 printf("Synchronize cache failed, status "
  668                                        "== 0x%x, scsi status == 0x%x\n",
  669                                        ccb->csio.ccb_h.status,
  670                                        ccb->csio.scsi_status);
  671                         }
  672                 }
  673 
  674                 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  675                         cam_release_devq(ccb->ccb_h.path,
  676                                          /*relsim_flags*/0,
  677                                          /*reduction*/0,
  678                                          /*timeout*/0,
  679                                          /*getcount_only*/0);
  680 
  681                 xpt_release_ccb(ccb);
  682 
  683         }
  684 
  685         if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
  686                 if ((softc->quirks & DA_Q_NO_PREVENT) == 0)
  687                         daprevent(periph, PR_ALLOW);
  688                 /*
  689                  * If we've got removeable media, mark the blocksize as
  690                  * unavailable, since it could change when new media is
  691                  * inserted.
  692                  */
  693                 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
  694         }
  695 
  696         softc->flags &= ~DA_FLAG_OPEN;
  697         cam_periph_unlock(periph);
  698         cam_periph_release(periph);
  699         return (0);     
  700 }
  701 
  702 /*
  703  * Actually translate the requested transfer into one the physical driver
  704  * can understand.  The transfer is described by a buf and will include
  705  * only one physical transfer.
  706  */
  707 static void
  708 dastrategy(struct bio *bp)
  709 {
  710         struct cam_periph *periph;
  711         struct da_softc *softc;
  712         int    s;
  713         
  714         periph = (struct cam_periph *)bp->bio_disk->d_drv1;
  715         if (periph == NULL) {
  716                 biofinish(bp, NULL, ENXIO);
  717                 return;
  718         }
  719         softc = (struct da_softc *)periph->softc;
  720 #if 0
  721         /*
  722          * check it's not too big a transfer for our adapter
  723          */
  724         scsi_minphys(bp,&sd_switch);
  725 #endif
  726 
  727         /*
  728          * Mask interrupts so that the pack cannot be invalidated until
  729          * after we are in the queue.  Otherwise, we might not properly
  730          * clean up one of the buffers.
  731          */
  732         s = splbio();
  733         
  734         /*
  735          * If the device has been made invalid, error out
  736          */
  737         if ((softc->flags & DA_FLAG_PACK_INVALID)) {
  738                 splx(s);
  739                 biofinish(bp, NULL, ENXIO);
  740                 return;
  741         }
  742         
  743         /*
  744          * Place it in the queue of disk activities for this disk
  745          */
  746         bioq_disksort(&softc->bio_queue, bp);
  747 
  748         splx(s);
  749         
  750         /*
  751          * Schedule ourselves for performing the work.
  752          */
  753         xpt_schedule(periph, /* XXX priority */1);
  754 
  755         return;
  756 }
  757 
  758 static int
  759 dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
  760 {
  761         struct      cam_periph *periph;
  762         struct      da_softc *softc;
  763         u_int       secsize;
  764         struct      ccb_scsiio csio;
  765         struct      disk *dp;
  766 
  767         dp = arg;
  768         periph = dp->d_drv1;
  769         if (periph == NULL)
  770                 return (ENXIO);
  771         softc = (struct da_softc *)periph->softc;
  772         secsize = softc->params.secsize;
  773         
  774         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
  775                 return (ENXIO);
  776 
  777         if (length > 0) {
  778                 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
  779                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
  780                 scsi_read_write(&csio,
  781                                 /*retries*/1,
  782                                 dadone,
  783                                 MSG_ORDERED_Q_TAG,
  784                                 /*read*/FALSE,
  785                                 /*byte2*/0,
  786                                 /*minimum_cmd_size*/ softc->minimum_cmd_size,
  787                                 offset / secsize,
  788                                 length / secsize,
  789                                 /*data_ptr*/(u_int8_t *) virtual,
  790                                 /*dxfer_len*/length,
  791                                 /*sense_len*/SSD_FULL_SIZE,
  792                                 DA_DEFAULT_TIMEOUT * 1000);             
  793                 xpt_polled_action((union ccb *)&csio);
  794 
  795                 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  796                         printf("Aborting dump due to I/O error.\n");
  797                         if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
  798                              CAM_SCSI_STATUS_ERROR)
  799                                 scsi_sense_print(&csio);
  800                         else
  801                                 printf("status == 0x%x, scsi status == 0x%x\n",
  802                                        csio.ccb_h.status, csio.scsi_status);
  803                         return(EIO);
  804                 }
  805                 return(0);
  806         } 
  807                 
  808         /*
  809          * Sync the disk cache contents to the physical media.
  810          */
  811         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
  812 
  813                 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
  814                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
  815                 scsi_synchronize_cache(&csio,
  816                                        /*retries*/1,
  817                                        /*cbfcnp*/dadone,
  818                                        MSG_SIMPLE_Q_TAG,
  819                                        /*begin_lba*/0,/* Cover the whole disk */
  820                                        /*lb_count*/0,
  821                                        SSD_FULL_SIZE,
  822                                        5 * 60 * 1000);
  823                 xpt_polled_action((union ccb *)&csio);
  824 
  825                 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  826                         if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
  827                              CAM_SCSI_STATUS_ERROR) {
  828                                 int asc, ascq;
  829                                 int sense_key, error_code;
  830 
  831                                 scsi_extract_sense(&csio.sense_data,
  832                                                    &error_code,
  833                                                    &sense_key, 
  834                                                    &asc, &ascq);
  835                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
  836                                         scsi_sense_print(&csio);
  837                         } else {
  838                                 xpt_print_path(periph->path);
  839                                 printf("Synchronize cache failed, status "
  840                                        "== 0x%x, scsi status == 0x%x\n",
  841                                        csio.ccb_h.status, csio.scsi_status);
  842                         }
  843                 }
  844         }
  845         return (0);
  846 }
  847 
  848 static void
  849 dainit(void)
  850 {
  851         cam_status status;
  852         struct cam_path *path;
  853 
  854         SLIST_INIT(&softc_list);
  855         
  856         /*
  857          * Install a global async callback.  This callback will
  858          * receive async callbacks like "new device found".
  859          */
  860         status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
  861                                  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
  862 
  863         if (status == CAM_REQ_CMP) {
  864                 struct ccb_setasync csa;
  865 
  866                 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
  867                 csa.ccb_h.func_code = XPT_SASYNC_CB;
  868                 csa.event_enable = AC_FOUND_DEVICE;
  869                 csa.callback = daasync;
  870                 csa.callback_arg = NULL;
  871                 xpt_action((union ccb *)&csa);
  872                 status = csa.ccb_h.status;
  873                 xpt_free_path(path);
  874         }
  875 
  876         if (status != CAM_REQ_CMP) {
  877                 printf("da: Failed to attach master async callback "
  878                        "due to status 0x%x!\n", status);
  879         } else if (da_send_ordered) {
  880 
  881                 /*
  882                  * Schedule a periodic event to occasionally send an
  883                  * ordered tag to a device.
  884                  */
  885                 timeout(dasendorderedtag, NULL,
  886                         (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
  887 
  888                 /* Register our shutdown event handler */
  889                 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown, 
  890                                            NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
  891                     printf("dainit: shutdown event registration failed!\n");
  892         }
  893 }
  894 
  895 static void
  896 daoninvalidate(struct cam_periph *periph)
  897 {
  898         int s;
  899         struct da_softc *softc;
  900         struct ccb_setasync csa;
  901 
  902         softc = (struct da_softc *)periph->softc;
  903 
  904         /*
  905          * De-register any async callbacks.
  906          */
  907         xpt_setup_ccb(&csa.ccb_h, periph->path,
  908                       /* priority */ 5);
  909         csa.ccb_h.func_code = XPT_SASYNC_CB;
  910         csa.event_enable = 0;
  911         csa.callback = daasync;
  912         csa.callback_arg = periph;
  913         xpt_action((union ccb *)&csa);
  914 
  915         softc->flags |= DA_FLAG_PACK_INVALID;
  916 
  917         /*
  918          * Although the oninvalidate() routines are always called at
  919          * splsoftcam, we need to be at splbio() here to keep the buffer
  920          * queue from being modified while we traverse it.
  921          */
  922         s = splbio();
  923 
  924         /*
  925          * Return all queued I/O with ENXIO.
  926          * XXX Handle any transactions queued to the card
  927          *     with XPT_ABORT_CCB.
  928          */
  929         bioq_flush(&softc->bio_queue, NULL, ENXIO);
  930         splx(s);
  931 
  932         SLIST_REMOVE(&softc_list, softc, da_softc, links);
  933 
  934         disk_gone(softc->disk);
  935         xpt_print_path(periph->path);
  936         printf("lost device\n");
  937 }
  938 
  939 static void
  940 dacleanup(struct cam_periph *periph)
  941 {
  942         struct da_softc *softc;
  943 
  944         softc = (struct da_softc *)periph->softc;
  945 
  946         xpt_print_path(periph->path);
  947         printf("removing device entry\n");
  948         /*
  949          * If we can't free the sysctl tree, oh well...
  950          */
  951         if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
  952             && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
  953                 xpt_print_path(periph->path);
  954                 printf("can't remove sysctl context\n");
  955         }
  956         disk_destroy(softc->disk);
  957         free(softc, M_DEVBUF);
  958 }
  959 
  960 static void
  961 daasync(void *callback_arg, u_int32_t code,
  962         struct cam_path *path, void *arg)
  963 {
  964         struct cam_periph *periph;
  965 
  966         periph = (struct cam_periph *)callback_arg;
  967         switch (code) {
  968         case AC_FOUND_DEVICE:
  969         {
  970                 struct ccb_getdev *cgd;
  971                 cam_status status;
  972  
  973                 cgd = (struct ccb_getdev *)arg;
  974                 if (cgd == NULL)
  975                         break;
  976 
  977                 if (SID_TYPE(&cgd->inq_data) != T_DIRECT
  978                     && SID_TYPE(&cgd->inq_data) != T_RBC
  979                     && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
  980                         break;
  981 
  982                 /*
  983                  * Allocate a peripheral instance for
  984                  * this device and start the probe
  985                  * process.
  986                  */
  987                 status = cam_periph_alloc(daregister, daoninvalidate,
  988                                           dacleanup, dastart,
  989                                           "da", CAM_PERIPH_BIO,
  990                                           cgd->ccb_h.path, daasync,
  991                                           AC_FOUND_DEVICE, cgd);
  992 
  993                 if (status != CAM_REQ_CMP
  994                  && status != CAM_REQ_INPROG)
  995                         printf("daasync: Unable to attach to new device "
  996                                 "due to status 0x%x\n", status);
  997                 break;
  998         }
  999         case AC_SENT_BDR:
 1000         case AC_BUS_RESET:
 1001         {
 1002                 struct da_softc *softc;
 1003                 struct ccb_hdr *ccbh;
 1004                 int s;
 1005 
 1006                 softc = (struct da_softc *)periph->softc;
 1007                 s = splsoftcam();
 1008                 /*
 1009                  * Don't fail on the expected unit attention
 1010                  * that will occur.
 1011                  */
 1012                 softc->flags |= DA_FLAG_RETRY_UA;
 1013                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
 1014                         ccbh->ccb_state |= DA_CCB_RETRY_UA;
 1015                 splx(s);
 1016                 /* FALLTHROUGH*/
 1017         }
 1018         default:
 1019                 cam_periph_async(periph, code, path, arg);
 1020                 break;
 1021         }
 1022 }
 1023 
 1024 static void
 1025 dasysctlinit(void *context, int pending)
 1026 {
 1027         struct cam_periph *periph;
 1028         struct da_softc *softc;
 1029         char tmpstr[80], tmpstr2[80];
 1030 
 1031         periph = (struct cam_periph *)context;
 1032         softc = (struct da_softc *)periph->softc;
 1033 
 1034         snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
 1035         snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
 1036 
 1037         mtx_lock(&Giant);
 1038         sysctl_ctx_init(&softc->sysctl_ctx);
 1039         softc->flags |= DA_FLAG_SCTX_INIT;
 1040         softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
 1041                 SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
 1042                 CTLFLAG_RD, 0, tmpstr);
 1043         if (softc->sysctl_tree == NULL) {
 1044                 printf("dasysctlinit: unable to allocate sysctl tree\n");
 1045                 mtx_unlock(&Giant);
 1046                 return;
 1047         }
 1048 
 1049         /*
 1050          * Now register the sysctl handler, so the user can the value on
 1051          * the fly.
 1052          */
 1053         SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
 1054                 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
 1055                 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
 1056                 "Minimum CDB size");
 1057 
 1058         mtx_unlock(&Giant);
 1059 }
 1060 
 1061 static int
 1062 dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
 1063 {
 1064         int error, value;
 1065 
 1066         value = *(int *)arg1;
 1067 
 1068         error = sysctl_handle_int(oidp, &value, 0, req);
 1069 
 1070         if ((error != 0)
 1071          || (req->newptr == NULL))
 1072                 return (error);
 1073 
 1074         /*
 1075          * Acceptable values here are 6, 10, 12 or 16.
 1076          */
 1077         if (value < 6)
 1078                 value = 6;
 1079         else if ((value > 6)
 1080               && (value <= 10))
 1081                 value = 10;
 1082         else if ((value > 10)
 1083               && (value <= 12))
 1084                 value = 12;
 1085         else if (value > 12)
 1086                 value = 16;
 1087 
 1088         *(int *)arg1 = value;
 1089 
 1090         return (0);
 1091 }
 1092 
 1093 static cam_status
 1094 daregister(struct cam_periph *periph, void *arg)
 1095 {
 1096         int s;
 1097         struct da_softc *softc;
 1098         struct ccb_setasync csa;
 1099         struct ccb_pathinq cpi;
 1100         struct ccb_getdev *cgd;
 1101         char tmpstr[80];
 1102         caddr_t match;
 1103 
 1104         cgd = (struct ccb_getdev *)arg;
 1105         if (periph == NULL) {
 1106                 printf("daregister: periph was NULL!!\n");
 1107                 return(CAM_REQ_CMP_ERR);
 1108         }
 1109 
 1110         if (cgd == NULL) {
 1111                 printf("daregister: no getdev CCB, can't register device\n");
 1112                 return(CAM_REQ_CMP_ERR);
 1113         }
 1114 
 1115         softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
 1116             M_NOWAIT|M_ZERO);
 1117 
 1118         if (softc == NULL) {
 1119                 printf("daregister: Unable to probe new device. "
 1120                        "Unable to allocate softc\n");                           
 1121                 return(CAM_REQ_CMP_ERR);
 1122         }
 1123 
 1124         LIST_INIT(&softc->pending_ccbs);
 1125         softc->state = DA_STATE_PROBE;
 1126         bioq_init(&softc->bio_queue);
 1127         if (SID_IS_REMOVABLE(&cgd->inq_data))
 1128                 softc->flags |= DA_FLAG_PACK_REMOVABLE;
 1129         if ((cgd->inq_data.flags & SID_CmdQue) != 0)
 1130                 softc->flags |= DA_FLAG_TAGGED_QUEUING;
 1131 
 1132         periph->softc = softc;
 1133 
 1134         /*
 1135          * See if this device has any quirks.
 1136          */
 1137         match = cam_quirkmatch((caddr_t)&cgd->inq_data,
 1138                                (caddr_t)da_quirk_table,
 1139                                sizeof(da_quirk_table)/sizeof(*da_quirk_table),
 1140                                sizeof(*da_quirk_table), scsi_inquiry_match);
 1141 
 1142         if (match != NULL)
 1143                 softc->quirks = ((struct da_quirk_entry *)match)->quirks;
 1144         else
 1145                 softc->quirks = DA_Q_NONE;
 1146 
 1147         /* Check if the SIM does not want 6 byte commands */
 1148         xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1);
 1149         cpi.ccb_h.func_code = XPT_PATH_INQ;
 1150         xpt_action((union ccb *)&cpi);
 1151         if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
 1152                 softc->quirks |= DA_Q_NO_6_BYTE;
 1153 
 1154         TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
 1155 
 1156         /*
 1157          * RBC devices don't have to support READ(6), only READ(10).
 1158          */
 1159         if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
 1160                 softc->minimum_cmd_size = 10;
 1161         else
 1162                 softc->minimum_cmd_size = 6;
 1163 
 1164         /*
 1165          * Load the user's default, if any.
 1166          */
 1167         snprintf(tmpstr, sizeof(tmpstr), "kern.cam.da.%d.minimum_cmd_size",
 1168                  periph->unit_number);
 1169         TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
 1170 
 1171         /*
 1172          * 6, 10, 12 and 16 are the currently permissible values.
 1173          */
 1174         if (softc->minimum_cmd_size < 6)
 1175                 softc->minimum_cmd_size = 6;
 1176         else if ((softc->minimum_cmd_size > 6)
 1177               && (softc->minimum_cmd_size <= 10))
 1178                 softc->minimum_cmd_size = 10;
 1179         else if ((softc->minimum_cmd_size > 10)
 1180               && (softc->minimum_cmd_size <= 12))
 1181                 softc->minimum_cmd_size = 12;
 1182         else if (softc->minimum_cmd_size > 12)
 1183                 softc->minimum_cmd_size = 16;
 1184 
 1185         /*
 1186          * Block our timeout handler while we
 1187          * add this softc to the dev list.
 1188          */
 1189         s = splsoftclock();
 1190         SLIST_INSERT_HEAD(&softc_list, softc, links);
 1191         splx(s);
 1192 
 1193         /*
 1194          * Register this media as a disk
 1195          */
 1196 
 1197         softc->disk = disk_alloc();
 1198         softc->disk->d_open = daopen;
 1199         softc->disk->d_close = daclose;
 1200         softc->disk->d_strategy = dastrategy;
 1201         softc->disk->d_dump = dadump;
 1202         softc->disk->d_name = "da";
 1203         softc->disk->d_drv1 = periph;
 1204         softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
 1205         softc->disk->d_unit = periph->unit_number;
 1206         softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
 1207         disk_create(softc->disk, DISK_VERSION);
 1208 
 1209         /*
 1210          * Add async callbacks for bus reset and
 1211          * bus device reset calls.  I don't bother
 1212          * checking if this fails as, in most cases,
 1213          * the system will function just fine without
 1214          * them and the only alternative would be to
 1215          * not attach the device on failure.
 1216          */
 1217         xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
 1218         csa.ccb_h.func_code = XPT_SASYNC_CB;
 1219         csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
 1220         csa.callback = daasync;
 1221         csa.callback_arg = periph;
 1222         xpt_action((union ccb *)&csa);
 1223         /*
 1224          * Lock this peripheral until we are setup.
 1225          * This first call can't block
 1226          */
 1227         (void)cam_periph_lock(periph, PRIBIO);
 1228         xpt_schedule(periph, /*priority*/5);
 1229 
 1230         return(CAM_REQ_CMP);
 1231 }
 1232 
 1233 static void
 1234 dastart(struct cam_periph *periph, union ccb *start_ccb)
 1235 {
 1236         struct da_softc *softc;
 1237 
 1238         softc = (struct da_softc *)periph->softc;
 1239 
 1240         
 1241         switch (softc->state) {
 1242         case DA_STATE_NORMAL:
 1243         {
 1244                 /* Pull a buffer from the queue and get going on it */          
 1245                 struct bio *bp;
 1246                 int s;
 1247 
 1248                 /*
 1249                  * See if there is a buf with work for us to do..
 1250                  */
 1251                 s = splbio();
 1252                 bp = bioq_first(&softc->bio_queue);
 1253                 if (periph->immediate_priority <= periph->pinfo.priority) {
 1254                         CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
 1255                                         ("queuing for immediate ccb\n"));
 1256                         start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
 1257                         SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
 1258                                           periph_links.sle);
 1259                         periph->immediate_priority = CAM_PRIORITY_NONE;
 1260                         splx(s);
 1261                         wakeup(&periph->ccb_list);
 1262                 } else if (bp == NULL) {
 1263                         splx(s);
 1264                         xpt_release_ccb(start_ccb);
 1265                 } else {
 1266                         int oldspl;
 1267                         u_int8_t tag_code;
 1268 
 1269                         bioq_remove(&softc->bio_queue, bp);
 1270 
 1271                         if ((softc->flags & DA_FLAG_NEED_OTAG) != 0) {
 1272                                 softc->flags &= ~DA_FLAG_NEED_OTAG;
 1273                                 softc->ordered_tag_count++;
 1274                                 tag_code = MSG_ORDERED_Q_TAG;
 1275                         } else {
 1276                                 tag_code = MSG_SIMPLE_Q_TAG;
 1277                         }
 1278                         scsi_read_write(&start_ccb->csio,
 1279                                         /*retries*/da_retry_count,
 1280                                         /*cbfcnp*/dadone,
 1281                                         /*tag_action*/tag_code,
 1282                                         /*read_op*/bp->bio_cmd == BIO_READ,
 1283                                         /*byte2*/0,
 1284                                         softc->minimum_cmd_size,
 1285                                         /*lba*/bp->bio_pblkno,
 1286                                         /*block_count*/bp->bio_bcount /
 1287                                         softc->params.secsize,
 1288                                         /*data_ptr*/ bp->bio_data,
 1289                                         /*dxfer_len*/ bp->bio_bcount,
 1290                                         /*sense_len*/SSD_FULL_SIZE,
 1291                                         /*timeout*/da_default_timeout*1000);
 1292                         start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
 1293 
 1294                         /*
 1295                          * Block out any asyncronous callbacks
 1296                          * while we touch the pending ccb list.
 1297                          */
 1298                         oldspl = splcam();
 1299                         LIST_INSERT_HEAD(&softc->pending_ccbs,
 1300                                          &start_ccb->ccb_h, periph_links.le);
 1301                         softc->outstanding_cmds++;
 1302                         splx(oldspl);
 1303 
 1304                         /* We expect a unit attention from this device */
 1305                         if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
 1306                                 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
 1307                                 softc->flags &= ~DA_FLAG_RETRY_UA;
 1308                         }
 1309 
 1310                         start_ccb->ccb_h.ccb_bp = bp;
 1311                         bp = bioq_first(&softc->bio_queue);
 1312                         splx(s);
 1313 
 1314                         xpt_action(start_ccb);
 1315                 }
 1316                 
 1317                 if (bp != NULL) {
 1318                         /* Have more work to do, so ensure we stay scheduled */
 1319                         xpt_schedule(periph, /* XXX priority */1);
 1320                 }
 1321                 break;
 1322         }
 1323         case DA_STATE_PROBE:
 1324         {
 1325                 struct ccb_scsiio *csio;
 1326                 struct scsi_read_capacity_data *rcap;
 1327 
 1328                 rcap = (struct scsi_read_capacity_data *)
 1329                     malloc(sizeof(*rcap), M_TEMP, M_NOWAIT|M_ZERO);
 1330                 if (rcap == NULL) {
 1331                         printf("dastart: Couldn't malloc read_capacity data\n");
 1332                         /* da_free_periph??? */
 1333                         break;
 1334                 }
 1335                 csio = &start_ccb->csio;
 1336                 scsi_read_capacity(csio,
 1337                                    /*retries*/4,
 1338                                    dadone,
 1339                                    MSG_SIMPLE_Q_TAG,
 1340                                    rcap,
 1341                                    SSD_FULL_SIZE,
 1342                                    /*timeout*/5000);
 1343                 start_ccb->ccb_h.ccb_bp = NULL;
 1344                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE;
 1345                 xpt_action(start_ccb);
 1346                 break;
 1347         }
 1348         case DA_STATE_PROBE2:
 1349         {
 1350                 struct ccb_scsiio *csio;
 1351                 struct scsi_read_capacity_data_long *rcaplong;
 1352 
 1353                 rcaplong = (struct scsi_read_capacity_data_long *)
 1354                         malloc(sizeof(*rcaplong), M_TEMP, M_NOWAIT|M_ZERO);
 1355                 if (rcaplong == NULL) {
 1356                         printf("dastart: Couldn't malloc read_capacity data\n");
 1357                         /* da_free_periph??? */
 1358                         break;
 1359                 }
 1360                 csio = &start_ccb->csio;
 1361                 scsi_read_capacity_16(csio,
 1362                                       /*retries*/ 4,
 1363                                       /*cbfcnp*/ dadone,
 1364                                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1365                                       /*lba*/ 0,
 1366                                       /*reladr*/ 0,
 1367                                       /*pmi*/ 0,
 1368                                       rcaplong,
 1369                                       /*sense_len*/ SSD_FULL_SIZE,
 1370                                       /*timeout*/ 60000);
 1371                 start_ccb->ccb_h.ccb_bp = NULL;
 1372                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2;
 1373                 xpt_action(start_ccb);  
 1374                 break;
 1375         }
 1376         }
 1377 }
 1378 
 1379 static int
 1380 cmd6workaround(union ccb *ccb)
 1381 {
 1382         struct scsi_rw_6 cmd6;
 1383         struct scsi_rw_10 *cmd10;
 1384         struct da_softc *softc;
 1385         u_int8_t *cdb;
 1386         int frozen;
 1387 
 1388         cdb = ccb->csio.cdb_io.cdb_bytes;
 1389 
 1390         /* Translation only possible if CDB is an array and cmd is R/W6 */
 1391         if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
 1392             (*cdb != READ_6 && *cdb != WRITE_6))
 1393                 return 0;
 1394 
 1395         xpt_print_path(ccb->ccb_h.path);
 1396         printf("READ(6)/WRITE(6) not supported, "
 1397                "increasing minimum_cmd_size to 10.\n");
 1398         softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
 1399         softc->minimum_cmd_size = 10;
 1400 
 1401         bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
 1402         cmd10 = (struct scsi_rw_10 *)cdb;
 1403         cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
 1404         cmd10->byte2 = 0;
 1405         scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
 1406         cmd10->reserved = 0;
 1407         scsi_ulto2b(cmd6.length, cmd10->length);
 1408         cmd10->control = cmd6.control;
 1409         ccb->csio.cdb_len = sizeof(*cmd10);
 1410 
 1411         /* Requeue request, unfreezing queue if necessary */
 1412         frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
 1413         ccb->ccb_h.status = CAM_REQUEUE_REQ;
 1414         xpt_action(ccb);
 1415         if (frozen) {
 1416                 cam_release_devq(ccb->ccb_h.path,
 1417                                  /*relsim_flags*/0,
 1418                                  /*reduction*/0,
 1419                                  /*timeout*/0,
 1420                                  /*getcount_only*/0);
 1421         }
 1422         return (ERESTART);
 1423 }
 1424 
 1425 static void
 1426 dadone(struct cam_periph *periph, union ccb *done_ccb)
 1427 {
 1428         struct da_softc *softc;
 1429         struct ccb_scsiio *csio;
 1430 
 1431         softc = (struct da_softc *)periph->softc;
 1432         csio = &done_ccb->csio;
 1433         switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
 1434         case DA_CCB_BUFFER_IO:
 1435         {
 1436                 struct bio *bp;
 1437                 int    oldspl;
 1438 
 1439                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 1440                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1441                         int error;
 1442                         int s;
 1443                         int sf;
 1444                         
 1445                         if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
 1446                                 sf = SF_RETRY_UA;
 1447                         else
 1448                                 sf = 0;
 1449 
 1450                         error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
 1451                         if (error == ERESTART) {
 1452                                 /*
 1453                                  * A retry was scheuled, so
 1454                                  * just return.
 1455                                  */
 1456                                 return;
 1457                         }
 1458                         if (error != 0) {
 1459 
 1460                                 s = splbio();
 1461 
 1462                                 if (error == ENXIO) {
 1463                                         /*
 1464                                          * Catastrophic error.  Mark our pack as
 1465                                          * invalid.
 1466                                          */
 1467                                         /* XXX See if this is really a media
 1468                                          *     change first.
 1469                                          */
 1470                                         xpt_print_path(periph->path);
 1471                                         printf("Invalidating pack\n");
 1472                                         softc->flags |= DA_FLAG_PACK_INVALID;
 1473                                 }
 1474 
 1475                                 /*
 1476                                  * return all queued I/O with EIO, so that
 1477                                  * the client can retry these I/Os in the
 1478                                  * proper order should it attempt to recover.
 1479                                  */
 1480                                 bioq_flush(&softc->bio_queue, NULL, EIO);
 1481                                 splx(s);
 1482                                 bp->bio_error = error;
 1483                                 bp->bio_resid = bp->bio_bcount;
 1484                                 bp->bio_flags |= BIO_ERROR;
 1485                         } else {
 1486                                 bp->bio_resid = csio->resid;
 1487                                 bp->bio_error = 0;
 1488                                 if (bp->bio_resid != 0)
 1489                                         bp->bio_flags |= BIO_ERROR;
 1490                         }
 1491                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1492                                 cam_release_devq(done_ccb->ccb_h.path,
 1493                                                  /*relsim_flags*/0,
 1494                                                  /*reduction*/0,
 1495                                                  /*timeout*/0,
 1496                                                  /*getcount_only*/0);
 1497                 } else {
 1498                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1499                                 panic("REQ_CMP with QFRZN");
 1500                         bp->bio_resid = csio->resid;
 1501                         if (csio->resid > 0)
 1502                                 bp->bio_flags |= BIO_ERROR;
 1503                 }
 1504 
 1505                 /*
 1506                  * Block out any asyncronous callbacks
 1507                  * while we touch the pending ccb list.
 1508                  */
 1509                 oldspl = splcam();
 1510                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
 1511                 softc->outstanding_cmds--;
 1512                 if (softc->outstanding_cmds == 0)
 1513                         softc->flags |= DA_FLAG_WENT_IDLE;
 1514                 splx(oldspl);
 1515 
 1516                 biodone(bp);
 1517                 break;
 1518         }
 1519         case DA_CCB_PROBE:
 1520         case DA_CCB_PROBE2:
 1521         {
 1522                 struct     scsi_read_capacity_data *rdcap;
 1523                 struct     scsi_read_capacity_data_long *rcaplong;
 1524                 char       announce_buf[80];
 1525 
 1526                 rdcap = NULL;
 1527                 rcaplong = NULL;
 1528                 if (softc->state == DA_STATE_PROBE)
 1529                         rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
 1530                 else
 1531                         rcaplong = (struct scsi_read_capacity_data_long *)
 1532                                 csio->data_ptr;
 1533 
 1534                 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
 1535                         struct disk_params *dp;
 1536                         uint32_t block_size;
 1537                         uint64_t maxsector;
 1538 
 1539                         if (softc->state == DA_STATE_PROBE) {
 1540                                 block_size = scsi_4btoul(rdcap->length);
 1541                                 maxsector = scsi_4btoul(rdcap->addr);
 1542 
 1543                                 /*
 1544                                  * According to SBC-2, if the standard 10
 1545                                  * byte READ CAPACITY command returns 2^32,
 1546                                  * we should issue the 16 byte version of
 1547                                  * the command, since the device in question
 1548                                  * has more sectors than can be represented
 1549                                  * with the short version of the command.
 1550                                  */
 1551                                 if (maxsector == 0xffffffff) {
 1552                                         softc->state = DA_STATE_PROBE2;
 1553                                         free(rdcap, M_TEMP);
 1554                                         xpt_release_ccb(done_ccb);
 1555                                         xpt_schedule(periph, /*priority*/5);
 1556                                         return;
 1557                                 }
 1558                         } else {
 1559                                 block_size = scsi_4btoul(rcaplong->length);
 1560                                 maxsector = scsi_8btou64(rcaplong->addr);
 1561                         }
 1562 
 1563                         /*
 1564                          * Because GEOM code just will panic us if we
 1565                          * give them an 'illegal' value we'll avoid that
 1566                          * here.
 1567                          */
 1568                         if (block_size >= MAXPHYS || block_size == 0) {
 1569                                 xpt_print_path(periph->path);
 1570                                 printf("unsupportable block size %ju\n",
 1571                                       (uintmax_t) block_size);
 1572                                 announce_buf[0] = '\0';
 1573                                 cam_periph_invalidate(periph);
 1574                         } else {
 1575                                 dasetgeom(periph, block_size, maxsector);
 1576                                 dp = &softc->params;
 1577                                 snprintf(announce_buf, sizeof(announce_buf),
 1578                                         "%juMB (%ju %u byte sectors: %dH %dS/T "
 1579                                         "%dC)", (uintmax_t)
 1580                                         (((uintmax_t)dp->secsize *
 1581                                         dp->sectors) / (1024*1024)),
 1582                                         (uintmax_t)dp->sectors,
 1583                                         dp->secsize, dp->heads,
 1584                                         dp->secs_per_track, dp->cylinders);
 1585                         }
 1586                 } else {
 1587                         int     error;
 1588 
 1589                         announce_buf[0] = '\0';
 1590 
 1591                         /*
 1592                          * Retry any UNIT ATTENTION type errors.  They
 1593                          * are expected at boot.
 1594                          */
 1595                         error = daerror(done_ccb, CAM_RETRY_SELTO,
 1596                                         SF_RETRY_UA|SF_NO_PRINT);
 1597                         if (error == ERESTART) {
 1598                                 /*
 1599                                  * A retry was scheuled, so
 1600                                  * just return.
 1601                                  */
 1602                                 return;
 1603                         } else if (error != 0) {
 1604                                 struct scsi_sense_data *sense;
 1605                                 int asc, ascq;
 1606                                 int sense_key, error_code;
 1607                                 int have_sense;
 1608                                 cam_status status;
 1609                                 struct ccb_getdev cgd;
 1610 
 1611                                 /* Don't wedge this device's queue */
 1612                                 status = done_ccb->ccb_h.status;
 1613                                 if ((status & CAM_DEV_QFRZN) != 0)
 1614                                         cam_release_devq(done_ccb->ccb_h.path,
 1615                                                          /*relsim_flags*/0,
 1616                                                          /*reduction*/0,
 1617                                                          /*timeout*/0,
 1618                                                          /*getcount_only*/0);
 1619 
 1620 
 1621                                 xpt_setup_ccb(&cgd.ccb_h, 
 1622                                               done_ccb->ccb_h.path,
 1623                                               /* priority */ 1);
 1624                                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 1625                                 xpt_action((union ccb *)&cgd);
 1626 
 1627                                 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
 1628                                  || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
 1629                                  || ((status & CAM_AUTOSNS_VALID) == 0))
 1630                                         have_sense = FALSE;
 1631                                 else
 1632                                         have_sense = TRUE;
 1633 
 1634                                 if (have_sense) {
 1635                                         sense = &csio->sense_data;
 1636                                         scsi_extract_sense(sense, &error_code,
 1637                                                            &sense_key, 
 1638                                                            &asc, &ascq);
 1639                                 }
 1640                                 /*
 1641                                  * Attach to anything that claims to be a
 1642                                  * direct access or optical disk device,
 1643                                  * as long as it doesn't return a "Logical
 1644                                  * unit not supported" (0x25) error.
 1645                                  */
 1646                                 if ((have_sense) && (asc != 0x25)
 1647                                  && (error_code == SSD_CURRENT_ERROR)) {
 1648                                         const char *sense_key_desc;
 1649                                         const char *asc_desc;
 1650 
 1651                                         scsi_sense_desc(sense_key, asc, ascq,
 1652                                                         &cgd.inq_data,
 1653                                                         &sense_key_desc,
 1654                                                         &asc_desc);
 1655                                         snprintf(announce_buf,
 1656                                             sizeof(announce_buf),
 1657                                                 "Attempt to query device "
 1658                                                 "size failed: %s, %s",
 1659                                                 sense_key_desc,
 1660                                                 asc_desc);
 1661                                 } else { 
 1662                                         if (have_sense)
 1663                                                 scsi_sense_print(
 1664                                                         &done_ccb->csio);
 1665                                         else {
 1666                                                 xpt_print_path(periph->path);
 1667                                                 printf("got CAM status %#x\n",
 1668                                                        done_ccb->ccb_h.status);
 1669                                         }
 1670 
 1671                                         xpt_print_path(periph->path);
 1672                                         printf("fatal error, failed" 
 1673                                                " to attach to device\n");
 1674 
 1675                                         /*
 1676                                          * Free up resources.
 1677                                          */
 1678                                         cam_periph_invalidate(periph);
 1679                                 } 
 1680                         }
 1681                 }
 1682                 free(csio->data_ptr, M_TEMP);
 1683                 if (announce_buf[0] != '\0') {
 1684                         xpt_announce_periph(periph, announce_buf);
 1685                         /*
 1686                          * Create our sysctl variables, now that we know
 1687                          * we have successfully attached.
 1688                          */
 1689                         taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
 1690                 }
 1691                 softc->state = DA_STATE_NORMAL; 
 1692                 /*
 1693                  * Since our peripheral may be invalidated by an error
 1694                  * above or an external event, we must release our CCB
 1695                  * before releasing the probe lock on the peripheral.
 1696                  * The peripheral will only go away once the last lock
 1697                  * is removed, and we need it around for the CCB release
 1698                  * operation.
 1699                  */
 1700                 xpt_release_ccb(done_ccb);
 1701                 cam_periph_unlock(periph);
 1702                 return;
 1703         }
 1704         case DA_CCB_WAITING:
 1705         {
 1706                 /* Caller will release the CCB */
 1707                 wakeup(&done_ccb->ccb_h.cbfcnp);
 1708                 return;
 1709         }
 1710         case DA_CCB_DUMP:
 1711                 /* No-op.  We're polling */
 1712                 return;
 1713         default:
 1714                 break;
 1715         }
 1716         xpt_release_ccb(done_ccb);
 1717 }
 1718 
 1719 static int
 1720 daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 1721 {
 1722         struct da_softc   *softc;
 1723         struct cam_periph *periph;
 1724         int error;
 1725 
 1726         periph = xpt_path_periph(ccb->ccb_h.path);
 1727         softc = (struct da_softc *)periph->softc;
 1728 
 1729         /*
 1730          * Automatically detect devices that do not support
 1731          * READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
 1732          */
 1733         error = 0;
 1734         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
 1735                 error = cmd6workaround(ccb);
 1736         } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
 1737                    CAM_SCSI_STATUS_ERROR)
 1738          && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)
 1739          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
 1740          && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0)
 1741          && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
 1742                 int sense_key, error_code, asc, ascq;
 1743 
 1744                 scsi_extract_sense(&ccb->csio.sense_data,
 1745                                    &error_code, &sense_key, &asc, &ascq);
 1746                 if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
 1747                         error = cmd6workaround(ccb);
 1748         }
 1749         if (error == ERESTART)
 1750                 return (ERESTART);
 1751 
 1752         /*
 1753          * XXX
 1754          * Until we have a better way of doing pack validation,
 1755          * don't treat UAs as errors.
 1756          */
 1757         sense_flags |= SF_RETRY_UA;
 1758         return(cam_periph_error(ccb, cam_flags, sense_flags,
 1759                                 &softc->saved_ccb));
 1760 }
 1761 
 1762 static void
 1763 daprevent(struct cam_periph *periph, int action)
 1764 {
 1765         struct  da_softc *softc;
 1766         union   ccb *ccb;               
 1767         int     error;
 1768                 
 1769         softc = (struct da_softc *)periph->softc;
 1770 
 1771         if (((action == PR_ALLOW)
 1772           && (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
 1773          || ((action == PR_PREVENT)
 1774           && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
 1775                 return;
 1776         }
 1777 
 1778         ccb = cam_periph_getccb(periph, /*priority*/1);
 1779 
 1780         scsi_prevent(&ccb->csio,
 1781                      /*retries*/1,
 1782                      /*cbcfp*/dadone,
 1783                      MSG_SIMPLE_Q_TAG,
 1784                      action,
 1785                      SSD_FULL_SIZE,
 1786                      5000);
 1787 
 1788         error = cam_periph_runccb(ccb, /*error_routine*/NULL, CAM_RETRY_SELTO,
 1789                                   SF_RETRY_UA, softc->disk->d_devstat);
 1790 
 1791         if (error == 0) {
 1792                 if (action == PR_ALLOW)
 1793                         softc->flags &= ~DA_FLAG_PACK_LOCKED;
 1794                 else
 1795                         softc->flags |= DA_FLAG_PACK_LOCKED;
 1796         }
 1797 
 1798         xpt_release_ccb(ccb);
 1799 }
 1800 
 1801 static int
 1802 dagetcapacity(struct cam_periph *periph)
 1803 {
 1804         struct da_softc *softc;
 1805         union ccb *ccb;
 1806         struct scsi_read_capacity_data *rcap;
 1807         struct scsi_read_capacity_data_long *rcaplong;
 1808         uint32_t block_len;
 1809         uint64_t maxsector;
 1810         int error;
 1811         u_int32_t sense_flags;
 1812 
 1813         softc = (struct da_softc *)periph->softc;
 1814         block_len = 0;
 1815         maxsector = 0;
 1816         error = 0;
 1817         sense_flags = SF_RETRY_UA;
 1818         if (softc->flags & DA_FLAG_PACK_REMOVABLE)
 1819                 sense_flags |= SF_NO_PRINT;
 1820 
 1821         /* Do a read capacity */
 1822         rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
 1823                                                         M_TEMP,
 1824                                                         M_WAITOK);
 1825                 
 1826         ccb = cam_periph_getccb(periph, /*priority*/1);
 1827         scsi_read_capacity(&ccb->csio,
 1828                            /*retries*/4,
 1829                            /*cbfncp*/dadone,
 1830                            MSG_SIMPLE_Q_TAG,
 1831                            rcap,
 1832                            SSD_FULL_SIZE,
 1833                            /*timeout*/60000);
 1834         ccb->ccb_h.ccb_bp = NULL;
 1835 
 1836         error = cam_periph_runccb(ccb, daerror,
 1837                                   /*cam_flags*/CAM_RETRY_SELTO,
 1838                                   sense_flags,
 1839                                   softc->disk->d_devstat);
 1840 
 1841         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1842                 cam_release_devq(ccb->ccb_h.path,
 1843                                  /*relsim_flags*/0,
 1844                                  /*reduction*/0,
 1845                                  /*timeout*/0,
 1846                                  /*getcount_only*/0);
 1847 
 1848         if (error == 0) {
 1849                 block_len = scsi_4btoul(rcap->length);
 1850                 maxsector = scsi_4btoul(rcap->addr);
 1851 
 1852                 if (maxsector != 0xffffffff)
 1853                         goto done;
 1854         } else
 1855                 goto done;
 1856 
 1857         rcaplong = (struct scsi_read_capacity_data_long *)rcap;
 1858 
 1859         scsi_read_capacity_16(&ccb->csio,
 1860                               /*retries*/ 4,
 1861                               /*cbfcnp*/ dadone,
 1862                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1863                               /*lba*/ 0,
 1864                               /*reladr*/ 0,
 1865                               /*pmi*/ 0,
 1866                               rcaplong,
 1867                               /*sense_len*/ SSD_FULL_SIZE,
 1868                               /*timeout*/ 60000);
 1869         ccb->ccb_h.ccb_bp = NULL;
 1870 
 1871         error = cam_periph_runccb(ccb, daerror,
 1872                                   /*cam_flags*/CAM_RETRY_SELTO,
 1873                                   sense_flags,
 1874                                   softc->disk->d_devstat);
 1875 
 1876         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1877                 cam_release_devq(ccb->ccb_h.path,
 1878                                  /*relsim_flags*/0,
 1879                                  /*reduction*/0,
 1880                                  /*timeout*/0,
 1881                                  /*getcount_only*/0);
 1882 
 1883         if (error == 0) {
 1884                 block_len = scsi_4btoul(rcaplong->length);
 1885                 maxsector = scsi_8btou64(rcaplong->addr);
 1886         }
 1887 
 1888 done:
 1889 
 1890         if (error == 0)
 1891                 dasetgeom(periph, block_len, maxsector);
 1892 
 1893         xpt_release_ccb(ccb);
 1894 
 1895         free(rcap, M_TEMP);
 1896 
 1897         return (error);
 1898 }
 1899 
 1900 static void
 1901 dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector)
 1902 {
 1903         struct ccb_calc_geometry ccg;
 1904         struct da_softc *softc;
 1905         struct disk_params *dp;
 1906 
 1907         softc = (struct da_softc *)periph->softc;
 1908 
 1909         dp = &softc->params;
 1910         dp->secsize = block_len;
 1911         dp->sectors = maxsector + 1;
 1912         /*
 1913          * Have the controller provide us with a geometry
 1914          * for this disk.  The only time the geometry
 1915          * matters is when we boot and the controller
 1916          * is the only one knowledgeable enough to come
 1917          * up with something that will make this a bootable
 1918          * device.
 1919          */
 1920         xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1);
 1921         ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
 1922         ccg.block_size = dp->secsize;
 1923         ccg.volume_size = dp->sectors;
 1924         ccg.heads = 0;
 1925         ccg.secs_per_track = 0;
 1926         ccg.cylinders = 0;
 1927         xpt_action((union ccb*)&ccg);
 1928         if ((ccg.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1929                 /*
 1930                  * We don't know what went wrong here- but just pick
 1931                  * a geometry so we don't have nasty things like divide
 1932                  * by zero.
 1933                  */
 1934                 dp->heads = 255;
 1935                 dp->secs_per_track = 255;
 1936                 dp->cylinders = dp->sectors / (255 * 255);
 1937                 if (dp->cylinders == 0) {
 1938                         dp->cylinders = 1;
 1939                 }
 1940         } else {
 1941                 dp->heads = ccg.heads;
 1942                 dp->secs_per_track = ccg.secs_per_track;
 1943                 dp->cylinders = ccg.cylinders;
 1944         }
 1945 }
 1946 
 1947 static void
 1948 dasendorderedtag(void *arg)
 1949 {
 1950         struct da_softc *softc;
 1951         int s;
 1952         if (da_send_ordered) {
 1953                 for (softc = SLIST_FIRST(&softc_list);
 1954                      softc != NULL;
 1955                      softc = SLIST_NEXT(softc, links)) {
 1956                         s = splsoftcam();
 1957                         if ((softc->ordered_tag_count == 0) 
 1958                          && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
 1959                                 softc->flags |= DA_FLAG_NEED_OTAG;
 1960                         }
 1961                         if (softc->outstanding_cmds > 0)
 1962                                 softc->flags &= ~DA_FLAG_WENT_IDLE;
 1963 
 1964                         softc->ordered_tag_count = 0;
 1965                         splx(s);
 1966                 }
 1967                 /* Queue us up again */
 1968                 timeout(dasendorderedtag, NULL,
 1969                         (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
 1970         }
 1971 }
 1972 
 1973 /*
 1974  * Step through all DA peripheral drivers, and if the device is still open,
 1975  * sync the disk cache to physical media.
 1976  */
 1977 static void
 1978 dashutdown(void * arg, int howto)
 1979 {
 1980         struct cam_periph *periph;
 1981         struct da_softc *softc;
 1982 
 1983         TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
 1984                 union ccb ccb;
 1985                 softc = (struct da_softc *)periph->softc;
 1986 
 1987                 /*
 1988                  * We only sync the cache if the drive is still open, and
 1989                  * if the drive is capable of it..
 1990                  */
 1991                 if (((softc->flags & DA_FLAG_OPEN) == 0)
 1992                  || (softc->quirks & DA_Q_NO_SYNC_CACHE))
 1993                         continue;
 1994 
 1995                 xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
 1996 
 1997                 ccb.ccb_h.ccb_state = DA_CCB_DUMP;
 1998                 scsi_synchronize_cache(&ccb.csio,
 1999                                        /*retries*/1,
 2000                                        /*cbfcnp*/dadone,
 2001                                        MSG_SIMPLE_Q_TAG,
 2002                                        /*begin_lba*/0, /* whole disk */
 2003                                        /*lb_count*/0,
 2004                                        SSD_FULL_SIZE,
 2005                                        60 * 60 * 1000);
 2006 
 2007                 xpt_polled_action(&ccb);
 2008 
 2009                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 2010                         if (((ccb.ccb_h.status & CAM_STATUS_MASK) ==
 2011                              CAM_SCSI_STATUS_ERROR)
 2012                          && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){
 2013                                 int error_code, sense_key, asc, ascq;
 2014 
 2015                                 scsi_extract_sense(&ccb.csio.sense_data,
 2016                                                    &error_code, &sense_key,
 2017                                                    &asc, &ascq);
 2018 
 2019                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
 2020                                         scsi_sense_print(&ccb.csio);
 2021                         } else {
 2022                                 xpt_print_path(periph->path);
 2023                                 printf("Synchronize cache failed, status "
 2024                                        "== 0x%x, scsi status == 0x%x\n",
 2025                                        ccb.ccb_h.status, ccb.csio.scsi_status);
 2026                         }
 2027                 }
 2028 
 2029                 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
 2030                         cam_release_devq(ccb.ccb_h.path,
 2031                                          /*relsim_flags*/0,
 2032                                          /*reduction*/0,
 2033                                          /*timeout*/0,
 2034                                          /*getcount_only*/0);
 2035 
 2036         }
 2037 }
 2038 
 2039 #else /* !_KERNEL */
 2040 
 2041 /*
 2042  * XXX This is only left out of the kernel build to silence warnings.  If,
 2043  * for some reason this function is used in the kernel, the ifdefs should
 2044  * be moved so it is included both in the kernel and userland.
 2045  */
 2046 void
 2047 scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
 2048                  void (*cbfcnp)(struct cam_periph *, union ccb *),
 2049                  u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
 2050                  u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
 2051                  u_int32_t timeout)
 2052 {
 2053         struct scsi_format_unit *scsi_cmd;
 2054 
 2055         scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
 2056         scsi_cmd->opcode = FORMAT_UNIT;
 2057         scsi_cmd->byte2 = byte2;
 2058         scsi_ulto2b(ileave, scsi_cmd->interleave);
 2059 
 2060         cam_fill_csio(csio,
 2061                       retries,
 2062                       cbfcnp,
 2063                       /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
 2064                       tag_action,
 2065                       data_ptr,
 2066                       dxfer_len,
 2067                       sense_len,
 2068                       sizeof(*scsi_cmd),
 2069                       timeout);
 2070 }
 2071 
 2072 #endif /* _KERNEL */

Cache object: 839ab6ebc2568e8ee5fcad7b1370b0e8


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