xref: /titanic_50/usr/src/uts/intel/io/dktp/dcdev/dadk.c (revision c6f76c3487b0d7e374ba5897fabad436f221c46e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Direct Attached Disk
31  */
32 
33 #include <sys/file.h>
34 #include <sys/scsi/scsi.h>
35 #include <sys/var.h>
36 #include <sys/proc.h>
37 #include <sys/dktp/cm.h>
38 #include <sys/vtoc.h>
39 #include <sys/dkio.h>
40 
41 #include <sys/dktp/dadev.h>
42 #include <sys/dktp/fctypes.h>
43 #include <sys/dktp/flowctrl.h>
44 #include <sys/dktp/tgcom.h>
45 #include <sys/dktp/tgdk.h>
46 #include <sys/dktp/bbh.h>
47 #include <sys/dktp/dadkio.h>
48 #include <sys/dktp/dadk.h>
49 #include <sys/cdio.h>
50 
51 /*
52  * Local Function Prototypes
53  */
54 static void dadk_restart(void *pktp);
55 static void dadk_pktcb(struct cmpkt *pktp);
56 static void dadk_iodone(struct buf *bp);
57 static void dadk_polldone(struct buf *bp);
58 static void dadk_setcap(struct dadk *dadkp);
59 static int dadk_create_errstats(struct dadk *dadkp, int instance);
60 static int dadk_destroy_errstats(struct dadk *dadkp);
61 
62 static int dadk_chkerr(struct cmpkt *pktp);
63 static int dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp);
64 static int dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp);
65 static int dadk_ioretry(struct cmpkt *pktp, int action);
66 
67 static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp,
68     struct buf *bp, void (*cb_func)(struct buf *), int (*func)(caddr_t),
69     caddr_t arg);
70 
71 static int  dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t),
72     caddr_t arg);
73 static void dadk_transport(opaque_t com_data, struct buf *bp);
74 
75 struct tgcom_objops dadk_com_ops = {
76 	nodev,
77 	nodev,
78 	dadk_pkt,
79 	dadk_transport,
80 	0, 0
81 };
82 
83 /*
84  * architecture dependent allocation restrictions for dadk_iob_alloc(). For
85  * x86, we'll set dma_attr_addr_hi to dadk_max_phys_addr and dma_attr_sgllen
86  * to dadk_sgl_size during _init().
87  */
88 #if defined(__sparc)
89 static ddi_dma_attr_t dadk_alloc_attr = {
90 	DMA_ATTR_V0,	/* version number */
91 	0x0,		/* lowest usable address */
92 	0xFFFFFFFFull,	/* high DMA address range */
93 	0xFFFFFFFFull,	/* DMA counter register */
94 	1,		/* DMA address alignment */
95 	1,		/* DMA burstsizes */
96 	1,		/* min effective DMA size */
97 	0xFFFFFFFFull,	/* max DMA xfer size */
98 	0xFFFFFFFFull,	/* segment boundary */
99 	1,		/* s/g list length */
100 	512,		/* granularity of device */
101 	0,		/* DMA transfer flags */
102 };
103 #elif defined(__x86)
104 static ddi_dma_attr_t dadk_alloc_attr = {
105 	DMA_ATTR_V0,	/* version number */
106 	0x0,		/* lowest usable address */
107 	0x0,		/* high DMA address range [set in _init()] */
108 	0xFFFFull,	/* DMA counter register */
109 	512,		/* DMA address alignment */
110 	1,		/* DMA burstsizes */
111 	1,		/* min effective DMA size */
112 	0xFFFFFFFFull,	/* max DMA xfer size */
113 	0xFFFFFFFFull,	/* segment boundary */
114 	0,		/* s/g list length [set in _init()] */
115 	512,		/* granularity of device */
116 	0,		/* DMA transfer flags */
117 };
118 
119 uint64_t dadk_max_phys_addr = 0xFFFFFFFFull;
120 int dadk_sgl_size = 0xFF;
121 #endif
122 
123 static int dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags,
124     int silent);
125 static void dadk_rmb_iodone(struct buf *bp);
126 
127 static int dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp,
128     dev_t dev, enum uio_seg dataspace, int rw);
129 static void dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *scmdp,
130     struct buf *bp);
131 static void dadkmin(struct buf *bp);
132 static int dadk_dk_strategy(struct buf *bp);
133 static void dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp);
134 
135 struct tgdk_objops dadk_ops = {
136 	dadk_init,
137 	dadk_free,
138 	dadk_probe,
139 	dadk_attach,
140 	dadk_open,
141 	dadk_close,
142 	dadk_ioctl,
143 	dadk_strategy,
144 	dadk_setgeom,
145 	dadk_getgeom,
146 	dadk_iob_alloc,
147 	dadk_iob_free,
148 	dadk_iob_htoc,
149 	dadk_iob_xfer,
150 	dadk_dump,
151 	dadk_getphygeom,
152 	dadk_set_bbhobj,
153 	dadk_check_media,
154 	dadk_inquiry,
155 	dadk_cleanup,
156 	0
157 };
158 
159 /*
160  * Local static data
161  */
162 
163 #ifdef	DADK_DEBUG
164 #define	DENT	0x0001
165 #define	DERR	0x0002
166 #define	DIO	0x0004
167 #define	DGEOM	0x0010
168 #define	DSTATE  0x0020
169 static	int	dadk_debug = DGEOM;
170 
171 #endif	/* DADK_DEBUG */
172 
173 static int dadk_check_media_time = 3000000;	/* 3 Second State Check */
174 static int dadk_dk_maxphys = 0x80000;
175 
176 static char	*dadk_cmds[] = {
177 	"\000Unknown",			/* unknown 		*/
178 	"\001read sector",		/* DCMD_READ 1		*/
179 	"\002write sector",		/* DCMD_WRITE 2		*/
180 	"\003format track",		/* DCMD_FMTTRK 3	*/
181 	"\004format whole drive",	/* DCMD_FMTDRV 4	*/
182 	"\005recalibrate",		/* DCMD_RECAL  5	*/
183 	"\006seek sector",		/* DCMD_SEEK   6	*/
184 	"\007read verify",		/* DCMD_RDVER  7	*/
185 	"\010read defect list",		/* DCMD_GETDEF 8	*/
186 	"\011lock door",		/* DCMD_LOCK   9	*/
187 	"\012unlock door",		/* DCMD_UNLOCK 10	*/
188 	"\013start motor",		/* DCMD_START_MOTOR 11	*/
189 	"\014stop motor",		/* DCMD_STOP_MOTOR 12	*/
190 	"\015eject",			/* DCMD_EJECT  13	*/
191 	"\016update geometry",		/* DCMD_UPDATE_GEOM  14	*/
192 	"\017get state",		/* DCMD_GET_STATE  15	*/
193 	"\020cdrom pause",		/* DCMD_PAUSE  16	*/
194 	"\021cdrom resume",		/* DCMD_RESUME  17	*/
195 	"\022cdrom play track index",	/* DCMD_PLAYTRKIND  18	*/
196 	"\023cdrom play msf",		/* DCMD_PLAYMSF  19	*/
197 	"\024cdrom sub channel",	/* DCMD_SUBCHNL  20	*/
198 	"\025cdrom read mode 1",	/* DCMD_READMODE1  21	*/
199 	"\026cdrom read toc header",	/* DCMD_READTOCHDR  22	*/
200 	"\027cdrom read toc entry",	/* DCMD_READTOCENT  23	*/
201 	"\030cdrom read offset",	/* DCMD_READOFFSET  24	*/
202 	"\031cdrom read mode 2",	/* DCMD_READMODE2  25	*/
203 	"\032cdrom volume control",	/* DCMD_VOLCTRL  26	*/
204 	"\033flush cache",		/* DCMD_FLUSH_CACHE  27	*/
205 	NULL
206 };
207 
208 static char *dadk_sense[] = {
209 	"\000Success",			/* DERR_SUCCESS		*/
210 	"\001address mark not found",	/* DERR_AMNF		*/
211 	"\002track 0 not found",	/* DERR_TKONF		*/
212 	"\003aborted command",		/* DERR_ABORT		*/
213 	"\004write fault",		/* DERR_DWF		*/
214 	"\005ID not found",		/* DERR_IDNF		*/
215 	"\006drive busy",		/* DERR_BUSY		*/
216 	"\007uncorrectable data error",	/* DERR_UNC		*/
217 	"\010bad block detected",	/* DERR_BBK		*/
218 	"\011invalid command",		/* DERR_INVCDB		*/
219 	"\012device hard error",	/* DERR_HARD		*/
220 	"\013illegal length indicated", /* DERR_ILI		*/
221 	"\014end of media",		/* DERR_EOM		*/
222 	"\015media change requested",	/* DERR_MCR		*/
223 	"\016recovered from error",	/* DERR_RECOVER		*/
224 	"\017device not ready",		/* DERR_NOTREADY	*/
225 	"\020medium error",		/* DERR_MEDIUM		*/
226 	"\021hardware error",		/* DERR_HW		*/
227 	"\022illegal request",		/* DERR_ILL		*/
228 	"\023unit attention",		/* DERR_UNIT_ATTN	*/
229 	"\024data protection",		/* DERR_DATA_PROT	*/
230 	"\025miscompare",		/* DERR_MISCOMPARE	*/
231 	"\026ICRC error during UDMA",	/* DERR_ICRC		*/
232 	"\027reserved",			/* DERR_RESV		*/
233 	NULL
234 };
235 
236 static char *dadk_name = "Disk";
237 
238 /*
239  *	This is the loadable module wrapper
240  */
241 #include <sys/modctl.h>
242 
243 extern struct mod_ops mod_miscops;
244 
245 static struct modlmisc modlmisc = {
246 	&mod_miscops,	/* Type of module */
247 	"Direct Attached Disk %I%"
248 };
249 
250 static struct modlinkage modlinkage = {
251 	MODREV_1, (void *)&modlmisc, NULL
252 };
253 
254 int
255 _init(void)
256 {
257 #ifdef DADK_DEBUG
258 	if (dadk_debug & DENT)
259 		PRF("dadk_init: call\n");
260 #endif
261 
262 #if defined(__x86)
263 	/* set the max physical address for iob allocs on x86 */
264 	dadk_alloc_attr.dma_attr_addr_hi = dadk_max_phys_addr;
265 
266 	/*
267 	 * set the sgllen for iob allocs on x86. If this is set less than
268 	 * the number of pages the buffer will take (taking into account
269 	 * alignment), it would force the allocator to try and allocate
270 	 * contiguous pages.
271 	 */
272 	dadk_alloc_attr.dma_attr_sgllen = dadk_sgl_size;
273 #endif
274 
275 	return (mod_install(&modlinkage));
276 }
277 
278 int
279 _fini(void)
280 {
281 #ifdef DADK_DEBUG
282 	if (dadk_debug & DENT)
283 		PRF("dadk_fini: call\n");
284 #endif
285 
286 	return (mod_remove(&modlinkage));
287 }
288 
289 int
290 _info(struct modinfo *modinfop)
291 {
292 	return (mod_info(&modlinkage, modinfop));
293 }
294 
295 struct tgdk_obj *
296 dadk_create()
297 {
298 	struct tgdk_obj *dkobjp;
299 	struct dadk *dadkp;
300 
301 	dkobjp = kmem_zalloc((sizeof (*dkobjp) + sizeof (*dadkp)), KM_NOSLEEP);
302 	if (!dkobjp)
303 		return (NULL);
304 	dadkp = (struct dadk *)(dkobjp+1);
305 
306 	dkobjp->tg_ops  = (struct  tgdk_objops *)&dadk_ops;
307 	dkobjp->tg_data = (opaque_t)dadkp;
308 	dkobjp->tg_ext = &(dkobjp->tg_extblk);
309 	dadkp->dad_extp = &(dkobjp->tg_extblk);
310 
311 #ifdef DADK_DEBUG
312 	if (dadk_debug & DENT)
313 		PRF("dadk_create: tgdkobjp= 0x%x dadkp= 0x%x\n", dkobjp, dadkp);
314 #endif
315 	return (dkobjp);
316 }
317 
318 int
319 dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp,
320 	opaque_t bbhobjp, void *lkarg)
321 {
322 	struct dadk *dadkp = (struct dadk *)objp;
323 	struct scsi_device *sdevp = (struct scsi_device *)devp;
324 
325 	dadkp->dad_sd = devp;
326 	dadkp->dad_ctlobjp = (opaque_t)sdevp->sd_address.a_hba_tran;
327 	sdevp->sd_private = (caddr_t)dadkp;
328 
329 	/* initialize the communication object */
330 	dadkp->dad_com.com_data = (opaque_t)dadkp;
331 	dadkp->dad_com.com_ops  = &dadk_com_ops;
332 
333 	dadkp->dad_bbhobjp = bbhobjp;
334 	BBH_INIT(bbhobjp);
335 
336 	dadkp->dad_flcobjp = flcobjp;
337 	return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg));
338 }
339 
340 int
341 dadk_free(struct tgdk_obj *dkobjp)
342 {
343 	TGDK_CLEANUP(dkobjp);
344 	kmem_free(dkobjp, (sizeof (*dkobjp) + sizeof (struct dadk)));
345 
346 	return (DDI_SUCCESS);
347 }
348 
349 void
350 dadk_cleanup(struct tgdk_obj *dkobjp)
351 {
352 	struct dadk *dadkp;
353 
354 	dadkp = (struct dadk *)(dkobjp->tg_data);
355 	if (dadkp->dad_sd)
356 		dadkp->dad_sd->sd_private = NULL;
357 	if (dadkp->dad_bbhobjp) {
358 		BBH_FREE(dadkp->dad_bbhobjp);
359 		dadkp->dad_bbhobjp = NULL;
360 	}
361 	if (dadkp->dad_flcobjp) {
362 		FLC_FREE(dadkp->dad_flcobjp);
363 		dadkp->dad_flcobjp = NULL;
364 	}
365 }
366 
367 /* ARGSUSED */
368 int
369 dadk_probe(opaque_t objp, int kmsflg)
370 {
371 	struct dadk *dadkp = (struct dadk *)objp;
372 	struct scsi_device *devp;
373 	char   name[80];
374 
375 	devp = dadkp->dad_sd;
376 	if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) ||
377 		(devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) {
378 		return (DDI_PROBE_FAILURE);
379 	}
380 
381 	switch (devp->sd_inq->inq_dtype) {
382 		case DTYPE_DIRECT:
383 			dadkp->dad_ctype = DKC_DIRECT;
384 			dadkp->dad_extp->tg_nodetype = DDI_NT_BLOCK;
385 			dadkp->dad_extp->tg_ctype = DKC_DIRECT;
386 			break;
387 		case DTYPE_RODIRECT: /* eg cdrom */
388 			dadkp->dad_ctype = DKC_CDROM;
389 			dadkp->dad_extp->tg_rdonly = 1;
390 			dadkp->dad_rdonly = 1;
391 			dadkp->dad_cdrom = 1;
392 			dadkp->dad_extp->tg_nodetype = DDI_NT_CD;
393 			dadkp->dad_extp->tg_ctype = DKC_CDROM;
394 			break;
395 		case DTYPE_WORM:
396 		case DTYPE_OPTICAL:
397 		default:
398 			return (DDI_PROBE_FAILURE);
399 	}
400 
401 	dadkp->dad_extp->tg_rmb = dadkp->dad_rmb = devp->sd_inq->inq_rmb;
402 
403 	dadkp->dad_secshf = SCTRSHFT;
404 	dadkp->dad_blkshf = 0;
405 
406 	/* display the device name */
407 	(void) strcpy(name, "Vendor '");
408 	gda_inqfill((caddr_t)devp->sd_inq->inq_vid, 8, &name[strlen(name)]);
409 	(void) strcat(name, "' Product '");
410 	gda_inqfill((caddr_t)devp->sd_inq->inq_pid, 16, &name[strlen(name)]);
411 	(void) strcat(name, "'");
412 	gda_log(devp->sd_dev, dadk_name, CE_NOTE, "!<%s>\n", name);
413 
414 	return (DDI_PROBE_SUCCESS);
415 }
416 
417 
418 /* ARGSUSED */
419 int
420 dadk_attach(opaque_t objp)
421 {
422 	return (DDI_SUCCESS);
423 }
424 
425 int
426 dadk_set_bbhobj(opaque_t objp, opaque_t bbhobjp)
427 {
428 	struct dadk *dadkp = (struct dadk *)objp;
429 	/* free the old bbh object */
430 	if (dadkp->dad_bbhobjp)
431 		BBH_FREE(dadkp->dad_bbhobjp);
432 
433 	/* initialize the new bbh object */
434 	dadkp->dad_bbhobjp = bbhobjp;
435 	BBH_INIT(bbhobjp);
436 
437 	return (DDI_SUCCESS);
438 }
439 
440 /* ARGSUSED */
441 int
442 dadk_open(opaque_t objp, int flag)
443 {
444 	struct dadk *dadkp = (struct dadk *)objp;
445 	int error;
446 	int wce;
447 
448 	if (!dadkp->dad_rmb) {
449 		if (dadkp->dad_phyg.g_cap) {
450 			FLC_START_KSTAT(dadkp->dad_flcobjp, "disk",
451 			    ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
452 			return (DDI_SUCCESS);
453 		}
454 	} else {
455 	    mutex_enter(&dadkp->dad_mutex);
456 	    dadkp->dad_iostate = DKIO_NONE;
457 	    cv_broadcast(&dadkp->dad_state_cv);
458 	    mutex_exit(&dadkp->dad_mutex);
459 
460 	    if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0, DADK_SILENT) ||
461 		dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) ||
462 		dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0, DADK_SILENT)) {
463 		    return (DDI_FAILURE);
464 	    }
465 
466 	    mutex_enter(&dadkp->dad_mutex);
467 	    dadkp->dad_iostate = DKIO_INSERTED;
468 	    cv_broadcast(&dadkp->dad_state_cv);
469 	    mutex_exit(&dadkp->dad_mutex);
470 	}
471 
472 	/*
473 	 * get write cache enable state
474 	 * If there is an error, must assume that write cache
475 	 * is enabled.
476 	 * NOTE: Since there is currently no Solaris mechanism to
477 	 * change the state of the Write Cache Enable feature,
478 	 * this code just checks the value of the WCE bit
479 	 * obtained at device init time.  If a mechanism
480 	 * is added to the driver to change WCE, dad_wce
481 	 * must be updated appropriately.
482 	 */
483 	error = CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETWCE,
484 	    (uintptr_t)&wce, 0);
485 	mutex_enter(&dadkp->dad_mutex);
486 	dadkp->dad_wce = (error != 0) || (wce != 0);
487 	mutex_exit(&dadkp->dad_mutex);
488 
489 	/* logical disk geometry */
490 	CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETGEOM,
491 	    (uintptr_t)&dadkp->dad_logg, 0);
492 	if (dadkp->dad_logg.g_cap == 0)
493 		return (DDI_FAILURE);
494 
495 	/* get physical disk geometry */
496 	CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETPHYGEOM,
497 	    (uintptr_t)&dadkp->dad_phyg, 0);
498 	if (dadkp->dad_phyg.g_cap == 0)
499 		return (DDI_FAILURE);
500 
501 	dadk_setcap(dadkp);
502 
503 	(void) dadk_create_errstats(dadkp,
504 	    ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
505 
506 	/* start profiling */
507 	FLC_START_KSTAT(dadkp->dad_flcobjp, "disk",
508 		ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
509 
510 	return (DDI_SUCCESS);
511 }
512 
513 static void
514 dadk_setcap(struct dadk *dadkp)
515 {
516 	int	 totsize;
517 	int	 i;
518 
519 	totsize = dadkp->dad_phyg.g_secsiz;
520 
521 	if (totsize == 0) {
522 		if (dadkp->dad_cdrom) {
523 			totsize = 2048;
524 		} else {
525 			totsize = NBPSCTR;
526 		}
527 	} else {
528 		/* Round down sector size to multiple of 512B */
529 		totsize &= ~(NBPSCTR-1);
530 	}
531 	dadkp->dad_phyg.g_secsiz = totsize;
532 
533 	/* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */
534 	totsize >>= SCTRSHFT;
535 	for (i = 0; totsize != 1; i++, totsize >>= 1);
536 	dadkp->dad_blkshf = i;
537 	dadkp->dad_secshf = i + SCTRSHFT;
538 }
539 
540 
541 static int
542 dadk_create_errstats(struct dadk *dadkp, int instance)
543 {
544 	struct dadk_errstats *dep;
545 	char kstatname[KSTAT_STRLEN];
546 	dadk_ioc_string_t dadk_ioc_string;
547 
548 	if (dadkp->dad_errstats)
549 		return (1);
550 
551 	(void) sprintf(kstatname, "cmdk%d,error", instance);
552 	dadkp->dad_errstats = kstat_create("cmdkerror", instance,
553 	    kstatname, "device_error", KSTAT_TYPE_NAMED,
554 	    sizeof (struct dadk_errstats) / sizeof (kstat_named_t),
555 	    KSTAT_FLAG_PERSISTENT);
556 
557 	if (!dadkp->dad_errstats)
558 		return (-1);
559 
560 	dep = dadkp->dad_errstats->ks_data;
561 
562 	kstat_named_init(&dep->dadk_softerrs,
563 	    "Soft Errors", KSTAT_DATA_UINT32);
564 	kstat_named_init(&dep->dadk_harderrs,
565 	    "Hard Errors", KSTAT_DATA_UINT32);
566 	kstat_named_init(&dep->dadk_transerrs,
567 	    "Transport Errors", KSTAT_DATA_UINT32);
568 	kstat_named_init(&dep->dadk_model,
569 	    "Model", KSTAT_DATA_CHAR);
570 	kstat_named_init(&dep->dadk_revision,
571 	    "Revision", KSTAT_DATA_CHAR);
572 	kstat_named_init(&dep->dadk_serial,
573 	    "Serial No", KSTAT_DATA_CHAR);
574 	kstat_named_init(&dep->dadk_capacity,
575 	    "Size", KSTAT_DATA_ULONGLONG);
576 	kstat_named_init(&dep->dadk_rq_media_err,
577 	    "Media Error", KSTAT_DATA_UINT32);
578 	kstat_named_init(&dep->dadk_rq_ntrdy_err,
579 	    "Device Not Ready", KSTAT_DATA_UINT32);
580 	kstat_named_init(&dep->dadk_rq_nodev_err,
581 	    "No Device", KSTAT_DATA_UINT32);
582 	kstat_named_init(&dep->dadk_rq_recov_err,
583 	    "Recoverable", KSTAT_DATA_UINT32);
584 	kstat_named_init(&dep->dadk_rq_illrq_err,
585 	    "Illegal Request", KSTAT_DATA_UINT32);
586 
587 	dadkp->dad_errstats->ks_private = dep;
588 	dadkp->dad_errstats->ks_update = nulldev;
589 	kstat_install(dadkp->dad_errstats);
590 
591 	/* get model */
592 	dep->dadk_model.value.c[0] = 0;
593 	dadk_ioc_string.is_buf = &dep->dadk_model.value.c[0];
594 	dadk_ioc_string.is_size = 16;
595 	CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETMODEL,
596 	    (uintptr_t)&dadk_ioc_string, FKIOCTL);
597 
598 	/* get serial */
599 	dep->dadk_serial.value.c[0] = 0;
600 	dadk_ioc_string.is_buf = &dep->dadk_serial.value.c[0];
601 	dadk_ioc_string.is_size = 16;
602 	CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETSERIAL,
603 	    (uintptr_t)&dadk_ioc_string, FKIOCTL);
604 
605 	/* Get revision */
606 	dep->dadk_revision.value.c[0] = 0;
607 
608 	/* Get capacity */
609 
610 	dep->dadk_capacity.value.ui64 =
611 	    (uint64_t)dadkp->dad_logg.g_cap *
612 	    (uint64_t)dadkp->dad_logg.g_secsiz;
613 
614 	return (0);
615 }
616 
617 
618 int
619 dadk_close(opaque_t objp)
620 {
621 	struct dadk *dadkp = (struct dadk *)objp;
622 
623 	if (dadkp->dad_rmb) {
624 		(void) dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 0,
625 		    DADK_SILENT);
626 		(void) dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT);
627 	}
628 	FLC_STOP_KSTAT(dadkp->dad_flcobjp);
629 
630 	(void) dadk_destroy_errstats(dadkp);
631 
632 	return (DDI_SUCCESS);
633 }
634 
635 static int
636 dadk_destroy_errstats(struct dadk *dadkp)
637 {
638 	if (!dadkp->dad_errstats)
639 		return (0);
640 
641 	kstat_delete(dadkp->dad_errstats);
642 	dadkp->dad_errstats = NULL;
643 	return (1);
644 }
645 
646 
647 int
648 dadk_strategy(opaque_t objp, struct buf *bp)
649 {
650 	struct dadk *dadkp = (struct dadk *)objp;
651 
652 	if (dadkp->dad_rdonly && !(bp->b_flags & B_READ)) {
653 		bioerror(bp, EROFS);
654 		return (DDI_FAILURE);
655 	}
656 
657 	if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) {
658 		bioerror(bp, ENXIO);
659 		return (DDI_FAILURE);
660 	}
661 
662 	SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf)));
663 	FLC_ENQUE(dadkp->dad_flcobjp, bp);
664 
665 	return (DDI_SUCCESS);
666 }
667 
668 int
669 dadk_dump(opaque_t objp, struct buf *bp)
670 {
671 	struct dadk *dadkp = (struct dadk *)objp;
672 	struct cmpkt *pktp;
673 
674 	if (dadkp->dad_rdonly) {
675 		bioerror(bp, EROFS);
676 		return (DDI_FAILURE);
677 	}
678 
679 	if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) {
680 		bioerror(bp, ENXIO);
681 		return (DDI_FAILURE);
682 	}
683 
684 	SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf)));
685 
686 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_polldone, NULL, NULL);
687 	if (!pktp) {
688 		cmn_err(CE_WARN, "no resources for dumping");
689 		bioerror(bp, EIO);
690 		return (DDI_FAILURE);
691 	}
692 	pktp->cp_flags |= CPF_NOINTR;
693 
694 	(void) dadk_ioprep(dadkp, pktp);
695 	dadk_transport(dadkp, bp);
696 	pktp->cp_byteleft -= pktp->cp_bytexfer;
697 
698 	while (geterror(bp) == 0 && pktp->cp_byteleft != 0) {
699 		(void) dadk_iosetup(dadkp, pktp);
700 		dadk_transport(dadkp, bp);
701 		pktp->cp_byteleft -= pktp->cp_bytexfer;
702 	}
703 
704 	if (pktp->cp_private)
705 		BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private);
706 	gda_free(dadkp->dad_ctlobjp, pktp, NULL);
707 	return (DDI_SUCCESS);
708 }
709 
710 /* ARGSUSED  */
711 int
712 dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag,
713 	cred_t *cred_p, int *rval_p)
714 {
715 	struct dadk *dadkp = (struct dadk *)objp;
716 
717 	switch (cmd) {
718 	case DKIOCGETDEF:
719 	    {
720 		struct buf	*bp;
721 		int		err, head;
722 		unsigned char	*secbuf;
723 		STRUCT_DECL(defect_header, adh);
724 
725 		STRUCT_INIT(adh, flag & FMODELS);
726 
727 		/*
728 		 * copyin header ....
729 		 * yields head number and buffer address
730 		 */
731 		if (ddi_copyin((caddr_t)arg, STRUCT_BUF(adh), STRUCT_SIZE(adh),
732 		    flag))
733 			return (EFAULT);
734 		head = STRUCT_FGET(adh, head);
735 		if (head < 0 || head >= dadkp->dad_phyg.g_head)
736 			return (ENXIO);
737 		secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
738 		if (!secbuf)
739 			return (ENOMEM);
740 		bp = getrbuf(KM_SLEEP);
741 		if (!bp) {
742 			kmem_free(secbuf, NBPSCTR);
743 			return (ENOMEM);
744 		}
745 
746 		bp->b_edev = dev;
747 		bp->b_dev  = cmpdev(dev);
748 		bp->b_flags = B_BUSY;
749 		bp->b_resid = 0;
750 		bp->b_bcount = NBPSCTR;
751 		bp->b_un.b_addr = (caddr_t)secbuf;
752 		bp->b_blkno = head; /* I had to put it somwhere! */
753 		bp->b_forw = (struct buf *)dadkp;
754 		bp->b_back = (struct buf *)DCMD_GETDEF;
755 
756 		FLC_ENQUE(dadkp->dad_flcobjp, bp);
757 		err = biowait(bp);
758 		if (!err) {
759 			if (ddi_copyout((caddr_t)secbuf,
760 			    STRUCT_FGETP(adh, buffer), NBPSCTR, flag))
761 				err = ENXIO;
762 		}
763 		kmem_free(secbuf, NBPSCTR);
764 		freerbuf(bp);
765 		return (err);
766 	    }
767 	case DIOCTL_RWCMD:
768 	    {
769 		struct dadkio_rwcmd *rwcmdp;
770 		int status, rw;
771 
772 		/*
773 		 * copied in by cmdk and, if necessary, converted to the
774 		 * correct datamodel
775 		 */
776 		rwcmdp = (struct dadkio_rwcmd *)(intptr_t)arg;
777 
778 		/*
779 		 * handle the complex cases here; we pass these
780 		 * through to the driver, which will queue them and
781 		 * handle the requests asynchronously.  The simpler
782 		 * cases ,which can return immediately, fail here, and
783 		 * the request reverts to the dadk_ioctl routine, while
784 		 *  will reroute them directly to the ata driver.
785 		 */
786 		switch (rwcmdp->cmd) {
787 			case DADKIO_RWCMD_READ :
788 				/*FALLTHROUGH*/
789 			case DADKIO_RWCMD_WRITE:
790 				rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ?
791 				    B_WRITE : B_READ);
792 				status = dadk_dk_buf_setup(dadkp,
793 				    (opaque_t)rwcmdp, dev, ((flag &FKIOCTL) ?
794 				    UIO_SYSSPACE : UIO_USERSPACE), rw);
795 				return (status);
796 			default:
797 				return (EINVAL);
798 		}
799 	    }
800 	case DKIOCFLUSHWRITECACHE:
801 		{
802 			struct buf *bp;
803 			int err = 0;
804 			struct dk_callback *dkc = (struct dk_callback *)arg;
805 			struct cmpkt *pktp;
806 			int is_sync = 1;
807 
808 			mutex_enter(&dadkp->dad_mutex);
809 			if (dadkp->dad_noflush || !  dadkp->dad_wce) {
810 				err = dadkp->dad_noflush ? ENOTSUP : 0;
811 				mutex_exit(&dadkp->dad_mutex);
812 				/*
813 				 * If a callback was requested: a
814 				 * callback will always be done if the
815 				 * caller saw the DKIOCFLUSHWRITECACHE
816 				 * ioctl return 0, and never done if the
817 				 * caller saw the ioctl return an error.
818 				 */
819 				if ((flag & FKIOCTL) && dkc != NULL &&
820 				    dkc->dkc_callback != NULL) {
821 					(*dkc->dkc_callback)(dkc->dkc_cookie,
822 					    err);
823 					/*
824 					 * Did callback and reported error.
825 					 * Since we did a callback, ioctl
826 					 * should return 0.
827 					 */
828 					err = 0;
829 				}
830 				return (err);
831 			}
832 			mutex_exit(&dadkp->dad_mutex);
833 
834 			bp = getrbuf(KM_SLEEP);
835 
836 			bp->b_edev = dev;
837 			bp->b_dev  = cmpdev(dev);
838 			bp->b_flags = B_BUSY;
839 			bp->b_resid = 0;
840 			bp->b_bcount = 0;
841 			SET_BP_SEC(bp, 0);
842 
843 			if ((flag & FKIOCTL) && dkc != NULL &&
844 			    dkc->dkc_callback != NULL) {
845 				struct dk_callback *dkc2 =
846 				    (struct dk_callback *)kmem_zalloc(
847 				    sizeof (struct dk_callback), KM_SLEEP);
848 
849 				bcopy(dkc, dkc2, sizeof (*dkc2));
850 				/*
851 				 * Borrow b_list to carry private data
852 				 * to the b_iodone func.
853 				 */
854 				bp->b_list = (struct buf *)dkc2;
855 				bp->b_iodone = dadk_flushdone;
856 				is_sync = 0;
857 			}
858 
859 			/*
860 			 * Setup command pkt
861 			 * dadk_pktprep() can't fail since DDI_DMA_SLEEP set
862 			 */
863 			pktp = dadk_pktprep(dadkp, NULL, bp,
864 			    dadk_iodone, DDI_DMA_SLEEP, NULL);
865 
866 			pktp->cp_time = DADK_FLUSH_CACHE_TIME;
867 
868 			*((char *)(pktp->cp_cdbp)) = DCMD_FLUSH_CACHE;
869 			pktp->cp_byteleft = 0;
870 			pktp->cp_private = NULL;
871 			pktp->cp_secleft = 0;
872 			pktp->cp_srtsec = -1;
873 			pktp->cp_bytexfer = 0;
874 
875 			CTL_IOSETUP(dadkp->dad_ctlobjp, pktp);
876 
877 			FLC_ENQUE(dadkp->dad_flcobjp, bp);
878 
879 			if (is_sync) {
880 				err = biowait(bp);
881 				freerbuf(bp);
882 			}
883 			return (err);
884 		}
885 	default:
886 		if (!dadkp->dad_rmb)
887 			return (CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag));
888 	}
889 
890 	switch (cmd) {
891 	case CDROMSTOP:
892 		return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0,
893 			0, DADK_SILENT));
894 	case CDROMSTART:
895 		return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0,
896 			0, DADK_SILENT));
897 	case DKIOCLOCK:
898 		return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT));
899 	case DKIOCUNLOCK:
900 		return (dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT));
901 	case DKIOCEJECT:
902 	case CDROMEJECT:
903 		{
904 			int ret;
905 
906 			if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0,
907 				DADK_SILENT)) {
908 				return (ret);
909 			}
910 			if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0,
911 				DADK_SILENT)) {
912 				return (ret);
913 			}
914 			mutex_enter(&dadkp->dad_mutex);
915 			dadkp->dad_iostate = DKIO_EJECTED;
916 			cv_broadcast(&dadkp->dad_state_cv);
917 			mutex_exit(&dadkp->dad_mutex);
918 
919 			return (0);
920 
921 		}
922 	default:
923 		return (ENOTTY);
924 	/*
925 	 * cdrom audio commands
926 	 */
927 	case CDROMPAUSE:
928 		cmd = DCMD_PAUSE;
929 		break;
930 	case CDROMRESUME:
931 		cmd = DCMD_RESUME;
932 		break;
933 	case CDROMPLAYMSF:
934 		cmd = DCMD_PLAYMSF;
935 		break;
936 	case CDROMPLAYTRKIND:
937 		cmd = DCMD_PLAYTRKIND;
938 		break;
939 	case CDROMREADTOCHDR:
940 		cmd = DCMD_READTOCHDR;
941 		break;
942 	case CDROMREADTOCENTRY:
943 		cmd = DCMD_READTOCENT;
944 		break;
945 	case CDROMVOLCTRL:
946 		cmd = DCMD_VOLCTRL;
947 		break;
948 	case CDROMSUBCHNL:
949 		cmd = DCMD_SUBCHNL;
950 		break;
951 	case CDROMREADMODE2:
952 		cmd = DCMD_READMODE2;
953 		break;
954 	case CDROMREADMODE1:
955 		cmd = DCMD_READMODE1;
956 		break;
957 	case CDROMREADOFFSET:
958 		cmd = DCMD_READOFFSET;
959 		break;
960 	}
961 	return (dadk_rmb_ioctl(dadkp, cmd, arg, flag, 0));
962 }
963 
964 int
965 dadk_flushdone(struct buf *bp)
966 {
967 	struct dk_callback *dkc = (struct dk_callback *)bp->b_list;
968 
969 	ASSERT(dkc != NULL && dkc->dkc_callback != NULL);
970 
971 	(*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp));
972 
973 	kmem_free(dkc, sizeof (*dkc));
974 	freerbuf(bp);
975 	return (0);
976 }
977 
978 int
979 dadk_getphygeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
980 {
981 	struct dadk *dadkp = (struct dadk *)objp;
982 
983 	bcopy((caddr_t)&dadkp->dad_phyg, (caddr_t)dkgeom_p,
984 	    sizeof (struct tgdk_geom));
985 	return (DDI_SUCCESS);
986 }
987 
988 int
989 dadk_getgeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
990 {
991 	struct dadk *dadkp = (struct dadk *)objp;
992 	bcopy((caddr_t)&dadkp->dad_logg, (caddr_t)dkgeom_p,
993 	    sizeof (struct tgdk_geom));
994 	return (DDI_SUCCESS);
995 }
996 
997 int
998 dadk_setgeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
999 {
1000 	struct dadk *dadkp = (struct dadk *)objp;
1001 
1002 	dadkp->dad_logg.g_cyl = dkgeom_p->g_cyl;
1003 	dadkp->dad_logg.g_head = dkgeom_p->g_head;
1004 	dadkp->dad_logg.g_sec = dkgeom_p->g_sec;
1005 	dadkp->dad_logg.g_cap = dkgeom_p->g_cap;
1006 	return (DDI_SUCCESS);
1007 }
1008 
1009 
1010 tgdk_iob_handle
1011 dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg)
1012 {
1013 	struct dadk *dadkp = (struct dadk *)objp;
1014 	struct buf *bp;
1015 	struct tgdk_iob *iobp;
1016 	size_t rlen;
1017 
1018 	iobp = kmem_zalloc(sizeof (*iobp), kmsflg);
1019 	if (iobp == NULL)
1020 		return (NULL);
1021 	if ((bp = getrbuf(kmsflg)) == NULL) {
1022 		kmem_free(iobp, sizeof (*iobp));
1023 		return (NULL);
1024 	}
1025 
1026 	iobp->b_psec  = LBLK2SEC(blkno, dadkp->dad_blkshf);
1027 	iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT;
1028 	iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1)
1029 				>> dadkp->dad_secshf) << dadkp->dad_secshf;
1030 
1031 	bp->b_un.b_addr = 0;
1032 	/*
1033 	 * use i_ddi_mem_alloc() for now until we have an interface to allocate
1034 	 * memory for DMA which doesn't require a DMA handle. ddi_iopb_alloc()
1035 	 * is obsolete and we want more flexibility in controlling the DMA
1036 	 * address constraints..
1037 	 */
1038 	if (i_ddi_mem_alloc((dadkp->dad_sd)->sd_dev, &dadk_alloc_attr,
1039 	    (size_t)iobp->b_pbytecnt, ((kmsflg == KM_SLEEP) ? 1 : 0), 0, NULL,
1040 	    &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
1041 		freerbuf(bp);
1042 		kmem_free(iobp, sizeof (*iobp));
1043 		return (NULL);
1044 	}
1045 	iobp->b_flag |= IOB_BPALLOC | IOB_BPBUFALLOC;
1046 	iobp->b_bp = bp;
1047 	iobp->b_lblk = blkno;
1048 	iobp->b_xfer = xfer;
1049 	iobp->b_lblk = blkno;
1050 	iobp->b_xfer = xfer;
1051 	return (iobp);
1052 }
1053 
1054 /* ARGSUSED */
1055 int
1056 dadk_iob_free(opaque_t objp, struct tgdk_iob *iobp)
1057 {
1058 	struct buf *bp;
1059 
1060 	if (iobp) {
1061 		if (iobp->b_bp && (iobp->b_flag & IOB_BPALLOC)) {
1062 			bp = iobp->b_bp;
1063 			if (bp->b_un.b_addr && (iobp->b_flag & IOB_BPBUFALLOC))
1064 				i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1065 			freerbuf(bp);
1066 		}
1067 		kmem_free(iobp, sizeof (*iobp));
1068 	}
1069 	return (DDI_SUCCESS);
1070 }
1071 
1072 /* ARGSUSED */
1073 caddr_t
1074 dadk_iob_htoc(opaque_t objp, struct tgdk_iob *iobp)
1075 {
1076 	return (iobp->b_bp->b_un.b_addr+iobp->b_pbyteoff);
1077 }
1078 
1079 
1080 caddr_t
1081 dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw)
1082 {
1083 	struct dadk	*dadkp = (struct dadk *)objp;
1084 	struct buf	*bp;
1085 	int		err;
1086 
1087 	bp = iobp->b_bp;
1088 	if (dadkp->dad_rdonly && !(rw & B_READ)) {
1089 		bioerror(bp, EROFS);
1090 		return (NULL);
1091 	}
1092 
1093 	bp->b_flags |= (B_BUSY | rw);
1094 	bp->b_bcount = iobp->b_pbytecnt;
1095 	SET_BP_SEC(bp, iobp->b_psec);
1096 	bp->av_back = (struct buf *)0;
1097 	bp->b_resid = 0;
1098 
1099 	/* call flow control */
1100 	FLC_ENQUE(dadkp->dad_flcobjp, bp);
1101 	err = biowait(bp);
1102 
1103 	bp->b_bcount = iobp->b_xfer;
1104 	bp->b_flags &= ~(B_DONE|B_BUSY);
1105 
1106 	if (err)
1107 		return (NULL);
1108 
1109 	return (bp->b_un.b_addr+iobp->b_pbyteoff);
1110 }
1111 
1112 static void
1113 dadk_transport(opaque_t com_data, struct buf *bp)
1114 {
1115 	struct dadk *dadkp = (struct dadk *)com_data;
1116 
1117 	if (CTL_TRANSPORT(dadkp->dad_ctlobjp, GDA_BP_PKT(bp)) ==
1118 	    CTL_SEND_SUCCESS)
1119 		return;
1120 	dadk_restart((void*)GDA_BP_PKT(bp));
1121 }
1122 
1123 static int
1124 dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg)
1125 {
1126 	struct cmpkt *pktp;
1127 	struct dadk *dadkp = (struct dadk *)com_data;
1128 
1129 	if (GDA_BP_PKT(bp))
1130 		return (DDI_SUCCESS);
1131 
1132 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, func, arg);
1133 	if (!pktp)
1134 		return (DDI_FAILURE);
1135 
1136 	return (dadk_ioprep(dadkp, pktp));
1137 }
1138 
1139 /*
1140  * Read, Write preparation
1141  */
1142 static int
1143 dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp)
1144 {
1145 	struct buf *bp;
1146 
1147 	bp = pktp->cp_bp;
1148 	if (bp->b_forw == (struct buf *)dadkp)
1149 		*((char *)(pktp->cp_cdbp)) = (char)(intptr_t)bp->b_back;
1150 
1151 	else if (bp->b_flags & B_READ)
1152 		*((char *)(pktp->cp_cdbp)) = DCMD_READ;
1153 	else
1154 		*((char *)(pktp->cp_cdbp)) = DCMD_WRITE;
1155 	pktp->cp_byteleft = bp->b_bcount;
1156 
1157 	/* setup the bad block list handle */
1158 	pktp->cp_private = BBH_GETHANDLE(dadkp->dad_bbhobjp, bp);
1159 	return (dadk_iosetup(dadkp, pktp));
1160 }
1161 
1162 static int
1163 dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp)
1164 {
1165 	struct buf	*bp;
1166 	bbh_cookie_t	bbhckp;
1167 	int		seccnt;
1168 
1169 	seccnt = pktp->cp_bytexfer >> dadkp->dad_secshf;
1170 	pktp->cp_secleft -= seccnt;
1171 
1172 	if (pktp->cp_secleft) {
1173 		pktp->cp_srtsec += seccnt;
1174 	} else {
1175 		/* get the first cookie from the bad block list */
1176 		if (!pktp->cp_private) {
1177 			bp = pktp->cp_bp;
1178 			pktp->cp_srtsec  = GET_BP_SEC(bp);
1179 			pktp->cp_secleft = (bp->b_bcount >> dadkp->dad_secshf);
1180 		} else {
1181 			bbhckp = BBH_HTOC(dadkp->dad_bbhobjp,
1182 			    pktp->cp_private);
1183 			pktp->cp_srtsec = BBH_GETCK_SECTOR(dadkp->dad_bbhobjp,
1184 			    bbhckp);
1185 			pktp->cp_secleft = BBH_GETCK_SECLEN(dadkp->dad_bbhobjp,
1186 			    bbhckp);
1187 		}
1188 	}
1189 
1190 	pktp->cp_bytexfer = pktp->cp_secleft << dadkp->dad_secshf;
1191 
1192 	if (CTL_IOSETUP(dadkp->dad_ctlobjp, pktp)) {
1193 		return (DDI_SUCCESS);
1194 	} else {
1195 		return (DDI_FAILURE);
1196 	}
1197 
1198 
1199 
1200 
1201 }
1202 
1203 static struct cmpkt *
1204 dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, struct buf *bp,
1205     void (*cb_func)(struct buf *), int (*func)(caddr_t), caddr_t arg)
1206 {
1207 	struct cmpkt *pktp;
1208 
1209 	pktp = gda_pktprep(dadkp->dad_ctlobjp, in_pktp, (opaque_t)bp, func,
1210 	    arg);
1211 
1212 	if (pktp) {
1213 		pktp->cp_callback = dadk_pktcb;
1214 		pktp->cp_time = DADK_IO_TIME;
1215 		pktp->cp_flags = 0;
1216 		pktp->cp_iodone = cb_func;
1217 		pktp->cp_dev_private = (opaque_t)dadkp;
1218 
1219 	}
1220 
1221 	return (pktp);
1222 }
1223 
1224 
1225 static void
1226 dadk_restart(void *vpktp)
1227 {
1228 	struct cmpkt *pktp = (struct cmpkt *)vpktp;
1229 
1230 	if (dadk_ioretry(pktp, QUE_COMMAND) == JUST_RETURN)
1231 		return;
1232 	pktp->cp_iodone(pktp->cp_bp);
1233 }
1234 
1235 static int
1236 dadk_ioretry(struct cmpkt *pktp, int action)
1237 {
1238 	struct buf *bp;
1239 	struct dadk *dadkp = PKT2DADK(pktp);
1240 
1241 	switch (action) {
1242 	case QUE_COMMAND:
1243 		if (pktp->cp_retry++ < DADK_RETRY_COUNT) {
1244 			CTL_IOSETUP(dadkp->dad_ctlobjp, pktp);
1245 			if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) ==
1246 				CTL_SEND_SUCCESS) {
1247 				return (JUST_RETURN);
1248 			}
1249 			gda_log(dadkp->dad_sd->sd_dev, dadk_name,
1250 				CE_WARN,
1251 				"transport of command fails\n");
1252 		} else
1253 			gda_log(dadkp->dad_sd->sd_dev,
1254 				dadk_name, CE_WARN,
1255 				"exceeds maximum number of retries\n");
1256 		bioerror(pktp->cp_bp, ENXIO);
1257 		/*FALLTHROUGH*/
1258 	case COMMAND_DONE_ERROR:
1259 		bp = pktp->cp_bp;
1260 		bp->b_resid += pktp->cp_byteleft - pktp->cp_bytexfer +
1261 		    pktp->cp_resid;
1262 		if (geterror(bp) == 0) {
1263 			if ((*((char *)(pktp->cp_cdbp)) == DCMD_FLUSH_CACHE) &&
1264 			    (pktp->cp_dev_private == (opaque_t)dadkp) &&
1265 			    ((int)(*(char *)pktp->cp_scbp) == DERR_ABORT)) {
1266 				/*
1267 				 * Flag "unimplemented" responses for
1268 				 * DCMD_FLUSH_CACHE as ENOTSUP
1269 				 */
1270 				bioerror(bp, ENOTSUP);
1271 				mutex_enter(&dadkp->dad_mutex);
1272 				dadkp->dad_noflush = 1;
1273 				mutex_exit(&dadkp->dad_mutex);
1274 			} else {
1275 				bioerror(bp, EIO);
1276 			}
1277 		}
1278 		/*FALLTHROUGH*/
1279 	case COMMAND_DONE:
1280 	default:
1281 		return (COMMAND_DONE);
1282 	}
1283 }
1284 
1285 
1286 static void
1287 dadk_pktcb(struct cmpkt *pktp)
1288 {
1289 	int action;
1290 	struct dadkio_rwcmd *rwcmdp;
1291 
1292 	rwcmdp = (struct dadkio_rwcmd *)pktp->cp_passthru;  /* ioctl packet */
1293 
1294 	if (pktp->cp_reason == CPS_SUCCESS) {
1295 		if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT))
1296 			rwcmdp->status.status = DADKIO_STAT_NO_ERROR;
1297 		pktp->cp_iodone(pktp->cp_bp);
1298 		return;
1299 	}
1300 
1301 	if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) {
1302 		if (pktp->cp_reason == CPS_CHKERR)
1303 			dadk_recorderr(pktp, rwcmdp);
1304 		dadk_iodone(pktp->cp_bp);
1305 		return;
1306 	}
1307 
1308 	if (pktp->cp_reason == CPS_CHKERR)
1309 		action = dadk_chkerr(pktp);
1310 	else
1311 		action = COMMAND_DONE_ERROR;
1312 
1313 	if (action == JUST_RETURN)
1314 		return;
1315 
1316 	if (action != COMMAND_DONE) {
1317 		if ((dadk_ioretry(pktp, action)) == JUST_RETURN)
1318 			return;
1319 	}
1320 	pktp->cp_iodone(pktp->cp_bp);
1321 }
1322 
1323 
1324 
1325 static struct dadkio_derr dadk_errtab[] = {
1326 	{COMMAND_DONE, GDA_INFORMATIONAL},	/*  0 DERR_SUCCESS	*/
1327 	{QUE_COMMAND, GDA_FATAL},		/*  1 DERR_AMNF		*/
1328 	{QUE_COMMAND, GDA_FATAL},		/*  2 DERR_TKONF	*/
1329 	{COMMAND_DONE_ERROR, GDA_INFORMATIONAL}, /* 3 DERR_ABORT	*/
1330 	{QUE_COMMAND, GDA_RETRYABLE},		/*  4 DERR_DWF		*/
1331 	{QUE_COMMAND, GDA_FATAL},		/*  5 DERR_IDNF		*/
1332 	{JUST_RETURN, GDA_INFORMATIONAL},	/*  6 DERR_BUSY		*/
1333 	{QUE_COMMAND, GDA_FATAL},		/*  7 DERR_UNC		*/
1334 	{QUE_COMMAND, GDA_RETRYABLE},		/*  8 DERR_BBK		*/
1335 	{COMMAND_DONE_ERROR, GDA_FATAL},	/*  9 DERR_INVCDB	*/
1336 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 10 DERR_HARD		*/
1337 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 11 DERR_ILI		*/
1338 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 12 DERR_EOM		*/
1339 	{COMMAND_DONE, GDA_INFORMATIONAL},	/* 13 DERR_MCR		*/
1340 	{COMMAND_DONE, GDA_INFORMATIONAL},	/* 14 DERR_RECOVER	*/
1341 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 15 DERR_NOTREADY	*/
1342 	{QUE_COMMAND, GDA_RETRYABLE},		/* 16 DERR_MEDIUM	*/
1343 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 17 DERR_HW		*/
1344 	{COMMAND_DONE, GDA_FATAL},		/* 18 DERR_ILL		*/
1345 	{COMMAND_DONE, GDA_FATAL},		/* 19 DERR_UNIT_ATTN	*/
1346 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 20 DERR_DATA_PROT	*/
1347 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 21 DERR_MISCOMPARE	*/
1348 	{QUE_COMMAND, GDA_RETRYABLE},		/* 22 DERR_ICRC		*/
1349 	{COMMAND_DONE_ERROR, GDA_FATAL},	/* 23 DERR_RESV		*/
1350 };
1351 
1352 static int
1353 dadk_chkerr(struct cmpkt *pktp)
1354 {
1355 	int err_blkno;
1356 	struct dadk *dadkp = PKT2DADK(pktp);
1357 	struct dadk_errstats *dep;
1358 	int scb = *(char *)pktp->cp_scbp;
1359 	int action;
1360 
1361 	if (scb == DERR_SUCCESS) {
1362 		if (pktp->cp_retry != 0 && dadkp->dad_errstats != NULL) {
1363 			dep = (struct dadk_errstats *)
1364 			    dadkp->dad_errstats->ks_data;
1365 			dep->dadk_rq_recov_err.value.ui32++;
1366 		}
1367 		return (COMMAND_DONE);
1368 	}
1369 
1370 	/* check error code table */
1371 	action = dadk_errtab[scb].d_action;
1372 
1373 	if (pktp->cp_retry) {
1374 		err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer -
1375 			pktp->cp_resid) >> dadkp->dad_secshf);
1376 	} else
1377 		err_blkno = -1;
1378 
1379 	if (dadkp->dad_errstats != NULL) {
1380 		dep = (struct dadk_errstats *)dadkp->dad_errstats->ks_data;
1381 
1382 		if (action == GDA_RETRYABLE)
1383 			dep->dadk_softerrs.value.ui32++;
1384 		else if (action == GDA_FATAL)
1385 			dep->dadk_harderrs.value.ui32++;
1386 
1387 		switch (scb) {
1388 			case DERR_INVCDB:
1389 			case DERR_ILI:
1390 			case DERR_EOM:
1391 			case DERR_HW:
1392 			case DERR_ICRC:
1393 				dep->dadk_transerrs.value.ui32++;
1394 				break;
1395 
1396 			case DERR_AMNF:
1397 			case DERR_TKONF:
1398 			case DERR_DWF:
1399 			case DERR_BBK:
1400 			case DERR_UNC:
1401 			case DERR_HARD:
1402 			case DERR_MEDIUM:
1403 			case DERR_DATA_PROT:
1404 			case DERR_MISCOMP:
1405 				dep->dadk_rq_media_err.value.ui32++;
1406 				break;
1407 
1408 			case DERR_NOTREADY:
1409 				dep->dadk_rq_ntrdy_err.value.ui32++;
1410 				break;
1411 
1412 			case DERR_IDNF:
1413 			case DERR_UNIT_ATTN:
1414 				dep->dadk_rq_nodev_err.value.ui32++;
1415 				break;
1416 
1417 			case DERR_ILL:
1418 			case DERR_RESV:
1419 				dep->dadk_rq_illrq_err.value.ui32++;
1420 				break;
1421 		}
1422 	}
1423 
1424 	/* if attempting to read a sector from a cdrom audio disk */
1425 	if ((dadkp->dad_cdrom) &&
1426 	    (*((char *)(pktp->cp_cdbp)) == DCMD_READ) &&
1427 	    (scb == DERR_ILL)) {
1428 		return (COMMAND_DONE);
1429 	}
1430 	if (pktp->cp_passthru == NULL) {
1431 		gda_errmsg(dadkp->dad_sd, pktp, dadk_name,
1432 		    dadk_errtab[scb].d_severity, pktp->cp_srtsec,
1433 		    err_blkno, dadk_cmds, dadk_sense);
1434 	}
1435 
1436 	if (scb == DERR_BUSY) {
1437 		(void) timeout(dadk_restart, (void *)pktp, DADK_BSY_TIMEOUT);
1438 	}
1439 
1440 	return (action);
1441 }
1442 
1443 static void
1444 dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp)
1445 {
1446 	struct dadk *dadkp;
1447 	int scb;
1448 
1449 	dadkp = PKT2DADK(pktp);
1450 	scb = (int)(*(char *)pktp->cp_scbp);
1451 
1452 
1453 	rwcmdp->status.failed_blk = rwcmdp->blkaddr +
1454 		((pktp->cp_bytexfer -
1455 		pktp->cp_resid) >> dadkp->dad_secshf);
1456 
1457 	rwcmdp->status.resid = pktp->cp_bp->b_resid +
1458 		pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid;
1459 	switch ((int)(* (char *)pktp->cp_scbp)) {
1460 	case DERR_AMNF:
1461 	case DERR_ABORT:
1462 		rwcmdp->status.status = DADKIO_STAT_ILLEGAL_REQUEST;
1463 		break;
1464 	case DERR_DWF:
1465 	case DERR_IDNF:
1466 		rwcmdp->status.status = DADKIO_STAT_ILLEGAL_ADDRESS;
1467 		break;
1468 	case DERR_TKONF:
1469 	case DERR_UNC:
1470 	case DERR_BBK:
1471 		rwcmdp->status.status = DADKIO_STAT_MEDIUM_ERROR;
1472 		rwcmdp->status.failed_blk_is_valid = 1;
1473 		rwcmdp->status.resid = 0;
1474 		break;
1475 	case DERR_BUSY:
1476 		rwcmdp->status.status = DADKIO_STAT_NOT_READY;
1477 		break;
1478 	case DERR_INVCDB:
1479 	case DERR_HARD:
1480 		rwcmdp->status.status = DADKIO_STAT_HARDWARE_ERROR;
1481 		break;
1482 	case DERR_ICRC:
1483 	default:
1484 		rwcmdp->status.status = DADKIO_STAT_NOT_SUPPORTED;
1485 	}
1486 
1487 	if (rwcmdp->flags & DADKIO_FLAG_SILENT)
1488 		return;
1489 	gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity,
1490 		rwcmdp->blkaddr, rwcmdp->status.failed_blk,
1491 		dadk_cmds, dadk_sense);
1492 }
1493 
1494 /*ARGSUSED*/
1495 static void
1496 dadk_polldone(struct buf *bp)
1497 {
1498 }
1499 
1500 static void
1501 dadk_iodone(struct buf *bp)
1502 {
1503 	struct cmpkt *pktp;
1504 	struct dadk *dadkp;
1505 
1506 	pktp  = GDA_BP_PKT(bp);
1507 	dadkp = PKT2DADK(pktp);
1508 
1509 	/* check for all iodone */
1510 	pktp->cp_byteleft -= pktp->cp_bytexfer;
1511 	if (geterror(bp) == 0 && pktp->cp_byteleft != 0) {
1512 		pktp->cp_retry = 0;
1513 		(void) dadk_iosetup(dadkp, pktp);
1514 
1515 
1516 	/* 	transport the next one */
1517 		if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == CTL_SEND_SUCCESS)
1518 			return;
1519 		if ((dadk_ioretry(pktp, QUE_COMMAND)) == JUST_RETURN)
1520 			return;
1521 	}
1522 
1523 	/* start next one */
1524 	FLC_DEQUE(dadkp->dad_flcobjp, bp);
1525 
1526 	/* free pkt */
1527 	if (pktp->cp_private)
1528 		BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private);
1529 	gda_free(dadkp->dad_ctlobjp, pktp, NULL);
1530 	biodone(bp);
1531 }
1532 
1533 int
1534 dadk_check_media(opaque_t objp, int *state)
1535 {
1536 	struct dadk *dadkp = (struct dadk *)objp;
1537 
1538 	if (!dadkp->dad_rmb) {
1539 		return (ENXIO);
1540 	}
1541 #ifdef DADK_DEBUG
1542 	if (dadk_debug & DSTATE)
1543 		PRF("dadk_check_media: user state %x disk state %x\n",
1544 			*state, dadkp->dad_iostate);
1545 #endif
1546 	/*
1547 	 * If state already changed just return
1548 	 */
1549 	if (*state != dadkp->dad_iostate) {
1550 		*state = dadkp->dad_iostate;
1551 		return (0);
1552 	}
1553 
1554 	/*
1555 	 * Startup polling on thread state
1556 	 */
1557 	mutex_enter(&dadkp->dad_mutex);
1558 	if (dadkp->dad_thread_cnt == 0) {
1559 		/*
1560 		 * One thread per removable dadk device
1561 		 */
1562 		(void) thread_create(NULL, 0, dadk_watch_thread, dadkp, 0, &p0,
1563 		    TS_RUN, v.v_maxsyspri - 2);
1564 	}
1565 	dadkp->dad_thread_cnt++;
1566 
1567 	/*
1568 	 * Wait for state to change
1569 	 */
1570 	do {
1571 		if (cv_wait_sig(&dadkp->dad_state_cv, &dadkp->dad_mutex) == 0) {
1572 			dadkp->dad_thread_cnt--;
1573 			mutex_exit(&dadkp->dad_mutex);
1574 			return (EINTR);
1575 		}
1576 	} while (*state == dadkp->dad_iostate);
1577 	*state = dadkp->dad_iostate;
1578 	dadkp->dad_thread_cnt--;
1579 	mutex_exit(&dadkp->dad_mutex);
1580 	return (0);
1581 }
1582 
1583 
1584 #define	MEDIA_ACCESS_DELAY 2000000
1585 
1586 static void
1587 dadk_watch_thread(struct dadk *dadkp)
1588 {
1589 	enum dkio_state state;
1590 	int interval;
1591 
1592 	interval = drv_usectohz(dadk_check_media_time);
1593 
1594 	do {
1595 		if (dadk_rmb_ioctl(dadkp, DCMD_GET_STATE, (intptr_t)&state, 0,
1596 		    DADK_SILENT)) {
1597 			/*
1598 			 * Assume state remained the same
1599 			 */
1600 			state = dadkp->dad_iostate;
1601 		}
1602 
1603 		/*
1604 		 * now signal the waiting thread if this is *not* the
1605 		 * specified state;
1606 		 * delay the signal if the state is DKIO_INSERTED
1607 		 * to allow the target to recover
1608 		 */
1609 		if (state != dadkp->dad_iostate) {
1610 
1611 			dadkp->dad_iostate = state;
1612 			if (state == DKIO_INSERTED) {
1613 				/*
1614 				 * delay the signal to give the drive a chance
1615 				 * to do what it apparently needs to do
1616 				 */
1617 				(void) timeout((void(*)(void *))cv_broadcast,
1618 				    (void *)&dadkp->dad_state_cv,
1619 				    drv_usectohz((clock_t)MEDIA_ACCESS_DELAY));
1620 			} else {
1621 				cv_broadcast(&dadkp->dad_state_cv);
1622 			}
1623 		}
1624 		delay(interval);
1625 	} while (dadkp->dad_thread_cnt);
1626 }
1627 
1628 int
1629 dadk_inquiry(opaque_t objp, opaque_t *inqpp)
1630 {
1631 	struct dadk *dadkp = (struct dadk *)objp;
1632 	struct scsi_inquiry **sinqpp = (struct scsi_inquiry **)inqpp;
1633 
1634 	if (dadkp && dadkp->dad_sd && dadkp->dad_sd->sd_inq) {
1635 		*sinqpp = dadkp->dad_sd->sd_inq;
1636 		return (DDI_SUCCESS);
1637 	}
1638 
1639 	return (DDI_FAILURE);
1640 }
1641 
1642 static int
1643 dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent)
1644 
1645 {
1646 	struct buf *bp;
1647 	int err;
1648 	struct cmpkt *pktp;
1649 
1650 	if ((bp = getrbuf(KM_SLEEP)) == NULL) {
1651 		return (ENOMEM);
1652 	}
1653 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_rmb_iodone, NULL, NULL);
1654 	if (!pktp) {
1655 		freerbuf(bp);
1656 		return (ENOMEM);
1657 	}
1658 	bp->b_back  = (struct buf *)arg;
1659 	bp->b_forw  = (struct buf *)dadkp->dad_flcobjp;
1660 	pktp->cp_passthru = (opaque_t)(intptr_t)silent;
1661 
1662 	err = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, (uintptr_t)pktp, flags);
1663 	freerbuf(bp);
1664 	gda_free(dadkp->dad_ctlobjp, pktp, NULL);
1665 	return (err);
1666 
1667 
1668 }
1669 
1670 static void
1671 dadk_rmb_iodone(struct buf *bp)
1672 {
1673 	struct cmpkt *pktp;
1674 	struct dadk *dadkp;
1675 
1676 	pktp  = GDA_BP_PKT(bp);
1677 	dadkp = PKT2DADK(pktp);
1678 
1679 	bp->b_flags &= ~(B_DONE|B_BUSY);
1680 
1681 	/* Start next one */
1682 	FLC_DEQUE(dadkp->dad_flcobjp, bp);
1683 
1684 	biodone(bp);
1685 }
1686 
1687 static int
1688 dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, dev_t dev,
1689 	enum uio_seg dataspace, int rw)
1690 {
1691 	struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp;
1692 	struct buf	*bp;
1693 	struct iovec	aiov;
1694 	struct uio	auio;
1695 	struct uio	*uio = &auio;
1696 	int		status;
1697 
1698 	bp = getrbuf(KM_SLEEP);
1699 
1700 	bp->av_forw = bp->b_forw = (struct buf *)dadkp;
1701 	bp->b_back  = (struct buf *)rwcmdp;	/* ioctl packet */
1702 
1703 	bzero((caddr_t)&auio, sizeof (struct uio));
1704 	bzero((caddr_t)&aiov, sizeof (struct iovec));
1705 	aiov.iov_base = rwcmdp->bufaddr;
1706 	aiov.iov_len = rwcmdp->buflen;
1707 	uio->uio_iov = &aiov;
1708 
1709 	uio->uio_iovcnt = 1;
1710 	uio->uio_resid = rwcmdp->buflen;
1711 	uio->uio_segflg = dataspace;
1712 
1713 	/* Let physio do the rest... */
1714 	status = physio(dadk_dk_strategy, bp, dev, rw, dadkmin, uio);
1715 
1716 	freerbuf(bp);
1717 	return (status);
1718 
1719 }
1720 
1721 /* Do not let a user gendisk request get too big or */
1722 /* else we could use to many resources.		    */
1723 
1724 static void
1725 dadkmin(struct buf *bp)
1726 {
1727 	if (bp->b_bcount > dadk_dk_maxphys)
1728 		bp->b_bcount = dadk_dk_maxphys;
1729 }
1730 
1731 static int
1732 dadk_dk_strategy(struct buf *bp)
1733 {
1734 	dadk_dk((struct dadk *)bp->av_forw, (struct dadkio_rwcmd *)bp->b_back,
1735 	    bp);
1736 	return (0);
1737 }
1738 
1739 static void
1740 dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp)
1741 {
1742 	struct  cmpkt *pktp;
1743 
1744 	pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, NULL, NULL);
1745 	if (!pktp) {
1746 		bioerror(bp, ENOMEM);
1747 		biodone(bp);
1748 		return;
1749 	}
1750 
1751 	pktp->cp_passthru = rwcmdp;
1752 
1753 	(void) dadk_ioprep(dadkp, pktp);
1754 
1755 	FLC_ENQUE(dadkp->dad_flcobjp, bp);
1756 }
1757