xref: /onnv-gate/usr/src/uts/intel/io/dktp/dcdev/dadk.c (revision 7563:84ec90ffc3f7)
11709Smlf /*
21709Smlf  * CDDL HEADER START
31709Smlf  *
41709Smlf  * The contents of this file are subject to the terms of the
51709Smlf  * Common Development and Distribution License (the "License").
61709Smlf  * You may not use this file except in compliance with the License.
71709Smlf  *
81709Smlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91709Smlf  * or http://www.opensolaris.org/os/licensing.
101709Smlf  * See the License for the specific language governing permissions
111709Smlf  * and limitations under the License.
121709Smlf  *
131709Smlf  * When distributing Covered Code, include this CDDL HEADER in each
141709Smlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151709Smlf  * If applicable, add the following below this CDDL HEADER, with the
161709Smlf  * fields enclosed by brackets "[]" replaced with your own identifying
171709Smlf  * information: Portions Copyright [yyyy] [name of copyright owner]
181709Smlf  *
191709Smlf  * CDDL HEADER END
201709Smlf  */
211709Smlf 
221709Smlf /*
237239Szk194757  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241709Smlf  * Use is subject to license terms.
251709Smlf  */
261709Smlf 
271709Smlf /*
281709Smlf  * Direct Attached Disk
291709Smlf  */
301709Smlf 
311709Smlf #include <sys/file.h>
321709Smlf #include <sys/scsi/scsi.h>
331709Smlf #include <sys/var.h>
341709Smlf #include <sys/proc.h>
351709Smlf #include <sys/dktp/cm.h>
361709Smlf #include <sys/vtoc.h>
371709Smlf #include <sys/dkio.h>
383652Syt160523 #include <sys/policy.h>
393652Syt160523 #include <sys/priv.h>
401709Smlf 
411709Smlf #include <sys/dktp/dadev.h>
421709Smlf #include <sys/dktp/fctypes.h>
431709Smlf #include <sys/dktp/flowctrl.h>
441709Smlf #include <sys/dktp/tgcom.h>
451709Smlf #include <sys/dktp/tgdk.h>
461709Smlf #include <sys/dktp/bbh.h>
471709Smlf #include <sys/dktp/dadkio.h>
481709Smlf #include <sys/dktp/dadk.h>
491709Smlf #include <sys/cdio.h>
501709Smlf 
511709Smlf /*
521709Smlf  * Local Function Prototypes
531709Smlf  */
541709Smlf static void dadk_restart(void *pktp);
551709Smlf static void dadk_pktcb(struct cmpkt *pktp);
561709Smlf static void dadk_iodone(struct buf *bp);
571709Smlf static void dadk_polldone(struct buf *bp);
581709Smlf static void dadk_setcap(struct dadk *dadkp);
592799Smarx static void dadk_create_errstats(struct dadk *dadkp, int instance);
602799Smarx static void dadk_destroy_errstats(struct dadk *dadkp);
611709Smlf 
621709Smlf static int dadk_chkerr(struct cmpkt *pktp);
631709Smlf static int dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp);
641709Smlf static int dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp);
651709Smlf static int dadk_ioretry(struct cmpkt *pktp, int action);
661709Smlf 
671709Smlf static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp,
681709Smlf     struct buf *bp, void (*cb_func)(struct buf *), int (*func)(caddr_t),
691709Smlf     caddr_t arg);
701709Smlf 
711709Smlf static int  dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t),
721709Smlf     caddr_t arg);
731709Smlf static void dadk_transport(opaque_t com_data, struct buf *bp);
745295Srandyf static int dadk_ctl_ioctl(struct dadk *, uint32_t, uintptr_t, int);
751709Smlf 
761709Smlf struct tgcom_objops dadk_com_ops = {
771709Smlf 	nodev,
781709Smlf 	nodev,
791709Smlf 	dadk_pkt,
801709Smlf 	dadk_transport,
811709Smlf 	0, 0
821709Smlf };
831709Smlf 
841709Smlf /*
851709Smlf  * architecture dependent allocation restrictions for dadk_iob_alloc(). For
861709Smlf  * x86, we'll set dma_attr_addr_hi to dadk_max_phys_addr and dma_attr_sgllen
871709Smlf  * to dadk_sgl_size during _init().
881709Smlf  */
891709Smlf #if defined(__sparc)
901709Smlf static ddi_dma_attr_t dadk_alloc_attr = {
911709Smlf 	DMA_ATTR_V0,	/* version number */
921709Smlf 	0x0,		/* lowest usable address */
931709Smlf 	0xFFFFFFFFull,	/* high DMA address range */
941709Smlf 	0xFFFFFFFFull,	/* DMA counter register */
951709Smlf 	1,		/* DMA address alignment */
961709Smlf 	1,		/* DMA burstsizes */
971709Smlf 	1,		/* min effective DMA size */
981709Smlf 	0xFFFFFFFFull,	/* max DMA xfer size */
991709Smlf 	0xFFFFFFFFull,	/* segment boundary */
1001709Smlf 	1,		/* s/g list length */
1011709Smlf 	512,		/* granularity of device */
1021709Smlf 	0,		/* DMA transfer flags */
1031709Smlf };
1041709Smlf #elif defined(__x86)
1051709Smlf static ddi_dma_attr_t dadk_alloc_attr = {
1061709Smlf 	DMA_ATTR_V0,	/* version number */
1071709Smlf 	0x0,		/* lowest usable address */
1081709Smlf 	0x0,		/* high DMA address range [set in _init()] */
1091709Smlf 	0xFFFFull,	/* DMA counter register */
1101709Smlf 	512,		/* DMA address alignment */
1111709Smlf 	1,		/* DMA burstsizes */
1121709Smlf 	1,		/* min effective DMA size */
1131709Smlf 	0xFFFFFFFFull,	/* max DMA xfer size */
1141709Smlf 	0xFFFFFFFFull,	/* segment boundary */
1151709Smlf 	0,		/* s/g list length [set in _init()] */
1161709Smlf 	512,		/* granularity of device */
1171709Smlf 	0,		/* DMA transfer flags */
1181709Smlf };
1191709Smlf 
1201709Smlf uint64_t dadk_max_phys_addr = 0xFFFFFFFFull;
1211709Smlf int dadk_sgl_size = 0xFF;
1221709Smlf #endif
1231709Smlf 
1241709Smlf static int dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags,
1251709Smlf     int silent);
1261709Smlf static void dadk_rmb_iodone(struct buf *bp);
1271709Smlf 
1281709Smlf static int dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp,
1291709Smlf     dev_t dev, enum uio_seg dataspace, int rw);
1301709Smlf static void dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *scmdp,
1311709Smlf     struct buf *bp);
1321709Smlf static void dadkmin(struct buf *bp);
1331709Smlf static int dadk_dk_strategy(struct buf *bp);
1341709Smlf static void dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp);
1351709Smlf 
1361709Smlf struct tgdk_objops dadk_ops = {
1371709Smlf 	dadk_init,
1381709Smlf 	dadk_free,
1391709Smlf 	dadk_probe,
1401709Smlf 	dadk_attach,
1411709Smlf 	dadk_open,
1421709Smlf 	dadk_close,
1431709Smlf 	dadk_ioctl,
1441709Smlf 	dadk_strategy,
1451709Smlf 	dadk_setgeom,
1461709Smlf 	dadk_getgeom,
1471709Smlf 	dadk_iob_alloc,
1481709Smlf 	dadk_iob_free,
1491709Smlf 	dadk_iob_htoc,
1501709Smlf 	dadk_iob_xfer,
1511709Smlf 	dadk_dump,
1521709Smlf 	dadk_getphygeom,
1531709Smlf 	dadk_set_bbhobj,
1541709Smlf 	dadk_check_media,
1551709Smlf 	dadk_inquiry,
1561709Smlf 	dadk_cleanup,
1571709Smlf 	0
1581709Smlf };
1591709Smlf 
1601709Smlf /*
1611709Smlf  * Local static data
1621709Smlf  */
1631709Smlf 
1641709Smlf #ifdef	DADK_DEBUG
1651709Smlf #define	DENT	0x0001
1661709Smlf #define	DERR	0x0002
1671709Smlf #define	DIO	0x0004
1681709Smlf #define	DGEOM	0x0010
1691709Smlf #define	DSTATE  0x0020
1701709Smlf static	int	dadk_debug = DGEOM;
1711709Smlf 
1721709Smlf #endif	/* DADK_DEBUG */
1731709Smlf 
1741709Smlf static int dadk_check_media_time = 3000000;	/* 3 Second State Check */
1751709Smlf static int dadk_dk_maxphys = 0x80000;
1761709Smlf 
1771709Smlf static char	*dadk_cmds[] = {
1781709Smlf 	"\000Unknown",			/* unknown 		*/
1791709Smlf 	"\001read sector",		/* DCMD_READ 1		*/
1801709Smlf 	"\002write sector",		/* DCMD_WRITE 2		*/
1811709Smlf 	"\003format track",		/* DCMD_FMTTRK 3	*/
1821709Smlf 	"\004format whole drive",	/* DCMD_FMTDRV 4	*/
1831709Smlf 	"\005recalibrate",		/* DCMD_RECAL  5	*/
1841709Smlf 	"\006seek sector",		/* DCMD_SEEK   6	*/
1851709Smlf 	"\007read verify",		/* DCMD_RDVER  7	*/
1861709Smlf 	"\010read defect list",		/* DCMD_GETDEF 8	*/
1871709Smlf 	"\011lock door",		/* DCMD_LOCK   9	*/
1881709Smlf 	"\012unlock door",		/* DCMD_UNLOCK 10	*/
1891709Smlf 	"\013start motor",		/* DCMD_START_MOTOR 11	*/
1901709Smlf 	"\014stop motor",		/* DCMD_STOP_MOTOR 12	*/
1911709Smlf 	"\015eject",			/* DCMD_EJECT  13	*/
1921709Smlf 	"\016update geometry",		/* DCMD_UPDATE_GEOM  14	*/
1931709Smlf 	"\017get state",		/* DCMD_GET_STATE  15	*/
1941709Smlf 	"\020cdrom pause",		/* DCMD_PAUSE  16	*/
1951709Smlf 	"\021cdrom resume",		/* DCMD_RESUME  17	*/
1961709Smlf 	"\022cdrom play track index",	/* DCMD_PLAYTRKIND  18	*/
1971709Smlf 	"\023cdrom play msf",		/* DCMD_PLAYMSF  19	*/
1981709Smlf 	"\024cdrom sub channel",	/* DCMD_SUBCHNL  20	*/
1991709Smlf 	"\025cdrom read mode 1",	/* DCMD_READMODE1  21	*/
2001709Smlf 	"\026cdrom read toc header",	/* DCMD_READTOCHDR  22	*/
2011709Smlf 	"\027cdrom read toc entry",	/* DCMD_READTOCENT  23	*/
2021709Smlf 	"\030cdrom read offset",	/* DCMD_READOFFSET  24	*/
2031709Smlf 	"\031cdrom read mode 2",	/* DCMD_READMODE2  25	*/
2041709Smlf 	"\032cdrom volume control",	/* DCMD_VOLCTRL  26	*/
2051709Smlf 	"\033flush cache",		/* DCMD_FLUSH_CACHE  27	*/
2061709Smlf 	NULL
2071709Smlf };
2081709Smlf 
2091709Smlf static char *dadk_sense[] = {
2101709Smlf 	"\000Success",			/* DERR_SUCCESS		*/
2111709Smlf 	"\001address mark not found",	/* DERR_AMNF		*/
2121709Smlf 	"\002track 0 not found",	/* DERR_TKONF		*/
2131709Smlf 	"\003aborted command",		/* DERR_ABORT		*/
2141709Smlf 	"\004write fault",		/* DERR_DWF		*/
2151709Smlf 	"\005ID not found",		/* DERR_IDNF		*/
2161709Smlf 	"\006drive busy",		/* DERR_BUSY		*/
2171709Smlf 	"\007uncorrectable data error",	/* DERR_UNC		*/
2181709Smlf 	"\010bad block detected",	/* DERR_BBK		*/
2191709Smlf 	"\011invalid command",		/* DERR_INVCDB		*/
2201709Smlf 	"\012device hard error",	/* DERR_HARD		*/
2211709Smlf 	"\013illegal length indicated", /* DERR_ILI		*/
2221709Smlf 	"\014end of media",		/* DERR_EOM		*/
2231709Smlf 	"\015media change requested",	/* DERR_MCR		*/
2241709Smlf 	"\016recovered from error",	/* DERR_RECOVER		*/
2251709Smlf 	"\017device not ready",		/* DERR_NOTREADY	*/
2261709Smlf 	"\020medium error",		/* DERR_MEDIUM		*/
2271709Smlf 	"\021hardware error",		/* DERR_HW		*/
2281709Smlf 	"\022illegal request",		/* DERR_ILL		*/
2291709Smlf 	"\023unit attention",		/* DERR_UNIT_ATTN	*/
2301709Smlf 	"\024data protection",		/* DERR_DATA_PROT	*/
2311709Smlf 	"\025miscompare",		/* DERR_MISCOMPARE	*/
2321709Smlf 	"\026ICRC error during UDMA",	/* DERR_ICRC		*/
2331709Smlf 	"\027reserved",			/* DERR_RESV		*/
2341709Smlf 	NULL
2351709Smlf };
2361709Smlf 
2371709Smlf static char *dadk_name = "Disk";
2381709Smlf 
2391709Smlf /*
2401709Smlf  *	This is the loadable module wrapper
2411709Smlf  */
2421709Smlf #include <sys/modctl.h>
2431709Smlf 
2441709Smlf extern struct mod_ops mod_miscops;
2451709Smlf 
2461709Smlf static struct modlmisc modlmisc = {
2471709Smlf 	&mod_miscops,	/* Type of module */
2487239Szk194757 	"Direct Attached Disk"
2491709Smlf };
2501709Smlf 
2511709Smlf static struct modlinkage modlinkage = {
2521709Smlf 	MODREV_1, (void *)&modlmisc, NULL
2531709Smlf };
2541709Smlf 
2551709Smlf int
2561709Smlf _init(void)
2571709Smlf {
2581709Smlf #ifdef DADK_DEBUG
2591709Smlf 	if (dadk_debug & DENT)
2601709Smlf 		PRF("dadk_init: call\n");
2611709Smlf #endif
2621709Smlf 
2631709Smlf #if defined(__x86)
2641709Smlf 	/* set the max physical address for iob allocs on x86 */
2651709Smlf 	dadk_alloc_attr.dma_attr_addr_hi = dadk_max_phys_addr;
2661709Smlf 
2671709Smlf 	/*
2681709Smlf 	 * set the sgllen for iob allocs on x86. If this is set less than
2691709Smlf 	 * the number of pages the buffer will take (taking into account
2701709Smlf 	 * alignment), it would force the allocator to try and allocate
2711709Smlf 	 * contiguous pages.
2721709Smlf 	 */
2731709Smlf 	dadk_alloc_attr.dma_attr_sgllen = dadk_sgl_size;
2741709Smlf #endif
2751709Smlf 
2761709Smlf 	return (mod_install(&modlinkage));
2771709Smlf }
2781709Smlf 
2791709Smlf int
2801709Smlf _fini(void)
2811709Smlf {
2821709Smlf #ifdef DADK_DEBUG
2831709Smlf 	if (dadk_debug & DENT)
2841709Smlf 		PRF("dadk_fini: call\n");
2851709Smlf #endif
2861709Smlf 
2871709Smlf 	return (mod_remove(&modlinkage));
2881709Smlf }
2891709Smlf 
2901709Smlf int
2911709Smlf _info(struct modinfo *modinfop)
2921709Smlf {
2931709Smlf 	return (mod_info(&modlinkage, modinfop));
2941709Smlf }
2951709Smlf 
2961709Smlf struct tgdk_obj *
2971709Smlf dadk_create()
2981709Smlf {
2991709Smlf 	struct tgdk_obj *dkobjp;
3001709Smlf 	struct dadk *dadkp;
3011709Smlf 
3021709Smlf 	dkobjp = kmem_zalloc((sizeof (*dkobjp) + sizeof (*dadkp)), KM_NOSLEEP);
3031709Smlf 	if (!dkobjp)
3041709Smlf 		return (NULL);
3051709Smlf 	dadkp = (struct dadk *)(dkobjp+1);
3061709Smlf 
3071709Smlf 	dkobjp->tg_ops  = (struct  tgdk_objops *)&dadk_ops;
3081709Smlf 	dkobjp->tg_data = (opaque_t)dadkp;
3091709Smlf 	dkobjp->tg_ext = &(dkobjp->tg_extblk);
3101709Smlf 	dadkp->dad_extp = &(dkobjp->tg_extblk);
3111709Smlf 
3121709Smlf #ifdef DADK_DEBUG
3131709Smlf 	if (dadk_debug & DENT)
3141709Smlf 		PRF("dadk_create: tgdkobjp= 0x%x dadkp= 0x%x\n", dkobjp, dadkp);
3151709Smlf #endif
3161709Smlf 	return (dkobjp);
3171709Smlf }
3181709Smlf 
3191709Smlf int
3201709Smlf dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp,
3211709Smlf 	opaque_t bbhobjp, void *lkarg)
3221709Smlf {
3231709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
3241709Smlf 	struct scsi_device *sdevp = (struct scsi_device *)devp;
3251709Smlf 
3261709Smlf 	dadkp->dad_sd = devp;
3271709Smlf 	dadkp->dad_ctlobjp = (opaque_t)sdevp->sd_address.a_hba_tran;
3281709Smlf 	sdevp->sd_private = (caddr_t)dadkp;
3291709Smlf 
3301709Smlf 	/* initialize the communication object */
3311709Smlf 	dadkp->dad_com.com_data = (opaque_t)dadkp;
3321709Smlf 	dadkp->dad_com.com_ops  = &dadk_com_ops;
3331709Smlf 
3341709Smlf 	dadkp->dad_bbhobjp = bbhobjp;
3351709Smlf 	BBH_INIT(bbhobjp);
3361709Smlf 
3371709Smlf 	dadkp->dad_flcobjp = flcobjp;
3385295Srandyf 	mutex_init(&dadkp->dad_cmd_mutex, NULL, MUTEX_DRIVER, NULL);
3395295Srandyf 	dadkp->dad_cmd_count = 0;
3401709Smlf 	return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg));
3411709Smlf }
3421709Smlf 
3431709Smlf int
3441709Smlf dadk_free(struct tgdk_obj *dkobjp)
3451709Smlf {
3461709Smlf 	TGDK_CLEANUP(dkobjp);
3471709Smlf 	kmem_free(dkobjp, (sizeof (*dkobjp) + sizeof (struct dadk)));
3481709Smlf 
3491709Smlf 	return (DDI_SUCCESS);
3501709Smlf }
3511709Smlf 
3521709Smlf void
3531709Smlf dadk_cleanup(struct tgdk_obj *dkobjp)
3541709Smlf {
3551709Smlf 	struct dadk *dadkp;
3561709Smlf 
3571709Smlf 	dadkp = (struct dadk *)(dkobjp->tg_data);
3581709Smlf 	if (dadkp->dad_sd)
3591709Smlf 		dadkp->dad_sd->sd_private = NULL;
3601709Smlf 	if (dadkp->dad_bbhobjp) {
3611709Smlf 		BBH_FREE(dadkp->dad_bbhobjp);
3621709Smlf 		dadkp->dad_bbhobjp = NULL;
3631709Smlf 	}
3641709Smlf 	if (dadkp->dad_flcobjp) {
3651709Smlf 		FLC_FREE(dadkp->dad_flcobjp);
3661709Smlf 		dadkp->dad_flcobjp = NULL;
3671709Smlf 	}
3685295Srandyf 	mutex_destroy(&dadkp->dad_cmd_mutex);
3691709Smlf }
3701709Smlf 
3711709Smlf /* ARGSUSED */
3721709Smlf int
3731709Smlf dadk_probe(opaque_t objp, int kmsflg)
3741709Smlf {
3751709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
3761709Smlf 	struct scsi_device *devp;
3771709Smlf 	char   name[80];
3781709Smlf 
3791709Smlf 	devp = dadkp->dad_sd;
3801709Smlf 	if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) ||
3815295Srandyf 	    (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) {
3821709Smlf 		return (DDI_PROBE_FAILURE);
3831709Smlf 	}
3841709Smlf 
3851709Smlf 	switch (devp->sd_inq->inq_dtype) {
3861709Smlf 		case DTYPE_DIRECT:
3871709Smlf 			dadkp->dad_ctype = DKC_DIRECT;
3881709Smlf 			dadkp->dad_extp->tg_nodetype = DDI_NT_BLOCK;
3891709Smlf 			dadkp->dad_extp->tg_ctype = DKC_DIRECT;
3901709Smlf 			break;
3911709Smlf 		case DTYPE_RODIRECT: /* eg cdrom */
3921709Smlf 			dadkp->dad_ctype = DKC_CDROM;
3931709Smlf 			dadkp->dad_extp->tg_rdonly = 1;
3941709Smlf 			dadkp->dad_rdonly = 1;
3951709Smlf 			dadkp->dad_cdrom = 1;
3961709Smlf 			dadkp->dad_extp->tg_nodetype = DDI_NT_CD;
3971709Smlf 			dadkp->dad_extp->tg_ctype = DKC_CDROM;
3981709Smlf 			break;
3991709Smlf 		case DTYPE_WORM:
4001709Smlf 		case DTYPE_OPTICAL:
4011709Smlf 		default:
4021709Smlf 			return (DDI_PROBE_FAILURE);
4031709Smlf 	}
4041709Smlf 
4051709Smlf 	dadkp->dad_extp->tg_rmb = dadkp->dad_rmb = devp->sd_inq->inq_rmb;
4061709Smlf 
4071709Smlf 	dadkp->dad_secshf = SCTRSHFT;
4081709Smlf 	dadkp->dad_blkshf = 0;
4091709Smlf 
4101709Smlf 	/* display the device name */
4111709Smlf 	(void) strcpy(name, "Vendor '");
4121709Smlf 	gda_inqfill((caddr_t)devp->sd_inq->inq_vid, 8, &name[strlen(name)]);
4131709Smlf 	(void) strcat(name, "' Product '");
4141709Smlf 	gda_inqfill((caddr_t)devp->sd_inq->inq_pid, 16, &name[strlen(name)]);
4151709Smlf 	(void) strcat(name, "'");
4161709Smlf 	gda_log(devp->sd_dev, dadk_name, CE_NOTE, "!<%s>\n", name);
4171709Smlf 
4181709Smlf 	return (DDI_PROBE_SUCCESS);
4191709Smlf }
4201709Smlf 
4211709Smlf 
4221709Smlf /* ARGSUSED */
4231709Smlf int
4241709Smlf dadk_attach(opaque_t objp)
4251709Smlf {
4261709Smlf 	return (DDI_SUCCESS);
4271709Smlf }
4281709Smlf 
4291709Smlf int
4301709Smlf dadk_set_bbhobj(opaque_t objp, opaque_t bbhobjp)
4311709Smlf {
4321709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
4331709Smlf 	/* free the old bbh object */
4341709Smlf 	if (dadkp->dad_bbhobjp)
4351709Smlf 		BBH_FREE(dadkp->dad_bbhobjp);
4361709Smlf 
4371709Smlf 	/* initialize the new bbh object */
4381709Smlf 	dadkp->dad_bbhobjp = bbhobjp;
4391709Smlf 	BBH_INIT(bbhobjp);
4401709Smlf 
4411709Smlf 	return (DDI_SUCCESS);
4421709Smlf }
4431709Smlf 
4441709Smlf /* ARGSUSED */
4451709Smlf int
4461709Smlf dadk_open(opaque_t objp, int flag)
4471709Smlf {
4481709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
4491709Smlf 	int error;
4501709Smlf 	int wce;
4511709Smlf 
4521709Smlf 	if (!dadkp->dad_rmb) {
4531709Smlf 		if (dadkp->dad_phyg.g_cap) {
4541709Smlf 			FLC_START_KSTAT(dadkp->dad_flcobjp, "disk",
4551709Smlf 			    ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
4561709Smlf 			return (DDI_SUCCESS);
4571709Smlf 		}
4581709Smlf 	} else {
4595295Srandyf 		mutex_enter(&dadkp->dad_mutex);
4605295Srandyf 		dadkp->dad_iostate = DKIO_NONE;
4615295Srandyf 		cv_broadcast(&dadkp->dad_state_cv);
4625295Srandyf 		mutex_exit(&dadkp->dad_mutex);
4631709Smlf 
4645295Srandyf 		if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0,
4655295Srandyf 		    DADK_SILENT) ||
4665295Srandyf 		    dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) ||
4675295Srandyf 		    dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0,
4685295Srandyf 		    DADK_SILENT)) {
4695295Srandyf 			return (DDI_FAILURE);
4705295Srandyf 		}
4711709Smlf 
4725295Srandyf 		mutex_enter(&dadkp->dad_mutex);
4735295Srandyf 		dadkp->dad_iostate = DKIO_INSERTED;
4745295Srandyf 		cv_broadcast(&dadkp->dad_state_cv);
4755295Srandyf 		mutex_exit(&dadkp->dad_mutex);
4761709Smlf 	}
4771709Smlf 
4781709Smlf 	/*
4791709Smlf 	 * get write cache enable state
4801709Smlf 	 * If there is an error, must assume that write cache
4811709Smlf 	 * is enabled.
4821709Smlf 	 * NOTE: Since there is currently no Solaris mechanism to
4831709Smlf 	 * change the state of the Write Cache Enable feature,
4841709Smlf 	 * this code just checks the value of the WCE bit
4851709Smlf 	 * obtained at device init time.  If a mechanism
4861709Smlf 	 * is added to the driver to change WCE, dad_wce
4871709Smlf 	 * must be updated appropriately.
4881709Smlf 	 */
4895295Srandyf 	error = dadk_ctl_ioctl(dadkp, DIOCTL_GETWCE,
4902799Smarx 	    (uintptr_t)&wce, FKIOCTL | FNATIVE);
4911709Smlf 	mutex_enter(&dadkp->dad_mutex);
4921709Smlf 	dadkp->dad_wce = (error != 0) || (wce != 0);
4931709Smlf 	mutex_exit(&dadkp->dad_mutex);
4941709Smlf 
4951709Smlf 	/* logical disk geometry */
4965295Srandyf 	(void) dadk_ctl_ioctl(dadkp, DIOCTL_GETGEOM,
4972799Smarx 	    (uintptr_t)&dadkp->dad_logg, FKIOCTL | FNATIVE);
4981709Smlf 	if (dadkp->dad_logg.g_cap == 0)
4991709Smlf 		return (DDI_FAILURE);
5001709Smlf 
5011709Smlf 	/* get physical disk geometry */
5025295Srandyf 	(void) dadk_ctl_ioctl(dadkp, DIOCTL_GETPHYGEOM,
5032799Smarx 	    (uintptr_t)&dadkp->dad_phyg, FKIOCTL | FNATIVE);
5041709Smlf 	if (dadkp->dad_phyg.g_cap == 0)
5051709Smlf 		return (DDI_FAILURE);
5061709Smlf 
5071709Smlf 	dadk_setcap(dadkp);
5081709Smlf 
5092799Smarx 	dadk_create_errstats(dadkp,
5102799Smarx 	    ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
5112799Smarx 
5121709Smlf 	/* start profiling */
5131709Smlf 	FLC_START_KSTAT(dadkp->dad_flcobjp, "disk",
5145295Srandyf 	    ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
5151709Smlf 
5161709Smlf 	return (DDI_SUCCESS);
5171709Smlf }
5181709Smlf 
5191709Smlf static void
5201709Smlf dadk_setcap(struct dadk *dadkp)
5211709Smlf {
5221709Smlf 	int	 totsize;
5231709Smlf 	int	 i;
5241709Smlf 
5251709Smlf 	totsize = dadkp->dad_phyg.g_secsiz;
5261709Smlf 
5271709Smlf 	if (totsize == 0) {
5281709Smlf 		if (dadkp->dad_cdrom) {
5291709Smlf 			totsize = 2048;
5301709Smlf 		} else {
5311709Smlf 			totsize = NBPSCTR;
5321709Smlf 		}
5331709Smlf 	} else {
5341709Smlf 		/* Round down sector size to multiple of 512B */
5351709Smlf 		totsize &= ~(NBPSCTR-1);
5361709Smlf 	}
5371709Smlf 	dadkp->dad_phyg.g_secsiz = totsize;
5381709Smlf 
5391709Smlf 	/* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */
5401709Smlf 	totsize >>= SCTRSHFT;
5415295Srandyf 	for (i = 0; totsize != 1; i++, totsize >>= 1)
5425295Srandyf 		;
5431709Smlf 	dadkp->dad_blkshf = i;
5441709Smlf 	dadkp->dad_secshf = i + SCTRSHFT;
5451709Smlf }
5461709Smlf 
5471709Smlf 
5482799Smarx static void
5492799Smarx dadk_create_errstats(struct dadk *dadkp, int instance)
5502799Smarx {
5512799Smarx 	dadk_errstats_t *dep;
5522799Smarx 	char kstatname[KSTAT_STRLEN];
5532799Smarx 	dadk_ioc_string_t dadk_ioc_string;
5542799Smarx 
5552799Smarx 	if (dadkp->dad_errstats)
5562799Smarx 		return;
5572799Smarx 
5582799Smarx 	(void) sprintf(kstatname, "cmdk%d,error", instance);
5592799Smarx 	dadkp->dad_errstats = kstat_create("cmdkerror", instance,
5602799Smarx 	    kstatname, "device_error", KSTAT_TYPE_NAMED,
5612799Smarx 	    sizeof (dadk_errstats_t) / sizeof (kstat_named_t),
5622799Smarx 	    KSTAT_FLAG_PERSISTENT);
5632799Smarx 
5642799Smarx 	if (!dadkp->dad_errstats)
5652799Smarx 		return;
5662799Smarx 
5672799Smarx 	dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data;
5682799Smarx 
5692799Smarx 	kstat_named_init(&dep->dadk_softerrs,
5702799Smarx 	    "Soft Errors", KSTAT_DATA_UINT32);
5712799Smarx 	kstat_named_init(&dep->dadk_harderrs,
5722799Smarx 	    "Hard Errors", KSTAT_DATA_UINT32);
5732799Smarx 	kstat_named_init(&dep->dadk_transerrs,
5742799Smarx 	    "Transport Errors", KSTAT_DATA_UINT32);
5752799Smarx 	kstat_named_init(&dep->dadk_model,
5762799Smarx 	    "Model", KSTAT_DATA_CHAR);
5772799Smarx 	kstat_named_init(&dep->dadk_revision,
5782799Smarx 	    "Revision", KSTAT_DATA_CHAR);
5792799Smarx 	kstat_named_init(&dep->dadk_serial,
5802799Smarx 	    "Serial No", KSTAT_DATA_CHAR);
5812799Smarx 	kstat_named_init(&dep->dadk_capacity,
5822799Smarx 	    "Size", KSTAT_DATA_ULONGLONG);
5832799Smarx 	kstat_named_init(&dep->dadk_rq_media_err,
5842799Smarx 	    "Media Error", KSTAT_DATA_UINT32);
5852799Smarx 	kstat_named_init(&dep->dadk_rq_ntrdy_err,
5862799Smarx 	    "Device Not Ready", KSTAT_DATA_UINT32);
5872799Smarx 	kstat_named_init(&dep->dadk_rq_nodev_err,
5882799Smarx 	    "No Device", KSTAT_DATA_UINT32);
5892799Smarx 	kstat_named_init(&dep->dadk_rq_recov_err,
5902799Smarx 	    "Recoverable", KSTAT_DATA_UINT32);
5912799Smarx 	kstat_named_init(&dep->dadk_rq_illrq_err,
5922799Smarx 	    "Illegal Request", KSTAT_DATA_UINT32);
5932799Smarx 
5942799Smarx 	dadkp->dad_errstats->ks_private = dep;
5952799Smarx 	dadkp->dad_errstats->ks_update = nulldev;
5962799Smarx 	kstat_install(dadkp->dad_errstats);
5972799Smarx 
5982799Smarx 	/* get model */
5992799Smarx 	dep->dadk_model.value.c[0] = 0;
6002799Smarx 	dadk_ioc_string.is_buf = &dep->dadk_model.value.c[0];
6013399Smarx 	dadk_ioc_string.is_size = sizeof (dep->dadk_model.value.c);
6025295Srandyf 	(void) dadk_ctl_ioctl(dadkp, DIOCTL_GETMODEL,
6032799Smarx 	    (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE);
6042799Smarx 
6052799Smarx 	/* get serial */
6062799Smarx 	dep->dadk_serial.value.c[0] = 0;
6072799Smarx 	dadk_ioc_string.is_buf = &dep->dadk_serial.value.c[0];
6083399Smarx 	dadk_ioc_string.is_size = sizeof (dep->dadk_serial.value.c);
6095295Srandyf 	(void) dadk_ctl_ioctl(dadkp, DIOCTL_GETSERIAL,
6102799Smarx 	    (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE);
6112799Smarx 
6122799Smarx 	/* Get revision */
6132799Smarx 	dep->dadk_revision.value.c[0] = 0;
6142799Smarx 
6152799Smarx 	/* Get capacity */
6162799Smarx 
6172799Smarx 	dep->dadk_capacity.value.ui64 =
6182799Smarx 	    (uint64_t)dadkp->dad_logg.g_cap *
6192799Smarx 	    (uint64_t)dadkp->dad_logg.g_secsiz;
6202799Smarx }
6212799Smarx 
6222799Smarx 
6231709Smlf int
6241709Smlf dadk_close(opaque_t objp)
6251709Smlf {
6261709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
6271709Smlf 
6281709Smlf 	if (dadkp->dad_rmb) {
6291709Smlf 		(void) dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 0,
6301709Smlf 		    DADK_SILENT);
6311709Smlf 		(void) dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT);
6321709Smlf 	}
6331709Smlf 	FLC_STOP_KSTAT(dadkp->dad_flcobjp);
6342799Smarx 
6352799Smarx 	dadk_destroy_errstats(dadkp);
6362799Smarx 
6371709Smlf 	return (DDI_SUCCESS);
6381709Smlf }
6391709Smlf 
6402799Smarx static void
6412799Smarx dadk_destroy_errstats(struct dadk *dadkp)
6422799Smarx {
6432799Smarx 	if (!dadkp->dad_errstats)
6442799Smarx 		return;
6452799Smarx 
6462799Smarx 	kstat_delete(dadkp->dad_errstats);
6472799Smarx 	dadkp->dad_errstats = NULL;
6482799Smarx }
6492799Smarx 
6502799Smarx 
6511709Smlf int
6521709Smlf dadk_strategy(opaque_t objp, struct buf *bp)
6531709Smlf {
6541709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
6551709Smlf 
6561709Smlf 	if (dadkp->dad_rdonly && !(bp->b_flags & B_READ)) {
6571709Smlf 		bioerror(bp, EROFS);
6581709Smlf 		return (DDI_FAILURE);
6591709Smlf 	}
6601709Smlf 
6611709Smlf 	if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) {
6621709Smlf 		bioerror(bp, ENXIO);
6631709Smlf 		return (DDI_FAILURE);
6641709Smlf 	}
6651709Smlf 
6661709Smlf 	SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf)));
6675295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
6685295Srandyf 	dadkp->dad_cmd_count++;
6695295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
6701709Smlf 	FLC_ENQUE(dadkp->dad_flcobjp, bp);
6711709Smlf 
6721709Smlf 	return (DDI_SUCCESS);
6731709Smlf }
6741709Smlf 
6751709Smlf int
6761709Smlf dadk_dump(opaque_t objp, struct buf *bp)
6771709Smlf {
6781709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
6791709Smlf 	struct cmpkt *pktp;
6801709Smlf 
6811709Smlf 	if (dadkp->dad_rdonly) {
6821709Smlf 		bioerror(bp, EROFS);
6831709Smlf 		return (DDI_FAILURE);
6841709Smlf 	}
6851709Smlf 
6861709Smlf 	if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) {
6871709Smlf 		bioerror(bp, ENXIO);
6881709Smlf 		return (DDI_FAILURE);
6891709Smlf 	}
6901709Smlf 
6911709Smlf 	SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf)));
6921709Smlf 
6931709Smlf 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_polldone, NULL, NULL);
6941709Smlf 	if (!pktp) {
6951709Smlf 		cmn_err(CE_WARN, "no resources for dumping");
6961709Smlf 		bioerror(bp, EIO);
6971709Smlf 		return (DDI_FAILURE);
6981709Smlf 	}
6991709Smlf 	pktp->cp_flags |= CPF_NOINTR;
7001709Smlf 
7011709Smlf 	(void) dadk_ioprep(dadkp, pktp);
7021709Smlf 	dadk_transport(dadkp, bp);
7031709Smlf 	pktp->cp_byteleft -= pktp->cp_bytexfer;
7041709Smlf 
7051709Smlf 	while (geterror(bp) == 0 && pktp->cp_byteleft != 0) {
7061709Smlf 		(void) dadk_iosetup(dadkp, pktp);
7071709Smlf 		dadk_transport(dadkp, bp);
7081709Smlf 		pktp->cp_byteleft -= pktp->cp_bytexfer;
7091709Smlf 	}
7101709Smlf 
7111709Smlf 	if (pktp->cp_private)
7121709Smlf 		BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private);
7131709Smlf 	gda_free(dadkp->dad_ctlobjp, pktp, NULL);
7141709Smlf 	return (DDI_SUCCESS);
7151709Smlf }
7161709Smlf 
7171709Smlf /* ARGSUSED  */
7181709Smlf int
7191709Smlf dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag,
7201709Smlf 	cred_t *cred_p, int *rval_p)
7211709Smlf {
7221709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
7231709Smlf 
7241709Smlf 	switch (cmd) {
7251709Smlf 	case DKIOCGETDEF:
7265295Srandyf 		{
7271709Smlf 		struct buf	*bp;
7281709Smlf 		int		err, head;
7291709Smlf 		unsigned char	*secbuf;
7301709Smlf 		STRUCT_DECL(defect_header, adh);
7311709Smlf 
7321709Smlf 		STRUCT_INIT(adh, flag & FMODELS);
7331709Smlf 
7341709Smlf 		/*
7351709Smlf 		 * copyin header ....
7361709Smlf 		 * yields head number and buffer address
7371709Smlf 		 */
7381709Smlf 		if (ddi_copyin((caddr_t)arg, STRUCT_BUF(adh), STRUCT_SIZE(adh),
7391709Smlf 		    flag))
7401709Smlf 			return (EFAULT);
7411709Smlf 		head = STRUCT_FGET(adh, head);
7421709Smlf 		if (head < 0 || head >= dadkp->dad_phyg.g_head)
7431709Smlf 			return (ENXIO);
7441709Smlf 		secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
7451709Smlf 		if (!secbuf)
7461709Smlf 			return (ENOMEM);
7471709Smlf 		bp = getrbuf(KM_SLEEP);
7481709Smlf 		if (!bp) {
7491709Smlf 			kmem_free(secbuf, NBPSCTR);
7501709Smlf 			return (ENOMEM);
7511709Smlf 		}
7521709Smlf 
7531709Smlf 		bp->b_edev = dev;
7541709Smlf 		bp->b_dev  = cmpdev(dev);
7551709Smlf 		bp->b_flags = B_BUSY;
7561709Smlf 		bp->b_resid = 0;
7571709Smlf 		bp->b_bcount = NBPSCTR;
7581709Smlf 		bp->b_un.b_addr = (caddr_t)secbuf;
7591709Smlf 		bp->b_blkno = head; /* I had to put it somwhere! */
7601709Smlf 		bp->b_forw = (struct buf *)dadkp;
7611709Smlf 		bp->b_back = (struct buf *)DCMD_GETDEF;
7621709Smlf 
7635295Srandyf 		mutex_enter(&dadkp->dad_cmd_mutex);
7645295Srandyf 		dadkp->dad_cmd_count++;
7655295Srandyf 		mutex_exit(&dadkp->dad_cmd_mutex);
7661709Smlf 		FLC_ENQUE(dadkp->dad_flcobjp, bp);
7671709Smlf 		err = biowait(bp);
7681709Smlf 		if (!err) {
7691709Smlf 			if (ddi_copyout((caddr_t)secbuf,
7701709Smlf 			    STRUCT_FGETP(adh, buffer), NBPSCTR, flag))
7711709Smlf 				err = ENXIO;
7721709Smlf 		}
7731709Smlf 		kmem_free(secbuf, NBPSCTR);
7741709Smlf 		freerbuf(bp);
7751709Smlf 		return (err);
7765295Srandyf 		}
7771709Smlf 	case DIOCTL_RWCMD:
7785295Srandyf 		{
7791709Smlf 		struct dadkio_rwcmd *rwcmdp;
7801709Smlf 		int status, rw;
7811709Smlf 
7821709Smlf 		/*
7831709Smlf 		 * copied in by cmdk and, if necessary, converted to the
7841709Smlf 		 * correct datamodel
7851709Smlf 		 */
7861709Smlf 		rwcmdp = (struct dadkio_rwcmd *)(intptr_t)arg;
7871709Smlf 
7881709Smlf 		/*
7891709Smlf 		 * handle the complex cases here; we pass these
7901709Smlf 		 * through to the driver, which will queue them and
7911709Smlf 		 * handle the requests asynchronously.  The simpler
7921709Smlf 		 * cases ,which can return immediately, fail here, and
7931709Smlf 		 * the request reverts to the dadk_ioctl routine, while
7941709Smlf 		 *  will reroute them directly to the ata driver.
7951709Smlf 		 */
7961709Smlf 		switch (rwcmdp->cmd) {
7971709Smlf 			case DADKIO_RWCMD_READ :
7981709Smlf 				/*FALLTHROUGH*/
7991709Smlf 			case DADKIO_RWCMD_WRITE:
8001709Smlf 				rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ?
8011709Smlf 				    B_WRITE : B_READ);
8021709Smlf 				status = dadk_dk_buf_setup(dadkp,
8031709Smlf 				    (opaque_t)rwcmdp, dev, ((flag &FKIOCTL) ?
8041709Smlf 				    UIO_SYSSPACE : UIO_USERSPACE), rw);
8051709Smlf 				return (status);
8061709Smlf 			default:
8071709Smlf 				return (EINVAL);
8085295Srandyf 			}
8091709Smlf 		}
8103652Syt160523 	case DKIOC_UPDATEFW:
8113652Syt160523 
8123652Syt160523 		/*
8133652Syt160523 		 * Require PRIV_ALL privilege to invoke DKIOC_UPDATEFW
8143652Syt160523 		 * to protect the firmware update from malicious use
8153652Syt160523 		 */
8163652Syt160523 		if (PRIV_POLICY(cred_p, PRIV_ALL, B_FALSE, EPERM, NULL) != 0)
8173652Syt160523 			return (EPERM);
8183652Syt160523 		else
8195295Srandyf 			return (dadk_ctl_ioctl(dadkp, cmd, arg, flag));
8203652Syt160523 
8211709Smlf 	case DKIOCFLUSHWRITECACHE:
8221709Smlf 		{
8231709Smlf 			struct buf *bp;
8241709Smlf 			int err = 0;
8251709Smlf 			struct dk_callback *dkc = (struct dk_callback *)arg;
8261709Smlf 			struct cmpkt *pktp;
8271709Smlf 			int is_sync = 1;
8281709Smlf 
8291709Smlf 			mutex_enter(&dadkp->dad_mutex);
8301709Smlf 			if (dadkp->dad_noflush || !  dadkp->dad_wce) {
8311709Smlf 				err = dadkp->dad_noflush ? ENOTSUP : 0;
8321709Smlf 				mutex_exit(&dadkp->dad_mutex);
8331709Smlf 				/*
8341709Smlf 				 * If a callback was requested: a
8351709Smlf 				 * callback will always be done if the
8361709Smlf 				 * caller saw the DKIOCFLUSHWRITECACHE
8371709Smlf 				 * ioctl return 0, and never done if the
8381709Smlf 				 * caller saw the ioctl return an error.
8391709Smlf 				 */
8401709Smlf 				if ((flag & FKIOCTL) && dkc != NULL &&
8411709Smlf 				    dkc->dkc_callback != NULL) {
8421709Smlf 					(*dkc->dkc_callback)(dkc->dkc_cookie,
8431709Smlf 					    err);
8441709Smlf 					/*
8451709Smlf 					 * Did callback and reported error.
8461709Smlf 					 * Since we did a callback, ioctl
8471709Smlf 					 * should return 0.
8481709Smlf 					 */
8491709Smlf 					err = 0;
8501709Smlf 				}
8511709Smlf 				return (err);
8521709Smlf 			}
8531709Smlf 			mutex_exit(&dadkp->dad_mutex);
8541709Smlf 
8551709Smlf 			bp = getrbuf(KM_SLEEP);
8561709Smlf 
8571709Smlf 			bp->b_edev = dev;
8581709Smlf 			bp->b_dev  = cmpdev(dev);
8591709Smlf 			bp->b_flags = B_BUSY;
8601709Smlf 			bp->b_resid = 0;
8611709Smlf 			bp->b_bcount = 0;
8621709Smlf 			SET_BP_SEC(bp, 0);
8631709Smlf 
8641709Smlf 			if ((flag & FKIOCTL) && dkc != NULL &&
8651709Smlf 			    dkc->dkc_callback != NULL) {
8661709Smlf 				struct dk_callback *dkc2 =
8671709Smlf 				    (struct dk_callback *)kmem_zalloc(
8681709Smlf 				    sizeof (struct dk_callback), KM_SLEEP);
8691709Smlf 
8701709Smlf 				bcopy(dkc, dkc2, sizeof (*dkc2));
8711709Smlf 				/*
8721709Smlf 				 * Borrow b_list to carry private data
8731709Smlf 				 * to the b_iodone func.
8741709Smlf 				 */
8751709Smlf 				bp->b_list = (struct buf *)dkc2;
8761709Smlf 				bp->b_iodone = dadk_flushdone;
8771709Smlf 				is_sync = 0;
8781709Smlf 			}
8791709Smlf 
8801709Smlf 			/*
8811709Smlf 			 * Setup command pkt
8821709Smlf 			 * dadk_pktprep() can't fail since DDI_DMA_SLEEP set
8831709Smlf 			 */
8841709Smlf 			pktp = dadk_pktprep(dadkp, NULL, bp,
8851709Smlf 			    dadk_iodone, DDI_DMA_SLEEP, NULL);
8861709Smlf 
8871709Smlf 			pktp->cp_time = DADK_FLUSH_CACHE_TIME;
8881709Smlf 
8891709Smlf 			*((char *)(pktp->cp_cdbp)) = DCMD_FLUSH_CACHE;
8901709Smlf 			pktp->cp_byteleft = 0;
8911709Smlf 			pktp->cp_private = NULL;
8921709Smlf 			pktp->cp_secleft = 0;
8931709Smlf 			pktp->cp_srtsec = -1;
8941709Smlf 			pktp->cp_bytexfer = 0;
8951709Smlf 
8961709Smlf 			CTL_IOSETUP(dadkp->dad_ctlobjp, pktp);
8971709Smlf 
8985295Srandyf 			mutex_enter(&dadkp->dad_cmd_mutex);
8995295Srandyf 			dadkp->dad_cmd_count++;
9005295Srandyf 			mutex_exit(&dadkp->dad_cmd_mutex);
9011709Smlf 			FLC_ENQUE(dadkp->dad_flcobjp, bp);
9021709Smlf 
9031709Smlf 			if (is_sync) {
9041709Smlf 				err = biowait(bp);
9051709Smlf 				freerbuf(bp);
9061709Smlf 			}
9071709Smlf 			return (err);
9081709Smlf 		}
9091709Smlf 	default:
9101709Smlf 		if (!dadkp->dad_rmb)
9115295Srandyf 			return (dadk_ctl_ioctl(dadkp, cmd, arg, flag));
9121709Smlf 	}
9131709Smlf 
9141709Smlf 	switch (cmd) {
9151709Smlf 	case CDROMSTOP:
9161709Smlf 		return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0,
9175295Srandyf 		    0, DADK_SILENT));
9181709Smlf 	case CDROMSTART:
9191709Smlf 		return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0,
9205295Srandyf 		    0, DADK_SILENT));
9211709Smlf 	case DKIOCLOCK:
9221709Smlf 		return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT));
9231709Smlf 	case DKIOCUNLOCK:
9241709Smlf 		return (dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT));
9251709Smlf 	case DKIOCEJECT:
9261709Smlf 	case CDROMEJECT:
9271709Smlf 		{
9281709Smlf 			int ret;
9291709Smlf 
9301709Smlf 			if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0,
9315295Srandyf 			    DADK_SILENT)) {
9321709Smlf 				return (ret);
9331709Smlf 			}
9341709Smlf 			if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0,
9355295Srandyf 			    DADK_SILENT)) {
9361709Smlf 				return (ret);
9371709Smlf 			}
9381709Smlf 			mutex_enter(&dadkp->dad_mutex);
9391709Smlf 			dadkp->dad_iostate = DKIO_EJECTED;
9401709Smlf 			cv_broadcast(&dadkp->dad_state_cv);
9411709Smlf 			mutex_exit(&dadkp->dad_mutex);
9421709Smlf 
9431709Smlf 			return (0);
9441709Smlf 
9451709Smlf 		}
9461709Smlf 	default:
9471709Smlf 		return (ENOTTY);
9481709Smlf 	/*
9491709Smlf 	 * cdrom audio commands
9501709Smlf 	 */
9511709Smlf 	case CDROMPAUSE:
9521709Smlf 		cmd = DCMD_PAUSE;
9531709Smlf 		break;
9541709Smlf 	case CDROMRESUME:
9551709Smlf 		cmd = DCMD_RESUME;
9561709Smlf 		break;
9571709Smlf 	case CDROMPLAYMSF:
9581709Smlf 		cmd = DCMD_PLAYMSF;
9591709Smlf 		break;
9601709Smlf 	case CDROMPLAYTRKIND:
9611709Smlf 		cmd = DCMD_PLAYTRKIND;
9621709Smlf 		break;
9631709Smlf 	case CDROMREADTOCHDR:
9641709Smlf 		cmd = DCMD_READTOCHDR;
9651709Smlf 		break;
9661709Smlf 	case CDROMREADTOCENTRY:
9671709Smlf 		cmd = DCMD_READTOCENT;
9681709Smlf 		break;
9691709Smlf 	case CDROMVOLCTRL:
9701709Smlf 		cmd = DCMD_VOLCTRL;
9711709Smlf 		break;
9721709Smlf 	case CDROMSUBCHNL:
9731709Smlf 		cmd = DCMD_SUBCHNL;
9741709Smlf 		break;
9751709Smlf 	case CDROMREADMODE2:
9761709Smlf 		cmd = DCMD_READMODE2;
9771709Smlf 		break;
9781709Smlf 	case CDROMREADMODE1:
9791709Smlf 		cmd = DCMD_READMODE1;
9801709Smlf 		break;
9811709Smlf 	case CDROMREADOFFSET:
9821709Smlf 		cmd = DCMD_READOFFSET;
9831709Smlf 		break;
9841709Smlf 	}
9851709Smlf 	return (dadk_rmb_ioctl(dadkp, cmd, arg, flag, 0));
9861709Smlf }
9871709Smlf 
9881709Smlf int
9891709Smlf dadk_flushdone(struct buf *bp)
9901709Smlf {
9911709Smlf 	struct dk_callback *dkc = (struct dk_callback *)bp->b_list;
9921709Smlf 
9931709Smlf 	ASSERT(dkc != NULL && dkc->dkc_callback != NULL);
9941709Smlf 
9951709Smlf 	(*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp));
9961709Smlf 
9971709Smlf 	kmem_free(dkc, sizeof (*dkc));
9981709Smlf 	freerbuf(bp);
9991709Smlf 	return (0);
10001709Smlf }
10011709Smlf 
10021709Smlf int
10031709Smlf dadk_getphygeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
10041709Smlf {
10051709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
10061709Smlf 
10071709Smlf 	bcopy((caddr_t)&dadkp->dad_phyg, (caddr_t)dkgeom_p,
10081709Smlf 	    sizeof (struct tgdk_geom));
10091709Smlf 	return (DDI_SUCCESS);
10101709Smlf }
10111709Smlf 
10121709Smlf int
10131709Smlf dadk_getgeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
10141709Smlf {
10151709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
10161709Smlf 	bcopy((caddr_t)&dadkp->dad_logg, (caddr_t)dkgeom_p,
10171709Smlf 	    sizeof (struct tgdk_geom));
10181709Smlf 	return (DDI_SUCCESS);
10191709Smlf }
10201709Smlf 
10211709Smlf int
10221709Smlf dadk_setgeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
10231709Smlf {
10241709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
10251709Smlf 
10261709Smlf 	dadkp->dad_logg.g_cyl = dkgeom_p->g_cyl;
10271709Smlf 	dadkp->dad_logg.g_head = dkgeom_p->g_head;
10281709Smlf 	dadkp->dad_logg.g_sec = dkgeom_p->g_sec;
10291709Smlf 	dadkp->dad_logg.g_cap = dkgeom_p->g_cap;
10301709Smlf 	return (DDI_SUCCESS);
10311709Smlf }
10321709Smlf 
10331709Smlf 
10341709Smlf tgdk_iob_handle
10351709Smlf dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg)
10361709Smlf {
10371709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
10381709Smlf 	struct buf *bp;
10391709Smlf 	struct tgdk_iob *iobp;
10401709Smlf 	size_t rlen;
10411709Smlf 
10421709Smlf 	iobp = kmem_zalloc(sizeof (*iobp), kmsflg);
10431709Smlf 	if (iobp == NULL)
10441709Smlf 		return (NULL);
10451709Smlf 	if ((bp = getrbuf(kmsflg)) == NULL) {
10461709Smlf 		kmem_free(iobp, sizeof (*iobp));
10471709Smlf 		return (NULL);
10481709Smlf 	}
10491709Smlf 
10501709Smlf 	iobp->b_psec  = LBLK2SEC(blkno, dadkp->dad_blkshf);
10511709Smlf 	iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT;
10521709Smlf 	iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1)
10535295Srandyf 	    >> dadkp->dad_secshf) << dadkp->dad_secshf;
10541709Smlf 
10551709Smlf 	bp->b_un.b_addr = 0;
10561709Smlf 	/*
10571709Smlf 	 * use i_ddi_mem_alloc() for now until we have an interface to allocate
10581709Smlf 	 * memory for DMA which doesn't require a DMA handle. ddi_iopb_alloc()
10591709Smlf 	 * is obsolete and we want more flexibility in controlling the DMA
10601709Smlf 	 * address constraints..
10611709Smlf 	 */
10621709Smlf 	if (i_ddi_mem_alloc((dadkp->dad_sd)->sd_dev, &dadk_alloc_attr,
10631709Smlf 	    (size_t)iobp->b_pbytecnt, ((kmsflg == KM_SLEEP) ? 1 : 0), 0, NULL,
10641709Smlf 	    &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
10651709Smlf 		freerbuf(bp);
10661709Smlf 		kmem_free(iobp, sizeof (*iobp));
10671709Smlf 		return (NULL);
10681709Smlf 	}
10691709Smlf 	iobp->b_flag |= IOB_BPALLOC | IOB_BPBUFALLOC;
10701709Smlf 	iobp->b_bp = bp;
10711709Smlf 	iobp->b_lblk = blkno;
10721709Smlf 	iobp->b_xfer = xfer;
10731709Smlf 	iobp->b_lblk = blkno;
10741709Smlf 	iobp->b_xfer = xfer;
10751709Smlf 	return (iobp);
10761709Smlf }
10771709Smlf 
10781709Smlf /* ARGSUSED */
10791709Smlf int
10801709Smlf dadk_iob_free(opaque_t objp, struct tgdk_iob *iobp)
10811709Smlf {
10821709Smlf 	struct buf *bp;
10831709Smlf 
10841709Smlf 	if (iobp) {
10851709Smlf 		if (iobp->b_bp && (iobp->b_flag & IOB_BPALLOC)) {
10861709Smlf 			bp = iobp->b_bp;
10871709Smlf 			if (bp->b_un.b_addr && (iobp->b_flag & IOB_BPBUFALLOC))
10881900Seota 				i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
10891709Smlf 			freerbuf(bp);
10901709Smlf 		}
10911709Smlf 		kmem_free(iobp, sizeof (*iobp));
10921709Smlf 	}
10931709Smlf 	return (DDI_SUCCESS);
10941709Smlf }
10951709Smlf 
10961709Smlf /* ARGSUSED */
10971709Smlf caddr_t
10981709Smlf dadk_iob_htoc(opaque_t objp, struct tgdk_iob *iobp)
10991709Smlf {
11001709Smlf 	return (iobp->b_bp->b_un.b_addr+iobp->b_pbyteoff);
11011709Smlf }
11021709Smlf 
11031709Smlf 
11041709Smlf caddr_t
11051709Smlf dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw)
11061709Smlf {
11071709Smlf 	struct dadk	*dadkp = (struct dadk *)objp;
11081709Smlf 	struct buf	*bp;
11091709Smlf 	int		err;
11101709Smlf 
11111709Smlf 	bp = iobp->b_bp;
11121709Smlf 	if (dadkp->dad_rdonly && !(rw & B_READ)) {
11131709Smlf 		bioerror(bp, EROFS);
11141709Smlf 		return (NULL);
11151709Smlf 	}
11161709Smlf 
11171709Smlf 	bp->b_flags |= (B_BUSY | rw);
11181709Smlf 	bp->b_bcount = iobp->b_pbytecnt;
11191709Smlf 	SET_BP_SEC(bp, iobp->b_psec);
11201709Smlf 	bp->av_back = (struct buf *)0;
11211709Smlf 	bp->b_resid = 0;
11221709Smlf 
11231709Smlf 	/* call flow control */
11245295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
11255295Srandyf 	dadkp->dad_cmd_count++;
11265295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
11271709Smlf 	FLC_ENQUE(dadkp->dad_flcobjp, bp);
11281709Smlf 	err = biowait(bp);
11291709Smlf 
11301709Smlf 	bp->b_bcount = iobp->b_xfer;
11311709Smlf 	bp->b_flags &= ~(B_DONE|B_BUSY);
11321709Smlf 
11331709Smlf 	if (err)
11341709Smlf 		return (NULL);
11351709Smlf 
11361709Smlf 	return (bp->b_un.b_addr+iobp->b_pbyteoff);
11371709Smlf }
11381709Smlf 
11391709Smlf static void
11401709Smlf dadk_transport(opaque_t com_data, struct buf *bp)
11411709Smlf {
11421709Smlf 	struct dadk *dadkp = (struct dadk *)com_data;
11431709Smlf 
11441709Smlf 	if (CTL_TRANSPORT(dadkp->dad_ctlobjp, GDA_BP_PKT(bp)) ==
11451709Smlf 	    CTL_SEND_SUCCESS)
11461709Smlf 		return;
11471709Smlf 	dadk_restart((void*)GDA_BP_PKT(bp));
11481709Smlf }
11491709Smlf 
11501709Smlf static int
11511709Smlf dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg)
11521709Smlf {
11531709Smlf 	struct cmpkt *pktp;
11541709Smlf 	struct dadk *dadkp = (struct dadk *)com_data;
11551709Smlf 
11561709Smlf 	if (GDA_BP_PKT(bp))
11571709Smlf 		return (DDI_SUCCESS);
11581709Smlf 
11591709Smlf 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, func, arg);
11601709Smlf 	if (!pktp)
11611709Smlf 		return (DDI_FAILURE);
11621709Smlf 
11631709Smlf 	return (dadk_ioprep(dadkp, pktp));
11641709Smlf }
11651709Smlf 
11661709Smlf /*
11671709Smlf  * Read, Write preparation
11681709Smlf  */
11691709Smlf static int
11701709Smlf dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp)
11711709Smlf {
11721709Smlf 	struct buf *bp;
11731709Smlf 
11741709Smlf 	bp = pktp->cp_bp;
11751709Smlf 	if (bp->b_forw == (struct buf *)dadkp)
11761709Smlf 		*((char *)(pktp->cp_cdbp)) = (char)(intptr_t)bp->b_back;
11771709Smlf 
11781709Smlf 	else if (bp->b_flags & B_READ)
11791709Smlf 		*((char *)(pktp->cp_cdbp)) = DCMD_READ;
11801709Smlf 	else
11811709Smlf 		*((char *)(pktp->cp_cdbp)) = DCMD_WRITE;
11821709Smlf 	pktp->cp_byteleft = bp->b_bcount;
11831709Smlf 
11841709Smlf 	/* setup the bad block list handle */
11851709Smlf 	pktp->cp_private = BBH_GETHANDLE(dadkp->dad_bbhobjp, bp);
11861709Smlf 	return (dadk_iosetup(dadkp, pktp));
11871709Smlf }
11881709Smlf 
11891709Smlf static int
11901709Smlf dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp)
11911709Smlf {
11921709Smlf 	struct buf	*bp;
11931709Smlf 	bbh_cookie_t	bbhckp;
11941709Smlf 	int		seccnt;
11951709Smlf 
11961709Smlf 	seccnt = pktp->cp_bytexfer >> dadkp->dad_secshf;
11971709Smlf 	pktp->cp_secleft -= seccnt;
11981709Smlf 
11991709Smlf 	if (pktp->cp_secleft) {
12001709Smlf 		pktp->cp_srtsec += seccnt;
12011709Smlf 	} else {
12021709Smlf 		/* get the first cookie from the bad block list */
12031709Smlf 		if (!pktp->cp_private) {
12041709Smlf 			bp = pktp->cp_bp;
12051709Smlf 			pktp->cp_srtsec  = GET_BP_SEC(bp);
12061709Smlf 			pktp->cp_secleft = (bp->b_bcount >> dadkp->dad_secshf);
12071709Smlf 		} else {
12081709Smlf 			bbhckp = BBH_HTOC(dadkp->dad_bbhobjp,
12091709Smlf 			    pktp->cp_private);
12101709Smlf 			pktp->cp_srtsec = BBH_GETCK_SECTOR(dadkp->dad_bbhobjp,
12111709Smlf 			    bbhckp);
12121709Smlf 			pktp->cp_secleft = BBH_GETCK_SECLEN(dadkp->dad_bbhobjp,
12131709Smlf 			    bbhckp);
12141709Smlf 		}
12151709Smlf 	}
12161709Smlf 
12171709Smlf 	pktp->cp_bytexfer = pktp->cp_secleft << dadkp->dad_secshf;
12181709Smlf 
12191709Smlf 	if (CTL_IOSETUP(dadkp->dad_ctlobjp, pktp)) {
12201709Smlf 		return (DDI_SUCCESS);
12211709Smlf 	} else {
12221709Smlf 		return (DDI_FAILURE);
12231709Smlf 	}
12241709Smlf 
12251709Smlf 
12261709Smlf 
12271709Smlf 
12281709Smlf }
12291709Smlf 
12301709Smlf static struct cmpkt *
12311709Smlf dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, struct buf *bp,
12321709Smlf     void (*cb_func)(struct buf *), int (*func)(caddr_t), caddr_t arg)
12331709Smlf {
12341709Smlf 	struct cmpkt *pktp;
12351709Smlf 
12361709Smlf 	pktp = gda_pktprep(dadkp->dad_ctlobjp, in_pktp, (opaque_t)bp, func,
12371709Smlf 	    arg);
12381709Smlf 
12391709Smlf 	if (pktp) {
12401709Smlf 		pktp->cp_callback = dadk_pktcb;
12411709Smlf 		pktp->cp_time = DADK_IO_TIME;
12421709Smlf 		pktp->cp_flags = 0;
12431709Smlf 		pktp->cp_iodone = cb_func;
12441709Smlf 		pktp->cp_dev_private = (opaque_t)dadkp;
12451709Smlf 
12461709Smlf 	}
12471709Smlf 
12481709Smlf 	return (pktp);
12491709Smlf }
12501709Smlf 
12511709Smlf 
12521709Smlf static void
12531709Smlf dadk_restart(void *vpktp)
12541709Smlf {
12551709Smlf 	struct cmpkt *pktp = (struct cmpkt *)vpktp;
12561709Smlf 
12571709Smlf 	if (dadk_ioretry(pktp, QUE_COMMAND) == JUST_RETURN)
12581709Smlf 		return;
12591709Smlf 	pktp->cp_iodone(pktp->cp_bp);
12601709Smlf }
12611709Smlf 
12621709Smlf static int
12631709Smlf dadk_ioretry(struct cmpkt *pktp, int action)
12641709Smlf {
12651709Smlf 	struct buf *bp;
12661709Smlf 	struct dadk *dadkp = PKT2DADK(pktp);
12671709Smlf 
12681709Smlf 	switch (action) {
12691709Smlf 	case QUE_COMMAND:
12701709Smlf 		if (pktp->cp_retry++ < DADK_RETRY_COUNT) {
12711709Smlf 			CTL_IOSETUP(dadkp->dad_ctlobjp, pktp);
12721709Smlf 			if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) ==
12735295Srandyf 			    CTL_SEND_SUCCESS) {
12741709Smlf 				return (JUST_RETURN);
12751709Smlf 			}
12761709Smlf 			gda_log(dadkp->dad_sd->sd_dev, dadk_name,
12775295Srandyf 			    CE_WARN, "transport of command fails\n");
12781709Smlf 		} else
12791709Smlf 			gda_log(dadkp->dad_sd->sd_dev,
12805295Srandyf 			    dadk_name, CE_WARN,
12815295Srandyf 			    "exceeds maximum number of retries\n");
12821709Smlf 		bioerror(pktp->cp_bp, ENXIO);
12831709Smlf 		/*FALLTHROUGH*/
12841709Smlf 	case COMMAND_DONE_ERROR:
12851709Smlf 		bp = pktp->cp_bp;
12861709Smlf 		bp->b_resid += pktp->cp_byteleft - pktp->cp_bytexfer +
12871709Smlf 		    pktp->cp_resid;
12881709Smlf 		if (geterror(bp) == 0) {
12891709Smlf 			if ((*((char *)(pktp->cp_cdbp)) == DCMD_FLUSH_CACHE) &&
12901709Smlf 			    (pktp->cp_dev_private == (opaque_t)dadkp) &&
12911709Smlf 			    ((int)(*(char *)pktp->cp_scbp) == DERR_ABORT)) {
12921709Smlf 				/*
12931709Smlf 				 * Flag "unimplemented" responses for
12941709Smlf 				 * DCMD_FLUSH_CACHE as ENOTSUP
12951709Smlf 				 */
12961709Smlf 				bioerror(bp, ENOTSUP);
12971709Smlf 				mutex_enter(&dadkp->dad_mutex);
12981709Smlf 				dadkp->dad_noflush = 1;
12991709Smlf 				mutex_exit(&dadkp->dad_mutex);
13001709Smlf 			} else {
13011709Smlf 				bioerror(bp, EIO);
13021709Smlf 			}
13031709Smlf 		}
13041709Smlf 		/*FALLTHROUGH*/
13051709Smlf 	case COMMAND_DONE:
13061709Smlf 	default:
13071709Smlf 		return (COMMAND_DONE);
13081709Smlf 	}
13091709Smlf }
13101709Smlf 
13111709Smlf 
13121709Smlf static void
13131709Smlf dadk_pktcb(struct cmpkt *pktp)
13141709Smlf {
13151709Smlf 	int action;
13161709Smlf 	struct dadkio_rwcmd *rwcmdp;
13171709Smlf 
13181709Smlf 	rwcmdp = (struct dadkio_rwcmd *)pktp->cp_passthru;  /* ioctl packet */
13191709Smlf 
13201709Smlf 	if (pktp->cp_reason == CPS_SUCCESS) {
13211709Smlf 		if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT))
13221709Smlf 			rwcmdp->status.status = DADKIO_STAT_NO_ERROR;
13231709Smlf 		pktp->cp_iodone(pktp->cp_bp);
13241709Smlf 		return;
13251709Smlf 	}
13261709Smlf 
13271709Smlf 	if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) {
13281709Smlf 		if (pktp->cp_reason == CPS_CHKERR)
13291709Smlf 			dadk_recorderr(pktp, rwcmdp);
13301709Smlf 		dadk_iodone(pktp->cp_bp);
13311709Smlf 		return;
13321709Smlf 	}
13331709Smlf 
13341709Smlf 	if (pktp->cp_reason == CPS_CHKERR)
13351709Smlf 		action = dadk_chkerr(pktp);
13361709Smlf 	else
13371709Smlf 		action = COMMAND_DONE_ERROR;
13381709Smlf 
13391709Smlf 	if (action == JUST_RETURN)
13401709Smlf 		return;
13411709Smlf 
13427239Szk194757 	/*
13437239Szk194757 	 * If we are panicking don't retry the command
13447239Szk194757 	 * just fail it so we can go down completing all
13457239Szk194757 	 * of the buffers.
13467239Szk194757 	 */
13477239Szk194757 	if (ddi_in_panic() && action == QUE_COMMAND)
13487239Szk194757 		action = COMMAND_DONE_ERROR;
13497239Szk194757 
13501709Smlf 	if (action != COMMAND_DONE) {
13511709Smlf 		if ((dadk_ioretry(pktp, action)) == JUST_RETURN)
13521709Smlf 			return;
13531709Smlf 	}
13541709Smlf 	pktp->cp_iodone(pktp->cp_bp);
13551709Smlf }
13561709Smlf 
13571709Smlf 
13581709Smlf 
13591709Smlf static struct dadkio_derr dadk_errtab[] = {
13601709Smlf 	{COMMAND_DONE, GDA_INFORMATIONAL},	/*  0 DERR_SUCCESS	*/
13611709Smlf 	{QUE_COMMAND, GDA_FATAL},		/*  1 DERR_AMNF		*/
13621709Smlf 	{QUE_COMMAND, GDA_FATAL},		/*  2 DERR_TKONF	*/
13631709Smlf 	{COMMAND_DONE_ERROR, GDA_INFORMATIONAL}, /* 3 DERR_ABORT	*/
13641709Smlf 	{QUE_COMMAND, GDA_RETRYABLE},		/*  4 DERR_DWF		*/
13651709Smlf 	{QUE_COMMAND, GDA_FATAL},		/*  5 DERR_IDNF		*/
13661709Smlf 	{JUST_RETURN, GDA_INFORMATIONAL},	/*  6 DERR_BUSY		*/
13671709Smlf 	{QUE_COMMAND, GDA_FATAL},		/*  7 DERR_UNC		*/
13681709Smlf 	{QUE_COMMAND, GDA_RETRYABLE},		/*  8 DERR_BBK		*/
13691709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/*  9 DERR_INVCDB	*/
13701709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 10 DERR_HARD		*/
13711709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 11 DERR_ILI		*/
13721709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 12 DERR_EOM		*/
13731709Smlf 	{COMMAND_DONE, GDA_INFORMATIONAL},	/* 13 DERR_MCR		*/
13741709Smlf 	{COMMAND_DONE, GDA_INFORMATIONAL},	/* 14 DERR_RECOVER	*/
13751709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 15 DERR_NOTREADY	*/
13761709Smlf 	{QUE_COMMAND, GDA_RETRYABLE},		/* 16 DERR_MEDIUM	*/
13771709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 17 DERR_HW		*/
13781709Smlf 	{COMMAND_DONE, GDA_FATAL},		/* 18 DERR_ILL		*/
13791709Smlf 	{COMMAND_DONE, GDA_FATAL},		/* 19 DERR_UNIT_ATTN	*/
13801709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 20 DERR_DATA_PROT	*/
13811709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 21 DERR_MISCOMPARE	*/
13821709Smlf 	{QUE_COMMAND, GDA_RETRYABLE},		/* 22 DERR_ICRC		*/
13831709Smlf 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 23 DERR_RESV		*/
13841709Smlf };
13851709Smlf 
13861709Smlf static int
13871709Smlf dadk_chkerr(struct cmpkt *pktp)
13881709Smlf {
1389*7563SPrasad.Singamsetty@Sun.COM 	daddr_t err_blkno;
13902799Smarx 	struct dadk *dadkp = PKT2DADK(pktp);
13912799Smarx 	dadk_errstats_t *dep;
13922799Smarx 	int scb = *(char *)pktp->cp_scbp;
13931709Smlf 
13942799Smarx 	if (scb == DERR_SUCCESS) {
13952799Smarx 		if (pktp->cp_retry != 0 && dadkp->dad_errstats != NULL) {
13962799Smarx 			dep = (dadk_errstats_t *)
13972799Smarx 			    dadkp->dad_errstats->ks_data;
13982799Smarx 			dep->dadk_rq_recov_err.value.ui32++;
13992799Smarx 		}
14001709Smlf 		return (COMMAND_DONE);
14012799Smarx 	}
14021709Smlf 
14031709Smlf 	if (pktp->cp_retry) {
14041709Smlf 		err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer -
14055295Srandyf 		    pktp->cp_resid) >> dadkp->dad_secshf);
14061709Smlf 	} else
14071709Smlf 		err_blkno = -1;
14081709Smlf 
14092799Smarx 	if (dadkp->dad_errstats != NULL) {
14102799Smarx 		dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data;
14112799Smarx 
14123399Smarx 		switch (dadk_errtab[scb].d_severity) {
14133399Smarx 			case GDA_RETRYABLE:
14143399Smarx 				dep->dadk_softerrs.value.ui32++;
14153399Smarx 				break;
14163399Smarx 
14173399Smarx 			case GDA_FATAL:
14183399Smarx 				dep->dadk_harderrs.value.ui32++;
14193399Smarx 				break;
14203399Smarx 
14213399Smarx 			default:
14223399Smarx 				break;
14233399Smarx 		}
14242799Smarx 
14252799Smarx 		switch (scb) {
14262799Smarx 			case DERR_INVCDB:
14272799Smarx 			case DERR_ILI:
14282799Smarx 			case DERR_EOM:
14292799Smarx 			case DERR_HW:
14302799Smarx 			case DERR_ICRC:
14312799Smarx 				dep->dadk_transerrs.value.ui32++;
14322799Smarx 				break;
14332799Smarx 
14342799Smarx 			case DERR_AMNF:
14352799Smarx 			case DERR_TKONF:
14362799Smarx 			case DERR_DWF:
14372799Smarx 			case DERR_BBK:
14382799Smarx 			case DERR_UNC:
14392799Smarx 			case DERR_HARD:
14402799Smarx 			case DERR_MEDIUM:
14412799Smarx 			case DERR_DATA_PROT:
14422799Smarx 			case DERR_MISCOMP:
14432799Smarx 				dep->dadk_rq_media_err.value.ui32++;
14442799Smarx 				break;
14452799Smarx 
14462799Smarx 			case DERR_NOTREADY:
14472799Smarx 				dep->dadk_rq_ntrdy_err.value.ui32++;
14482799Smarx 				break;
14492799Smarx 
14502799Smarx 			case DERR_IDNF:
14512799Smarx 			case DERR_UNIT_ATTN:
14522799Smarx 				dep->dadk_rq_nodev_err.value.ui32++;
14532799Smarx 				break;
14542799Smarx 
14552799Smarx 			case DERR_ILL:
14562799Smarx 			case DERR_RESV:
14572799Smarx 				dep->dadk_rq_illrq_err.value.ui32++;
14582799Smarx 				break;
14592799Smarx 
14602799Smarx 			default:
14612799Smarx 				break;
14622799Smarx 		}
14632799Smarx 	}
14642799Smarx 
14651709Smlf 	/* if attempting to read a sector from a cdrom audio disk */
14661709Smlf 	if ((dadkp->dad_cdrom) &&
14671709Smlf 	    (*((char *)(pktp->cp_cdbp)) == DCMD_READ) &&
14681709Smlf 	    (scb == DERR_ILL)) {
14691709Smlf 		return (COMMAND_DONE);
14701709Smlf 	}
14711709Smlf 	if (pktp->cp_passthru == NULL) {
14721709Smlf 		gda_errmsg(dadkp->dad_sd, pktp, dadk_name,
14731709Smlf 		    dadk_errtab[scb].d_severity, pktp->cp_srtsec,
14741709Smlf 		    err_blkno, dadk_cmds, dadk_sense);
14751709Smlf 	}
14761709Smlf 
14771709Smlf 	if (scb == DERR_BUSY) {
14781709Smlf 		(void) timeout(dadk_restart, (void *)pktp, DADK_BSY_TIMEOUT);
14791709Smlf 	}
14801709Smlf 
14813399Smarx 	return (dadk_errtab[scb].d_action);
14821709Smlf }
14831709Smlf 
14841709Smlf static void
14851709Smlf dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp)
14861709Smlf {
14871709Smlf 	struct dadk *dadkp;
14881709Smlf 	int scb;
14891709Smlf 
14901709Smlf 	dadkp = PKT2DADK(pktp);
14911709Smlf 	scb = (int)(*(char *)pktp->cp_scbp);
14921709Smlf 
14931709Smlf 
14941709Smlf 	rwcmdp->status.failed_blk = rwcmdp->blkaddr +
14955295Srandyf 	    ((pktp->cp_bytexfer - pktp->cp_resid) >> dadkp->dad_secshf);
14961709Smlf 
14971709Smlf 	rwcmdp->status.resid = pktp->cp_bp->b_resid +
14985295Srandyf 	    pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid;
14991709Smlf 	switch ((int)(* (char *)pktp->cp_scbp)) {
15001709Smlf 	case DERR_AMNF:
15011709Smlf 	case DERR_ABORT:
15021709Smlf 		rwcmdp->status.status = DADKIO_STAT_ILLEGAL_REQUEST;
15031709Smlf 		break;
15041709Smlf 	case DERR_DWF:
15051709Smlf 	case DERR_IDNF:
15061709Smlf 		rwcmdp->status.status = DADKIO_STAT_ILLEGAL_ADDRESS;
15071709Smlf 		break;
15081709Smlf 	case DERR_TKONF:
15091709Smlf 	case DERR_UNC:
15101709Smlf 	case DERR_BBK:
15111709Smlf 		rwcmdp->status.status = DADKIO_STAT_MEDIUM_ERROR;
15121709Smlf 		rwcmdp->status.failed_blk_is_valid = 1;
15131709Smlf 		rwcmdp->status.resid = 0;
15141709Smlf 		break;
15151709Smlf 	case DERR_BUSY:
15161709Smlf 		rwcmdp->status.status = DADKIO_STAT_NOT_READY;
15171709Smlf 		break;
15181709Smlf 	case DERR_INVCDB:
15191709Smlf 	case DERR_HARD:
15201709Smlf 		rwcmdp->status.status = DADKIO_STAT_HARDWARE_ERROR;
15211709Smlf 		break;
15221709Smlf 	case DERR_ICRC:
15231709Smlf 	default:
15241709Smlf 		rwcmdp->status.status = DADKIO_STAT_NOT_SUPPORTED;
15251709Smlf 	}
15261709Smlf 
15271709Smlf 	if (rwcmdp->flags & DADKIO_FLAG_SILENT)
15281709Smlf 		return;
15291709Smlf 	gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity,
15305295Srandyf 	    rwcmdp->blkaddr, rwcmdp->status.failed_blk,
15315295Srandyf 	    dadk_cmds, dadk_sense);
15321709Smlf }
15331709Smlf 
15341709Smlf /*ARGSUSED*/
15351709Smlf static void
15361709Smlf dadk_polldone(struct buf *bp)
15371709Smlf {
15385295Srandyf 	struct cmpkt *pktp;
15395295Srandyf 	struct dadk *dadkp;
15405295Srandyf 
15415295Srandyf 	pktp  = GDA_BP_PKT(bp);
15425295Srandyf 	dadkp = PKT2DADK(pktp);
15435295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
15445295Srandyf 	dadkp->dad_cmd_count--;
15455295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
15461709Smlf }
15471709Smlf 
15481709Smlf static void
15491709Smlf dadk_iodone(struct buf *bp)
15501709Smlf {
15511709Smlf 	struct cmpkt *pktp;
15521709Smlf 	struct dadk *dadkp;
15531709Smlf 
15541709Smlf 	pktp  = GDA_BP_PKT(bp);
15551709Smlf 	dadkp = PKT2DADK(pktp);
15561709Smlf 
15571709Smlf 	/* check for all iodone */
15581709Smlf 	pktp->cp_byteleft -= pktp->cp_bytexfer;
15591709Smlf 	if (geterror(bp) == 0 && pktp->cp_byteleft != 0) {
15601709Smlf 		pktp->cp_retry = 0;
15611709Smlf 		(void) dadk_iosetup(dadkp, pktp);
15621709Smlf 
15631709Smlf 
15641709Smlf 	/* 	transport the next one */
15651709Smlf 		if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == CTL_SEND_SUCCESS)
15661709Smlf 			return;
15671709Smlf 		if ((dadk_ioretry(pktp, QUE_COMMAND)) == JUST_RETURN)
15681709Smlf 			return;
15691709Smlf 	}
15701709Smlf 
15711709Smlf 	/* start next one */
15721709Smlf 	FLC_DEQUE(dadkp->dad_flcobjp, bp);
15731709Smlf 
15741709Smlf 	/* free pkt */
15751709Smlf 	if (pktp->cp_private)
15761709Smlf 		BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private);
15771709Smlf 	gda_free(dadkp->dad_ctlobjp, pktp, NULL);
15785295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
15795295Srandyf 	dadkp->dad_cmd_count--;
15805295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
15811709Smlf 	biodone(bp);
15821709Smlf }
15831709Smlf 
15841709Smlf int
15851709Smlf dadk_check_media(opaque_t objp, int *state)
15861709Smlf {
15871709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
15881709Smlf 
15891709Smlf 	if (!dadkp->dad_rmb) {
15901709Smlf 		return (ENXIO);
15911709Smlf 	}
15921709Smlf #ifdef DADK_DEBUG
15931709Smlf 	if (dadk_debug & DSTATE)
15941709Smlf 		PRF("dadk_check_media: user state %x disk state %x\n",
15955295Srandyf 		    *state, dadkp->dad_iostate);
15961709Smlf #endif
15971709Smlf 	/*
15981709Smlf 	 * If state already changed just return
15991709Smlf 	 */
16001709Smlf 	if (*state != dadkp->dad_iostate) {
16011709Smlf 		*state = dadkp->dad_iostate;
16021709Smlf 		return (0);
16031709Smlf 	}
16041709Smlf 
16051709Smlf 	/*
16061709Smlf 	 * Startup polling on thread state
16071709Smlf 	 */
16081709Smlf 	mutex_enter(&dadkp->dad_mutex);
16091709Smlf 	if (dadkp->dad_thread_cnt == 0) {
16101709Smlf 		/*
16111709Smlf 		 * One thread per removable dadk device
16121709Smlf 		 */
16131709Smlf 		(void) thread_create(NULL, 0, dadk_watch_thread, dadkp, 0, &p0,
16141709Smlf 		    TS_RUN, v.v_maxsyspri - 2);
16151709Smlf 	}
16161709Smlf 	dadkp->dad_thread_cnt++;
16171709Smlf 
16181709Smlf 	/*
16191709Smlf 	 * Wait for state to change
16201709Smlf 	 */
16211709Smlf 	do {
16221709Smlf 		if (cv_wait_sig(&dadkp->dad_state_cv, &dadkp->dad_mutex) == 0) {
16231709Smlf 			dadkp->dad_thread_cnt--;
16241709Smlf 			mutex_exit(&dadkp->dad_mutex);
16251709Smlf 			return (EINTR);
16261709Smlf 		}
16271709Smlf 	} while (*state == dadkp->dad_iostate);
16281709Smlf 	*state = dadkp->dad_iostate;
16291709Smlf 	dadkp->dad_thread_cnt--;
16301709Smlf 	mutex_exit(&dadkp->dad_mutex);
16311709Smlf 	return (0);
16321709Smlf }
16331709Smlf 
16341709Smlf 
16351709Smlf #define	MEDIA_ACCESS_DELAY 2000000
16361709Smlf 
16371709Smlf static void
16381709Smlf dadk_watch_thread(struct dadk *dadkp)
16391709Smlf {
16401709Smlf 	enum dkio_state state;
16411709Smlf 	int interval;
16421709Smlf 
16431709Smlf 	interval = drv_usectohz(dadk_check_media_time);
16441709Smlf 
16451709Smlf 	do {
16461709Smlf 		if (dadk_rmb_ioctl(dadkp, DCMD_GET_STATE, (intptr_t)&state, 0,
16471709Smlf 		    DADK_SILENT)) {
16481709Smlf 			/*
16491709Smlf 			 * Assume state remained the same
16501709Smlf 			 */
16511709Smlf 			state = dadkp->dad_iostate;
16521709Smlf 		}
16531709Smlf 
16541709Smlf 		/*
16551709Smlf 		 * now signal the waiting thread if this is *not* the
16561709Smlf 		 * specified state;
16571709Smlf 		 * delay the signal if the state is DKIO_INSERTED
16581709Smlf 		 * to allow the target to recover
16591709Smlf 		 */
16601709Smlf 		if (state != dadkp->dad_iostate) {
16611709Smlf 
16621709Smlf 			dadkp->dad_iostate = state;
16631709Smlf 			if (state == DKIO_INSERTED) {
16641709Smlf 				/*
16651709Smlf 				 * delay the signal to give the drive a chance
16661709Smlf 				 * to do what it apparently needs to do
16671709Smlf 				 */
16681709Smlf 				(void) timeout((void(*)(void *))cv_broadcast,
16691709Smlf 				    (void *)&dadkp->dad_state_cv,
16701709Smlf 				    drv_usectohz((clock_t)MEDIA_ACCESS_DELAY));
16711709Smlf 			} else {
16721709Smlf 				cv_broadcast(&dadkp->dad_state_cv);
16731709Smlf 			}
16741709Smlf 		}
16751709Smlf 		delay(interval);
16761709Smlf 	} while (dadkp->dad_thread_cnt);
16771709Smlf }
16781709Smlf 
16791709Smlf int
16801709Smlf dadk_inquiry(opaque_t objp, opaque_t *inqpp)
16811709Smlf {
16821709Smlf 	struct dadk *dadkp = (struct dadk *)objp;
16831709Smlf 	struct scsi_inquiry **sinqpp = (struct scsi_inquiry **)inqpp;
16841709Smlf 
16851709Smlf 	if (dadkp && dadkp->dad_sd && dadkp->dad_sd->sd_inq) {
16861709Smlf 		*sinqpp = dadkp->dad_sd->sd_inq;
16871709Smlf 		return (DDI_SUCCESS);
16881709Smlf 	}
16891709Smlf 
16901709Smlf 	return (DDI_FAILURE);
16911709Smlf }
16921709Smlf 
16931709Smlf static int
16941709Smlf dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent)
16951709Smlf 
16961709Smlf {
16971709Smlf 	struct buf *bp;
16981709Smlf 	int err;
16991709Smlf 	struct cmpkt *pktp;
17001709Smlf 
17011709Smlf 	if ((bp = getrbuf(KM_SLEEP)) == NULL) {
17021709Smlf 		return (ENOMEM);
17031709Smlf 	}
17041709Smlf 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_rmb_iodone, NULL, NULL);
17051709Smlf 	if (!pktp) {
17061709Smlf 		freerbuf(bp);
17071709Smlf 		return (ENOMEM);
17081709Smlf 	}
17091709Smlf 	bp->b_back  = (struct buf *)arg;
17101709Smlf 	bp->b_forw  = (struct buf *)dadkp->dad_flcobjp;
17111709Smlf 	pktp->cp_passthru = (opaque_t)(intptr_t)silent;
17121709Smlf 
17135295Srandyf 	err = dadk_ctl_ioctl(dadkp, cmd, (uintptr_t)pktp, flags);
17141709Smlf 	freerbuf(bp);
17151709Smlf 	gda_free(dadkp->dad_ctlobjp, pktp, NULL);
17161709Smlf 	return (err);
17171709Smlf 
17181709Smlf 
17191709Smlf }
17201709Smlf 
17211709Smlf static void
17221709Smlf dadk_rmb_iodone(struct buf *bp)
17231709Smlf {
17241709Smlf 	struct cmpkt *pktp;
17251709Smlf 	struct dadk *dadkp;
17261709Smlf 
17271709Smlf 	pktp  = GDA_BP_PKT(bp);
17281709Smlf 	dadkp = PKT2DADK(pktp);
17291709Smlf 
17301709Smlf 	bp->b_flags &= ~(B_DONE|B_BUSY);
17311709Smlf 
17321709Smlf 	/* Start next one */
17331709Smlf 	FLC_DEQUE(dadkp->dad_flcobjp, bp);
17341709Smlf 
17355295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
17365295Srandyf 	dadkp->dad_cmd_count--;
17375295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
17381709Smlf 	biodone(bp);
17391709Smlf }
17401709Smlf 
17411709Smlf static int
17421709Smlf dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, dev_t dev,
17431709Smlf 	enum uio_seg dataspace, int rw)
17441709Smlf {
17451709Smlf 	struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp;
17461709Smlf 	struct buf	*bp;
17471709Smlf 	struct iovec	aiov;
17481709Smlf 	struct uio	auio;
17491709Smlf 	struct uio	*uio = &auio;
17501709Smlf 	int		status;
17511709Smlf 
17521709Smlf 	bp = getrbuf(KM_SLEEP);
17531709Smlf 
17541709Smlf 	bp->av_forw = bp->b_forw = (struct buf *)dadkp;
17551709Smlf 	bp->b_back  = (struct buf *)rwcmdp;	/* ioctl packet */
17561709Smlf 
17571709Smlf 	bzero((caddr_t)&auio, sizeof (struct uio));
17581709Smlf 	bzero((caddr_t)&aiov, sizeof (struct iovec));
17591709Smlf 	aiov.iov_base = rwcmdp->bufaddr;
17601709Smlf 	aiov.iov_len = rwcmdp->buflen;
17611709Smlf 	uio->uio_iov = &aiov;
17621709Smlf 
17631709Smlf 	uio->uio_iovcnt = 1;
17641709Smlf 	uio->uio_resid = rwcmdp->buflen;
17651709Smlf 	uio->uio_segflg = dataspace;
17661709Smlf 
17671709Smlf 	/* Let physio do the rest... */
17681709Smlf 	status = physio(dadk_dk_strategy, bp, dev, rw, dadkmin, uio);
17691709Smlf 
17701709Smlf 	freerbuf(bp);
17711709Smlf 	return (status);
17721709Smlf 
17731709Smlf }
17741709Smlf 
17751709Smlf /* Do not let a user gendisk request get too big or */
17761709Smlf /* else we could use to many resources.		    */
17771709Smlf 
17781709Smlf static void
17791709Smlf dadkmin(struct buf *bp)
17801709Smlf {
17811709Smlf 	if (bp->b_bcount > dadk_dk_maxphys)
17821709Smlf 		bp->b_bcount = dadk_dk_maxphys;
17831709Smlf }
17841709Smlf 
17851709Smlf static int
17861709Smlf dadk_dk_strategy(struct buf *bp)
17871709Smlf {
17881709Smlf 	dadk_dk((struct dadk *)bp->av_forw, (struct dadkio_rwcmd *)bp->b_back,
17891709Smlf 	    bp);
17901709Smlf 	return (0);
17911709Smlf }
17921709Smlf 
17931709Smlf static void
17941709Smlf dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp)
17951709Smlf {
17961709Smlf 	struct  cmpkt *pktp;
17971709Smlf 
17981709Smlf 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, NULL, NULL);
17991709Smlf 	if (!pktp) {
18001709Smlf 		bioerror(bp, ENOMEM);
18011709Smlf 		biodone(bp);
18021709Smlf 		return;
18031709Smlf 	}
18041709Smlf 
18051709Smlf 	pktp->cp_passthru = rwcmdp;
18061709Smlf 
18071709Smlf 	(void) dadk_ioprep(dadkp, pktp);
18081709Smlf 
18095295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
18105295Srandyf 	dadkp->dad_cmd_count++;
18115295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
18121709Smlf 	FLC_ENQUE(dadkp->dad_flcobjp, bp);
18131709Smlf }
18145295Srandyf 
18155295Srandyf /*
18165295Srandyf  * There is no existing way to notify cmdk module
18175295Srandyf  * when the command completed, so add this function
18185295Srandyf  * to calculate how many on-going commands.
18195295Srandyf  */
18205295Srandyf int
18215295Srandyf dadk_getcmds(opaque_t objp)
18225295Srandyf {
18235295Srandyf 	struct dadk *dadkp = (struct dadk *)objp;
18245295Srandyf 	int count;
18255295Srandyf 
18265295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
18275295Srandyf 	count = dadkp->dad_cmd_count;
18285295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
18295295Srandyf 	return (count);
18305295Srandyf }
18315295Srandyf 
18325295Srandyf /*
18335295Srandyf  * this function was used to calc the cmd for CTL_IOCTL
18345295Srandyf  */
18355295Srandyf static int
18365295Srandyf dadk_ctl_ioctl(struct dadk *dadkp, uint32_t cmd, uintptr_t arg, int flag)
18375295Srandyf {
18385295Srandyf 	int error;
18395295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
18405295Srandyf 	dadkp->dad_cmd_count++;
18415295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
18425295Srandyf 	error = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag);
18435295Srandyf 	mutex_enter(&dadkp->dad_cmd_mutex);
18445295Srandyf 	dadkp->dad_cmd_count--;
18455295Srandyf 	mutex_exit(&dadkp->dad_cmd_mutex);
18465295Srandyf 	return (error);
18475295Srandyf }
1848