Home | History | Annotate | Download | only in targets
      1  3786    arutz /*
      2  3786    arutz  * CDDL HEADER START
      3  3786    arutz  *
      4  3786    arutz  * The contents of this file are subject to the terms of the
      5  3786    arutz  * Common Development and Distribution License (the "License").
      6  3786    arutz  * You may not use this file except in compliance with the License.
      7  3786    arutz  *
      8  3786    arutz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  3786    arutz  * or http://www.opensolaris.org/os/licensing.
     10  3786    arutz  * See the License for the specific language governing permissions
     11  3786    arutz  * and limitations under the License.
     12  3786    arutz  *
     13  3786    arutz  * When distributing Covered Code, include this CDDL HEADER in each
     14  3786    arutz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  3786    arutz  * If applicable, add the following below this CDDL HEADER, with the
     16  3786    arutz  * fields enclosed by brackets "[]" replaced with your own identifying
     17  3786    arutz  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  3786    arutz  *
     19  3786    arutz  * CDDL HEADER END
     20  3786    arutz  */
     21  3786    arutz 
     22  3786    arutz /*
     23  8863   Edward  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  3786    arutz  * Use is subject to license terms.
     25  3786    arutz  */
     26  3786    arutz 
     27  3786    arutz 
     28  3786    arutz /*
     29  3786    arutz  * Direct Attached  disk driver for SPARC machines.
     30  3786    arutz  */
     31  3786    arutz 
     32  3786    arutz /*
     33  3786    arutz  * Includes, Declarations and Local Data
     34  3786    arutz  */
     35  3786    arutz #include <sys/dada/dada.h>
     36  3786    arutz #include <sys/dkbad.h>
     37  3786    arutz #include <sys/dklabel.h>
     38  3786    arutz #include <sys/dkio.h>
     39  3786    arutz #include <sys/cdio.h>
     40  3786    arutz #include <sys/vtoc.h>
     41  3786    arutz #include <sys/dada/targets/daddef.h>
     42  3786    arutz #include <sys/dada/targets/dadpriv.h>
     43  3786    arutz #include <sys/file.h>
     44  3786    arutz #include <sys/stat.h>
     45  3786    arutz #include <sys/kstat.h>
     46  3786    arutz #include <sys/vtrace.h>
     47  3786    arutz #include <sys/aio_req.h>
     48  3786    arutz #include <sys/note.h>
     49  3786    arutz #include <sys/cmlb.h>
     50  3786    arutz 
     51  3786    arutz /*
     52  3786    arutz  * Global Error Levels for Error Reporting
     53  3786    arutz  */
     54  3786    arutz int dcd_error_level	= DCD_ERR_RETRYABLE;
     55  3786    arutz /*
     56  3786    arutz  * Local Static Data
     57  3786    arutz  */
     58  3786    arutz 
     59  3786    arutz static int dcd_io_time		= DCD_IO_TIME;
     60  3786    arutz static int dcd_retry_count	= DCD_RETRY_COUNT;
     61  3786    arutz #ifndef lint
     62  3786    arutz static int dcd_report_pfa = 1;
     63  3786    arutz #endif
     64  3786    arutz static int dcd_rot_delay = 4;
     65  3786    arutz static int dcd_poll_busycnt = DCD_POLL_TIMEOUT;
     66  3786    arutz 
     67  3786    arutz /*
     68  3786    arutz  * Local Function Prototypes
     69  3786    arutz  */
     70  3786    arutz 
     71  3786    arutz static int dcdopen(dev_t *dev_p, int flag, int otyp, cred_t *cred_p);
     72  3786    arutz static int dcdclose(dev_t dev, int flag, int otyp, cred_t *cred_p);
     73  3786    arutz static int dcdstrategy(struct buf *bp);
     74  3786    arutz static int dcddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk);
     75  3786    arutz static int dcdioctl(dev_t, int, intptr_t, int, cred_t *, int *);
     76  3786    arutz static int dcdread(dev_t dev, struct uio *uio, cred_t *cred_p);
     77  3786    arutz static int dcdwrite(dev_t dev, struct uio *uio, cred_t *cred_p);
     78  3786    arutz static int dcd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int,
     79  3786    arutz     char *, caddr_t, int *);
     80  3786    arutz static int dcdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p);
     81  3786    arutz static int dcdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p);
     82  3786    arutz 
     83  3786    arutz 
     84  3786    arutz static void dcd_free_softstate(struct dcd_disk *un, dev_info_t *devi);
     85  3786    arutz static int dcd_doattach(dev_info_t *devi, int (*f)());
     86  3786    arutz static int dcd_validate_geometry(struct dcd_disk *un);
     87  3786    arutz static ddi_devid_t dcd_get_devid(struct dcd_disk *un);
     88  3786    arutz static ddi_devid_t  dcd_create_devid(struct dcd_disk *un);
     89  3786    arutz static int dcd_make_devid_from_serial(struct dcd_disk *un);
     90  3786    arutz static void dcd_validate_model_serial(char *str, int *retlen, int totallen);
     91  3786    arutz static int dcd_read_deviceid(struct dcd_disk *un);
     92  3786    arutz static int dcd_write_deviceid(struct dcd_disk *un);
     93  3786    arutz static int dcd_poll(struct dcd_pkt *pkt);
     94  3786    arutz static char *dcd_rname(int reason);
     95  3786    arutz static void dcd_flush_cache(struct dcd_disk *un);
     96  3786    arutz 
     97  3786    arutz static int dcd_compute_dk_capacity(struct dcd_device *devp,
     98  3786    arutz     diskaddr_t *capacity);
     99  3786    arutz static int dcd_send_lb_rw_cmd(dev_info_t *devinfo, void *bufaddr,
    100  3786    arutz     diskaddr_t start_block, size_t reqlength, uchar_t cmd);
    101  3786    arutz 
    102  3786    arutz static void dcdmin(struct buf *bp);
    103  3786    arutz 
    104  3786    arutz static int dcdioctl_cmd(dev_t, struct udcd_cmd *,
    105  3786    arutz     enum uio_seg, enum uio_seg);
    106  3786    arutz 
    107  3786    arutz static void dcdstart(struct dcd_disk *un);
    108  3786    arutz static void dcddone_and_mutex_exit(struct dcd_disk *un, struct buf *bp);
    109  3786    arutz static void make_dcd_cmd(struct dcd_disk *un, struct buf *bp, int (*f)());
    110  3786    arutz static void dcdudcdmin(struct buf *bp);
    111  3786    arutz 
    112  3786    arutz static int dcdrunout(caddr_t);
    113  3786    arutz static int dcd_check_wp(dev_t dev);
    114  3786    arutz static int dcd_unit_ready(dev_t dev);
    115  3786    arutz static void dcd_handle_tran_busy(struct buf *bp, struct diskhd *dp,
    116  3786    arutz     struct dcd_disk *un);
    117  3786    arutz static void dcdintr(struct dcd_pkt *pkt);
    118  3786    arutz static int dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp);
    119  3786    arutz static void dcd_offline(struct dcd_disk *un, int bechatty);
    120  3786    arutz static int dcd_ready_and_valid(dev_t dev, struct dcd_disk *un);
    121  3786    arutz static void dcd_reset_disk(struct dcd_disk *un, struct dcd_pkt *pkt);
    122  3786    arutz static void dcd_translate(struct dadkio_status32 *statp, struct udcd_cmd *cmdp);
    123  3786    arutz static int dcdflushdone(struct buf *bp);
    124  3786    arutz 
    125  3786    arutz /* Function prototypes for cmlb */
    126  3786    arutz 
    127  3786    arutz static int dcd_lb_rdwr(dev_info_t *devi, uchar_t cmd, void *bufaddr,
    128  3786    arutz     diskaddr_t start_block, size_t reqlength, void *tg_cookie);
    129  3786    arutz 
    130  3786    arutz static int dcd_lb_getphygeom(dev_info_t *devi, cmlb_geom_t *phygeomp);
    131  3786    arutz static int dcd_lb_getinfo(dev_info_t *devi, int cmd, void *arg,
    132  3786    arutz     void *tg_cookie);
    133  3786    arutz 
    134  3786    arutz 
    135  3786    arutz static cmlb_tg_ops_t dcd_lb_ops = {
    136  3786    arutz 	TG_DK_OPS_VERSION_1,
    137  3786    arutz 	dcd_lb_rdwr,
    138  3786    arutz 	dcd_lb_getinfo
    139  3786    arutz };
    140  3786    arutz 
    141  3786    arutz /*
    142  3786    arutz  * Error and Logging Functions
    143  3786    arutz  */
    144  3786    arutz #ifndef lint
    145  3786    arutz static void clean_print(dev_info_t *dev, char *label, uint_t level,
    146  3786    arutz     char *title, char *data, int len);
    147  3786    arutz static void dcdrestart(void *arg);
    148  3786    arutz #endif /* lint */
    149  3786    arutz 
    150  3786    arutz static int dcd_check_error(struct dcd_disk *un, struct buf *bp);
    151  3786    arutz 
    152  3786    arutz /*
    153  3786    arutz  * Error statistics create/update functions
    154  3786    arutz  */
    155  3786    arutz static int dcd_create_errstats(struct dcd_disk *, int);
    156  3786    arutz 
    157  3786    arutz 
    158  3786    arutz 
    159  3786    arutz /*PRINTFLIKE4*/
    160  3786    arutz extern void dcd_log(dev_info_t *, char *, uint_t, const char *, ...)
    161  3786    arutz     __KPRINTFLIKE(4);
    162  3786    arutz extern void makecommand(struct dcd_pkt *, int, uchar_t, uint32_t,
    163  3786    arutz     uchar_t, uint32_t, uchar_t, uchar_t);
    164  3786    arutz 
    165  3786    arutz 
    166  3786    arutz /*
    167  3786    arutz  * Configuration Routines
    168  3786    arutz  */
    169  3786    arutz static int dcdinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
    170  3786    arutz     void **result);
    171  3786    arutz static int dcdprobe(dev_info_t *devi);
    172  3786    arutz static int dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd);
    173  3786    arutz static int dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd);
    174  3786    arutz static int dcdreset(dev_info_t *dip, ddi_reset_cmd_t cmd);
    175  3786    arutz static int dcd_dr_detach(dev_info_t *devi);
    176  3786    arutz static int dcdpower(dev_info_t *devi, int component, int level);
    177  3786    arutz 
    178  3786    arutz static void *dcd_state;
    179  3786    arutz static int dcd_max_instance;
    180  3786    arutz static char *dcd_label = "dad";
    181  3786    arutz 
    182  3786    arutz static char *diskokay = "disk okay\n";
    183  3786    arutz 
    184  3786    arutz #if DEBUG || lint
    185  3786    arutz #define	DCDDEBUG
    186  3786    arutz #endif
    187  3786    arutz 
    188  3786    arutz int dcd_test_flag = 0;
    189  3786    arutz /*
    190  3786    arutz  * Debugging macros
    191  3786    arutz  */
    192  3786    arutz #ifdef	DCDDEBUG
    193  3786    arutz static int dcddebug = 0;
    194  3786    arutz #define	DEBUGGING	(dcddebug > 1)
    195  3786    arutz #define	DAD_DEBUG	if (dcddebug == 1) dcd_log
    196  3786    arutz #define	DAD_DEBUG2	if (dcddebug > 1) dcd_log
    197  3786    arutz #else	/* DCDDEBUG */
    198  3786    arutz #define	dcddebug		(0)
    199  3786    arutz #define	DEBUGGING	(0)
    200  3786    arutz #define	DAD_DEBUG	if (0) dcd_log
    201  3786    arutz #define	DAD_DEBUG2	if (0) dcd_log
    202  3786    arutz #endif
    203  3786    arutz 
    204  3786    arutz /*
    205  3786    arutz  * we use pkt_private area for storing bp and retry_count
    206  3786    arutz  * XXX: Really is this usefull.
    207  3786    arutz  */
    208  3786    arutz struct dcd_pkt_private {
    209  3786    arutz 	struct buf	*dcdpp_bp;
    210  3786    arutz 	short		 dcdpp_retry_count;
    211  3786    arutz 	short		 dcdpp_victim_retry_count;
    212  3786    arutz };
    213  3786    arutz 
    214  3786    arutz 
    215  3786    arutz _NOTE(SCHEME_PROTECTS_DATA("Unique per pkt", dcd_pkt_private buf))
    216  3786    arutz 
    217  3786    arutz #define	PP_LEN	(sizeof (struct dcd_pkt_private))
    218  3786    arutz 
    219  3786    arutz #define	PKT_SET_BP(pkt, bp)	\
    220  3786    arutz 	((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_bp = bp
    221  3786    arutz #define	PKT_GET_BP(pkt) \
    222  3786    arutz 	(((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_bp)
    223  3786    arutz 
    224  3786    arutz 
    225  3786    arutz #define	PKT_SET_RETRY_CNT(pkt, n) \
    226  3786    arutz 	((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count = n
    227  3786    arutz 
    228  3786    arutz #define	PKT_GET_RETRY_CNT(pkt) \
    229  3786    arutz 	(((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count)
    230  3786    arutz 
    231  3786    arutz #define	PKT_INCR_RETRY_CNT(pkt, n) \
    232  3786    arutz 	((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count += n
    233  3786    arutz 
    234  3786    arutz #define	PKT_SET_VICTIM_RETRY_CNT(pkt, n) \
    235  3786    arutz 	((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count \
    236  3786    arutz 			= n
    237  3786    arutz 
    238  3786    arutz #define	PKT_GET_VICTIM_RETRY_CNT(pkt) \
    239  3786    arutz 	(((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count)
    240  3786    arutz #define	PKT_INCR_VICTIM_RETRY_CNT(pkt, n) \
    241  3786    arutz 	((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count \
    242  3786    arutz 			+= n
    243  3786    arutz 
    244  3786    arutz #define	DISK_NOT_READY_RETRY_COUNT	(dcd_retry_count / 2)
    245  3786    arutz 
    246  3786    arutz 
    247  3786    arutz /*
    248  3786    arutz  * Urk!
    249  3786    arutz  */
    250  3786    arutz #define	SET_BP_ERROR(bp, err)	\
    251  3786    arutz 	bioerror(bp, err);
    252  3786    arutz 
    253  3786    arutz #define	IOSP			KSTAT_IO_PTR(un->un_stats)
    254  3786    arutz #define	IO_PARTITION_STATS	un->un_pstats[DCDPART(bp->b_edev)]
    255  3786    arutz #define	IOSP_PARTITION		KSTAT_IO_PTR(IO_PARTITION_STATS)
    256  3786    arutz 
    257  3786    arutz #define	DCD_DO_KSTATS(un, kstat_function, bp) \
    258  3786    arutz 	ASSERT(mutex_owned(DCD_MUTEX)); \
    259  3786    arutz 	if (bp != un->un_sbufp) { \
    260  3786    arutz 		if (un->un_stats) { \
    261  3786    arutz 			kstat_function(IOSP); \
    262  3786    arutz 		} \
    263  3786    arutz 		if (IO_PARTITION_STATS) { \
    264  3786    arutz 			kstat_function(IOSP_PARTITION); \
    265  3786    arutz 		} \
    266  3786    arutz 	}
    267  3786    arutz 
    268  3786    arutz #define	DCD_DO_ERRSTATS(un, x) \
    269  3786    arutz 	if (un->un_errstats) { \
    270  3786    arutz 		struct dcd_errstats *dtp; \
    271  3786    arutz 		dtp = (struct dcd_errstats *)un->un_errstats->ks_data; \
    272  3786    arutz 		dtp->x.value.ui32++; \
    273  3786    arutz 	}
    274  3786    arutz 
    275  3786    arutz #define	GET_SOFT_STATE(dev)						\
    276  3786    arutz 	struct dcd_disk *un;					\
    277  3786    arutz 	int instance, part;					\
    278  3786    arutz 	minor_t minor = getminor(dev);				\
    279  3786    arutz 									\
    280  3786    arutz 	part = minor & DCDPART_MASK;					\
    281  3786    arutz 	instance = minor >> DCDUNIT_SHIFT;				\
    282  3786    arutz 	if ((un = ddi_get_soft_state(dcd_state, instance)) == NULL)	\
    283  3786    arutz 		return (ENXIO);
    284  3786    arutz 
    285  3786    arutz #define	LOGICAL_BLOCK_ALIGN(blkno, blknoshift) \
    286  3786    arutz 		(((blkno) & ((1 << (blknoshift)) - 1)) == 0)
    287  3786    arutz 
    288  3786    arutz /*
    289  3786    arutz  * After the following number of sectors, the cylinder number spills over
    290  3786    arutz  * 0xFFFF if sectors = 63 and heads = 16.
    291  3786    arutz  */
    292  3786    arutz #define	NUM_SECTORS_32G	0x3EFFC10
    293  3786    arutz 
    294  3786    arutz /*
    295  3786    arutz  * Configuration Data
    296  3786    arutz  */
    297  3786    arutz 
    298  3786    arutz /*
    299  3786    arutz  * Device driver ops vector
    300  3786    arutz  */
    301  3786    arutz 
    302  3786    arutz static struct cb_ops dcd_cb_ops = {
    303  3786    arutz 	dcdopen,		/* open */
    304  3786    arutz 	dcdclose,		/* close */
    305  3786    arutz 	dcdstrategy,		/* strategy */
    306  3786    arutz 	nodev,			/* print */
    307  3786    arutz 	dcddump,		/* dump */
    308  3786    arutz 	dcdread,		/* read */
    309  3786    arutz 	dcdwrite,		/* write */
    310  3786    arutz 	dcdioctl,		/* ioctl */
    311  3786    arutz 	nodev,			/* devmap */
    312  3786    arutz 	nodev,			/* mmap */
    313  3786    arutz 	nodev,			/* segmap */
    314  3786    arutz 	nochpoll,		/* poll */
    315  3786    arutz 	dcd_prop_op,		/* cb_prop_op */
    316  3786    arutz 	0,			/* streamtab  */
    317  3786    arutz 	D_64BIT | D_MP | D_NEW,	/* Driver compatibility flag */
    318  3786    arutz 	CB_REV,			/* cb_rev */
    319  3786    arutz 	dcdaread, 		/* async I/O read entry point */
    320  3786    arutz 	dcdawrite		/* async I/O write entry point */
    321  3786    arutz };
    322  3786    arutz 
    323  3786    arutz static struct dev_ops dcd_ops = {
    324  3786    arutz 	DEVO_REV,		/* devo_rev, */
    325  3786    arutz 	0,			/* refcnt  */
    326  3786    arutz 	dcdinfo,		/* info */
    327  3786    arutz 	nulldev,		/* identify */
    328  3786    arutz 	dcdprobe,		/* probe */
    329  3786    arutz 	dcdattach,		/* attach */
    330  3786    arutz 	dcddetach,		/* detach */
    331  3786    arutz 	dcdreset,		/* reset */
    332  3786    arutz 	&dcd_cb_ops,		/* driver operations */
    333  3786    arutz 	(struct bus_ops *)0,	/* bus operations */
    334  7656   Sherry 	dcdpower,		/* power */
    335  7656   Sherry 	ddi_quiesce_not_supported,	/* devo_quiesce */
    336  3786    arutz };
    337  3786    arutz 
    338  3786    arutz 
    339  3786    arutz /*
    340  3786    arutz  * This is the loadable module wrapper.
    341  3786    arutz  */
    342  3786    arutz #include <sys/modctl.h>
    343  3786    arutz 
    344  3786    arutz static struct modldrv modldrv = {
    345  3786    arutz 	&mod_driverops,		/* Type of module. This one is a driver */
    346  7656   Sherry 	"DAD Disk Driver",	/* Name of the module. */
    347  3786    arutz 	&dcd_ops,	/* driver ops */
    348  3786    arutz };
    349  3786    arutz 
    350  3786    arutz 
    351  3786    arutz 
    352  3786    arutz static struct modlinkage modlinkage = {
    353  3786    arutz 	MODREV_1, &modldrv, NULL
    354  3786    arutz };
    355  3786    arutz 
    356  3786    arutz /*
    357  3786    arutz  * the dcd_attach_mutex only protects dcd_max_instance in multi-threaded
    358  3786    arutz  * attach situations
    359  3786    arutz  */
    360  3786    arutz static kmutex_t dcd_attach_mutex;
    361  3786    arutz 
    362  3786    arutz int
    363  3786    arutz _init(void)
    364  3786    arutz {
    365  3786    arutz 	int e;
    366  3786    arutz 
    367  3786    arutz 	if ((e = ddi_soft_state_init(&dcd_state, sizeof (struct dcd_disk),
    368  3786    arutz 	    DCD_MAXUNIT)) != 0)
    369  3786    arutz 		return (e);
    370  3786    arutz 
    371  3786    arutz 	mutex_init(&dcd_attach_mutex, NULL, MUTEX_DRIVER, NULL);
    372  3786    arutz 	e = mod_install(&modlinkage);
    373  3786    arutz 	if (e != 0) {
    374  3786    arutz 		mutex_destroy(&dcd_attach_mutex);
    375  3786    arutz 		ddi_soft_state_fini(&dcd_state);
    376  3786    arutz 		return (e);
    377  3786    arutz 	}
    378  3786    arutz 
    379  3786    arutz 	return (e);
    380  3786    arutz }
    381  3786    arutz 
    382  3786    arutz int
    383  3786    arutz _fini(void)
    384  3786    arutz {
    385  3786    arutz 	int e;
    386  3786    arutz 
    387  3786    arutz 	if ((e = mod_remove(&modlinkage)) != 0)
    388  3786    arutz 		return (e);
    389  3786    arutz 
    390  3786    arutz 	ddi_soft_state_fini(&dcd_state);
    391  3786    arutz 	mutex_destroy(&dcd_attach_mutex);
    392  3786    arutz 
    393  3786    arutz 	return (e);
    394  3786    arutz }
    395  3786    arutz 
    396  3786    arutz int
    397  3786    arutz _info(struct modinfo *modinfop)
    398  3786    arutz {
    399  3786    arutz 
    400  3786    arutz 	return (mod_info(&modlinkage, modinfop));
    401  3786    arutz }
    402  3786    arutz 
    403  3786    arutz static int
    404  3786    arutz dcdprobe(dev_info_t *devi)
    405  3786    arutz {
    406  3786    arutz 	struct dcd_device *devp;
    407  3786    arutz 	int rval = DDI_PROBE_PARTIAL;
    408  3786    arutz 	int instance;
    409  3786    arutz 
    410  3786    arutz 	devp = ddi_get_driver_private(devi);
    411  3786    arutz 	instance = ddi_get_instance(devi);
    412  3786    arutz 
    413  3786    arutz 	/*
    414  3786    arutz 	 * Keep a count of how many disks (ie. highest instance no) we have
    415  3786    arutz 	 * XXX currently not used but maybe useful later again
    416  3786    arutz 	 */
    417  3786    arutz 	mutex_enter(&dcd_attach_mutex);
    418  3786    arutz 	if (instance > dcd_max_instance)
    419  3786    arutz 		dcd_max_instance = instance;
    420  3786    arutz 	mutex_exit(&dcd_attach_mutex);
    421  3786    arutz 
    422  7224      cth 	DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "dcdprobe:\n");
    423  3786    arutz 
    424  3786    arutz 	if (ddi_get_soft_state(dcd_state, instance) != NULL)
    425  3786    arutz 		return (DDI_PROBE_PARTIAL);
    426  3786    arutz 
    427  3786    arutz 	/*
    428  3786    arutz 	 * Turn around and call utility probe routine
    429  3786    arutz 	 * to see whether we actually have a disk at
    430  3786    arutz 	 */
    431  3786    arutz 
    432  3786    arutz 	DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
    433  3786    arutz 	    "dcdprobe: %x\n", dcd_probe(devp, NULL_FUNC));
    434  3786    arutz 
    435  3786    arutz 	switch (dcd_probe(devp, NULL_FUNC)) {
    436  3786    arutz 	default:
    437  3786    arutz 	case DCDPROBE_NORESP:
    438  3786    arutz 	case DCDPROBE_NONCCS:
    439  3786    arutz 	case DCDPROBE_NOMEM:
    440  3786    arutz 	case DCDPROBE_FAILURE:
    441  3786    arutz 	case DCDPROBE_BUSY:
    442  3786    arutz 		break;
    443  3786    arutz 
    444  3786    arutz 	case DCDPROBE_EXISTS:
    445  3786    arutz 		/*
    446  3786    arutz 		 * Check whether it is a ATA device and then
    447  3786    arutz 		 * return  SUCCESS.
    448  3786    arutz 		 */
    449  3786    arutz 		DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
    450  3786    arutz 		    "config %x\n", devp->dcd_ident->dcd_config);
    451  3786    arutz 		if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
    452  3786    arutz 			if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
    453  3786    arutz 				rval = DDI_PROBE_SUCCESS;
    454  3786    arutz 			} else
    455  3786    arutz 				rval = DDI_PROBE_FAILURE;
    456  3786    arutz 		} else {
    457  3786    arutz 			rval = DDI_PROBE_FAILURE;
    458  3786    arutz 		}
    459  3786    arutz 		break;
    460  3786    arutz 	}
    461  3786    arutz 	dcd_unprobe(devp);
    462  3786    arutz 
    463  3786    arutz 	DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
    464  3786    arutz 	    "dcdprobe returns %x\n", rval);
    465  3786    arutz 
    466  3786    arutz 	return (rval);
    467  3786    arutz }
    468  3786    arutz 
    469  3786    arutz 
    470  3786    arutz /*ARGSUSED*/
    471  3786    arutz static int
    472  3786    arutz dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    473  3786    arutz {
    474  3786    arutz 	int instance, rval;
    475  3786    arutz 	struct dcd_device *devp;
    476  3786    arutz 	struct dcd_disk *un;
    477  3786    arutz 	struct diskhd *dp;
    478  3786    arutz 	char	*pm_comp[] =
    479  3786    arutz 	    { "NAME=ide-disk", "0=standby", "1=idle", "2=active" };
    480  3786    arutz 
    481  3786    arutz 	/* CONSTCOND */
    482  3786    arutz 	ASSERT(NO_COMPETING_THREADS);
    483  3786    arutz 
    484  3786    arutz 
    485  3786    arutz 	devp = ddi_get_driver_private(devi);
    486  3786    arutz 	instance = ddi_get_instance(devi);
    487  3786    arutz 	DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "Attach Started\n");
    488  3786    arutz 
    489  3786    arutz 	switch (cmd) {
    490  3786    arutz 	case DDI_ATTACH:
    491  3786    arutz 		break;
    492  3786    arutz 
    493  3786    arutz 	case DDI_RESUME:
    494  3786    arutz 		if (!(un = ddi_get_soft_state(dcd_state, instance)))
    495  3786    arutz 			return (DDI_FAILURE);
    496  3786    arutz 		mutex_enter(DCD_MUTEX);
    497  3786    arutz 		Restore_state(un);
    498  3786    arutz 		/*
    499  3786    arutz 		 * Restore the state which was saved to give the
    500  3786    arutz 		 * the right state in un_last_state
    501  3786    arutz 		 */
    502  3786    arutz 		un->un_last_state = un->un_save_state;
    503  3786    arutz 		un->un_throttle = 2;
    504  3786    arutz 		cv_broadcast(&un->un_suspend_cv);
    505  3786    arutz 		/*
    506  3786    arutz 		 * Raise the power level of the device to active.
    507  3786    arutz 		 */
    508  3786    arutz 		mutex_exit(DCD_MUTEX);
    509  3786    arutz 		(void) pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE);
    510  3786    arutz 		mutex_enter(DCD_MUTEX);
    511  3786    arutz 
    512  3786    arutz 		/*
    513  3786    arutz 		 * start unit - if this is a low-activity device
    514  3786    arutz 		 * commands in queue will have to wait until new
    515  3786    arutz 		 * commands come in, which may take awhile.
    516  3786    arutz 		 * Also, we specifically don't check un_ncmds
    517  3786    arutz 		 * because we know that there really are no
    518  3786    arutz 		 * commands in progress after the unit was suspended
    519  3786    arutz 		 * and we could have reached the throttle level, been
    520  3786    arutz 		 * suspended, and have no new commands coming in for
    521  3786    arutz 		 * awhile.  Highly unlikely, but so is the low-
    522  3786    arutz 		 * activity disk scenario.
    523  3786    arutz 		 */
    524  3786    arutz 		dp = &un->un_utab;
    525  3786    arutz 		if (dp->b_actf && (dp->b_forw == NULL)) {
    526  3786    arutz 			dcdstart(un);
    527  3786    arutz 		}
    528  3786    arutz 
    529  3786    arutz 		mutex_exit(DCD_MUTEX);
    530  3786    arutz 		return (DDI_SUCCESS);
    531  3786    arutz 
    532  3786    arutz 	default:
    533  3786    arutz 		return (DDI_FAILURE);
    534  3786    arutz 	}
    535  3786    arutz 
    536  3786    arutz 	if (dcd_doattach(devi, SLEEP_FUNC) == DDI_FAILURE) {
    537  3786    arutz 		return (DDI_FAILURE);
    538  3786    arutz 	}
    539  3786    arutz 
    540  3786    arutz 	if (!(un = (struct dcd_disk *)
    541  3786    arutz 	    ddi_get_soft_state(dcd_state, instance))) {
    542  3786    arutz 		return (DDI_FAILURE);
    543  3786    arutz 	}
    544  3786    arutz 	devp->dcd_private = (ataopaque_t)un;
    545  3786    arutz 
    546  3786    arutz 	/*
    547  3786    arutz 	 * Add a zero-length attribute to tell the world we support
    548  3786    arutz 	 * kernel ioctls (for layered drivers)
    549  3786    arutz 	 */
    550  3786    arutz 	(void) ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP,
    551  3786    arutz 	    DDI_KERNEL_IOCTL, NULL, 0);
    552  3786    arutz 
    553  3786    arutz 	/*
    554  3786    arutz 	 * Since the dad device does not have the 'reg' property,
    555  3786    arutz 	 * cpr will not call its DDI_SUSPEND/DDI_RESUME entries.
    556  3786    arutz 	 * The following code is to tell cpr that this device
    557  3786    arutz 	 * does need to be suspended and resumed.
    558  3786    arutz 	 */
    559  3786    arutz 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
    560  3786    arutz 	    "pm-hardware-state", (caddr_t)"needs-suspend-resume");
    561  3786    arutz 
    562  3786    arutz 	/*
    563  3786    arutz 	 * Initialize power management bookkeeping;
    564  3786    arutz 	 * Create components - In IDE case there are 3 levels and one
    565  3786    arutz 	 * component. The levels being - active, idle, standby.
    566  3786    arutz 	 */
    567  3786    arutz 
    568  3786    arutz 	rval = ddi_prop_update_string_array(DDI_DEV_T_NONE,
    569  3786    arutz 	    devi, "pm-components", pm_comp, 4);
    570  3786    arutz 	if (rval == DDI_PROP_SUCCESS) {
    571  3786    arutz 		/*
    572  3786    arutz 		 * Ignore the return value of pm_raise_power
    573  3786    arutz 		 * Even if we check the return values and
    574  3786    arutz 		 * remove the property created above, PM
    575  3786    arutz 		 * framework will not honour the change after
    576  3786    arutz 		 * first call to pm_raise_power. Hence, the
    577  3786    arutz 		 * removal of that property does not help if
    578  3786    arutz 		 * pm_raise_power fails.
    579  3786    arutz 		 */
    580  3786    arutz 		(void) pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE);
    581  3786    arutz 	}
    582  3786    arutz 
    583  3786    arutz 	ddi_report_dev(devi);
    584  3786    arutz 
    585  3786    arutz 	cmlb_alloc_handle(&un->un_dklbhandle);
    586  3786    arutz 
    587  3786    arutz 	if (cmlb_attach(devi,
    588  7224      cth 	    &dcd_lb_ops,
    589  7224      cth 	    0,
    590  8863   Edward 	    B_FALSE,
    591  8863   Edward 	    B_FALSE,
    592  7224      cth 	    DDI_NT_BLOCK_CHAN,
    593  7224      cth 	    CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8,
    594  7224      cth 	    un->un_dklbhandle,
    595  7224      cth 	    0) != 0) {
    596  3786    arutz 		cmlb_free_handle(&un->un_dklbhandle);
    597  3786    arutz 		dcd_free_softstate(un, devi);
    598  3786    arutz 		return (DDI_FAILURE);
    599  3786    arutz 	}
    600  3786    arutz 
    601  3786    arutz 	mutex_enter(DCD_MUTEX);
    602  3786    arutz 	(void) dcd_validate_geometry(un);
    603  3786    arutz 
    604  3786    arutz 	/* Get devid; create a devid ONLY IF could not get ID */
    605  3786    arutz 	if (dcd_get_devid(un) == NULL) {
    606  3786    arutz 		/* Create the fab'd devid */
    607  3786    arutz 		(void) dcd_create_devid(un);
    608  3786    arutz 	}
    609  3786    arutz 	mutex_exit(DCD_MUTEX);
    610  3786    arutz 
    611  3786    arutz 	return (DDI_SUCCESS);
    612  3786    arutz }
    613  3786    arutz 
    614  3786    arutz static void
    615  3786    arutz dcd_free_softstate(struct dcd_disk *un, dev_info_t *devi)
    616  3786    arutz {
    617  3786    arutz 	struct dcd_device		*devp;
    618  3786    arutz 	int instance = ddi_get_instance(devi);
    619  3786    arutz 
    620  3786    arutz 	devp = ddi_get_driver_private(devi);
    621  3786    arutz 
    622  3786    arutz 	if (un) {
    623  3786    arutz 		sema_destroy(&un->un_semoclose);
    624  3786    arutz 		cv_destroy(&un->un_sbuf_cv);
    625  3786    arutz 		cv_destroy(&un->un_state_cv);
    626  3786    arutz 		cv_destroy(&un->un_disk_busy_cv);
    627  3786    arutz 		cv_destroy(&un->un_suspend_cv);
    628  3786    arutz 
    629  3786    arutz 		/*
    630  3786    arutz 		 * Deallocate command packet resources.
    631  3786    arutz 		 */
    632  3786    arutz 		if (un->un_sbufp)
    633  3786    arutz 			freerbuf(un->un_sbufp);
    634  3786    arutz 		if (un->un_dp) {
    635  3786    arutz 			kmem_free((caddr_t)un->un_dp, sizeof (*un->un_dp));
    636  3786    arutz 		}
    637  3786    arutz 		/*
    638  3786    arutz 		 * Unregister the devid and free devid resources allocated
    639  3786    arutz 		 */
    640  3786    arutz 		ddi_devid_unregister(DCD_DEVINFO);
    641  3786    arutz 		if (un->un_devid) {
    642  3786    arutz 			ddi_devid_free(un->un_devid);
    643  3786    arutz 			un->un_devid = NULL;
    644  3786    arutz 		}
    645  3786    arutz 
    646  3786    arutz 		/*
    647  3786    arutz 		 * Delete kstats. Kstats for non CD devices are deleted
    648  3786    arutz 		 * in dcdclose.
    649  3786    arutz 		 */
    650  3786    arutz 		if (un->un_stats) {
    651  3786    arutz 			kstat_delete(un->un_stats);
    652  3786    arutz 		}
    653  3786    arutz 
    654  3786    arutz 	}
    655  3786    arutz 
    656  3786    arutz 	/*
    657  3786    arutz 	 * Cleanup scsi_device resources.
    658  3786    arutz 	 */
    659  3786    arutz 	ddi_soft_state_free(dcd_state, instance);
    660  3786    arutz 	devp->dcd_private = (ataopaque_t)0;
    661  3786    arutz 	/* unprobe scsi device */
    662  3786    arutz 	dcd_unprobe(devp);
    663  3786    arutz 
    664  3786    arutz 	/* Remove properties created during attach */
    665  3786    arutz 	ddi_prop_remove_all(devi);
    666  3786    arutz }
    667  3786    arutz 
    668  3786    arutz static int
    669  3786    arutz dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd)
    670  3786    arutz {
    671  3786    arutz 	int instance;
    672  3786    arutz 	struct dcd_disk *un;
    673  3786    arutz 	clock_t	wait_cmds_complete;
    674  3786    arutz 	instance = ddi_get_instance(devi);
    675  3786    arutz 
    676  3786    arutz 	if (!(un = ddi_get_soft_state(dcd_state, instance)))
    677  3786    arutz 		return (DDI_FAILURE);
    678  3786    arutz 
    679  3786    arutz 	switch (cmd) {
    680  3786    arutz 	case DDI_DETACH:
    681  3786    arutz 		return (dcd_dr_detach(devi));
    682  3786    arutz 
    683  3786    arutz 	case DDI_SUSPEND:
    684  3786    arutz 		mutex_enter(DCD_MUTEX);
    685  3786    arutz 		if (un->un_state == DCD_STATE_SUSPENDED) {
    686  3786    arutz 			mutex_exit(DCD_MUTEX);
    687  3786    arutz 			return (DDI_SUCCESS);
    688  3786    arutz 		}
    689  3786    arutz 		un->un_throttle = 0;
    690  3786    arutz 		/*
    691  3786    arutz 		 * Save the last state first
    692  3786    arutz 		 */
    693  3786    arutz 		un->un_save_state = un->un_last_state;
    694  3786    arutz 
    695  3786    arutz 		New_state(un, DCD_STATE_SUSPENDED);
    696  3786    arutz 
    697  3786    arutz 		/*
    698  3786    arutz 		 * wait till current operation completed. If we are
    699  3786    arutz 		 * in the resource wait state (with an intr outstanding)
    700  3786    arutz 		 * then we need to wait till the intr completes and
    701  3786    arutz 		 * starts the next cmd. We wait for
    702  3786    arutz 		 * DCD_WAIT_CMDS_COMPLETE seconds before failing the
    703  3786    arutz 		 * DDI_SUSPEND.
    704  3786    arutz 		 */
    705  3786    arutz 		wait_cmds_complete = ddi_get_lbolt();
    706  3786    arutz 		wait_cmds_complete +=
    707  7224      cth 		    DCD_WAIT_CMDS_COMPLETE * drv_usectohz(1000000);
    708  3786    arutz 
    709  3786    arutz 		while (un->un_ncmds) {
    710  3786    arutz 			if (cv_timedwait(&un->un_disk_busy_cv,
    711  3786    arutz 			    DCD_MUTEX, wait_cmds_complete) == -1) {
    712  3786    arutz 				/*
    713  3786    arutz 				 * commands Didn't finish in the
    714  3786    arutz 				 * specified time, fail the DDI_SUSPEND.
    715  3786    arutz 				 */
    716  3786    arutz 				DAD_DEBUG2(DCD_DEVINFO, dcd_label,
    717  3786    arutz 				    DCD_DEBUG, "dcddetach: SUSPEND "
    718  3786    arutz 				    "failed due to outstanding cmds\n");
    719  3786    arutz 				Restore_state(un);
    720  3786    arutz 				mutex_exit(DCD_MUTEX);
    721  3786    arutz 				return (DDI_FAILURE);
    722  3786    arutz 			}
    723  3786    arutz 		}
    724  3786    arutz 		mutex_exit(DCD_MUTEX);
    725  3786    arutz 		return (DDI_SUCCESS);
    726  3786    arutz 	}
    727  3786    arutz 	return (DDI_FAILURE);
    728  3786    arutz }
    729  3786    arutz 
    730  3786    arutz /*
    731  3786    arutz  * The reset entry point gets invoked at the system shutdown time or through
    732  3786    arutz  * CPR code at system suspend.
    733  3786    arutz  * Will be flushing the cache and expect this to be last I/O operation to the
    734  3786    arutz  * disk before system reset/power off.
    735  3786    arutz  */
    736  3786    arutz /*ARGSUSED*/
    737  3786    arutz static int
    738  3786    arutz dcdreset(dev_info_t *dip, ddi_reset_cmd_t cmd)
    739  3786    arutz {
    740  3786    arutz 	struct dcd_disk *un;
    741  3786    arutz 	int instance;
    742  3786    arutz 
    743  3786    arutz 	instance = ddi_get_instance(dip);
    744  3786    arutz 
    745  3786    arutz 	if (!(un = ddi_get_soft_state(dcd_state, instance)))
    746  3786    arutz 		return (DDI_FAILURE);
    747  3786    arutz 
    748  3786    arutz 	dcd_flush_cache(un);
    749  3786    arutz 
    750  3786    arutz 	return (DDI_SUCCESS);
    751  3786    arutz }
    752  3786    arutz 
    753  3786    arutz 
    754  3786    arutz static int
    755  3786    arutz dcd_dr_detach(dev_info_t *devi)
    756  3786    arutz {
    757  3786    arutz 	struct dcd_device	*devp;
    758  3786    arutz 	struct dcd_disk		*un;
    759  3786    arutz 
    760  3786    arutz 	/*
    761  3786    arutz 	 * Get scsi_device structure for this instance.
    762  3786    arutz 	 */
    763  3786    arutz 	if ((devp = ddi_get_driver_private(devi)) == NULL)
    764  3786    arutz 		return (DDI_FAILURE);
    765  3786    arutz 
    766  3786    arutz 	/*
    767  3786    arutz 	 * Get dcd_disk structure containing target 'private' information
    768  3786    arutz 	 */
    769  3786    arutz 	un = (struct dcd_disk *)devp->dcd_private;
    770  3786    arutz 
    771  3786    arutz 	/*
    772  3786    arutz 	 * Verify there are NO outstanding commands issued to this device.
    773  3786    arutz 	 * ie, un_ncmds == 0.
    774  3786    arutz 	 * It's possible to have outstanding commands through the physio
    775  3786    arutz 	 * code path, even though everything's closed.
    776  3786    arutz 	 */
    777  3786    arutz #ifndef lint
    778  3786    arutz 	_NOTE(COMPETING_THREADS_NOW);
    779  3786    arutz #endif
    780  3786    arutz 	mutex_enter(DCD_MUTEX);
    781  3786    arutz 	if (un->un_ncmds) {
    782  3786    arutz 		mutex_exit(DCD_MUTEX);
    783  3786    arutz 		_NOTE(NO_COMPETING_THREADS_NOW);
    784  3786    arutz 		return (DDI_FAILURE);
    785  3786    arutz 	}
    786  3786    arutz 
    787  3786    arutz 	mutex_exit(DCD_MUTEX);
    788  3786    arutz 
    789  3786    arutz 	cmlb_detach(un->un_dklbhandle, 0);
    790  3786    arutz 	cmlb_free_handle(&un->un_dklbhandle);
    791  3786    arutz 
    792  3786    arutz 
    793  3786    arutz 	/*
    794  3786    arutz 	 * Lower the power state of the device
    795  3786    arutz 	 * i.e. the minimum power consumption state - sleep.
    796  3786    arutz 	 */
    797  3786    arutz 	(void) pm_lower_power(DCD_DEVINFO, 0, DCD_DEVICE_STANDBY);
    798  3786    arutz 
    799  3786    arutz 	_NOTE(NO_COMPETING_THREADS_NOW);
    800  3786    arutz 
    801  3786    arutz 	/*
    802  3786    arutz 	 * at this point there are no competing threads anymore
    803  3786    arutz 	 * release active MT locks and all device resources.
    804  3786    arutz 	 */
    805  3786    arutz 	dcd_free_softstate(un, devi);
    806  3786    arutz 
    807  3786    arutz 	return (DDI_SUCCESS);
    808  3786    arutz }
    809  3786    arutz 
    810  3786    arutz static int
    811  3786    arutz dcdpower(dev_info_t *devi, int component, int level)
    812  3786    arutz {
    813  3786    arutz 	struct dcd_pkt *pkt;
    814  3786    arutz 	struct dcd_disk *un;
    815  3786    arutz 	int	instance;
    816  3786    arutz 	uchar_t	cmd;
    817  3786    arutz 
    818  3786    arutz 
    819  3786    arutz 	instance = ddi_get_instance(devi);
    820  3786    arutz 
    821  3786    arutz 	if (!(un = ddi_get_soft_state(dcd_state, instance)) ||
    822  7224      cth 	    (DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) ||
    823  7224      cth 	    component != 0) {
    824  3786    arutz 		return (DDI_FAILURE);
    825  3786    arutz 	}
    826  3786    arutz 
    827  3786    arutz 	mutex_enter(DCD_MUTEX);
    828  3786    arutz 	/*
    829  3786    arutz 	 * if there are active commands for the device or device will be
    830  3786    arutz 	 * active soon. At the same time there is request to lower power
    831  3786    arutz 	 * return failure.
    832  3786    arutz 	 */
    833  3786    arutz 	if ((un->un_ncmds) && (level != DCD_DEVICE_ACTIVE)) {
    834  3786    arutz 		mutex_exit(DCD_MUTEX);
    835  3786    arutz 		return (DDI_FAILURE);
    836  3786    arutz 	}
    837  3786    arutz 
    838  3786    arutz 	if ((un->un_state == DCD_STATE_OFFLINE) ||
    839  3786    arutz 	    (un->un_state == DCD_STATE_FATAL)) {
    840  3786    arutz 		mutex_exit(DCD_MUTEX);
    841  3786    arutz 		return (DDI_FAILURE);
    842  3786    arutz 	}
    843  3786    arutz 
    844  3786    arutz 	if (level == DCD_DEVICE_ACTIVE) {
    845  3786    arutz 		/*
    846  3786    arutz 		 * No need to fire any command, just set the state structure
    847  3786    arutz 		 * to indicate previous state and set the level to active
    848  3786    arutz 		 */
    849  3786    arutz 		un->un_power_level = DCD_DEVICE_ACTIVE;
    850  3786    arutz 		if (un->un_state == DCD_STATE_PM_SUSPENDED)
    851  3786    arutz 			Restore_state(un);
    852  3786    arutz 		mutex_exit(DCD_MUTEX);
    853  3786    arutz 	} else {
    854  3786    arutz 		pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL,
    855  3786    arutz 		    NULL, (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN,
    856  3786    arutz 		    PKT_CONSISTENT, NULL_FUNC, NULL);
    857  3786    arutz 
    858  3786    arutz 		if (pkt == (struct dcd_pkt *)NULL) {
    859  3786    arutz 			mutex_exit(DCD_MUTEX);
    860  3786    arutz 			return (DDI_FAILURE);
    861  3786    arutz 		}
    862  3786    arutz 
    863  3786    arutz 		switch (level) {
    864  3786    arutz 		case DCD_DEVICE_IDLE:
    865  3786    arutz 			cmd = ATA_IDLE_IMMEDIATE;
    866  3786    arutz 			break;
    867  3786    arutz 
    868  3786    arutz 		case DCD_DEVICE_STANDBY:
    869  3786    arutz 			cmd = ATA_STANDBY_IMMEDIATE;
    870  3786    arutz 			break;
    871  3786    arutz 		}
    872  3786    arutz 
    873  3786    arutz 		makecommand(pkt, 0, cmd, 0, 0, 0, NO_DATA_XFER, 0);
    874  3786    arutz 		mutex_exit(DCD_MUTEX);
    875  3786    arutz 		/*
    876  3786    arutz 		 * Issue the appropriate command
    877  3786    arutz 		 */
    878  3786    arutz 		if ((dcd_poll(pkt)) || (SCBP_C(pkt) != STATUS_GOOD)) {
    879  3786    arutz 			dcd_destroy_pkt(pkt);
    880  3786    arutz 			return (DDI_FAILURE);
    881  3786    arutz 		}
    882  3786    arutz 		dcd_destroy_pkt(pkt);
    883  3786    arutz 		mutex_enter(DCD_MUTEX);
    884  3786    arutz 		if (un->un_state != DCD_STATE_PM_SUSPENDED)
    885  3786    arutz 			New_state(un, DCD_STATE_PM_SUSPENDED);
    886  3786    arutz 		un->un_power_level = level;
    887  3786    arutz 		mutex_exit(DCD_MUTEX);
    888  3786    arutz 	}
    889  3786    arutz 
    890  3786    arutz 	return (DDI_SUCCESS);
    891  3786    arutz }
    892  3786    arutz 
    893  3786    arutz static int
    894  3786    arutz dcd_doattach(dev_info_t *devi, int (*canwait)())
    895  3786    arutz {
    896  3786    arutz 	struct dcd_device *devp;
    897  3786    arutz 	struct dcd_disk *un = (struct dcd_disk *)0;
    898  3786    arutz 	int instance;
    899  3786    arutz 	int km_flags = (canwait != NULL_FUNC)? KM_SLEEP : KM_NOSLEEP;
    900  3786    arutz 	int rval;
    901  3786    arutz 	char *prop_template = "target%x-dcd-options";
    902  3786    arutz 	int options;
    903  3786    arutz 	char    prop_str[32];
    904  3786    arutz 	int target;
    905  3786    arutz 	diskaddr_t capacity;
    906  3786    arutz 
    907  3786    arutz 	devp = ddi_get_driver_private(devi);
    908  3786    arutz 
    909  3786    arutz 	/*
    910  3786    arutz 	 * Call the routine scsi_probe to do some of the dirty work.
    911  3786    arutz 	 * If the INQUIRY command succeeds, the field dcd_inq in the
    912  3786    arutz 	 * device structure will be filled in. The dcd_sense structure
    913  3786    arutz 	 * will also be allocated.
    914  3786    arutz 	 */
    915  3786    arutz 
    916  3786    arutz 	switch (dcd_probe(devp, canwait)) {
    917  3786    arutz 	default:
    918  3786    arutz 		return (DDI_FAILURE);
    919  3786    arutz 
    920  3786    arutz 	case DCDPROBE_EXISTS:
    921  3786    arutz 		if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
    922  3786    arutz 			if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
    923  3786    arutz 				rval = DDI_SUCCESS;
    924  3786    arutz 			} else {
    925  3786    arutz 				rval = DDI_FAILURE;
    926  3786    arutz 				goto error;
    927  3786    arutz 			}
    928  3786    arutz 		} else {
    929  3786    arutz 			rval = DDI_FAILURE;
    930  3786    arutz 			goto error;
    931  3786    arutz 		}
    932  3786    arutz 	}
    933  3786    arutz 
    934  3786    arutz 
    935  3786    arutz 	instance = ddi_get_instance(devp->dcd_dev);
    936  3786    arutz 
    937  3786    arutz 	if (ddi_soft_state_zalloc(dcd_state, instance) != DDI_SUCCESS) {
    938  3786    arutz 		rval = DDI_FAILURE;
    939  3786    arutz 		goto error;
    940  3786    arutz 	}
    941  3786    arutz 
    942  3786    arutz 	un = ddi_get_soft_state(dcd_state, instance);
    943  3786    arutz 
    944  3786    arutz 	un->un_sbufp = getrbuf(km_flags);
    945  3786    arutz 	if (un->un_sbufp == (struct buf *)NULL) {
    946  3786    arutz 		rval = DDI_FAILURE;
    947  3786    arutz 		goto error;
    948  3786    arutz 	}
    949  3786    arutz 
    950  3786    arutz 
    951  3786    arutz 	un->un_dcd = devp;
    952  3786    arutz 	un->un_power_level = -1;
    953  3786    arutz 	un->un_tgattribute.media_is_writable = 1;
    954  3786    arutz 
    955  3786    arutz 	sema_init(&un->un_semoclose, 1, NULL, SEMA_DRIVER, NULL);
    956  3786    arutz 	cv_init(&un->un_sbuf_cv, NULL, CV_DRIVER, NULL);
    957  3786    arutz 	cv_init(&un->un_state_cv, NULL, CV_DRIVER, NULL);
    958  3786    arutz 	/* Initialize power management conditional variable */
    959  3786    arutz 	cv_init(&un->un_disk_busy_cv, NULL, CV_DRIVER, NULL);
    960  3786    arutz 	cv_init(&un->un_suspend_cv, NULL, CV_DRIVER, NULL);
    961  3786    arutz 
    962  3786    arutz 	if (un->un_dp == 0) {
    963  3786    arutz 		/*
    964  3786    arutz 		 * Assume CCS drive, assume parity, but call
    965  3786    arutz 		 * it a CDROM if it is a RODIRECT device.
    966  3786    arutz 		 */
    967  3786    arutz 		un->un_dp = (struct dcd_drivetype *)
    968  3786    arutz 		    kmem_zalloc(sizeof (struct dcd_drivetype), km_flags);
    969  3786    arutz 		if (!un->un_dp) {
    970  3786    arutz 			rval = DDI_FAILURE;
    971  3786    arutz 			goto error;
    972  3786    arutz 		}
    973  3786    arutz 		if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) {
    974  3786    arutz 			if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) {
    975  3786    arutz 				un->un_dp->ctype = CTYPE_DISK;
    976  3786    arutz 			}
    977  3786    arutz 		} else  {
    978  3786    arutz 			rval = DDI_FAILURE;
    979  3786    arutz 			goto error;
    980  3786    arutz 		}
    981  3786    arutz 		un->un_dp->name = "CCS";
    982  3786    arutz 		un->un_dp->options = 0;
    983  3786    arutz 	}
    984  3786    arutz 
    985  3786    arutz 	/*
    986  3786    arutz 	 * Allow I/O requests at un_secsize offset in multiple of un_secsize.
    987  3786    arutz 	 */
    988  3786    arutz 	un->un_secsize = DEV_BSIZE;
    989  3786    arutz 
    990  3786    arutz 	/*
    991  3786    arutz 	 * If the device is not a removable media device, make sure that
    992  3786    arutz 	 * that the device is ready, by issuing the another identify but
    993  3786    arutz 	 * not needed. Get the capacity from identify data and store here.
    994  3786    arutz 	 */
    995  3786    arutz 	if (dcd_compute_dk_capacity(devp, &capacity) == 0) {
    996  3786    arutz 		un->un_diskcapacity = capacity;
    997  3786    arutz 		un->un_lbasize = DEV_BSIZE;
    998  3786    arutz 	}
    999  3786    arutz 
   1000  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "Geometry Data\n");
   1001  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "cyls %x, heads %x",
   1002  3786    arutz 	    devp->dcd_ident->dcd_fixcyls,
   1003  3786    arutz 	    devp->dcd_ident->dcd_heads);
   1004  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "sectors %x,",
   1005  3786    arutz 	    devp->dcd_ident->dcd_sectors);
   1006  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "capacity %llx\n",
   1007  3786    arutz 	    capacity);
   1008  3786    arutz 
   1009  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1010  3786    arutz 	    "dcdprobe: drive selected\n");
   1011  3786    arutz 
   1012  3786    arutz 	/*
   1013  3786    arutz 	 * Check for the property target<n>-dcd-options to find the option
   1014  3786    arutz 	 * set by the HBA driver for this target so that we can set the
   1015  3786    arutz 	 * Unit structure variable so that we can send commands accordingly.
   1016  3786    arutz 	 */
   1017  7875    Chris 	target = devp->dcd_address->da_target;
   1018  3786    arutz 	(void) sprintf(prop_str, prop_template, target);
   1019  3786    arutz 	options = ddi_prop_get_int(DDI_DEV_T_ANY, devi, DDI_PROP_NOTPROM,
   1020  3786    arutz 	    prop_str, -1);
   1021  3786    arutz 	if (options < 0) {
   1022  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1023  3786    arutz 		    "No per target properties");
   1024  3786    arutz 	} else {
   1025  3786    arutz 		if ((options & DCD_DMA_MODE) == DCD_DMA_MODE) {
   1026  3786    arutz 			un->un_dp->options |= DMA_SUPPORTTED;
   1027  3786    arutz 			un->un_dp->dma_mode = (options >> 3) & 0x03;
   1028  3786    arutz 			DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1029  3786    arutz 			    "mode %x\n", un->un_dp->dma_mode);
   1030  3786    arutz 		} else {
   1031  3786    arutz 			un->un_dp->options &= ~DMA_SUPPORTTED;
   1032  3786    arutz 			un->un_dp->pio_mode = options & 0x7;
   1033  3786    arutz 			if (options & DCD_BLOCK_MODE)
   1034  3786    arutz 				un->un_dp->options |= BLOCK_MODE;
   1035  3786    arutz 			DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1036  3786    arutz 			    "mode %x\n", un->un_dp->pio_mode);
   1037  3786    arutz 		}
   1038  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1039  3786    arutz 		    "options %x,", un->un_dp->options);
   1040  3786    arutz 	}
   1041  3786    arutz 
   1042  3786    arutz 	un->un_throttle = 2;
   1043  3786    arutz 	/*
   1044  3786    arutz 	 * set default max_xfer_size - This should depend on whether the
   1045  3786    arutz 	 * Block mode is supported by the device or not.
   1046  3786    arutz 	 */
   1047  3786    arutz 	un->un_max_xfer_size = MAX_ATA_XFER_SIZE;
   1048  3786    arutz 
   1049  3786    arutz 	/*
   1050  3786    arutz 	 * Set write cache enable softstate
   1051  3786    arutz 	 *
   1052  3786    arutz 	 * WCE is only supported in ATAPI-4 or higher; for
   1053  3786    arutz 	 * lower rev devices, must assume write cache is
   1054  3786    arutz 	 * enabled.
   1055  3786    arutz 	 */
   1056  3786    arutz 	mutex_enter(DCD_MUTEX);
   1057  3786    arutz 	un->un_write_cache_enabled = (devp->dcd_ident->dcd_majvers == 0xffff) ||
   1058  3786    arutz 	    ((devp->dcd_ident->dcd_majvers & IDENTIFY_80_ATAPI_4) == 0) ||
   1059  3786    arutz 	    (devp->dcd_ident->dcd_features85 & IDENTIFY_85_WCE) != 0;
   1060  3786    arutz 	mutex_exit(DCD_MUTEX);
   1061  3786    arutz 
   1062  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1063  3786    arutz 	    "dcd_doattach returns good\n");
   1064  3786    arutz 
   1065  3786    arutz 	return (rval);
   1066  3786    arutz 
   1067  3786    arutz error:
   1068  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcd_doattach failed\n");
   1069  3786    arutz 	dcd_free_softstate(un, devi);
   1070  3786    arutz 	return (rval);
   1071  3786    arutz }
   1072  3786    arutz 
   1073  3786    arutz #ifdef NOTNEEDED
   1074  3786    arutz /*
   1075  3786    arutz  * This routine is used to set the block mode of operation by issuing the
   1076  3786    arutz  * Set Block mode ata command with the maximum block mode possible
   1077  3786    arutz  */
   1078  3786    arutz dcd_set_multiple(struct dcd_disk *un)
   1079  3786    arutz {
   1080  3786    arutz 	int status;
   1081  3786    arutz 	struct udcd_cmd ucmd;
   1082  3786    arutz 	struct dcd_cmd cdb;
   1083  3786    arutz 	dev_t	dev;
   1084  3786    arutz 
   1085  3786    arutz 
   1086  3786    arutz 	/* Zero all the required structure */
   1087  3786    arutz 	(void) bzero((caddr_t)&ucmd, sizeof (ucmd));
   1088  3786    arutz 
   1089  3786    arutz 	(void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd));
   1090  3786    arutz 
   1091  3786    arutz 	cdb.cmd = ATA_SET_MULTIPLE;
   1092  3786    arutz 	/*
   1093  3786    arutz 	 * Here we should pass what needs to go into sector count REGISTER.
   1094  3786    arutz 	 * Eventhough this field indicates the number of bytes to read we
   1095  3786    arutz 	 * need to specify the block factor in terms of bytes so that it
   1096  3786    arutz 	 * will be programmed by the HBA driver into the sector count register.
   1097  3786    arutz 	 */
   1098  3786    arutz 	cdb.size = un->un_lbasize * un->un_dp->block_factor;
   1099  3786    arutz 
   1100  3786    arutz 	cdb.sector_num.lba_num = 0;
   1101  3786    arutz 	cdb.address_mode = ADD_LBA_MODE;
   1102  3786    arutz 	cdb.direction = NO_DATA_XFER;
   1103  3786    arutz 
   1104  3786    arutz 	ucmd.udcd_flags = 0;
   1105  3786    arutz 	ucmd.udcd_cmd = &cdb;
   1106  3786    arutz 	ucmd.udcd_bufaddr = NULL;
   1107  3786    arutz 	ucmd.udcd_buflen = 0;
   1108  3786    arutz 	ucmd.udcd_flags |= UDCD_SILENT;
   1109  3786    arutz 
   1110  3786    arutz 	dev = makedevice(ddi_driver_major(DCD_DEVINFO),
   1111  3786    arutz 	    ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT);
   1112  3786    arutz 
   1113  3786    arutz 
   1114  3786    arutz 	status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE);
   1115  3786    arutz 
   1116  3786    arutz 	return (status);
   1117  3786    arutz }
   1118  3786    arutz /*
   1119  3786    arutz  * The following routine is used only for setting the transfer mode
   1120  3786    arutz  * and it is not designed for transferring any other features subcommand.
   1121  3786    arutz  */
   1122  3786    arutz dcd_set_features(struct dcd_disk *un, uchar_t mode)
   1123  3786    arutz {
   1124  3786    arutz 	int status;
   1125  3786    arutz 	struct udcd_cmd ucmd;
   1126  3786    arutz 	struct dcd_cmd cdb;
   1127  3786    arutz 	dev_t	dev;
   1128  3786    arutz 
   1129  3786    arutz 
   1130  3786    arutz 	/* Zero all the required structure */
   1131  3786    arutz 	(void) bzero((caddr_t)&ucmd, sizeof (ucmd));
   1132  3786    arutz 
   1133  3786    arutz 	(void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd));
   1134  3786    arutz 
   1135  3786    arutz 	cdb.cmd = ATA_SET_FEATURES;
   1136  3786    arutz 	/*
   1137  3786    arutz 	 * Here we need to pass what needs to go into the sector count register
   1138  3786    arutz 	 * But in the case of SET FEATURES command the value taken in the
   1139  3786    arutz 	 * sector count register depends what type of subcommand is
   1140  3786    arutz 	 * passed in the features register. Since we have defined the size to
   1141  3786    arutz 	 * be the size in bytes in this context it does not indicate bytes
   1142  3786    arutz 	 * instead it indicates the mode to be programmed.
   1143  3786    arutz 	 */
   1144  3786    arutz 	cdb.size = un->un_lbasize * mode;
   1145  3786    arutz 
   1146  3786    arutz 	cdb.sector_num.lba_num = 0;
   1147  3786    arutz 	cdb.address_mode = ADD_LBA_MODE;
   1148  3786    arutz 	cdb.direction = NO_DATA_XFER;
   1149  3786    arutz 	cdb.features = ATA_FEATURE_SET_MODE;
   1150  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1151  3786    arutz 	    "size %x, features %x, cmd %x\n",
   1152  3786    arutz 	    cdb.size, cdb.features, cdb.cmd);
   1153  3786    arutz 
   1154  3786    arutz 	ucmd.udcd_flags = 0;
   1155  3786    arutz 	ucmd.udcd_cmd = &cdb;
   1156  3786    arutz 	ucmd.udcd_bufaddr = NULL;
   1157  3786    arutz 	ucmd.udcd_buflen = 0;
   1158  3786    arutz 	ucmd.udcd_flags |= UDCD_SILENT;
   1159  3786    arutz 
   1160  3786    arutz 	dev = makedevice(ddi_driver_major(DCD_DEVINFO),
   1161  3786    arutz 	    ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT);
   1162  3786    arutz 
   1163  3786    arutz 	status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE);
   1164  3786    arutz 
   1165  3786    arutz 	return (status);
   1166  3786    arutz }
   1167  3786    arutz #endif
   1168  3786    arutz 
   1169  3786    arutz /*
   1170  3786    arutz  * Validate the geometry for this disk, e.g.,
   1171  3786    arutz  * see whether it has a valid label.
   1172  3786    arutz  */
   1173  3786    arutz static int
   1174  3786    arutz dcd_validate_geometry(struct dcd_disk *un)
   1175  3786    arutz {
   1176  3786    arutz 	int secsize = 0;
   1177  3786    arutz 	struct  dcd_device *devp;
   1178  3786    arutz 	int secdiv;
   1179  3786    arutz 	int rval;
   1180  3786    arutz 
   1181  3786    arutz 	ASSERT(mutex_owned(DCD_MUTEX));
   1182  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1183  3786    arutz 	    "dcd_validate_geometry: started \n");
   1184  3786    arutz 
   1185  3786    arutz 	if (un->un_lbasize < 0) {
   1186  3786    arutz 		return (DCD_BAD_LABEL);
   1187  3786    arutz 	}
   1188  3786    arutz 
   1189  3786    arutz 	if (un->un_state == DCD_STATE_PM_SUSPENDED) {
   1190  3786    arutz 		mutex_exit(DCD_MUTEX);
   1191  7224      cth 		if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) !=
   1192  7224      cth 		    DDI_SUCCESS) {
   1193  3786    arutz 			mutex_enter(DCD_MUTEX);
   1194  3786    arutz 			return (DCD_BAD_LABEL);
   1195  3786    arutz 		}
   1196  3786    arutz 		mutex_enter(DCD_MUTEX);
   1197  3786    arutz 	}
   1198  3786    arutz 
   1199  3786    arutz 	secsize = un->un_secsize;
   1200  3786    arutz 
   1201  3786    arutz 	/*
   1202  3786    arutz 	 * take a log base 2 of sector size (sorry)
   1203  3786    arutz 	 */
   1204  3786    arutz 	for (secdiv = 0; secsize = secsize >> 1; secdiv++)
   1205  3786    arutz 		;
   1206  3786    arutz 	un->un_secdiv = secdiv;
   1207  3786    arutz 
   1208  3786    arutz 	/*
   1209  3786    arutz 	 * Only DIRECT ACCESS devices will have Sun labels.
   1210  3786    arutz 	 * CD's supposedly have a Sun label, too
   1211  3786    arutz 	 */
   1212  3786    arutz 
   1213  3786    arutz 	devp = un->un_dcd;
   1214  3786    arutz 
   1215  3786    arutz 	if (((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) &&
   1216  3786    arutz 	    (devp->dcd_ident->dcd_config & ATANON_REMOVABLE)) {
   1217  3786    arutz 		mutex_exit(DCD_MUTEX);
   1218  3786    arutz 		rval = cmlb_validate(un->un_dklbhandle, 0, 0);
   1219  3786    arutz 		mutex_enter(DCD_MUTEX);
   1220  3786    arutz 		if (rval == ENOMEM)
   1221  3786    arutz 			return (DCD_NO_MEM_FOR_LABEL);
   1222  3786    arutz 		else if (rval != 0)
   1223  3786    arutz 			return (DCD_BAD_LABEL);
   1224  3786    arutz 	} else {
   1225  3786    arutz 		/* it should never get here. */
   1226  3786    arutz 		return (DCD_BAD_LABEL);
   1227  3786    arutz 	}
   1228  3786    arutz 
   1229  3786    arutz 	/*
   1230  3786    arutz 	 * take a log base 2 of logical block size
   1231  3786    arutz 	 */
   1232  3786    arutz 	secsize = un->un_lbasize;
   1233  3786    arutz 	for (secdiv = 0; secsize = secsize >> 1; secdiv++)
   1234  3786    arutz 		;
   1235  3786    arutz 	un->un_lbadiv = secdiv;
   1236  3786    arutz 
   1237  3786    arutz 	/*
   1238  3786    arutz 	 * take a log base 2 of the multiple of DEV_BSIZE blocks that
   1239  3786    arutz 	 * make up one logical block
   1240  3786    arutz 	 */
   1241  3786    arutz 	secsize = un->un_lbasize >> DEV_BSHIFT;
   1242  3786    arutz 	for (secdiv = 0; secsize = secsize >> 1; secdiv++)
   1243  3786    arutz 		;
   1244  3786    arutz 	un->un_blknoshift = secdiv;
   1245  3786    arutz 	return (0);
   1246  3786    arutz }
   1247  3786    arutz 
   1248  3786    arutz /*
   1249  3786    arutz  * Unix Entry Points
   1250  3786    arutz  */
   1251  3786    arutz 
   1252  3786    arutz /* ARGSUSED3 */
   1253  3786    arutz static int
   1254  3786    arutz dcdopen(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
   1255  3786    arutz {
   1256  3786    arutz 	dev_t dev = *dev_p;
   1257  3786    arutz 	int rval = EIO;
   1258  3786    arutz 	int partmask;
   1259  3786    arutz 	int nodelay = (flag & (FNDELAY | FNONBLOCK));
   1260  3786    arutz 	int i;
   1261  3786    arutz 	char kstatname[KSTAT_STRLEN];
   1262  3786    arutz 	diskaddr_t lblocks;
   1263  3786    arutz 	char *partname;
   1264  3786    arutz 
   1265  3786    arutz 	GET_SOFT_STATE(dev);
   1266  3786    arutz 
   1267  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1268  3786    arutz 	    "Inside Open flag %x, otyp %x\n", flag, otyp);
   1269  3786    arutz 
   1270  3786    arutz 	if (otyp >= OTYPCNT) {
   1271  3786    arutz 		return (EINVAL);
   1272  3786    arutz 	}
   1273  3786    arutz 
   1274  3786    arutz 	partmask = 1 << part;
   1275  3786    arutz 
   1276  3786    arutz 	/*
   1277  3786    arutz 	 * We use a semaphore here in order to serialize
   1278  3786    arutz 	 * open and close requests on the device.
   1279  3786    arutz 	 */
   1280  3786    arutz 	sema_p(&un->un_semoclose);
   1281  3786    arutz 
   1282  3786    arutz 	mutex_enter(DCD_MUTEX);
   1283  3786    arutz 
   1284  3786    arutz 	if ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL) {
   1285  3786    arutz 		rval = ENXIO;
   1286  3786    arutz 		goto done;
   1287  3786    arutz 	}
   1288  3786    arutz 
   1289  3786    arutz 	while (un->un_state == DCD_STATE_SUSPENDED) {
   1290  3786    arutz 		cv_wait(&un->un_suspend_cv, DCD_MUTEX);
   1291  3786    arutz 	}
   1292  3786    arutz 
   1293  3786    arutz 	if ((un->un_state == DCD_STATE_PM_SUSPENDED) && (!nodelay)) {
   1294  3786    arutz 		mutex_exit(DCD_MUTEX);
   1295  3786    arutz 		if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE)
   1296  3786    arutz 		    != DDI_SUCCESS) {
   1297  3786    arutz 			mutex_enter(DCD_MUTEX);
   1298  3786    arutz 			rval = EIO;
   1299  3786    arutz 			goto done;
   1300  3786    arutz 		}
   1301  3786    arutz 		mutex_enter(DCD_MUTEX);
   1302  3786    arutz 	}
   1303  3786    arutz 
   1304  3786    arutz 	/*
   1305  3786    arutz 	 * set make_dcd_cmd() flags and stat_size here since these
   1306  3786    arutz 	 * are unlikely to change
   1307  3786    arutz 	 */
   1308  3786    arutz 	un->un_cmd_flags = 0;
   1309  3786    arutz 
   1310  3786    arutz 	un->un_cmd_stat_size = 2;
   1311  3786    arutz 
   1312  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdopen un=0x%p\n",
   1313  3786    arutz 	    (void *)un);
   1314  3786    arutz 	/*
   1315  3786    arutz 	 * check for previous exclusive open
   1316  3786    arutz 	 */
   1317  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1318  3786    arutz 	    "exclopen=%x, flag=%x, regopen=%x\n",
   1319  3786    arutz 	    un->un_exclopen, flag, un->un_ocmap.regopen[otyp]);
   1320  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1321  3786    arutz 	    "Exclusive open flag %x, partmask %x\n",
   1322  3786    arutz 	    un->un_exclopen, partmask);
   1323  3786    arutz 
   1324  3786    arutz 	if (un->un_exclopen & (partmask)) {
   1325  3786    arutz failed_exclusive:
   1326  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1327  3786    arutz 		    "exclusive open fails\n");
   1328  3786    arutz 		rval = EBUSY;
   1329  3786    arutz 		goto done;
   1330  3786    arutz 	}
   1331  3786    arutz 
   1332  3786    arutz 	if (flag & FEXCL) {
   1333  3786    arutz 		int i;
   1334  3786    arutz 		if (un->un_ocmap.lyropen[part]) {
   1335  3786    arutz 			goto failed_exclusive;
   1336  3786    arutz 		}
   1337  3786    arutz 		for (i = 0; i < (OTYPCNT - 1); i++) {
   1338  3786    arutz 			if (un->un_ocmap.regopen[i] & (partmask)) {
   1339  3786    arutz 				goto failed_exclusive;
   1340  3786    arutz 			}
   1341  3786    arutz 		}
   1342  3786    arutz 	}
   1343  3786    arutz 	if (flag & FWRITE) {
   1344  3786    arutz 		mutex_exit(DCD_MUTEX);
   1345  3786    arutz 		if (dcd_check_wp(dev)) {
   1346  3786    arutz 			sema_v(&un->un_semoclose);
   1347  3786    arutz 			return (EROFS);
   1348  3786    arutz 		}
   1349  3786    arutz 		mutex_enter(DCD_MUTEX);
   1350  3786    arutz 	}
   1351  3786    arutz 
   1352  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1353  3786    arutz 	    "Check Write Protect handled\n");
   1354  3786    arutz 
   1355  3786    arutz 	if (!nodelay) {
   1356  3786    arutz 		mutex_exit(DCD_MUTEX);
   1357  3786    arutz 		if ((rval = dcd_ready_and_valid(dev, un)) != 0) {
   1358  3786    arutz 			rval = EIO;
   1359  3786    arutz 		}
   1360  3786    arutz 		(void) pm_idle_component(DCD_DEVINFO, 0);
   1361  3786    arutz 		/*
   1362  3786    arutz 		 * Fail if device is not ready or if the number of disk
   1363  3786    arutz 		 * blocks is zero or negative for non CD devices.
   1364  3786    arutz 		 */
   1365  3786    arutz 		if (rval || cmlb_partinfo(un->un_dklbhandle,
   1366  3786    arutz 		    part, &lblocks, NULL, &partname, NULL, 0) ||
   1367  3786    arutz 		    lblocks <= 0) {
   1368  3786    arutz 			rval = EIO;
   1369  3786    arutz 			mutex_enter(DCD_MUTEX);
   1370  3786    arutz 			goto done;
   1371  3786    arutz 		}
   1372  3786    arutz 		mutex_enter(DCD_MUTEX);
   1373  3786    arutz 	}
   1374  3786    arutz 
   1375  3786    arutz 	if (otyp == OTYP_LYR) {
   1376  3786    arutz 		un->un_ocmap.lyropen[part]++;
   1377  3786    arutz 	} else {
   1378  3786    arutz 		un->un_ocmap.regopen[otyp] |= partmask;
   1379  3786    arutz 	}
   1380  3786    arutz 
   1381  3786    arutz 	/*
   1382  3786    arutz 	 * set up open and exclusive open flags
   1383  3786    arutz 	 */
   1384  3786    arutz 	if (flag & FEXCL) {
   1385  3786    arutz 		un->un_exclopen |= (partmask);
   1386  3786    arutz 	}
   1387  3786    arutz 
   1388  3786    arutz 
   1389  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1390  3786    arutz 	    "open of part %d type %d\n",
   1391  3786    arutz 	    part, otyp);
   1392  3786    arutz 
   1393  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1394  3786    arutz 	    "Kstats getting updated\n");
   1395  3786    arutz 	/*
   1396  3786    arutz 	 * only create kstats for disks, CD kstats created in dcdattach
   1397  3786    arutz 	 */
   1398  3786    arutz 	_NOTE(NO_COMPETING_THREADS_NOW);
   1399  3786    arutz 	mutex_exit(DCD_MUTEX);
   1400  3786    arutz 	if (un->un_stats == (kstat_t *)0) {
   1401  3786    arutz 		un->un_stats = kstat_create("dad", instance,
   1402  3786    arutz 		    NULL, "disk", KSTAT_TYPE_IO, 1,
   1403  3786    arutz 		    KSTAT_FLAG_PERSISTENT);
   1404  3786    arutz 		if (un->un_stats) {
   1405  3786    arutz 			un->un_stats->ks_lock = DCD_MUTEX;
   1406  3786    arutz 			kstat_install(un->un_stats);
   1407  3786    arutz 		}
   1408  3786    arutz 
   1409  3786    arutz 		/*
   1410  3786    arutz 		 * set up partition statistics for each partition
   1411  3786    arutz 		 * with number of blocks > 0
   1412  3786    arutz 		 */
   1413  3786    arutz 		if (!nodelay) {
   1414  3786    arutz 			for (i = 0; i < NDKMAP; i++) {
   1415  3786    arutz 				if ((un->un_pstats[i] == (kstat_t *)0) &&
   1416  3786    arutz 				    (cmlb_partinfo(un->un_dklbhandle,
   1417  3786    arutz 				    i, &lblocks, NULL, &partname,
   1418  3786    arutz 				    NULL, 0) == 0) && lblocks > 0) {
   1419  3786    arutz 					(void) sprintf(kstatname, "dad%d,%s",
   1420  3786    arutz 					    instance, partname);
   1421  3786    arutz 					un->un_pstats[i] = kstat_create("dad",
   1422  3786    arutz 					    instance,
   1423  3786    arutz 					    kstatname,
   1424  3786    arutz 					    "partition",
   1425  3786    arutz 					    KSTAT_TYPE_IO,
   1426  3786    arutz 					    1,
   1427  3786    arutz 					    KSTAT_FLAG_PERSISTENT);
   1428  3786    arutz 					if (un->un_pstats[i]) {
   1429  3786    arutz 						un->un_pstats[i]->ks_lock =
   1430  3786    arutz 						    DCD_MUTEX;
   1431  3786    arutz 						kstat_install(un->un_pstats[i]);
   1432  3786    arutz 					}
   1433  3786    arutz 				}
   1434  3786    arutz 			}
   1435  3786    arutz 		}
   1436  3786    arutz 		/*
   1437  3786    arutz 		 * set up error kstats
   1438  3786    arutz 		 */
   1439  3786    arutz 		(void) dcd_create_errstats(un, instance);
   1440  3786    arutz 	}
   1441  3786    arutz #ifndef lint
   1442  3786    arutz 	_NOTE(COMPETING_THREADS_NOW);
   1443  3786    arutz #endif
   1444  3786    arutz 
   1445  3786    arutz 	sema_v(&un->un_semoclose);
   1446  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "Open success\n");
   1447  3786    arutz 	return (0);
   1448  3786    arutz 
   1449  3786    arutz done:
   1450  3786    arutz 	mutex_exit(DCD_MUTEX);
   1451  3786    arutz 	sema_v(&un->un_semoclose);
   1452  3786    arutz 	return (rval);
   1453  3786    arutz 
   1454  3786    arutz }
   1455  3786    arutz 
   1456  3786    arutz /*
   1457  3786    arutz  * Test if disk is ready and has a valid geometry.
   1458  3786    arutz  */
   1459  3786    arutz static int
   1460  3786    arutz dcd_ready_and_valid(dev_t dev, struct dcd_disk *un)
   1461  3786    arutz {
   1462  3786    arutz 	int rval = 1;
   1463  3786    arutz 	int g_error = 0;
   1464  3786    arutz 
   1465  3786    arutz 	mutex_enter(DCD_MUTEX);
   1466  3786    arutz 	/*
   1467  3786    arutz 	 * cmds outstanding
   1468  3786    arutz 	 */
   1469  3786    arutz 	if (un->un_ncmds == 0) {
   1470  3786    arutz 		(void) dcd_unit_ready(dev);
   1471  3786    arutz 	}
   1472  3786    arutz 
   1473  3786    arutz 	/*
   1474  3786    arutz 	 * If device is not yet ready here, inform it is offline
   1475  3786    arutz 	 */
   1476  3786    arutz 	if (un->un_state == DCD_STATE_NORMAL) {
   1477  3786    arutz 		rval = dcd_unit_ready(dev);
   1478  3786    arutz 		if (rval != 0 && rval != EACCES) {
   1479  3786    arutz 			dcd_offline(un, 1);
   1480  3786    arutz 			goto done;
   1481  3786    arutz 		}
   1482  3786    arutz 	}
   1483  3786    arutz 
   1484  3786    arutz 	if (un->un_format_in_progress == 0) {
   1485  3786    arutz 		g_error = dcd_validate_geometry(un);
   1486  3786    arutz 	}
   1487  3786    arutz 
   1488  3786    arutz 	/*
   1489  3786    arutz 	 * check if geometry was valid. We don't check the validity of
   1490  3786    arutz 	 * geometry for CDROMS.
   1491  3786    arutz 	 */
   1492  3786    arutz 
   1493  3786    arutz 	if (g_error == DCD_BAD_LABEL) {
   1494  3786    arutz 		rval = 1;
   1495  3786    arutz 		goto done;
   1496  3786    arutz 	}
   1497  3786    arutz 
   1498  3786    arutz 
   1499  3786    arutz 	/*
   1500  3786    arutz 	 * the state has changed; inform the media watch routines
   1501  3786    arutz 	 */
   1502  3786    arutz 	un->un_mediastate = DKIO_INSERTED;
   1503  3786    arutz 	cv_broadcast(&un->un_state_cv);
   1504  3786    arutz 	rval = 0;
   1505  3786    arutz 
   1506  3786    arutz done:
   1507  3786    arutz 	mutex_exit(DCD_MUTEX);
   1508  3786    arutz 	return (rval);
   1509  3786    arutz }
   1510  3786    arutz 
   1511  3786    arutz 
   1512  3786    arutz /*ARGSUSED*/
   1513  3786    arutz static int
   1514  3786    arutz dcdclose(dev_t dev, int flag, int otyp, cred_t *cred_p)
   1515  3786    arutz {
   1516  3786    arutz 	uchar_t *cp;
   1517  3786    arutz 	int i;
   1518  3786    arutz 
   1519  3786    arutz 	GET_SOFT_STATE(dev);
   1520  3786    arutz 
   1521  3786    arutz 
   1522  3786    arutz 	if (otyp >= OTYPCNT)
   1523  3786    arutz 		return (ENXIO);
   1524  3786    arutz 
   1525  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1526  3786    arutz 	    "close of part %d type %d\n",
   1527  3786    arutz 	    part, otyp);
   1528  3786    arutz 	sema_p(&un->un_semoclose);
   1529  3786    arutz 
   1530  3786    arutz 	mutex_enter(DCD_MUTEX);
   1531  3786    arutz 
   1532  3786    arutz 	if (un->un_exclopen & (1<<part)) {
   1533  3786    arutz 		un->un_exclopen &= ~(1<<part);
   1534  3786    arutz 	}
   1535  3786    arutz 
   1536  3786    arutz 	if (otyp == OTYP_LYR) {
   1537  3786    arutz 		un->un_ocmap.lyropen[part] -= 1;
   1538  3786    arutz 	} else {
   1539  3786    arutz 		un->un_ocmap.regopen[otyp] &= ~(1<<part);
   1540  3786    arutz 	}
   1541  3786    arutz 
   1542  3786    arutz 	cp = &un->un_ocmap.chkd[0];
   1543  3786    arutz 	while (cp < &un->un_ocmap.chkd[OCSIZE]) {
   1544  3786    arutz 		if (*cp != (uchar_t)0) {
   1545  3786    arutz 			break;
   1546  3786    arutz 		}
   1547  3786    arutz 		cp++;
   1548  3786    arutz 	}
   1549  3786    arutz 
   1550  3786    arutz 	if (cp == &un->un_ocmap.chkd[OCSIZE]) {
   1551  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "last close\n");
   1552  3786    arutz 		if (un->un_state == DCD_STATE_OFFLINE) {
   1553  3786    arutz 			dcd_offline(un, 1);
   1554  3786    arutz 		}
   1555  3786    arutz 
   1556  3786    arutz 		mutex_exit(DCD_MUTEX);
   1557  3786    arutz 		(void) cmlb_close(un->un_dklbhandle, 0);
   1558  3786    arutz 
   1559  3786    arutz 		_NOTE(NO_COMPETING_THREADS_NOW);
   1560  3786    arutz 		if (un->un_stats) {
   1561  3786    arutz 			kstat_delete(un->un_stats);
   1562  3786    arutz 			un->un_stats = 0;
   1563  3786    arutz 		}
   1564  3786    arutz 		for (i = 0; i < NDKMAP; i++) {
   1565  3786    arutz 			if (un->un_pstats[i]) {
   1566  3786    arutz 				kstat_delete(un->un_pstats[i]);
   1567  3786    arutz 				un->un_pstats[i] = (kstat_t *)0;
   1568  3786    arutz 			}
   1569  3786    arutz 		}
   1570  3786    arutz 
   1571  3786    arutz 		if (un->un_errstats) {
   1572  3786    arutz 			kstat_delete(un->un_errstats);
   1573  3786    arutz 			un->un_errstats = (kstat_t *)0;
   1574  3786    arutz 		}
   1575  3786    arutz 		mutex_enter(DCD_MUTEX);
   1576  3786    arutz 
   1577  3786    arutz #ifndef lint
   1578  3786    arutz 		_NOTE(COMPETING_THREADS_NOW);
   1579  3786    arutz #endif
   1580  3786    arutz 	}
   1581  3786    arutz 
   1582  3786    arutz 	mutex_exit(DCD_MUTEX);
   1583  3786    arutz 	sema_v(&un->un_semoclose);
   1584  3786    arutz 	return (0);
   1585  3786    arutz }
   1586  3786    arutz 
   1587  3786    arutz static void
   1588  3786    arutz dcd_offline(struct dcd_disk *un, int bechatty)
   1589  3786    arutz {
   1590  3786    arutz 	if (bechatty)
   1591  3786    arutz 		dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "offline\n");
   1592  3786    arutz 
   1593  3786    arutz 	mutex_exit(DCD_MUTEX);
   1594  3786    arutz 	cmlb_invalidate(un->un_dklbhandle, 0);
   1595  3786    arutz 	mutex_enter(DCD_MUTEX);
   1596  3786    arutz }
   1597  3786    arutz 
   1598  3786    arutz /*
   1599  3786    arutz  * Given the device number return the devinfo pointer
   1600  3786    arutz  * from the scsi_device structure.
   1601  3786    arutz  */
   1602  3786    arutz /*ARGSUSED*/
   1603  3786    arutz static int
   1604  3786    arutz dcdinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
   1605  3786    arutz {
   1606  3786    arutz 	dev_t dev;
   1607  3786    arutz 	struct dcd_disk *un;
   1608  3786    arutz 	int instance, error;
   1609  3786    arutz 
   1610  3786    arutz 
   1611  3786    arutz 	switch (infocmd) {
   1612  3786    arutz 	case DDI_INFO_DEVT2DEVINFO:
   1613  3786    arutz 		dev = (dev_t)arg;
   1614  3786    arutz 		instance = DCDUNIT(dev);
   1615  3786    arutz 		if ((un = ddi_get_soft_state(dcd_state, instance)) == NULL)
   1616  3786    arutz 			return (DDI_FAILURE);
   1617  3786    arutz 		*result = (void *) DCD_DEVINFO;
   1618  3786    arutz 		error = DDI_SUCCESS;
   1619  3786    arutz 		break;
   1620  3786    arutz 	case DDI_INFO_DEVT2INSTANCE:
   1621  3786    arutz 		dev = (dev_t)arg;
   1622  3786    arutz 		instance = DCDUNIT(dev);
   1623  3786    arutz 		*result = (void *)(uintptr_t)instance;
   1624  3786    arutz 		error = DDI_SUCCESS;
   1625  3786    arutz 		break;
   1626  3786    arutz 	default:
   1627  3786    arutz 		error = DDI_FAILURE;
   1628  3786    arutz 	}
   1629  3786    arutz 	return (error);
   1630  3786    arutz }
   1631  3786    arutz 
   1632  3786    arutz /*
   1633  3786    arutz  * property operation routine.	return the number of blocks for the partition
   1634  3786    arutz  * in question or forward the request to the propery facilities.
   1635  3786    arutz  */
   1636  3786    arutz static int
   1637  3786    arutz dcd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
   1638  3786    arutz     char *name, caddr_t valuep, int *lengthp)
   1639  3786    arutz {
   1640  3786    arutz 	struct dcd_disk	*un;
   1641  7224      cth 
   1642  7224      cth 	if ((un = ddi_get_soft_state(dcd_state, ddi_get_instance(dip))) == NULL)
   1643  3786    arutz 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
   1644  3786    arutz 		    name, valuep, lengthp));
   1645  7224      cth 
   1646  7224      cth 	return (cmlb_prop_op(un->un_dklbhandle,
   1647  7224      cth 	    dev, dip, prop_op, mod_flags, name, valuep, lengthp,
   1648  7224      cth 	    DCDPART(dev), NULL));
   1649  3786    arutz }
   1650  3786    arutz 
   1651  3786    arutz /*
   1652  3786    arutz  * These routines perform raw i/o operations.
   1653  3786    arutz  */
   1654  3786    arutz /*ARGSUSED*/
   1655  3786    arutz void
   1656  3786    arutz dcduscsimin(struct buf *bp)
   1657  3786    arutz {
   1658  3786    arutz 
   1659  3786    arutz }
   1660  3786    arutz 
   1661  3786    arutz 
   1662  3786    arutz static void
   1663  3786    arutz dcdmin(struct buf *bp)
   1664  3786    arutz {
   1665  3786    arutz 	struct dcd_disk *un;
   1666  3786    arutz 	int instance;
   1667  3786    arutz 	minor_t minor = getminor(bp->b_edev);
   1668  3786    arutz 	instance = minor >> DCDUNIT_SHIFT;
   1669  3786    arutz 	un = ddi_get_soft_state(dcd_state, instance);
   1670  3786    arutz 
   1671  3786    arutz 	if (bp->b_bcount > un->un_max_xfer_size)
   1672  3786    arutz 		bp->b_bcount = un->un_max_xfer_size;
   1673  3786    arutz }
   1674  3786    arutz 
   1675  3786    arutz 
   1676  3786    arutz /* ARGSUSED2 */
   1677  3786    arutz static int
   1678  3786    arutz dcdread(dev_t dev, struct uio *uio, cred_t *cred_p)
   1679  3786    arutz {
   1680  3786    arutz 	int secmask;
   1681  3786    arutz 	GET_SOFT_STATE(dev);
   1682  3786    arutz #ifdef lint
   1683  3786    arutz 	part = part;
   1684  3786    arutz #endif /* lint */
   1685  3786    arutz 	secmask = un->un_secsize - 1;
   1686  3786    arutz 
   1687  3786    arutz 	if (uio->uio_loffset & ((offset_t)(secmask))) {
   1688  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1689  3786    arutz 		    "file offset not modulo %d\n",
   1690  3786    arutz 		    un->un_secsize);
   1691  3786    arutz 		return (EINVAL);
   1692  3786    arutz 	} else if (uio->uio_iov->iov_len & (secmask)) {
   1693  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1694  3786    arutz 		    "transfer length not modulo %d\n", un->un_secsize);
   1695  3786    arutz 		return (EINVAL);
   1696  3786    arutz 	}
   1697  3786    arutz 	return (physio(dcdstrategy, (struct buf *)0, dev, B_READ, dcdmin, uio));
   1698  3786    arutz }
   1699  3786    arutz 
   1700  3786    arutz /* ARGSUSED2 */
   1701  3786    arutz static int
   1702  3786    arutz dcdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p)
   1703  3786    arutz {
   1704  3786    arutz 	int secmask;
   1705  3786    arutz 	struct uio *uio = aio->aio_uio;
   1706  3786    arutz 	GET_SOFT_STATE(dev);
   1707  3786    arutz #ifdef lint
   1708  3786    arutz 	part = part;
   1709  3786    arutz #endif /* lint */
   1710  3786    arutz 	secmask = un->un_secsize - 1;
   1711  3786    arutz 
   1712  3786    arutz 	if (uio->uio_loffset & ((offset_t)(secmask))) {
   1713  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1714  3786    arutz 		    "file offset not modulo %d\n",
   1715  3786    arutz 		    un->un_secsize);
   1716  3786    arutz 		return (EINVAL);
   1717  3786    arutz 	} else if (uio->uio_iov->iov_len & (secmask)) {
   1718  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1719  3786    arutz 		    "transfer length not modulo %d\n", un->un_secsize);
   1720  3786    arutz 		return (EINVAL);
   1721  3786    arutz 	}
   1722  3786    arutz 	return (aphysio(dcdstrategy, anocancel, dev, B_READ, dcdmin, aio));
   1723  3786    arutz }
   1724  3786    arutz 
   1725  3786    arutz /* ARGSUSED2 */
   1726  3786    arutz static int
   1727  3786    arutz dcdwrite(dev_t dev, struct uio *uio, cred_t *cred_p)
   1728  3786    arutz {
   1729  3786    arutz 	int secmask;
   1730  3786    arutz 	GET_SOFT_STATE(dev);
   1731  3786    arutz #ifdef lint
   1732  3786    arutz 	part = part;
   1733  3786    arutz #endif /* lint */
   1734  3786    arutz 	secmask = un->un_secsize - 1;
   1735  3786    arutz 
   1736  3786    arutz 	if (uio->uio_loffset & ((offset_t)(secmask))) {
   1737  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1738  3786    arutz 		    "file offset not modulo %d\n",
   1739  3786    arutz 		    un->un_secsize);
   1740  3786    arutz 		return (EINVAL);
   1741  3786    arutz 	} else if (uio->uio_iov->iov_len & (secmask)) {
   1742  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1743  3786    arutz 		    "transfer length not modulo %d\n", un->un_secsize);
   1744  3786    arutz 		return (EINVAL);
   1745  3786    arutz 	}
   1746  3786    arutz 	return (physio(dcdstrategy, (struct buf *)0, dev, B_WRITE, dcdmin,
   1747  3786    arutz 	    uio));
   1748  3786    arutz }
   1749  3786    arutz 
   1750  3786    arutz /* ARGSUSED2 */
   1751  3786    arutz static int
   1752  3786    arutz dcdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p)
   1753  3786    arutz {
   1754  3786    arutz 	int secmask;
   1755  3786    arutz 	struct uio *uio = aio->aio_uio;
   1756  3786    arutz 	GET_SOFT_STATE(dev);
   1757  3786    arutz #ifdef lint
   1758  3786    arutz 	part = part;
   1759  3786    arutz #endif /* lint */
   1760  3786    arutz 	secmask = un->un_secsize - 1;
   1761  3786    arutz 
   1762  3786    arutz 	if (uio->uio_loffset & ((offset_t)(secmask))) {
   1763  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1764  3786    arutz 		    "file offset not modulo %d\n",
   1765  3786    arutz 		    un->un_secsize);
   1766  3786    arutz 		return (EINVAL);
   1767  3786    arutz 	} else if (uio->uio_iov->iov_len & (secmask)) {
   1768  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1769  3786    arutz 		    "transfer length not modulo %d\n", un->un_secsize);
   1770  3786    arutz 		return (EINVAL);
   1771  3786    arutz 	}
   1772  3786    arutz 	return (aphysio(dcdstrategy, anocancel, dev, B_WRITE, dcdmin, aio));
   1773  3786    arutz }
   1774  3786    arutz 
   1775  3786    arutz /*
   1776  3786    arutz  * strategy routine
   1777  3786    arutz  */
   1778  3786    arutz static int
   1779  3786    arutz dcdstrategy(struct buf *bp)
   1780  3786    arutz {
   1781  3786    arutz 	struct dcd_disk *un;
   1782  3786    arutz 	struct diskhd *dp;
   1783  3786    arutz 	int i;
   1784  3786    arutz 	minor_t minor = getminor(bp->b_edev);
   1785  3786    arutz 	diskaddr_t p_lblksrt;
   1786  3786    arutz 	diskaddr_t lblocks;
   1787  3786    arutz 	diskaddr_t bn;
   1788  3786    arutz 
   1789  3786    arutz 	if ((un = ddi_get_soft_state(dcd_state,
   1790  3786    arutz 	    minor >> DCDUNIT_SHIFT)) == NULL ||
   1791  3786    arutz 	    un->un_state == DCD_STATE_DUMPING ||
   1792  3786    arutz 	    ((un->un_state  & DCD_STATE_FATAL) == DCD_STATE_FATAL)) {
   1793  3786    arutz 		SET_BP_ERROR(bp, ((un) ? ENXIO : EIO));
   1794  3786    arutz error:
   1795  3786    arutz 		bp->b_resid = bp->b_bcount;
   1796  3786    arutz 		biodone(bp);
   1797  3786    arutz 		return (0);
   1798  3786    arutz 	}
   1799  3786    arutz 
   1800  3786    arutz 	/*
   1801  3786    arutz 	 * If the request size (buf->b_bcount)is greater than the size
   1802  3786    arutz 	 * (un->un_max_xfer_size) supported by the target driver fail
   1803  3786    arutz 	 * the request with EINVAL error code.
   1804  3786    arutz 	 *
   1805  3786    arutz 	 * We are not supposed to receive requests exceeding
   1806  3786    arutz 	 * un->un_max_xfer_size size because the caller is expected to
   1807  3786    arutz 	 * check what is the maximum size that is supported by this
   1808  3786    arutz 	 * driver either through ioctl or dcdmin routine(which is private
   1809  3786    arutz 	 * to this driver).
   1810  3786    arutz 	 * But we have seen cases (like meta driver(md))where dcdstrategy
   1811  3786    arutz 	 * called with more than supported size and cause data corruption.
   1812  3786    arutz 	 */
   1813  3786    arutz 
   1814  3786    arutz 	if (bp->b_bcount > un->un_max_xfer_size) {
   1815  3786    arutz 		SET_BP_ERROR(bp, EINVAL);
   1816  3786    arutz 		goto error;
   1817  3786    arutz 	}
   1818  3786    arutz 
   1819  3786    arutz 	TRACE_2(TR_FAC_DADA, TR_DCDSTRATEGY_START,
   1820  3786    arutz 	    "dcdstrategy_start: bp 0x%p un 0x%p", bp, un);
   1821  3786    arutz 
   1822  3786    arutz 	/*
   1823  3786    arutz 	 * Commands may sneak in while we released the mutex in
   1824  3786    arutz 	 * DDI_SUSPEND, we should block new commands.
   1825  3786    arutz 	 */
   1826  3786    arutz 	mutex_enter(DCD_MUTEX);
   1827  3786    arutz 	while (un->un_state == DCD_STATE_SUSPENDED) {
   1828  3786    arutz 		cv_wait(&un->un_suspend_cv, DCD_MUTEX);
   1829  3786    arutz 	}
   1830  3786    arutz 
   1831  3786    arutz 	if (un->un_state == DCD_STATE_PM_SUSPENDED) {
   1832  3786    arutz 		mutex_exit(DCD_MUTEX);
   1833  3786    arutz 		(void) pm_idle_component(DCD_DEVINFO, 0);
   1834  3786    arutz 		if (pm_raise_power(DCD_DEVINFO, 0,
   1835  7224      cth 		    DCD_DEVICE_ACTIVE) !=  DDI_SUCCESS) {
   1836  3786    arutz 			SET_BP_ERROR(bp, EIO);
   1837  3786    arutz 			goto error;
   1838  3786    arutz 		}
   1839  3786    arutz 		mutex_enter(DCD_MUTEX);
   1840  3786    arutz 	}
   1841  3786    arutz 	mutex_exit(DCD_MUTEX);
   1842  3786    arutz 
   1843  3786    arutz 	/*
   1844  3786    arutz 	 * Map-in the buffer in case starting address is not word aligned.
   1845  3786    arutz 	 */
   1846  3786    arutz 
   1847  3786    arutz 	if (((uintptr_t)bp->b_un.b_addr) & 0x1)
   1848  3786    arutz 		bp_mapin(bp);
   1849  3786    arutz 
   1850  3786    arutz 	bp->b_flags &= ~(B_DONE|B_ERROR);
   1851  3786    arutz 	bp->b_resid = 0;
   1852  3786    arutz 	bp->av_forw = 0;
   1853  3786    arutz 
   1854  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1855  3786    arutz 	    "bp->b_bcount %lx\n", bp->b_bcount);
   1856  3786    arutz 
   1857  3786    arutz 	if (bp != un->un_sbufp) {
   1858  3786    arutz validated:	if (cmlb_partinfo(un->un_dklbhandle,
   1859  3786    arutz 		    minor & DCDPART_MASK,
   1860  3786    arutz 		    &lblocks,
   1861  3786    arutz 		    &p_lblksrt,
   1862  3786    arutz 		    NULL,
   1863  3786    arutz 		    NULL,
   1864  3786    arutz 		    0) == 0) {
   1865  3786    arutz 
   1866  3786    arutz 			bn = dkblock(bp);
   1867  3786    arutz 
   1868  3786    arutz 			DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1869  3786    arutz 			    "dkblock(bp) is %llu\n", bn);
   1870  3786    arutz 
   1871  3786    arutz 			i = 0;
   1872  3786    arutz 			if (bn < 0) {
   1873  3786    arutz 				i = -1;
   1874  3786    arutz 			} else if (bn >= lblocks) {
   1875  3786    arutz 				/*
   1876  3786    arutz 				 * For proper comparison, file system block
   1877  3786    arutz 				 * number has to be scaled to actual CD
   1878  3786    arutz 				 * transfer size.
   1879  3786    arutz 				 * Since all the CDROM operations
   1880  3786    arutz 				 * that have Sun Labels are in the correct
   1881  3786    arutz 				 * block size this will work for CD's.	This
   1882  3786    arutz 				 * will have to change when we have different
   1883  3786    arutz 				 * sector sizes.
   1884  3786    arutz 				 *
   1885  3786    arutz 				 * if bn == lblocks,
   1886  3786    arutz 				 * Not an error, resid == count
   1887  3786    arutz 				 */
   1888  3786    arutz 				if (bn > lblocks) {
   1889  3786    arutz 					i = -1;
   1890  3786    arutz 				} else {
   1891  3786    arutz 					i = 1;
   1892  3786    arutz 				}
   1893  3786    arutz 			} else if (bp->b_bcount & (un->un_secsize-1)) {
   1894  3786    arutz 				/*
   1895  3786    arutz 				 * This should really be:
   1896  3786    arutz 				 *
   1897  3786    arutz 				 * ... if (bp->b_bcount & (un->un_lbasize-1))
   1898  3786    arutz 				 *
   1899  3786    arutz 				 */
   1900  3786    arutz 				i = -1;
   1901  3786    arutz 			} else {
   1902  3786    arutz 				if (!bp->b_bcount) {
   1903  3786    arutz 					printf("Waring : Zero read or Write\n");
   1904  3786    arutz 					goto error;
   1905  3786    arutz 				}
   1906  3786    arutz 				/*
   1907  3786    arutz 				 * sort by absolute block number.
   1908  3786    arutz 				 */
   1909  3786    arutz 				bp->b_resid = bn;
   1910  3786    arutz 				bp->b_resid += p_lblksrt;
   1911  3786    arutz 				/*
   1912  3786    arutz 				 * zero out av_back - this will be a signal
   1913  3786    arutz 				 * to dcdstart to go and fetch the resources
   1914  3786    arutz 				 */
   1915  3786    arutz 				bp->av_back = NO_PKT_ALLOCATED;
   1916  3786    arutz 			}
   1917  3786    arutz 
   1918  3786    arutz 			/*
   1919  3786    arutz 			 * Check to see whether or not we are done
   1920  3786    arutz 			 * (with or without errors).
   1921  3786    arutz 			 */
   1922  3786    arutz 
   1923  3786    arutz 			if (i != 0) {
   1924  3786    arutz 				if (i < 0) {
   1925  3786    arutz 					bp->b_flags |= B_ERROR;
   1926  3786    arutz 				}
   1927  3786    arutz 				goto error;
   1928  3786    arutz 			}
   1929  3786    arutz 		} else {
   1930  3786    arutz 			/*
   1931  3786    arutz 			 * opened in NDELAY/NONBLOCK mode?
   1932  3786    arutz 			 * Check if disk is ready and has a valid geometry
   1933  3786    arutz 			 */
   1934  3786    arutz 			if (dcd_ready_and_valid(bp->b_edev, un) == 0) {
   1935  3786    arutz 				goto validated;
   1936  3786    arutz 			} else {
   1937  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   1938  3786    arutz 				    "i/o to invalid geometry\n");
   1939  3786    arutz 				SET_BP_ERROR(bp, EIO);
   1940  3786    arutz 				goto error;
   1941  3786    arutz 			}
   1942  3786    arutz 		}
   1943  3786    arutz 	} else if (BP_HAS_NO_PKT(bp)) {
   1944  3786    arutz 		struct udcd_cmd *tscmdp;
   1945  3786    arutz 		struct dcd_cmd *tcmdp;
   1946  3786    arutz 		/*
   1947  3786    arutz 		 * This indicates that it is a special buffer
   1948  3786    arutz 		 * This could be a udcd-cmd and hence call bp_mapin just
   1949  3786    arutz 		 * in case that it could be a PIO command issued.
   1950  3786    arutz 		 */
   1951  3786    arutz 		tscmdp = (struct udcd_cmd *)bp->b_forw;
   1952  3786    arutz 		tcmdp = tscmdp->udcd_cmd;
   1953  3786    arutz 		if ((tcmdp->cmd != ATA_READ_DMA) && (tcmdp->cmd != 0xc9) &&
   1954  3786    arutz 		    (tcmdp->cmd != ATA_WRITE_DMA) && (tcmdp->cmd != 0xcb) &&
   1955  3786    arutz 		    (tcmdp->cmd != IDENTIFY_DMA) &&
   1956  3786    arutz 		    (tcmdp->cmd != ATA_FLUSH_CACHE)) {
   1957  3786    arutz 			bp_mapin(bp);
   1958  3786    arutz 		}
   1959  3786    arutz 	}
   1960  3786    arutz 
   1961  3786    arutz 	/*
   1962  3786    arutz 	 * We are doing it a bit non-standard. That is, the
   1963  3786    arutz 	 * head of the b_actf chain is *not* the active command-
   1964  3786    arutz 	 * it is just the head of the wait queue. The reason
   1965  3786    arutz 	 * we do this is that the head of the b_actf chain is
   1966  3786    arutz 	 * guaranteed to not be moved by disksort(), so that
   1967  3786    arutz 	 * our restart command (pointed to by
   1968  3786    arutz 	 * b_forw) and the head of the wait queue (b_actf) can
   1969  3786    arutz 	 * have resources granted without it getting lost in
   1970  3786    arutz 	 * the queue at some later point (where we would have
   1971  3786    arutz 	 * to go and look for it).
   1972  3786    arutz 	 */
   1973  3786    arutz 	mutex_enter(DCD_MUTEX);
   1974  3786    arutz 
   1975  3786    arutz 	DCD_DO_KSTATS(un, kstat_waitq_enter, bp);
   1976  3786    arutz 
   1977  3786    arutz 	dp = &un->un_utab;
   1978  3786    arutz 
   1979  3786    arutz 	if (dp->b_actf == NULL) {
   1980  3786    arutz 		dp->b_actf = bp;
   1981  3786    arutz 		dp->b_actl = bp;
   1982  3786    arutz 	} else if ((un->un_state == DCD_STATE_SUSPENDED) &&
   1983  3786    arutz 	    bp == un->un_sbufp) {
   1984  3786    arutz 		bp->b_actf = dp->b_actf;
   1985  3786    arutz 		dp->b_actf = bp;
   1986  3786    arutz 	} else {
   1987  3786    arutz 		TRACE_3(TR_FAC_DADA, TR_DCDSTRATEGY_DISKSORT_START,
   1988  3786    arutz 		    "dcdstrategy_disksort_start: dp 0x%p bp 0x%p un 0x%p",
   1989  3786    arutz 		    dp, bp, un);
   1990  3786    arutz 		disksort(dp, bp);
   1991  3786    arutz 		TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_DISKSORT_END,
   1992  3786    arutz 		    "dcdstrategy_disksort_end");
   1993  3786    arutz 	}
   1994  3786    arutz 
   1995  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   1996  3786    arutz 	    "ncmd %x , throttle %x, forw 0x%p\n",
   1997  3786    arutz 	    un->un_ncmds, un->un_throttle, (void *)dp->b_forw);
   1998  3786    arutz 	ASSERT(un->un_ncmds >= 0);
   1999  3786    arutz 	ASSERT(un->un_throttle >= 0);
   2000  3786    arutz 	if ((un->un_ncmds < un->un_throttle) && (dp->b_forw == NULL)) {
   2001  3786    arutz 		dcdstart(un);
   2002  3786    arutz 	} else if (BP_HAS_NO_PKT(dp->b_actf)) {
   2003  3786    arutz 		struct buf *cmd_bp;
   2004  3786    arutz 
   2005  3786    arutz 		cmd_bp = dp->b_actf;
   2006  3786    arutz 		cmd_bp->av_back = ALLOCATING_PKT;
   2007  3786    arutz 		mutex_exit(DCD_MUTEX);
   2008  3786    arutz 		/*
   2009  3786    arutz 		 * try and map this one
   2010  3786    arutz 		 */
   2011  3786    arutz 		TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_SMALL_WINDOW_START,
   2012  3786    arutz 		    "dcdstrategy_small_window_call (begin)");
   2013  3786    arutz 
   2014  3786    arutz 		make_dcd_cmd(un, cmd_bp, NULL_FUNC);
   2015  3786    arutz 
   2016  3786    arutz 		TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_SMALL_WINDOW_END,
   2017  3786    arutz 		    "dcdstrategy_small_window_call (end)");
   2018  3786    arutz 
   2019  3786    arutz 		/*
   2020  3786    arutz 		 * there is a small window where the active cmd
   2021  3786    arutz 		 * completes before make_dcd_cmd returns.
   2022  3786    arutz 		 * consequently, this cmd never gets started so
   2023  3786    arutz 		 * we start it from here
   2024  3786    arutz 		 */
   2025  3786    arutz 		mutex_enter(DCD_MUTEX);
   2026  3786    arutz 		if ((un->un_ncmds < un->un_throttle) &&
   2027  3786    arutz 		    (dp->b_forw == NULL)) {
   2028  3786    arutz 			dcdstart(un);
   2029  3786    arutz 		}
   2030  3786    arutz 	}
   2031  3786    arutz 	mutex_exit(DCD_MUTEX);
   2032  3786    arutz 
   2033  3786    arutz done:
   2034  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_END, "dcdstrategy_end");
   2035  3786    arutz 	return (0);
   2036  3786    arutz }
   2037  3786    arutz 
   2038  3786    arutz 
   2039  3786    arutz /*
   2040  3786    arutz  * Unit start and Completion
   2041  3786    arutz  * NOTE: we assume that the caller has at least checked for:
   2042  3786    arutz  *		(un->un_ncmds < un->un_throttle)
   2043  3786    arutz  *	if not, there is no real harm done, dcd_transport() will
   2044  3786    arutz  *	return BUSY
   2045  3786    arutz  */
   2046  3786    arutz static void
   2047  3786    arutz dcdstart(struct dcd_disk *un)
   2048  3786    arutz {
   2049  3786    arutz 	int status, sort_key;
   2050  3786    arutz 	struct buf *bp;
   2051  3786    arutz 	struct diskhd *dp;
   2052  3786    arutz 	uchar_t state = un->un_last_state;
   2053  3786    arutz 
   2054  3786    arutz 	TRACE_1(TR_FAC_DADA, TR_DCDSTART_START, "dcdstart_start: un 0x%p", un);
   2055  3786    arutz 
   2056  3786    arutz retry:
   2057  3786    arutz 	ASSERT(mutex_owned(DCD_MUTEX));
   2058  3786    arutz 
   2059  3786    arutz 	dp = &un->un_utab;
   2060  3786    arutz 	if (((bp = dp->b_actf) == NULL) || (bp->av_back == ALLOCATING_PKT) ||
   2061  3786    arutz 	    (dp->b_forw != NULL)) {
   2062  3786    arutz 		TRACE_0(TR_FAC_DADA, TR_DCDSTART_NO_WORK_END,
   2063  3786    arutz 		    "dcdstart_end (no work)");
   2064  3786    arutz 		return;
   2065  3786    arutz 	}
   2066  3786    arutz 
   2067  3786    arutz 	/*
   2068  3786    arutz 	 * remove from active queue
   2069  3786    arutz 	 */
   2070  3786    arutz 	dp->b_actf = bp->b_actf;
   2071  3786    arutz 	bp->b_actf = 0;
   2072  3786    arutz 
   2073  3786    arutz 	/*
   2074  3786    arutz 	 * increment ncmds before calling dcd_transport because dcdintr
   2075  3786    arutz 	 * may be called before we return from dcd_transport!
   2076  3786    arutz 	 */
   2077  3786    arutz 	un->un_ncmds++;
   2078  3786    arutz 
   2079  3786    arutz 	/*
   2080  3786    arutz 	 * If measuring stats, mark exit from wait queue and
   2081  3786    arutz 	 * entrance into run 'queue' if and only if we are
   2082  3786    arutz 	 * going to actually start a command.
   2083  3786    arutz 	 * Normally the bp already has a packet at this point
   2084  3786    arutz 	 */
   2085  3786    arutz 	DCD_DO_KSTATS(un, kstat_waitq_to_runq, bp);
   2086  3786    arutz 
   2087  3786    arutz 	mutex_exit(DCD_MUTEX);
   2088  3786    arutz 
   2089  3786    arutz 	if (BP_HAS_NO_PKT(bp)) {
   2090  3786    arutz 		make_dcd_cmd(un, bp, dcdrunout);
   2091  3786    arutz 		if (BP_HAS_NO_PKT(bp) && !(bp->b_flags & B_ERROR)) {
   2092  3786    arutz 			mutex_enter(DCD_MUTEX);
   2093  3786    arutz 			DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
   2094  3786    arutz 
   2095  3786    arutz 			bp->b_actf = dp->b_actf;
   2096  3786    arutz 			dp->b_actf = bp;
   2097  3786    arutz 			New_state(un, DCD_STATE_RWAIT);
   2098  3786    arutz 			un->un_ncmds--;
   2099  3786    arutz 			TRACE_0(TR_FAC_DADA, TR_DCDSTART_NO_RESOURCES_END,
   2100  3786    arutz 			    "dcdstart_end (No Resources)");
   2101  3786    arutz 			goto done;
   2102  3786    arutz 
   2103  3786    arutz 		} else if (bp->b_flags & B_ERROR) {
   2104  3786    arutz 			mutex_enter(DCD_MUTEX);
   2105  3786    arutz 			DCD_DO_KSTATS(un, kstat_runq_exit, bp);
   2106  3786    arutz 
   2107  3786    arutz 			un->un_ncmds--;
   2108  3786    arutz 			bp->b_resid = bp->b_bcount;
   2109  3786    arutz 			if (bp->b_error == 0) {
   2110  3786    arutz 				SET_BP_ERROR(bp, EIO);
   2111  3786    arutz 			}
   2112  3786    arutz 
   2113  3786    arutz 			/*
   2114  3786    arutz 			 * restore old state
   2115  3786    arutz 			 */
   2116  3786    arutz 			un->un_state = un->un_last_state;
   2117  3786    arutz 			un->un_last_state = state;
   2118  3786    arutz 
   2119  3786    arutz 			mutex_exit(DCD_MUTEX);
   2120  3786    arutz 
   2121  3786    arutz 			biodone(bp);
   2122  3786    arutz 			mutex_enter(DCD_MUTEX);
   2123  3786    arutz 			if (un->un_state == DCD_STATE_SUSPENDED) {
   2124  3786    arutz 				cv_broadcast(&un->un_disk_busy_cv);
   2125  3786    arutz 			}
   2126  3786    arutz 
   2127  3786    arutz 			if ((un->un_ncmds < un->un_throttle) &&
   2128  3786    arutz 			    (dp->b_forw == NULL)) {
   2129  3786    arutz 				goto retry;
   2130  3786    arutz 			} else {
   2131  3786    arutz 				goto done;
   2132  3786    arutz 			}
   2133  3786    arutz 		}
   2134  3786    arutz 	}
   2135  3786    arutz 
   2136  3786    arutz 	/*
   2137  3786    arutz 	 * Restore resid from the packet, b_resid had been the
   2138  3786    arutz 	 * disksort key.
   2139  3786    arutz 	 */
   2140  3786    arutz 	sort_key = bp->b_resid;
   2141  3786    arutz 	bp->b_resid = BP_PKT(bp)->pkt_resid;
   2142  3786    arutz 	BP_PKT(bp)->pkt_resid = 0;
   2143  3786    arutz 
   2144  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2145  3786    arutz 	    "bp->b_resid %lx, pkt_resid %lx\n",
   2146  3786    arutz 	    bp->b_resid, BP_PKT(bp)->pkt_resid);
   2147  3786    arutz 
   2148  3786    arutz 	/*
   2149  3786    arutz 	 * We used to check whether or not to try and link commands here.
   2150  3786    arutz 	 * Since we have found that there is no performance improvement
   2151  3786    arutz 	 * for linked commands, this has not made much sense.
   2152  3786    arutz 	 */
   2153  3786    arutz 	if ((status = dcd_transport((struct dcd_pkt *)BP_PKT(bp)))
   2154  3786    arutz 	    != TRAN_ACCEPT) {
   2155  3786    arutz 		mutex_enter(DCD_MUTEX);
   2156  3786    arutz 		un->un_ncmds--;
   2157  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2158  3786    arutz 		    "transport returned %x\n", status);
   2159  3786    arutz 		if (status == TRAN_BUSY) {
   2160  3786    arutz 			DCD_DO_ERRSTATS(un, dcd_transerrs);
   2161  3786    arutz 			DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
   2162  3786    arutz 			dcd_handle_tran_busy(bp, dp, un);
   2163  3786    arutz 			if (un->un_ncmds > 0) {
   2164  3786    arutz 				bp->b_resid = sort_key;
   2165  3786    arutz 			}
   2166  3786    arutz 		} else {
   2167  3786    arutz 			DCD_DO_KSTATS(un, kstat_runq_exit, bp);
   2168  3786    arutz 			mutex_exit(DCD_MUTEX);
   2169  3786    arutz 
   2170  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2171  3786    arutz 			    "transport rejected (%d)\n",
   2172  3786    arutz 			    status);
   2173  3786    arutz 			SET_BP_ERROR(bp, EIO);
   2174  3786    arutz 			bp->b_resid = bp->b_bcount;
   2175  3786    arutz 			if (bp != un->un_sbufp) {
   2176  3786    arutz 				dcd_destroy_pkt(BP_PKT(bp));
   2177  3786    arutz 			}
   2178  3786    arutz 			biodone(bp);
   2179  3786    arutz 
   2180  3786    arutz 			mutex_enter(DCD_MUTEX);
   2181  3786    arutz 			if (un->un_state == DCD_STATE_SUSPENDED) {
   2182  3786    arutz 				cv_broadcast(&un->un_disk_busy_cv);
   2183  3786    arutz 			}
   2184  3786    arutz 			if ((un->un_ncmds < un->un_throttle) &&
   2185  3786    arutz 			    (dp->b_forw == NULL)) {
   2186  3786    arutz 					goto retry;
   2187  3786    arutz 			}
   2188  3786    arutz 		}
   2189  3786    arutz 	} else {
   2190  3786    arutz 		mutex_enter(DCD_MUTEX);
   2191  3786    arutz 
   2192  3786    arutz 		if (dp->b_actf && BP_HAS_NO_PKT(dp->b_actf)) {
   2193  3786    arutz 			struct buf *cmd_bp;
   2194  3786    arutz 
   2195  3786    arutz 			cmd_bp = dp->b_actf;
   2196  3786    arutz 			cmd_bp->av_back = ALLOCATING_PKT;
   2197  3786    arutz 			mutex_exit(DCD_MUTEX);
   2198  3786    arutz 			/*
   2199  3786    arutz 			 * try and map this one
   2200  3786    arutz 			 */
   2201  3786    arutz 			TRACE_0(TR_FAC_DADA, TR_DCASTART_SMALL_WINDOW_START,
   2202  3786    arutz 			    "dcdstart_small_window_start");
   2203  3786    arutz 
   2204  3786    arutz 			make_dcd_cmd(un, cmd_bp, NULL_FUNC);
   2205  3786    arutz 
   2206  3786    arutz 			TRACE_0(TR_FAC_DADA, TR_DCDSTART_SMALL_WINDOW_END,
   2207  3786    arutz 			    "dcdstart_small_window_end");
   2208  3786    arutz 			/*
   2209  3786    arutz 			 * there is a small window where the active cmd
   2210  3786    arutz 			 * completes before make_dcd_cmd returns.
   2211  3786    arutz 			 * consequently, this cmd never gets started so
   2212  3786    arutz 			 * we start it from here
   2213  3786    arutz 			 */
   2214  3786    arutz 			mutex_enter(DCD_MUTEX);
   2215  3786    arutz 			if ((un->un_ncmds < un->un_throttle) &&
   2216  3786    arutz 			    (dp->b_forw == NULL)) {
   2217  3786    arutz 				goto retry;
   2218  3786    arutz 			}
   2219  3786    arutz 		}
   2220  3786    arutz 	}
   2221  3786    arutz 
   2222  3786    arutz done:
   2223  3786    arutz 	ASSERT(mutex_owned(DCD_MUTEX));
   2224  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCDSTART_END, "dcdstart_end");
   2225  3786    arutz }
   2226  3786    arutz 
   2227  3786    arutz /*
   2228  3786    arutz  * make_dcd_cmd: create a pkt
   2229  3786    arutz  */
   2230  3786    arutz static void
   2231  3786    arutz make_dcd_cmd(struct dcd_disk *un, struct buf *bp, int (*func)())
   2232  3786    arutz {
   2233  3786    arutz 	auto int count, com, direction;
   2234  3786    arutz 	struct dcd_pkt *pkt;
   2235  3786    arutz 	int flags, tval;
   2236  3786    arutz 
   2237  3786    arutz 	_NOTE(DATA_READABLE_WITHOUT_LOCK(dcd_disk::un_dp))
   2238  3786    arutz 	TRACE_3(TR_FAC_DADA, TR_MAKE_DCD_CMD_START,
   2239  3786    arutz 	    "make_dcd_cmd_start: un 0x%p bp 0x%p un 0x%p", un, bp, un);
   2240  3786    arutz 
   2241  3786    arutz 
   2242  3786    arutz 	flags = un->un_cmd_flags;
   2243  3786    arutz 
   2244  3786    arutz 	if (bp != un->un_sbufp) {
   2245  3786    arutz 		int partition = DCDPART(bp->b_edev);
   2246  3786    arutz 		diskaddr_t p_lblksrt;
   2247  3786    arutz 		diskaddr_t lblocks;
   2248  3786    arutz 		long secnt;
   2249  3786    arutz 		uint32_t blkno;
   2250  3786    arutz 		int dkl_nblk, delta;
   2251  3786    arutz 		long resid;
   2252  3786    arutz 
   2253  3786    arutz 		if (cmlb_partinfo(un->un_dklbhandle,
   2254  3786    arutz 		    partition,
   2255  3786    arutz 		    &lblocks,
   2256  3786    arutz 		    &p_lblksrt,
   2257  3786    arutz 		    NULL,
   2258  3786    arutz 		    NULL,
   2259  3786    arutz 		    0) != NULL) {
   2260  3786    arutz 			lblocks = 0;
   2261  3786    arutz 			p_lblksrt = 0;
   2262  3786    arutz 		}
   2263  3786    arutz 
   2264  3786    arutz 		dkl_nblk = (int)lblocks;
   2265  3786    arutz 
   2266  3786    arutz 		/*
   2267  3786    arutz 		 * Make sure we don't run off the end of a partition.
   2268  3786    arutz 		 *
   2269  3786    arutz 		 * Put this test here so that we can adjust b_count
   2270  3786    arutz 		 * to accurately reflect the actual amount we are
   2271  3786    arutz 		 * goint to transfer.
   2272  3786    arutz 		 */
   2273  3786    arutz 
   2274  3786    arutz 		/*
   2275  3786    arutz 		 * First, compute partition-relative block number
   2276  3786    arutz 		 */
   2277  3786    arutz 		blkno = dkblock(bp);
   2278  3786    arutz 		secnt = (bp->b_bcount + (un->un_secsize - 1)) >> un->un_secdiv;
   2279  3786    arutz 		count = MIN(secnt, dkl_nblk - blkno);
   2280  3786    arutz 		if (count != secnt) {
   2281  3786    arutz 			/*
   2282  3786    arutz 			 * We have an overrun
   2283  3786    arutz 			 */
   2284  3786    arutz 			resid = (secnt - count) << un->un_secdiv;
   2285  3786    arutz 			DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2286  3786    arutz 			    "overrun by %ld sectors\n",
   2287  3786    arutz 			    secnt - count);
   2288  3786    arutz 			bp->b_bcount -= resid;
   2289  3786    arutz 		} else {
   2290  3786    arutz 			resid = 0;
   2291  3786    arutz 		}
   2292  3786    arutz 
   2293  3786    arutz 		/*
   2294  3786    arutz 		 * Adjust block number to absolute
   2295  3786    arutz 		 */
   2296  3786    arutz 		delta = (int)p_lblksrt;
   2297  3786    arutz 		blkno += delta;
   2298  3786    arutz 
   2299  3786    arutz 		mutex_enter(DCD_MUTEX);
   2300  3786    arutz 		/*
   2301  3786    arutz 		 * This is for devices having block size different from
   2302  3786    arutz 		 * from DEV_BSIZE (e.g. 2K CDROMs).
   2303  3786    arutz 		 */
   2304  3786    arutz 		if (un->un_lbasize != un->un_secsize) {
   2305  3786    arutz 			blkno >>= un->un_blknoshift;
   2306  3786    arutz 			count >>= un->un_blknoshift;
   2307  3786    arutz 		}
   2308  3786    arutz 		mutex_exit(DCD_MUTEX);
   2309  3786    arutz 
   2310  3786    arutz 		TRACE_0(TR_FAC_DADA, TR_MAKE_DCD_CMD_INIT_PKT_START,
   2311  3786    arutz 		    "make_dcd_cmd_init_pkt_call (begin)");
   2312  3786    arutz 		pkt = dcd_init_pkt(ROUTE, NULL, bp,
   2313  3786    arutz 		    (uint32_t)sizeof (struct dcd_cmd),
   2314  3786    arutz 		    un->un_cmd_stat_size, PP_LEN, PKT_CONSISTENT,
   2315  3786    arutz 		    func, (caddr_t)un);
   2316  3786    arutz 		TRACE_1(TR_FAC_DADA, TR_MAKE_DCD_CMD_INIT_PKT_END,
   2317  3786    arutz 		    "make_dcd_cmd_init_pkt_call (end): pkt 0x%p", pkt);
   2318  3786    arutz 		if (!pkt) {
   2319  3786    arutz 			bp->b_bcount += resid;
   2320  3786    arutz 			bp->av_back = NO_PKT_ALLOCATED;
   2321  3786    arutz 			TRACE_0(TR_FAC_DADA,
   2322  3786    arutz 			    TR_MAKE_DCD_CMD_NO_PKT_ALLOCATED1_END,
   2323  3786    arutz 			    "make_dcd_cmd_end (NO_PKT_ALLOCATED1)");
   2324  3786    arutz 			return;
   2325  3786    arutz 		}
   2326  3786    arutz 		if (bp->b_flags & B_READ) {
   2327  3786    arutz 			if ((un->un_dp->options & DMA_SUPPORTTED) ==
   2328  3786    arutz 			    DMA_SUPPORTTED) {
   2329  3786    arutz 				com = ATA_READ_DMA;
   2330  3786    arutz 			} else {
   2331  3786    arutz 				if (un->un_dp->options & BLOCK_MODE)
   2332  3786    arutz 					com = ATA_READ_MULTIPLE;
   2333  3786    arutz 				else
   2334  3786    arutz 					com = ATA_READ;
   2335  3786    arutz 			}
   2336  3786    arutz 			direction = DATA_READ;
   2337  3786    arutz 		} else {
   2338  3786    arutz 			if ((un->un_dp->options & DMA_SUPPORTTED) ==
   2339  3786    arutz 			    DMA_SUPPORTTED) {
   2340  3786    arutz 				com = ATA_WRITE_DMA;
   2341  3786    arutz 			} else {
   2342  3786    arutz 				if (un->un_dp->options & BLOCK_MODE)
   2343  3786    arutz 					com = ATA_WRITE_MULTIPLE;
   2344  3786    arutz 				else
   2345  3786    arutz 					com = ATA_WRITE;
   2346  3786    arutz 			}
   2347  3786    arutz 			direction = DATA_WRITE;
   2348  3786    arutz 		}
   2349  3786    arutz 
   2350  3786    arutz 		/*
   2351  3786    arutz 		 * Save the resid in the packet, temporarily until
   2352  3786    arutz 		 * we transport the command.
   2353  3786    arutz 		 */
   2354  3786    arutz 		pkt->pkt_resid = resid;
   2355  3786    arutz 
   2356  3786    arutz 		makecommand(pkt, flags, com, blkno, ADD_LBA_MODE,
   2357  3786    arutz 		    bp->b_bcount, direction, 0);
   2358  3786    arutz 		tval = dcd_io_time;
   2359  3786    arutz 	} else {
   2360  3786    arutz 
   2361  3786    arutz 		struct udcd_cmd *scmd = (struct udcd_cmd *)bp->b_forw;
   2362  3786    arutz 
   2363  3786    arutz 		/*
   2364  3786    arutz 		 * set options
   2365  3786    arutz 		 */
   2366  3786    arutz 		if ((scmd->udcd_flags & UDCD_SILENT) && !(DEBUGGING)) {
   2367  3786    arutz 			flags |= FLAG_SILENT;
   2368  3786    arutz 		}
   2369  3786    arutz 		if (scmd->udcd_flags &  UDCD_DIAGNOSE)
   2370  3786    arutz 			flags |= FLAG_DIAGNOSE;
   2371  3786    arutz 
   2372  3786    arutz 		if (scmd->udcd_flags & UDCD_NOINTR)
   2373  3786    arutz 			flags |= FLAG_NOINTR;
   2374  3786    arutz 
   2375  3786    arutz 		pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL,
   2376  3786    arutz 		    (bp->b_bcount)? bp: NULL,
   2377  3786    arutz 		    (uint32_t)sizeof (struct dcd_cmd),
   2378  3786    arutz 		    2, PP_LEN, PKT_CONSISTENT, func, (caddr_t)un);
   2379  3786    arutz 
   2380  3786    arutz 		if (!pkt) {
   2381  3786    arutz 			bp->av_back = NO_PKT_ALLOCATED;
   2382  3786    arutz 			return;
   2383  3786    arutz 		}
   2384  3786    arutz 
   2385  3786    arutz 		makecommand(pkt, 0, scmd->udcd_cmd->cmd,
   2386  3786    arutz 		    scmd->udcd_cmd->sector_num.lba_num,
   2387  3786    arutz 		    scmd->udcd_cmd->address_mode,
   2388  3786    arutz 		    scmd->udcd_cmd->size,
   2389  3786    arutz 		    scmd->udcd_cmd->direction, scmd->udcd_cmd->features);
   2390  3786    arutz 
   2391  3786    arutz 		pkt->pkt_flags = flags;
   2392  3786    arutz 		if (scmd->udcd_timeout == 0)
   2393  3786    arutz 			tval = dcd_io_time;
   2394  3786    arutz 		else
   2395  3786    arutz 			tval = scmd->udcd_timeout;
   2396  3786    arutz 		/* UDAD interface should be decided. */
   2397  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2398  3786    arutz 		    "udcd interface\n");
   2399  3786    arutz 	}
   2400  3786    arutz 
   2401  3786    arutz 	pkt->pkt_comp = dcdintr;
   2402  3786    arutz 	pkt->pkt_time = tval;
   2403  3786    arutz 	PKT_SET_BP(pkt, bp);
   2404  3786    arutz 	bp->av_back = (struct buf *)pkt;
   2405  3786    arutz 
   2406  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_MAKE_DCD_CMD_END, "make_dcd_cmd_end");
   2407  3786    arutz }
   2408  3786    arutz 
   2409  3786    arutz /*
   2410  3786    arutz  * Command completion processing
   2411  3786    arutz  */
   2412  3786    arutz static void
   2413  3786    arutz dcdintr(struct dcd_pkt *pkt)
   2414  3786    arutz {
   2415  3786    arutz 	struct dcd_disk *un;
   2416  3786    arutz 	struct buf *bp;
   2417  3786    arutz 	int action;
   2418  3786    arutz 	int status;
   2419  3786    arutz 
   2420  3786    arutz 	bp = PKT_GET_BP(pkt);
   2421  3786    arutz 	un = ddi_get_soft_state(dcd_state, DCDUNIT(bp->b_edev));
   2422  3786    arutz 
   2423  3786    arutz 	TRACE_1(TR_FAC_DADA, TR_DCDINTR_START, "dcdintr_start: un 0x%p", un);
   2424  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdintr\n");
   2425  3786    arutz 
   2426  3786    arutz 	mutex_enter(DCD_MUTEX);
   2427  3786    arutz 	un->un_ncmds--;
   2428  3786    arutz 	DCD_DO_KSTATS(un, kstat_runq_exit, bp);
   2429  3786    arutz 	ASSERT(un->un_ncmds >= 0);
   2430  3786    arutz 
   2431  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2432  3786    arutz 	    "reason %x and Status %x\n", pkt->pkt_reason, SCBP_C(pkt));
   2433  3786    arutz 
   2434  3786    arutz 	/*
   2435  3786    arutz 	 * do most common case first
   2436  3786    arutz 	 */
   2437  3786    arutz 	if ((pkt->pkt_reason == CMD_CMPLT) && (SCBP_C(pkt) == 0)) {
   2438  3786    arutz 		int com = GETATACMD((struct dcd_cmd *)pkt->pkt_cdbp);
   2439  3786    arutz 
   2440  3786    arutz 		if (un->un_state == DCD_STATE_OFFLINE) {
   2441  3786    arutz 			un->un_state = un->un_last_state;
   2442  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_NOTE,
   2443  3786    arutz 			    (const char *) diskokay);
   2444  3786    arutz 		}
   2445  3786    arutz 		/*
   2446  3786    arutz 		 * If the command is a read or a write, and we have
   2447  3786    arutz 		 * a non-zero pkt_resid, that is an error. We should
   2448  3786    arutz 		 * attempt to retry the operation if possible.
   2449  3786    arutz 		 */
   2450  3786    arutz 		action = COMMAND_DONE;
   2451  3786    arutz 		if (pkt->pkt_resid && (com == ATA_READ || com == ATA_WRITE)) {
   2452  3786    arutz 			DCD_DO_ERRSTATS(un, dcd_harderrs);
   2453  3786    arutz 			if ((int)PKT_GET_RETRY_CNT(pkt) < dcd_retry_count) {
   2454  3786    arutz 				PKT_INCR_RETRY_CNT(pkt, 1);
   2455  3786    arutz 				action = QUE_COMMAND;
   2456  3786    arutz 			} else {
   2457  3786    arutz 				/*
   2458  3786    arutz 				 * if we have exhausted retries
   2459  3786    arutz 				 * a command with a residual is in error in
   2460  3786    arutz 				 * this case.
   2461  3786    arutz 				 */
   2462  3786    arutz 				action = COMMAND_DONE_ERROR;
   2463  3786    arutz 			}
   2464  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label,
   2465  3786    arutz 			    CE_WARN, "incomplete %s- %s\n",
   2466  3786    arutz 			    (bp->b_flags & B_READ)? "read" : "write",
   2467  3786    arutz 			    (action == QUE_COMMAND)? "retrying" :
   2468  3786    arutz 			    "giving up");
   2469  3786    arutz 		}
   2470  3786    arutz 
   2471  3786    arutz 		/*
   2472  3786    arutz 		 * pkt_resid will reflect, at this point, a residual
   2473  3786    arutz 		 * of how many bytes left to be transferred there were
   2474  3786    arutz 		 * from the actual scsi command. Add this to b_resid i.e
   2475  3786    arutz 		 * the amount this driver could not see to transfer,
   2476  3786    arutz 		 * to get the total number of bytes not transfered.
   2477  3786    arutz 		 */
   2478  3786    arutz 		if (action != QUE_COMMAND) {
   2479  3786    arutz 			bp->b_resid += pkt->pkt_resid;
   2480  3786    arutz 		}
   2481  3786    arutz 
   2482  3786    arutz 	} else if (pkt->pkt_reason != CMD_CMPLT) {
   2483  3786    arutz 		action = dcd_handle_incomplete(un, bp);
   2484  3786    arutz 	}
   2485  3786    arutz 
   2486  3786    arutz 	/*
   2487  3786    arutz 	 * If we are in the middle of syncing or dumping, we have got
   2488  3786    arutz 	 * here because dcd_transport has called us explictly after
   2489  3786    arutz 	 * completing the command in a polled mode. We don't want to
   2490  3786    arutz 	 * have a recursive call into dcd_transport again.
   2491  3786    arutz 	 */
   2492  3786    arutz 	if (ddi_in_panic() && (action == QUE_COMMAND)) {
   2493  3786    arutz 		action = COMMAND_DONE_ERROR;
   2494  3786    arutz 	}
   2495  3786    arutz 
   2496  3786    arutz 	/*
   2497  3786    arutz 	 * save pkt reason; consecutive failures are not reported unless
   2498  3786    arutz 	 * fatal
   2499  3786    arutz 	 * do not reset last_pkt_reason when the cmd was retried and
   2500  3786    arutz 	 * succeeded because
   2501  3786    arutz 	 * there maybe more commands comming back with last_pkt_reason
   2502  3786    arutz 	 */
   2503  3786    arutz 	if ((un->un_last_pkt_reason != pkt->pkt_reason) &&
   2504  3786    arutz 	    ((pkt->pkt_reason != CMD_CMPLT) ||
   2505  3786    arutz 	    (PKT_GET_RETRY_CNT(pkt) == 0))) {
   2506  3786    arutz 		un->un_last_pkt_reason = pkt->pkt_reason;
   2507  3786    arutz 	}
   2508  3786    arutz 
   2509  3786    arutz 	switch (action) {
   2510  3786    arutz 	case COMMAND_DONE_ERROR:
   2511  3786    arutz error:
   2512  3786    arutz 		if (bp->b_resid == 0) {
   2513  3786    arutz 			bp->b_resid = bp->b_bcount;
   2514  3786    arutz 		}
   2515  3786    arutz 		if (bp->b_error == 0) {
   2516  3786    arutz 			struct	dcd_cmd *cdbp = (struct dcd_cmd *)pkt->pkt_cdbp;
   2517  3786    arutz 			if (cdbp->cmd == ATA_FLUSH_CACHE &&
   2518  3786    arutz 			    (pkt->pkt_scbp[0] & STATUS_ATA_ERR) &&
   2519  3786    arutz 			    (pkt->pkt_scbp[1] & ERR_ABORT)) {
   2520  3786    arutz 				SET_BP_ERROR(bp, ENOTSUP);
   2521  3786    arutz 				un->un_flush_not_supported = 1;
   2522  3786    arutz 			} else {
   2523  3786    arutz 				SET_BP_ERROR(bp, EIO);
   2524  3786    arutz 			}
   2525  3786    arutz 		}
   2526  3786    arutz 		bp->b_flags |= B_ERROR;
   2527  3786    arutz 		/*FALLTHROUGH*/
   2528  3786    arutz 	case COMMAND_DONE:
   2529  3786    arutz 		dcddone_and_mutex_exit(un, bp);
   2530  3786    arutz 
   2531  3786    arutz 		TRACE_0(TR_FAC_DADA, TR_DCDINTR_COMMAND_DONE_END,
   2532  3786    arutz 		    "dcdintr_end (COMMAND_DONE)");
   2533  3786    arutz 		return;
   2534  3786    arutz 
   2535  3786    arutz 	case QUE_COMMAND:
   2536  3786    arutz 		if (un->un_ncmds >= un->un_throttle) {
   2537  3786    arutz 			struct diskhd *dp = &un->un_utab;
   2538  3786    arutz 
   2539  3786    arutz 			bp->b_actf = dp->b_actf;
   2540  3786    arutz 			dp->b_actf = bp;
   2541  3786    arutz 
   2542  3786    arutz 			DCD_DO_KSTATS(un, kstat_waitq_enter, bp);
   2543  3786    arutz 
   2544  3786    arutz 			mutex_exit(DCD_MUTEX);
   2545  3786    arutz 			goto exit;
   2546  3786    arutz 		}
   2547  3786    arutz 
   2548  3786    arutz 		un->un_ncmds++;
   2549  3786    arutz 		/* reset the pkt reason again */
   2550  3786    arutz 		pkt->pkt_reason = 0;
   2551  3786    arutz 		DCD_DO_KSTATS(un, kstat_runq_enter, bp);
   2552  3786    arutz 		mutex_exit(DCD_MUTEX);
   2553  3786    arutz 		if ((status = dcd_transport(BP_PKT(bp))) != TRAN_ACCEPT) {
   2554  3786    arutz 			struct diskhd *dp = &un->un_utab;
   2555  3786    arutz 
   2556  3786    arutz 			mutex_enter(DCD_MUTEX);
   2557  3786    arutz 			un->un_ncmds--;
   2558  3786    arutz 			if (status == TRAN_BUSY) {
   2559  3786    arutz 				DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp);
   2560  3786    arutz 				dcd_handle_tran_busy(bp, dp, un);
   2561  3786    arutz 				mutex_exit(DCD_MUTEX);
   2562  3786    arutz 				goto exit;
   2563  3786    arutz 			}
   2564  3786    arutz 			DCD_DO_ERRSTATS(un, dcd_transerrs);
   2565  3786    arutz 			DCD_DO_KSTATS(un, kstat_runq_exit, bp);
   2566  3786    arutz 
   2567  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2568  3786    arutz 			    "requeue of command fails (%x)\n", status);
   2569  3786    arutz 			SET_BP_ERROR(bp, EIO);
   2570  3786    arutz 			bp->b_resid = bp->b_bcount;
   2571  3786    arutz 
   2572  3786    arutz 			dcddone_and_mutex_exit(un, bp);
   2573  3786    arutz 			goto exit;
   2574  3786    arutz 		}
   2575  3786    arutz 		break;
   2576  3786    arutz 
   2577  3786    arutz 	case JUST_RETURN:
   2578  3786    arutz 	default:
   2579  3786    arutz 		DCD_DO_KSTATS(un, kstat_waitq_enter, bp);
   2580  3786    arutz 		mutex_exit(DCD_MUTEX);
   2581  3786    arutz 		break;
   2582  3786    arutz 	}
   2583  3786    arutz 
   2584  3786    arutz exit:
   2585  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCDINTR_END, "dcdintr_end");
   2586  3786    arutz }
   2587  3786    arutz 
   2588  3786    arutz 
   2589  3786    arutz /*
   2590  3786    arutz  * Done with a command.
   2591  3786    arutz  */
   2592  3786    arutz static void
   2593  3786    arutz dcddone_and_mutex_exit(struct dcd_disk *un, register struct buf *bp)
   2594  3786    arutz {
   2595  3786    arutz 	struct diskhd *dp;
   2596  3786    arutz 
   2597  3786    arutz 	TRACE_1(TR_FAC_DADA, TR_DCDONE_START, "dcddone_start: un 0x%p", un);
   2598  3786    arutz 
   2599  3786    arutz 	_NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&un->un_dcd->dcd_mutex));
   2600  3786    arutz 
   2601  3786    arutz 	dp = &un->un_utab;
   2602  3786    arutz 	if (bp == dp->b_forw) {
   2603  3786    arutz 		dp->b_forw = NULL;
   2604  3786    arutz 	}
   2605  3786    arutz 
   2606  3786    arutz 	if (un->un_stats) {
   2607  3786    arutz 		ulong_t n_done = bp->b_bcount - bp->b_resid;
   2608  3786    arutz 		if (bp->b_flags & B_READ) {
   2609  3786    arutz 			IOSP->reads++;
   2610  3786    arutz 			IOSP->nread += n_done;
   2611  3786    arutz 		} else {
   2612  3786    arutz 			IOSP->writes++;
   2613  3786    arutz 			IOSP->nwritten += n_done;
   2614  3786    arutz 		}
   2615  3786    arutz 	}
   2616  3786    arutz 	if (IO_PARTITION_STATS) {
   2617  3786    arutz 		ulong_t n_done = bp->b_bcount - bp->b_resid;
   2618  3786    arutz 		if (bp->b_flags & B_READ) {
   2619  3786    arutz 			IOSP_PARTITION->reads++;
   2620  3786    arutz 			IOSP_PARTITION->nread += n_done;
   2621  3786    arutz 		} else {
   2622  3786    arutz 			IOSP_PARTITION->writes++;
   2623  3786    arutz 			IOSP_PARTITION->nwritten += n_done;
   2624  3786    arutz 		}
   2625  3786    arutz 	}
   2626  3786    arutz 
   2627  3786    arutz 	/*
   2628  3786    arutz 	 * Start the next one before releasing resources on this one
   2629  3786    arutz 	 */
   2630  3786    arutz 	if (un->un_state == DCD_STATE_SUSPENDED) {
   2631  3786    arutz 		cv_broadcast(&un->un_disk_busy_cv);
   2632  3786    arutz 	} else if (dp->b_actf && (un->un_ncmds < un->un_throttle) &&
   2633  3786    arutz 	    (dp->b_forw == NULL && un->un_state != DCD_STATE_SUSPENDED)) {
   2634  3786    arutz 		dcdstart(un);
   2635  3786    arutz 	}
   2636  3786    arutz 
   2637  3786    arutz 	mutex_exit(DCD_MUTEX);
   2638  3786    arutz 
   2639  3786    arutz 	if (bp != un->un_sbufp) {
   2640  3786    arutz 		dcd_destroy_pkt(BP_PKT(bp));
   2641  3786    arutz 		DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2642  3786    arutz 		    "regular done: resid %ld\n", bp->b_resid);
   2643  3786    arutz 	} else {
   2644  3786    arutz 		ASSERT(un->un_sbuf_busy);
   2645  3786    arutz 	}
   2646  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCDDONE_BIODONE_CALL, "dcddone_biodone_call");
   2647  3786    arutz 
   2648  3786    arutz 	biodone(bp);
   2649  3786    arutz 
   2650  3786    arutz 	(void) pm_idle_component(DCD_DEVINFO, 0);
   2651  3786    arutz 
   2652  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCDDONE_END, "dcddone end");
   2653  3786    arutz }
   2654  3786    arutz 
   2655  3786    arutz 
   2656  3786    arutz /*
   2657  3786    arutz  * reset the disk unless the transport layer has already
   2658  3786    arutz  * cleared the problem
   2659  3786    arutz  */
   2660  3786    arutz #define	C1	(STAT_ATA_BUS_RESET|STAT_ATA_DEV_RESET|STAT_ATA_ABORTED)
   2661  3786    arutz static void
   2662  3786    arutz dcd_reset_disk(struct dcd_disk *un, struct dcd_pkt *pkt)
   2663  3786    arutz {
   2664  3786    arutz 
   2665  3786    arutz 	if ((pkt->pkt_statistics & C1) == 0) {
   2666  3786    arutz 		mutex_exit(DCD_MUTEX);
   2667  3786    arutz 		if (!dcd_reset(ROUTE, RESET_ALL)) {
   2668  3786    arutz 			DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2669  3786    arutz 			    "Reset failed");
   2670  3786    arutz 		}
   2671  3786    arutz 		mutex_enter(DCD_MUTEX);
   2672  3786    arutz 	}
   2673  3786    arutz }
   2674  3786    arutz 
   2675  3786    arutz static int
   2676  3786    arutz dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp)
   2677  3786    arutz {
   2678  3786    arutz 	static char *fail = "ATA transport failed: reason '%s': %s\n";
   2679  3786    arutz 	static char *notresp = "disk not responding to selection\n";
   2680  3786    arutz 	int rval = COMMAND_DONE_ERROR;
   2681  3786    arutz 	int action = COMMAND_SOFT_ERROR;
   2682  3786    arutz 	struct dcd_pkt *pkt = BP_PKT(bp);
   2683  3786    arutz 	int be_chatty = (un->un_state != DCD_STATE_SUSPENDED) &&
   2684  3786    arutz 	    (bp != un->un_sbufp || !(pkt->pkt_flags & FLAG_SILENT));
   2685  3786    arutz 
   2686  3786    arutz 	ASSERT(mutex_owned(DCD_MUTEX));
   2687  3786    arutz 
   2688  3786    arutz 	switch (pkt->pkt_reason) {
   2689  3786    arutz 
   2690  3786    arutz 	case CMD_TIMEOUT:
   2691  3786    arutz 		/*
   2692  3786    arutz 		 * This Indicates the already the HBA would  have reset
   2693  3786    arutz 		 * so Just indicate to retry the command
   2694  3786    arutz 		 */
   2695  3786    arutz 		break;
   2696  3786    arutz 
   2697  3786    arutz 	case CMD_INCOMPLETE:
   2698  3786    arutz 		action = dcd_check_error(un, bp);
   2699  3786    arutz 		DCD_DO_ERRSTATS(un, dcd_transerrs);
   2700  4137  kc28005 		if (action == COMMAND_HARD_ERROR) {
   2701  4137  kc28005 			(void) dcd_reset_disk(un, pkt);
   2702  4137  kc28005 		}
   2703  3786    arutz 		break;
   2704  3786    arutz 
   2705  3786    arutz 	case CMD_FATAL:
   2706  3786    arutz 		/*
   2707  3786    arutz 		 * Something drastic has gone wrong
   2708  3786    arutz 		 */
   2709  3786    arutz 		break;
   2710  3786    arutz 	case CMD_DMA_DERR:
   2711  3786    arutz 	case CMD_DATA_OVR:
   2712  3786    arutz 		/* FALLTHROUGH */
   2713  3786    arutz 
   2714  3786    arutz 	default:
   2715  3786    arutz 		/*
   2716  3786    arutz 		 * the target may still be running the	command,
   2717  3786    arutz 		 * so we should try and reset that target.
   2718  3786    arutz 		 */
   2719  3786    arutz 		DCD_DO_ERRSTATS(un, dcd_transerrs);
   2720  3786    arutz 		if ((pkt->pkt_reason != CMD_RESET) &&
   2721  7224      cth 		    (pkt->pkt_reason != CMD_ABORTED)) {
   2722  3786    arutz 			(void) dcd_reset_disk(un, pkt);
   2723  3786    arutz 		}
   2724  3786    arutz 		break;
   2725  3786    arutz 	}
   2726  3786    arutz 
   2727  3786    arutz 	/*
   2728  3786    arutz 	 * If pkt_reason is CMD_RESET/ABORTED, chances are that this pkt got
   2729  3786    arutz 	 * reset/aborted because another disk on this bus caused it.
   2730  3786    arutz 	 * The disk that caused it, should get CMD_TIMEOUT with pkt_statistics
   2731  3786    arutz 	 * of STAT_TIMEOUT/STAT_DEV_RESET
   2732  3786    arutz 	 */
   2733  3786    arutz 	if ((pkt->pkt_reason == CMD_RESET) ||(pkt->pkt_reason == CMD_ABORTED)) {
   2734  3786    arutz 		/* To be written : XXX */
   2735  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2736  3786    arutz 		    "Command aborted\n");
   2737  3786    arutz 	}
   2738  3786    arutz 
   2739  3786    arutz 	if (bp == un->un_sbufp && (pkt->pkt_flags & FLAG_DIAGNOSE)) {
   2740  3786    arutz 		rval = COMMAND_DONE_ERROR;
   2741  3786    arutz 	} else {
   2742  3786    arutz 		if ((rval == COMMAND_DONE_ERROR) &&
   2743  3786    arutz 		    (action == COMMAND_SOFT_ERROR) &&
   2744  3786    arutz 		    ((int)PKT_GET_RETRY_CNT(pkt) < dcd_retry_count)) {
   2745  3786    arutz 			PKT_INCR_RETRY_CNT(pkt, 1);
   2746  3786    arutz 			rval = QUE_COMMAND;
   2747  3786    arutz 		}
   2748  3786    arutz 	}
   2749  3786    arutz 
   2750  3786    arutz 	if (pkt->pkt_reason == CMD_INCOMPLETE && rval == COMMAND_DONE_ERROR) {
   2751  3786    arutz 		/*
   2752  3786    arutz 		 * Looks like someone turned off this shoebox.
   2753  3786    arutz 		 */
   2754  3786    arutz 		if (un->un_state != DCD_STATE_OFFLINE) {
   2755  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2756  7224      cth 			    (const char *) notresp);
   2757  3786    arutz 			New_state(un, DCD_STATE_OFFLINE);
   2758  3786    arutz 		}
   2759  3786    arutz 	} else if (pkt->pkt_reason == CMD_FATAL) {
   2760  3786    arutz 		/*
   2761  3786    arutz 		 * Suppressing the following message for the time being
   2762  3786    arutz 		 * dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2763  3786    arutz 		 * (const char *) notresp);
   2764  3786    arutz 		 */
   2765  3786    arutz 		PKT_INCR_RETRY_CNT(pkt, 6);
   2766  3786    arutz 		rval = COMMAND_DONE_ERROR;
   2767  3786    arutz 		New_state(un, DCD_STATE_FATAL);
   2768  3786    arutz 	} else if (be_chatty) {
   2769  3786    arutz 		int in_panic = ddi_in_panic();
   2770  3786    arutz 		if (!in_panic || (rval == COMMAND_DONE_ERROR)) {
   2771  3786    arutz 			if (((pkt->pkt_reason != un->un_last_pkt_reason) &&
   2772  3786    arutz 			    (pkt->pkt_reason != CMD_RESET)) ||
   2773  3786    arutz 			    (rval == COMMAND_DONE_ERROR) ||
   2774  3786    arutz 			    (dcd_error_level == DCD_ERR_ALL)) {
   2775  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2776  3786    arutz 				    fail, dcd_rname(pkt->pkt_reason),
   2777  3786    arutz 				    (rval == COMMAND_DONE_ERROR) ?
   2778  3786    arutz 				    "giving up": "retrying command");
   2779  3786    arutz 				DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2780  3786    arutz 				    "retrycount=%x\n",
   2781  3786    arutz 				    PKT_GET_RETRY_CNT(pkt));
   2782  3786    arutz 			}
   2783  3786    arutz 		}
   2784  3786    arutz 	}
   2785  3786    arutz error:
   2786  3786    arutz 	return (rval);
   2787  3786    arutz }
   2788  3786    arutz 
   2789  3786    arutz static int
   2790  3786    arutz dcd_check_error(struct dcd_disk *un, struct buf *bp)
   2791  3786    arutz {
   2792  3786    arutz 	struct diskhd *dp = &un->un_utab;
   2793  3786    arutz 	struct dcd_pkt *pkt = BP_PKT(bp);
   2794  3786    arutz 	int rval = 0;
   2795  3786    arutz 	unsigned char status;
   2796  3786    arutz 	unsigned char error;
   2797  3786    arutz 
   2798  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCD_CHECK_ERROR_START, "dcd_check_error_start");
   2799  3786    arutz 	ASSERT(mutex_owned(DCD_MUTEX));
   2800  3786    arutz 
   2801  3786    arutz 	DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   2802  3786    arutz 	    "Pkt: 0x%p dp: 0x%p\n", (void *)pkt, (void *)dp);
   2803  3786    arutz 
   2804  3786    arutz 	/*
   2805  3786    arutz 	 * Here we need to check status first and then if error is indicated
   2806  3786    arutz 	 * Then the error register.
   2807  3786    arutz 	 */
   2808  3786    arutz 
   2809  3786    arutz 	status = (pkt->pkt_scbp)[0];
   2810  3786    arutz 	if ((status & STATUS_ATA_DWF) == STATUS_ATA_DWF) {
   2811  3786    arutz 		/*
   2812  3786    arutz 		 * There has been a Device Fault  - reason for such error
   2813  3786    arutz 		 * is vendor specific
   2814  3786    arutz 		 * Action to be taken is - Indicate error and reset device.
   2815  3786    arutz 		 */
   2816  3786    arutz 
   2817  3786    arutz 		dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "Device Fault\n");
   2818  3786    arutz 		rval = COMMAND_HARD_ERROR;
   2819  3786    arutz 	} else if ((status & STATUS_ATA_CORR) == STATUS_ATA_CORR) {
   2820  3786    arutz 
   2821  3786    arutz 		/*
   2822  3786    arutz 		 * The sector read or written is marginal and hence ECC
   2823  3786    arutz 		 * Correction has been applied. Indicate to repair
   2824  3786    arutz 		 * Here we need to probably re-assign based on the badblock
   2825  3786    arutz 		 * mapping.
   2826  3786    arutz 		 */
   2827  3786    arutz 
   2828  3786    arutz 		dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2829  3786    arutz 		    "Soft Error on block %x\n",
   2830  3786    arutz 		    ((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num);
   2831  3786    arutz 		rval = COMMAND_SOFT_ERROR;
   2832  3786    arutz 	} else if ((status & STATUS_ATA_ERR) == STATUS_ATA_ERR) {
   2833  3786    arutz 		error = pkt->pkt_scbp[1];
   2834  3786    arutz 
   2835  3786    arutz 		dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2836  3786    arutz 		    "Command:0x%x,Error:0x%x,Status:0x%x\n",
   2837  3786    arutz 		    GETATACMD((struct dcd_cmd *)pkt->pkt_cdbp),
   2838  3786    arutz 		    error, status);
   2839  3786    arutz 		if ((error &  ERR_AMNF) == ERR_AMNF) {
   2840  3786    arutz 			/* Address make not found */
   2841  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2842  3786    arutz 			    "Address Mark Not Found");
   2843  3786    arutz 		} else if ((error & ERR_TKONF) == ERR_TKONF) {
   2844  3786    arutz 			/* Track 0 Not found */
   2845  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2846  3786    arutz 			    "Track 0 Not found \n");
   2847  3786    arutz 		} else if ((error & ERR_IDNF) == ERR_IDNF) {
   2848  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2849  3786    arutz 			    " ID not found \n");
   2850  3786    arutz 		} else if ((error &  ERR_UNC) == ERR_UNC) {
   2851  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2852  3786    arutz 			    "Uncorrectable data Error: Block %x\n",
   2853  7224      cth 			    ((struct dcd_cmd *)pkt->pkt_cdbp)->
   2854  7224      cth 			    sector_num.lba_num);
   2855  3786    arutz 		} else if ((error & ERR_BBK) == ERR_BBK) {
   2856  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2857  3786    arutz 			    "Bad block detected: Block %x\n",
   2858  7224      cth 			    ((struct dcd_cmd *)pkt->pkt_cdbp)->
   2859  7224      cth 			    sector_num.lba_num);
   2860  3786    arutz 		} else if ((error & ERR_ABORT) == ERR_ABORT) {
   2861  3786    arutz 			/* Aborted Command */
   2862  3786    arutz 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2863  3786    arutz 			    " Aborted Command \n");
   2864  3786    arutz 		}
   2865  3786    arutz 		/*
   2866  3786    arutz 		 * Return the soft error so that the command
   2867  3786    arutz 		 * will be retried.
   2868  3786    arutz 		 */
   2869  3786    arutz 		rval = COMMAND_SOFT_ERROR;
   2870  3786    arutz 	}
   2871  3786    arutz 
   2872  3786    arutz 	TRACE_0(TR_FAC_DADA, TR_DCD_CHECK_ERROR_END, "dcd_check_error_end");
   2873  3786    arutz 	return (rval);
   2874  3786    arutz }
   2875  3786    arutz 
   2876  3786    arutz 
   2877  3786    arutz /*
   2878  3786    arutz  *	System Crash Dump routine
   2879  3786    arutz  */
   2880  3786    arutz 
   2881  3786    arutz #define	NDUMP_RETRIES	5
   2882  3786    arutz 
   2883  3786    arutz static int
   2884  3786    arutz dcddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
   2885  3786    arutz {
   2886  3786    arutz 	struct dcd_pkt *pkt;
   2887  3786    arutz 	int i;
   2888  3786    arutz 	struct buf local, *bp;
   2889  3786    arutz 	int err;
   2890  3786    arutz 	unsigned char com;
   2891  3786    arutz 	diskaddr_t p_lblksrt;
   2892  3786    arutz 	diskaddr_t lblocks;
   2893  3786    arutz 
   2894  3786    arutz 	GET_SOFT_STATE(dev);
   2895  3786    arutz #ifdef lint
   2896  3786    arutz 	part = part;
   2897  3786    arutz #endif /* lint */
   2898  3786    arutz 
   2899  3786    arutz 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*un))
   2900  3786    arutz 
   2901  3786    arutz 	if ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL)
   2902  3786    arutz 		return (ENXIO);
   2903  3786    arutz 
   2904  3786    arutz 	if (cmlb_partinfo(un->un_dklbhandle, DCDPART(dev),
   2905  3786    arutz 	    &lblocks, &p_lblksrt, NULL, NULL, 0))
   2906  3786    arutz 		return (ENXIO);
   2907  3786    arutz 
   2908  3786    arutz 	if (blkno+nblk > lblocks) {
   2909  3786    arutz 		return (EINVAL);
   2910  3786    arutz 	}
   2911  3786    arutz 
   2912  3786    arutz 
   2913  3786    arutz 	if ((un->un_state == DCD_STATE_SUSPENDED) ||
   2914  3786    arutz 	    (un->un_state == DCD_STATE_PM_SUSPENDED)) {
   2915  3786    arutz 		if (pm_raise_power(DCD_DEVINFO, 0,
   2916  3786    arutz 		    DCD_DEVICE_ACTIVE) != DDI_SUCCESS) {
   2917  3786    arutz 			return (EIO);
   2918  3786    arutz 		}
   2919  3786    arutz 	}
   2920  3786    arutz 
   2921  3786    arutz 	/*
   2922  3786    arutz 	 * When cpr calls dcddump, we know that dad is in a
   2923  3786    arutz 	 * a good state, so no bus reset is required
   2924  3786    arutz 	 */
   2925  3786    arutz 	un->un_throttle = 0;
   2926  3786    arutz 
   2927  3786    arutz 	if ((un->un_state != DCD_STATE_SUSPENDED) &&
   2928  3786    arutz 	    (un->un_state != DCD_STATE_DUMPING)) {
   2929  3786    arutz 
   2930  3786    arutz 		New_state(un, DCD_STATE_DUMPING);
   2931  3786    arutz 
   2932  3786    arutz 		/*
   2933  3786    arutz 		 * Reset the bus. I'd like to not have to do this,
   2934  3786    arutz 		 * but this is the safest thing to do...
   2935  3786    arutz 		 */
   2936  3786    arutz 
   2937  3786    arutz 		if (dcd_reset(ROUTE, RESET_ALL) == 0) {
   2938  3786    arutz 			return (EIO);
   2939  3786    arutz 		}
   2940  3786    arutz 
   2941  3786    arutz 	}
   2942  3786    arutz 
   2943  3786    arutz 	blkno += p_lblksrt;
   2944  3786    arutz 
   2945  3786    arutz 	/*
   2946  3786    arutz 	 * It should be safe to call the allocator here without
   2947  3786    arutz 	 * worrying about being locked for DVMA mapping because
   2948  3786    arutz 	 * the address we're passed is already a DVMA mapping
   2949  3786    arutz 	 *
   2950  3786    arutz 	 * We are also not going to worry about semaphore ownership
   2951  3786    arutz 	 * in the dump buffer. Dumping is single threaded at present.
   2952  3786    arutz 	 */
   2953  3786    arutz 
   2954  3786    arutz 	bp = &local;
   2955  3786    arutz 	bzero((caddr_t)bp, sizeof (*bp));
   2956  3786    arutz 	bp->b_flags = B_BUSY;
   2957  3786    arutz 	bp->b_un.b_addr = addr;
   2958  3786    arutz 	bp->b_bcount = nblk << DEV_BSHIFT;
   2959  3786    arutz 	bp->b_resid = 0;
   2960  3786    arutz 
   2961  3786    arutz 	for (i = 0; i < NDUMP_RETRIES; i++) {
   2962  3786    arutz 		bp->b_flags &= ~B_ERROR;
   2963  3786    arutz 		if ((pkt = dcd_init_pkt(ROUTE, NULL, bp,
   2964  3786    arutz 		    (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN,
   2965  3786    arutz 		    PKT_CONSISTENT, NULL_FUNC, NULL)) != NULL) {
   2966  3786    arutz 			break;
   2967  3786    arutz 		}
   2968  3786    arutz 		if (i == 0) {
   2969  3786    arutz 			if (bp->b_flags & B_ERROR) {
   2970  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2971  3786    arutz 				    "no resources for dumping; "
   2972  3786    arutz 				    "error code: 0x%x, retrying",
   2973  3786    arutz 				    geterror(bp));
   2974  3786    arutz 			} else {
   2975  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
   2976  3786    arutz 				    "no resources for dumping; retrying");
   2977  3786    arutz 			}
   2978  3786    arutz 		} else if (i != (NDUMP_RETRIES - 1)) {
   2979  3786    arutz 			if (bp->b_flags & B_ERROR) {
   2980  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_CONT, "no "
   2981  3786    arutz 				    "resources for dumping; error code: 0x%x, "
   2982  3786    arutz 				    "retrying\n", geterror(bp));
   2983  3786    arutz 			}
   2984  3786    arutz 		} else {
   2985  3786    arutz 			if (bp->b_flags & B_ERROR) {
   2986  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_CONT,
   2987  3786    arutz 				    "no resources for dumping; "
   2988  3786    arutz 				    "error code: 0x%x, retries failed, "
   2989  3786    arutz 				    "giving up.\n", geterror(bp));
   2990  3786    arutz 			} else {
   2991  3786    arutz 				dcd_log(DCD_DEVINFO, dcd_label, CE_CONT,
   2992  3786    arutz 				    "no resources for dumping; "
   2993  3786    arutz 				    "retries failed, giving up.\n");
   2994  3786    arutz 			}
   2995  3786    arutz 			return (EIO);
   2996  3786    arutz 		}
   2997  3786    arutz 		delay(10);
   2998  3786    arutz 	}
   2999  3786    arutz 	if ((un->un_dp->options & DMA_SUPPORTTED) == DMA_SUPPORTTED) {
   3000  3786    arutz 		com = ATA_WRITE_DMA;
   3001  3786    arutz 	} else {
   3002  3786    arutz 		if (un->un_dp->options & BLOCK_MODE)
   3003  3786    arutz 			com = ATA_WRITE_MULTIPLE;
   3004  3786    arutz 		else
   3005  3786    arutz 			com = ATA_WRITE;
   3006  3786    arutz 	}
   3007  3786    arutz 
   3008  3786    arutz 	makecommand(pkt, 0, com, blkno, ADD_LBA_MODE,
   3009  3786    arutz 	    (int)nblk*un->un_secsize, DATA_WRITE, 0);
   3010  3786    arutz 
   3011  3786    arutz 	for (err = EIO, i = 0; i < NDUMP_RETRIES && err == EIO; i++) {
   3012  3786    arutz 
   3013  3786    arutz 		if (dcd_poll(pkt) == 0) {
   3014  3786    arutz 			switch (SCBP_C(pkt)) {
   3015  3786    arutz 			case STATUS_GOOD:
   3016  3786    arutz 				if (pkt->pkt_resid == 0) {
   3017  3786    arutz 					err = 0;
   3018  3786    arutz 				}
   3019  3786    arutz 				break;
   3020  3786    arutz 			case STATUS_ATA_BUSY:
   3021  3786    arutz 				(void) dcd_reset(ROUTE, RESET_TARGET);
   3022  3786    arutz 				break;
   3023  3786    arutz 			default:
   3024  3786    arutz 				mutex_enter(DCD_MUTEX);
   3025  3786    arutz 				(void) dcd_reset_disk(un, pkt);
   3026  3786    arutz 				mutex_exit(DCD_MUTEX);
   3027  3786    arutz 				break;
   3028  3786    arutz 			}
   3029  3786    arutz 		} else if (i > NDUMP_RETRIES/2) {
   3030  3786    arutz 			(void) dcd_reset(ROUTE, RESET_ALL);
   3031  3786    arutz 		}
   3032  3786    arutz 
   3033  3786    arutz 	}
   3034  3786    arutz 	dcd_destroy_pkt(pkt);
   3035  3786    arutz 	return (err);
   3036  3786    arutz }
   3037  3786    arutz 
   3038  3786    arutz /*
   3039  3786    arutz  * This routine implements the ioctl calls.  It is called
   3040  3786    arutz  * from the device switch at normal priority.
   3041  3786    arutz  */
   3042  3786    arutz /* ARGSUSED3 */
   3043  3786    arutz static int
   3044  3786    arutz dcdioctl(dev_t dev, int cmd, intptr_t arg, int flag,
   3045  3786    arutz 	cred_t *cred_p, int *rval_p)
   3046  3786    arutz {
   3047  3786    arutz 	auto int32_t data[512 / (sizeof (int32_t))];
   3048  3786    arutz 	struct dk_cinfo *info;
   3049  3786    arutz 	struct dk_minfo media_info;
   3050  3786    arutz 	struct udcd_cmd *scmd;
   3051  3786    arutz 	int i, err;
   3052  3786    arutz 	enum uio_seg uioseg = 0;
   3053  3786    arutz 	enum dkio_state state = 0;
   3054  3786    arutz #ifdef _MULTI_DATAMODEL
   3055  3786    arutz 	struct dadkio_rwcmd rwcmd;
   3056  3786    arutz #endif
   3057  3786    arutz 	struct dadkio_rwcmd32 rwcmd32;
   3058  3786    arutz 	struct dcd_cmd dcdcmd;
   3059  3786    arutz 
   3060  3786    arutz 	GET_SOFT_STATE(dev);
   3061  3786    arutz #ifdef lint
   3062  3786    arutz 	part = part;
   3063  3786    arutz 	state = state;
   3064  3786    arutz 	uioseg = uioseg;
   3065  3786    arutz #endif  /* lint */
   3066  3786    arutz 
   3067  3786    arutz 	DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   3068  3786    arutz 	    "dcd_ioctl : cmd %x, arg %lx\n", cmd, arg);
   3069  3786    arutz 
   3070  3786    arutz 	bzero((caddr_t)data, sizeof (data));
   3071  3786    arutz 
   3072  3786    arutz 	switch (cmd) {
   3073  3786    arutz 
   3074  3786    arutz #ifdef DCDDEBUG
   3075  3786    arutz /*
   3076  3786    arutz  * Following ioctl are for testing RESET/ABORTS
   3077  3786    arutz  */
   3078  3786    arutz #define	DKIOCRESET	(DKIOC|14)
   3079  3786    arutz #define	DKIOCABORT	(DKIOC|15)
   3080  3786    arutz 
   3081  3786    arutz 	case DKIOCRESET:
   3082  3786    arutz 		if (ddi_copyin((caddr_t)arg, (caddr_t)data, 4, flag))
   3083  3786    arutz 			return (EFAULT);
   3084  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   3085  3786    arutz 		    "DKIOCRESET: data = 0x%x\n", data[0]);
   3086  3786    arutz 		if (dcd_reset(ROUTE, data[0])) {
   3087  3786    arutz 			return (0);
   3088  3786    arutz 		} else {
   3089  3786    arutz 			return (EIO);
   3090  3786    arutz 		}
   3091  3786    arutz 	case DKIOCABORT:
   3092  3786    arutz 		DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG,
   3093  3786    arutz 		    "DKIOCABORT:\n");
   3094  3786    arutz 		if (dcd_abort(ROUTE, (struct dcd_pkt *)0)) {
   3095  3786    arutz 			return (0);
   3096  3786    arutz 		} else {
   3097  3786    arutz 			return (EIO);
   3098  3786    arutz 		}
   3099  3786    arutz #endif
   3100  3786    arutz 
   3101  3786    arutz 	case DKIOCINFO:
   3102  3786    arutz 		/*
   3103  3786    arutz 		 * Controller Information
   3104  3786    arutz 		 */
   3105  3786    arutz 		info = (struct dk_cinfo *)data;
   3106  3786    arutz 
   3107  3786    arutz 		mutex_enter(DCD_MUTEX);
   3108  3786    arutz 		switch (un->un_dp->ctype) {
   3109  3786    arutz 		default:
   3110  3786    arutz 			info->dki_ctype = DKC_DIRECT;
   3111  3786    arutz 			break;
   3112  3786    arutz 		}
   3113  3786    arutz 		mutex_exit(DCD_MUTEX);
   3114  3786    arutz 		info->dki_cnum = ddi_get_instance(ddi_get_parent(DCD_DEVINFO));
   3115  3786    arutz 		(void) strcpy(info->dki_cname,
   3116  3786    arutz 		    ddi_get_name(ddi_get_parent(DCD_DEVINFO)));
   3117  3786    arutz 		/*
   3118  3786    arutz 		 * Unit Information
   3119  3786    arutz 		 */
   3120  3786    arutz 		info->dki_unit = ddi_get_instance(DCD_DEVINFO);
   3121  3786    arutz 		info->dki_slave = (Tgt(DCD_DCD_DEVP)<<3);
   3122  3786    arutz 		(void) strcpy(info->dki_dname, ddi_driver_name(DCD_DEVINFO));
   3123  3786    arutz 		info->dki_flags = DKI_FMTVOL;
   3124  3786    arutz 		info->dki_partition = DCDPART(dev);
   3125  3786    arutz 
   3126  3786    arutz 		/*
   3127  3786    arutz 		 * Max Transfer size of this device in blocks
   3128  3786    arutz 		 */
   3129  3786    arutz 		info->dki_maxtransfer = un->un_max_xfer_size / DEV_BSIZE;
   3130  3786    arutz 
   3131  3786    arutz 		/*
   3132  3786    arutz 		 * We can't get from here to there yet
   3133