1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 
  27 /*
  28  * Direct Attached  disk driver for SPARC machines.
  29  */
  30 
  31 /*
  32  * Includes, Declarations and Local Data
  33  */
  34 #include <sys/dada/dada.h>
  35 #include <sys/dkbad.h>
  36 #include <sys/dklabel.h>
  37 #include <sys/dkio.h>
  38 #include <sys/cdio.h>
  39 #include <sys/vtoc.h>
  40 #include <sys/dada/targets/daddef.h>
  41 #include <sys/dada/targets/dadpriv.h>
  42 #include <sys/file.h>
  43 #include <sys/stat.h>
  44 #include <sys/kstat.h>
  45 #include <sys/vtrace.h>
  46 #include <sys/aio_req.h>
  47 #include <sys/note.h>
  48 #include <sys/cmlb.h>
  49 
  50 /*
  51  * Global Error Levels for Error Reporting
  52  */
  53 int dcd_error_level     = DCD_ERR_RETRYABLE;
  54 /*
  55  * Local Static Data
  56  */
  57 
  58 static int dcd_io_time          = DCD_IO_TIME;
  59 static int dcd_retry_count      = DCD_RETRY_COUNT;
  60 #ifndef lint
  61 static int dcd_report_pfa = 1;
  62 #endif
  63 static int dcd_rot_delay = 4;
  64 static int dcd_poll_busycnt = DCD_POLL_TIMEOUT;
  65 
  66 /*
  67  * Local Function Prototypes
  68  */
  69 
  70 static int dcdopen(dev_t *dev_p, int flag, int otyp, cred_t *cred_p);
  71 static int dcdclose(dev_t dev, int flag, int otyp, cred_t *cred_p);
  72 static int dcdstrategy(struct buf *bp);
  73 static int dcddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk);
  74 static int dcdioctl(dev_t, int, intptr_t, int, cred_t *, int *);
  75 static int dcdread(dev_t dev, struct uio *uio, cred_t *cred_p);
  76 static int dcdwrite(dev_t dev, struct uio *uio, cred_t *cred_p);
  77 static int dcd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int,
  78     char *, caddr_t, int *);
  79 static int dcdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p);
  80 static int dcdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p);
  81 
  82 
  83 static void dcd_free_softstate(struct dcd_disk *un, dev_info_t *devi);
  84 static int dcd_doattach(dev_info_t *devi, int (*f)());
  85 static int dcd_validate_geometry(struct dcd_disk *un);
  86 static ddi_devid_t dcd_get_devid(struct dcd_disk *un);
  87 static ddi_devid_t  dcd_create_devid(struct dcd_disk *un);
  88 static int dcd_make_devid_from_serial(struct dcd_disk *un);
  89 static void dcd_validate_model_serial(char *str, int *retlen, int totallen);
  90 static int dcd_read_deviceid(struct dcd_disk *un);
  91 static int dcd_write_deviceid(struct dcd_disk *un);
  92 static int dcd_poll(struct dcd_pkt *pkt);
  93 static char *dcd_rname(int reason);
  94 static void dcd_flush_cache(struct dcd_disk *un);
  95 
  96 static int dcd_compute_dk_capacity(struct dcd_device *devp,
  97     diskaddr_t *capacity);
  98 static int dcd_send_lb_rw_cmd(dev_info_t *devinfo, void *bufaddr,
  99     diskaddr_t start_block, size_t reqlength, uchar_t cmd);
 100 
 101 static void dcdmin(struct buf *bp);
 102 
 103 static int dcdioctl_cmd(dev_t, struct udcd_cmd *,
 104     enum uio_seg, enum uio_seg);
 105 
 106 static void dcdstart(struct dcd_disk *un);
 107 static void dcddone_and_mutex_exit(struct dcd_disk *un, struct buf *bp);
 108 static void make_dcd_cmd(struct dcd_disk *un, struct buf *bp, int (*f)());
 109 static void dcdudcdmin(struct buf *bp);
 110 
 111 static int dcdrunout(caddr_t);
 112 static int dcd_check_wp(dev_t dev);
 113 static int dcd_unit_ready(dev_t dev);
 114 static void dcd_handle_tran_busy(struct buf *bp, struct diskhd *dp,
 115     struct dcd_disk *un);
 116 static void dcdintr(struct dcd_pkt *pkt);
 117 static int dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp);
 118 static void dcd_offline(struct dcd_disk *un, int bechatty);
 119 static int dcd_ready_and_valid(dev_t dev, struct dcd_disk *un);
 120 static void dcd_reset_disk(struct dcd_disk *un, struct dcd_pkt *pkt);
 121 static void dcd_translate(struct dadkio_status32 *statp, struct udcd_cmd *cmdp);
 122 static int dcdflushdone(struct buf *bp);
 123 
 124 /* Function prototypes for cmlb */
 125 
 126 static int dcd_lb_rdwr(dev_info_t *devi, uchar_t cmd, void *bufaddr,
 127     diskaddr_t start_block, size_t reqlength, void *tg_cookie);
 128 
 129 static int dcd_lb_getphygeom(dev_info_t *devi, cmlb_geom_t *phygeomp);
 130 static int dcd_lb_getinfo(dev_info_t *devi, int cmd, void *arg,
 131     void *tg_cookie);
 132 
 133 
 134 static cmlb_tg_ops_t dcd_lb_ops = {
 135         TG_DK_OPS_VERSION_1,
 136         dcd_lb_rdwr,
 137         dcd_lb_getinfo
 138 };
 139 
 140 /*
 141  * Error and Logging Functions
 142  */
 143 #ifndef lint
 144 static void clean_print(dev_info_t *dev, char *label, uint_t level,
 145     char *title, char *data, int len);
 146 static void dcdrestart(void *arg);
 147 #endif /* lint */
 148 
 149 static int dcd_check_error(struct dcd_disk *un, struct buf *bp);
 150 
 151 /*
 152  * Error statistics create/update functions
 153  */
 154 static int dcd_create_errstats(struct dcd_disk *, int);
 155 
 156 
 157 
 158 /*PRINTFLIKE4*/
 159 extern void dcd_log(dev_info_t *, char *, uint_t, const char *, ...)
 160     __KPRINTFLIKE(4);
 161 extern void makecommand(struct dcd_pkt *, int, uchar_t, uint32_t,
 162     uchar_t, uint32_t, uchar_t, uchar_t);
 163 
 164 
 165 /*
 166  * Configuration Routines
 167  */
 168 static int dcdinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 169     void **result);
 170 static int dcdprobe(dev_info_t *devi);
 171 static int dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd);
 172 static int dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 173 static int dcdreset(dev_info_t *dip, ddi_reset_cmd_t cmd);
 174 static int dcd_dr_detach(dev_info_t *devi);
 175 static int dcdpower(dev_info_t *devi, int component, int level);
 176 
 177 static void *dcd_state;
 178 static int dcd_max_instance;
 179 static char *dcd_label = "dad";
 180 
 181 static char *diskokay = "disk okay\n";
 182 
 183 #if DEBUG || lint
 184 #define DCDDEBUG
 185 #endif
 186 
 187 int dcd_test_flag = 0;
 188 /*
 189  * Debugging macros
 190  */
 191 #ifdef  DCDDEBUG
 192 static int dcddebug = 0;
 193 #define DEBUGGING       (dcddebug > 1)
 194 #define DAD_DEBUG       if (dcddebug == 1) dcd_log
 195 #define DAD_DEBUG2      if (dcddebug > 1) dcd_log
 196 #else   /* DCDDEBUG */
 197 #define dcddebug                (0)
 198 #define DEBUGGING       (0)
 199 #define DAD_DEBUG       if (0) dcd_log
 200 #define DAD_DEBUG2      if (0) dcd_log
 201 #endif
 202 
 203 /*
 204  * we use pkt_private area for storing bp and retry_count
 205  * XXX: Really is this usefull.
 206  */
 207 struct dcd_pkt_private {
 208         struct buf      *dcdpp_bp;
 209         short            dcdpp_retry_count;
 210         short            dcdpp_victim_retry_count;
 211 };
 212 
 213 
 214 _NOTE(SCHEME_PROTECTS_DATA("Unique per pkt", dcd_pkt_private buf))
 215 
 216 #define PP_LEN  (sizeof (struct dcd_pkt_private))
 217 
 218 #define PKT_SET_BP(pkt, bp)     \
 219         ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_bp = bp
 220 #define PKT_GET_BP(pkt) \
 221         (((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_bp)
 222 
 223 
 224 #define PKT_SET_RETRY_CNT(pkt, n) \
 225         ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count = n
 226 
 227 #define PKT_GET_RETRY_CNT(pkt) \
 228         (((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count)
 229 
 230 #define PKT_INCR_RETRY_CNT(pkt, n) \
 231         ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count += n
 232 
 233 #define PKT_SET_VICTIM_RETRY_CNT(pkt, n) \
 234         ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count \
 235                         = n
 236 
 237 #define PKT_GET_VICTIM_RETRY_CNT(pkt) \
 238         (((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count)
 239 #define PKT_INCR_VICTIM_RETRY_CNT(pkt, n) \
 240         ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count \
 241                         += n
 242 
 243 #define DISK_NOT_READY_RETRY_COUNT      (dcd_retry_count / 2)
 244 
 245 
 246 /*
 247  * Urk!
 248  */
 249 #define SET_BP_ERROR(bp, err)   \
 250         bioerror(bp, err);
 251 
 252 #define IOSP                    KSTAT_IO_PTR(un->un_stats)
 253 #define IO_PARTITION_STATS      un->un_pstats[DCDPART(bp->b_edev)]
 254 #define IOSP_PARTITION          KSTAT_IO_PTR(IO_PARTITION_STATS)
 255 
 256 #define DCD_DO_KSTATS(un, kstat_function, bp) \
 257         ASSERT(mutex_owned(DCD_MUTEX)); \
 258         if (bp != un->un_sbufp) { \
 259                 if (un->un_stats) { \
 260                         kstat_function(IOSP); \
 261                 } \
 262                 if (IO_PARTITION_STATS) { \
 263                         kstat_function(IOSP_PARTITION); \
 264                 } \
 265         }
 266 
 267 #define DCD_DO_ERRSTATS(un, x) \
 268         if (un->un_errstats) { \
 269                 struct dcd_errstats *dtp; \
 270                 dtp = (struct dcd_errstats *)un->un_errstats->ks_data; \
 271                 dtp->x.value.ui32++; \
 272         }
 273 
 274 #define GET_SOFT_STATE(dev)                                             \
 275         struct dcd_disk *un;                                    \
 276         int instance, part;                                     \
 277         minor_t minor = getminor(dev);                          \
 278                                                                         \
 279         part = minor & DCDPART_MASK;                                        \
 280         instance = minor >> DCDUNIT_SHIFT;                                \
 281         if ((un = ddi_get_soft_state(dcd_state, instance)) == NULL)     \
 282                 return (ENXIO);
 283 
 284 #define LOGICAL_BLOCK_ALIGN(blkno, blknoshift) \
 285                 (((blkno) & ((1 << (blknoshift)) - 1)) == 0)
 286 
 287 /*
 288  * After the following number of sectors, the cylinder number spills over
 289  * 0xFFFF if sectors = 63 and heads = 16.
 290  */
 291 #define NUM_SECTORS_32G 0x3EFFC10
 292 
 293 /*
 294  * Configuration Data
 295  */
 296 
 297 /*
 298  * Device driver ops vector
 299  */
 300 
 301 static struct cb_ops dcd_cb_ops = {
 302         dcdopen,                /* open */
 303         dcdclose,               /* close */
 304         dcdstrategy,            /* strategy */
 305         nodev,                  /* print */
 306         dcddump,                /* dump */
 307         dcdread,                /* read */
 308         dcdwrite,               /* write */
 309         dcdioctl,               /* ioctl */
 310         nodev,                  /* devmap */
 311         nodev,                  /* mmap */
 312         nodev,                  /* segmap */
 313         nochpoll,               /* poll */
 314         dcd_prop_op,            /* cb_prop_op */
 315         0,                      /* streamtab  */
 316         D_64BIT | D_MP | D_NEW, /* Driver compatibility flag */
 317         CB_REV,                 /* cb_rev */
 318         dcdaread,               /* async I/O read entry point */
 319         dcdawrite               /* async I/O write entry point */
 320 };
 321 
 322 static struct dev_ops dcd_ops = {
 323         DEVO_REV,               /* devo_rev, */
 324         0,                      /* refcnt  */
 325         dcdinfo,                /* info */
 326         nulldev,                /* identify */
 327         dcdprobe,               /* probe */
 328         dcdattach,              /* attach */
 329         dcddetach,              /* detach */
 330         dcdreset,               /* reset */
 331         &dcd_cb_ops,                /* driver operations */
 332         (struct bus_ops *)0,    /* bus operations */
 333         dcdpower,               /* power */
 334         ddi_quiesce_not_supported,      /* devo_quiesce */
 335 };
 336 
 337 
 338 /*
 339  * This is the loadable module wrapper.
 340  */
 341 #include <sys/modctl.h>
 342 
 343 static struct modldrv modldrv = {
 344         &mod_driverops,             /* Type of module. This one is a driver */
 345         "DAD Disk Driver",      /* Name of the module. */
 346         &dcd_ops,   /* driver ops */
 347 };
 348 
 349 
 350 
 351 static struct modlinkage modlinkage = {
 352         MODREV_1, &modldrv, NULL
 353 };
 354 
 355 /*
 356  * the dcd_attach_mutex only protects dcd_max_instance in multi-threaded
 357  * attach situations
 358  */
 359 static kmutex_t dcd_attach_mutex;
 360 
 361 int
 362 _init(void)
 363 {
 364         int e;
 365 
 366         if ((e = ddi_soft_state_init(&dcd_state, sizeof (struct dcd_disk),
 367             DCD_MAXUNIT)) != 0)
 368                 return (e);
 369 
 370         mutex_init(&dcd_attach_mutex, NULL, MUTEX_DRIVER, NULL);
 371         e = mod_install(&modlinkage);
 372         if (e != 0) {
 373                 mutex_destroy(&dcd_attach_mutex);
 374                 ddi_soft_state_fini(&dcd_state);
 375                 return (e);
 376         }
 377 
 378         return (e);
 379 }
 380 
 381 int
 382 _fini(void)
 383 {
 384         int e;
 385 
 386         if ((e = mod_remove(&modlinkage)) != 0)
 387                 return (e);
 388 
 389         ddi_soft_state_fini(&dcd_state);
 390         mutex_destroy(&dcd_attach_mutex);
 391 
 392         return (e);
 393 }
 394 
 395 int
 396 _info(struct modinfo *modinfop)
 397 {
 398 
 399         return (mod_info(&modlinkage, modinfop));
 400 }
 401 
 402 static int
 403 dcdprobe(dev_info_t *devi)
 404 {
 405         struct dcd_device *devp;
 406         int rval = DDI_PROBE_PARTIAL;
 407         int instance;
 408 
 409         devp = ddi_get_driver_private(devi);
 410         instance = ddi_get_instance(devi);
 411 
 412         /*
 413          * Keep a count of how many disks (ie. highest instance no) we have
 414          * XXX currently not used but maybe useful later again
 415          */
 416         mutex_enter(&dcd_attach_mutex);
 417         if (instance > dcd_max_instance)
 418                 dcd_max_instance = instance;
 419         mutex_exit(&dcd_attach_mutex);
 420 
 421         DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "dcdprobe:\n");
 422 
 423         if (ddi_get_soft_state(dcd_state, instance) != NULL)
 424                 return (DDI_PROBE_PARTIAL);
 425 
 426         /*
 427          * Turn around and call utility probe routine
 428          * to see whether we actually have a disk at
 429          */
 430 
 431         DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
 432             "dcdprobe: %x\n", dcd_probe(devp, NULL_FUNC));
 433 
 434         switch (dcd_probe(devp, NULL_FUNC)) {
 435         default:
 436         case DCDPROBE_NORESP:
 437         case DCDPROBE_NONCCS:
 438         case DCDPROBE_NOMEM:
 439         case DCDPROBE_FAILURE:
 440         case DCDPROBE_BUSY:
 441                 break;
 442 
 443         case DCDPROBE_EXISTS:
 444                 /*
 445                  * Check whether it is a ATA device and then
 446                  * return  SUCCESS.
 447                  */
 448                 DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
 449                     "config %x\n", devp->dcd_ident->dcd_config);
 450                 if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
 451                         if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
 452                                 rval = DDI_PROBE_SUCCESS;
 453                         } else
 454                                 rval = DDI_PROBE_FAILURE;
 455                 } else {
 456                         rval = DDI_PROBE_FAILURE;
 457                 }
 458                 break;
 459         }
 460         dcd_unprobe(devp);
 461 
 462         DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
 463             "dcdprobe returns %x\n", rval);
 464 
 465         return (rval);
 466 }
 467 
 468 
 469 /*ARGSUSED*/
 470 static int
 471 dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd)
 472 {
 473         int instance, rval;
 474         struct dcd_device *devp;
 475         struct dcd_disk *un;
 476         struct diskhd *dp;
 477         char    *pm_comp[] =
 478             { "NAME=ide-disk", "0=standby", "1=idle", "2=active" };
 479 
 480         /* CONSTCOND */
 481         ASSERT(NO_COMPETING_THREADS);
 482 
 483 
 484         devp = ddi_get_driver_private(devi);
 485         instance = ddi_get_instance(devi);
 486         DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "Attach Started\n");
 487 
 488         switch (cmd) {
 489         case DDI_ATTACH:
 490                 break;
 491 
 492         case DDI_RESUME:
 493                 if (!(un = ddi_get_soft_state(dcd_state, instance)))
 494                         return (DDI_FAILURE);
 495                 mutex_enter(DCD_MUTEX);
 496                 Restore_state(un);
 497                 /*
 498                  * Restore the state which was saved to give the
 499                  * the right state in un_last_state
 500                  */
 501                 un->un_last_state = un->un_save_state;
 502                 un->un_throttle = 2;
 503                 cv_broadcast(&un->un_suspend_cv);
 504                 /*
 505                  * Raise the power level of the device to active.
 506                  */
 507                 mutex_exit(DCD_MUTEX);
 508                 (void) pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE);
 509                 mutex_enter(DCD_MUTEX);
 510 
 511                 /*
 512                  * start unit - if this is a low-activity device
 513                  * commands in queue will have to wait until new
 514                  * commands come in, which may take awhile.
 515                  * Also, we specifically don't check un_ncmds
 516                  * because we know that there really are no
 517                  * commands in progress after the unit was suspended
 518                  * and we could have reached the throttle level, been
 519                  * suspended, and have no new commands coming in for
 520                  * awhile.  Highly unlikely, but so is the low-
 521                  * activity disk scenario.
 522                  */
 523                 dp = &un->un_utab;
 524                 if (dp->b_actf && (dp->b_forw == NULL)) {
 525                         dcdstart(un);
 526                 }
 527 
 528                 mutex_exit(DCD_MUTEX);
 529                 return (DDI_SUCCESS);
 530 
 531         default:
 532                 return (DDI_FAILURE);
 533         }
 534 
 535         if (dcd_doattach(devi, SLEEP_FUNC) == DDI_FAILURE) {
 536                 return (DDI_FAILURE);
 537         }
 538 
 539         if (!(un = (struct dcd_disk *)
 540             ddi_get_soft_state(dcd_state, instance))) {
 541                 return (DDI_FAILURE);
 542         }
 543         devp->dcd_private = (ataopaque_t)un;
 544 
 545         /*
 546          * Add a zero-length attribute to tell the world we support
 547          * kernel ioctls (for layered drivers)
 548          */
 549         (void) ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP,
 550             DDI_KERNEL_IOCTL, NULL, 0);
 551 
 552         /*
 553          * Since the dad device does not have the 'reg' property,
 554          * cpr will not call its DDI_SUSPEND/DDI_RESUME entries.
 555          * The following code is to tell cpr that this device
 556          * does need to be suspended and resumed.
 557          */
 558         (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
 559             "pm-hardware-state", (caddr_t)"needs-suspend-resume");
 560 
 561         /*
 562          * Initialize power management bookkeeping;
 563          * Create components - In IDE case there are 3 levels and one
 564          * component. The levels being - active, idle, standby.
 565          */
 566 
 567         rval = ddi_prop_update_string_array(DDI_DEV_T_NONE,
 568             devi, "pm-components", pm_comp, 4);
 569         if (rval == DDI_PROP_SUCCESS) {
 570                 /*
 571                  * Ignore the return value of pm_raise_power
 572                  * Even if we check the return values and
 573                  * remove the property created above, PM
 574                  * framework will not honour the change after
 575                  * first call to pm_raise_power. Hence, the
 576                  * removal of that property does not help if
 577                  * pm_raise_power fails.
 578                  */
 579                 (void) pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE);
 580         }
 581 
 582         ddi_report_dev(devi);
 583 
 584         cmlb_alloc_handle(&un->un_dklbhandle);
 585 
 586         if (cmlb_attach(devi,
 587             &dcd_lb_ops,
 588             0,
 589             B_FALSE,
 590             B_FALSE,
 591             DDI_NT_BLOCK_CHAN,
 592             CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8,
 593             un->un_dklbhandle,
 594             0) != 0) {
 595                 cmlb_free_handle(&un->un_dklbhandle);
 596                 dcd_free_softstate(un, devi);
 597                 return (DDI_FAILURE);
 598         }
 599 
 600         mutex_enter(DCD_MUTEX);
 601         (void) dcd_validate_geometry(un);
 602 
 603         /* Get devid; create a devid ONLY IF could not get ID */
 604         if (dcd_get_devid(un) == NULL) {
 605                 /* Create the fab'd devid */
 606                 (void) dcd_create_devid(un);
 607         }
 608         mutex_exit(DCD_MUTEX);
 609 
 610         return (DDI_SUCCESS);
 611 }
 612 
 613 static void
 614 dcd_free_softstate(struct dcd_disk *un, dev_info_t *devi)
 615 {
 616         struct dcd_device               *devp;
 617         int instance = ddi_get_instance(devi);
 618 
 619         devp = ddi_get_driver_private(devi);
 620 
 621         if (un) {
 622                 sema_destroy(&un->un_semoclose);
 623                 cv_destroy(&un->un_sbuf_cv);
 624                 cv_destroy(&un->un_state_cv);
 625                 cv_destroy(&un->un_disk_busy_cv);
 626                 cv_destroy(&un->un_suspend_cv);
 627 
 628                 /*
 629                  * Deallocate command packet resources.
 630                  */
 631                 if (un->un_sbufp)
 632                         freerbuf(un->un_sbufp);
 633                 if (un->un_dp) {
 634                         kmem_free((caddr_t)un->un_dp, sizeof (*un->un_dp));
 635                 }
 636                 /*
 637                  * Unregister the devid and free devid resources allocated
 638                  */
 639                 ddi_devid_unregister(DCD_DEVINFO);
 640                 if (un->un_devid) {
 641                         ddi_devid_free(un->un_devid);
 642                         un->un_devid = NULL;
 643                 }
 644 
 645                 /*
 646                  * Delete kstats. Kstats for non CD devices are deleted
 647                  * in dcdclose.
 648                  */
 649                 if (un->un_stats) {
 650                         kstat_delete(un->un_stats);
 651                 }
 652 
 653         }
 654 
 655         /*
 656          * Cleanup scsi_device resources.
 657          */
 658         ddi_soft_state_free(dcd_state, instance);
 659         devp->dcd_private = (ataopaque_t)0;
 660         /* unprobe scsi device */
 661         dcd_unprobe(devp);
 662 
 663         /* Remove properties created during attach */
 664         ddi_prop_remove_all(devi);
 665 }
 666 
 667 static int
 668 dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd)
 669 {
 670         int instance;
 671         struct dcd_disk *un;
 672         clock_t wait_cmds_complete;
 673         instance = ddi_get_instance(devi);
 674 
 675         if (!(un = ddi_get_soft_state(dcd_state, instance)))
 676                 return (DDI_FAILURE);
 677 
 678         switch (cmd) {
 679         case DDI_DETACH:
 680                 return (dcd_dr_detach(devi));
 681 
 682         case DDI_SUSPEND:
 683                 mutex_enter(DCD_MUTEX);
 684                 if (un->un_state == DCD_STATE_SUSPENDED) {
 685                         mutex_exit(DCD_MUTEX);
 686                         return (DDI_SUCCESS);
 687                 }
 688                 un->un_throttle = 0;
 689                 /*
 690                  * Save the last state first
 691                  */
 692                 un->un_save_state = un->un_last_state;
 693 
 694                 New_state(un, DCD_STATE_SUSPENDED);
 695 
 696                 /*
 697                  * wait till current operation completed. If we are
 698                  * in the resource wait state (with an intr outstanding)
 699                  * then we need to wait till the intr completes and
 700                  * starts the next cmd. We wait for
 701                  * DCD_WAIT_CMDS_COMPLETE seconds before failing the
 702                  * DDI_SUSPEND.
 703                  */
 704                 wait_cmds_complete = ddi_get_lbolt();
 705                 wait_cmds_complete +=
 706                     drv_sectohz(DCD_WAIT_CMDS_COMPLETE);
 707 
 708                 while (un->un_ncmds) {
 709                         if (cv_timedwait(&un->un_disk_busy_cv,
 710                             DCD_MUTEX, wait_cmds_complete) == -1) {
 711                                 /*
 712                                  * commands Didn't finish in the
 713                                  * specified time, fail the DDI_SUSPEND.
 714                                  */
 715                                 DAD_DEBUG2(DCD_DEVINFO, dcd_label,
 716                                     DCD_DEBUG, "dcddetach: SUSPEND "
 717                                     "failed due to outstanding cmds\n");
 718                                 Restore_state(un);
 719                                 mutex_exit(DCD_MUTEX);
 720                                 return (DDI_FAILURE);
 721                         }
 722                 }
 723                 mutex_exit(DCD_MUTEX);
 724                 return (DDI_SUCCESS);
 725         }
 726         return (DDI_FAILURE);
 727 }
 728 
 729 /*
 730  * The reset entry point gets invoked at the system shutdown time or through
 731  * CPR code at system suspend.
 732  * Will be flushing the cache and expect this to be last I/O operation to the
 733  * disk before system reset/power off.
 734  */
 735 /*ARGSUSED*/
 736 static int
 737 dcdreset(dev_info_t *dip, ddi_reset_cmd_t cmd)
 738 {
 739         struct dcd_disk *un;
 740         int instance;
 741 
 742         instance = ddi_get_instance(dip);
 743 
 744         if (!(un = ddi_get_soft_state(dcd_state, instance)))
 745                 return (DDI_FAILURE);
 746 
 747         dcd_flush_cache(un);
 748 
 749         return (DDI_SUCCESS);
 750 }
 751 
 752 
 753 static int
 754 dcd_dr_detach(dev_info_t *devi)
 755 {
 756         struct dcd_device       *devp;
 757         struct dcd_disk         *un;
 758 
 759         /*
 760          * Get scsi_device structure for this instance.
 761          */
 762         if ((devp = ddi_get_driver_private(devi)) == NULL)
 763                 return (DDI_FAILURE);
 764 
 765         /*
 766          * Get dcd_disk structure containing target 'private' information
 767          */
 768         un = (struct dcd_disk *)devp->dcd_private;
 769 
 770         /*
 771          * Verify there are NO outstanding commands issued to this device.
 772          * ie, un_ncmds == 0.
 773          * It's possible to have outstanding commands through the physio
 774          * code path, even though everything's closed.
 775          */
 776 #ifndef lint
 777         _NOTE(COMPETING_THREADS_NOW);
 778 #endif
 779         mutex_enter(DCD_MUTEX);
 780         if (un->un_ncmds) {
 781                 mutex_exit(DCD_MUTEX);
 782                 _NOTE(NO_COMPETING_THREADS_NOW);
 783                 return (DDI_FAILURE);
 784         }
 785 
 786         mutex_exit(DCD_MUTEX);
 787 
 788         cmlb_detach(un->un_dklbhandle, 0);
 789         cmlb_free_handle(&un->un_dklbhandle);
 790 
 791 
 792         /*
 793          * Lower the power state of the device
 794          * i.e. the minimum power consumption state - sleep.
 795          */
 796         (void) pm_lower_power(DCD_DEVINFO, 0, DCD_DEVICE_STANDBY);
 797 
 798         _NOTE(NO_COMPETING_THREADS_NOW);
 799 
 800         /*
 801          * at this point there are no competing threads anymore
 802          * release active MT locks and all device resources.
 803          */
 804         dcd_free_softstate(un, devi);
 805 
 806         return (DDI_SUCCESS);
 807 }
 808 
 809 static int
 810 dcdpower(dev_info_t *devi, int component, int level)
 811 {
 812         struct dcd_pkt *pkt;
 813         struct dcd_disk *un;
 814         int     instance;
 815         uchar_t cmd;
 816 
 817 
 818         instance = ddi_get_instance(devi);
 819 
 820         if (!(un = ddi_get_soft_state(dcd_state, instance)) ||
 821             (DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) ||
 822             component != 0) {
 823                 return (DDI_FAILURE);
 824         }
 825 
 826         mutex_enter(DCD_MUTEX);
 827         /*
 828          * if there are active commands for the device or device will be
 829          * active soon. At the same time there is request to lower power
 830          * return failure.
 831          */
 832         if ((un->un_ncmds) && (level != DCD_DEVICE_ACTIVE)) {
 833                 mutex_exit(DCD_MUTEX);
 834                 return (DDI_FAILURE);
 835         }
 836 
 837         if ((un->un_state == DCD_STATE_OFFLINE) ||
 838             (un->un_state == DCD_STATE_FATAL)) {
 839                 mutex_exit(DCD_MUTEX);
 840                 return (DDI_FAILURE);
 841         }
 842 
 843         if (level == DCD_DEVICE_ACTIVE) {
 844                 /*
 845                  * No need to fire any command, just set the state structure
 846                  * to indicate previous state and set the level to active
 847                  */
 848                 un->un_power_level = DCD_DEVICE_ACTIVE;
 849                 if (un->un_state == DCD_STATE_PM_SUSPENDED)
 850                         Restore_state(un);
 851                 mutex_exit(DCD_MUTEX);
 852         } else {
 853                 pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL,
 854                     NULL, (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN,
 855                     PKT_CONSISTENT, NULL_FUNC, NULL);
 856 
 857                 if (pkt == (struct dcd_pkt *)NULL) {
 858                         mutex_exit(DCD_MUTEX);
 859                         return (DDI_FAILURE);
 860                 }
 861 
 862                 switch (level) {
 863                 case DCD_DEVICE_IDLE:
 864                         cmd = ATA_IDLE_IMMEDIATE;
 865                         break;
 866 
 867                 case DCD_DEVICE_STANDBY:
 868                         cmd = ATA_STANDBY_IMMEDIATE;
 869                         break;
 870                 }
 871 
 872                 makecommand(pkt, 0, cmd, 0, 0, 0, NO_DATA_XFER, 0);
 873                 mutex_exit(DCD_MUTEX);
 874                 /*
 875                  * Issue the appropriate command
 876                  */
 877                 if ((dcd_poll(pkt)) || (SCBP_C(pkt) != STATUS_GOOD)) {
 878                         dcd_destroy_pkt(pkt);
 879                         return (DDI_FAILURE);
 880                 }
 881                 dcd_destroy_pkt(pkt);
 882                 mutex_enter(DCD_MUTEX);
 883                 if (un->un_state != DCD_STATE_PM_SUSPENDED)
 884                         New_state(un, DCD_STATE_PM_SUSPENDED);
 885                 un->un_power_level = level;
 886                 mutex_exit(DCD_MUTEX);
 887         }
 888 
 889         return (DDI_SUCCESS);
 890 }
 891 
 892 static int
 893 dcd_doattach(dev_info_t *devi, int (*canwait)())
 894 {
 895         struct dcd_device *devp;
 896         struct dcd_disk *un = (struct dcd_disk *)0;
 897         int instance;
 898         int km_flags = (canwait != NULL_FUNC)? KM_SLEEP : KM_NOSLEEP;
 899         int rval;
 900         char *prop_template = "target%x-dcd-options";
 901         int options;
 902         char    prop_str[32];
 903         int target;
 904         diskaddr_t capacity;
 905 
 906         devp = ddi_get_driver_private(devi);
 907 
 908         /*
 909          * Call the routine scsi_probe to do some of the dirty work.
 910          * If the INQUIRY command succeeds, the field dcd_inq in the
 911          * device structure will be filled in. The dcd_sense structure
 912          * will also be allocated.
 913          */
 914 
 915         switch (dcd_probe(devp, canwait)) {
 916         default:
 917                 return (DDI_FAILURE);
 918 
 919         case DCDPROBE_EXISTS:
 920                 if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
 921                         if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
 922                                 rval = DDI_SUCCESS;
 923                         } else {
 924                                 rval = DDI_FAILURE;
 925                                 goto error;
 926                         }
 927                 } else {
 928                         rval = DDI_FAILURE;
 929                         goto error;
 930                 }
 931         }
 932 
 933 
 934         instance = ddi_get_instance(devp->dcd_dev);
 935 
 936         if (ddi_soft_state_zalloc(dcd_state, instance) != DDI_SUCCESS) {
 937                 rval = DDI_FAILURE;
 938                 goto error;
 939         }
 940 
 941         un = ddi_get_soft_state(dcd_state, instance);
 942 
 943         un->un_sbufp = getrbuf(km_flags);
 944         if (un->un_sbufp == (struct buf *)NULL) {
 945                 rval = DDI_FAILURE;
 946                 goto error;
 947         }
 948 
 949 
 950         un->un_dcd = devp;
 951         un->un_power_level = -1;
 952         un->un_tgattribute.media_is_writable = 1;
 953 
 954         sema_init(&un->un_semoclose, 1, NULL, SEMA_DRIVER, NULL);
 955         cv_init(&un->un_sbuf_cv, NULL, CV_DRIVER, NULL);
 956         cv_init(&un->un_state_cv, NULL, CV_DRIVER, NULL);
 957         /* Initialize power management conditional variable */
 958         cv_init(&un->un_disk_busy_cv, NULL, CV_DRIVER, NULL);
 959         cv_init(&un->un_suspend_cv, NULL, CV_DRIVER, NULL);
 960 
 961         if (un->un_dp == 0) {
 962                 /*
 963                  * Assume CCS drive, assume parity, but call
 964                  * it a CDROM if it is a RODIRECT device.
 965                  */
 966                 un->un_dp = (struct dcd_drivetype *)
 967                     kmem_zalloc(sizeof (struct dcd_drivetype), km_flags);
 968                 if (!un->un_dp) {
 969                         rval = DDI_FAILURE;
 970                         goto error;
 971                 }
 972                 if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
 973                         if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
 974                                 un->un_dp->ctype = CTYPE_DISK;
 975                         }
 976                 } else  {
 977                         rval = DDI_FAILURE;
 978                         goto error;
 979                 }
 980                 un->un_dp->name = "CCS";
 981                 un->un_dp->options = 0;
 982         }
 983 
 984         /*
 985          * Allow I/O requests at un_secsize offset in multiple of un_secsize.
 986          */
 987         un->un_secsize = DEV_BSIZE;
 988 
 989         /*
 990          * If the device is not a removable media device, make sure that
 991          * that the device is ready, by issuing the another identify but
 992          * not needed. Get the capacity from identify data and store here.
 993          */
 994         if (dcd_compute_dk_capacity(devp, &capacity) == 0) {
 995                 un->un_diskcapacity = capacity;
 996                 un->un_lbasize = DEV_BSIZE;
 997         }
 998 
 999         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "Geometry Data\n");
