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