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.4/sys/cam/scsi/scsi_da.c 181127 2008-08-01 18:25:28Z emaste $");
   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.00"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  477         },
  478         {
  479                 /*
  480                  * Denver MP3 player
  481                  * PR: usb/107101
  482                  */
  483                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "DENVER", "MP3 PLAYER",
  484                  "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
  485         },
  486 };
  487 
  488 static  disk_strategy_t dastrategy;
  489 static  dumper_t        dadump;
  490 static  periph_init_t   dainit;
  491 static  void            daasync(void *callback_arg, u_int32_t code,
  492                                 struct cam_path *path, void *arg);
  493 static  void            dasysctlinit(void *context, int pending);
  494 static  int             dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
  495 static  periph_ctor_t   daregister;
  496 static  periph_dtor_t   dacleanup;
  497 static  periph_start_t  dastart;
  498 static  periph_oninv_t  daoninvalidate;
  499 static  void            dadone(struct cam_periph *periph,
  500                                union ccb *done_ccb);
  501 static  int             daerror(union ccb *ccb, u_int32_t cam_flags,
  502                                 u_int32_t sense_flags);
  503 static void             daprevent(struct cam_periph *periph, int action);
  504 static int              dagetcapacity(struct cam_periph *periph);
  505 static void             dasetgeom(struct cam_periph *periph, uint32_t block_len,
  506                                   uint64_t maxsector);
  507 static timeout_t        dasendorderedtag;
  508 static void             dashutdown(void *arg, int howto);
  509 
  510 #ifndef DA_DEFAULT_TIMEOUT
  511 #define DA_DEFAULT_TIMEOUT 60   /* Timeout in seconds */
  512 #endif
  513 
  514 #ifndef DA_DEFAULT_RETRY
  515 #define DA_DEFAULT_RETRY        4
  516 #endif
  517 
  518 #ifndef DA_DEFAULT_SEND_ORDERED
  519 #define DA_DEFAULT_SEND_ORDERED 1
  520 #endif
  521 
  522 
  523 static int da_retry_count = DA_DEFAULT_RETRY;
  524 static int da_default_timeout = DA_DEFAULT_TIMEOUT;
  525 static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
  526 
  527 SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
  528             "CAM Direct Access Disk driver");
  529 SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW,
  530            &da_retry_count, 0, "Normal I/O retry count");
  531 TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count);
  532 SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
  533            &da_default_timeout, 0, "Normal I/O timeout (in seconds)");
  534 TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
  535 SYSCTL_INT(_kern_cam_da, OID_AUTO, da_send_ordered, CTLFLAG_RW,
  536            &da_send_ordered, 0, "Send Ordered Tags");
  537 TUNABLE_INT("kern.cam.da.da_send_ordered", &da_send_ordered);
  538 
  539 /*
  540  * DA_ORDEREDTAG_INTERVAL determines how often, relative
  541  * to the default timeout, we check to see whether an ordered
  542  * tagged transaction is appropriate to prevent simple tag
  543  * starvation.  Since we'd like to ensure that there is at least
  544  * 1/2 of the timeout length left for a starved transaction to
  545  * complete after we've sent an ordered tag, we must poll at least
  546  * four times in every timeout period.  This takes care of the worst
  547  * case where a starved transaction starts during an interval that
  548  * meets the requirement "don't send an ordered tag" test so it takes
  549  * us two intervals to determine that a tag must be sent.
  550  */
  551 #ifndef DA_ORDEREDTAG_INTERVAL
  552 #define DA_ORDEREDTAG_INTERVAL 4
  553 #endif
  554 
  555 static struct periph_driver dadriver =
  556 {
  557         dainit, "da",
  558         TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
  559 };
  560 
  561 PERIPHDRIVER_DECLARE(da, dadriver);
  562 
  563 MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
  564 
  565 static SLIST_HEAD(,da_softc) softc_list;
  566 
  567 static int
  568 daopen(struct disk *dp)
  569 {
  570         struct cam_periph *periph;
  571         struct da_softc *softc;
  572         int unit;
  573         int error;
  574         int s;
  575 
  576         s = splsoftcam();
  577         periph = (struct cam_periph *)dp->d_drv1;
  578         if (periph == NULL) {
  579                 splx(s);
  580                 return (ENXIO); 
  581         }
  582         unit = periph->unit_number;
  583 
  584         softc = (struct da_softc *)periph->softc;
  585 
  586         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
  587             ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
  588              unit));
  589 
  590         if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
  591                 return (error); /* error code from tsleep */
  592 
  593         if (cam_periph_acquire(periph) != CAM_REQ_CMP)
  594                 return(ENXIO);
  595         softc->flags |= DA_FLAG_OPEN;
  596 
  597         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
  598                 /* Invalidate our pack information. */
  599                 softc->flags &= ~DA_FLAG_PACK_INVALID;
  600         }
  601         splx(s);
  602 
  603         error = dagetcapacity(periph);
  604 
  605         if (error == 0) {
  606 
  607                 softc->disk->d_sectorsize = softc->params.secsize;
  608                 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
  609                 /* XXX: these are not actually "firmware" values, so they may be wrong */
  610                 softc->disk->d_fwsectors = softc->params.secs_per_track;
  611                 softc->disk->d_fwheads = softc->params.heads;
  612                 softc->disk->d_devstat->block_size = softc->params.secsize;
  613                 softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
  614         }
  615         
  616         if (error == 0) {
  617                 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
  618                     (softc->quirks & DA_Q_NO_PREVENT) == 0)
  619                         daprevent(periph, PR_PREVENT);
  620         } else {
  621                 softc->flags &= ~DA_FLAG_OPEN;
  622                 cam_periph_release(periph);
  623         }
  624         cam_periph_unlock(periph);
  625         return (error);
  626 }
  627 
  628 static int
  629 daclose(struct disk *dp)
  630 {
  631         struct  cam_periph *periph;
  632         struct  da_softc *softc;
  633         int     error;
  634 
  635         periph = (struct cam_periph *)dp->d_drv1;
  636         if (periph == NULL)
  637                 return (ENXIO); 
  638 
  639         softc = (struct da_softc *)periph->softc;
  640 
  641         if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
  642                 return (error); /* error code from tsleep */
  643         }
  644 
  645         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
  646                 union   ccb *ccb;
  647 
  648                 ccb = cam_periph_getccb(periph, /*priority*/1);
  649 
  650                 scsi_synchronize_cache(&ccb->csio,
  651                                        /*retries*/1,
  652                                        /*cbfcnp*/dadone,
  653                                        MSG_SIMPLE_Q_TAG,
  654                                        /*begin_lba*/0,/* Cover the whole disk */
  655                                        /*lb_count*/0,
  656                                        SSD_FULL_SIZE,
  657                                        5 * 60 * 1000);
  658 
  659                 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
  660                                   /*sense_flags*/SF_RETRY_UA,
  661                                   softc->disk->d_devstat);
  662 
  663                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  664                         if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
  665                              CAM_SCSI_STATUS_ERROR) {
  666                                 int asc, ascq;
  667                                 int sense_key, error_code;
  668 
  669                                 scsi_extract_sense(&ccb->csio.sense_data,
  670                                                    &error_code,
  671                                                    &sense_key, 
  672                                                    &asc, &ascq);
  673                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
  674                                         scsi_sense_print(&ccb->csio);
  675                         } else {
  676                                 xpt_print_path(periph->path);
  677                                 printf("Synchronize cache failed, status "
  678                                        "== 0x%x, scsi status == 0x%x\n",
  679                                        ccb->csio.ccb_h.status,
  680                                        ccb->csio.scsi_status);
  681                         }
  682                 }
  683 
  684                 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  685                         cam_release_devq(ccb->ccb_h.path,
  686                                          /*relsim_flags*/0,
  687                                          /*reduction*/0,
  688                                          /*timeout*/0,
  689                                          /*getcount_only*/0);
  690 
  691                 xpt_release_ccb(ccb);
  692 
  693         }
  694 
  695         if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
  696                 if ((softc->quirks & DA_Q_NO_PREVENT) == 0)
  697                         daprevent(periph, PR_ALLOW);
  698                 /*
  699                  * If we've got removeable media, mark the blocksize as
  700                  * unavailable, since it could change when new media is
  701                  * inserted.
  702                  */
  703                 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
  704         }
  705 
  706         softc->flags &= ~DA_FLAG_OPEN;
  707         cam_periph_unlock(periph);
  708         cam_periph_release(periph);
  709         return (0);     
  710 }
  711 
  712 /*
  713  * Actually translate the requested transfer into one the physical driver
  714  * can understand.  The transfer is described by a buf and will include
  715  * only one physical transfer.
  716  */
  717 static void
  718 dastrategy(struct bio *bp)
  719 {
  720         struct cam_periph *periph;
  721         struct da_softc *softc;
  722         int    s;
  723         
  724         periph = (struct cam_periph *)bp->bio_disk->d_drv1;
  725         if (periph == NULL) {
  726                 biofinish(bp, NULL, ENXIO);
  727                 return;
  728         }
  729         softc = (struct da_softc *)periph->softc;
  730 #if 0
  731         /*
  732          * check it's not too big a transfer for our adapter
  733          */
  734         scsi_minphys(bp,&sd_switch);
  735 #endif
  736 
  737         /*
  738          * Mask interrupts so that the pack cannot be invalidated until
  739          * after we are in the queue.  Otherwise, we might not properly
  740          * clean up one of the buffers.
  741          */
  742         s = splbio();
  743         
  744         /*
  745          * If the device has been made invalid, error out
  746          */
  747         if ((softc->flags & DA_FLAG_PACK_INVALID)) {
  748                 splx(s);
  749                 biofinish(bp, NULL, ENXIO);
  750                 return;
  751         }
  752         
  753         /*
  754          * Place it in the queue of disk activities for this disk
  755          */
  756         bioq_disksort(&softc->bio_queue, bp);
  757 
  758         splx(s);
  759         
  760         /*
  761          * Schedule ourselves for performing the work.
  762          */
  763         xpt_schedule(periph, /* XXX priority */1);
  764 
  765         return;
  766 }
  767 
  768 static int
  769 dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
  770 {
  771         struct      cam_periph *periph;
  772         struct      da_softc *softc;
  773         u_int       secsize;
  774         struct      ccb_scsiio csio;
  775         struct      disk *dp;
  776 
  777         dp = arg;
  778         periph = dp->d_drv1;
  779         if (periph == NULL)
  780                 return (ENXIO);
  781         softc = (struct da_softc *)periph->softc;
  782         secsize = softc->params.secsize;
  783         
  784         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
  785                 return (ENXIO);
  786 
  787         if (length > 0) {
  788                 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
  789                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
  790                 scsi_read_write(&csio,
  791                                 /*retries*/1,
  792                                 dadone,
  793                                 MSG_ORDERED_Q_TAG,
  794                                 /*read*/FALSE,
  795                                 /*byte2*/0,
  796                                 /*minimum_cmd_size*/ softc->minimum_cmd_size,
  797                                 offset / secsize,
  798                                 length / secsize,
  799                                 /*data_ptr*/(u_int8_t *) virtual,
  800                                 /*dxfer_len*/length,
  801                                 /*sense_len*/SSD_FULL_SIZE,
  802                                 DA_DEFAULT_TIMEOUT * 1000);             
  803                 xpt_polled_action((union ccb *)&csio);
  804 
  805                 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  806                         printf("Aborting dump due to I/O error.\n");
  807                         if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
  808                              CAM_SCSI_STATUS_ERROR)
  809                                 scsi_sense_print(&csio);
  810                         else
  811                                 printf("status == 0x%x, scsi status == 0x%x\n",
  812                                        csio.ccb_h.status, csio.scsi_status);
  813                         return(EIO);
  814                 }
  815                 return(0);
  816         } 
  817                 
  818         /*
  819          * Sync the disk cache contents to the physical media.
  820          */
  821         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
  822 
  823                 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
  824                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
  825                 scsi_synchronize_cache(&csio,
  826                                        /*retries*/1,
  827                                        /*cbfcnp*/dadone,
  828                                        MSG_SIMPLE_Q_TAG,
  829                                        /*begin_lba*/0,/* Cover the whole disk */
  830                                        /*lb_count*/0,
  831                                        SSD_FULL_SIZE,
  832                                        5 * 60 * 1000);
  833                 xpt_polled_action((union ccb *)&csio);
  834 
  835                 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  836                         if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
  837                              CAM_SCSI_STATUS_ERROR) {
  838                                 int asc, ascq;
  839                                 int sense_key, error_code;
  840 
  841                                 scsi_extract_sense(&csio.sense_data,
  842                                                    &error_code,
  843                                                    &sense_key, 
  844                                                    &asc, &ascq);
  845                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
  846                                         scsi_sense_print(&csio);
  847                         } else {
  848                                 xpt_print_path(periph->path);
  849                                 printf("Synchronize cache failed, status "
  850                                        "== 0x%x, scsi status == 0x%x\n",
  851                                        csio.ccb_h.status, csio.scsi_status);
  852                         }
  853                 }
  854         }
  855         return (0);
  856 }
  857 
  858 static void
  859 dainit(void)
  860 {
  861         cam_status status;
  862         struct cam_path *path;
  863 
  864         SLIST_INIT(&softc_list);
  865         
  866         /*
  867          * Install a global async callback.  This callback will
  868          * receive async callbacks like "new device found".
  869          */
  870         status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
  871                                  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
  872 
  873         if (status == CAM_REQ_CMP) {
  874                 struct ccb_setasync csa;
  875 
  876                 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
  877                 csa.ccb_h.func_code = XPT_SASYNC_CB;
  878                 csa.event_enable = AC_FOUND_DEVICE;
  879                 csa.callback = daasync;
  880                 csa.callback_arg = NULL;
  881                 xpt_action((union ccb *)&csa);
  882                 status = csa.ccb_h.status;
  883                 xpt_free_path(path);
  884         }
  885 
  886         if (status != CAM_REQ_CMP) {
  887                 printf("da: Failed to attach master async callback "
  888                        "due to status 0x%x!\n", status);
  889         } else if (da_send_ordered) {
  890 
  891                 /*
  892                  * Schedule a periodic event to occasionally send an
  893                  * ordered tag to a device.
  894                  */
  895                 timeout(dasendorderedtag, NULL,
  896                         (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
  897 
  898                 /* Register our shutdown event handler */
  899                 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown, 
  900                                            NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
  901                     printf("dainit: shutdown event registration failed!\n");
  902         }
  903 }
  904 
  905 static void
  906 daoninvalidate(struct cam_periph *periph)
  907 {
  908         int s;
  909         struct da_softc *softc;
  910         struct ccb_setasync csa;
  911 
  912         softc = (struct da_softc *)periph->softc;
  913 
  914         /*
  915          * De-register any async callbacks.
  916          */
  917         xpt_setup_ccb(&csa.ccb_h, periph->path,
  918                       /* priority */ 5);
  919         csa.ccb_h.func_code = XPT_SASYNC_CB;
  920         csa.event_enable = 0;
  921         csa.callback = daasync;
  922         csa.callback_arg = periph;
  923         xpt_action((union ccb *)&csa);
  924 
  925         softc->flags |= DA_FLAG_PACK_INVALID;
  926 
  927         /*
  928          * Although the oninvalidate() routines are always called at
  929          * splsoftcam, we need to be at splbio() here to keep the buffer
  930          * queue from being modified while we traverse it.
  931          */
  932         s = splbio();
  933 
  934         /*
  935          * Return all queued I/O with ENXIO.
  936          * XXX Handle any transactions queued to the card
  937          *     with XPT_ABORT_CCB.
  938          */
  939         bioq_flush(&softc->bio_queue, NULL, ENXIO);
  940         splx(s);
  941 
  942         SLIST_REMOVE(&softc_list, softc, da_softc, links);
  943 
  944         disk_gone(softc->disk);
  945         xpt_print_path(periph->path);
  946         printf("lost device\n");
  947 }
  948 
  949 static void
  950 dacleanup(struct cam_periph *periph)
  951 {
  952         struct da_softc *softc;
  953 
  954         softc = (struct da_softc *)periph->softc;
  955 
  956         xpt_print_path(periph->path);
  957         printf("removing device entry\n");
  958         /*
  959          * If we can't free the sysctl tree, oh well...
  960          */
  961         if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
  962             && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
  963                 xpt_print_path(periph->path);
  964                 printf("can't remove sysctl context\n");
  965         }
  966         disk_destroy(softc->disk);
  967         free(softc, M_DEVBUF);
  968 }
  969 
  970 static void
  971 daasync(void *callback_arg, u_int32_t code,
  972         struct cam_path *path, void *arg)
  973 {
  974         struct cam_periph *periph;
  975 
  976         periph = (struct cam_periph *)callback_arg;
  977         switch (code) {
  978         case AC_FOUND_DEVICE:
  979         {
  980                 struct ccb_getdev *cgd;
  981                 cam_status status;
  982  
  983                 cgd = (struct ccb_getdev *)arg;
  984                 if (cgd == NULL)
  985                         break;
  986 
  987                 if (SID_TYPE(&cgd->inq_data) != T_DIRECT
  988                     && SID_TYPE(&cgd->inq_data) != T_RBC
  989                     && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
  990                         break;
  991 
  992                 /*
  993                  * Allocate a peripheral instance for
  994                  * this device and start the probe
  995                  * process.
  996                  */
  997                 status = cam_periph_alloc(daregister, daoninvalidate,
  998                                           dacleanup, dastart,
  999                                           "da", CAM_PERIPH_BIO,
 1000                                           cgd->ccb_h.path, daasync,
 1001                                           AC_FOUND_DEVICE, cgd);
 1002 
 1003                 if (status != CAM_REQ_CMP
 1004                  && status != CAM_REQ_INPROG)
 1005                         printf("daasync: Unable to attach to new device "
 1006                                 "due to status 0x%x\n", status);
 1007                 break;
 1008         }
 1009         case AC_SENT_BDR:
 1010         case AC_BUS_RESET:
 1011         {
 1012                 struct da_softc *softc;
 1013                 struct ccb_hdr *ccbh;
 1014                 int s;
 1015 
 1016                 softc = (struct da_softc *)periph->softc;
 1017                 s = splsoftcam();
 1018                 /*
 1019                  * Don't fail on the expected unit attention
 1020                  * that will occur.
 1021                  */
 1022                 softc->flags |= DA_FLAG_RETRY_UA;
 1023                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
 1024                         ccbh->ccb_state |= DA_CCB_RETRY_UA;
 1025                 splx(s);
 1026                 /* FALLTHROUGH*/
 1027         }
 1028         default:
 1029                 cam_periph_async(periph, code, path, arg);
 1030                 break;
 1031         }
 1032 }
 1033 
 1034 static void
 1035 dasysctlinit(void *context, int pending)
 1036 {
 1037         struct cam_periph *periph;
 1038         struct da_softc *softc;
 1039         char tmpstr[80], tmpstr2[80];
 1040 
 1041         periph = (struct cam_periph *)context;
 1042         softc = (struct da_softc *)periph->softc;
 1043 
 1044         snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
 1045         snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
 1046 
 1047         mtx_lock(&Giant);
 1048         sysctl_ctx_init(&softc->sysctl_ctx);
 1049         softc->flags |= DA_FLAG_SCTX_INIT;
 1050         softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
 1051                 SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
 1052                 CTLFLAG_RD, 0, tmpstr);
 1053         if (softc->sysctl_tree == NULL) {
 1054                 printf("dasysctlinit: unable to allocate sysctl tree\n");
 1055                 mtx_unlock(&Giant);
 1056                 return;
 1057         }
 1058 
 1059         /*
 1060          * Now register the sysctl handler, so the user can the value on
 1061          * the fly.
 1062          */
 1063         SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
 1064                 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
 1065                 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
 1066                 "Minimum CDB size");
 1067 
 1068         mtx_unlock(&Giant);
 1069 }
 1070 
 1071 static int
 1072 dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
 1073 {
 1074         int error, value;
 1075 
 1076         value = *(int *)arg1;
 1077 
 1078         error = sysctl_handle_int(oidp, &value, 0, req);
 1079 
 1080         if ((error != 0)
 1081          || (req->newptr == NULL))
 1082                 return (error);
 1083 
 1084         /*
 1085          * Acceptable values here are 6, 10, 12 or 16.
 1086          */
 1087         if (value < 6)
 1088                 value = 6;
 1089         else if ((value > 6)
 1090               && (value <= 10))
 1091                 value = 10;
 1092         else if ((value > 10)
 1093               && (value <= 12))
 1094                 value = 12;
 1095         else if (value > 12)
 1096                 value = 16;
 1097 
 1098         *(int *)arg1 = value;
 1099 
 1100         return (0);
 1101 }
 1102 
 1103 static cam_status
 1104 daregister(struct cam_periph *periph, void *arg)
 1105 {
 1106         int s;
 1107         struct da_softc *softc;
 1108         struct ccb_setasync csa;
 1109         struct ccb_pathinq cpi;
 1110         struct ccb_getdev *cgd;
 1111         char tmpstr[80];
 1112         caddr_t match;
 1113 
 1114         cgd = (struct ccb_getdev *)arg;
 1115         if (periph == NULL) {
 1116                 printf("daregister: periph was NULL!!\n");
 1117                 return(CAM_REQ_CMP_ERR);
 1118         }
 1119 
 1120         if (cgd == NULL) {
 1121                 printf("daregister: no getdev CCB, can't register device\n");
 1122                 return(CAM_REQ_CMP_ERR);
 1123         }
 1124 
 1125         softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
 1126             M_NOWAIT|M_ZERO);
 1127 
 1128         if (softc == NULL) {
 1129                 printf("daregister: Unable to probe new device. "
 1130                        "Unable to allocate softc\n");                           
 1131                 return(CAM_REQ_CMP_ERR);
 1132         }
 1133 
 1134         LIST_INIT(&softc->pending_ccbs);
 1135         softc->state = DA_STATE_PROBE;
 1136         bioq_init(&softc->bio_queue);
 1137         if (SID_IS_REMOVABLE(&cgd->inq_data))
 1138                 softc->flags |= DA_FLAG_PACK_REMOVABLE;
 1139         if ((cgd->inq_data.flags & SID_CmdQue) != 0)
 1140                 softc->flags |= DA_FLAG_TAGGED_QUEUING;
 1141 
 1142         periph->softc = softc;
 1143 
 1144         /*
 1145          * See if this device has any quirks.
 1146          */
 1147         match = cam_quirkmatch((caddr_t)&cgd->inq_data,
 1148                                (caddr_t)da_quirk_table,
 1149                                sizeof(da_quirk_table)/sizeof(*da_quirk_table),
 1150                                sizeof(*da_quirk_table), scsi_inquiry_match);
 1151 
 1152         if (match != NULL)
 1153                 softc->quirks = ((struct da_quirk_entry *)match)->quirks;
 1154         else
 1155                 softc->quirks = DA_Q_NONE;
 1156 
 1157         /* Check if the SIM does not want 6 byte commands */
 1158         xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1);
 1159         cpi.ccb_h.func_code = XPT_PATH_INQ;
 1160         xpt_action((union ccb *)&cpi);
 1161         if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
 1162                 softc->quirks |= DA_Q_NO_6_BYTE;
 1163 
 1164         TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
 1165 
 1166         /*
 1167          * RBC devices don't have to support READ(6), only READ(10).
 1168          */
 1169         if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
 1170                 softc->minimum_cmd_size = 10;
 1171         else
 1172                 softc->minimum_cmd_size = 6;
 1173 
 1174         /*
 1175          * Load the user's default, if any.
 1176          */
 1177         snprintf(tmpstr, sizeof(tmpstr), "kern.cam.da.%d.minimum_cmd_size",
 1178                  periph->unit_number);
 1179         TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
 1180 
 1181         /*
 1182          * 6, 10, 12 and 16 are the currently permissible values.
 1183          */
 1184         if (softc->minimum_cmd_size < 6)
 1185                 softc->minimum_cmd_size = 6;
 1186         else if ((softc->minimum_cmd_size > 6)
 1187               && (softc->minimum_cmd_size <= 10))
 1188                 softc->minimum_cmd_size = 10;
 1189         else if ((softc->minimum_cmd_size > 10)
 1190               && (softc->minimum_cmd_size <= 12))
 1191                 softc->minimum_cmd_size = 12;
 1192         else if (softc->minimum_cmd_size > 12)
 1193                 softc->minimum_cmd_size = 16;
 1194 
 1195         /*
 1196          * Block our timeout handler while we
 1197          * add this softc to the dev list.
 1198          */
 1199         s = splsoftclock();
 1200         SLIST_INSERT_HEAD(&softc_list, softc, links);
 1201         splx(s);
 1202 
 1203         /*
 1204          * Register this media as a disk
 1205          */
 1206 
 1207         softc->disk = disk_alloc();
 1208         softc->disk->d_open = daopen;
 1209         softc->disk->d_close = daclose;
 1210         softc->disk->d_strategy = dastrategy;
 1211         softc->disk->d_dump = dadump;
 1212         softc->disk->d_name = "da";
 1213         softc->disk->d_drv1 = periph;
 1214         softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
 1215         softc->disk->d_unit = periph->unit_number;
 1216         softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
 1217         disk_create(softc->disk, DISK_VERSION);
 1218 
 1219         /*
 1220          * Add async callbacks for bus reset and
 1221          * bus device reset calls.  I don't bother
 1222          * checking if this fails as, in most cases,
 1223          * the system will function just fine without
 1224          * them and the only alternative would be to
 1225          * not attach the device on failure.
 1226          */
 1227         xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
 1228         csa.ccb_h.func_code = XPT_SASYNC_CB;
 1229         csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
 1230         csa.callback = daasync;
 1231         csa.callback_arg = periph;
 1232         xpt_action((union ccb *)&csa);
 1233         /*
 1234          * Lock this peripheral until we are setup.
 1235          * This first call can't block
 1236          */
 1237         (void)cam_periph_lock(periph, PRIBIO);
 1238         xpt_schedule(periph, /*priority*/5);
 1239 
 1240         return(CAM_REQ_CMP);
 1241 }
 1242 
 1243 static void
 1244 dastart(struct cam_periph *periph, union ccb *start_ccb)
 1245 {
 1246         struct da_softc *softc;
 1247 
 1248         softc = (struct da_softc *)periph->softc;
 1249 
 1250         
 1251         switch (softc->state) {
 1252         case DA_STATE_NORMAL:
 1253         {
 1254                 /* Pull a buffer from the queue and get going on it */          
 1255                 struct bio *bp;
 1256                 int s;
 1257 
 1258                 /*
 1259                  * See if there is a buf with work for us to do..
 1260                  */
 1261                 s = splbio();
 1262                 bp = bioq_first(&softc->bio_queue);
 1263                 if (periph->immediate_priority <= periph->pinfo.priority) {
 1264                         CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
 1265                                         ("queuing for immediate ccb\n"));
 1266                         start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
 1267                         SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
 1268                                           periph_links.sle);
 1269                         periph->immediate_priority = CAM_PRIORITY_NONE;
 1270                         splx(s);
 1271                         wakeup(&periph->ccb_list);
 1272                 } else if (bp == NULL) {
 1273                         splx(s);
 1274                         xpt_release_ccb(start_ccb);
 1275                 } else {
 1276                         int oldspl;
 1277                         u_int8_t tag_code;
 1278 
 1279                         bioq_remove(&softc->bio_queue, bp);
 1280 
 1281                         if ((softc->flags & DA_FLAG_NEED_OTAG) != 0) {
 1282                                 softc->flags &= ~DA_FLAG_NEED_OTAG;
 1283                                 softc->ordered_tag_count++;
 1284                                 tag_code = MSG_ORDERED_Q_TAG;
 1285                         } else {
 1286                                 tag_code = MSG_SIMPLE_Q_TAG;
 1287                         }
 1288                         scsi_read_write(&start_ccb->csio,
 1289                                         /*retries*/da_retry_count,
 1290                                         /*cbfcnp*/dadone,
 1291                                         /*tag_action*/tag_code,
 1292                                         /*read_op*/bp->bio_cmd == BIO_READ,
 1293                                         /*byte2*/0,
 1294                                         softc->minimum_cmd_size,
 1295                                         /*lba*/bp->bio_pblkno,
 1296                                         /*block_count*/bp->bio_bcount /
 1297                                         softc->params.secsize,
 1298                                         /*data_ptr*/ bp->bio_data,
 1299                                         /*dxfer_len*/ bp->bio_bcount,
 1300                                         /*sense_len*/SSD_FULL_SIZE,
 1301                                         /*timeout*/da_default_timeout*1000);
 1302                         start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
 1303 
 1304                         /*
 1305                          * Block out any asyncronous callbacks
 1306                          * while we touch the pending ccb list.
 1307                          */
 1308                         oldspl = splcam();
 1309                         LIST_INSERT_HEAD(&softc->pending_ccbs,
 1310                                          &start_ccb->ccb_h, periph_links.le);
 1311                         softc->outstanding_cmds++;
 1312                         splx(oldspl);
 1313 
 1314                         /* We expect a unit attention from this device */
 1315                         if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
 1316                                 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
 1317                                 softc->flags &= ~DA_FLAG_RETRY_UA;
 1318                         }
 1319 
 1320                         start_ccb->ccb_h.ccb_bp = bp;
 1321                         bp = bioq_first(&softc->bio_queue);
 1322                         splx(s);
 1323 
 1324                         xpt_action(start_ccb);
 1325                 }
 1326                 
 1327                 if (bp != NULL) {
 1328                         /* Have more work to do, so ensure we stay scheduled */
 1329                         xpt_schedule(periph, /* XXX priority */1);
 1330                 }
 1331                 break;
 1332         }
 1333         case DA_STATE_PROBE:
 1334         {
 1335                 struct ccb_scsiio *csio;
 1336                 struct scsi_read_capacity_data *rcap;
 1337 
 1338                 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
 1339                                                                 M_SCSIDA,
 1340                                                                 M_NOWAIT|M_ZERO);
 1341                 if (rcap == NULL) {
 1342                         printf("dastart: Couldn't malloc read_capacity data\n");
 1343                         /* da_free_periph??? */
 1344                         break;
 1345                 }
 1346                 csio = &start_ccb->csio;
 1347                 scsi_read_capacity(csio,
 1348                                    /*retries*/4,
 1349                                    dadone,
 1350                                    MSG_SIMPLE_Q_TAG,
 1351                                    rcap,
 1352                                    SSD_FULL_SIZE,
 1353                                    /*timeout*/5000);
 1354                 start_ccb->ccb_h.ccb_bp = NULL;
 1355                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE;
 1356                 xpt_action(start_ccb);
 1357                 break;
 1358         }
 1359         case DA_STATE_PROBE2:
 1360         {
 1361                 struct ccb_scsiio *csio;
 1362                 struct scsi_read_capacity_data_long *rcaplong;
 1363 
 1364                 rcaplong = (struct scsi_read_capacity_data_long *)
 1365                         malloc(sizeof(*rcaplong), M_SCSIDA, M_NOWAIT|M_ZERO);
 1366                 if (rcaplong == NULL) {
 1367                         printf("dastart: Couldn't malloc read_capacity data\n");
 1368                         /* da_free_periph??? */
 1369                         break;
 1370                 }
 1371                 csio = &start_ccb->csio;
 1372                 scsi_read_capacity_16(csio,
 1373                                       /*retries*/ 4,
 1374                                       /*cbfcnp*/ dadone,
 1375                                       /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1376                                       /*lba*/ 0,
 1377                                       /*reladr*/ 0,
 1378                                       /*pmi*/ 0,
 1379                                       rcaplong,
 1380                                       /*sense_len*/ SSD_FULL_SIZE,
 1381                                       /*timeout*/ 60000);
 1382                 start_ccb->ccb_h.ccb_bp = NULL;
 1383                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2;
 1384                 xpt_action(start_ccb);  
 1385                 break;
 1386         }
 1387         }
 1388 }
 1389 
 1390 static int
 1391 cmd6workaround(union ccb *ccb)
 1392 {
 1393         struct scsi_rw_6 cmd6;
 1394         struct scsi_rw_10 *cmd10;
 1395         struct da_softc *softc;
 1396         u_int8_t *cdb;
 1397         int frozen;
 1398 
 1399         cdb = ccb->csio.cdb_io.cdb_bytes;
 1400 
 1401         /* Translation only possible if CDB is an array and cmd is R/W6 */
 1402         if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
 1403             (*cdb != READ_6 && *cdb != WRITE_6))
 1404                 return 0;
 1405 
 1406         xpt_print_path(ccb->ccb_h.path);
 1407         printf("READ(6)/WRITE(6) not supported, "
 1408                "increasing minimum_cmd_size to 10.\n");
 1409         softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
 1410         softc->minimum_cmd_size = 10;
 1411 
 1412         bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
 1413         cmd10 = (struct scsi_rw_10 *)cdb;
 1414         cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
 1415         cmd10->byte2 = 0;
 1416         scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
 1417         cmd10->reserved = 0;
 1418         scsi_ulto2b(cmd6.length, cmd10->length);
 1419         cmd10->control = cmd6.control;
 1420         ccb->csio.cdb_len = sizeof(*cmd10);
 1421 
 1422         /* Requeue request, unfreezing queue if necessary */
 1423         frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
 1424         ccb->ccb_h.status = CAM_REQUEUE_REQ;
 1425         xpt_action(ccb);
 1426         if (frozen) {
 1427                 cam_release_devq(ccb->ccb_h.path,
 1428                                  /*relsim_flags*/0,
 1429                                  /*reduction*/0,
 1430                                  /*timeout*/0,
 1431                                  /*getcount_only*/0);
 1432         }
 1433         return (ERESTART);
 1434 }
 1435 
 1436 static void
 1437 dadone(struct cam_periph *periph, union ccb *done_ccb)
 1438 {
 1439         struct da_softc *softc;
 1440         struct ccb_scsiio *csio;
 1441 
 1442         softc = (struct da_softc *)periph->softc;
 1443         csio = &done_ccb->csio;
 1444         switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
 1445         case DA_CCB_BUFFER_IO:
 1446         {
 1447                 struct bio *bp;
 1448                 int    oldspl;
 1449 
 1450                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 1451                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1452                         int error;
 1453                         int s;
 1454                         int sf;
 1455                         
 1456                         if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
 1457                                 sf = SF_RETRY_UA;
 1458                         else
 1459                                 sf = 0;
 1460 
 1461                         error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
 1462                         if (error == ERESTART) {
 1463                                 /*
 1464                                  * A retry was scheuled, so
 1465                                  * just return.
 1466                                  */
 1467                                 return;
 1468                         }
 1469                         if (error != 0) {
 1470 
 1471                                 s = splbio();
 1472 
 1473                                 if (error == ENXIO) {
 1474                                         /*
 1475                                          * Catastrophic error.  Mark our pack as
 1476                                          * invalid.
 1477                                          */
 1478                                         /* XXX See if this is really a media
 1479                                          *     change first.
 1480                                          */
 1481                                         xpt_print_path(periph->path);
 1482                                         printf("Invalidating pack\n");
 1483                                         softc->flags |= DA_FLAG_PACK_INVALID;
 1484                                 }
 1485 
 1486                                 /*
 1487                                  * return all queued I/O with EIO, so that
 1488                                  * the client can retry these I/Os in the
 1489                                  * proper order should it attempt to recover.
 1490                                  */
 1491                                 bioq_flush(&softc->bio_queue, NULL, EIO);
 1492                                 splx(s);
 1493                                 bp->bio_error = error;
 1494                                 bp->bio_resid = bp->bio_bcount;
 1495                                 bp->bio_flags |= BIO_ERROR;
 1496                         } else {
 1497                                 bp->bio_resid = csio->resid;
 1498                                 bp->bio_error = 0;
 1499                                 if (bp->bio_resid != 0)
 1500                                         bp->bio_flags |= BIO_ERROR;
 1501                         }
 1502                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1503                                 cam_release_devq(done_ccb->ccb_h.path,
 1504                                                  /*relsim_flags*/0,
 1505                                                  /*reduction*/0,
 1506                                                  /*timeout*/0,
 1507                                                  /*getcount_only*/0);
 1508                 } else {
 1509                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1510                                 panic("REQ_CMP with QFRZN");
 1511                         bp->bio_resid = csio->resid;
 1512                         if (csio->resid > 0)
 1513                                 bp->bio_flags |= BIO_ERROR;
 1514                 }
 1515 
 1516                 /*
 1517                  * Block out any asyncronous callbacks
 1518                  * while we touch the pending ccb list.
 1519                  */
 1520                 oldspl = splcam();
 1521                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
 1522                 softc->outstanding_cmds--;
 1523                 if (softc->outstanding_cmds == 0)
 1524                         softc->flags |= DA_FLAG_WENT_IDLE;
 1525                 splx(oldspl);
 1526 
 1527                 biodone(bp);
 1528                 break;
 1529         }
 1530         case DA_CCB_PROBE:
 1531         case DA_CCB_PROBE2:
 1532         {
 1533                 struct     scsi_read_capacity_data *rdcap;
 1534                 struct     scsi_read_capacity_data_long *rcaplong;
 1535                 char       announce_buf[80];
 1536 
 1537                 rdcap = NULL;
 1538                 rcaplong = NULL;
 1539                 if (softc->state == DA_STATE_PROBE)
 1540                         rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
 1541                 else
 1542                         rcaplong = (struct scsi_read_capacity_data_long *)
 1543                                 csio->data_ptr;
 1544 
 1545                 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
 1546                         struct disk_params *dp;
 1547                         uint32_t block_size;
 1548                         uint64_t maxsector;
 1549 
 1550                         if (softc->state == DA_STATE_PROBE) {
 1551                                 block_size = scsi_4btoul(rdcap->length);
 1552                                 maxsector = scsi_4btoul(rdcap->addr);
 1553 
 1554                                 /*
 1555                                  * According to SBC-2, if the standard 10
 1556                                  * byte READ CAPACITY command returns 2^32,
 1557                                  * we should issue the 16 byte version of
 1558                                  * the command, since the device in question
 1559                                  * has more sectors than can be represented
 1560                                  * with the short version of the command.
 1561                                  */
 1562                                 if (maxsector == 0xffffffff) {
 1563                                         softc->state = DA_STATE_PROBE2;
 1564                                         free(rdcap, M_SCSIDA);
 1565                                         xpt_release_ccb(done_ccb);
 1566                                         xpt_schedule(periph, /*priority*/5);
 1567                                         return;
 1568                                 }
 1569                         } else {
 1570                                 block_size = scsi_4btoul(rcaplong->length);
 1571                                 maxsector = scsi_8btou64(rcaplong->addr);
 1572                         }
 1573 
 1574                         /*
 1575                          * Because GEOM code just will panic us if we
 1576                          * give them an 'illegal' value we'll avoid that
 1577                          * here.
 1578                          */
 1579                         if (block_size >= MAXPHYS || block_size == 0) {
 1580                                 xpt_print_path(periph->path);
 1581                                 printf("unsupportable block size %ju\n",
 1582                                       (uintmax_t) block_size);
 1583                                 announce_buf[0] = '\0';
 1584                                 cam_periph_invalidate(periph);
 1585                         } else {
 1586                                 dasetgeom(periph, block_size, maxsector);
 1587                                 dp = &softc->params;
 1588                                 snprintf(announce_buf, sizeof(announce_buf),
 1589                                         "%juMB (%ju %u byte sectors: %dH %dS/T "
 1590                                         "%dC)", (uintmax_t)
 1591                                         (((uintmax_t)dp->secsize *
 1592                                         dp->sectors) / (1024*1024)),
 1593                                         (uintmax_t)dp->sectors,
 1594                                         dp->secsize, dp->heads,
 1595                                         dp->secs_per_track, dp->cylinders);
 1596                         }
 1597                 } else {
 1598                         int     error;
 1599 
 1600                         announce_buf[0] = '\0';
 1601 
 1602                         /*
 1603                          * Retry any UNIT ATTENTION type errors.  They
 1604                          * are expected at boot.
 1605                          */
 1606                         error = daerror(done_ccb, CAM_RETRY_SELTO,
 1607                                         SF_RETRY_UA|SF_NO_PRINT);
 1608                         if (error == ERESTART) {
 1609                                 /*
 1610                                  * A retry was scheuled, so
 1611                                  * just return.
 1612                                  */
 1613                                 return;
 1614                         } else if (error != 0) {
 1615                                 struct scsi_sense_data *sense;
 1616                                 int asc, ascq;
 1617                                 int sense_key, error_code;
 1618                                 int have_sense;
 1619                                 cam_status status;
 1620                                 struct ccb_getdev cgd;
 1621 
 1622                                 /* Don't wedge this device's queue */
 1623                                 status = done_ccb->ccb_h.status;
 1624                                 if ((status & CAM_DEV_QFRZN) != 0)
 1625                                         cam_release_devq(done_ccb->ccb_h.path,
 1626                                                          /*relsim_flags*/0,
 1627                                                          /*reduction*/0,
 1628                                                          /*timeout*/0,
 1629                                                          /*getcount_only*/0);
 1630 
 1631 
 1632                                 xpt_setup_ccb(&cgd.ccb_h, 
 1633                                               done_ccb->ccb_h.path,
 1634                                               /* priority */ 1);
 1635                                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 1636                                 xpt_action((union ccb *)&cgd);
 1637 
 1638                                 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
 1639                                  || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
 1640                                  || ((status & CAM_AUTOSNS_VALID) == 0))
 1641                                         have_sense = FALSE;
 1642                                 else
 1643                                         have_sense = TRUE;
 1644 
 1645                                 if (have_sense) {
 1646                                         sense = &csio->sense_data;
 1647                                         scsi_extract_sense(sense, &error_code,
 1648                                                            &sense_key, 
 1649                                                            &asc, &ascq);
 1650                                 }
 1651                                 /*
 1652                                  * Attach to anything that claims to be a
 1653                                  * direct access or optical disk device,
 1654                                  * as long as it doesn't return a "Logical
 1655                                  * unit not supported" (0x25) error.
 1656                                  */
 1657                                 if ((have_sense) && (asc != 0x25)
 1658                                  && (error_code == SSD_CURRENT_ERROR)) {
 1659                                         const char *sense_key_desc;
 1660                                         const char *asc_desc;
 1661 
 1662                                         scsi_sense_desc(sense_key, asc, ascq,
 1663                                                         &cgd.inq_data,
 1664                                                         &sense_key_desc,
 1665                                                         &asc_desc);
 1666                                         snprintf(announce_buf,
 1667                                             sizeof(announce_buf),
 1668                                                 "Attempt to query device "
 1669                                                 "size failed: %s, %s",
 1670                                                 sense_key_desc,
 1671                                                 asc_desc);
 1672                                 } else { 
 1673                                         if (have_sense)
 1674                                                 scsi_sense_print(
 1675                                                         &done_ccb->csio);
 1676                                         else {
 1677                                                 xpt_print_path(periph->path);
 1678                                                 printf("got CAM status %#x\n",
 1679                                                        done_ccb->ccb_h.status);
 1680                                         }
 1681 
 1682                                         xpt_print_path(periph->path);
 1683                                         printf("fatal error, failed" 
 1684                                                " to attach to device\n");
 1685 
 1686                                         /*
 1687                                          * Free up resources.
 1688                                          */
 1689                                         cam_periph_invalidate(periph);
 1690                                 } 
 1691                         }
 1692                 }
 1693                 free(csio->data_ptr, M_SCSIDA);
 1694                 if (announce_buf[0] != '\0') {
 1695                         xpt_announce_periph(periph, announce_buf);
 1696                         /*
 1697                          * Create our sysctl variables, now that we know
 1698                          * we have successfully attached.
 1699                          */
 1700                         taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
 1701                 }
 1702                 softc->state = DA_STATE_NORMAL; 
 1703                 /*
 1704                  * Since our peripheral may be invalidated by an error
 1705                  * above or an external event, we must release our CCB
 1706                  * before releasing the probe lock on the peripheral.
 1707                  * The peripheral will only go away once the last lock
 1708                  * is removed, and we need it around for the CCB release
 1709                  * operation.
 1710                  */
 1711                 xpt_release_ccb(done_ccb);
 1712                 cam_periph_unlock(periph);
 1713                 return;
 1714         }
 1715         case DA_CCB_WAITING:
 1716         {
 1717                 /* Caller will release the CCB */
 1718                 wakeup(&done_ccb->ccb_h.cbfcnp);
 1719                 return;
 1720         }
 1721         case DA_CCB_DUMP:
 1722                 /* No-op.  We're polling */
 1723                 return;
 1724         default:
 1725                 break;
 1726         }
 1727         xpt_release_ccb(done_ccb);
 1728 }
 1729 
 1730 static int
 1731 daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 1732 {
 1733         struct da_softc   *softc;
 1734         struct cam_periph *periph;
 1735         int error;
 1736 
 1737         periph = xpt_path_periph(ccb->ccb_h.path);
 1738         softc = (struct da_softc *)periph->softc;
 1739 
 1740         /*
 1741          * Automatically detect devices that do not support
 1742          * READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
 1743          */
 1744         error = 0;
 1745         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
 1746                 error = cmd6workaround(ccb);
 1747         } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
 1748                    CAM_SCSI_STATUS_ERROR)
 1749          && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)
 1750          && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
 1751          && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0)
 1752          && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
 1753                 int sense_key, error_code, asc, ascq;
 1754 
 1755                 scsi_extract_sense(&ccb->csio.sense_data,
 1756                                    &error_code, &sense_key, &asc, &ascq);
 1757                 if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
 1758                         error = cmd6workaround(ccb);
 1759         }
 1760         if (error == ERESTART)
 1761                 return (ERESTART);
 1762 
 1763         /*
 1764          * XXX
 1765          * Until we have a better way of doing pack validation,
 1766          * don't treat UAs as errors.
 1767          */
 1768         sense_flags |= SF_RETRY_UA;
 1769         return(cam_periph_error(ccb, cam_flags, sense_flags,
 1770                                 &softc->saved_ccb));
 1771 }
 1772 
 1773 static void
 1774 daprevent(struct cam_periph *periph, int action)
 1775 {
 1776         struct  da_softc *softc;
 1777         union   ccb *ccb;               
 1778         int     error;
 1779                 
 1780         softc = (struct da_softc *)periph->softc;
 1781 
 1782         if (((action == PR_ALLOW)
 1783           && (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
 1784          || ((action == PR_PREVENT)
 1785           && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
 1786                 return;
 1787         }
 1788 
 1789         ccb = cam_periph_getccb(periph, /*priority*/1);
 1790 
 1791         scsi_prevent(&ccb->csio,
 1792                      /*retries*/1,
 1793                      /*cbcfp*/dadone,
 1794                      MSG_SIMPLE_Q_TAG,
 1795                      action,
 1796                      SSD_FULL_SIZE,
 1797                      5000);
 1798 
 1799         error = cam_periph_runccb(ccb, /*error_routine*/NULL, CAM_RETRY_SELTO,
 1800                                   SF_RETRY_UA, softc->disk->d_devstat);
 1801 
 1802         if (error == 0) {
 1803                 if (action == PR_ALLOW)
 1804                         softc->flags &= ~DA_FLAG_PACK_LOCKED;
 1805                 else
 1806                         softc->flags |= DA_FLAG_PACK_LOCKED;
 1807         }
 1808 
 1809         xpt_release_ccb(ccb);
 1810 }
 1811 
 1812 static int
 1813 dagetcapacity(struct cam_periph *periph)
 1814 {
 1815         struct da_softc *softc;
 1816         union ccb *ccb;
 1817         struct scsi_read_capacity_data *rcap;
 1818         struct scsi_read_capacity_data_long *rcaplong;
 1819         uint32_t block_len;
 1820         uint64_t maxsector;
 1821         int error;
 1822         u_int32_t sense_flags;
 1823 
 1824         softc = (struct da_softc *)periph->softc;
 1825         block_len = 0;
 1826         maxsector = 0;
 1827         error = 0;
 1828         sense_flags = SF_RETRY_UA;
 1829         if (softc->flags & DA_FLAG_PACK_REMOVABLE)
 1830                 sense_flags |= SF_NO_PRINT;
 1831 
 1832         /* Do a read capacity */
 1833         rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
 1834                                                         M_SCSIDA,
 1835                                                         M_WAITOK);
 1836                 
 1837         ccb = cam_periph_getccb(periph, /*priority*/1);
 1838         scsi_read_capacity(&ccb->csio,
 1839                            /*retries*/4,
 1840                            /*cbfncp*/dadone,
 1841                            MSG_SIMPLE_Q_TAG,
 1842                            rcap,
 1843                            SSD_FULL_SIZE,
 1844                            /*timeout*/60000);
 1845         ccb->ccb_h.ccb_bp = NULL;
 1846 
 1847         error = cam_periph_runccb(ccb, daerror,
 1848                                   /*cam_flags*/CAM_RETRY_SELTO,
 1849                                   sense_flags,
 1850                                   softc->disk->d_devstat);
 1851 
 1852         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1853                 cam_release_devq(ccb->ccb_h.path,
 1854                                  /*relsim_flags*/0,
 1855                                  /*reduction*/0,
 1856                                  /*timeout*/0,
 1857                                  /*getcount_only*/0);
 1858 
 1859         if (error == 0) {
 1860                 block_len = scsi_4btoul(rcap->length);
 1861                 maxsector = scsi_4btoul(rcap->addr);
 1862 
 1863                 if (maxsector != 0xffffffff)
 1864                         goto done;
 1865         } else
 1866                 goto done;
 1867 
 1868         rcaplong = (struct scsi_read_capacity_data_long *)rcap;
 1869 
 1870         scsi_read_capacity_16(&ccb->csio,
 1871                               /*retries*/ 4,
 1872                               /*cbfcnp*/ dadone,
 1873                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1874                               /*lba*/ 0,
 1875                               /*reladr*/ 0,
 1876                               /*pmi*/ 0,
 1877                               rcaplong,
 1878                               /*sense_len*/ SSD_FULL_SIZE,
 1879                               /*timeout*/ 60000);
 1880         ccb->ccb_h.ccb_bp = NULL;
 1881 
 1882         error = cam_periph_runccb(ccb, daerror,
 1883                                   /*cam_flags*/CAM_RETRY_SELTO,
 1884                                   sense_flags,
 1885                                   softc->disk->d_devstat);
 1886 
 1887         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1888                 cam_release_devq(ccb->ccb_h.path,
 1889                                  /*relsim_flags*/0,
 1890                                  /*reduction*/0,
 1891                                  /*timeout*/0,
 1892                                  /*getcount_only*/0);
 1893 
 1894         if (error == 0) {
 1895                 block_len = scsi_4btoul(rcaplong->length);
 1896                 maxsector = scsi_8btou64(rcaplong->addr);
 1897         }
 1898 
 1899 done:
 1900 
 1901         if (error == 0)
 1902                 dasetgeom(periph, block_len, maxsector);
 1903 
 1904         xpt_release_ccb(ccb);
 1905 
 1906         free(rcap, M_SCSIDA);
 1907 
 1908         return (error);
 1909 }
 1910 
 1911 static void
 1912 dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector)
 1913 {
 1914         struct ccb_calc_geometry ccg;
 1915         struct da_softc *softc;
 1916         struct disk_params *dp;
 1917 
 1918         softc = (struct da_softc *)periph->softc;
 1919 
 1920         dp = &softc->params;
 1921         dp->secsize = block_len;
 1922         dp->sectors = maxsector + 1;
 1923         /*
 1924          * Have the controller provide us with a geometry
 1925          * for this disk.  The only time the geometry
 1926          * matters is when we boot and the controller
 1927          * is the only one knowledgeable enough to come
 1928          * up with something that will make this a bootable
 1929          * device.
 1930          */
 1931         xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1);
 1932         ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
 1933         ccg.block_size = dp->secsize;
 1934         ccg.volume_size = dp->sectors;
 1935         ccg.heads = 0;
 1936         ccg.secs_per_track = 0;
 1937         ccg.cylinders = 0;
 1938         xpt_action((union ccb*)&ccg);
 1939         if ((ccg.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1940                 /*
 1941                  * We don't know what went wrong here- but just pick
 1942                  * a geometry so we don't have nasty things like divide
 1943                  * by zero.
 1944                  */
 1945                 dp->heads = 255;
 1946                 dp->secs_per_track = 255;
 1947                 dp->cylinders = dp->sectors / (255 * 255);
 1948                 if (dp->cylinders == 0) {
 1949                         dp->cylinders = 1;
 1950                 }
 1951         } else {
 1952                 dp->heads = ccg.heads;
 1953                 dp->secs_per_track = ccg.secs_per_track;
 1954                 dp->cylinders = ccg.cylinders;
 1955         }
 1956 }
 1957 
 1958 static void
 1959 dasendorderedtag(void *arg)
 1960 {
 1961         struct da_softc *softc;
 1962         int s;
 1963         if (da_send_ordered) {
 1964                 for (softc = SLIST_FIRST(&softc_list);
 1965                      softc != NULL;
 1966                      softc = SLIST_NEXT(softc, links)) {
 1967                         s = splsoftcam();
 1968                         if ((softc->ordered_tag_count == 0) 
 1969                          && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
 1970                                 softc->flags |= DA_FLAG_NEED_OTAG;
 1971                         }
 1972                         if (softc->outstanding_cmds > 0)
 1973                                 softc->flags &= ~DA_FLAG_WENT_IDLE;
 1974 
 1975                         softc->ordered_tag_count = 0;
 1976                         splx(s);
 1977                 }
 1978                 /* Queue us up again */
 1979                 timeout(dasendorderedtag, NULL,
 1980                         (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
 1981         }
 1982 }
 1983 
 1984 /*
 1985  * Step through all DA peripheral drivers, and if the device is still open,
 1986  * sync the disk cache to physical media.
 1987  */
 1988 static void
 1989 dashutdown(void * arg, int howto)
 1990 {
 1991         struct cam_periph *periph;
 1992         struct da_softc *softc;
 1993 
 1994         TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
 1995                 union ccb ccb;
 1996                 softc = (struct da_softc *)periph->softc;
 1997 
 1998                 /*
 1999                  * We only sync the cache if the drive is still open, and
 2000                  * if the drive is capable of it..
 2001                  */
 2002                 if (((softc->flags & DA_FLAG_OPEN) == 0)
 2003                  || (softc->quirks & DA_Q_NO_SYNC_CACHE))
 2004                         continue;
 2005 
 2006                 xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
 2007 
 2008                 ccb.ccb_h.ccb_state = DA_CCB_DUMP;
 2009                 scsi_synchronize_cache(&ccb.csio,
 2010                                        /*retries*/1,
 2011                                        /*cbfcnp*/dadone,
 2012                                        MSG_SIMPLE_Q_TAG,
 2013                                        /*begin_lba*/0, /* whole disk */
 2014                                        /*lb_count*/0,
 2015                                        SSD_FULL_SIZE,
 2016                                        60 * 60 * 1000);
 2017 
 2018                 xpt_polled_action(&ccb);
 2019 
 2020                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 2021                         if (((ccb.ccb_h.status & CAM_STATUS_MASK) ==
 2022                              CAM_SCSI_STATUS_ERROR)
 2023                          && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){
 2024                                 int error_code, sense_key, asc, ascq;
 2025 
 2026                                 scsi_extract_sense(&ccb.csio.sense_data,
 2027                                                    &error_code, &sense_key,
 2028                                                    &asc, &ascq);
 2029 
 2030                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
 2031                                         scsi_sense_print(&ccb.csio);
 2032                         } else {
 2033                                 xpt_print_path(periph->path);
 2034                                 printf("Synchronize cache failed, status "
 2035                                        "== 0x%x, scsi status == 0x%x\n",
 2036                                        ccb.ccb_h.status, ccb.csio.scsi_status);
 2037                         }
 2038                 }
 2039 
 2040                 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
 2041                         cam_release_devq(ccb.ccb_h.path,
 2042                                          /*relsim_flags*/0,
 2043                                          /*reduction*/0,
 2044                                          /*timeout*/0,
 2045                                          /*getcount_only*/0);
 2046 
 2047         }
 2048 }
 2049 
 2050 #else /* !_KERNEL */
 2051 
 2052 /*
 2053  * XXX This is only left out of the kernel build to silence warnings.  If,
 2054  * for some reason this function is used in the kernel, the ifdefs should
 2055  * be moved so it is included both in the kernel and userland.
 2056  */
 2057 void
 2058 scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
 2059                  void (*cbfcnp)(struct cam_periph *, union ccb *),
 2060                  u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
 2061                  u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
 2062                  u_int32_t timeout)
 2063 {
 2064         struct scsi_format_unit *scsi_cmd;
 2065 
 2066         scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
 2067         scsi_cmd->opcode = FORMAT_UNIT;
 2068         scsi_cmd->byte2 = byte2;
 2069         scsi_ulto2b(ileave, scsi_cmd->interleave);
 2070 
 2071         cam_fill_csio(csio,
 2072                       retries,
 2073                       cbfcnp,
 2074                       /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
 2075                       tag_action,
 2076                       data_ptr,
 2077                       dxfer_len,
 2078                       sense_len,
 2079                       sizeof(*scsi_cmd),
 2080                       timeout);
 2081 }
 2082 
 2083 #endif /* _KERNEL */

Cache object: dd6d2c380c52c9435a29b1ddc9d57525


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