1000         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "cyls %x, heads %x",
1001             devp->dcd_ident->dcd_fixcyls,
1002             devp->dcd_ident->dcd_heads);
1003         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "sectors %x,",
1004             devp->dcd_ident->dcd_sectors);
1005         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "capacity %llx\n",
1006             capacity);
1007 
1008         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1009             "dcdprobe: drive selected\n");
1010 
1011         /*
1012          * Check for the property target<n>-dcd-options to find the option
1013          * set by the HBA driver for this target so that we can set the
1014          * Unit structure variable so that we can send commands accordingly.
1015          */
1016         target = devp->dcd_address->da_target;
1017         (void) sprintf(prop_str, prop_template, target);
1018         options = ddi_prop_get_int(DDI_DEV_T_ANY, devi, DDI_PROP_NOTPROM,
1019             prop_str, -1);
1020         if (options < 0) {
1021                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1022                     "No per target properties");
1023         } else {
1024                 if ((options & DCD_DMA_MODE) == DCD_DMA_MODE) {
1025                         un->un_dp->options |= DMA_SUPPORTTED;
1026                         un->un_dp->dma_mode = (options >> 3) & 0x03;
1027                         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1028                             "mode %x\n", un->un_dp->dma_mode);
1029                 } else {
1030                         un->un_dp->options &= ~DMA_SUPPORTTED;
1031                         un->un_dp->pio_mode = options & 0x7;
1032                         if (options & DCD_BLOCK_MODE)
1033                                 un->un_dp->options |= BLOCK_MODE;
1034                         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1035                             "mode %x\n", un->un_dp->pio_mode);
1036                 }
1037                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1038                     "options %x,", un->un_dp->options);
1039         }
1040 
1041         un->un_throttle = 2;
1042         /*
1043          * set default max_xfer_size - This should depend on whether the
1044          * Block mode is supported by the device or not.
1045          */
1046         un->un_max_xfer_size = MAX_ATA_XFER_SIZE;
1047 
1048         /*
1049          * Set write cache enable softstate
1050          *
1051          * WCE is only supported in ATAPI-4 or higher; for
1052          * lower rev devices, must assume write cache is
1053          * enabled.
1054          */
1055         mutex_enter(DCD_MUTEX);
1056         un->un_write_cache_enabled = (devp->dcd_ident->dcd_majvers == 0xffff) ||
1057             ((devp->dcd_ident->dcd_majvers & IDENTIFY_80_ATAPI_4) == 0) ||
1058             (devp->dcd_ident->dcd_features85 & IDENTIFY_85_WCE) != 0;
1059         mutex_exit(DCD_MUTEX);
1060 
1061         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1062             "dcd_doattach returns good\n");
1063 
1064         return (rval);
1065 
1066 error:
1067         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcd_doattach failed\n");
1068         dcd_free_softstate(un, devi);
1069         return (rval);
1070 }
1071 
1072 #ifdef NOTNEEDED
1073 /*
1074  * This routine is used to set the block mode of operation by issuing the
1075  * Set Block mode ata command with the maximum block mode possible
1076  */
1077 dcd_set_multiple(struct dcd_disk *un)
1078 {
1079         int status;
1080         struct udcd_cmd ucmd;
1081         struct dcd_cmd cdb;
1082         dev_t   dev;
1083 
1084 
1085         /* Zero all the required structure */
1086         (void) bzero((caddr_t)&ucmd, sizeof (ucmd));
1087 
1088         (void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd));
1089 
1090         cdb.cmd = ATA_SET_MULTIPLE;
1091         /*
1092          * Here we should pass what needs to go into sector count REGISTER.
1093          * Eventhough this field indicates the number of bytes to read we
1094          * need to specify the block factor in terms of bytes so that it
1095          * will be programmed by the HBA driver into the sector count register.
1096          */
1097         cdb.size = un->un_lbasize * un->un_dp->block_factor;
1098 
1099         cdb.sector_num.lba_num = 0;
1100         cdb.address_mode = ADD_LBA_MODE;
1101         cdb.direction = NO_DATA_XFER;
1102 
1103         ucmd.udcd_flags = 0;
1104         ucmd.udcd_cmd = &cdb;
1105         ucmd.udcd_bufaddr = NULL;
1106         ucmd.udcd_buflen = 0;
1107         ucmd.udcd_flags |= UDCD_SILENT;
1108 
1109         dev = makedevice(ddi_driver_major(DCD_DEVINFO),
1110             ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT);
1111 
1112 
1113         status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE);
1114 
1115         return (status);
1116 }
1117 /*
1118  * The following routine is used only for setting the transfer mode
1119  * and it is not designed for transferring any other features subcommand.
1120  */
1121 dcd_set_features(struct dcd_disk *un, uchar_t mode)
1122 {
1123         int status;
1124         struct udcd_cmd ucmd;
1125         struct dcd_cmd cdb;
1126         dev_t   dev;
1127 
1128 
1129         /* Zero all the required structure */
1130         (void) bzero((caddr_t)&ucmd, sizeof (ucmd));
1131 
1132         (void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd));
1133 
1134         cdb.cmd = ATA_SET_FEATURES;
1135         /*
1136          * Here we need to pass what needs to go into the sector count register
1137          * But in the case of SET FEATURES command the value taken in the
1138          * sector count register depends what type of subcommand is
1139          * passed in the features register. Since we have defined the size to
1140          * be the size in bytes in this context it does not indicate bytes
1141          * instead it indicates the mode to be programmed.
1142          */
1143         cdb.size = un->un_lbasize * mode;
1144 
1145         cdb.sector_num.lba_num = 0;
1146         cdb.address_mode = ADD_LBA_MODE;
1147         cdb.direction = NO_DATA_XFER;
1148         cdb.features = ATA_FEATURE_SET_MODE;
1149         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1150             "size %x, features %x, cmd %x\n",
1151             cdb.size, cdb.features, cdb.cmd);
1152 
1153         ucmd.udcd_flags = 0;
1154         ucmd.udcd_cmd = &cdb;
1155         ucmd.udcd_bufaddr = NULL;
1156         ucmd.udcd_buflen = 0;
1157         ucmd.udcd_flags |= UDCD_SILENT;
1158 
1159         dev = makedevice(ddi_driver_major(DCD_DEVINFO),
1160             ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT);
1161 
1162         status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE);
1163 
1164         return (status);
1165 }
1166 #endif
1167 
1168 /*
1169  * Validate the geometry for this disk, e.g.,
1170  * see whether it has a valid label.
1171  */
1172 static int
1173 dcd_validate_geometry(struct dcd_disk *un)
1174 {
1175         int secsize = 0;
1176         struct  dcd_device *devp;
1177         int secdiv;
1178         int rval;
1179 
1180         ASSERT(mutex_owned(DCD_MUTEX));
1181         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1182             "dcd_validate_geometry: started \n");
1183 
1184         if (un->un_lbasize < 0) {
1185                 return (DCD_BAD_LABEL);
1186         }
1187 
1188         if (un->un_state == DCD_STATE_PM_SUSPENDED) {
1189                 mutex_exit(DCD_MUTEX);
1190                 if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) !=
1191                     DDI_SUCCESS) {
1192                         mutex_enter(DCD_MUTEX);
1193                         return (DCD_BAD_LABEL);
1194                 }
1195                 mutex_enter(DCD_MUTEX);
1196         }
1197 
1198         secsize = un->un_secsize;
1199 
1200         /*
1201          * take a log base 2 of sector size (sorry)
1202          */
1203         for (secdiv = 0; secsize = secsize >> 1; secdiv++)
1204                 ;
1205         un->un_secdiv = secdiv;
1206 
1207         /*
1208          * Only DIRECT ACCESS devices will have Sun labels.
1209          * CD's supposedly have a Sun label, too
1210          */
1211 
1212         devp = un->un_dcd;
1213 
1214         if (((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) &&
1215             (devp->dcd_ident->dcd_config & ATANON_REMOVABLE)) {
1216                 mutex_exit(DCD_MUTEX);
1217                 rval = cmlb_validate(un->un_dklbhandle, 0, 0);
1218                 mutex_enter(DCD_MUTEX);
1219                 if (rval == ENOMEM)
1220                         return (DCD_NO_MEM_FOR_LABEL);
1221                 else if (rval != 0)
1222                         return (DCD_BAD_LABEL);
1223         } else {
1224                 /* it should never get here. */
1225                 return (DCD_BAD_LABEL);
1226         }
1227 
1228         /*
1229          * take a log base 2 of logical block size
1230          */
1231         secsize = un->un_lbasize;
1232         for (secdiv = 0; secsize = secsize >> 1; secdiv++)
1233                 ;
1234         un->un_lbadiv = secdiv;
1235 
1236         /*
1237          * take a log base 2 of the multiple of DEV_BSIZE blocks that
1238          * make up one logical block
1239          */
1240         secsize = un->un_lbasize >> DEV_BSHIFT;
1241         for (secdiv = 0; secsize = secsize >> 1; secdiv++)
1242                 ;
1243         un->un_blknoshift = secdiv;
1244         return (0);
1245 }
1246 
1247 /*
1248  * Unix Entry Points
1249  */
1250 
1251 /* ARGSUSED3 */
1252 static int
1253 dcdopen(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
1254 {
1255         dev_t dev = *dev_p;
1256         int rval = EIO;
1257         int partmask;
1258         int nodelay = (flag & (FNDELAY | FNONBLOCK));
1259         int i;
1260         char kstatname[KSTAT_STRLEN];
1261         diskaddr_t lblocks;
1262         char *partname;
1263 
1264         GET_SOFT_STATE(dev);
1265 
1266         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1267             "Inside Open flag %x, otyp %x\n", flag, otyp);
1268 
1269         if (otyp >= OTYPCNT) {
1270                 return (EINVAL);
1271         }
1272 
1273         partmask = 1 << part;
1274 
1275         /*
1276          * We use a semaphore here in order to serialize
1277          * open and close requests on the device.
1278          */
1279         sema_p(&un->un_semoclose);
1280 
1281         mutex_enter(DCD_MUTEX);
1282 
1283         if ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL) {
1284                 rval = ENXIO;
1285                 goto done;
1286         }
1287 
1288         while (un->un_state == DCD_STATE_SUSPENDED) {
1289                 cv_wait(&un->un_suspend_cv, DCD_MUTEX);
1290         }
1291 
1292         if ((un->un_state == DCD_STATE_PM_SUSPENDED) && (!nodelay)) {
1293                 mutex_exit(DCD_MUTEX);
1294                 if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE)
1295                     != DDI_SUCCESS) {
1296                         mutex_enter(DCD_MUTEX);
1297                         rval = EIO;
1298                         goto done;
1299                 }
1300                 mutex_enter(DCD_MUTEX);
1301         }
1302 
1303         /*
1304          * set make_dcd_cmd() flags and stat_size here since these
1305          * are unlikely to change
1306          */
1307         un->un_cmd_flags = 0;
1308 
1309         un->un_cmd_stat_size = 2;
1310 
1311         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdopen un=0x%p\n",
1312             (void *)un);
1313         /*
1314          * check for previous exclusive open
1315          */
1316         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1317             "exclopen=%x, flag=%x, regopen=%x\n",
1318             un->un_exclopen, flag, un->un_ocmap.regopen[otyp]);
1319         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1320             "Exclusive open flag %x, partmask %x\n",
1321             un->un_exclopen, partmask);
1322 
1323         if (un->un_exclopen & (partmask)) {
1324 failed_exclusive:
1325                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1326                     "exclusive open fails\n");
1327                 rval = EBUSY;
1328                 goto done;
1329         }
1330 
1331         if (flag & FEXCL) {
1332                 int i;
1333                 if (un->un_ocmap.lyropen[part]) {
1334                         goto failed_exclusive;
1335                 }
1336                 for (i = 0; i < (OTYPCNT - 1); i++) {
1337                         if (un->un_ocmap.regopen[i] & (partmask)) {
1338                                 goto failed_exclusive;
1339                         }
1340                 }
1341         }
1342         if (flag & FWRITE) {
1343                 mutex_exit(DCD_MUTEX);
1344                 if (dcd_check_wp(dev)) {
1345                         sema_v(&un->un_semoclose);
1346                         return (EROFS);
1347                 }
1348                 mutex_enter(DCD_MUTEX);
1349         }
1350 
1351         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1352             "Check Write Protect handled\n");
1353 
1354         if (!nodelay) {
1355                 mutex_exit(DCD_MUTEX);
1356                 if ((rval = dcd_ready_and_valid(dev, un)) != 0) {
1357                         rval = EIO;
1358                 }
1359                 (void) pm_idle_component(DCD_DEVINFO, 0);
1360                 /*
1361                  * Fail if device is not ready or if the number of disk
1362                  * blocks is zero or negative for non CD devices.
1363                  */
1364                 if (rval || cmlb_partinfo(un->un_dklbhandle,
1365                     part, &lblocks, NULL, &partname, NULL, 0) ||
1366                     lblocks <= 0) {
1367                         rval = EIO;
1368                         mutex_enter(DCD_MUTEX);
1369                         goto done;
1370                 }
1371                 mutex_enter(DCD_MUTEX);
1372         }
1373 
1374         if (otyp == OTYP_LYR) {
1375                 un->un_ocmap.lyropen[part]++;
1376         } else {
1377                 un->un_ocmap.regopen[otyp] |= partmask;
1378         }
1379 
1380         /*
1381          * set up open and exclusive open flags
1382          */
1383         if (flag & FEXCL) {
1384                 un->un_exclopen |= (partmask);
1385         }
1386 
1387 
1388         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1389             "open of part %d type %d\n",
1390             part, otyp);
1391 
1392         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1393             "Kstats getting updated\n");
1394         /*
1395          * only create kstats for disks, CD kstats created in dcdattach
1396          */
1397         _NOTE(NO_COMPETING_THREADS_NOW);
1398         mutex_exit(DCD_MUTEX);
1399         if (un->un_stats == (kstat_t *)0) {
1400                 un->un_stats = kstat_create("dad", instance,
1401                     NULL, "disk", KSTAT_TYPE_IO, 1,
1402                     KSTAT_FLAG_PERSISTENT);
1403                 if (un->un_stats) {
1404                         un->un_stats->ks_lock = DCD_MUTEX;
1405                         kstat_install(un->un_stats);
1406                 }
1407 
1408                 /*
1409                  * set up partition statistics for each partition
1410                  * with number of blocks > 0
1411                  */
1412                 if (!nodelay) {
1413                         for (i = 0; i < NDKMAP; i++) {
1414                                 if ((un->un_pstats[i] == (kstat_t *)0) &&
1415                                     (cmlb_partinfo(un->un_dklbhandle,
1416                                     i, &lblocks, NULL, &partname,
1417                                     NULL, 0) == 0) && lblocks > 0) {
1418                                         (void) sprintf(kstatname, "dad%d,%s",
1419                                             instance, partname);
1420                                         un->un_pstats[i] = kstat_create("dad",
1421                                             instance,
1422                                             kstatname,
1423                                             "partition",
1424                                             KSTAT_TYPE_IO,
1425                                             1,
1426                                             KSTAT_FLAG_PERSISTENT);
1427                                         if (un->un_pstats[i]) {
1428                                                 un->un_pstats[i]->ks_lock =
1429                                                     DCD_MUTEX;
1430                                                 kstat_install(un->un_pstats[i]);
1431                                         }
1432                                 }
1433                         }
1434                 }
1435                 /*
1436                  * set up error kstats
1437                  */
1438                 (void) dcd_create_errstats(un, instance);
1439         }
1440 #ifndef lint
1441         _NOTE(COMPETING_THREADS_NOW);
1442 #endif
1443 
1444         sema_v(&un->un_semoclose);
1445         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "Open success\n");
1446         return (0);
1447 
1448 done:
1449         mutex_exit(DCD_MUTEX);
1450         sema_v(&un->un_semoclose);
1451         return (rval);
1452 
1453 }
1454 
1455 /*
1456  * Test if disk is ready and has a valid geometry.
1457  */
1458 static int
1459 dcd_ready_and_valid(dev_t dev, struct dcd_disk *un)
1460 {
1461         int rval = 1;
1462         int g_error = 0;
1463 
1464         mutex_enter(DCD_MUTEX);
1465         /*
1466          * cmds outstanding
1467          */
1468         if (un->un_ncmds == 0) {
1469                 (void) dcd_unit_ready(dev);
1470         }
1471 
1472         /*
1473          * If device is not yet ready here, inform it is offline
1474          */
1475         if (un->un_state == DCD_STATE_NORMAL) {
1476                 rval = dcd_unit_ready(dev);
1477                 if (rval != 0 && rval != EACCES) {
1478                         dcd_offline(un, 1);
1479                         goto done;
1480                 }
1481         }
1482 
1483         if (un->un_format_in_progress == 0) {
1484                 g_error = dcd_validate_geometry(un);
1485         }
1486 
1487         /*
1488          * check if geometry was valid. We don't check the validity of
1489          * geometry for CDROMS.
1490          */
1491 
1492         if (g_error == DCD_BAD_LABEL) {
1493                 rval = 1;
1494                 goto done;
1495         }
1496 
1497 
1498         /*
1499          * the state has changed; inform the media watch routines
1500          */
1501         un->un_mediastate = DKIO_INSERTED;
1502         cv_broadcast(&un->un_state_cv);
1503         rval = 0;
1504 
1505 done:
1506         mutex_exit(DCD_MUTEX);
1507         return (rval);
1508 }
1509 
1510 
1511 /*ARGSUSED*/
1512 static int
1513 dcdclose(dev_t dev, int flag, int otyp, cred_t *cred_p)
1514 {
1515         uchar_t *cp;
1516         int i;
1517 
1518         GET_SOFT_STATE(dev);
1519 
1520 
1521         if (otyp >= OTYPCNT)
1522                 return (ENXIO);
1523 
1524         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1525             "close of part %d type %d\n",
1526             part, otyp);
1527         sema_p(&un->un_semoclose);
1528 
1529         mutex_enter(DCD_MUTEX);
1530 
1531         if (un->un_exclopen & (1<<part)) {
1532                 un->un_exclopen &= ~(1<<part);
1533         }
1534 
1535         if (otyp == OTYP_LYR) {
1536                 un->un_ocmap.lyropen[part] -= 1;
1537         } else {
1538                 un->un_ocmap.regopen[otyp] &= ~(1<<part);
1539         }
1540 
1541         cp = &un->un_ocmap.chkd[0];
1542         while (cp < &un->un_ocmap.chkd[OCSIZE]) {
1543                 if (*cp != (uchar_t)0) {
1544                         break;
1545                 }
1546                 cp++;
1547         }
1548 
1549         if (cp == &un->un_ocmap.chkd[OCSIZE]) {
1550                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "last close\n");
1551                 if (un->un_state == DCD_STATE_OFFLINE) {
1552                         dcd_offline(un, 1);
1553                 }
1554 
1555                 mutex_exit(DCD_MUTEX);
1556                 (void) cmlb_close(un->un_dklbhandle, 0);
1557 
1558                 _NOTE(NO_COMPETING_THREADS_NOW);
1559                 if (un->un_stats) {
1560                         kstat_delete(un->un_stats);
1561                         un->un_stats = 0;
1562                 }
1563                 for (i = 0; i < NDKMAP; i++) {
1564                         if (un->un_pstats[i]) {
1565                                 kstat_delete(un->un_pstats[i]);
1566                                 un->un_pstats[i] = (kstat_t *)0;
1567                         }
1568                 }
1569 
1570                 if (un->un_errstats) {
1571                         kstat_delete(un->un_errstats);
1572                         un->un_errstats = (kstat_t *)0;
1573                 }
1574                 mutex_enter(DCD_MUTEX);
1575 
1576 #ifndef lint
1577                 _NOTE(COMPETING_THREADS_NOW);
1578 #endif
1579         }
1580 
1581         mutex_exit(DCD_MUTEX);
1582         sema_v(&un->un_semoclose);
1583         return (0);
1584 }
1585 
1586 static void
1587 dcd_offline(struct dcd_disk *un, int bechatty)
1588 {
1589         if (bechatty)
1590                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "offline\n");
1591 
1592         mutex_exit(DCD_MUTEX);
1593         cmlb_invalidate(un->un_dklbhandle, 0);
1594         mutex_enter(DCD_MUTEX);
1595 }
1596 
1597 /*
1598  * Given the device number return the devinfo pointer
1599  * from the scsi_device structure.
1600  */
1601 /*ARGSUSED*/
1602 static int
1603 dcdinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
1604 {
1605         dev_t dev;
1606         struct dcd_disk *un;
1607         int instance, error;
1608 
1609 
1610         switch (infocmd) {
1611         case DDI_INFO_DEVT2DEVINFO:
1612                 dev = (dev_t)arg;
1613                 instance = DCDUNIT(dev);
1614                 if ((un = ddi_get_soft_state(dcd_state, instance)) == NULL)
1615                         return (DDI_FAILURE);
1616                 *result = (void *) DCD_DEVINFO;
1617                 error = DDI_SUCCESS;
1618                 break;
1619         case DDI_INFO_DEVT2INSTANCE:
1620                 dev = (dev_t)arg;
1621                 instance = DCDUNIT(dev);
1622                 *result = (void *)(uintptr_t)instance;
1623                 error = DDI_SUCCESS;
1624                 break;
1625         default:
1626                 error = DDI_FAILURE;
1627         }
1628         return (error);
1629 }
1630 
1631 /*
1632  * property operation routine.  return the number of blocks for the partition
1633  * in question or forward the request to the propery facilities.
1634  */
1635 static int
1636 dcd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1637     char *name, caddr_t valuep, int *lengthp)
1638 {
1639         struct dcd_disk *un;
1640 
1641         if ((un = ddi_get_soft_state(dcd_state, ddi_get_instance(dip))) == NULL)
1642                 return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1643                     name, valuep, lengthp));
1644 
1645         return (cmlb_prop_op(un->un_dklbhandle,
1646             dev, dip, prop_op, mod_flags, name, valuep, lengthp,
1647             DCDPART(dev), NULL));
1648 }
1649 
1650 /*
1651  * These routines perform raw i/o operations.
1652  */
1653 /*ARGSUSED*/
1654 void
1655 dcduscsimin(struct buf *bp)
1656 {
1657 
1658 }
1659 
1660 
1661 static void
1662 dcdmin(struct buf *bp)
1663 {
1664         struct dcd_disk *un;
1665         int instance;
1666         minor_t minor = getminor(bp->b_edev);
1667         instance = minor >> DCDUNIT_SHIFT;
1668         un = ddi_get_soft_state(dcd_state, instance);
1669 
1670         if (bp->b_bcount > un->un_max_xfer_size)
1671                 bp->b_bcount = un->un_max_xfer_size;
1672 }
1673 
1674 
1675 /* ARGSUSED2 */
1676 static int
1677 dcdread(dev_t dev, struct uio *uio, cred_t *cred_p)
1678 {
1679         int secmask;
1680         GET_SOFT_STATE(dev);
1681 #ifdef lint
1682         part = part;
1683 #endif /* lint */
1684         secmask = un->un_secsize - 1;
1685 
1686         if (uio->uio_loffset & ((offset_t)(secmask))) {
1687                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1688                     "file offset not modulo %d\n",
1689                     un->un_secsize);
1690                 return (EINVAL);
1691         } else if (uio->uio_iov->iov_len & (secmask)) {
1692                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1693                     "transfer length not modulo %d\n", un->un_secsize);
1694                 return (EINVAL);
1695         }
1696         return (physio(dcdstrategy, (struct buf *)0, dev, B_READ, dcdmin, uio));
1697 }
1698 
1699 /* ARGSUSED2 */
1700 static int
1701 dcdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p)
1702 {
1703         int secmask;
1704         struct uio *uio = aio->aio_uio;
1705         GET_SOFT_STATE(dev);
1706 #ifdef lint
1707         part = part;
1708 #endif /* lint */
1709         secmask = un->un_secsize - 1;
1710 
1711         if (uio->uio_loffset & ((offset_t)(secmask))) {
1712                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1713                     "file offset not modulo %d\n",
1714                     un->un_secsize);
1715                 return (EINVAL);
1716         } else if (uio->uio_iov->iov_len & (secmask)) {
1717                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1718                     "transfer length not modulo %d\n", un->un_secsize);
1719                 return (EINVAL);
1720         }
1721         return (aphysio(dcdstrategy, anocancel, dev, B_READ, dcdmin, aio));
1722 }
1723 
1724 /* ARGSUSED2 */
1725 static int
1726 dcdwrite(dev_t dev, struct uio *uio, cred_t *cred_p)
1727 {
1728         int secmask;
1729         GET_SOFT_STATE(dev);
1730 #ifdef lint
1731         part = part;
1732 #endif /* lint */
1733         secmask = un->un_secsize - 1;
1734 
1735         if (uio->uio_loffset & ((offset_t)(secmask))) {
1736                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1737                     "file offset not modulo %d\n",
1738                     un->un_secsize);
1739                 return (EINVAL);
1740         } else if (uio->uio_iov->iov_len & (secmask)) {
1741                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1742                     "transfer length not modulo %d\n", un->un_secsize);
1743                 return (EINVAL);
1744         }
1745         return (physio(dcdstrategy, (struct buf *)0, dev, B_WRITE, dcdmin,
1746             uio));
1747 }
1748 
1749 /* ARGSUSED2 */
1750 static int
1751 dcdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p)
1752 {
1753         int secmask;
1754         struct uio *uio = aio->aio_uio;
1755         GET_SOFT_STATE(dev);
1756 #ifdef lint
1757         part = part;
1758 #endif /* lint */
1759         secmask = un->un_secsize - 1;
1760 
1761         if (uio->uio_loffset & ((offset_t)(secmask))) {
1762                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1763                     "file offset not modulo %d\n",
1764                     un->un_secsize);
1765                 return (EINVAL);
1766         } else if (uio->uio_iov->iov_len & (secmask)) {
1767                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1768                     "transfer length not modulo %d\n", un->un_secsize);
1769                 return (EINVAL);
1770         }
1771         return (aphysio(dcdstrategy, anocancel, dev, B_WRITE, dcdmin, aio));
1772 }
1773 
1774 /*
1775  * strategy routine
1776  */
1777 static int
1778 dcdstrategy(struct buf *bp)
1779 {
1780         struct dcd_disk *un;
1781         struct diskhd *dp;
1782         int i;
1783         minor_t minor = getminor(bp->b_edev);
1784         diskaddr_t p_lblksrt;
1785         diskaddr_t lblocks;
1786         diskaddr_t bn;
1787 
1788         if ((un = ddi_get_soft_state(dcd_state,
1789             minor >> DCDUNIT_SHIFT)) == NULL ||
1790             un->un_state == DCD_STATE_DUMPING ||
1791             ((un->un_state  & DCD_STATE_FATAL) == DCD_STATE_FATAL)) {
1792                 SET_BP_ERROR(bp, ((un) ? ENXIO : EIO));
1793 error:
1794                 bp->b_resid = bp->b_bcount;
1795                 biodone(bp);
1796                 return (0);
1797         }
1798 
1799         /*
1800          * If the request size (buf->b_bcount)is greater than the size
1801          * (un->un_max_xfer_size) supported by the target driver fail
1802          * the request with EINVAL error code.
1803          *
1804          * We are not supposed to receive requests exceeding
1805          * un->un_max_xfer_size size because the caller is expected to
1806          * check what is the maximum size that is supported by this
1807          * driver either through ioctl or dcdmin routine(which is private
1808          * to this driver).
1809          * But we have seen cases (like meta driver(md))where dcdstrategy
1810          * called with more than supported size and cause data corruption.
1811          */
1812 
1813         if (bp->b_bcount > un->un_max_xfer_size) {
1814                 SET_BP_ERROR(bp, EINVAL);
1815                 goto error;
1816         }
1817 
1818         TRACE_2(TR_FAC_DADA, TR_DCDSTRATEGY_START,
1819             "dcdstrategy_start: bp 0x%p un 0x%p", bp, un);
1820 
1821         /*
1822          * Commands may sneak in while we released the mutex in
1823          * DDI_SUSPEND, we should block new commands.
1824          */
1825         mutex_enter(DCD_MUTEX);
1826         while (un->un_state == DCD_STATE_SUSPENDED) {
1827                 cv_wait(&un->un_suspend_cv, DCD_MUTEX);
1828         }
1829 
1830         if (un->un_state == DCD_STATE_PM_SUSPENDED) {
1831                 mutex_exit(DCD_MUTEX);
1832                 (void) pm_idle_component(DCD_DEVINFO, 0);
1833                 if (pm_raise_power(DCD_DEVINFO, 0,
1834                     DCD_DEVICE_ACTIVE) !=  DDI_SUCCESS) {
1835                         SET_BP_ERROR(bp, EIO);
1836                         goto error;
1837                 }
1838                 mutex_enter(DCD_MUTEX);
1839         }
1840         mutex_exit(DCD_MUTEX);
1841 
1842         /*
1843          * Map-in the buffer in case starting address is not word aligned.
1844          */
1845 
1846         if (((uintptr_t)bp->b_un.b_addr) & 0x1)
1847                 bp_mapin(bp);
1848 
1849         bp->b_flags &= ~(B_DONE|B_ERROR);
1850         bp->b_resid = 0;
1851         bp->av_forw = 0;
1852 
1853         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1854             "bp->b_bcount %lx\n", bp->b_bcount);
1855 
1856         if (bp != un->un_sbufp) {
1857 validated:      if (cmlb_partinfo(un->un_dklbhandle,
1858                     minor & DCDPART_MASK,
1859                     &lblocks,
1860                     &p_lblksrt,
1861                     NULL,
1862                     NULL,
1863                     0) == 0) {
1864 
1865                         bn = dkblock(bp);
1866 
1867                         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1868                             "dkblock(bp) is %llu\n", bn);
1869 
1870                         i = 0;
1871                         if (bn < 0) {
1872                                 i = -1;
1873                         } else if (bn >= lblocks) {
1874                                 /*
1875                                  * For proper comparison, file system block
1876                                  * number has to be scaled to actual CD
1877                                  * transfer size.
1878                                  * Since all the CDROM operations
1879                                  * that have Sun Labels are in the correct
1880                                  * block size this will work for CD's.  This
1881                                  * will have to change when we have different
1882                                  * sector sizes.
1883                                  *
1884                                  * if bn == lblocks,
1885                                  * Not an error, resid == count
1886                                  */
1887                                 if (bn > lblocks) {
1888                                         i = -1;
1889                                 } else {
1890                                         i = 1;
1891                                 }
1892                         } else if (bp->b_bcount & (un->un_secsize-1)) {
1893                                 /*
1894                                  * This should really be:
1895                                  *
1896                                  * ... if (bp->b_bcount & (un->un_lbasize-1))
1897                                  *
1898                                  */
1899                                 i = -1;
1900                         } else {
1901                                 if (!bp->b_bcount) {
1902                                         printf("Waring : Zero read or Write\n");
1903                                         goto error;
1904                                 }
1905                                 /*
1906                                  * sort by absolute block number.
1907                                  */
1908                                 bp->b_resid = bn;
1909                                 bp->b_resid += p_lblksrt;
1910                                 /*
1911                                  * zero out av_back - this will be a signal
1912                                  * to dcdstart to go and fetch the resources
1913                                  */
1914                                 bp->av_back = NO_PKT_ALLOCATED;
1915                         }
1916 
1917                         /*
1918                          * Check to see whether or not we are done
1919                          * (with or without errors).
1920                          */
1921 
1922                         if (i != 0) {
1923                                 if (i < 0) {
1924                                         bp->b_flags |= B_ERROR;
1925                                 }
1926                                 goto error;
1927                         }
1928                 } else {
1929                         /*
1930                          * opened in NDELAY/NONBLOCK mode?
1931                          * Check if disk is ready and has a valid geometry
1932                          */
1933                         if (dcd_ready_and_valid(bp->b_edev, un) == 0) {
1934                                 goto validated;
1935                         } else {
1936                                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
1937                                     "i/o to invalid geometry\n");
1938                                 SET_BP_ERROR(bp, EIO);
1939                                 goto error;
1940                         }
1941                 }
1942         } else if (BP_HAS_NO_PKT(bp)) {
1943                 struct udcd_cmd *tscmdp;
1944                 struct dcd_cmd *tcmdp;
1945                 /*
1946                  * This indicates that it is a special buffer
1947                  * This could be a udcd-cmd and hence call bp_mapin just
1948                  * in case that it could be a PIO command issued.
1949                  */
1950                 tscmdp = (struct udcd_cmd *)bp->b_forw;
1951                 tcmdp = tscmdp->udcd_cmd;
1952                 if ((tcmdp->cmd != ATA_READ_DMA) && (tcmdp->cmd != 0xc9) &&
1953                     (tcmdp->cmd != ATA_WRITE_DMA) && (tcmdp->cmd != 0xcb) &&
1954                     (tcmdp->cmd != IDENTIFY_DMA) &&
1955                     (tcmdp->cmd != ATA_FLUSH_CACHE)) {
1956                         bp_mapin(bp);
1957                 }
1958         }
1959 
1960         /*
1961          * We are doing it a bit non-standard. That is, the
1962          * head of the b_actf chain is *not* the active command-
1963          * it is just the head of the wait queue. The reason
1964          * we do this is that the head of the b_actf chain is
1965          * guaranteed to not be moved by disksort(), so that
1966          * our restart command (pointed to by
1967          * b_forw) and the head of the wait queue (b_actf) can
1968          * have resources granted without it getting lost in
1969          * the queue at some later point (where we would have
1970          * to go and look for it).
1971          */
1972         mutex_enter(DCD_MUTEX);
1973 
1974         DCD_DO_KSTATS(un, kstat_waitq_enter, bp);
1975 
1976         dp = &un->un_utab;
1977 
1978         if (dp->b_actf == NULL) {
1979                 dp->b_actf = bp;
1980                 dp->b_actl = bp;
1981         } else if ((un->un_state == DCD_STATE_SUSPENDED) &&
1982             bp == un->un_sbufp) {
1983                 bp->b_actf = dp->b_actf;
1984                 dp->b_actf = bp;
1985         } else {
1986                 TRACE_3(TR_FAC_DADA, TR_DCDSTRATEGY_DISKSORT_START,
1987                     "dcdstrategy_disksort_start: dp 0x%p bp 0x%p un 0x%p",
1988                     dp, bp, un);
1989                 disksort(dp, bp);
1990                 TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_DISKSORT_END,
1991                     "dcdstrategy_disksort_end");
1992         }
1993 
1994         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
1995             "ncmd %x , throttle %x, forw 0x%p\n",
1996             un->un_ncmds, un->un_throttle, (void *)dp->b_forw);
1997         ASSERT(un->un_ncmds >= 0);
1998         ASSERT(un->un_throttle >= 0);
1999         if ((un->un_ncmds < un->un_throttle) && (dp->b_forw == NULL)) {
2000                 dcdstart(un);
2001         } else if (BP_HAS_NO_PKT(dp->b_actf)) {
2002                 struct buf *cmd_bp;
2003 
2004                 cmd_bp = dp->b_actf;
2005                 cmd_bp->av_back = ALLOCATING_PKT;
2006                 mutex_exit(DCD_MUTEX);
2007                 /*
2008                  * try and map this one
2009                  */
2010                 TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_SMALL_WINDOW_START,
2011                     "dcdstrategy_small_window_call (begin)");
2012 
2013                 make_dcd_cmd(un, cmd_bp, NULL_FUNC);
2014 
2015                 TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_SMALL_WINDOW_END,
2016                     "dcdstrategy_small_window_call (end)");
2017 
2018                 /*
2019                  * there is a small window where the active cmd
2020                  * completes before make_dcd_cmd returns.
2021                  * consequently, this cmd never gets started so
2022                  * we start it from here
2023                  */
2024                 mutex_enter(DCD_MUTEX);
2025                 if ((un->un_ncmds < un->un_throttle) &&
2026                     (dp->b_forw == NULL)) {
2027                         dcdstart(un);
2028                 }
2029         }
2030         mutex_exit(DCD_MUTEX);
2031 
2032 done:
2033         TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_END, "dcdstrategy_end");
2034         return (0);
2035 }
2036 
2037 
2038 /*
2039  * Unit start and Completion
2040  * NOTE: we assume that the caller has at least checked for:
2041  *              (un->un_ncmds < un->un_throttle)
2042  *      if not, there is no real harm done, dcd_transport() will
2043  *      return BUSY
2044  */
2045 static void
2046 dcdstart(struct dcd_disk *un)
2047 {
2048         int status, sort_key;
2049         struct buf *bp;
2050         struct diskhd *dp;
2051         uchar_t state = un->un_last_state;
2052 
2053         TRACE_1(TR_FAC_DADA, TR_DCDSTART_START, "dcdstart_start: un 0x%p", un);
2054 
2055 retry:
2056         ASSERT(mutex_owned(DCD_MUTEX));
2057 
2058         dp = &un->un_utab;
2059         if (((bp = dp->b_actf) == NULL) || (bp->av_back == ALLOCATING_PKT) ||
2060             (dp->b_forw != NULL)) {
2061                 TRACE_0(TR_FAC_DADA, TR_DCDSTART_NO_WORK_END,
2062                     "dcdstart_end (no work)");
2063                 return;
2064         }
2065 
2066         /*
2067          * remove from active queue
2068          */
2069         dp->b_actf = bp->b_actf;
2070         bp->b_actf = 0;
2071 
2072         /*
2073          * increment ncmds before calling dcd_transport because dcdintr
2074          * may be called before we return from dcd_transport!
2075          */
2076         un->un_ncmds++;
2077 
2078         /*
2079          * If measuring stats, mark exit from wait queue and
2080          * entrance into run 'queue' if and only if we are
2081          * going to actually start a command.
2082          * Normally the bp already has a packet at this point
2083          */
2084         DCD_DO_KSTATS(un, kstat_waitq_to_runq, bp);
2085 
2086         mutex_exit(DCD_MUTEX);
2087 
2088         if (BP_HAS_NO_PKT(bp)) {
2089                 make_dcd_cmd(un, bp, dcdrunout);
2090                 if (BP_HAS_NO_PKT(bp) && !(bp->b_flags & B_ERROR)) {
2091                         mutex_enter(DCD_MUTEX);
2092                         DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
2093 
2094                         bp->b_actf = dp->b_actf;
2095                         dp->b_actf = bp;
2096                         New_state(un, DCD_STATE_RWAIT);
2097                         un->un_ncmds--;
2098                         TRACE_0(TR_FAC_DADA, TR_DCDSTART_NO_RESOURCES_END,
2099                             "dcdstart_end (No Resources)");
2100                         goto done;
2101 
2102                 } else if (bp->b_flags & B_ERROR) {
2103                         mutex_enter(DCD_MUTEX);
2104                         DCD_DO_KSTATS(un, kstat_runq_exit, bp);
2105 
2106                         un->un_ncmds--;
2107                         bp->b_resid = bp->b_bcount;
2108                         if (bp->b_error == 0) {
2109                                 SET_BP_ERROR(bp, EIO);
2110                         }
2111 
2112                         /*
2113                          * restore old state
2114                          */
2115                         un->un_state = un->un_last_state;
2116                         un->un_last_state = state;
2117 
2118                         mutex_exit(DCD_MUTEX);
2119 
2120                         biodone(bp);
2121                         mutex_enter(DCD_MUTEX);
2122                         if (un->un_state == DCD_STATE_SUSPENDED) {
2123                                 cv_broadcast(&un->un_disk_busy_cv);
2124                         }
2125 
2126                         if ((un->un_ncmds < un->un_throttle) &&
2127                             (dp->b_forw == NULL)) {
2128                                 goto retry;
2129                         } else {
2130                                 goto done;
2131                         }
2132                 }
2133         }
2134 
2135         /*
2136          * Restore resid from the packet, b_resid had been the
2137          * disksort key.
2138          */
2139         sort_key = bp->b_resid;
2140         bp->b_resid = BP_PKT(bp)->pkt_resid;
2141         BP_PKT(bp)->pkt_resid = 0;
2142 
2143         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2144             "bp->b_resid %lx, pkt_resid %lx\n",
2145             bp->b_resid, BP_PKT(bp)->pkt_resid);
2146 
2147         /*
2148          * We used to check whether or not to try and link commands here.
2149          * Since we have found that there is no performance improvement
2150          * for linked commands, this has not made much sense.
2151          */
2152         if ((status = dcd_transport((struct dcd_pkt *)BP_PKT(bp)))
2153             != TRAN_ACCEPT) {
2154                 mutex_enter(DCD_MUTEX);
2155                 un->un_ncmds--;
2156                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2157                     "transport returned %x\n", status);
2158                 if (status == TRAN_BUSY) {
2159                         DCD_DO_ERRSTATS(un, dcd_transerrs);
2160                         DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
2161                         dcd_handle_tran_busy(bp, dp, un);
2162                         if (un->un_ncmds > 0) {
2163                                 bp->b_resid = sort_key;
2164                         }
2165                 } else {
2166                         DCD_DO_KSTATS(un, kstat_runq_exit, bp);
2167                         mutex_exit(DCD_MUTEX);
2168 
2169                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2170                             "transport rejected (%d)\n",
2171                             status);
2172                         SET_BP_ERROR(bp, EIO);
2173                         bp->b_resid = bp->b_bcount;
2174                         if (bp != un->un_sbufp) {
2175                                 dcd_destroy_pkt(BP_PKT(bp));
2176                         }
2177                         biodone(bp);
2178 
2179                         mutex_enter(DCD_MUTEX);
2180                         if (un->un_state == DCD_STATE_SUSPENDED) {
2181                                 cv_broadcast(&un->un_disk_busy_cv);
2182                         }
2183                         if ((un->un_ncmds < un->un_throttle) &&
2184                             (dp->b_forw == NULL)) {
2185                                         goto retry;
2186                         }
2187                 }
2188         } else {
2189                 mutex_enter(DCD_MUTEX);
2190 
2191                 if (dp->b_actf && BP_HAS_NO_PKT(dp->b_actf)) {
2192                         struct buf *cmd_bp;
2193 
2194                         cmd_bp = dp->b_actf;
2195                         cmd_bp->av_back = ALLOCATING_PKT;
2196                         mutex_exit(DCD_MUTEX);
2197                         /*
2198                          * try and map this one
2199                          */
2200                         TRACE_0(TR_FAC_DADA, TR_DCASTART_SMALL_WINDOW_START,
2201                             "dcdstart_small_window_start");
2202 
2203                         make_dcd_cmd(un, cmd_bp, NULL_FUNC);
2204 
2205                         TRACE_0(TR_FAC_DADA, TR_DCDSTART_SMALL_WINDOW_END,
2206                             "dcdstart_small_window_end");
2207                         /*
2208                          * there is a small window where the active cmd
2209                          * completes before make_dcd_cmd returns.
2210                          * consequently, this cmd never gets started so
2211                          * we start it from here
2212                          */
2213                         mutex_enter(DCD_MUTEX);
2214                         if ((un->un_ncmds < un->un_throttle) &&
2215                             (dp->b_forw == NULL)) {
2216                                 goto retry;
2217                         }
2218                 }
2219         }
2220 
2221 done:
2222         ASSERT(mutex_owned(DCD_MUTEX));
2223         TRACE_0(TR_FAC_DADA, TR_DCDSTART_END, "dcdstart_end");
2224 }
2225 
2226 /*
2227  * make_dcd_cmd: create a pkt
2228  */
2229 static void
2230 make_dcd_cmd(struct dcd_disk *un, struct buf *bp, int (*func)())
2231 {
2232         auto int count, com, direction;
2233         struct dcd_pkt *pkt;
2234         int flags, tval;
2235 
2236         _NOTE(DATA_READABLE_WITHOUT_LOCK(dcd_disk::un_dp))
2237         TRACE_3(TR_FAC_DADA, TR_MAKE_DCD_CMD_START,
2238             "make_dcd_cmd_start: un 0x%p bp 0x%p un 0x%p", un, bp, un);
2239 
2240 
2241         flags = un->un_cmd_flags;
2242 
2243         if (bp != un->un_sbufp) {
2244                 int partition = DCDPART(bp->b_edev);
2245                 diskaddr_t p_lblksrt;
2246                 diskaddr_t lblocks;
2247                 long secnt;
2248                 uint32_t blkno;
2249                 int dkl_nblk, delta;
2250                 long resid;
2251 
2252                 if (cmlb_partinfo(un->un_dklbhandle,
2253                     partition,
2254                     &lblocks,
2255                     &p_lblksrt,
2256                     NULL,
2257                     NULL,
2258                     0) != NULL) {
2259                         lblocks = 0;
2260                         p_lblksrt = 0;
2261                 }
2262 
2263                 dkl_nblk = (int)lblocks;
2264 
2265                 /*
2266                  * Make sure we don't run off the end of a partition.
2267                  *
2268                  * Put this test here so that we can adjust b_count
2269                  * to accurately reflect the actual amount we are
2270                  * goint to transfer.
2271                  */
2272 
2273                 /*
2274                  * First, compute partition-relative block number
2275                  */
2276                 blkno = dkblock(bp);
2277                 secnt = (bp->b_bcount + (un->un_secsize - 1)) >> un->un_secdiv;
2278                 count = MIN(secnt, dkl_nblk - blkno);
2279                 if (count != secnt) {
2280                         /*
2281                          * We have an overrun
2282                          */
2283                         resid = (secnt - count) << un->un_secdiv;
2284                         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2285                             "overrun by %ld sectors\n",
2286                             secnt - count);
2287                         bp->b_bcount -= resid;
2288                 } else {
2289                         resid = 0;
2290                 }
2291 
2292                 /*
2293                  * Adjust block number to absolute
2294                  */
2295                 delta = (int)p_lblksrt;
2296                 blkno += delta;
2297 
2298                 mutex_enter(DCD_MUTEX);
2299                 /*
2300                  * This is for devices having block size different from
2301                  * from DEV_BSIZE (e.g. 2K CDROMs).
2302                  */
2303                 if (un->un_lbasize != un->un_secsize) {
2304                         blkno >>= un->un_blknoshift;
2305                         count >>= un->un_blknoshift;
2306                 }
2307                 mutex_exit(DCD_MUTEX);
2308 
2309                 TRACE_0(TR_FAC_DADA, TR_MAKE_DCD_CMD_INIT_PKT_START,
2310                     "make_dcd_cmd_init_pkt_call (begin)");
2311                 pkt = dcd_init_pkt(ROUTE, NULL, bp,
2312                     (uint32_t)sizeof (struct dcd_cmd),
2313                     un->un_cmd_stat_size, PP_LEN, PKT_CONSISTENT,
2314                     func, (caddr_t)un);
2315                 TRACE_1(TR_FAC_DADA, TR_MAKE_DCD_CMD_INIT_PKT_END,
2316                     "make_dcd_cmd_init_pkt_call (end): pkt 0x%p", pkt);
2317                 if (!pkt) {
2318                         bp->b_bcount += resid;
2319                         bp->av_back = NO_PKT_ALLOCATED;
2320                         TRACE_0(TR_FAC_DADA,
2321                             TR_MAKE_DCD_CMD_NO_PKT_ALLOCATED1_END,
2322                             "make_dcd_cmd_end (NO_PKT_ALLOCATED1)");
2323                         return;
2324                 }
2325                 if (bp->b_flags & B_READ) {
2326                         if ((un->un_dp->options & DMA_SUPPORTTED) ==
2327                             DMA_SUPPORTTED) {
2328                                 com = ATA_READ_DMA;
2329                         } else {
2330                                 if (un->un_dp->options & BLOCK_MODE)
2331                                         com = ATA_READ_MULTIPLE;
2332                                 else
2333                                         com = ATA_READ;
2334                         }
2335                         direction = DATA_READ;
2336                 } else {
2337                         if ((un->un_dp->options & DMA_SUPPORTTED) ==
2338                             DMA_SUPPORTTED) {
2339                                 com = ATA_WRITE_DMA;
2340                         } else {
2341                                 if (un->un_dp->options & BLOCK_MODE)
2342                                         com = ATA_WRITE_MULTIPLE;
2343                                 else
2344                                         com = ATA_WRITE;
2345                         }
2346                         direction = DATA_WRITE;
2347                 }
2348 
2349                 /*
2350                  * Save the resid in the packet, temporarily until
2351                  * we transport the command.
2352                  */
2353                 pkt->pkt_resid = resid;
2354 
2355                 makecommand(pkt, flags, com, blkno, ADD_LBA_MODE,
2356                     bp->b_bcount, direction, 0);
2357                 tval = dcd_io_time;
2358         } else {
2359 
2360                 struct udcd_cmd *scmd = (struct udcd_cmd *)bp->b_forw;
2361 
2362                 /*
2363                  * set options
2364                  */
2365                 if ((scmd->udcd_flags & UDCD_SILENT) && !(DEBUGGING)) {
2366                         flags |= FLAG_SILENT;
2367                 }
2368                 if (scmd->udcd_flags &  UDCD_DIAGNOSE)
2369                         flags |= FLAG_DIAGNOSE;
2370 
2371                 if (scmd->udcd_flags & UDCD_NOINTR)
2372                         flags |= FLAG_NOINTR;
2373 
2374                 pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL,
2375                     (bp->b_bcount)? bp: NULL,
2376                     (uint32_t)sizeof (struct dcd_cmd),
2377                     2, PP_LEN, PKT_CONSISTENT, func, (caddr_t)un);
2378 
2379                 if (!pkt) {
2380                         bp->av_back = NO_PKT_ALLOCATED;
2381                         return;
2382                 }
2383 
2384                 makecommand(pkt, 0, scmd->udcd_cmd->cmd,
2385                     scmd->udcd_cmd->sector_num.lba_num,
2386                     scmd->udcd_cmd->address_mode,
2387                     scmd->udcd_cmd->size,
2388                     scmd->udcd_cmd->direction, scmd->udcd_cmd->features);
2389 
2390                 pkt->pkt_flags = flags;
2391                 if (scmd->udcd_timeout == 0)
2392                         tval = dcd_io_time;
2393                 else
2394                         tval = scmd->udcd_timeout;
2395                 /* UDAD interface should be decided. */
2396                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2397                     "udcd interface\n");
2398         }
2399 
2400         pkt->pkt_comp = dcdintr;
2401         pkt->pkt_time = tval;
2402         PKT_SET_BP(pkt, bp);
2403         bp->av_back = (struct buf *)pkt;
2404 
2405         TRACE_0(TR_FAC_DADA, TR_MAKE_DCD_CMD_END, "make_dcd_cmd_end");
2406 }
2407 
2408 /*
2409  * Command completion processing
2410  */
2411 static void
2412 dcdintr(struct dcd_pkt *pkt)
2413 {
2414         struct dcd_disk *un;
2415         struct buf *bp;
2416         int action;
2417         int status;
2418 
2419         bp = PKT_GET_BP(pkt);
2420         un = ddi_get_soft_state(dcd_state, DCDUNIT(bp->b_edev));
2421 
2422         TRACE_1(TR_FAC_DADA, TR_DCDINTR_START, "dcdintr_start: un 0x%p", un);
2423         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdintr\n");
2424 
2425         mutex_enter(DCD_MUTEX);
2426         un->un_ncmds--;
2427         DCD_DO_KSTATS(un, kstat_runq_exit, bp);
2428         ASSERT(un->un_ncmds >= 0);
2429 
2430         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2431             "reason %x and Status %x\n", pkt->pkt_reason, SCBP_C(pkt));
2432 
2433         /*
2434          * do most common case first
2435          */
2436         if ((pkt->pkt_reason == CMD_CMPLT) && (SCBP_C(pkt) == 0)) {
2437                 int com = GETATACMD((struct dcd_cmd *)pkt->pkt_cdbp);
2438 
2439                 if (un->un_state == DCD_STATE_OFFLINE) {
2440                         un->un_state = un->un_last_state;
2441                         dcd_log(DCD_DEVINFO, dcd_label, CE_NOTE,
2442                             (const char *) diskokay);
2443                 }
2444                 /*
2445                  * If the command is a read or a write, and we have
2446                  * a non-zero pkt_resid, that is an error. We should
2447                  * attempt to retry the operation if possible.
2448                  */
2449                 action = COMMAND_DONE;
2450                 if (pkt->pkt_resid && (com == ATA_READ || com == ATA_WRITE)) {
2451                         DCD_DO_ERRSTATS(un, dcd_harderrs);
2452                         if ((int)PKT_GET_RETRY_CNT(pkt) < dcd_retry_count) {
2453                                 PKT_INCR_RETRY_CNT(pkt, 1);
2454                                 action = QUE_COMMAND;
2455                         } else {
2456                                 /*
2457                                  * if we have exhausted retries
2458                                  * a command with a residual is in error in
2459                                  * this case.
2460                                  */
2461                                 action = COMMAND_DONE_ERROR;
2462                         }
2463                         dcd_log(DCD_DEVINFO, dcd_label,
2464                             CE_WARN, "incomplete %s- %s\n",
2465                             (bp->b_flags & B_READ)? "read" : "write",
2466                             (action == QUE_COMMAND)? "retrying" :
2467                             "giving up");
2468                 }
2469 
2470                 /*
2471                  * pkt_resid will reflect, at this point, a residual
2472                  * of how many bytes left to be transferred there were
2473                  * from the actual scsi command. Add this to b_resid i.e
2474                  * the amount this driver could not see to transfer,
2475                  * to get the total number of bytes not transfered.
2476                  */
2477                 if (action != QUE_COMMAND) {
2478                         bp->b_resid += pkt->pkt_resid;
2479                 }
2480 
2481         } else if (pkt->pkt_reason != CMD_CMPLT) {
2482                 action = dcd_handle_incomplete(un, bp);
2483         }
2484 
2485         /*
2486          * If we are in the middle of syncing or dumping, we have got
2487          * here because dcd_transport has called us explictly after
2488          * completing the command in a polled mode. We don't want to
2489          * have a recursive call into dcd_transport again.
2490          */
2491         if (ddi_in_panic() && (action == QUE_COMMAND)) {
2492                 action = COMMAND_DONE_ERROR;
2493         }
2494 
2495         /*
2496          * save pkt reason; consecutive failures are not reported unless
2497          * fatal
2498          * do not reset last_pkt_reason when the cmd was retried and
2499          * succeeded because
2500          * there maybe more commands comming back with last_pkt_reason
2501          */
2502         if ((un->un_last_pkt_reason != pkt->pkt_reason) &&
2503             ((pkt->pkt_reason != CMD_CMPLT) ||
2504             (PKT_GET_RETRY_CNT(pkt) == 0))) {
2505                 un->un_last_pkt_reason = pkt->pkt_reason;
2506         }
2507 
2508         switch (action) {
2509         case COMMAND_DONE_ERROR:
2510 error:
2511                 if (bp->b_resid == 0) {
2512                         bp->b_resid = bp->b_bcount;
2513                 }
2514                 if (bp->b_error == 0) {
2515                         struct  dcd_cmd *cdbp = (struct dcd_cmd *)pkt->pkt_cdbp;
2516                         if (cdbp->cmd == ATA_FLUSH_CACHE &&
2517                             (pkt->pkt_scbp[0] & STATUS_ATA_ERR) &&
2518                             (pkt->pkt_scbp[1] & ERR_ABORT)) {
2519                                 SET_BP_ERROR(bp, ENOTSUP);
2520                                 un->un_flush_not_supported = 1;
2521                         } else {
2522                                 SET_BP_ERROR(bp, EIO);
2523                         }
2524                 }
2525                 bp->b_flags |= B_ERROR;
2526                 /*FALLTHROUGH*/
2527         case COMMAND_DONE:
2528                 dcddone_and_mutex_exit(un, bp);
2529 
2530                 TRACE_0(TR_FAC_DADA, TR_DCDINTR_COMMAND_DONE_END,
2531                     "dcdintr_end (COMMAND_DONE)");
2532                 return;
2533 
2534         case QUE_COMMAND:
2535                 if (un->un_ncmds >= un->un_throttle) {
2536                         struct diskhd *dp = &un->un_utab;
2537 
2538                         bp->b_actf = dp->b_actf;
2539                         dp->b_actf = bp;
2540 
2541                         DCD_DO_KSTATS(un, kstat_waitq_enter, bp);
2542 
2543                         mutex_exit(DCD_MUTEX);
2544                         goto exit;
2545                 }
2546 
2547                 un->un_ncmds++;
2548                 /* reset the pkt reason again */
2549                 pkt->pkt_reason = 0;
2550                 DCD_DO_KSTATS(un, kstat_runq_enter, bp);
2551                 mutex_exit(DCD_MUTEX);
2552                 if ((status = dcd_transport(BP_PKT(bp))) != TRAN_ACCEPT) {
2553                         struct diskhd *dp = &un->un_utab;
2554 
2555                         mutex_enter(DCD_MUTEX);
2556                         un->un_ncmds--;
2557                         if (status == TRAN_BUSY) {
2558                                 DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
2559                                 dcd_handle_tran_busy(bp, dp, un);
2560                                 mutex_exit(DCD_MUTEX);
2561                                 goto exit;
2562                         }
2563                         DCD_DO_ERRSTATS(un, dcd_transerrs);
2564                         DCD_DO_KSTATS(un, kstat_runq_exit, bp);
2565 
2566                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2567                             "requeue of command fails (%x)\n", status);
2568                         SET_BP_ERROR(bp, EIO);
2569                         bp->b_resid = bp->b_bcount;
2570 
2571                         dcddone_and_mutex_exit(un, bp);
2572                         goto exit;
2573                 }
2574                 break;
2575 
2576         case JUST_RETURN:
2577         default:
2578                 DCD_DO_KSTATS(un, kstat_waitq_enter, bp);
2579                 mutex_exit(DCD_MUTEX);
2580                 break;
2581         }
2582 
2583 exit:
2584         TRACE_0(TR_FAC_DADA, TR_DCDINTR_END, "dcdintr_end");
2585 }
2586 
2587 
2588 /*
2589  * Done with a command.
2590  */
2591 static void
2592 dcddone_and_mutex_exit(struct dcd_disk *un, register struct buf *bp)
2593 {
2594         struct diskhd *dp;
2595 
2596         TRACE_1(TR_FAC_DADA, TR_DCDONE_START, "dcddone_start: un 0x%p", un);
2597 
2598         _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&un->un_dcd->dcd_mutex));
2599 
2600         dp = &un->un_utab;
2601         if (bp == dp->b_forw) {
2602                 dp->b_forw = NULL;
2603         }
2604 
2605         if (un->un_stats) {
2606                 ulong_t n_done = bp->b_bcount - bp->b_resid;
2607                 if (bp->b_flags & B_READ) {
2608                         IOSP->reads++;
2609                         IOSP->nread += n_done;
2610                 } else {
2611                         IOSP->writes++;
2612                         IOSP->nwritten += n_done;
2613                 }
2614         }
2615         if (IO_PARTITION_STATS) {
2616                 ulong_t n_done = bp->b_bcount - bp->b_resid;
2617                 if (bp->b_flags & B_READ) {
2618                         IOSP_PARTITION->reads++;
2619                         IOSP_PARTITION->nread += n_done;
2620                 } else {
2621                         IOSP_PARTITION->writes++;
2622                         IOSP_PARTITION->nwritten += n_done;
2623                 }
2624         }
2625 
2626         /*
2627          * Start the next one before releasing resources on this one
2628          */
2629         if (un->un_state == DCD_STATE_SUSPENDED) {
2630                 cv_broadcast(&un->un_disk_busy_cv);
2631         } else if (dp->b_actf && (un->un_ncmds < un->un_throttle) &&
2632             (dp->b_forw == NULL && un->un_state != DCD_STATE_SUSPENDED)) {
2633                 dcdstart(un);
2634         }
2635 
2636         mutex_exit(DCD_MUTEX);
2637 
2638         if (bp != un->un_sbufp) {
2639                 dcd_destroy_pkt(BP_PKT(bp));
2640                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2641                     "regular done: resid %ld\n", bp->b_resid);
2642         } else {
2643                 ASSERT(un->un_sbuf_busy);
2644         }
2645         TRACE_0(TR_FAC_DADA, TR_DCDDONE_BIODONE_CALL, "dcddone_biodone_call");
2646 
2647         biodone(bp);
2648 
2649         (void) pm_idle_component(DCD_DEVINFO, 0);
2650 
2651         TRACE_0(TR_FAC_DADA, TR_DCDDONE_END, "dcddone end");
2652 }
2653 
2654 
2655 /*
2656  * reset the disk unless the transport layer has already
2657  * cleared the problem
2658  */
2659 #define C1      (STAT_ATA_BUS_RESET|STAT_ATA_DEV_RESET|STAT_ATA_ABORTED)
2660 static void
2661 dcd_reset_disk(struct dcd_disk *un, struct dcd_pkt *pkt)
2662 {
2663 
2664         if ((pkt->pkt_statistics & C1) == 0) {
2665                 mutex_exit(DCD_MUTEX);
2666                 if (!dcd_reset(ROUTE, RESET_ALL)) {
2667                         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2668                             "Reset failed");
2669                 }
2670                 mutex_enter(DCD_MUTEX);
2671         }
2672 }
2673 
2674 static int
2675 dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp)
2676 {
2677         static char *fail = "ATA transport failed: reason '%s': %s\n";
2678         static char *notresp = "disk not responding to selection\n";
2679         int rval = COMMAND_DONE_ERROR;
2680         int action = COMMAND_SOFT_ERROR;
2681         struct dcd_pkt *pkt = BP_PKT(bp);
2682         int be_chatty = (un->un_state != DCD_STATE_SUSPENDED) &&
2683             (bp != un->un_sbufp || !(pkt->pkt_flags & FLAG_SILENT));
2684 
2685         ASSERT(mutex_owned(DCD_MUTEX));
2686 
2687         switch (pkt->pkt_reason) {
2688 
2689         case CMD_TIMEOUT:
2690                 /*
2691                  * This Indicates the already the HBA would  have reset
2692                  * so Just indicate to retry the command
2693                  */
2694                 break;
2695 
2696         case CMD_INCOMPLETE:
2697                 action = dcd_check_error(un, bp);
2698                 DCD_DO_ERRSTATS(un, dcd_transerrs);
2699                 if (action == COMMAND_HARD_ERROR) {
2700                         (void) dcd_reset_disk(un, pkt);
2701                 }
2702                 break;
2703 
2704         case CMD_FATAL:
2705                 /*
2706                  * Something drastic has gone wrong
2707                  */
2708                 break;
2709         case CMD_DMA_DERR:
2710         case CMD_DATA_OVR:
2711                 /* FALLTHROUGH */
2712 
2713         default:
2714                 /*
2715                  * the target may still be running the  command,
2716                  * so we should try and reset that target.
2717                  */
2718                 DCD_DO_ERRSTATS(un, dcd_transerrs);
2719                 if ((pkt->pkt_reason != CMD_RESET) &&
2720                     (pkt->pkt_reason != CMD_ABORTED)) {
2721                         (void) dcd_reset_disk(un, pkt);
2722                 }
2723                 break;
2724         }
2725 
2726         /*
2727          * If pkt_reason is CMD_RESET/ABORTED, chances are that this pkt got
2728          * reset/aborted because another disk on this bus caused it.
2729          * The disk that caused it, should get CMD_TIMEOUT with pkt_statistics
2730          * of STAT_TIMEOUT/STAT_DEV_RESET
2731          */
2732         if ((pkt->pkt_reason == CMD_RESET) ||(pkt->pkt_reason == CMD_ABORTED)) {
2733                 /* To be written : XXX */
2734                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2735                     "Command aborted\n");
2736         }
2737 
2738         if (bp == un->un_sbufp && (pkt->pkt_flags & FLAG_DIAGNOSE)) {
2739                 rval = COMMAND_DONE_ERROR;
2740         } else {
2741                 if ((rval == COMMAND_DONE_ERROR) &&
2742                     (action == COMMAND_SOFT_ERROR) &&
2743                     ((int)PKT_GET_RETRY_CNT(pkt) < dcd_retry_count)) {
2744                         PKT_INCR_RETRY_CNT(pkt, 1);
2745                         rval = QUE_COMMAND;
2746                 }
2747         }
2748 
2749         if (pkt->pkt_reason == CMD_INCOMPLETE && rval == COMMAND_DONE_ERROR) {
2750                 /*
2751                  * Looks like someone turned off this shoebox.
2752                  */
2753                 if (un->un_state != DCD_STATE_OFFLINE) {
2754                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2755                             (const char *) notresp);
2756                         New_state(un, DCD_STATE_OFFLINE);
2757                 }
2758         } else if (pkt->pkt_reason == CMD_FATAL) {
2759                 /*
2760                  * Suppressing the following message for the time being
2761                  * dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2762                  * (const char *) notresp);
2763                  */
2764                 PKT_INCR_RETRY_CNT(pkt, 6);
2765                 rval = COMMAND_DONE_ERROR;
2766                 New_state(un, DCD_STATE_FATAL);
2767         } else if (be_chatty) {
2768                 int in_panic = ddi_in_panic();
2769                 if (!in_panic || (rval == COMMAND_DONE_ERROR)) {
2770                         if (((pkt->pkt_reason != un->un_last_pkt_reason) &&
2771                             (pkt->pkt_reason != CMD_RESET)) ||
2772                             (rval == COMMAND_DONE_ERROR) ||
2773                             (dcd_error_level == DCD_ERR_ALL)) {
2774                                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2775                                     fail, dcd_rname(pkt->pkt_reason),
2776                                     (rval == COMMAND_DONE_ERROR) ?
2777                                     "giving up": "retrying command");
2778                                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2779                                     "retrycount=%x\n",
2780                                     PKT_GET_RETRY_CNT(pkt));
2781                         }
2782                 }
2783         }
2784 error:
2785         return (rval);
2786 }
2787 
2788 static int
2789 dcd_check_error(struct dcd_disk *un, struct buf *bp)
2790 {
2791         struct diskhd *dp = &un->un_utab;
2792         struct dcd_pkt *pkt = BP_PKT(bp);
2793         int rval = 0;
2794         unsigned char status;
2795         unsigned char error;
2796 
2797         TRACE_0(TR_FAC_DADA, TR_DCD_CHECK_ERROR_START, "dcd_check_error_start");
2798         ASSERT(mutex_owned(DCD_MUTEX));
2799 
2800         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
2801             "Pkt: 0x%p dp: 0x%p\n", (void *)pkt, (void *)dp);
2802 
2803         /*
2804          * Here we need to check status first and then if error is indicated
2805          * Then the error register.
2806          */
2807 
2808         status = (pkt->pkt_scbp)[0];
2809         if ((status & STATUS_ATA_DWF) == STATUS_ATA_DWF) {
2810                 /*
2811                  * There has been a Device Fault  - reason for such error
2812                  * is vendor specific
2813                  * Action to be taken is - Indicate error and reset device.
2814                  */
2815 
2816                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "Device Fault\n");
2817                 rval = COMMAND_HARD_ERROR;
2818         } else if ((status & STATUS_ATA_CORR) == STATUS_ATA_CORR) {
2819 
2820                 /*
2821                  * The sector read or written is marginal and hence ECC
2822                  * Correction has been applied. Indicate to repair
2823                  * Here we need to probably re-assign based on the badblock
2824                  * mapping.
2825                  */
2826 
2827                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2828                     "Soft Error on block %x\n",
2829                     ((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num);
2830                 rval = COMMAND_SOFT_ERROR;
2831         } else if ((status & STATUS_ATA_ERR) == STATUS_ATA_ERR) {
2832                 error = pkt->pkt_scbp[1];
2833 
2834                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2835                     "Command:0x%x,Error:0x%x,Status:0x%x\n",
2836                     GETATACMD((struct dcd_cmd *)pkt->pkt_cdbp),
2837                     error, status);
2838                 if ((error &  ERR_AMNF) == ERR_AMNF) {
2839                         /* Address make not found */
2840                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2841                             "Address Mark Not Found");
2842                 } else if ((error & ERR_TKONF) == ERR_TKONF) {
2843                         /* Track 0 Not found */
2844                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2845                             "Track 0 Not found \n");
2846                 } else if ((error & ERR_IDNF) == ERR_IDNF) {
2847                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2848                             " ID not found \n");
2849                 } else if ((error &  ERR_UNC) == ERR_UNC) {
2850                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2851                             "Uncorrectable data Error: Block %x\n",
2852                             ((struct dcd_cmd *)pkt->pkt_cdbp)->
2853                             sector_num.lba_num);
2854                 } else if ((error & ERR_BBK) == ERR_BBK) {
2855                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2856                             "Bad block detected: Block %x\n",
2857                             ((struct dcd_cmd *)pkt->pkt_cdbp)->
2858                             sector_num.lba_num);
2859                 } else if ((error & ERR_ABORT) == ERR_ABORT) {
2860                         /* Aborted Command */
2861                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2862                             " Aborted Command \n");
2863                 }
2864                 /*
2865                  * Return the soft error so that the command
2866                  * will be retried.
2867                  */
2868                 rval = COMMAND_SOFT_ERROR;
2869         }
2870 
2871         TRACE_0(TR_FAC_DADA, TR_DCD_CHECK_ERROR_END, "dcd_check_error_end");
2872         return (rval);
2873 }
2874 
2875 
2876 /*
2877  *      System Crash Dump routine
2878  */
2879 
2880 #define NDUMP_RETRIES   5
2881 
2882 static int
2883 dcddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
2884 {
2885         struct dcd_pkt *pkt;
2886         int i;
2887         struct buf local, *bp;
2888         int err;
2889         unsigned char com;
2890         diskaddr_t p_lblksrt;
2891         diskaddr_t lblocks;
2892 
2893         GET_SOFT_STATE(dev);
2894 #ifdef lint
2895         part = part;
2896 #endif /* lint */
2897 
2898         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*un))
2899 
2900         if ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL)
2901                 return (ENXIO);
2902 
2903         if (cmlb_partinfo(un->un_dklbhandle, DCDPART(dev),
2904             &lblocks, &p_lblksrt, NULL, NULL, 0))
2905                 return (ENXIO);
2906 
2907         if (blkno+nblk > lblocks) {
2908                 return (EINVAL);
2909         }
2910 
2911 
2912         if ((un->un_state == DCD_STATE_SUSPENDED) ||
2913             (un->un_state == DCD_STATE_PM_SUSPENDED)) {
2914                 if (pm_raise_power(DCD_DEVINFO, 0,
2915                     DCD_DEVICE_ACTIVE) != DDI_SUCCESS) {
2916                         return (EIO);
2917                 }
2918         }
2919 
2920         /*
2921          * When cpr calls dcddump, we know that dad is in a
2922          * a good state, so no bus reset is required
2923          */
2924         un->un_throttle = 0;
2925 
2926         if ((un->un_state != DCD_STATE_SUSPENDED) &&
2927             (un->un_state != DCD_STATE_DUMPING)) {
2928 
2929                 New_state(un, DCD_STATE_DUMPING);
2930 
2931                 /*
2932                  * Reset the bus. I'd like to not have to do this,
2933                  * but this is the safest thing to do...
2934                  */
2935 
2936                 if (dcd_reset(ROUTE, RESET_ALL) == 0) {
2937                         return (EIO);
2938                 }
2939 
2940         }
2941 
2942         blkno += p_lblksrt;
2943 
2944         /*
2945          * It should be safe to call the allocator here without
2946          * worrying about being locked for DVMA mapping because
2947          * the address we're passed is already a DVMA mapping
2948          *
2949          * We are also not going to worry about semaphore ownership
2950          * in the dump buffer. Dumping is single threaded at present.
2951          */
2952 
2953         bp = &local;
2954         bzero((caddr_t)bp, sizeof (*bp));
2955         bp->b_flags = B_BUSY;
2956         bp->b_un.b_addr = addr;
2957         bp->b_bcount = nblk << DEV_BSHIFT;
2958         bp->b_resid = 0;
2959 
2960         for (i = 0; i < NDUMP_RETRIES; i++) {
2961                 bp->b_flags &= ~B_ERROR;
2962                 if ((pkt = dcd_init_pkt(ROUTE, NULL, bp,
2963                     (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN,
2964                     PKT_CONSISTENT, NULL_FUNC, NULL)) != NULL) {
2965                         break;
2966                 }
2967                 if (i == 0) {
2968                         if (bp->b_flags & B_ERROR) {
2969                                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2970                                     "no resources for dumping; "
2971                                     "error code: 0x%x, retrying",
2972                                     geterror(bp));
2973                         } else {
2974                                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
2975                                     "no resources for dumping; retrying");
2976                         }
2977                 } else if (i != (NDUMP_RETRIES - 1)) {
2978                         if (bp->b_flags & B_ERROR) {
2979                                 dcd_log(DCD_DEVINFO, dcd_label, CE_CONT, "no "
2980                                     "resources for dumping; error code: 0x%x, "
2981                                     "retrying\n", geterror(bp));
2982                         }
2983                 } else {
2984                         if (bp->b_flags & B_ERROR) {
2985                                 dcd_log(DCD_DEVINFO, dcd_label, CE_CONT,
2986                                     "no resources for dumping; "
2987                                     "error code: 0x%x, retries failed, "
2988                                     "giving up.\n", geterror(bp));
2989                         } else {
2990                                 dcd_log(DCD_DEVINFO, dcd_label, CE_CONT,
2991                                     "no resources for dumping; "
2992                                     "retries failed, giving up.\n");
2993                         }
2994                         return (EIO);
2995                 }
2996                 delay(10);
2997         }
2998         if ((un->un_dp->options & DMA_SUPPORTTED) == DMA_SUPPORTTED) {
2999                 com = ATA_WRITE_DMA;
3000         } else {
3001                 if (un->un_dp->options & BLOCK_MODE)
3002                         com = ATA_WRITE_MULTIPLE;
3003                 else
3004                         com = ATA_WRITE;
3005         }
3006 
3007         makecommand(pkt, 0, com, blkno, ADD_LBA_MODE,
3008             (int)nblk*un->un_secsize, DATA_WRITE, 0);
3009 
3010         for (err = EIO, i = 0; i < NDUMP_RETRIES && err == EIO; i++) {
3011 
3012                 if (dcd_poll(pkt) == 0) {
3013                         switch (SCBP_C(pkt)) {
3014                         case STATUS_GOOD:
3015                                 if (pkt->pkt_resid == 0) {
3016                                         err = 0;
3017                                 }
3018                                 break;
3019                         case STATUS_ATA_BUSY:
3020                                 (void) dcd_reset(ROUTE, RESET_TARGET);
3021                                 break;
3022                         default:
3023                                 mutex_enter(DCD_MUTEX);
3024                                 (void) dcd_reset_disk(un, pkt);
3025                                 mutex_exit(DCD_MUTEX);
3026                                 break;
3027                         }
3028                 } else if (i > NDUMP_RETRIES/2) {
3029                         (void) dcd_reset(ROUTE, RESET_ALL);
3030                 }
3031 
3032         }
3033         dcd_destroy_pkt(pkt);
3034         return (err);
3035 }
3036 
3037 /*
3038  * This routine implements the ioctl calls.  It is called
3039  * from the device switch at normal priority.
3040  */
3041 /* ARGSUSED3 */
3042 static int
3043 dcdioctl(dev_t dev, int cmd, intptr_t arg, int flag,
3044         cred_t *cred_p, int *rval_p)
3045 {
3046         auto int32_t data[512 / (sizeof (int32_t))];
3047         struct dk_cinfo *info;
3048         struct dk_minfo media_info;
3049         struct udcd_cmd *scmd;
3050         int i, err;
3051         enum uio_seg uioseg = 0;
3052         enum dkio_state state = 0;
3053 #ifdef _MULTI_DATAMODEL
3054         struct dadkio_rwcmd rwcmd;
3055 #endif
3056         struct dadkio_rwcmd32 rwcmd32;
3057         struct dcd_cmd dcdcmd;
3058 
3059         GET_SOFT_STATE(dev);
3060 #ifdef lint
3061         part = part;
3062         state = state;
3063         uioseg = uioseg;
3064 #endif  /* lint */
3065 
3066         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
3067             "dcd_ioctl : cmd %x, arg %lx\n", cmd, arg);
3068 
3069         bzero((caddr_t)data, sizeof (data));
3070 
3071         switch (cmd) {
3072 
3073 #ifdef DCDDEBUG
3074 /*
3075  * Following ioctl are for testing RESET/ABORTS
3076  */
3077 #define DKIOCRESET      (DKIOC|14)
3078 #define DKIOCABORT      (DKIOC|15)
3079 
3080         case DKIOCRESET:
3081                 if (ddi_copyin((caddr_t)arg, (caddr_t)data, 4, flag))
3082                         return (EFAULT);
3083                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
3084                     "DKIOCRESET: data = 0x%x\n", data[0]);
3085                 if (dcd_reset(ROUTE, data[0])) {
3086                         return (0);
3087                 } else {
3088                         return (EIO);
3089                 }
3090         case DKIOCABORT:
3091                 DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
3092                     "DKIOCABORT:\n");
3093                 if (dcd_abort(ROUTE, (struct dcd_pkt *)0)) {
3094                         return (0);
3095                 } else {
3096                         return (EIO);
3097                 }
3098 #endif
3099 
3100         case DKIOCINFO:
3101                 /*
3102                  * Controller Information
3103                  */
3104                 info = (struct dk_cinfo *)data;
3105 
3106                 mutex_enter(DCD_MUTEX);
3107                 switch (un->un_dp->ctype) {
3108                 default:
3109                         info->dki_ctype = DKC_DIRECT;
3110                         break;
3111                 }
3112                 mutex_exit(DCD_MUTEX);
3113                 info->dki_cnum = ddi_get_instance(ddi_get_parent(DCD_DEVINFO));
3114                 (void) strcpy(info->dki_cname,
3115                     ddi_get_name(ddi_get_parent(DCD_DEVINFO)));
3116                 /*
3117                  * Unit Information
3118                  */
3119                 info->dki_unit = ddi_get_instance(DCD_DEVINFO);
3120                 info->dki_slave = (Tgt(DCD_DCD_DEVP)<<3);
3121                 (void) strcpy(info->dki_dname, ddi_driver_name(DCD_DEVINFO));
3122                 info->dki_flags = DKI_FMTVOL;
3123                 info->dki_partition = DCDPART(dev);
3124 
3125                 /*
3126                  * Max Transfer size of this device in blocks
3127                  */
3128                 info->dki_maxtransfer = un->un_max_xfer_size / DEV_BSIZE;
3129 
3130                 /*
3131                  * We can't get from here to there yet
3132                  */
3133                 info->dki_addr = 0;
3134                 info->dki_space = 0;
3135                 info->dki_prio = 0;
3136                 info->dki_vec = 0;
3137 
3138                 i = sizeof (struct dk_cinfo);
3139                 if (ddi_copyout((caddr_t)data, (caddr_t)arg, i, flag))
3140                         return (EFAULT);
3141                 else
3142                         return (0);
3143 
3144         case DKIOCGMEDIAINFO:
3145                 /*
3146                  * As dad target driver is used for IDE disks only
3147                  * Can keep the return value hardcoded to FIXED_DISK
3148                  */
3149                 media_info.dki_media_type = DK_FIXED_DISK;
3150 
3151                 mutex_enter(DCD_MUTEX);
3152                 media_info.dki_lbsize = un->un_lbasize;
3153                 media_info.dki_capacity = un->un_diskcapacity;
3154                 mutex_exit(DCD_MUTEX);
3155 
3156                 if (ddi_copyout(&media_info, (caddr_t)arg,
3157                     sizeof (struct dk_minfo), flag))
3158                         return (EFAULT);
3159                 else
3160                         return (0);
3161 
3162         case DKIOCGGEOM:
3163         case DKIOCGVTOC:
3164         case DKIOCGETEFI:
3165 
3166                 mutex_enter(DCD_MUTEX);
3167                 if (un->un_ncmds == 0) {
3168                         if ((err = dcd_unit_ready(dev)) != 0) {
3169                                 mutex_exit(DCD_MUTEX);
3170                                 return (err);
3171                         }
3172                 }
3173 
3174                 mutex_exit(DCD_MUTEX);
3175                 err = cmlb_ioctl(un->un_dklbhandle, dev, cmd,
3176                     arg, flag, cred_p, rval_p, 0);
3177                 return (err);
3178 
3179         case DKIOCGAPART:
3180         case DKIOCSAPART:
3181         case DKIOCSGEOM:
3182         case DKIOCSVTOC:
3183         case DKIOCSETEFI:
3184         case DKIOCPARTITION:
3185         case DKIOCPARTINFO:
3186         case DKIOCGMBOOT:
3187         case DKIOCSMBOOT:
3188 
3189                 err = cmlb_ioctl(un->un_dklbhandle, dev, cmd,
3190                     arg, flag, cred_p, rval_p, 0);
3191                 return (err);
3192 
3193         case DIOCTL_RWCMD:
3194                 if (drv_priv(cred_p) != 0) {
3195                         return (EPERM);
3196                 }
3197 
3198 #ifdef _MULTI_DATAMODEL
3199                 switch (ddi_model_convert_from(flag & FMODELS)) {
3200                 case DDI_MODEL_NONE:
3201                         if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd,
3202                             sizeof (struct dadkio_rwcmd), flag)) {
3203                                 return (EFAULT);
3204                         }
3205                         rwcmd32.cmd = rwcmd.cmd;
3206                         rwcmd32.flags = rwcmd.flags;
3207                         rwcmd32.blkaddr = rwcmd.blkaddr;
3208                         rwcmd32.buflen = rwcmd.buflen;
3209                         rwcmd32.bufaddr = (caddr32_t)(uintptr_t)rwcmd.bufaddr;
3210                         break;
3211                 case DDI_MODEL_ILP32:
3212                         if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd32,
3213                             sizeof (struct dadkio_rwcmd32), flag)) {
3214                                 return (EFAULT);
3215                         }
3216                         break;
3217                 }
3218 #else
3219                 if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd32,
3220                     sizeof (struct dadkio_rwcmd32), flag)) {
3221                         return (EFAULT);
3222                 }
3223 #endif
3224                 mutex_enter(DCD_MUTEX);
3225 
3226                 uioseg  = UIO_SYSSPACE;
3227                 scmd = (struct udcd_cmd *)data;
3228                 scmd->udcd_cmd = &dcdcmd;
3229                 /*
3230                  * Convert the dadkio_rwcmd structure to udcd_cmd so that
3231                  * it can take the normal path to get the io done
3232                  */
3233                 if (rwcmd32.cmd == DADKIO_RWCMD_READ) {
3234                         if ((un->un_dp->options & DMA_SUPPORTTED) ==
3235                             DMA_SUPPORTTED)
3236                                 scmd->udcd_cmd->cmd = ATA_READ_DMA;
3237                         else
3238                                 scmd->udcd_cmd->cmd = ATA_READ;
3239                         scmd->udcd_cmd->address_mode = ADD_LBA_MODE;
3240                         scmd->udcd_cmd->direction = DATA_READ;
3241                         scmd->udcd_flags |= UDCD_READ|UDCD_SILENT;
3242                 } else if (rwcmd32.cmd == DADKIO_RWCMD_WRITE) {
3243                         if ((un->un_dp->options & DMA_SUPPORTTED) ==
3244                             DMA_SUPPORTTED)
3245                                 scmd->udcd_cmd->cmd = ATA_WRITE_DMA;
3246                         else
3247                                 scmd->udcd_cmd->cmd = ATA_WRITE;
3248                         scmd->udcd_cmd->direction = DATA_WRITE;
3249                         scmd->udcd_flags |= UDCD_WRITE|UDCD_SILENT;
3250                 } else {
3251                         mutex_exit(DCD_MUTEX);
3252                         return (EINVAL);
3253                 }
3254 
3255                 scmd->udcd_cmd->address_mode = ADD_LBA_MODE;
3256                 scmd->udcd_cmd->features = 0;
3257                 scmd->udcd_cmd->size = rwcmd32.buflen;
3258                 scmd->udcd_cmd->sector_num.lba_num = rwcmd32.blkaddr;
3259                 scmd->udcd_bufaddr = (caddr_t)(uintptr_t)rwcmd32.bufaddr;
3260                 scmd->udcd_buflen = rwcmd32.buflen;
3261                 scmd->udcd_timeout = (ushort_t)dcd_io_time;
3262                 scmd->udcd_resid = 0ULL;
3263                 scmd->udcd_status = 0;
3264                 scmd->udcd_error_reg = 0;
3265                 scmd->udcd_status_reg = 0;
3266 
3267                 mutex_exit(DCD_MUTEX);
3268 
3269                 i = dcdioctl_cmd(dev, scmd, UIO_SYSSPACE, UIO_USERSPACE);
3270                 mutex_enter(DCD_MUTEX);
3271                 /*
3272                  * After return convert the status from scmd to
3273                  * dadkio_status
3274                  */
3275                 (void) dcd_translate(&(rwcmd32.status), scmd);
3276                 rwcmd32.status.resid = scmd->udcd_resid;
3277                 mutex_exit(DCD_MUTEX);
3278 
3279 #ifdef _MULTI_DATAMODEL
3280                 switch (ddi_model_convert_from(flag & FMODELS)) {
3281                 case DDI_MODEL_NONE: {
3282                         int counter;
3283                         rwcmd.status.status = rwcmd32.status.status;
3284                         rwcmd.status.resid  = rwcmd32.status.resid;
3285                         rwcmd.status.failed_blk_is_valid =
3286                             rwcmd32.status.failed_blk_is_valid;
3287                         rwcmd.status.failed_blk = rwcmd32.status.failed_blk;
3288                         rwcmd.status.fru_code_is_valid =
3289                             rwcmd32.status.fru_code_is_valid;
3290                         rwcmd.status.fru_code = rwcmd32.status.fru_code;
3291                         for (counter = 0;
3292                             counter < DADKIO_ERROR_INFO_LEN; counter++)
3293                                 rwcmd.status.add_error_info[counter] =
3294                                     rwcmd32.status.add_error_info[counter];
3295                         }
3296                         /* Copy out the result back to the user program */
3297                         if (ddi_copyout((caddr_t)&rwcmd, (caddr_t)arg,
3298                             sizeof (struct dadkio_rwcmd), flag)) {
3299                                 if (i != 0) {
3300                                         i = EFAULT;
3301                                 }
3302                         }
3303                         break;
3304                 case DDI_MODEL_ILP32:
3305                         /* Copy out the result back to the user program */
3306                         if (ddi_copyout((caddr_t)&rwcmd32, (caddr_t)arg,
3307                             sizeof (struct dadkio_rwcmd32), flag)) {
3308                                 if (i != 0) {
3309                                         i = EFAULT;
3310                                 }
3311                         }
3312                         break;
3313                 }
3314 #else
3315                 /* Copy out the result back to the user program  */
3316                 if (ddi_copyout((caddr_t)&rwcmd32, (caddr_t)arg,
3317                     sizeof (struct dadkio_rwcmd32), flag)) {
3318                         if (i != 0)
3319                                 i = EFAULT;
3320                 }
3321 #endif
3322                 return (i);
3323 
3324         case UDCDCMD:   {
3325 #ifdef  _MULTI_DATAMODEL
3326                 /*
3327                  * For use when a 32 bit app makes a call into a
3328                  * 64 bit ioctl
3329                  */
3330                 struct udcd_cmd32       udcd_cmd_32_for_64;
3331                 struct udcd_cmd32       *ucmd32 = &udcd_cmd_32_for_64;
3332                 model_t                 model;
3333 #endif /* _MULTI_DATAMODEL */
3334 
3335                 if (drv_priv(cred_p) != 0) {
3336                         return (EPERM);
3337                 }
3338 
3339                 scmd = (struct udcd_cmd *)data;
3340 
3341 #ifdef _MULTI_DATAMODEL
3342                 switch (model = ddi_model_convert_from(flag & FMODELS)) {
3343                 case DDI_MODEL_ILP32:
3344                         if (ddi_copyin((caddr_t)arg, ucmd32,
3345                             sizeof (struct udcd_cmd32), flag)) {
3346                                 return (EFAULT);
3347                         }
3348                         /*
3349                          * Convert the ILP32 uscsi data from the
3350                          * application to LP64 for internal use.
3351                          */
3352                         udcd_cmd32toudcd_cmd(ucmd32, scmd);
3353                         break;
3354                 case DDI_MODEL_NONE:
3355                         if (ddi_copyin((caddr_t)arg, scmd, sizeof (*scmd),
3356                             flag)) {
3357                                 return (EFAULT);
3358                         }
3359                         break;
3360                 }
3361 #else /* ! _MULTI_DATAMODEL */
3362                 if (ddi_copyin((caddr_t)arg, (caddr_t)scmd,
3363                     sizeof (*scmd), flag)) {
3364                         return (EFAULT);
3365                 }
3366 #endif /* ! _MULTI_DATAMODEL */
3367 
3368                 scmd->udcd_flags &= ~UDCD_NOINTR;
3369                 uioseg = (flag & FKIOCTL)? UIO_SYSSPACE: UIO_USERSPACE;
3370 
3371                 i = dcdioctl_cmd(dev, scmd, uioseg, uioseg);
3372 #ifdef _MULTI_DATAMODEL
3373                 switch (model) {
3374                 case DDI_MODEL_ILP32:
3375                         /*
3376                          * Convert back to ILP32 before copyout to the
3377                          * application
3378                          */
3379                         udcd_cmdtoudcd_cmd32(scmd, ucmd32);
3380                         if (ddi_copyout(ucmd32, (caddr_t)arg,
3381                             sizeof (*ucmd32), flag)) {
3382                                 if (i != 0)
3383                                         i = EFAULT;
3384                         }
3385                         break;
3386                 case DDI_MODEL_NONE:
3387                         if (ddi_copyout(scmd, (caddr_t)arg, sizeof (*scmd),
3388                             flag)) {
3389                                 if (i != 0)
3390                                         i = EFAULT;
3391                         }
3392                         break;
3393                 }
3394 #else /* ! _MULTI_DATAMODE */
3395                 if (ddi_copyout((caddr_t)scmd, (caddr_t)arg,
3396                     sizeof (*scmd), flag)) {
3397                         if (i != 0)
3398                                 i = EFAULT;
3399                 }
3400 #endif
3401                 return (i);
3402         }
3403         case DKIOCFLUSHWRITECACHE:      {
3404                 struct dk_callback *dkc = (struct dk_callback *)arg;
3405                 struct dcd_pkt *pkt;
3406                 struct buf *bp;
3407                 int is_sync = 1;
3408 
3409                 mutex_enter(DCD_MUTEX);
3410                 if (un->un_flush_not_supported ||
3411                     ! un->un_write_cache_enabled) {
3412                         i = un->un_flush_not_supported ? ENOTSUP : 0;
3413                         mutex_exit(DCD_MUTEX);
3414                         /*
3415                          * If a callback was requested: a callback will
3416                          * always be done if the caller saw the
3417                          * DKIOCFLUSHWRITECACHE ioctl return 0, and
3418                          * never done if the caller saw the ioctl return
3419                          * an error.
3420                          */
3421                         if ((flag & FKIOCTL) && dkc != NULL &&
3422                             dkc->dkc_callback != NULL) {
3423                                 (*dkc->dkc_callback)(dkc->dkc_cookie, i);
3424                                 /*
3425                                  * Did callback and reported error.
3426                                  * Since we did a callback, ioctl
3427                                  * should return 0.
3428                                  */
3429                                 i = 0;
3430                         }
3431                         return (i);
3432                 }
3433 
3434                 /*
3435                  * Get the special buffer
3436                  */
3437                 while (un->un_sbuf_busy) {
3438                         cv_wait(&un->un_sbuf_cv, DCD_MUTEX);
3439                 }
3440                 un->un_sbuf_busy = 1;
3441                 bp  = un->un_sbufp;
3442                 mutex_exit(DCD_MUTEX);
3443 
3444                 pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL,
3445                     NULL, (uint32_t)sizeof (struct dcd_cmd),
3446                     2, PP_LEN, PKT_CONSISTENT, SLEEP_FUNC, (caddr_t)un);
3447                 ASSERT(pkt != NULL);
3448 
3449                 makecommand(pkt, un->un_cmd_flags | FLAG_SILENT,
3450                     ATA_FLUSH_CACHE, 0, ADD_LBA_MODE, 0, NO_DATA_XFER, 0);
3451 
3452                 pkt->pkt_comp = dcdintr;
3453                 pkt->pkt_time = DCD_FLUSH_TIME;
3454                 PKT_SET_BP(pkt, bp);
3455 
3456                 bp->av_back = (struct buf *)pkt;
3457                 bp->b_forw = NULL;
3458                 bp->b_flags = B_BUSY;
3459                 bp->b_error = 0;
3460                 bp->b_edev = dev;
3461                 bp->b_dev = cmpdev(dev);
3462                 bp->b_bcount = 0;
3463                 bp->b_blkno = 0;
3464                 bp->b_un.b_addr = 0;
3465                 bp->b_iodone = NULL;
3466                 bp->b_list = NULL;
3467                 bp->b_private = NULL;
3468 
3469                 if ((flag & FKIOCTL) && dkc != NULL &&
3470                     dkc->dkc_callback != NULL) {
3471                         struct dk_callback *dkc2 = (struct dk_callback *)
3472                             kmem_zalloc(sizeof (*dkc2), KM_SLEEP);
3473                         bcopy(dkc, dkc2, sizeof (*dkc2));
3474 
3475                         bp->b_private = dkc2;
3476                         bp->b_iodone = dcdflushdone;
3477                         is_sync = 0;
3478                 }
3479 
3480                 (void) dcdstrategy(bp);
3481 
3482                 i = 0;
3483                 if (is_sync) {
3484                         i = biowait(bp);
3485                         (void) dcdflushdone(bp);
3486                 }
3487 
3488                 return (i);
3489         }
3490         default:
3491                 break;
3492         }
3493         return (ENOTTY);
3494 }
3495 
3496 
3497 static int
3498 dcdflushdone(struct buf *bp)
3499 {
3500         struct dcd_disk *un = ddi_get_soft_state(dcd_state,
3501             DCDUNIT(bp->b_edev));
3502         struct dcd_pkt *pkt = BP_PKT(bp);
3503         struct dk_callback *dkc = bp->b_private;
3504 
3505         ASSERT(un != NULL);
3506         ASSERT(bp == un->un_sbufp);
3507         ASSERT(pkt != NULL);
3508 
3509         dcd_destroy_pkt(pkt);
3510         bp->av_back = NO_PKT_ALLOCATED;
3511 
3512         if (dkc != NULL) {
3513                 ASSERT(bp->b_iodone != NULL);
3514                 (*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp));
3515                 kmem_free(dkc, sizeof (*dkc));
3516                 bp->b_iodone = NULL;
3517                 bp->b_private = NULL;
3518         }
3519 
3520         /*
3521          * Tell anybody who cares that the buffer is now free
3522          */
3523         mutex_enter(DCD_MUTEX);
3524         un->un_sbuf_busy = 0;
3525         cv_signal(&un->un_sbuf_cv);
3526         mutex_exit(DCD_MUTEX);
3527         return (0);
3528 }
3529 
3530 /*
3531  * dcdrunout:
3532  *      the callback function for resource allocation
3533  *
3534  * XXX it would be preferable that dcdrunout() scans the whole
3535  *      list for possible candidates for dcdstart(); this avoids
3536  *      that a bp at the head of the list whose request cannot be
3537  *      satisfied is retried again and again
3538  */
3539 /*ARGSUSED*/
3540 static int
3541 dcdrunout(caddr_t arg)
3542 {
3543         int serviced;
3544         struct dcd_disk *un;
3545         struct diskhd *dp;
3546 
3547         TRACE_1(TR_FAC_DADA, TR_DCDRUNOUT_START, "dcdrunout_start: arg 0x%p",
3548             arg);
3549         serviced = 1;
3550 
3551         un = (struct dcd_disk *)arg;
3552         dp = &un->un_utab;
3553 
3554         /*
3555          * We now support passing a structure to the callback
3556          * routine.
3557          */
3558         ASSERT(un != NULL);
3559         mutex_enter(DCD_MUTEX);
3560         if ((un->un_ncmds < un->un_throttle) && (dp->b_forw == NULL)) {
3561                 dcdstart(un);
3562         }
3563         if (un->un_state == DCD_STATE_RWAIT) {
3564                 serviced = 0;
3565         }
3566         mutex_exit(DCD_MUTEX);
3567         TRACE_1(TR_FAC_DADA, TR_DCDRUNOUT_END,
3568             "dcdrunout_end: serviced %d", serviced);
3569         return (serviced);
3570 }
3571 
3572 
3573 /*
3574  * This routine called to see whether unit is (still) there. Must not
3575  * be called when un->un_sbufp is in use, and must not be called with
3576  * an unattached disk. Soft state of disk is restored to what it was
3577  * upon entry- up to caller to set the correct state.
3578  *
3579  * We enter with the disk mutex held.
3580  */
3581 
3582 /* ARGSUSED0 */
3583 static int
3584 dcd_unit_ready(dev_t dev)
3585 {
3586 #ifndef lint
3587         auto struct udcd_cmd dcmd, *com = &dcmd;
3588         auto struct dcd_cmd cmdblk;
3589 #endif
3590         int error;
3591 #ifndef lint
3592         GET_SOFT_STATE(dev);
3593 #endif
3594 
3595         /*
3596          * Now that we protect the special buffer with
3597          * a mutex, we could probably do a mutex_tryenter
3598          * on it here and return failure if it were held...
3599          */
3600 
3601         error = 0;
3602         return (error);
3603 }
3604 
3605 /* ARGSUSED0 */
3606 int
3607 dcdioctl_cmd(dev_t devp, struct udcd_cmd *in, enum uio_seg cdbspace,
3608     enum uio_seg dataspace)
3609 {
3610 
3611         struct buf *bp;
3612         struct  udcd_cmd *scmd;
3613         struct dcd_pkt *pkt;
3614         int     err, rw;
3615         caddr_t cdb;
3616         int     flags = 0;
3617 
3618         GET_SOFT_STATE(devp);
3619 
3620 #ifdef lint
3621         part = part;
3622 #endif
3623 
3624         /*
3625          * Is this a request to reset the bus?
3626          * if so, we need to do reseting.
3627          */
3628 
3629         if (in->udcd_flags & UDCD_RESET) {
3630                 int flag = RESET_TARGET;
3631                 err = dcd_reset(ROUTE, flag) ? 0: EIO;
3632                 return (err);
3633         }
3634 
3635         scmd = in;
3636 
3637 
3638         /* Do some sanity checks */
3639         if (scmd->udcd_buflen <= 0) {
3640                 if (scmd->udcd_flags & (UDCD_READ | UDCD_WRITE)) {
3641                         return (EINVAL);
3642                 } else {
3643                         scmd->udcd_buflen = 0;
3644                 }
3645         }
3646 
3647         /* Make a copy of the dcd_cmd passed  */
3648         cdb = kmem_zalloc(sizeof (struct dcd_cmd), KM_SLEEP);
3649         if (cdbspace == UIO_SYSSPACE) {
3650                 flags |= FKIOCTL;
3651         }
3652 
3653         if (ddi_copyin((void *)scmd->udcd_cmd, cdb, sizeof (struct dcd_cmd),
3654             flags)) {
3655                 kmem_free(cdb, sizeof (struct dcd_cmd));
3656                 return (EFAULT);
3657         }
3658         scmd = (struct udcd_cmd *)kmem_alloc(sizeof (*scmd), KM_SLEEP);
3659         bcopy((caddr_t)in, (caddr_t)scmd, sizeof (*scmd));
3660         scmd->udcd_cmd = (struct dcd_cmd *)cdb;
3661         rw = (scmd->udcd_flags & UDCD_READ) ? B_READ: B_WRITE;
3662 
3663 
3664         /*
3665          * Get the special buffer
3666          */
3667 
3668         mutex_enter(DCD_MUTEX);
3669         while (un->un_sbuf_busy) {
3670                 if (cv_wait_sig(&un->un_sbuf_cv, DCD_MUTEX) == 0) {
3671                         kmem_free(scmd->udcd_cmd, sizeof (struct dcd_cmd));
3672                         kmem_free((caddr_t)scmd, sizeof (*scmd));
3673                         mutex_exit(DCD_MUTEX);
3674                         return (EINTR);
3675                 }
3676         }
3677 
3678         un->un_sbuf_busy = 1;
3679         bp  = un->un_sbufp;
3680         mutex_exit(DCD_MUTEX);
3681 
3682 
3683         /*
3684          * If we are going to do actual I/O, let physio do all the
3685          * things
3686          */
3687         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
3688             "dcdioctl_cmd : buflen %x\n", scmd->udcd_buflen);
3689 
3690         if (scmd->udcd_buflen) {
3691                 auto struct iovec aiov;
3692                 auto struct uio auio;
3693                 struct uio *uio = &auio;
3694 
3695                 bzero((caddr_t)&auio, sizeof (struct uio));
3696                 bzero((caddr_t)&aiov, sizeof (struct iovec));
3697 
3698                 aiov.iov_base = scmd->udcd_bufaddr;
3699                 aiov.iov_len = scmd->udcd_buflen;
3700 
3701                 uio->uio_iov = &aiov;
3702                 uio->uio_iovcnt = 1;
3703                 uio->uio_resid = scmd->udcd_buflen;
3704                 uio->uio_segflg = dataspace;
3705 
3706                 /*
3707                  * Let physio do the rest...
3708                  */
3709                 bp->av_back = NO_PKT_ALLOCATED;
3710                 bp->b_forw = (struct buf *)scmd;
3711                 err = physio(dcdstrategy, bp, devp, rw, dcdudcdmin, uio);
3712         } else {
3713                 /*
3714                  * We have to mimic what physio would do here.
3715                  */
3716                 bp->av_back = NO_PKT_ALLOCATED;
3717                 bp->b_forw = (struct buf *)scmd;
3718                 bp->b_flags = B_BUSY | rw;
3719                 bp->b_edev = devp;
3720                 bp->b_dev = cmpdev(devp);
3721                 bp->b_bcount = bp->b_blkno = 0;
3722                 (void) dcdstrategy(bp);
3723                 err = biowait(bp);
3724         }
3725 
3726 done:
3727         if ((pkt = BP_PKT(bp)) != NULL) {
3728                 bp->av_back = NO_PKT_ALLOCATED;
3729                 /* we need to update the completion status of udcd command */
3730                 in->udcd_resid = bp->b_resid;
3731                 in->udcd_status_reg = SCBP_C(pkt);
3732                 /* XXX: we need to give error_reg also */
3733                 dcd_destroy_pkt(pkt);
3734         }
3735         /*
3736          * Tell anybody who cares that the buffer is now free
3737          */
3738         mutex_enter(DCD_MUTEX);
3739         un->un_sbuf_busy = 0;
3740         cv_signal(&un->un_sbuf_cv);
3741         mutex_exit(DCD_MUTEX);
3742 
3743         kmem_free(scmd->udcd_cmd, sizeof (struct dcd_cmd));
3744         kmem_free((caddr_t)scmd, sizeof (*scmd));
3745         return (err);
3746 }
3747 
3748 static void
3749 dcdudcdmin(struct buf *bp)
3750 {
3751 
3752 #ifdef lint
3753         bp = bp;
3754 #endif
3755 
3756 }
3757 
3758 /*
3759  * restart a cmd from timeout() context
3760  *
3761  * the cmd is expected to be in un_utab.b_forw. If this pointer is non-zero
3762  * a restart timeout request has been issued and no new timeouts should
3763  * be requested. b_forw is reset when the cmd eventually completes in
3764  * dcddone_and_mutex_exit()
3765  */
3766 void
3767 dcdrestart(void *arg)
3768 {
3769         struct dcd_disk *un = (struct dcd_disk *)arg;
3770         struct buf *bp;
3771         int status;
3772 
3773         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdrestart\n");
3774 
3775         mutex_enter(DCD_MUTEX);
3776         bp = un->un_utab.b_forw;
3777         if (bp) {
3778                 un->un_ncmds++;
3779                 DCD_DO_KSTATS(un, kstat_waitq_to_runq, bp);
3780         }
3781 
3782 
3783         if (bp) {
3784                 struct dcd_pkt *pkt = BP_PKT(bp);
3785 
3786                 mutex_exit(DCD_MUTEX);
3787 
3788                 pkt->pkt_flags = 0;
3789 
3790                 if ((status = dcd_transport(pkt)) != TRAN_ACCEPT) {
3791                         mutex_enter(DCD_MUTEX);
3792                         DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
3793                         un->un_ncmds--;
3794                         if (status == TRAN_BUSY) {
3795                                 /* XXX : To be checked */
3796                                 /*
3797                                  * if (un->un_throttle > 1) {
3798                                  *      ASSERT(un->un_ncmds >= 0);
3799                                  *      un->un_throttle = un->un_ncmds;
3800                                  * }
3801                                  */
3802                                 un->un_reissued_timeid =
3803                                     timeout(dcdrestart, (caddr_t)un,
3804                                     DCD_BSY_TIMEOUT/500);
3805                                 mutex_exit(DCD_MUTEX);
3806                                 return;
3807                         }
3808                         DCD_DO_ERRSTATS(un, dcd_transerrs);
3809                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
3810                             "dcdrestart transport failed (%x)\n", status);
3811                         bp->b_resid = bp->b_bcount;
3812                         SET_BP_ERROR(bp, EIO);
3813 
3814                         DCD_DO_KSTATS(un, kstat_waitq_exit, bp);
3815                         un->un_reissued_timeid = 0L;
3816                         dcddone_and_mutex_exit(un, bp);
3817                         return;
3818                 }
3819                 mutex_enter(DCD_MUTEX);
3820         }
3821         un->un_reissued_timeid = 0L;
3822         mutex_exit(DCD_MUTEX);
3823         DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdrestart done\n");
3824 }
3825 
3826 /*
3827  * This routine gets called to reset the throttle to its saved
3828  * value wheneven we lower the throttle.
3829  */
3830 void
3831 dcd_reset_throttle(caddr_t arg)
3832 {
3833         struct dcd_disk *un = (struct dcd_disk *)arg;
3834         struct diskhd *dp;
3835 
3836         mutex_enter(DCD_MUTEX);
3837         dp = &un->un_utab;
3838 
3839         /*
3840          * start any commands that didn't start while throttling.
3841          */
3842         if (dp->b_actf && (un->un_ncmds < un->un_throttle) &&
3843             (dp->b_forw == NULL)) {
3844                 dcdstart(un);
3845         }
3846         mutex_exit(DCD_MUTEX);
3847 }
3848 
3849 
3850 /*
3851  * This routine handles the case when a TRAN_BUSY is
3852  * returned by HBA.
3853  *
3854  * If there are some commands already in the transport, the
3855  * bp can be put back on queue and it will
3856  * be retried when the queue is emptied after command
3857  * completes. But if there is no command in the tranport
3858  * and it still return busy, we have to retry the command
3859  * after some time like 10ms.
3860  */
3861 /* ARGSUSED0 */
3862 static void
3863 dcd_handle_tran_busy(struct buf *bp, struct diskhd *dp, struct dcd_disk *un)
3864 {
3865         ASSERT(mutex_owned(DCD_MUTEX));
3866 
3867 
3868         if (dp->b_forw == NULL || dp->b_forw == bp) {
3869                 dp->b_forw = bp;
3870         } else if (dp->b_forw != bp) {
3871                 bp->b_actf = dp->b_actf;
3872                 dp->b_actf = bp;
3873 
3874         }
3875         if (!un->un_reissued_timeid) {
3876                 un->un_reissued_timeid =
3877                     timeout(dcdrestart, (caddr_t)un, DCD_BSY_TIMEOUT/500);
3878         }
3879 }
3880 
3881 static int
3882 dcd_write_deviceid(struct dcd_disk *un)
3883 {
3884 
3885         int     status;
3886         diskaddr_t blk;
3887         struct udcd_cmd ucmd;
3888         struct dcd_cmd cdb;
3889         struct dk_devid *dkdevid;
3890         uint_t *ip, chksum;
3891         int     i;
3892         dev_t   dev;
3893 
3894         mutex_exit(DCD_MUTEX);
3895         if (cmlb_get_devid_block(un->un_dklbhandle, &blk, 0)) {
3896                 mutex_enter(DCD_MUTEX);
3897                 return (EINVAL);
3898         }
3899         mutex_enter(DCD_MUTEX);
3900 
3901         /* Allocate the buffer */
3902         dkdevid = kmem_zalloc(un->un_secsize, KM_SLEEP);
3903 
3904         /* Fill in the revision */
3905         dkdevid->dkd_rev_hi = DK_DEVID_REV_MSB;
3906         dkdevid->dkd_rev_lo = DK_DEVID_REV_LSB;
3907 
3908         /* Copy in the device id */
3909         bcopy(un->un_devid, &dkdevid->dkd_devid,
3910             ddi_devid_sizeof(un->un_devid));
3911 
3912         /* Calculate the chksum */
3913         chksum = 0;
3914         ip = (uint_t *)dkdevid;
3915         for (i = 0; i < ((un->un_secsize - sizeof (int))/sizeof (int)); i++)
3916                 chksum ^= ip[i];
3917 
3918         /* Fill in the checksum */
3919         DKD_FORMCHKSUM(chksum, dkdevid);
3920 
3921         (void) bzero((caddr_t)&ucmd, sizeof (ucmd));
3922         (void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd));
3923 
3924         if ((un->un_dp->options & DMA_SUPPORTTED) == DMA_SUPPORTTED) {
3925                 cdb.cmd = ATA_WRITE_DMA;
3926         } else {
3927                 if (un->un_dp->options & BLOCK_MODE)
3928                         cdb.cmd = ATA_WRITE_MULTIPLE;
3929                 else
3930                         cdb.cmd = ATA_WRITE;
3931         }
3932         cdb.size = un->un_secsize;
3933         cdb.sector_num.lba_num = blk;
3934         cdb.address_mode = ADD_LBA_MODE;
3935         cdb.direction = DATA_WRITE;
3936 
3937         ucmd.udcd_flags = UDCD_WRITE;
3938         ucmd.udcd_cmd =  &cdb;
3939         ucmd.udcd_bufaddr = (caddr_t)dkdevid;
3940         ucmd.udcd_buflen = un->un_secsize;
3941         ucmd.udcd_flags |= UDCD_SILENT;
3942         dev = makedevice(ddi_driver_major(DCD_DEVINFO),
3943             ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT);
3944         mutex_exit(DCD_MUTEX);
3945         status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE);
3946         mutex_enter(DCD_MUTEX);
3947 
3948         kmem_free(dkdevid, un->un_secsize);
3949         return (status);
3950 }
3951 
3952 static int
3953 dcd_read_deviceid(struct dcd_disk *un)
3954 {
3955         int status;
3956         diskaddr_t blk;
3957         struct udcd_cmd ucmd;
3958         struct dcd_cmd cdb;
3959         struct dk_devid *dkdevid;
3960         uint_t *ip;
3961         int chksum;
3962         int i, sz;
3963         dev_t dev;
3964 
3965         mutex_exit(DCD_MUTEX);
3966         if (cmlb_get_devid_block(un->un_dklbhandle, &blk, 0)) {
3967                 mutex_enter(DCD_MUTEX);
3968                 return (EINVAL);
3969         }
3970         mutex_enter(DCD_MUTEX);
3971 
3972         dkdevid = kmem_alloc(un->un_secsize, KM_SLEEP);
3973 
3974         (void) bzero((caddr_t)&ucmd, sizeof (ucmd));
3975         (void) bzero((caddr_t)&cdb, sizeof (cdb));
3976 
3977         if ((un->un_dp->options & DMA_SUPPORTTED) == DMA_SUPPORTTED) {
3978                 cdb.cmd = ATA_READ_DMA;
3979         } else {
3980                 if (un->un_dp->options & BLOCK_MODE)
3981                         cdb.cmd = ATA_READ_MULTIPLE;
3982                 else
3983                         cdb.cmd = ATA_READ;
3984         }
3985         cdb.size = un->un_secsize;
3986         cdb.sector_num.lba_num = blk;
3987         cdb.address_mode = ADD_LBA_MODE;
3988         cdb.direction = DATA_READ;
3989 
3990         ucmd.udcd_flags = UDCD_READ;
3991         ucmd.udcd_cmd =  &cdb;
3992         ucmd.udcd_bufaddr = (caddr_t)dkdevid;
3993         ucmd.udcd_buflen = un->un_secsize;
3994         ucmd.udcd_flags |= UDCD_SILENT;
3995         dev = makedevice(ddi_driver_major(DCD_DEVINFO),
3996             ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT);
3997         mutex_exit(DCD_MUTEX);
3998         status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE);
3999         mutex_enter(DCD_MUTEX);
4000 
4001         if (status != 0) {
4002                 kmem_free((caddr_t)dkdevid, un->un_secsize);
4003                 return (status);
4004         }
4005 
4006         /* Validate the revision */
4007 
4008         if ((dkdevid->dkd_rev_hi != DK_DEVID_REV_MSB) ||
4009             (dkdevid->dkd_rev_lo != DK_DEVID_REV_LSB)) {
4010                 kmem_free((caddr_t)dkdevid, un->un_secsize);
4011                 return (EINVAL);
4012         }
4013 
4014         /* Calculate the checksum */
4015         chksum = 0;
4016         ip = (uint_t *)dkdevid;
4017         for (i = 0; i < ((un->un_secsize - sizeof (int))/sizeof (int)); i++)
4018                 chksum ^= ip[i];
4019 
4020         /* Compare the checksums */
4021 
4022         if (DKD_GETCHKSUM(dkdevid) != chksum) {
4023                 kmem_free((caddr_t)dkdevid, un->un_secsize);
4024                 return (EINVAL);
4025         }
4026 
4027         /* VAlidate the device id */
4028         if (ddi_devid_valid((ddi_devid_t)&dkdevid->dkd_devid) != DDI_SUCCESS) {
4029                 kmem_free((caddr_t)dkdevid, un->un_secsize);
4030                 return (EINVAL);
4031         }
4032 
4033         /* return a copy of the device id */
4034         sz = ddi_devid_sizeof((ddi_devid_t)&dkdevid->dkd_devid);
4035         un->un_devid = (ddi_devid_t)kmem_alloc(sz, KM_SLEEP);
4036         bcopy(&dkdevid->dkd_devid, un->un_devid, sz);
4037         kmem_free((caddr_t)dkdevid, un->un_secsize);
4038 
4039         return (0);
4040 }
4041 
4042 /*
4043  * Return the device id for the device.
4044  * 1. If the device ID exists then just return it - nothing to do in that case.
4045  * 2. Build one from the drives model number and serial number.
4046  * 3. If there is a problem in building it from serial/model #, then try
4047  * to read it from the acyl region of the disk.
4048  * Note: If this function is unable to return a valid ID then the calling
4049  * point will invoke the routine to create a fabricated ID ans stor it on the
4050  * acyl region of the disk.
4051  */
4052 static ddi_devid_t
4053 dcd_get_devid(struct dcd_disk *un)
4054 {
4055         int             rc;
4056 
4057         /* If already registered, return that value */
4058         if (un->un_devid != NULL)
4059                 return (un->un_devid);
4060 
4061         /* Build a devid from model and serial number, if present */
4062         rc = dcd_make_devid_from_serial(un);
4063 
4064         if (rc != DDI_SUCCESS) {
4065                 /* Read the devid from the disk. */
4066                 if (dcd_read_deviceid(un))
4067                         return (NULL);
4068         }
4069 
4070         (void) ddi_devid_register(DCD_DEVINFO, un->un_devid);
4071         return (un->un_devid);
4072 }
4073 
4074 
4075 static ddi_devid_t
4076 dcd_create_devid(struct dcd_disk *un)
4077 {
4078         if (ddi_devid_init(DCD_DEVINFO, DEVID_FAB, 0, NULL, (ddi_devid_t *)
4079             &un->un_devid) == DDI_FAILURE)
4080                 return (NULL);
4081 
4082         if (dcd_write_deviceid(un)) {
4083                 ddi_devid_free(un->un_devid);
4084                 un->un_devid = NULL;
4085                 return (NULL);
4086         }
4087 
4088         (void) ddi_devid_register(DCD_DEVINFO, un->un_devid);
4089         return (un->un_devid);
4090 }
4091 
4092 /*
4093  * Build a devid from the model and serial number, if present
4094  * Return DDI_SUCCESS or DDI_FAILURE.
4095  */
4096 static int
4097 dcd_make_devid_from_serial(struct dcd_disk *un)
4098 {
4099         int     rc = DDI_SUCCESS;
4100         char    *hwid;
4101         char    *model;
4102         int     model_len;
4103         char    *serno;
4104         int     serno_len;
4105         int     total_len;
4106 
4107         /* initialize the model and serial number information */
4108         model = un->un_dcd->dcd_ident->dcd_model;
4109         model_len = DCD_MODEL_NUMBER_LENGTH;
4110         serno = un->un_dcd->dcd_ident->dcd_drvser;
4111         serno_len = DCD_SERIAL_NUMBER_LENGTH;
4112 
4113         /* Verify the model and serial number */
4114         dcd_validate_model_serial(model, &model_len, model_len);
4115         if (model_len == 0) {
4116                 rc = DDI_FAILURE;
4117                 goto out;
4118         }
4119         dcd_validate_model_serial(serno, &serno_len, serno_len);
4120         if (serno_len == 0) {
4121                 rc = DDI_FAILURE;
4122                 goto out;
4123         }
4124 
4125         /*
4126          * The device ID will be concatenation of the model number,
4127          * the '=' separator, the serial number. Allocate
4128          * the string and concatenate the components.
4129          */
4130         total_len = model_len + 1 + serno_len;
4131         hwid = kmem_alloc(total_len, KM_SLEEP);
4132         bcopy((caddr_t)model, (caddr_t)hwid, model_len);
4133         bcopy((caddr_t)"=", (caddr_t)&hwid[model_len], 1);
4134         bcopy((caddr_t)serno, (caddr_t)&hwid[model_len + 1], serno_len);
4135 
4136         /* Initialize the device ID, trailing NULL not included */
4137         rc = ddi_devid_init(DCD_DEVINFO, DEVID_ATA_SERIAL, total_len,
4138             hwid, (ddi_devid_t *)&un->un_devid);
4139 
4140         /* Free the allocated string */
4141         kmem_free(hwid, total_len);
4142 
4143 out:    return (rc);
4144 }
4145 
4146 /*
4147  * Test for a valid model or serial number. Assume that a valid representation
4148  * contains at least one character that is neither a space, 0 digit, or NULL.
4149  * Trim trailing blanks and NULLS from returned length.
4150  */
4151 static void
4152 dcd_validate_model_serial(char *str, int *retlen, int totallen)
4153 {
4154         char            ch;
4155         boolean_t       ret = B_FALSE;
4156         int             i;
4157         int             tb;
4158 
4159         for (i = 0, tb = 0; i < totallen; i++) {
4160                 ch = *str++;
4161                 if ((ch != ' ') && (ch != '\0') && (ch != '0'))
4162                         ret = B_TRUE;
4163                 if ((ch == ' ') || (ch == '\0'))
4164                         tb++;
4165                 else
4166                         tb = 0;
4167         }
4168 
4169         if (ret == B_TRUE) {
4170                 /* Atleast one non 0 or blank character. */
4171                 *retlen = totallen - tb;
4172         } else {
4173                 *retlen = 0;
4174         }
4175 }
4176 
4177 #ifndef lint
4178 void
4179 clean_print(dev_info_t *dev, char *label, uint_t level,
4180         char *title, char *data, int len)
4181 {
4182         int     i;
4183         char    buf[256];
4184 
4185         (void) sprintf(buf, "%s:", title);
4186         for (i = 0; i < len; i++) {
4187                 (void) sprintf(&buf[strlen(buf)], "0x%x ", (data[i] & 0xff));
4188         }
4189         (void) sprintf(&buf[strlen(buf)], "\n");
4190 
4191         dcd_log(dev, label, level, "%s", buf);
4192 }
4193 #endif /* Not lint */
4194 
4195 #ifndef lint
4196 /*
4197  * Print a piece of inquiry data- cleaned up for non-printable characters
4198  * and stopping at the first space character after the beginning of the
4199  * passed string;
4200  */
4201 
4202 void
4203 inq_fill(char *p, int l, char *s)
4204 {
4205         unsigned i = 0;
4206         char c;
4207 
4208         while (i++ < l) {
4209                 if ((c = *p++) < ' ' || c >= 0177) {
4210                         c = '*';
4211                 } else if (i != 1 && c == ' ') {
4212                         break;
4213                 }
4214                 *s++ = c;
4215         }
4216         *s++ = 0;
4217 }
4218 #endif /* Not lint */
4219 
4220 char *
4221 dcd_sname(uchar_t status)
4222 {
4223         switch (status & STATUS_ATA_MASK) {
4224         case STATUS_GOOD:
4225                 return ("good status");
4226 
4227         case STATUS_ATA_BUSY:
4228                 return ("busy");
4229 
4230         default:
4231                 return ("<unknown status>");
4232         }
4233 }
4234 
4235 /* ARGSUSED0 */
4236 char *
4237 dcd_rname(int reason)
4238 {
4239         static char *rnames[] = {
4240                 "cmplt",
4241                 "incomplete",
4242                 "dma_derr",
4243                 "tran_err",
4244                 "reset",
4245                 "aborted",
4246                 "timeout",
4247                 "data_ovr",
4248         };
4249         if (reason > CMD_DATA_OVR) {
4250                 return ("<unknown reason>");
4251         } else {
4252                 return (rnames[reason]);
4253         }
4254 }
4255 
4256 
4257 
4258 /* ARGSUSED0 */
4259 int
4260 dcd_check_wp(dev_t dev)
4261 {
4262 
4263         return (0);
4264 }
4265 
4266 /*
4267  * Create device error kstats
4268  */
4269 static int
4270 dcd_create_errstats(struct dcd_disk *un, int instance)
4271 {
4272 
4273         char kstatname[KSTAT_STRLEN];
4274 
4275         if (un->un_errstats == (kstat_t *)0) {
4276                 (void) sprintf(kstatname, "dad%d,error", instance);
4277                 un->un_errstats = kstat_create("daderror", instance, kstatname,
4278                     "device_error", KSTAT_TYPE_NAMED,
4279                     sizeof (struct dcd_errstats)/ sizeof (kstat_named_t),
4280                     KSTAT_FLAG_PERSISTENT);
4281 
4282                 if (un->un_errstats) {
4283                         struct dcd_errstats *dtp;
4284 
4285                         dtp = (struct dcd_errstats *)un->un_errstats->ks_data;
4286                         kstat_named_init(&dtp->dcd_softerrs, "Soft Errors",
4287                             KSTAT_DATA_UINT32);
4288                         kstat_named_init(&dtp->dcd_harderrs, "Hard Errors",
4289                             KSTAT_DATA_UINT32);
4290                         kstat_named_init(&dtp->dcd_transerrs,
4291                             "Transport Errors", KSTAT_DATA_UINT32);
4292                         kstat_named_init(&dtp->dcd_model, "Model",
4293                             KSTAT_DATA_CHAR);
4294                         kstat_named_init(&dtp->dcd_revision, "Revision",
4295                             KSTAT_DATA_CHAR);
4296                         kstat_named_init(&dtp->dcd_serial, "Serial No",
4297                             KSTAT_DATA_CHAR);
4298                         kstat_named_init(&dtp->dcd_capacity, "Size",
4299                             KSTAT_DATA_ULONGLONG);
4300                         kstat_named_init(&dtp->dcd_rq_media_err, "Media Error",
4301                             KSTAT_DATA_UINT32);
4302                         kstat_named_init(&dtp->dcd_rq_ntrdy_err,
4303                             "Device Not Ready", KSTAT_DATA_UINT32);
4304                         kstat_named_init(&dtp->dcd_rq_nodev_err, " No Device",
4305                             KSTAT_DATA_UINT32);
4306                         kstat_named_init(&dtp->dcd_rq_recov_err, "Recoverable",
4307                             KSTAT_DATA_UINT32);
4308                         kstat_named_init(&dtp->dcd_rq_illrq_err,
4309                             "Illegal Request", KSTAT_DATA_UINT32);
4310 
4311                         un->un_errstats->ks_private = un;
4312                         un->un_errstats->ks_update = nulldev;
4313                         kstat_install(un->un_errstats);
4314 
4315                         (void) strncpy(&dtp->dcd_model.value.c[0],
4316                             un->un_dcd->dcd_ident->dcd_model, 16);
4317                         (void) strncpy(&dtp->dcd_serial.value.c[0],
4318                             un->un_dcd->dcd_ident->dcd_drvser, 16);
4319                         (void) strncpy(&dtp->dcd_revision.value.c[0],
4320                             un->un_dcd->dcd_ident->dcd_fw, 8);
4321                         dtp->dcd_capacity.value.ui64 =
4322                             (uint64_t)((uint64_t)un->un_diskcapacity *
4323                             (uint64_t)un->un_lbasize);
4324                 }
4325         }
4326         return (0);
4327 }
4328 
4329 
4330 /*
4331  * This has been moved from DADA layer as this does not do anything other than
4332  * retrying the command when it is busy or it does not complete
4333  */
4334 int
4335 dcd_poll(struct dcd_pkt *pkt)
4336 {
4337         int     busy_count, rval = -1, savef;
4338         clock_t savet;
4339         void    (*savec)();
4340 
4341 
4342         /*
4343          * Save old flags
4344          */
4345         savef = pkt->pkt_flags;
4346         savec = pkt->pkt_comp;
4347         savet = pkt->pkt_time;
4348 
4349         pkt->pkt_flags |= FLAG_NOINTR;
4350 
4351 
4352         /*
4353          * Set the Pkt_comp to NULL
4354          */
4355 
4356         pkt->pkt_comp = 0;
4357 
4358         /*
4359          * Set the Pkt time for the polled command
4360          */
4361         if (pkt->pkt_time == 0) {
4362                 pkt->pkt_time = DCD_POLL_TIMEOUT;
4363         }
4364 
4365 
4366         /* Now transport the command */
4367         for (busy_count = 0; busy_count < dcd_poll_busycnt; busy_count++) {
4368                 if ((rval = dcd_transport(pkt)) == TRAN_ACCEPT) {
4369                         if (pkt->pkt_reason == CMD_INCOMPLETE &&
4370                             pkt->pkt_state == 0) {
4371                                 delay(100);
4372                         } else if (pkt->pkt_reason  == CMD_CMPLT) {
4373                                 rval = 0;
4374                                 break;
4375                         }
4376                 }
4377                 if (rval == TRAN_BUSY)  {
4378                         delay(100);
4379                         continue;
4380                 }
4381         }
4382 
4383         pkt->pkt_flags = savef;
4384         pkt->pkt_comp = savec;
4385         pkt->pkt_time = savet;
4386         return (rval);
4387 }
4388 
4389 
4390 void
4391 dcd_translate(struct dadkio_status32 *statp, struct udcd_cmd *cmdp)
4392 {
4393         if (cmdp->udcd_status_reg & STATUS_ATA_BUSY)
4394                 statp->status = DADKIO_STAT_NOT_READY;
4395         else if (cmdp->udcd_status_reg & STATUS_ATA_DWF)
4396                 statp->status = DADKIO_STAT_HARDWARE_ERROR;
4397         else if (cmdp->udcd_status_reg & STATUS_ATA_CORR)
4398                 statp->status = DADKIO_STAT_SOFT_ERROR;
4399         else if (cmdp->udcd_status_reg & STATUS_ATA_ERR) {
4400                 /*
4401                  * The error register is valid only when BSY and DRQ not set
4402                  * Assumed that HBA has checked this before it gives the data
4403                  */
4404                 if (cmdp->udcd_error_reg & ERR_AMNF)
4405                         statp->status = DADKIO_STAT_NOT_FORMATTED;
4406                 else if (cmdp->udcd_error_reg & ERR_TKONF)
4407                         statp->status = DADKIO_STAT_NOT_FORMATTED;
4408                 else if (cmdp->udcd_error_reg & ERR_ABORT)
4409                         statp->status = DADKIO_STAT_ILLEGAL_REQUEST;
4410                 else if (cmdp->udcd_error_reg & ERR_IDNF)
4411                         statp->status = DADKIO_STAT_NOT_FORMATTED;
4412                 else if (cmdp->udcd_error_reg & ERR_UNC)
4413                         statp->status = DADKIO_STAT_BUS_ERROR;
4414                 else if (cmdp->udcd_error_reg & ERR_BBK)
4415                         statp->status = DADKIO_STAT_MEDIUM_ERROR;
4416         } else
4417                 statp->status = DADKIO_STAT_NO_ERROR;
4418 }
4419 
4420 static void
4421 dcd_flush_cache(struct dcd_disk *un)
4422 {
4423         struct dcd_pkt *pkt;
4424         int retry_count;
4425 
4426 
4427         if ((pkt = dcd_init_pkt(ROUTE, NULL, NULL,
4428             (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN,
4429             PKT_CONSISTENT, NULL_FUNC, NULL)) == NULL) {
4430                 return;
4431         }
4432 
4433         makecommand(pkt, 0, ATA_FLUSH_CACHE, 0, ADD_LBA_MODE, 0,
4434             NO_DATA_XFER, 0);
4435 
4436         /*
4437          * Send the command. There are chances it might fail on some
4438          * disks since it is not a mandatory command as per ata-4. Try
4439          * 3 times if it fails. The retry count has been randomly selected.
4440          * There is a need for retry since as per the spec FLUSH CACHE can fail
4441          * as a result of unrecoverable error encountered during execution
4442          * of writing data and subsequent command should continue flushing
4443          * cache.
4444          */
4445         for (retry_count = 0; retry_count < 3; retry_count++) {
4446                 /*
4447                  * Set the packet fields.
4448                  */
4449                 pkt->pkt_comp = 0;
4450                 pkt->pkt_time = DCD_POLL_TIMEOUT;
4451                 pkt->pkt_flags |= FLAG_FORCENOINTR;
4452                 pkt->pkt_flags |= FLAG_NOINTR;
4453                 if (dcd_transport(pkt) == TRAN_ACCEPT) {
4454                         if (pkt->pkt_reason  == CMD_CMPLT) {
4455                                 break;
4456                         }
4457                 }
4458                 /*
4459                  * Note the wait time value of 100ms is same as in the
4460                  * dcd_poll routine.
4461                  */
4462                 drv_usecwait(1000000);
4463         }
4464         (void) dcd_destroy_pkt(pkt);
4465 }
4466 
4467 static int
4468 dcd_send_lb_rw_cmd(dev_info_t *devi, void *bufaddr,
4469     diskaddr_t start_block, size_t reqlength, uchar_t cmd)
4470 {
4471         struct dcd_pkt *pkt;
4472         struct buf *bp;
4473         diskaddr_t real_addr = start_block;
4474         size_t buffer_size = reqlength;
4475         uchar_t command, tmp;
4476         int i, rval = 0;
4477         struct dcd_disk *un;
4478 
4479         un = ddi_get_soft_state(dcd_state, ddi_get_instance(devi));
4480         if (un == NULL)
4481                 return (ENXIO);
4482 
4483         bp = dcd_alloc_consistent_buf(ROUTE, (struct buf *)NULL,
4484             buffer_size, B_READ, NULL_FUNC, NULL);
4485         if (!bp) {
4486                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
4487                     "no bp for disk label\n");
4488                 return (ENOMEM);
4489         }
4490 
4491         pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL,
4492             bp, (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN,
4493             PKT_CONSISTENT, NULL_FUNC, NULL);
4494 
4495         if (!pkt) {
4496                 dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
4497                     "no memory for disk label\n");
4498                 dcd_free_consistent_buf(bp);
4499                 return (ENOMEM);
4500         }
4501 
4502         if (cmd == TG_READ) {
4503                 bzero(bp->b_un.b_addr, buffer_size);
4504                 tmp = DATA_READ;
4505         } else {
4506                 bcopy((caddr_t)bufaddr, bp->b_un.b_addr, buffer_size);
4507                 tmp = DATA_WRITE;
4508         }
4509 
4510         mutex_enter(DCD_MUTEX);
4511         if ((un->un_dp->options & DMA_SUPPORTTED) == DMA_SUPPORTTED) {
4512                 if (cmd == TG_READ) {
4513                         command = ATA_READ_DMA;
4514                 } else {
4515                         command = ATA_WRITE_DMA;
4516                 }
4517         } else {
4518                 if (cmd == TG_READ) {
4519                         if (un->un_dp->options & BLOCK_MODE)
4520                                 command = ATA_READ_MULTIPLE;
4521                         else
4522                                 command = ATA_READ;
4523                 } else {
4524                         if (un->un_dp->options & BLOCK_MODE)
4525                                 command = ATA_READ_MULTIPLE;
4526                         else
4527                                 command = ATA_WRITE;
4528                 }
4529         }
4530         mutex_exit(DCD_MUTEX);
4531         (void) makecommand(pkt, 0, command, real_addr, ADD_LBA_MODE,
4532             buffer_size, tmp, 0);
4533 
4534         for (i = 0; i < 3; i++) {
4535                 if (dcd_poll(pkt) || SCBP_C(pkt) != STATUS_GOOD ||
4536                     (pkt->pkt_state & STATE_XFERRED_DATA) == 0 ||
4537                     (pkt->pkt_resid != 0)) {
4538                         DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
4539                             "Status %x, state %x, resid %lx\n",
4540                             SCBP_C(pkt), pkt->pkt_state, pkt->pkt_resid);
4541                         rval = EIO;
4542                 } else {
4543                         break;
4544                 }
4545         }
4546 
4547         if (rval != 0) {
4548                 dcd_destroy_pkt(pkt);
4549                 dcd_free_consistent_buf(bp);
4550                 return (EIO);
4551         }
4552 
4553         if (cmd == TG_READ) {
4554                 bcopy(bp->b_un.b_addr, bufaddr, reqlength);
4555                 rval = 0;
4556         }
4557 
4558         dcd_destroy_pkt(pkt);
4559         dcd_free_consistent_buf(bp);
4560         return (rval);
4561 }
4562 
4563 static int dcd_compute_dk_capacity(struct dcd_device *devp,
4564     diskaddr_t *capacity)
4565 {
4566         diskaddr_t cap;
4567         diskaddr_t no_of_lbasec;
4568 
4569         cap = devp->dcd_ident->dcd_fixcyls *
4570             devp->dcd_ident->dcd_heads *
4571             devp->dcd_ident->dcd_sectors;
4572         no_of_lbasec = devp->dcd_ident->dcd_addrsec[1];
4573         no_of_lbasec = no_of_lbasec << 16;
4574         no_of_lbasec = no_of_lbasec | devp->dcd_ident->dcd_addrsec[0];
4575 
4576         if (no_of_lbasec > cap) {
4577                 cap = no_of_lbasec;
4578         }
4579 
4580         if (cap != ((uint32_t)-1))
4581                 *capacity = cap;
4582         else
4583                 return (EINVAL);
4584         return (0);
4585 }
4586 
4587 /*ARGSUSED5*/
4588 static int
4589 dcd_lb_rdwr(dev_info_t *devi, uchar_t cmd, void *bufaddr,
4590     diskaddr_t start_block, size_t reqlength, void *tg_cookie)
4591 {
4592         if (cmd != TG_READ && cmd != TG_WRITE)
4593                 return (EINVAL);
4594 
4595         return (dcd_send_lb_rw_cmd(devi, bufaddr, start_block,
4596             reqlength, cmd));
4597 }
4598 
4599 static int
4600 dcd_lb_getphygeom(dev_info_t *devi, cmlb_geom_t *phygeomp)
4601 {
4602         struct dcd_device *devp;
4603         uint32_t no_of_lbasec, capacity, calculated_cylinders;
4604 
4605         devp = ddi_get_driver_private(devi);
4606 
4607         if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
4608                 if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
4609                         phygeomp->g_ncyl = devp->dcd_ident->dcd_fixcyls - 2;
4610                         phygeomp->g_acyl = 2;
4611                         phygeomp->g_nhead = devp->dcd_ident->dcd_heads;
4612                         phygeomp->g_nsect = devp->dcd_ident->dcd_sectors;
4613 
4614                         no_of_lbasec = devp->dcd_ident->dcd_addrsec[1];
4615                         no_of_lbasec = no_of_lbasec << 16;
4616                         no_of_lbasec = no_of_lbasec |
4617                             devp->dcd_ident->dcd_addrsec[0];
4618                         capacity = devp->dcd_ident->dcd_fixcyls *
4619                             devp->dcd_ident->dcd_heads *
4620                             devp->dcd_ident->dcd_sectors;
4621                         if (no_of_lbasec > capacity) {
4622                                 capacity = no_of_lbasec;
4623                                 if (capacity > NUM_SECTORS_32G) {
4624                                         /*
4625                                          * if the capacity is greater than 32G,
4626                                          * then 255 is the sectors per track.
4627                                          * This should be good until 128G disk
4628                                          * capacity, which is the current ATA-4
4629                                          * limitation.
4630                                          */
4631                                         phygeomp->g_nsect = 255;
4632                                 }
4633 
4634                                 /*
4635                                  * If the disk capacity is >= 128GB then no. of
4636                                  * addressable sectors will be set to 0xfffffff
4637                                  * in the IDENTIFY info. In that case set the
4638                                  *  no. of pcyl to the Max. 16bit value.
4639                                  */
4640 
4641                                 calculated_cylinders = (capacity) /
4642                                     (phygeomp->g_nhead * phygeomp->g_nsect);
4643                                 if (calculated_cylinders >= USHRT_MAX) {
4644                                         phygeomp->g_ncyl = USHRT_MAX - 2;
4645                                 } else {
4646                                         phygeomp->g_ncyl =
4647                                             calculated_cylinders - 2;
4648                                 }
4649                         }
4650 
4651                         phygeomp->g_capacity = capacity;
4652                         phygeomp->g_intrlv = 0;
4653                         phygeomp->g_rpm = 5400;
4654                         phygeomp->g_secsize = devp->dcd_ident->dcd_secsiz;
4655 
4656                         return (0);
4657                 } else
4658                         return (ENOTSUP);
4659         } else {
4660                 return (EINVAL);
4661         }
4662 }
4663 
4664 
4665 /*ARGSUSED3*/
4666 static int
4667 dcd_lb_getinfo(dev_info_t *devi, int cmd,  void *arg, void *tg_cookie)
4668 {
4669         struct dcd_disk *un;
4670 
4671         un = ddi_get_soft_state(dcd_state, ddi_get_instance(devi));
4672 
4673         if (un == NULL)
4674                 return (ENXIO);
4675 
4676         switch (cmd) {
4677         case TG_GETPHYGEOM:
4678                 return (dcd_lb_getphygeom(devi, (cmlb_geom_t *)arg));
4679 
4680         case TG_GETVIRTGEOM:
4681                 return (-1);
4682 
4683         case TG_GETCAPACITY:
4684         case TG_GETBLOCKSIZE:
4685                 mutex_enter(DCD_MUTEX);
4686                 if (un->un_diskcapacity <= 0) {
4687                         mutex_exit(DCD_MUTEX);
4688                         dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
4689                             "invalid disk capacity\n");
4690                         return (EIO);
4691                 }
4692                 if (cmd == TG_GETCAPACITY)
4693                         *(diskaddr_t *)arg = un->un_diskcapacity;
4694                 else
4695                         *(uint32_t *)arg = DEV_BSIZE;
4696 
4697                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "capacity %x\n",
4698                     un->un_diskcapacity);
4699                 mutex_exit(DCD_MUTEX);
4700                 return (0);
4701 
4702         case TG_GETATTR:
4703                 mutex_enter(DCD_MUTEX);
4704                 *(tg_attribute_t *)arg = un->un_tgattribute;
4705                 DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
4706                     "media_is_writable %x\n",
4707                     un->un_tgattribute.media_is_writable);
4708                 mutex_exit(DCD_MUTEX);
4709                 return (0);
4710         default:
4711                 return (ENOTTY);
4712         }
4713 }