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  * $FreeBSD: releng/5.0/sys/cam/scsi/scsi_da.c 107790 2002-12-12 18:09:35Z yar $
   29  */
   30 
   31 #ifdef _KERNEL
   32 #include "opt_hw_wdog.h"
   33 #endif /* _KERNEL */
   34 
   35 #include <sys/param.h>
   36 
   37 #ifdef _KERNEL
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/bio.h>
   41 #include <sys/sysctl.h>
   42 #endif /* _KERNEL */
   43 
   44 #include <sys/devicestat.h>
   45 #include <sys/conf.h>
   46 #include <sys/disk.h>
   47 #include <sys/eventhandler.h>
   48 #include <sys/malloc.h>
   49 #include <sys/cons.h>
   50 
   51 #include <machine/md_var.h>
   52 
   53 #include <vm/vm.h>
   54 #include <vm/pmap.h>
   55 
   56 #ifndef _KERNEL
   57 #include <stdio.h>
   58 #include <string.h>
   59 #endif /* _KERNEL */
   60 
   61 #include <cam/cam.h>
   62 #include <cam/cam_ccb.h>
   63 #include <cam/cam_periph.h>
   64 #include <cam/cam_xpt_periph.h>
   65 
   66 #include <cam/scsi/scsi_message.h>
   67 
   68 #ifndef _KERNEL 
   69 #include <cam/scsi/scsi_da.h>
   70 #endif /* !_KERNEL */
   71 
   72 #ifdef _KERNEL
   73 typedef enum {
   74         DA_STATE_PROBE,
   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_flags;
   89 
   90 typedef enum {
   91         DA_Q_NONE               = 0x00,
   92         DA_Q_NO_SYNC_CACHE      = 0x01,
   93         DA_Q_NO_6_BYTE          = 0x02
   94 } da_quirks;
   95 
   96 typedef enum {
   97         DA_CCB_PROBE            = 0x01,
   98         DA_CCB_BUFFER_IO        = 0x02,
   99         DA_CCB_WAITING          = 0x03,
  100         DA_CCB_DUMP             = 0x04,
  101         DA_CCB_TYPE_MASK        = 0x0F,
  102         DA_CCB_RETRY_UA         = 0x10
  103 } da_ccb_state;
  104 
  105 /* Offsets into our private area for storing information */
  106 #define ccb_state       ppriv_field0
  107 #define ccb_bp          ppriv_ptr1
  108 
  109 struct disk_params {
  110         u_int8_t  heads;
  111         u_int16_t cylinders;
  112         u_int8_t  secs_per_track;
  113         u_int32_t secsize;      /* Number of bytes/sector */
  114         u_int32_t sectors;      /* total number sectors */
  115 };
  116 
  117 struct da_softc {
  118         struct   bio_queue_head bio_queue;
  119         struct   devstat device_stats;
  120         SLIST_ENTRY(da_softc) links;
  121         LIST_HEAD(, ccb_hdr) pending_ccbs;
  122         da_state state;
  123         da_flags flags; 
  124         da_quirks quirks;
  125         int      minimum_cmd_size;
  126         int      ordered_tag_count;
  127         struct   disk_params params;
  128         struct   disk disk;
  129         union    ccb saved_ccb;
  130         dev_t    dev;
  131 };
  132 
  133 struct da_quirk_entry {
  134         struct scsi_inquiry_pattern inq_pat;
  135         da_quirks quirks;
  136 };
  137 
  138 static const char quantum[] = "QUANTUM";
  139 static const char microp[] = "MICROP";
  140 
  141 static struct da_quirk_entry da_quirk_table[] =
  142 {
  143         /*
  144          * Logitec USB/Firewire LHD-P30FU
  145          */
  146         {
  147                 /* USB part */
  148                 {T_DIRECT, SIP_MEDIA_FIXED, "HITACHI_", "DK23DA*", "*"},
  149                 /*quirks*/ DA_Q_NO_6_BYTE
  150         },
  151         {
  152                 /* Firewire part */
  153                 {T_DIRECT, SIP_MEDIA_FIXED, "LSILogic", "SYM13FW*", "*"},
  154                 /*quirks*/ DA_Q_NO_6_BYTE
  155         },
  156         {
  157                 /*
  158                  * Fujitsu M2513A MO drives.
  159                  * Tested devices: M2513A2 firmware versions 1200 & 1300.
  160                  * (dip switch selects whether T_DIRECT or T_OPTICAL device)
  161                  * Reported by: W.Scholten <whs@xs4all.nl>
  162                  */
  163                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
  164                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  165         },
  166         {
  167                 /* See above. */
  168                 {T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
  169                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  170         },
  171         {
  172                 /*
  173                  * This particular Fujitsu drive doesn't like the
  174                  * synchronize cache command.
  175                  * Reported by: Tom Jackson <toj@gorilla.net>
  176                  */
  177                 {T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
  178                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  179         
  180         },
  181         {
  182                 /*
  183                  * This drive doesn't like the synchronize cache command
  184                  * either.  Reported by: Matthew Jacob <mjacob@feral.com>
  185                  * in NetBSD PR kern/6027, August 24, 1998.
  186                  */
  187                 {T_DIRECT, SIP_MEDIA_FIXED, microp, "2217*", "*"},
  188                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  189         },
  190         {
  191                 /*
  192                  * This drive doesn't like the synchronize cache command
  193                  * either.  Reported by: Hellmuth Michaelis (hm@kts.org)
  194                  * (PR 8882).
  195                  */
  196                 {T_DIRECT, SIP_MEDIA_FIXED, microp, "2112*", "*"},
  197                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  198         },
  199         {
  200                 /*
  201                  * Doesn't like the synchronize cache command.
  202                  * Reported by: Blaz Zupan <blaz@gold.amis.net>
  203                  */
  204                 {T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"},
  205                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  206         },
  207         {
  208                 /*
  209                  * Doesn't like the synchronize cache command.
  210                  */
  211                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "MAVERICK 540S", "*"},
  212                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  213         },
  214         {
  215                 /*
  216                  * Doesn't like the synchronize cache command.
  217                  */
  218                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"},
  219                 /*quirks*/ DA_Q_NO_SYNC_CACHE
  220         },
  221         {
  222                 /*
  223                  * Doesn't work correctly with 6 byte reads/writes.
  224                  * Returns illegal request, and points to byte 9 of the
  225                  * 6-byte CDB.
  226                  * Reported by:  Adam McDougall <bsdx@spawnet.com>
  227                  */
  228                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 4*", "*"},
  229                 /*quirks*/ DA_Q_NO_6_BYTE
  230         },
  231         {
  232                 /*
  233                  * See above.
  234                  */
  235                 {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 2*", "*"},
  236                 /*quirks*/ DA_Q_NO_6_BYTE
  237         },
  238 
  239         /* Below a list of quirks for USB devices supported by umass. */
  240         {
  241                 /*
  242                  * This USB floppy drive uses the UFI command set. This
  243                  * command set is a derivative of the ATAPI command set and
  244                  * does not support READ_6 commands only READ_10. It also does
  245                  * not support sync cache (0x35).
  246                  */
  247                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Y-E DATA", "USB-FDU", "*"},
  248                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  249         },
  250         {
  251                 /* Another USB floppy */
  252                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "MATSHITA", "FDD CF-VFDU*","*"},
  253                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  254         },
  255         {
  256                 /*
  257                  * Sony Memory Stick adapter MSAC-US1 and
  258                  * Sony PCG-C1VJ Internal Memory Stick Slot (MSC-U01).
  259                  * Make all sony MS* products use this quirk.
  260                  */
  261                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "MS*", "*"},
  262                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  263         },
  264         {
  265                 /*
  266                  * Sony Memory Stick adapter for the CLIE series
  267                  * of PalmOS PDA's
  268                  */
  269                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "CLIE*", "*"},
  270                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  271         },
  272         {
  273                 /*
  274                  * Sony DSC cameras (DSC-S30, DSC-S50, DSC-S70)
  275                  */
  276                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"},
  277                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  278         },
  279         {
  280                 /*
  281                  * Maxtor 3000LE USB Drive
  282                  */
  283                 {T_DIRECT, SIP_MEDIA_FIXED, "MAXTOR*", "K040H2*", "*"},
  284                 /*quirks*/ DA_Q_NO_6_BYTE
  285         },
  286         {
  287                 /*
  288                  * LaCie USB drive, among others
  289                  */
  290                 {T_DIRECT, SIP_MEDIA_FIXED, "Maxtor*", "D080H4*", "*"},
  291                 /*quirks*/ DA_Q_NO_6_BYTE
  292         },
  293         {
  294                 {T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "MCF3064AP", "*"},
  295                 /*quirks*/ DA_Q_NO_6_BYTE
  296         },
  297         {
  298                 /*
  299                  * Microtech USB CameraMate
  300                  */
  301                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "eUSB    Compact*",
  302                  "Compact Flash*", "*"},
  303                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  304         },
  305         {
  306                 /*
  307                  * The vendor, product and version strings coming from the
  308                  * controller are null terminated instead of being padded with
  309                  * spaces. The trailing wildcard character '*' is required.
  310                  */
  311                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SMSC*", "USB FDC*","*"},
  312                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  313         },
  314         {
  315                 /*
  316                  * Olympus digital cameras (C-3040ZOOM, C-2040ZOOM, C-1)
  317                  */
  318                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "C-*", "*"},
  319                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  320         },
  321         {
  322                 /*
  323                  * Olympus digital cameras (D-370)
  324                  */
  325                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "D-*", "*"},
  326                 /*quirks*/ DA_Q_NO_6_BYTE
  327         },
  328         {
  329                 /*
  330                  * Olympus digital cameras (E-100RS, E-10).
  331                  */
  332                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "E-*", "*"},
  333                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  334         },
  335         {
  336                 /*
  337                  * KingByte Pen Drives
  338                  */
  339                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "NO BRAND", "PEN DRIVE", "*"},
  340                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  341         },
  342         {
  343                 /*
  344                  * FujiFilm Camera
  345                  */
  346                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJIFILMUSB-DRIVEUNIT",
  347                  "USB-DRIVEUNIT", "*"},
  348                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  349         },
  350         {
  351                 /*
  352                  * Nikon Coolpix E775/E995 Cameras 
  353                  */
  354                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "NIKON", "NIKON DSC E*", "*"},
  355                 /*quirks*/ DA_Q_NO_6_BYTE
  356         },
  357         {
  358                 /*
  359                  * Nikon Coolpix E885 Camera
  360                  */
  361                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Nikon", "Digital Camera", "*"},
  362                 /*quirks*/ DA_Q_NO_6_BYTE
  363         },
  364         {
  365                 /*
  366                  * SimpleTech FlashLink UCF-100
  367                  */
  368                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "OEI-USB", "CompactFlash", "*"},
  369                 /*quirks*/ DA_Q_NO_6_BYTE
  370         },
  371         {
  372                 /*
  373                  * Minolta Dimage 2330
  374                  */
  375                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "MINOLTA", "DIMAGE 2330*", "*"},
  376                 /*quirks*/ DA_Q_NO_6_BYTE
  377         },
  378         {
  379                 /*
  380                  * Minolta Dimage E203
  381                  */
  382                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "MINOLTA", "DiMAGE E203", "*"},
  383                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  384         },
  385         {
  386                 /*
  387                  * DIVA USB Mp3 Player.
  388                  * PR: kern/33638
  389                  */
  390                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "DIVA USB", "Media Reader","*"},
  391                 /*quirks*/ DA_Q_NO_6_BYTE
  392         },
  393         {
  394                 /*
  395                  * Daisy Technology PhotoClip USB Camera
  396                  */
  397                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Digital", "World   DMC","*"},
  398                 /*quirks*/ DA_Q_NO_6_BYTE
  399         },
  400         {
  401                 /*
  402                  * Apacer HandyDrive
  403                  * PR: kern/43627
  404                  */
  405                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "Apacer", "HandyDrive", "*"},
  406                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  407         },
  408         {
  409                 /*
  410                  * Daisy Technology PhotoClip on Zoran chip
  411                  * PR: kern/43580
  412                  */
  413                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "ZORAN", "COACH", "*"},
  414                 /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE
  415         },
  416         {
  417                 /*
  418                  * HP 315 Digital Camera
  419                  * PR: kern/41010
  420                  */
  421                 {T_DIRECT, SIP_MEDIA_REMOVABLE, "HP", "USB CAMERA", "*"},
  422                 /*quirks*/ DA_Q_NO_6_BYTE
  423         }
  424 };
  425 
  426 static  d_open_t        daopen;
  427 static  d_close_t       daclose;
  428 static  d_strategy_t    dastrategy;
  429 static  d_ioctl_t       daioctl;
  430 static  d_dump_t        dadump;
  431 static  periph_init_t   dainit;
  432 static  void            daasync(void *callback_arg, u_int32_t code,
  433                                 struct cam_path *path, void *arg);
  434 static  periph_ctor_t   daregister;
  435 static  periph_dtor_t   dacleanup;
  436 static  periph_start_t  dastart;
  437 static  periph_oninv_t  daoninvalidate;
  438 static  void            dadone(struct cam_periph *periph,
  439                                union ccb *done_ccb);
  440 static  int             daerror(union ccb *ccb, u_int32_t cam_flags,
  441                                 u_int32_t sense_flags);
  442 static void             daprevent(struct cam_periph *periph, int action);
  443 static void             dasetgeom(struct cam_periph *periph,
  444                                   struct scsi_read_capacity_data * rdcap);
  445 static timeout_t        dasendorderedtag;
  446 static void             dashutdown(void *arg, int howto);
  447 
  448 #ifndef DA_DEFAULT_TIMEOUT
  449 #define DA_DEFAULT_TIMEOUT 60   /* Timeout in seconds */
  450 #endif
  451 
  452 #ifndef DA_DEFAULT_RETRY
  453 #define DA_DEFAULT_RETRY        4
  454 #endif
  455 
  456 static int da_retry_count = DA_DEFAULT_RETRY;
  457 static int da_default_timeout = DA_DEFAULT_TIMEOUT;
  458 static int da_no_6_byte = 0;
  459 
  460 SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
  461             "CAM Direct Access Disk driver");
  462 SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW,
  463            &da_retry_count, 0, "Normal I/O retry count");
  464 SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
  465            &da_default_timeout, 0, "Normal I/O timeout (in seconds)");
  466 SYSCTL_INT(_kern_cam_da, OID_AUTO, no_6_byte, CTLFLAG_RW,
  467            &da_no_6_byte, 0, "No 6 bytes commands");
  468 
  469 /*
  470  * DA_ORDEREDTAG_INTERVAL determines how often, relative
  471  * to the default timeout, we check to see whether an ordered
  472  * tagged transaction is appropriate to prevent simple tag
  473  * starvation.  Since we'd like to ensure that there is at least
  474  * 1/2 of the timeout length left for a starved transaction to
  475  * complete after we've sent an ordered tag, we must poll at least
  476  * four times in every timeout period.  This takes care of the worst
  477  * case where a starved transaction starts during an interval that
  478  * meets the requirement "don't send an ordered tag" test so it takes
  479  * us two intervals to determine that a tag must be sent.
  480  */
  481 #ifndef DA_ORDEREDTAG_INTERVAL
  482 #define DA_ORDEREDTAG_INTERVAL 4
  483 #endif
  484 
  485 static struct periph_driver dadriver =
  486 {
  487         dainit, "da",
  488         TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
  489 };
  490 
  491 PERIPHDRIVER_DECLARE(da, dadriver);
  492 
  493 #define DA_CDEV_MAJOR 13
  494 
  495 /* For 2.2-stable support */
  496 #ifndef D_DISK
  497 #define D_DISK 0
  498 #endif
  499 
  500 static struct cdevsw da_cdevsw = {
  501         /* open */      daopen,
  502         /* close */     daclose,
  503         /* read */      physread,
  504         /* write */     physwrite,
  505         /* ioctl */     daioctl,
  506         /* poll */      nopoll,
  507         /* mmap */      nommap,
  508         /* strategy */  dastrategy,
  509         /* name */      "da",
  510         /* maj */       DA_CDEV_MAJOR,
  511         /* dump */      dadump,
  512         /* psize */     nopsize,
  513         /* flags */     D_DISK,
  514 };
  515 
  516 static struct cdevsw dadisk_cdevsw;
  517 
  518 static SLIST_HEAD(,da_softc) softc_list;
  519 
  520 static int
  521 daopen(dev_t dev, int flags __unused, int fmt __unused, struct thread *td __unused)
  522 {
  523         struct cam_periph *periph;
  524         struct da_softc *softc;
  525         struct scsi_read_capacity_data *rcap;
  526         union  ccb *ccb;
  527         int unit;
  528         int error;
  529         int s;
  530 
  531         s = splsoftcam();
  532         periph = (struct cam_periph *)dev->si_drv1;
  533         unit = periph->unit_number;
  534         if (periph == NULL) {
  535                 splx(s);
  536                 return (ENXIO); 
  537         }
  538 
  539         softc = (struct da_softc *)periph->softc;
  540 
  541         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
  542             ("daopen: dev=%s (unit %d)\n", devtoname(dev),
  543              unit));
  544 
  545         if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
  546                 return (error); /* error code from tsleep */
  547 
  548         if (cam_periph_acquire(periph) != CAM_REQ_CMP)
  549                 return(ENXIO);
  550         softc->flags |= DA_FLAG_OPEN;
  551 
  552         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
  553                 /* Invalidate our pack information. */
  554                 disk_invalidate(&softc->disk);
  555                 softc->flags &= ~DA_FLAG_PACK_INVALID;
  556         }
  557         splx(s);
  558 
  559         /* Do a read capacity */
  560         rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
  561                                                         M_TEMP,
  562                                                         M_WAITOK);
  563                 
  564         ccb = cam_periph_getccb(periph, /*priority*/1);
  565         scsi_read_capacity(&ccb->csio,
  566                            /*retries*/4,
  567                            /*cbfncp*/dadone,
  568                            MSG_SIMPLE_Q_TAG,
  569                            rcap,
  570                            SSD_FULL_SIZE,
  571                            /*timeout*/60000);
  572         ccb->ccb_h.ccb_bp = NULL;
  573 
  574         error = cam_periph_runccb(ccb, daerror,
  575                                   /*cam_flags*/CAM_RETRY_SELTO,
  576                                   /*sense_flags*/SF_RETRY_UA,
  577                                   &softc->device_stats);
  578 
  579         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  580                 cam_release_devq(ccb->ccb_h.path,
  581                                  /*relsim_flags*/0,
  582                                  /*reduction*/0,
  583                                  /*timeout*/0,
  584                                  /*getcount_only*/0);
  585         xpt_release_ccb(ccb);
  586 
  587         if (error == 0)
  588                 dasetgeom(periph, rcap);
  589 
  590         free(rcap, M_TEMP);
  591 
  592         if (error == 0) {
  593 
  594                 softc->disk.d_sectorsize = softc->params.secsize;
  595                 softc->disk.d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
  596                 /* XXX: these are not actually "firmware" values, so they may be wrong */
  597                 softc->disk.d_fwsectors = softc->params.secs_per_track;
  598                 softc->disk.d_fwheads = softc->params.heads;
  599 
  600                 /*
  601                  * Check to see whether or not the blocksize is set yet.
  602                  * If it isn't, set it and then clear the blocksize
  603                  * unavailable flag for the device statistics.
  604                  */
  605                 if ((softc->device_stats.flags & DEVSTAT_BS_UNAVAILABLE) != 0){
  606                         softc->device_stats.block_size = softc->params.secsize;
  607                         softc->device_stats.flags &= ~DEVSTAT_BS_UNAVAILABLE;
  608                 }
  609         }
  610         
  611         if (error == 0) {
  612                 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)
  613                         daprevent(periph, PR_PREVENT);
  614         } else {
  615                 softc->flags &= ~DA_FLAG_OPEN;
  616                 cam_periph_release(periph);
  617         }
  618         cam_periph_unlock(periph);
  619         return (error);
  620 }
  621 
  622 static int
  623 daclose(dev_t dev, int flag __unused, int fmt __unused, struct thread *td __unused)
  624 {
  625         struct  cam_periph *periph;
  626         struct  da_softc *softc;
  627         int     error;
  628 
  629         periph = (struct cam_periph *)dev->si_drv1;
  630         if (periph == NULL)
  631                 return (ENXIO); 
  632 
  633         softc = (struct da_softc *)periph->softc;
  634 
  635         if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
  636                 return (error); /* error code from tsleep */
  637         }
  638 
  639         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
  640                 union   ccb *ccb;
  641 
  642                 ccb = cam_periph_getccb(periph, /*priority*/1);
  643 
  644                 scsi_synchronize_cache(&ccb->csio,
  645                                        /*retries*/1,
  646                                        /*cbfcnp*/dadone,
  647                                        MSG_SIMPLE_Q_TAG,
  648                                        /*begin_lba*/0,/* Cover the whole disk */
  649                                        /*lb_count*/0,
  650                                        SSD_FULL_SIZE,
  651                                        5 * 60 * 1000);
  652 
  653                 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
  654                                   /*sense_flags*/SF_RETRY_UA,
  655                                   &softc->device_stats);
  656 
  657                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  658                         if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
  659                              CAM_SCSI_STATUS_ERROR) {
  660                                 int asc, ascq;
  661                                 int sense_key, error_code;
  662 
  663                                 scsi_extract_sense(&ccb->csio.sense_data,
  664                                                    &error_code,
  665                                                    &sense_key, 
  666                                                    &asc, &ascq);
  667                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
  668                                         scsi_sense_print(&ccb->csio);
  669                         } else {
  670                                 xpt_print_path(periph->path);
  671                                 printf("Synchronize cache failed, status "
  672                                        "== 0x%x, scsi status == 0x%x\n",
  673                                        ccb->csio.ccb_h.status,
  674                                        ccb->csio.scsi_status);
  675                         }
  676                 }
  677 
  678                 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  679                         cam_release_devq(ccb->ccb_h.path,
  680                                          /*relsim_flags*/0,
  681                                          /*reduction*/0,
  682                                          /*timeout*/0,
  683                                          /*getcount_only*/0);
  684 
  685                 xpt_release_ccb(ccb);
  686 
  687         }
  688 
  689         if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
  690                 daprevent(periph, PR_ALLOW);
  691                 /*
  692                  * If we've got removeable media, mark the blocksize as
  693                  * unavailable, since it could change when new media is
  694                  * inserted.
  695                  */
  696                 softc->device_stats.flags |= DEVSTAT_BS_UNAVAILABLE;
  697         }
  698 
  699         softc->flags &= ~DA_FLAG_OPEN;
  700         cam_periph_unlock(periph);
  701         cam_periph_release(periph);
  702         return (0);     
  703 }
  704 
  705 /*
  706  * Actually translate the requested transfer into one the physical driver
  707  * can understand.  The transfer is described by a buf and will include
  708  * only one physical transfer.
  709  */
  710 static void
  711 dastrategy(struct bio *bp)
  712 {
  713         struct cam_periph *periph;
  714         struct da_softc *softc;
  715         int    s;
  716         
  717         periph = (struct cam_periph *)bp->bio_dev->si_drv1;
  718         if (periph == NULL) {
  719                 biofinish(bp, NULL, ENXIO);
  720                 return;
  721         }
  722         softc = (struct da_softc *)periph->softc;
  723 #if 0
  724         /*
  725          * check it's not too big a transfer for our adapter
  726          */
  727         scsi_minphys(bp,&sd_switch);
  728 #endif
  729 
  730         /*
  731          * Mask interrupts so that the pack cannot be invalidated until
  732          * after we are in the queue.  Otherwise, we might not properly
  733          * clean up one of the buffers.
  734          */
  735         s = splbio();
  736         
  737         /*
  738          * If the device has been made invalid, error out
  739          */
  740         if ((softc->flags & DA_FLAG_PACK_INVALID)) {
  741                 splx(s);
  742                 biofinish(bp, NULL, ENXIO);
  743                 return;
  744         }
  745         
  746         /*
  747          * Place it in the queue of disk activities for this disk
  748          */
  749         bioqdisksort(&softc->bio_queue, bp);
  750 
  751         splx(s);
  752         
  753         /*
  754          * Schedule ourselves for performing the work.
  755          */
  756         xpt_schedule(periph, /* XXX priority */1);
  757 
  758         return;
  759 }
  760 
  761 /* For 2.2-stable support */
  762 #ifndef ENOIOCTL
  763 #define ENOIOCTL -1
  764 #endif
  765 
  766 static int
  767 daioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
  768 {
  769         struct cam_periph *periph;
  770         struct da_softc *softc;
  771         int error;
  772 
  773         periph = (struct cam_periph *)dev->si_drv1;
  774         if (periph == NULL)
  775                 return (ENXIO); 
  776 
  777         softc = (struct da_softc *)periph->softc;
  778 
  779         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("daioctl\n"));
  780 
  781         if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
  782                 return (error); /* error code from tsleep */
  783         }       
  784 
  785         error = cam_periph_ioctl(periph, cmd, addr, daerror);
  786 
  787         cam_periph_unlock(periph);
  788         
  789         return (error);
  790 }
  791 
  792 static int
  793 dadump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length)
  794 {
  795         struct      cam_periph *periph;
  796         struct      da_softc *softc;
  797         u_int       secsize;
  798         struct      ccb_scsiio csio;
  799 
  800         periph = (struct cam_periph *)dev->si_drv1;
  801         if (periph == NULL)
  802                 return (ENXIO);
  803         softc = (struct da_softc *)periph->softc;
  804         secsize = softc->params.secsize;
  805         
  806         if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
  807                 return (ENXIO);
  808 
  809         if (length > 0) {
  810                 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
  811                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
  812                 scsi_read_write(&csio,
  813                                 /*retries*/1,
  814                                 dadone,
  815                                 MSG_ORDERED_Q_TAG,
  816                                 /*read*/FALSE,
  817                                 /*byte2*/0,
  818                                 /*minimum_cmd_size*/ softc->minimum_cmd_size,
  819                                 offset / secsize,
  820                                 length / secsize,
  821                                 /*data_ptr*/(u_int8_t *) virtual,
  822                                 /*dxfer_len*/length,
  823                                 /*sense_len*/SSD_FULL_SIZE,
  824                                 DA_DEFAULT_TIMEOUT * 1000);             
  825                 xpt_polled_action((union ccb *)&csio);
  826 
  827                 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  828                         printf("Aborting dump due to I/O error.\n");
  829                         if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
  830                              CAM_SCSI_STATUS_ERROR)
  831                                 scsi_sense_print(&csio);
  832                         else
  833                                 printf("status == 0x%x, scsi status == 0x%x\n",
  834                                        csio.ccb_h.status, csio.scsi_status);
  835                         return(EIO);
  836                 }
  837                 return(0);
  838         } 
  839                 
  840         /*
  841          * Sync the disk cache contents to the physical media.
  842          */
  843         if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
  844 
  845                 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
  846                 csio.ccb_h.ccb_state = DA_CCB_DUMP;
  847                 scsi_synchronize_cache(&csio,
  848                                        /*retries*/1,
  849                                        /*cbfcnp*/dadone,
  850                                        MSG_SIMPLE_Q_TAG,
  851                                        /*begin_lba*/0,/* Cover the whole disk */
  852                                        /*lb_count*/0,
  853                                        SSD_FULL_SIZE,
  854                                        5 * 60 * 1000);
  855                 xpt_polled_action((union ccb *)&csio);
  856 
  857                 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  858                         if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
  859                              CAM_SCSI_STATUS_ERROR) {
  860                                 int asc, ascq;
  861                                 int sense_key, error_code;
  862 
  863                                 scsi_extract_sense(&csio.sense_data,
  864                                                    &error_code,
  865                                                    &sense_key, 
  866                                                    &asc, &ascq);
  867                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
  868                                         scsi_sense_print(&csio);
  869                         } else {
  870                                 xpt_print_path(periph->path);
  871                                 printf("Synchronize cache failed, status "
  872                                        "== 0x%x, scsi status == 0x%x\n",
  873                                        csio.ccb_h.status, csio.scsi_status);
  874                         }
  875                 }
  876         }
  877         return (0);
  878 }
  879 
  880 static void
  881 dainit(void)
  882 {
  883         cam_status status;
  884         struct cam_path *path;
  885 
  886         SLIST_INIT(&softc_list);
  887         
  888         /*
  889          * Install a global async callback.  This callback will
  890          * receive async callbacks like "new device found".
  891          */
  892         status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
  893                                  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
  894 
  895         if (status == CAM_REQ_CMP) {
  896                 struct ccb_setasync csa;
  897 
  898                 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
  899                 csa.ccb_h.func_code = XPT_SASYNC_CB;
  900                 csa.event_enable = AC_FOUND_DEVICE;
  901                 csa.callback = daasync;
  902                 csa.callback_arg = NULL;
  903                 xpt_action((union ccb *)&csa);
  904                 status = csa.ccb_h.status;
  905                 xpt_free_path(path);
  906         }
  907 
  908         if (status != CAM_REQ_CMP) {
  909                 printf("da: Failed to attach master async callback "
  910                        "due to status 0x%x!\n", status);
  911         } else {
  912 
  913                 /*
  914                  * Schedule a periodic event to occasionally send an
  915                  * ordered tag to a device.
  916                  */
  917                 timeout(dasendorderedtag, NULL,
  918                         (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
  919 
  920                 /* Register our shutdown event handler */
  921                 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown, 
  922                                            NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
  923                     printf("dainit: shutdown event registration failed!\n");
  924         }
  925 }
  926 
  927 static void
  928 daoninvalidate(struct cam_periph *periph)
  929 {
  930         int s;
  931         struct da_softc *softc;
  932         struct bio *q_bp;
  933         struct ccb_setasync csa;
  934 
  935         softc = (struct da_softc *)periph->softc;
  936 
  937         /*
  938          * De-register any async callbacks.
  939          */
  940         xpt_setup_ccb(&csa.ccb_h, periph->path,
  941                       /* priority */ 5);
  942         csa.ccb_h.func_code = XPT_SASYNC_CB;
  943         csa.event_enable = 0;
  944         csa.callback = daasync;
  945         csa.callback_arg = periph;
  946         xpt_action((union ccb *)&csa);
  947 
  948         softc->flags |= DA_FLAG_PACK_INVALID;
  949 
  950         /*
  951          * Although the oninvalidate() routines are always called at
  952          * splsoftcam, we need to be at splbio() here to keep the buffer
  953          * queue from being modified while we traverse it.
  954          */
  955         s = splbio();
  956 
  957         /*
  958          * Return all queued I/O with ENXIO.
  959          * XXX Handle any transactions queued to the card
  960          *     with XPT_ABORT_CCB.
  961          */
  962         while ((q_bp = bioq_first(&softc->bio_queue)) != NULL){
  963                 bioq_remove(&softc->bio_queue, q_bp);
  964                 q_bp->bio_resid = q_bp->bio_bcount;
  965                 biofinish(q_bp, NULL, ENXIO);
  966         }
  967         splx(s);
  968 
  969         SLIST_REMOVE(&softc_list, softc, da_softc, links);
  970 
  971         xpt_print_path(periph->path);
  972         printf("lost device\n");
  973 }
  974 
  975 static void
  976 dacleanup(struct cam_periph *periph)
  977 {
  978         struct da_softc *softc;
  979 
  980         softc = (struct da_softc *)periph->softc;
  981 
  982         devstat_remove_entry(&softc->device_stats);
  983         xpt_print_path(periph->path);
  984         printf("removing device entry\n");
  985         if (softc->dev) {
  986                 disk_destroy(softc->dev);
  987         }
  988         free(softc, M_DEVBUF);
  989 }
  990 
  991 static void
  992 daasync(void *callback_arg, u_int32_t code,
  993         struct cam_path *path, void *arg)
  994 {
  995         struct cam_periph *periph;
  996 
  997         periph = (struct cam_periph *)callback_arg;
  998         switch (code) {
  999         case AC_FOUND_DEVICE:
 1000         {
 1001                 struct ccb_getdev *cgd;
 1002                 cam_status status;
 1003  
 1004                 cgd = (struct ccb_getdev *)arg;
 1005                 if (cgd == NULL)
 1006                         break;
 1007 
 1008                 if (SID_TYPE(&cgd->inq_data) != T_DIRECT
 1009                     && SID_TYPE(&cgd->inq_data) != T_RBC
 1010                     && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
 1011                         break;
 1012 
 1013                 /*
 1014                  * Allocate a peripheral instance for
 1015                  * this device and start the probe
 1016                  * process.
 1017                  */
 1018                 status = cam_periph_alloc(daregister, daoninvalidate,
 1019                                           dacleanup, dastart,
 1020                                           "da", CAM_PERIPH_BIO,
 1021                                           cgd->ccb_h.path, daasync,
 1022                                           AC_FOUND_DEVICE, cgd);
 1023 
 1024                 if (status != CAM_REQ_CMP
 1025                  && status != CAM_REQ_INPROG)
 1026                         printf("daasync: Unable to attach to new device "
 1027                                 "due to status 0x%x\n", status);
 1028                 break;
 1029         }
 1030         case AC_SENT_BDR:
 1031         case AC_BUS_RESET:
 1032         {
 1033                 struct da_softc *softc;
 1034                 struct ccb_hdr *ccbh;
 1035                 int s;
 1036 
 1037                 softc = (struct da_softc *)periph->softc;
 1038                 s = splsoftcam();
 1039                 /*
 1040                  * Don't fail on the expected unit attention
 1041                  * that will occur.
 1042                  */
 1043                 softc->flags |= DA_FLAG_RETRY_UA;
 1044                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
 1045                         ccbh->ccb_state |= DA_CCB_RETRY_UA;
 1046                 splx(s);
 1047                 /* FALLTHROUGH*/
 1048         }
 1049         default:
 1050                 cam_periph_async(periph, code, path, arg);
 1051                 break;
 1052         }
 1053 }
 1054 
 1055 static cam_status
 1056 daregister(struct cam_periph *periph, void *arg)
 1057 {
 1058         int s;
 1059         struct da_softc *softc;
 1060         struct ccb_setasync csa;
 1061         struct ccb_getdev *cgd;
 1062         caddr_t match;
 1063 
 1064         cgd = (struct ccb_getdev *)arg;
 1065         if (periph == NULL) {
 1066                 printf("daregister: periph was NULL!!\n");
 1067                 return(CAM_REQ_CMP_ERR);
 1068         }
 1069 
 1070         if (cgd == NULL) {
 1071                 printf("daregister: no getdev CCB, can't register device\n");
 1072                 return(CAM_REQ_CMP_ERR);
 1073         }
 1074 
 1075         softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
 1076             M_NOWAIT|M_ZERO);
 1077 
 1078         if (softc == NULL) {
 1079                 printf("daregister: Unable to probe new device. "
 1080                        "Unable to allocate softc\n");                           
 1081                 return(CAM_REQ_CMP_ERR);
 1082         }
 1083 
 1084         LIST_INIT(&softc->pending_ccbs);
 1085         softc->state = DA_STATE_PROBE;
 1086         bioq_init(&softc->bio_queue);
 1087         if (SID_IS_REMOVABLE(&cgd->inq_data))
 1088                 softc->flags |= DA_FLAG_PACK_REMOVABLE;
 1089         if ((cgd->inq_data.flags & SID_CmdQue) != 0)
 1090                 softc->flags |= DA_FLAG_TAGGED_QUEUING;
 1091 
 1092         periph->softc = softc;
 1093 
 1094         /*
 1095          * See if this device has any quirks.
 1096          */
 1097         match = cam_quirkmatch((caddr_t)&cgd->inq_data,
 1098                                (caddr_t)da_quirk_table,
 1099                                sizeof(da_quirk_table)/sizeof(*da_quirk_table),
 1100                                sizeof(*da_quirk_table), scsi_inquiry_match);
 1101 
 1102         if (match != NULL)
 1103                 softc->quirks = ((struct da_quirk_entry *)match)->quirks;
 1104         else
 1105                 softc->quirks = DA_Q_NONE;
 1106 
 1107         if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
 1108                 softc->minimum_cmd_size = 10;
 1109         else
 1110                 softc->minimum_cmd_size = 6;
 1111 
 1112         /*
 1113          * Block our timeout handler while we
 1114          * add this softc to the dev list.
 1115          */
 1116         s = splsoftclock();
 1117         SLIST_INSERT_HEAD(&softc_list, softc, links);
 1118         splx(s);
 1119 
 1120         /*
 1121          * The DA driver supports a blocksize, but
 1122          * we don't know the blocksize until we do 
 1123          * a read capacity.  So, set a flag to
 1124          * indicate that the blocksize is 
 1125          * unavailable right now.  We'll clear the
 1126          * flag as soon as we've done a read capacity.
 1127          */
 1128         devstat_add_entry(&softc->device_stats, "da", 
 1129                           periph->unit_number, 0,
 1130                           DEVSTAT_BS_UNAVAILABLE,
 1131                           SID_TYPE(&cgd->inq_data) | DEVSTAT_TYPE_IF_SCSI,
 1132                           DEVSTAT_PRIORITY_DISK);
 1133 
 1134         /*
 1135          * Register this media as a disk
 1136          */
 1137         softc->dev = disk_create(periph->unit_number, &softc->disk, 0, 
 1138             &da_cdevsw, &dadisk_cdevsw);
 1139         softc->dev->si_drv1 = periph;
 1140 
 1141         /*
 1142          * Add async callbacks for bus reset and
 1143          * bus device reset calls.  I don't bother
 1144          * checking if this fails as, in most cases,
 1145          * the system will function just fine without
 1146          * them and the only alternative would be to
 1147          * not attach the device on failure.
 1148          */
 1149         xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
 1150         csa.ccb_h.func_code = XPT_SASYNC_CB;
 1151         csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
 1152         csa.callback = daasync;
 1153         csa.callback_arg = periph;
 1154         xpt_action((union ccb *)&csa);
 1155         /*
 1156          * Lock this peripheral until we are setup.
 1157          * This first call can't block
 1158          */
 1159         (void)cam_periph_lock(periph, PRIBIO);
 1160         xpt_schedule(periph, /*priority*/5);
 1161 
 1162         return(CAM_REQ_CMP);
 1163 }
 1164 
 1165 static void
 1166 dastart(struct cam_periph *periph, union ccb *start_ccb)
 1167 {
 1168         struct da_softc *softc;
 1169 
 1170         softc = (struct da_softc *)periph->softc;
 1171 
 1172         
 1173         switch (softc->state) {
 1174         case DA_STATE_NORMAL:
 1175         {
 1176                 /* Pull a buffer from the queue and get going on it */          
 1177                 struct bio *bp;
 1178                 int s;
 1179 
 1180                 /*
 1181                  * See if there is a buf with work for us to do..
 1182                  */
 1183                 s = splbio();
 1184                 bp = bioq_first(&softc->bio_queue);
 1185                 if (periph->immediate_priority <= periph->pinfo.priority) {
 1186                         CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
 1187                                         ("queuing for immediate ccb\n"));
 1188                         start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
 1189                         SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
 1190                                           periph_links.sle);
 1191                         periph->immediate_priority = CAM_PRIORITY_NONE;
 1192                         splx(s);
 1193                         wakeup(&periph->ccb_list);
 1194                 } else if (bp == NULL) {
 1195                         splx(s);
 1196                         xpt_release_ccb(start_ccb);
 1197                 } else {
 1198                         int oldspl;
 1199                         u_int8_t tag_code;
 1200 
 1201                         bioq_remove(&softc->bio_queue, bp);
 1202 
 1203                         devstat_start_transaction(&softc->device_stats);
 1204 
 1205                         if ((softc->flags & DA_FLAG_NEED_OTAG) != 0) {
 1206                                 softc->flags &= ~DA_FLAG_NEED_OTAG;
 1207                                 softc->ordered_tag_count++;
 1208                                 tag_code = MSG_ORDERED_Q_TAG;
 1209                         } else {
 1210                                 tag_code = MSG_SIMPLE_Q_TAG;
 1211                         }
 1212                         if (da_no_6_byte && softc->minimum_cmd_size == 6)
 1213                                 softc->minimum_cmd_size = 10;
 1214                         scsi_read_write(&start_ccb->csio,
 1215                                         /*retries*/da_retry_count,
 1216                                         dadone,
 1217                                         tag_code,
 1218                                         bp->bio_cmd == BIO_READ,
 1219                                         /*byte2*/0,
 1220                                         softc->minimum_cmd_size,
 1221                                         bp->bio_pblkno,
 1222                                         bp->bio_bcount / softc->params.secsize,
 1223                                         bp->bio_data,
 1224                                         bp->bio_bcount,
 1225                                         /*sense_len*/SSD_FULL_SIZE,
 1226                                         da_default_timeout * 1000);
 1227                         start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
 1228 
 1229                         /*
 1230                          * Block out any asyncronous callbacks
 1231                          * while we touch the pending ccb list.
 1232                          */
 1233                         oldspl = splcam();
 1234                         LIST_INSERT_HEAD(&softc->pending_ccbs,
 1235                                          &start_ccb->ccb_h, periph_links.le);
 1236                         splx(oldspl);
 1237 
 1238                         /* We expect a unit attention from this device */
 1239                         if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
 1240                                 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
 1241                                 softc->flags &= ~DA_FLAG_RETRY_UA;
 1242                         }
 1243 
 1244                         start_ccb->ccb_h.ccb_bp = bp;
 1245                         bp = bioq_first(&softc->bio_queue);
 1246                         splx(s);
 1247 
 1248                         xpt_action(start_ccb);
 1249                 }
 1250                 
 1251                 if (bp != NULL) {
 1252                         /* Have more work to do, so ensure we stay scheduled */
 1253                         xpt_schedule(periph, /* XXX priority */1);
 1254                 }
 1255                 break;
 1256         }
 1257         case DA_STATE_PROBE:
 1258         {
 1259                 struct ccb_scsiio *csio;
 1260                 struct scsi_read_capacity_data *rcap;
 1261 
 1262                 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
 1263                                                                 M_TEMP,
 1264                                                                 M_NOWAIT);
 1265                 if (rcap == NULL) {
 1266                         printf("dastart: Couldn't malloc read_capacity data\n");
 1267                         /* da_free_periph??? */
 1268                         break;
 1269                 }
 1270                 csio = &start_ccb->csio;
 1271                 scsi_read_capacity(csio,
 1272                                    /*retries*/4,
 1273                                    dadone,
 1274                                    MSG_SIMPLE_Q_TAG,
 1275                                    rcap,
 1276                                    SSD_FULL_SIZE,
 1277                                    /*timeout*/5000);
 1278                 start_ccb->ccb_h.ccb_bp = NULL;
 1279                 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE;
 1280                 xpt_action(start_ccb);
 1281                 break;
 1282         }
 1283         }
 1284 }
 1285 
 1286 static int
 1287 cmd6workaround(union ccb *ccb)
 1288 {
 1289         struct scsi_rw_6 cmd6;
 1290         struct scsi_rw_10 *cmd10;
 1291         struct da_softc *softc;
 1292         u_int8_t *cdb;
 1293         int frozen;
 1294 
 1295         cdb = ccb->csio.cdb_io.cdb_bytes;
 1296 
 1297         /* Translation only possible if CDB is an array and cmd is R/W6 */
 1298         if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
 1299             (*cdb != READ_6 && *cdb != WRITE_6))
 1300                 return 0;
 1301 
 1302         xpt_print_path(ccb->ccb_h.path);
 1303         printf("READ(6)/WRITE(6) not supported, "
 1304                "increasing minimum_cmd_size to 10.\n");
 1305         softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
 1306         softc->minimum_cmd_size = 10;
 1307 
 1308         bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
 1309         cmd10 = (struct scsi_rw_10 *)cdb;
 1310         cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
 1311         cmd10->byte2 = 0;
 1312         scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
 1313         cmd10->reserved = 0;
 1314         scsi_ulto2b(cmd6.length, cmd10->length);
 1315         cmd10->control = cmd6.control;
 1316         ccb->csio.cdb_len = sizeof(*cmd10);
 1317 
 1318         /* Requeue request, unfreezing queue if necessary */
 1319         frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
 1320         ccb->ccb_h.status = CAM_REQUEUE_REQ;
 1321         xpt_action(ccb);
 1322         if (frozen) {
 1323                 cam_release_devq(ccb->ccb_h.path,
 1324                                  /*relsim_flags*/0,
 1325                                  /*reduction*/0,
 1326                                  /*timeout*/0,
 1327                                  /*getcount_only*/0);
 1328         }
 1329         return (ERESTART);
 1330 }
 1331 
 1332 static void
 1333 dadone(struct cam_periph *periph, union ccb *done_ccb)
 1334 {
 1335         struct da_softc *softc;
 1336         struct ccb_scsiio *csio;
 1337 
 1338         softc = (struct da_softc *)periph->softc;
 1339         csio = &done_ccb->csio;
 1340         switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
 1341         case DA_CCB_BUFFER_IO:
 1342         {
 1343                 struct bio *bp;
 1344                 int    oldspl;
 1345 
 1346                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 1347                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1348                         int error;
 1349                         int s;
 1350                         int sf;
 1351                         
 1352                         if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
 1353                                 sf = SF_RETRY_UA;
 1354                         else
 1355                                 sf = 0;
 1356 
 1357                         error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
 1358                         if (error == ERESTART) {
 1359                                 /*
 1360                                  * A retry was scheuled, so
 1361                                  * just return.
 1362                                  */
 1363                                 return;
 1364                         }
 1365                         if (error != 0) {
 1366                                 struct bio *q_bp;
 1367 
 1368                                 s = splbio();
 1369 
 1370                                 if (error == ENXIO) {
 1371                                         /*
 1372                                          * Catastrophic error.  Mark our pack as
 1373                                          * invalid.
 1374                                          */
 1375                                         /* XXX See if this is really a media
 1376                                          *     change first.
 1377                                          */
 1378                                         xpt_print_path(periph->path);
 1379                                         printf("Invalidating pack\n");
 1380                                         softc->flags |= DA_FLAG_PACK_INVALID;
 1381                                 }
 1382 
 1383                                 /*
 1384                                  * return all queued I/O with EIO, so that
 1385                                  * the client can retry these I/Os in the
 1386                                  * proper order should it attempt to recover.
 1387                                  */
 1388                                 while ((q_bp = bioq_first(&softc->bio_queue))
 1389                                         != NULL) {
 1390                                         bioq_remove(&softc->bio_queue, q_bp);
 1391                                         q_bp->bio_resid = q_bp->bio_bcount;
 1392                                         biofinish(q_bp, NULL, EIO);
 1393                                 }
 1394                                 splx(s);
 1395                                 bp->bio_error = error;
 1396                                 bp->bio_resid = bp->bio_bcount;
 1397                                 bp->bio_flags |= BIO_ERROR;
 1398                         } else {
 1399                                 bp->bio_resid = csio->resid;
 1400                                 bp->bio_error = 0;
 1401                                 if (bp->bio_resid != 0) {
 1402                                         /* Short transfer ??? */
 1403 #if 0
 1404                                         if (cmd6workaround(done_ccb) 
 1405                                                                 == ERESTART)
 1406                                                 return;
 1407 #endif
 1408                                         bp->bio_flags |= BIO_ERROR;
 1409                                 }
 1410                         }
 1411                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1412                                 cam_release_devq(done_ccb->ccb_h.path,
 1413                                                  /*relsim_flags*/0,
 1414                                                  /*reduction*/0,
 1415                                                  /*timeout*/0,
 1416                                                  /*getcount_only*/0);
 1417                 } else {
 1418                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1419                                 panic("REQ_CMP with QFRZN");
 1420                         bp->bio_resid = csio->resid;
 1421                         if (csio->resid > 0) {
 1422                                 /* Short transfer ??? */
 1423 #if 0 /* XXX most of the broken umass devices need this ad-hoc work around */
 1424                                 if (cmd6workaround(done_ccb) == ERESTART)
 1425                                         return;
 1426 #endif
 1427                                 bp->bio_flags |= BIO_ERROR;
 1428                         }
 1429                 }
 1430 
 1431                 /*
 1432                  * Block out any asyncronous callbacks
 1433                  * while we touch the pending ccb list.
 1434                  */
 1435                 oldspl = splcam();
 1436                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
 1437                 splx(oldspl);
 1438 
 1439                 if (softc->device_stats.busy_count == 0)
 1440                         softc->flags |= DA_FLAG_WENT_IDLE;
 1441 
 1442                 biofinish(bp, &softc->device_stats, 0);
 1443                 break;
 1444         }
 1445         case DA_CCB_PROBE:
 1446         {
 1447                 struct     scsi_read_capacity_data *rdcap;
 1448                 char       announce_buf[80];
 1449 
 1450                 rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
 1451                 
 1452                 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
 1453                         struct disk_params *dp;
 1454 
 1455                         dasetgeom(periph, rdcap);
 1456                         dp = &softc->params;
 1457                         snprintf(announce_buf, sizeof(announce_buf),
 1458                                 "%luMB (%u %u byte sectors: %dH %dS/T %dC)",
 1459                                 (unsigned long) (((u_int64_t)dp->secsize *
 1460                                 dp->sectors) / (1024*1024)), dp->sectors,
 1461                                 dp->secsize, dp->heads, dp->secs_per_track,
 1462                                 dp->cylinders);
 1463                 } else {
 1464                         int     error;
 1465 
 1466                         announce_buf[0] = '\0';
 1467 
 1468                         /*
 1469                          * Retry any UNIT ATTENTION type errors.  They
 1470                          * are expected at boot.
 1471                          */
 1472                         error = daerror(done_ccb, CAM_RETRY_SELTO,
 1473                                         SF_RETRY_UA|SF_NO_PRINT);
 1474                         if (error == ERESTART) {
 1475                                 /*
 1476                                  * A retry was scheuled, so
 1477                                  * just return.
 1478                                  */
 1479                                 return;
 1480                         } else if (error != 0) {
 1481                                 struct scsi_sense_data *sense;
 1482                                 int asc, ascq;
 1483                                 int sense_key, error_code;
 1484                                 int have_sense;
 1485                                 cam_status status;
 1486                                 struct ccb_getdev cgd;
 1487 
 1488                                 /* Don't wedge this device's queue */
 1489                                 status = done_ccb->ccb_h.status;
 1490                                 if ((status & CAM_DEV_QFRZN) != 0)
 1491                                         cam_release_devq(done_ccb->ccb_h.path,
 1492                                                          /*relsim_flags*/0,
 1493                                                          /*reduction*/0,
 1494                                                          /*timeout*/0,
 1495                                                          /*getcount_only*/0);
 1496 
 1497 
 1498                                 xpt_setup_ccb(&cgd.ccb_h, 
 1499                                               done_ccb->ccb_h.path,
 1500                                               /* priority */ 1);
 1501                                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 1502                                 xpt_action((union ccb *)&cgd);
 1503 
 1504                                 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
 1505                                  || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
 1506                                  || ((status & CAM_AUTOSNS_VALID) == 0))
 1507                                         have_sense = FALSE;
 1508                                 else
 1509                                         have_sense = TRUE;
 1510 
 1511                                 if (have_sense) {
 1512                                         sense = &csio->sense_data;
 1513                                         scsi_extract_sense(sense, &error_code,
 1514                                                            &sense_key, 
 1515                                                            &asc, &ascq);
 1516                                 }
 1517                                 /*
 1518                                  * Attach to anything that claims to be a
 1519                                  * direct access or optical disk device,
 1520                                  * as long as it doesn't return a "Logical
 1521                                  * unit not supported" (0x25) error.
 1522                                  */
 1523                                 if ((have_sense) && (asc != 0x25)
 1524                                  && (error_code == SSD_CURRENT_ERROR)) {
 1525                                         const char *sense_key_desc;
 1526                                         const char *asc_desc;
 1527 
 1528                                         scsi_sense_desc(sense_key, asc, ascq,
 1529                                                         &cgd.inq_data,
 1530                                                         &sense_key_desc,
 1531                                                         &asc_desc);
 1532                                         snprintf(announce_buf,
 1533                                             sizeof(announce_buf),
 1534                                                 "Attempt to query device "
 1535                                                 "size failed: %s, %s",
 1536                                                 sense_key_desc,
 1537                                                 asc_desc);
 1538                                 } else { 
 1539                                         if (have_sense)
 1540                                                 scsi_sense_print(
 1541                                                         &done_ccb->csio);
 1542                                         else {
 1543                                                 xpt_print_path(periph->path);
 1544                                                 printf("got CAM status %#x\n",
 1545                                                        done_ccb->ccb_h.status);
 1546                                         }
 1547 
 1548                                         xpt_print_path(periph->path);
 1549                                         printf("fatal error, failed" 
 1550                                                " to attach to device\n");
 1551 
 1552                                         /*
 1553                                          * Free up resources.
 1554                                          */
 1555                                         cam_periph_invalidate(periph);
 1556                                 } 
 1557                         }
 1558                 }
 1559                 free(rdcap, M_TEMP);
 1560                 if (announce_buf[0] != '\0')
 1561                         xpt_announce_periph(periph, announce_buf);
 1562                 softc->state = DA_STATE_NORMAL; 
 1563                 /*
 1564                  * Since our peripheral may be invalidated by an error
 1565                  * above or an external event, we must release our CCB
 1566                  * before releasing the probe lock on the peripheral.
 1567                  * The peripheral will only go away once the last lock
 1568                  * is removed, and we need it around for the CCB release
 1569                  * operation.
 1570                  */
 1571                 xpt_release_ccb(done_ccb);
 1572                 cam_periph_unlock(periph);
 1573                 return;
 1574         }
 1575         case DA_CCB_WAITING:
 1576         {
 1577                 /* Caller will release the CCB */
 1578                 wakeup(&done_ccb->ccb_h.cbfcnp);
 1579                 return;
 1580         }
 1581         case DA_CCB_DUMP:
 1582                 /* No-op.  We're polling */
 1583                 return;
 1584         default:
 1585                 break;
 1586         }
 1587         xpt_release_ccb(done_ccb);
 1588 }
 1589 
 1590 static int
 1591 daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 1592 {
 1593         struct da_softc   *softc;
 1594         struct cam_periph *periph;
 1595         int error, sense_key, error_code, asc, ascq;
 1596 
 1597         periph = xpt_path_periph(ccb->ccb_h.path);
 1598         softc = (struct da_softc *)periph->softc;
 1599 
 1600         /*
 1601          * Automatically detect devices that do not support
 1602          * READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
 1603          */
 1604         error = 0;
 1605         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR
 1606           && ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) {
 1607                 scsi_extract_sense(&ccb->csio.sense_data,
 1608                                    &error_code, &sense_key, &asc, &ascq);
 1609                 if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
 1610                         error = cmd6workaround(ccb);
 1611         }
 1612         if (error == ERESTART)
 1613                 return (ERESTART);
 1614 
 1615         /*
 1616          * XXX
 1617          * Until we have a better way of doing pack validation,
 1618          * don't treat UAs as errors.
 1619          */
 1620         sense_flags |= SF_RETRY_UA;
 1621         return(cam_periph_error(ccb, cam_flags, sense_flags,
 1622                                 &softc->saved_ccb));
 1623 }
 1624 
 1625 static void
 1626 daprevent(struct cam_periph *periph, int action)
 1627 {
 1628         struct  da_softc *softc;
 1629         union   ccb *ccb;               
 1630         int     error;
 1631                 
 1632         softc = (struct da_softc *)periph->softc;
 1633 
 1634         if (((action == PR_ALLOW)
 1635           && (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
 1636          || ((action == PR_PREVENT)
 1637           && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
 1638                 return;
 1639         }
 1640 
 1641         ccb = cam_periph_getccb(periph, /*priority*/1);
 1642 
 1643         scsi_prevent(&ccb->csio,
 1644                      /*retries*/1,
 1645                      /*cbcfp*/dadone,
 1646                      MSG_SIMPLE_Q_TAG,
 1647                      action,
 1648                      SSD_FULL_SIZE,
 1649                      5000);
 1650 
 1651         error = cam_periph_runccb(ccb, /*error_routine*/NULL, CAM_RETRY_SELTO,
 1652                                   SF_RETRY_UA, &softc->device_stats);
 1653 
 1654         if (error == 0) {
 1655                 if (action == PR_ALLOW)
 1656                         softc->flags &= ~DA_FLAG_PACK_LOCKED;
 1657                 else
 1658                         softc->flags |= DA_FLAG_PACK_LOCKED;
 1659         }
 1660 
 1661         xpt_release_ccb(ccb);
 1662 }
 1663 
 1664 static void
 1665 dasetgeom(struct cam_periph *periph, struct scsi_read_capacity_data * rdcap)
 1666 {
 1667         struct ccb_calc_geometry ccg;
 1668         struct da_softc *softc;
 1669         struct disk_params *dp;
 1670 
 1671         softc = (struct da_softc *)periph->softc;
 1672 
 1673         dp = &softc->params;
 1674         dp->secsize = scsi_4btoul(rdcap->length);
 1675         dp->sectors = scsi_4btoul(rdcap->addr) + 1;
 1676         /*
 1677          * Have the controller provide us with a geometry
 1678          * for this disk.  The only time the geometry
 1679          * matters is when we boot and the controller
 1680          * is the only one knowledgeable enough to come
 1681          * up with something that will make this a bootable
 1682          * device.
 1683          */
 1684         xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1);
 1685         ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
 1686         ccg.block_size = dp->secsize;
 1687         ccg.volume_size = dp->sectors;
 1688         ccg.heads = 0;
 1689         ccg.secs_per_track = 0;
 1690         ccg.cylinders = 0;
 1691         xpt_action((union ccb*)&ccg);
 1692         dp->heads = ccg.heads;
 1693         dp->secs_per_track = ccg.secs_per_track;
 1694         dp->cylinders = ccg.cylinders;
 1695 }
 1696 
 1697 static void
 1698 dasendorderedtag(void *arg)
 1699 {
 1700         struct da_softc *softc;
 1701         int s;
 1702 
 1703         for (softc = SLIST_FIRST(&softc_list);
 1704              softc != NULL;
 1705              softc = SLIST_NEXT(softc, links)) {
 1706                 s = splsoftcam();
 1707                 if ((softc->ordered_tag_count == 0) 
 1708                  && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
 1709                         softc->flags |= DA_FLAG_NEED_OTAG;
 1710                 }
 1711                 if (softc->device_stats.busy_count > 0)
 1712                         softc->flags &= ~DA_FLAG_WENT_IDLE;
 1713 
 1714                 softc->ordered_tag_count = 0;
 1715                 splx(s);
 1716         }
 1717         /* Queue us up again */
 1718         timeout(dasendorderedtag, NULL,
 1719                 (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
 1720 }
 1721 
 1722 /*
 1723  * Step through all DA peripheral drivers, and if the device is still open,
 1724  * sync the disk cache to physical media.
 1725  */
 1726 static void
 1727 dashutdown(void * arg, int howto)
 1728 {
 1729         struct cam_periph *periph;
 1730         struct da_softc *softc;
 1731 
 1732         TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
 1733                 union ccb ccb;
 1734                 softc = (struct da_softc *)periph->softc;
 1735 
 1736                 /*
 1737                  * We only sync the cache if the drive is still open, and
 1738                  * if the drive is capable of it..
 1739                  */
 1740                 if (((softc->flags & DA_FLAG_OPEN) == 0)
 1741                  || (softc->quirks & DA_Q_NO_SYNC_CACHE))
 1742                         continue;
 1743 
 1744                 xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
 1745 
 1746                 ccb.ccb_h.ccb_state = DA_CCB_DUMP;
 1747                 scsi_synchronize_cache(&ccb.csio,
 1748                                        /*retries*/1,
 1749                                        /*cbfcnp*/dadone,
 1750                                        MSG_SIMPLE_Q_TAG,
 1751                                        /*begin_lba*/0, /* whole disk */
 1752                                        /*lb_count*/0,
 1753                                        SSD_FULL_SIZE,
 1754                                        60 * 60 * 1000);
 1755 
 1756                 xpt_polled_action(&ccb);
 1757 
 1758                 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1759                         if (((ccb.ccb_h.status & CAM_STATUS_MASK) ==
 1760                              CAM_SCSI_STATUS_ERROR)
 1761                          && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){
 1762                                 int error_code, sense_key, asc, ascq;
 1763 
 1764                                 scsi_extract_sense(&ccb.csio.sense_data,
 1765                                                    &error_code, &sense_key,
 1766                                                    &asc, &ascq);
 1767 
 1768                                 if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
 1769                                         scsi_sense_print(&ccb.csio);
 1770                         } else {
 1771                                 xpt_print_path(periph->path);
 1772                                 printf("Synchronize cache failed, status "
 1773                                        "== 0x%x, scsi status == 0x%x\n",
 1774                                        ccb.ccb_h.status, ccb.csio.scsi_status);
 1775                         }
 1776                 }
 1777 
 1778                 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
 1779                         cam_release_devq(ccb.ccb_h.path,
 1780                                          /*relsim_flags*/0,
 1781                                          /*reduction*/0,
 1782                                          /*timeout*/0,
 1783                                          /*getcount_only*/0);
 1784 
 1785         }
 1786 }
 1787 
 1788 #else /* !_KERNEL */
 1789 
 1790 /*
 1791  * XXX This is only left out of the kernel build to silence warnings.  If,
 1792  * for some reason this function is used in the kernel, the ifdefs should
 1793  * be moved so it is included both in the kernel and userland.
 1794  */
 1795 void
 1796 scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
 1797                  void (*cbfcnp)(struct cam_periph *, union ccb *),
 1798                  u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
 1799                  u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
 1800                  u_int32_t timeout)
 1801 {
 1802         struct scsi_format_unit *scsi_cmd;
 1803 
 1804         scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
 1805         scsi_cmd->opcode = FORMAT_UNIT;
 1806         scsi_cmd->byte2 = byte2;
 1807         scsi_ulto2b(ileave, scsi_cmd->interleave);
 1808 
 1809         cam_fill_csio(csio,
 1810                       retries,
 1811                       cbfcnp,
 1812                       /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
 1813                       tag_action,
 1814                       data_ptr,
 1815                       dxfer_len,
 1816                       sense_len,
 1817                       sizeof(*scsi_cmd),
 1818                       timeout);
 1819 }
 1820 
 1821 #endif /* _KERNEL */

Cache object: d7734188731f185781994eb82ba710a1


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