xref: /illumos-gate/usr/src/uts/common/io/1394/targets/scsa1394/hba.c (revision 89b2a9fbeabf42fa54594df0e5927bcc50a07cc9)
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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * 1394 mass storage HBA driver
29  */
30 
31 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/cred.h>
34 #include <sys/conf.h>
35 #include <sys/modctl.h>
36 #include <sys/stat.h>
37 #include <sys/byteorder.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 
41 #include <sys/1394/targets/scsa1394/impl.h>
42 #include <sys/1394/targets/scsa1394/cmd.h>
43 
44 /* DDI/DKI entry points */
45 static int	scsa1394_attach(dev_info_t *, ddi_attach_cmd_t);
46 static int	scsa1394_detach(dev_info_t *, ddi_detach_cmd_t);
47 static int	scsa1394_power(dev_info_t *, int, int);
48 static int	scsa1394_cpr_suspend(dev_info_t *);
49 static void	scsa1394_cpr_resume(dev_info_t *);
50 
51 /* configuration routines */
52 static void	scsa1394_cleanup(scsa1394_state_t *, int);
53 static int	scsa1394_attach_1394(scsa1394_state_t *);
54 static void	scsa1394_detach_1394(scsa1394_state_t *);
55 static int	scsa1394_attach_threads(scsa1394_state_t *);
56 static void	scsa1394_detach_threads(scsa1394_state_t *);
57 static int	scsa1394_attach_scsa(scsa1394_state_t *);
58 static void	scsa1394_detach_scsa(scsa1394_state_t *);
59 static int	scsa1394_create_cmd_cache(scsa1394_state_t *);
60 static void	scsa1394_destroy_cmd_cache(scsa1394_state_t *);
61 static int	scsa1394_add_events(scsa1394_state_t *);
62 static void	scsa1394_remove_events(scsa1394_state_t *);
63 
64 /* device configuration */
65 static int	scsa1394_scsi_bus_config(dev_info_t *, uint_t,
66 		ddi_bus_config_op_t, void *, dev_info_t **);
67 static int	scsa1394_scsi_bus_unconfig(dev_info_t *, uint_t,
68 		ddi_bus_config_op_t, void *);
69 static void	scsa1394_create_children(scsa1394_state_t *);
70 static void	scsa1394_bus_reset(dev_info_t *, ddi_eventcookie_t, void *,
71 		void *);
72 static void	scsa1394_disconnect(dev_info_t *, ddi_eventcookie_t, void *,
73 		void *);
74 static void	scsa1394_reconnect(dev_info_t *, ddi_eventcookie_t, void *,
75 		void *);
76 
77 /* SCSA HBA entry points */
78 static int	scsa1394_scsi_tgt_init(dev_info_t *, dev_info_t *,
79 		scsi_hba_tran_t *, struct scsi_device *);
80 static void	scsa1394_scsi_tgt_free(dev_info_t *, dev_info_t *,
81 		scsi_hba_tran_t *, struct scsi_device *);
82 static int	scsa1394_scsi_tgt_probe(struct scsi_device *, int (*)());
83 static int	scsa1394_probe_g0_nodata(struct scsi_device *, int (*)(),
84 		uchar_t, uint_t, uint_t);
85 static int	scsa1394_probe_tran(struct scsi_pkt *);
86 static struct scsi_pkt *scsa1394_scsi_init_pkt(struct scsi_address *,
87 		struct scsi_pkt *, struct buf *, int, int, int, int,
88 		int (*)(), caddr_t arg);
89 static void	scsa1394_scsi_destroy_pkt(struct scsi_address *,
90 		struct scsi_pkt *);
91 static int	scsa1394_scsi_start(struct scsi_address *, struct scsi_pkt *);
92 static int	scsa1394_scsi_abort(struct scsi_address *, struct scsi_pkt *);
93 static int	scsa1394_scsi_reset(struct scsi_address *, int);
94 static int	scsa1394_scsi_getcap(struct scsi_address *, char *, int);
95 static int	scsa1394_scsi_setcap(struct scsi_address *, char *, int, int);
96 static void	scsa1394_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
97 static void	scsa1394_scsi_sync_pkt(struct scsi_address *,
98 		struct scsi_pkt *);
99 
100 /* pkt resource allocation routines */
101 static int	scsa1394_cmd_cache_constructor(void *, void *, int);
102 static void	scsa1394_cmd_cache_destructor(void *, void *);
103 static int	scsa1394_cmd_ext_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
104 		int);
105 static void	scsa1394_cmd_ext_free(scsa1394_state_t *, scsa1394_cmd_t *);
106 static int	scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
107 		int, int (*)(), caddr_t);
108 static void	scsa1394_cmd_cdb_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
109 static int	scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
110 		int, int (*)(), caddr_t, struct buf *);
111 static void	scsa1394_cmd_buf_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
112 static int	scsa1394_cmd_dmac2seg(scsa1394_state_t *, scsa1394_cmd_t *,
113 		ddi_dma_cookie_t *, uint_t, int);
114 static void	scsa1394_cmd_seg_free(scsa1394_state_t *, scsa1394_cmd_t *);
115 static int	scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
116 		int (*)(), caddr_t, int);
117 static void	scsa1394_cmd_pt_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
118 static int	scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *,
119 		scsa1394_cmd_t *);
120 static void	scsa1394_cmd_buf_addr_free(scsa1394_state_t *,
121 		scsa1394_cmd_t *);
122 static int	scsa1394_cmd_buf_dma_move(scsa1394_state_t *, scsa1394_cmd_t *);
123 
124 
125 /* pkt and data transfer routines */
126 static void	scsa1394_prepare_pkt(scsa1394_state_t *, struct scsi_pkt *);
127 static void	scsa1394_cmd_fill_cdb(scsa1394_lun_t *, scsa1394_cmd_t *);
128 static void	scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *, scsa1394_cmd_t *);
129 static void	scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *, scsa1394_cmd_t *);
130 static void	scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *, int);
131 static void	scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *, int);
132 static void	scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *, int);
133 static void	scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *, int);
134 static int	scsa1394_cmd_read_cd_blk_size(uchar_t);
135 static int	scsa1394_cmd_fake_mode_sense(scsa1394_state_t *,
136 		scsa1394_cmd_t *);
137 static int	scsa1394_cmd_fake_inquiry(scsa1394_state_t *, scsa1394_cmd_t *);
138 static int	scsa1394_cmd_fake_comp(scsa1394_state_t *, scsa1394_cmd_t *);
139 static int	scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *,
140 		scsa1394_cmd_t *);
141 static void	scsa1394_cmd_adjust_cdb(scsa1394_lun_t *, scsa1394_cmd_t *);
142 static void	scsa1394_cmd_status_wrka(scsa1394_lun_t *, scsa1394_cmd_t *);
143 
144 /* other routines */
145 static boolean_t scsa1394_is_my_child(dev_info_t *);
146 static void *	scsa1394_kmem_realloc(void *, int, int, size_t, int);
147 
148 static void	*scsa1394_statep;
149 #define	SCSA1394_INST2STATE(inst) (ddi_get_soft_state(scsa1394_statep, inst))
150 
151 static struct cb_ops scsa1394_cb_ops = {
152 	nodev,			/* open */
153 	nodev,			/* close */
154 	nodev,			/* strategy */
155 	nodev,			/* print */
156 	nodev,			/* dump */
157 	nodev,			/* read */
158 	nodev,			/* write */
159 	NULL,			/* ioctl */
160 	nodev,			/* devmap */
161 	nodev,			/* mmap */
162 	nodev,			/* segmap */
163 	nochpoll,		/* poll */
164 	ddi_prop_op,		/* prop_op */
165 	NULL,			/* stream */
166 	D_MP,			/* cb_flag */
167 	CB_REV,			/* rev */
168 	nodev,			/* aread */
169 	nodev			/* awrite */
170 };
171 
172 static struct dev_ops scsa1394_ops = {
173 	DEVO_REV,		/* devo_rev, */
174 	0,			/* refcnt  */
175 	ddi_no_info,		/* info */
176 	nulldev,		/* identify */
177 	nulldev,		/* probe */
178 	scsa1394_attach,	/* attach */
179 	scsa1394_detach,	/* detach */
180 	nodev,			/* reset */
181 	&scsa1394_cb_ops,	/* driver operations */
182 	NULL,			/* bus operations */
183 	scsa1394_power,		/* power */
184 	ddi_quiesce_not_supported,	/* devo_quiesce */
185 };
186 
187 static struct modldrv scsa1394_modldrv = {
188 	&mod_driverops,			/* module type */
189 	"1394 Mass Storage HBA Driver", /* name of the module */
190 	&scsa1394_ops,			/* driver ops */
191 };
192 
193 static struct modlinkage scsa1394_modlinkage = {
194 	MODREV_1, (void *)&scsa1394_modldrv, NULL
195 };
196 
197 /* tunables */
198 int scsa1394_bus_config_debug = 0;
199 int scsa1394_start_stop_fail_max = SCSA1394_START_STOP_FAIL_MAX;
200 int scsa1394_mode_sense_fail_max = SCSA1394_MODE_SENSE_FAIL_MAX;
201 int scsa1394_start_stop_timeout_max = SCSA1394_START_STOP_TIMEOUT_MAX;
202 
203 /* workarounds */
204 int scsa1394_wrka_rbc2direct = 1;
205 int scsa1394_wrka_fake_rmb = 0;
206 int scsa1394_wrka_fake_prin = 1;
207 
208 int scsa1394_wrka_symbios = 1;
209 int scsa1394_symbios_page_size = 4 * 1024;	/* must be <= _pagesize */
210 int scsa1394_symbios_size_max = 512 * 248;	/* multiple of page size */
211 
212 /*
213  *
214  * --- DDI/DKI entry points
215  *
216  */
217 int
218 _init(void)
219 {
220 	int	ret;
221 
222 	if (((ret = ddi_soft_state_init(&scsa1394_statep,
223 	    sizeof (scsa1394_state_t), 1)) != 0)) {
224 		return (ret);
225 	}
226 
227 	if ((ret = scsi_hba_init(&scsa1394_modlinkage)) != 0) {
228 		ddi_soft_state_fini(&scsa1394_statep);
229 		return (ret);
230 	}
231 
232 	if ((ret = mod_install(&scsa1394_modlinkage)) != 0) {
233 		scsi_hba_fini(&scsa1394_modlinkage);
234 		ddi_soft_state_fini(&scsa1394_statep);
235 		return (ret);
236 	}
237 
238 	return (ret);
239 }
240 
241 int
242 _fini(void)
243 {
244 	int	ret;
245 
246 	if ((ret = mod_remove(&scsa1394_modlinkage)) == 0) {
247 		scsi_hba_fini(&scsa1394_modlinkage);
248 		ddi_soft_state_fini(&scsa1394_statep);
249 	}
250 
251 	return (ret);
252 }
253 
254 int
255 _info(struct modinfo *modinfop)
256 {
257 	return (mod_info(&scsa1394_modlinkage, modinfop));
258 }
259 
260 static int
261 scsa1394_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
262 {
263 	int		instance = ddi_get_instance(dip);
264 	scsa1394_state_t *sp;
265 
266 	switch (cmd) {
267 	case DDI_ATTACH:
268 		break;
269 	case DDI_RESUME:
270 		scsa1394_cpr_resume(dip);
271 		return (DDI_SUCCESS);
272 	default:
273 		return (DDI_FAILURE);
274 	}
275 
276 	if (ddi_soft_state_zalloc(scsa1394_statep, instance) != 0) {
277 		return (DDI_FAILURE);
278 	}
279 	sp = SCSA1394_INST2STATE(instance);
280 
281 #ifndef __lock_lint
282 	sp->s_dip = dip;
283 	sp->s_instance = instance;
284 #endif
285 	mutex_init(&sp->s_mutex, NULL, MUTEX_DRIVER,
286 	    sp->s_attachinfo.iblock_cookie);
287 	cv_init(&sp->s_event_cv, NULL, CV_DRIVER, NULL);
288 
289 	if (scsa1394_attach_1394(sp) != DDI_SUCCESS) {
290 		scsa1394_cleanup(sp, 1);
291 		return (DDI_FAILURE);
292 	}
293 
294 	if (scsa1394_sbp2_attach(sp) != DDI_SUCCESS) {
295 		scsa1394_cleanup(sp, 2);
296 		return (DDI_FAILURE);
297 	}
298 
299 	if (scsa1394_attach_threads(sp) != DDI_SUCCESS) {
300 		scsa1394_cleanup(sp, 3);
301 		return (DDI_FAILURE);
302 	}
303 
304 	if (scsa1394_attach_scsa(sp) != DDI_SUCCESS) {
305 		scsa1394_cleanup(sp, 4);
306 		return (DDI_FAILURE);
307 	}
308 
309 	if (scsa1394_create_cmd_cache(sp) != DDI_SUCCESS) {
310 		scsa1394_cleanup(sp, 5);
311 		return (DDI_FAILURE);
312 	}
313 
314 	if (scsa1394_add_events(sp) != DDI_SUCCESS) {
315 		scsa1394_cleanup(sp, 6);
316 		return (DDI_FAILURE);
317 	}
318 
319 	/* prevent async PM changes until we are done */
320 	(void) pm_busy_component(dip, 0);
321 
322 	/* Set power to full on */
323 	(void) pm_raise_power(dip, 0, PM_LEVEL_D0);
324 
325 	/* we are done */
326 	(void) pm_idle_component(dip, 0);
327 
328 #ifndef __lock_lint
329 	sp->s_dev_state = SCSA1394_DEV_ONLINE;
330 #endif
331 
332 	ddi_report_dev(dip);
333 
334 	return (DDI_SUCCESS);
335 }
336 
337 static int
338 scsa1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
339 {
340 	int		instance = ddi_get_instance(dip);
341 	scsa1394_state_t *sp;
342 
343 	if ((sp = SCSA1394_INST2STATE(instance)) == NULL) {
344 		return (DDI_FAILURE);
345 	}
346 
347 	switch (cmd) {
348 	case DDI_DETACH:
349 		/* Cycle power state to off and idle  where done/gone */
350 		(void) pm_lower_power(dip, 0, PM_LEVEL_D3);
351 
352 		scsa1394_cleanup(sp, SCSA1394_CLEANUP_LEVEL_MAX);
353 		return (DDI_SUCCESS);
354 	case DDI_SUSPEND:
355 		return (scsa1394_cpr_suspend(dip));
356 	default:
357 		return (DDI_FAILURE);
358 	}
359 }
360 
361 /*ARGSUSED*/
362 static int
363 scsa1394_power(dev_info_t *dip, int comp, int level)
364 {
365 	return (DDI_SUCCESS);
366 }
367 
368 /*
369  * scsa1394_cpr_suspend
370  *	determine if the device's state can be changed to SUSPENDED
371  */
372 /* ARGSUSED */
373 static int
374 scsa1394_cpr_suspend(dev_info_t *dip)
375 {
376 	int		instance = ddi_get_instance(dip);
377 	scsa1394_state_t *sp;
378 	int		rval = DDI_FAILURE;
379 
380 	sp = SCSA1394_INST2STATE(instance);
381 
382 	ASSERT(sp != NULL);
383 
384 
385 	mutex_enter(&sp->s_mutex);
386 	switch (sp->s_dev_state) {
387 	case SCSA1394_DEV_ONLINE:
388 	case SCSA1394_DEV_PWRED_DOWN:
389 	case SCSA1394_DEV_DISCONNECTED:
390 		sp->s_dev_state = SCSA1394_DEV_SUSPENDED;
391 
392 		/*  Power down and make device idle */
393 		(void) pm_lower_power(dip, 0, PM_LEVEL_D3);
394 
395 		rval = DDI_SUCCESS;
396 		break;
397 	case SCSA1394_DEV_SUSPENDED:
398 	default:
399 		if (scsa1394_bus_config_debug)
400 			cmn_err(CE_WARN,
401 			    "scsa1304_cpr_suspend: Illegal dev state: %d",
402 			    sp->s_dev_state);
403 
404 		rval = DDI_SUCCESS;
405 		break;
406 	}
407 	mutex_exit(&sp->s_mutex);
408 
409 	return (rval);
410 }
411 
412 /*
413  * scsa2usb_cpr_resume:
414  *	restore device's state
415  */
416 static void
417 scsa1394_cpr_resume(dev_info_t *dip)
418 {
419 	int		instance = ddi_get_instance(dip);
420 	scsa1394_state_t *sp;
421 	int		i;
422 	scsa1394_lun_t	*lp;
423 
424 	sp = SCSA1394_INST2STATE(instance);
425 
426 	ASSERT(sp != NULL);
427 
428 	if (sp->s_dev_state != SCSA1394_DEV_SUSPENDED)
429 		return;
430 
431 	/*
432 	 * Go through each lun and reset it to force a reconnect.
433 	 */
434 	for (i = 0; i < sp->s_nluns; i++) {
435 		lp = &sp->s_lun[i];
436 		if (lp->l_ses != NULL) {  /* Are we loged in? */
437 			scsa1394_sbp2_req_bus_reset(lp);
438 			scsa1394_sbp2_req_reconnect(lp);
439 		}
440 	}
441 
442 	/* we are down so let the power get managed */
443 	(void) pm_idle_component(dip, 0);
444 }
445 
446 
447 
448 /*
449  *
450  * --- configuration routines
451  *
452  */
453 static void
454 scsa1394_cleanup(scsa1394_state_t *sp, int level)
455 {
456 	ASSERT((level > 0) && (level <= SCSA1394_CLEANUP_LEVEL_MAX));
457 
458 	switch (level) {
459 	default:
460 		scsa1394_remove_events(sp);
461 		/* FALLTHRU */
462 	case 6:
463 		scsa1394_detach_scsa(sp);
464 		/* FALLTHRU */
465 	case 5:
466 		scsa1394_destroy_cmd_cache(sp);
467 		/* FALLTHRU */
468 	case 4:
469 		scsa1394_detach_threads(sp);
470 		/* FALLTHRU */
471 	case 3:
472 		scsa1394_sbp2_detach(sp);
473 		/* FALLTHRU */
474 	case 2:
475 		scsa1394_detach_1394(sp);
476 		/* FALLTHRU */
477 	case 1:
478 		cv_destroy(&sp->s_event_cv);
479 		mutex_destroy(&sp->s_mutex);
480 		ddi_soft_state_free(scsa1394_statep, sp->s_instance);
481 	}
482 }
483 
484 static int
485 scsa1394_attach_1394(scsa1394_state_t *sp)
486 {
487 	int	ret;
488 
489 	if ((ret = t1394_attach(sp->s_dip, T1394_VERSION_V1, 0,
490 	    &sp->s_attachinfo, &sp->s_t1394_hdl)) != DDI_SUCCESS) {
491 		return (ret);
492 	}
493 
494 	/* DMA attributes for data buffers */
495 	sp->s_buf_dma_attr = sp->s_attachinfo.dma_attr;
496 
497 	/* DMA attributes for page tables */
498 	sp->s_pt_dma_attr = sp->s_attachinfo.dma_attr;
499 	sp->s_pt_dma_attr.dma_attr_sgllen = 1;	/* pt must be contiguous */
500 
501 	if ((ret = t1394_get_targetinfo(sp->s_t1394_hdl, SCSA1394_BUSGEN(sp), 0,
502 	    &sp->s_targetinfo)) != DDI_SUCCESS) {
503 		(void) t1394_detach(&sp->s_t1394_hdl, 0);
504 		return (ret);
505 	}
506 
507 	return (DDI_SUCCESS);
508 }
509 
510 static void
511 scsa1394_detach_1394(scsa1394_state_t *sp)
512 {
513 	(void) t1394_detach(&sp->s_t1394_hdl, 0);
514 }
515 
516 static int
517 scsa1394_attach_threads(scsa1394_state_t *sp)
518 {
519 	char		name[16];
520 	int		nthr;
521 
522 	nthr = sp->s_nluns;
523 	(void) snprintf(name, sizeof (name), "scsa1394%d", sp->s_instance);
524 	if ((sp->s_taskq = ddi_taskq_create(sp->s_dip, name, nthr,
525 	    TASKQ_DEFAULTPRI, 0)) == NULL) {
526 		return (DDI_FAILURE);
527 	}
528 
529 	if (scsa1394_sbp2_threads_init(sp) != DDI_SUCCESS) {
530 		ddi_taskq_destroy(sp->s_taskq);
531 		return (DDI_FAILURE);
532 	}
533 
534 	return (DDI_SUCCESS);
535 }
536 
537 static void
538 scsa1394_detach_threads(scsa1394_state_t *sp)
539 {
540 	scsa1394_sbp2_threads_fini(sp);
541 	ddi_taskq_destroy(sp->s_taskq);
542 }
543 
544 static int
545 scsa1394_attach_scsa(scsa1394_state_t *sp)
546 {
547 	scsi_hba_tran_t	*tran;
548 	int		ret;
549 
550 	sp->s_tran = tran = scsi_hba_tran_alloc(sp->s_dip, SCSI_HBA_CANSLEEP);
551 
552 	tran->tran_hba_private	= sp;
553 	tran->tran_tgt_private	= NULL;
554 	tran->tran_tgt_init	= scsa1394_scsi_tgt_init;
555 	tran->tran_tgt_probe	= scsa1394_scsi_tgt_probe;
556 	tran->tran_tgt_free	= scsa1394_scsi_tgt_free;
557 	tran->tran_start	= scsa1394_scsi_start;
558 	tran->tran_abort	= scsa1394_scsi_abort;
559 	tran->tran_reset	= scsa1394_scsi_reset;
560 	tran->tran_getcap	= scsa1394_scsi_getcap;
561 	tran->tran_setcap	= scsa1394_scsi_setcap;
562 	tran->tran_init_pkt	= scsa1394_scsi_init_pkt;
563 	tran->tran_destroy_pkt	= scsa1394_scsi_destroy_pkt;
564 	tran->tran_dmafree	= scsa1394_scsi_dmafree;
565 	tran->tran_sync_pkt	= scsa1394_scsi_sync_pkt;
566 	tran->tran_reset_notify	= NULL;
567 	tran->tran_get_bus_addr	= NULL;
568 	tran->tran_get_name	= NULL;
569 	tran->tran_bus_reset	= NULL;
570 	tran->tran_quiesce	= NULL;
571 	tran->tran_unquiesce	= NULL;
572 	tran->tran_get_eventcookie = NULL;
573 	tran->tran_add_eventcall = NULL;
574 	tran->tran_remove_eventcall = NULL;
575 	tran->tran_post_event	= NULL;
576 	tran->tran_bus_config	= scsa1394_scsi_bus_config;
577 	tran->tran_bus_unconfig	= scsa1394_scsi_bus_unconfig;
578 
579 	if ((ret = scsi_hba_attach_setup(sp->s_dip, &sp->s_attachinfo.dma_attr,
580 	    tran, 0)) != DDI_SUCCESS) {
581 		scsi_hba_tran_free(tran);
582 		return (ret);
583 	}
584 
585 	return (DDI_SUCCESS);
586 }
587 
588 static void
589 scsa1394_detach_scsa(scsa1394_state_t *sp)
590 {
591 	int	ret;
592 
593 	ret = scsi_hba_detach(sp->s_dip);
594 	ASSERT(ret == DDI_SUCCESS);
595 
596 	scsi_hba_tran_free(sp->s_tran);
597 }
598 
599 static int
600 scsa1394_create_cmd_cache(scsa1394_state_t *sp)
601 {
602 	char	name[64];
603 
604 	(void) sprintf(name, "scsa1394%d_cache", sp->s_instance);
605 	sp->s_cmd_cache = kmem_cache_create(name,
606 	    SCSA1394_CMD_SIZE, sizeof (void *),
607 	    scsa1394_cmd_cache_constructor, scsa1394_cmd_cache_destructor,
608 	    NULL, (void *)sp, NULL, 0);
609 
610 	return ((sp->s_cmd_cache == NULL) ? DDI_FAILURE : DDI_SUCCESS);
611 }
612 
613 static void
614 scsa1394_destroy_cmd_cache(scsa1394_state_t *sp)
615 {
616 	kmem_cache_destroy(sp->s_cmd_cache);
617 }
618 
619 static int
620 scsa1394_add_events(scsa1394_state_t *sp)
621 {
622 	ddi_eventcookie_t	br_evc, rem_evc, ins_evc;
623 
624 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,
625 	    &br_evc) != DDI_SUCCESS) {
626 		return (DDI_FAILURE);
627 	}
628 	if (ddi_add_event_handler(sp->s_dip, br_evc, scsa1394_bus_reset,
629 	    sp, &sp->s_reset_cb_id) != DDI_SUCCESS) {
630 		return (DDI_FAILURE);
631 	}
632 
633 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_REMOVE_EVENT,
634 	    &rem_evc) != DDI_SUCCESS) {
635 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
636 		return (DDI_FAILURE);
637 	}
638 	if (ddi_add_event_handler(sp->s_dip, rem_evc, scsa1394_disconnect,
639 	    sp, &sp->s_remove_cb_id) != DDI_SUCCESS) {
640 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
641 		return (DDI_FAILURE);
642 	}
643 
644 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_INSERT_EVENT,
645 	    &ins_evc) != DDI_SUCCESS) {
646 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
647 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
648 		return (DDI_FAILURE);
649 	}
650 	if (ddi_add_event_handler(sp->s_dip, ins_evc, scsa1394_reconnect,
651 	    sp, &sp->s_insert_cb_id) != DDI_SUCCESS) {
652 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
653 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
654 		return (DDI_FAILURE);
655 	}
656 
657 	return (DDI_SUCCESS);
658 }
659 
660 static void
661 scsa1394_remove_events(scsa1394_state_t *sp)
662 {
663 	ddi_eventcookie_t	evc;
664 
665 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_INSERT_EVENT,
666 	    &evc) == DDI_SUCCESS) {
667 		(void) ddi_remove_event_handler(sp->s_insert_cb_id);
668 	}
669 
670 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_REMOVE_EVENT,
671 	    &evc) == DDI_SUCCESS) {
672 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
673 	}
674 
675 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,
676 	    &evc) == DDI_SUCCESS) {
677 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
678 	}
679 }
680 
681 /*
682  *
683  * --- device configuration
684  *
685  */
686 static int
687 scsa1394_scsi_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
688     void *arg, dev_info_t **child)
689 {
690 	scsa1394_state_t *sp = SCSA1394_INST2STATE(ddi_get_instance(dip));
691 	int		circ;
692 	int		ret;
693 
694 	if (scsa1394_bus_config_debug) {
695 		flag |= NDI_DEVI_DEBUG;
696 	}
697 
698 	ndi_devi_enter(dip, &circ);
699 	if (DEVI(dip)->devi_child == NULL) {
700 		scsa1394_create_children(sp);
701 	}
702 	ret = ndi_busop_bus_config(dip, flag, op, arg, child, 0);
703 	ndi_devi_exit(dip, circ);
704 
705 	return (ret);
706 }
707 
708 static int
709 scsa1394_scsi_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
710     void *arg)
711 {
712 	scsa1394_state_t *sp = SCSA1394_INST2STATE(ddi_get_instance(dip));
713 	int		circ;
714 	int		ret;
715 	uint_t		saved_flag = flag;
716 
717 	if (scsa1394_bus_config_debug) {
718 		flag |= NDI_DEVI_DEBUG;
719 	}
720 
721 	/*
722 	 * First offline and if offlining successful, then remove children.
723 	 */
724 	if (op == BUS_UNCONFIG_ALL) {
725 		flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG);
726 	}
727 
728 	ndi_devi_enter(dip, &circ);
729 
730 	ret = ndi_busop_bus_unconfig(dip, flag, op, arg);
731 
732 	/*
733 	 * If previous step was successful and not part of modunload daemon,
734 	 * attempt to remove children.
735 	 */
736 	if ((op == BUS_UNCONFIG_ALL) && (ret == NDI_SUCCESS) &&
737 	    ((flag & NDI_AUTODETACH) == 0)) {
738 		flag |= NDI_DEVI_REMOVE;
739 		ret = ndi_busop_bus_unconfig(dip, flag, op, arg);
740 	}
741 	ndi_devi_exit(dip, circ);
742 
743 	if ((ret != NDI_SUCCESS) && (op == BUS_UNCONFIG_ALL) &&
744 	    ((saved_flag & NDI_DEVI_REMOVE) != 0)) {
745 		mutex_enter(&sp->s_mutex);
746 		if (!sp->s_disconnect_warned) {
747 			cmn_err(CE_WARN, "scsa1394(%d): "
748 			    "Disconnected device was busy, please reconnect.\n",
749 			    sp->s_instance);
750 			sp->s_disconnect_warned = B_TRUE;
751 		}
752 		mutex_exit(&sp->s_mutex);
753 	}
754 
755 	return (ret);
756 }
757 
758 void
759 scsa1394_dtype2name(int dtype, char **node_name, char **driver_name)
760 {
761 	static struct {
762 		char	*node_name;
763 		char	*driver_name;
764 	} dtype2name[] = {
765 		{ "disk",	"sd" },		/* DTYPE_DIRECT		0x00 */
766 		{ "tape",	"st" },		/* DTYPE_SEQUENTIAL	0x01 */
767 		{ "printer",	NULL },		/* DTYPE_PRINTER	0x02 */
768 		{ "processor",	NULL },		/* DTYPE_PROCESSOR	0x03 */
769 		{ "worm",	NULL },		/* DTYPE_WORM		0x04 */
770 		{ "disk",	"sd" },		/* DTYPE_RODIRECT	0x05 */
771 		{ "scanner",	NULL },		/* DTYPE_SCANNER	0x06 */
772 		{ "disk",	"sd" },		/* DTYPE_OPTICAL	0x07 */
773 		{ "changer",	NULL },		/* DTYPE_CHANGER	0x08 */
774 		{ "comm",	NULL },		/* DTYPE_COMM		0x09 */
775 		{ "generic",	NULL },		/* DTYPE_???		0x0A */
776 		{ "generic",	NULL },		/* DTYPE_???		0x0B */
777 		{ "array_ctrl",	NULL },		/* DTYPE_ARRAY_CTRL	0x0C */
778 		{ "esi",	"ses" },	/* DTYPE_ESI		0x0D */
779 		{ "disk",	"sd" }		/* DTYPE_RBC		0x0E */
780 	};
781 
782 	if (dtype < NELEM(dtype2name)) {
783 		*node_name = dtype2name[dtype].node_name;
784 		*driver_name = dtype2name[dtype].driver_name;
785 	} else {
786 		*node_name = "generic";
787 		*driver_name = NULL;
788 	}
789 }
790 
791 static void
792 scsa1394_create_children(scsa1394_state_t *sp)
793 {
794 	char		name[SCSA1394_COMPAT_MAX][16];
795 	char		*compatible[SCSA1394_COMPAT_MAX];
796 	dev_info_t	*cdip;
797 	int		i;
798 	int		dtype;
799 	char		*node_name;
800 	char		*driver_name;
801 	int		ret;
802 
803 	bzero(name, sizeof (name));
804 	(void) strcpy(name[0], "sd");
805 	for (i = 0; i < SCSA1394_COMPAT_MAX; i++) {
806 		compatible[i] = name[i];
807 	}
808 
809 	for (i = 0; i < sp->s_nluns; i++) {
810 		dtype = scsa1394_sbp2_get_lun_type(&sp->s_lun[i]);
811 		scsa1394_dtype2name(dtype, &node_name, &driver_name);
812 
813 		ndi_devi_alloc_sleep(sp->s_dip, node_name,
814 		    (pnode_t)DEVI_SID_NODEID, &cdip);
815 
816 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
817 		    SCSI_ADDR_PROP_TARGET, 0);
818 		if (ret != DDI_PROP_SUCCESS) {
819 			(void) ndi_devi_free(cdip);
820 			continue;
821 		}
822 
823 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
824 		    SCSI_ADDR_PROP_LUN, i);
825 		if (ret != DDI_PROP_SUCCESS) {
826 			ddi_prop_remove_all(cdip);
827 			(void) ndi_devi_free(cdip);
828 			continue;
829 		}
830 
831 		/*
832 		 * Some devices don't support LOG SENSE, so tell
833 		 * sd driver not to send this command.
834 		 */
835 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
836 		    "pm-capable", 1);
837 		if (ret != DDI_PROP_SUCCESS) {
838 			ddi_prop_remove_all(cdip);
839 			(void) ndi_devi_free(cdip);
840 			continue;
841 		}
842 
843 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
844 		    "hotpluggable");
845 		if (ret != DDI_PROP_SUCCESS) {
846 			ddi_prop_remove_all(cdip);
847 			(void) ndi_devi_free(cdip);
848 			continue;
849 		}
850 
851 		if (driver_name) {
852 			compatible[0] = driver_name;
853 			ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
854 			    "compatible", (char **)compatible,
855 			    SCSA1394_COMPAT_MAX);
856 			if (ret != DDI_PROP_SUCCESS) {
857 				ddi_prop_remove_all(cdip);
858 				(void) ndi_devi_free(cdip);
859 				continue;
860 			}
861 		}
862 
863 		/*
864 		 * add property "scsa1394" to distinguish from others' children
865 		 */
866 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
867 		if (ret != DDI_PROP_SUCCESS) {
868 			ddi_prop_remove_all(cdip);
869 			(void) ndi_devi_free(cdip);
870 			continue;
871 		}
872 
873 		(void) ddi_initchild(sp->s_dip, cdip);
874 	}
875 }
876 
877 /*ARGSUSED*/
878 static void
879 scsa1394_bus_reset(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
880     void *data)
881 {
882 	scsa1394_state_t	*sp = arg;
883 
884 	if (sp != NULL) {
885 		mutex_enter(&sp->s_mutex);
886 		if (sp->s_dev_state == SCSA1394_DEV_DISCONNECTED) {
887 			mutex_exit(&sp->s_mutex);
888 			return;
889 		}
890 		sp->s_stat.stat_bus_reset_cnt++;
891 		sp->s_dev_state = SCSA1394_DEV_BUS_RESET;
892 		sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
893 		mutex_exit(&sp->s_mutex);
894 
895 		scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_BUS_RESET);
896 	}
897 }
898 
899 /*ARGSUSED*/
900 static void
901 scsa1394_disconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
902     void *data)
903 {
904 	scsa1394_state_t	*sp = arg;
905 	int			circ;
906 	dev_info_t		*cdip, *cdip_next;
907 
908 	if (sp == NULL) {
909 		return;
910 	}
911 
912 	mutex_enter(&sp->s_mutex);
913 	sp->s_stat.stat_disconnect_cnt++;
914 	sp->s_dev_state = SCSA1394_DEV_DISCONNECTED;
915 	mutex_exit(&sp->s_mutex);
916 
917 	scsa1394_sbp2_disconnect(sp);
918 
919 	ndi_devi_enter(dip, &circ);
920 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
921 		cdip_next = ddi_get_next_sibling(cdip);
922 
923 		mutex_enter(&DEVI(cdip)->devi_lock);
924 		DEVI_SET_DEVICE_REMOVED(cdip);
925 		mutex_exit(&DEVI(cdip)->devi_lock);
926 	}
927 	ndi_devi_exit(dip, circ);
928 }
929 
930 /*ARGSUSED*/
931 static void
932 scsa1394_reconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
933     void *data)
934 {
935 	scsa1394_state_t	*sp = arg;
936 	int			circ;
937 	dev_info_t		*cdip, *cdip_next;
938 
939 	if (sp == NULL) {
940 		return;
941 	}
942 
943 	mutex_enter(&sp->s_mutex);
944 	sp->s_stat.stat_reconnect_cnt++;
945 	sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
946 	sp->s_disconnect_warned = B_FALSE;
947 	mutex_exit(&sp->s_mutex);
948 
949 	ndi_devi_enter(dip, &circ);
950 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
951 		cdip_next = ddi_get_next_sibling(cdip);
952 
953 		mutex_enter(&DEVI(cdip)->devi_lock);
954 		DEVI_SET_DEVICE_REINSERTED(cdip);
955 		mutex_exit(&DEVI(cdip)->devi_lock);
956 	}
957 	ndi_devi_exit(dip, circ);
958 
959 	scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_RECONNECT);
960 }
961 
962 /*
963  *
964  * --- SCSA entry points
965  *
966  */
967 /*ARGSUSED*/
968 static int
969 scsa1394_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
970     struct scsi_device *sd)
971 {
972 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
973 	int		lun;
974 	int		plen = sizeof (int);
975 	int		ret = DDI_FAILURE;
976 
977 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
978 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, SCSI_ADDR_PROP_LUN,
979 	    (caddr_t)&lun, &plen) != DDI_PROP_SUCCESS) {
980 		return (DDI_FAILURE);
981 	}
982 
983 	if (!scsa1394_is_my_child(cdip)) {
984 		/*
985 		 * add property "scsa1394" to distinguish from others' children
986 		 */
987 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
988 		if (ret != DDI_PROP_SUCCESS) {
989 			return (DDI_FAILURE);
990 		}
991 
992 		if (scsa1394_dev_is_online(sp)) {
993 			return (scsa1394_sbp2_login(sp, lun));
994 		} else {
995 			return (DDI_FAILURE);
996 		}
997 	}
998 
999 	if ((lun >= sp->s_nluns) || (sp->s_lun[lun].l_cdip != NULL) ||
1000 	    !scsa1394_dev_is_online(sp)) {
1001 		return (DDI_FAILURE);
1002 	}
1003 
1004 	if ((ret = scsa1394_sbp2_login(sp, lun)) == DDI_SUCCESS) {
1005 		sp->s_lun[lun].l_cdip = cdip;
1006 	}
1007 	return (ret);
1008 }
1009 
1010 /*ARGSUSED*/
1011 static void
1012 scsa1394_scsi_tgt_free(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
1013     struct scsi_device *sd)
1014 {
1015 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
1016 	int		lun;
1017 	int		plen = sizeof (int);
1018 
1019 	if (!scsa1394_is_my_child(cdip)) {
1020 		return;
1021 	}
1022 
1023 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
1024 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, SCSI_ADDR_PROP_LUN,
1025 	    (caddr_t)&lun, &plen) != DDI_PROP_SUCCESS) {
1026 		return;
1027 	}
1028 
1029 	if ((lun < sp->s_nluns) && (sp->s_lun[lun].l_cdip == cdip)) {
1030 		if (scsa1394_dev_is_online(sp)) {
1031 			scsa1394_sbp2_logout(sp, lun, B_TRUE);
1032 		}
1033 		sp->s_lun[lun].l_cdip = NULL;
1034 	}
1035 }
1036 
1037 static int
1038 scsa1394_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
1039 {
1040 	dev_info_t	*dip = ddi_get_parent(sd->sd_dev);
1041 	scsi_hba_tran_t	*tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
1042 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
1043 	scsa1394_lun_t	*lp;
1044 
1045 	if (!scsa1394_dev_is_online(sp)) {
1046 		return (SCSIPROBE_FAILURE);
1047 	}
1048 	lp = &sp->s_lun[sd->sd_address.a_lun];
1049 
1050 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
1051 	    SCMD_TEST_UNIT_READY, 0, 0) != SCSIPROBE_EXISTS) {
1052 		lp->l_nosup_tur = B_TRUE;
1053 		(void) scsa1394_sbp2_reset(lp, RESET_LUN, NULL);
1054 	}
1055 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
1056 	    SCMD_START_STOP, 0, 1) != SCSIPROBE_EXISTS) {
1057 		lp->l_nosup_start_stop = B_TRUE;
1058 	}
1059 
1060 	/* standard probe issues INQUIRY, which some devices may not support */
1061 	if (scsi_hba_probe(sd, waitfunc) != SCSIPROBE_EXISTS) {
1062 		lp->l_nosup_inquiry = B_TRUE;
1063 		scsa1394_sbp2_fake_inquiry(sp, &lp->l_fake_inq);
1064 		bcopy(&lp->l_fake_inq, sd->sd_inq, SUN_INQSIZE);
1065 #ifndef __lock_lint
1066 		lp->l_rmb_orig = 1;
1067 #endif
1068 	}
1069 
1070 	if (scsa1394_wrka_fake_rmb) {
1071 		sd->sd_inq->inq_rmb = 1;
1072 	}
1073 
1074 	return (SCSIPROBE_EXISTS);
1075 }
1076 
1077 static int
1078 scsa1394_probe_g0_nodata(struct scsi_device *sd, int (*waitfunc)(),
1079     uchar_t cmd, uint_t addr, uint_t cnt)
1080 {
1081 	struct scsi_pkt	*pkt;
1082 	int		ret = SCSIPROBE_EXISTS;
1083 
1084 	pkt = scsi_init_pkt(&sd->sd_address, NULL, NULL, CDB_GROUP0,
1085 	    sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, waitfunc, NULL);
1086 
1087 	if (pkt == NULL) {
1088 		return (SCSIPROBE_NOMEM);
1089 	}
1090 
1091 	(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp, cmd, addr, cnt,
1092 	    0);
1093 	((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = sd->sd_address.a_lun;
1094 	pkt->pkt_flags = FLAG_NOINTR;
1095 
1096 	if (scsa1394_probe_tran(pkt) < 0) {
1097 		if (pkt->pkt_reason == CMD_INCOMPLETE) {
1098 			ret = SCSIPROBE_NORESP;
1099 		} else if ((pkt->pkt_reason == CMD_TRAN_ERR) &&
1100 		    ((*(pkt->pkt_scbp) & STATUS_MASK) == STATUS_CHECK) &&
1101 		    (pkt->pkt_state & STATE_ARQ_DONE)) {
1102 			ret = SCSIPROBE_EXISTS;
1103 		} else {
1104 			ret = SCSIPROBE_FAILURE;
1105 		}
1106 	}
1107 
1108 	scsi_destroy_pkt(pkt);
1109 
1110 	return (ret);
1111 }
1112 
1113 static int
1114 scsa1394_probe_tran(struct scsi_pkt *pkt)
1115 {
1116 	pkt->pkt_time = SCSA1394_PROBE_TIMEOUT;
1117 
1118 	if (scsi_transport(pkt) != TRAN_ACCEPT) {
1119 		return (-1);
1120 	} else if ((pkt->pkt_reason == CMD_INCOMPLETE) &&
1121 	    (pkt->pkt_state == 0)) {
1122 		return (-1);
1123 	} else if (pkt->pkt_reason != CMD_CMPLT) {
1124 		return (-1);
1125 	} else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) {
1126 		return (0);
1127 	}
1128 	return (0);
1129 }
1130 
1131 /*ARGSUSED*/
1132 static int
1133 scsa1394_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1134 {
1135 	return (0);
1136 }
1137 
1138 static int
1139 scsa1394_scsi_reset(struct scsi_address *ap, int level)
1140 {
1141 	scsa1394_state_t *sp = ADDR2STATE(ap);
1142 	scsa1394_lun_t	*lp;
1143 	int		ret;
1144 
1145 	switch (level) {
1146 	case RESET_ALL:
1147 	case RESET_TARGET:
1148 		lp = &sp->s_lun[0];
1149 		break;
1150 	case RESET_LUN:
1151 		lp = &sp->s_lun[ap->a_lun];
1152 		break;
1153 	default:
1154 		return (DDI_FAILURE);
1155 	}
1156 
1157 	ret = scsa1394_sbp2_reset(lp, level, NULL);
1158 
1159 	return ((ret == SBP2_SUCCESS) ? 1 : 0);
1160 }
1161 
1162 /*ARGSUSED*/
1163 static int
1164 scsa1394_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
1165 {
1166 	scsa1394_state_t *sp = ADDR2STATE(ap);
1167 	size_t		dev_bsize_cap;
1168 	int		ret = -1;
1169 
1170 	if (!scsa1394_dev_is_online(sp)) {
1171 		return (-1);
1172 	}
1173 
1174 	if (cap == NULL) {
1175 		return (-1);
1176 	}
1177 
1178 	switch (scsi_hba_lookup_capstr(cap)) {
1179 	case SCSI_CAP_DMA_MAX:
1180 		ret = sp->s_attachinfo.dma_attr.dma_attr_maxxfer;
1181 		break;
1182 	case SCSI_CAP_SCSI_VERSION:
1183 		ret = SCSI_VERSION_2;
1184 		break;
1185 	case SCSI_CAP_ARQ:
1186 		ret = 1;
1187 		break;
1188 	case SCSI_CAP_UNTAGGED_QING:
1189 		ret = 1;
1190 		break;
1191 	case SCSI_CAP_GEOMETRY:
1192 		dev_bsize_cap = sp->s_totalsec;
1193 
1194 		if (sp->s_secsz > DEV_BSIZE) {
1195 			dev_bsize_cap *= sp->s_secsz / DEV_BSIZE;
1196 		} else if (sp->s_secsz < DEV_BSIZE) {
1197 			dev_bsize_cap /= DEV_BSIZE / sp->s_secsz;
1198 		}
1199 
1200 		if (dev_bsize_cap < 65536 * 2 * 18) {		/* < ~1GB */
1201 			/* unlabeled floppy, 18k per cylinder */
1202 			ret = ((2 << 16) | 18);
1203 		} else if (dev_bsize_cap < 65536 * 64 * 32) {	/* < 64GB */
1204 			/* 1024k per cylinder */
1205 			ret = ((64 << 16) | 32);
1206 		} else if (dev_bsize_cap < 65536 * 255 * 63) {	/* < ~500GB */
1207 			/* ~8m per cylinder */
1208 			ret = ((255 << 16) | 63);
1209 		} else {					/* .. 8TB */
1210 			/* 64m per cylinder */
1211 			ret = ((512 << 16) | 256);
1212 		}
1213 		break;
1214 	default:
1215 		break;
1216 	}
1217 
1218 	return (ret);
1219 }
1220 
1221 /*ARGSUSED*/
1222 static int
1223 scsa1394_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1224 {
1225 	scsa1394_state_t *sp = ADDR2STATE(ap);
1226 	int		ret = -1;
1227 
1228 	if (!scsa1394_dev_is_online(sp)) {
1229 		return (-1);
1230 	}
1231 
1232 	switch (scsi_hba_lookup_capstr(cap)) {
1233 	case SCSI_CAP_ARQ:
1234 		ret = 1;
1235 		break;
1236 	case SCSI_CAP_DMA_MAX:
1237 	case SCSI_CAP_SCSI_VERSION:
1238 	case SCSI_CAP_UNTAGGED_QING:
1239 		/* supported but not settable */
1240 		ret = 0;
1241 		break;
1242 	case SCSI_CAP_SECTOR_SIZE:
1243 		if (value) {
1244 			sp->s_secsz = value;
1245 		}
1246 		break;
1247 	case SCSI_CAP_TOTAL_SECTORS:
1248 		if (value) {
1249 			sp->s_totalsec = value;
1250 		}
1251 		break;
1252 	default:
1253 		break;
1254 	}
1255 
1256 	return (ret);
1257 }
1258 
1259 /*ARGSUSED*/
1260 static void
1261 scsa1394_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1262 {
1263 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1264 
1265 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1266 		(void) ddi_dma_sync(cmd->sc_buf_dma_hdl, 0, 0,
1267 		    (cmd->sc_flags & SCSA1394_CMD_READ) ?
1268 		    DDI_DMA_SYNC_FORCPU : DDI_DMA_SYNC_FORDEV);
1269 	}
1270 }
1271 
1272 /*
1273  *
1274  * --- pkt resource allocation routines
1275  *
1276  */
1277 static struct scsi_pkt *
1278 scsa1394_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
1279     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
1280     int (*callback)(), caddr_t arg)
1281 {
1282 	scsa1394_state_t *sp = ADDR2STATE(ap);
1283 	scsa1394_lun_t	*lp;
1284 	scsa1394_cmd_t	*cmd;
1285 	boolean_t	is_new;	/* new cmd is being allocated */
1286 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
1287 
1288 	if (ap->a_lun >= sp->s_nluns) {
1289 		return (NULL);
1290 	}
1291 	lp = &sp->s_lun[ap->a_lun];
1292 
1293 	/*
1294 	 * allocate cmd space
1295 	 */
1296 	if (pkt == NULL) {
1297 		is_new = B_TRUE;
1298 		if ((cmd = kmem_cache_alloc(sp->s_cmd_cache, kf)) == NULL) {
1299 			return (NULL);
1300 		}
1301 
1302 		/* initialize cmd */
1303 		pkt = &cmd->sc_scsi_pkt;
1304 		pkt->pkt_ha_private	= cmd;
1305 		pkt->pkt_address	= *ap;
1306 		pkt->pkt_private	= cmd->sc_priv;
1307 		pkt->pkt_scbp		= (uchar_t *)&cmd->sc_scb;
1308 		pkt->pkt_cdbp		= (uchar_t *)&cmd->sc_pkt_cdb;
1309 		pkt->pkt_resid		= 0;
1310 
1311 		cmd->sc_lun		= lp;
1312 		cmd->sc_pkt		= pkt;
1313 		cmd->sc_cdb_len		= cmdlen;
1314 		cmd->sc_scb_len		= statuslen;
1315 		cmd->sc_priv_len	= tgtlen;
1316 
1317 		/* need external space? */
1318 		if ((cmdlen > sizeof (cmd->sc_pkt_cdb)) ||
1319 		    (statuslen > sizeof (cmd->sc_scb)) ||
1320 		    (tgtlen > sizeof (cmd->sc_priv))) {
1321 			if (scsa1394_cmd_ext_alloc(sp, cmd, kf) !=
1322 			    DDI_SUCCESS) {
1323 				kmem_cache_free(sp->s_cmd_cache, cmd);
1324 				lp->l_stat.stat_err_pkt_kmem_alloc++;
1325 				return (NULL);
1326 			}
1327 		}
1328 
1329 		/* allocate DMA resources for CDB */
1330 		if (scsa1394_cmd_cdb_dma_alloc(sp, cmd, flags, callback, arg) !=
1331 		    DDI_SUCCESS) {
1332 			scsa1394_scsi_destroy_pkt(ap, pkt);
1333 			return (NULL);
1334 		}
1335 	} else {
1336 		is_new = B_FALSE;
1337 		cmd = PKT2CMD(pkt);
1338 	}
1339 
1340 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
1341 
1342 	/* allocate/move DMA resources for data buffer */
1343 	if ((bp != NULL) && (bp->b_bcount > 0)) {
1344 		if ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) == 0) {
1345 			if (scsa1394_cmd_buf_dma_alloc(sp, cmd, flags, callback,
1346 			    arg, bp) != DDI_SUCCESS) {
1347 				if (is_new) {
1348 					scsa1394_scsi_destroy_pkt(ap, pkt);
1349 				}
1350 				return (NULL);
1351 			}
1352 		} else {
1353 			if (scsa1394_cmd_buf_dma_move(sp, cmd) != DDI_SUCCESS) {
1354 				return (NULL);
1355 			}
1356 		}
1357 
1358 		ASSERT(cmd->sc_win_len > 0);
1359 		pkt->pkt_resid = bp->b_bcount - cmd->sc_win_len;
1360 	}
1361 
1362 	/*
1363 	 * kernel virtual address may be required for certain workarounds
1364 	 * and in case of B_PHYS or B_PAGEIO, bp_mapin() will get it for us
1365 	 */
1366 	if ((bp != NULL) && ((bp->b_flags & (B_PAGEIO | B_PHYS)) != 0) &&
1367 	    (bp->b_bcount < SCSA1394_MAPIN_SIZE_MAX) &&
1368 	    ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) == 0)) {
1369 		bp_mapin(bp);
1370 		cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_MAPIN;
1371 	}
1372 
1373 	return (pkt);
1374 }
1375 
1376 static void
1377 scsa1394_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1378 {
1379 	scsa1394_state_t *sp = ADDR2STATE(ap);
1380 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1381 
1382 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1383 		scsa1394_cmd_buf_dma_free(sp, cmd);
1384 	}
1385 	if (cmd->sc_flags & SCSA1394_CMD_DMA_CDB_VALID) {
1386 		scsa1394_cmd_cdb_dma_free(sp, cmd);
1387 	}
1388 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
1389 		bp_mapout(cmd->sc_bp);
1390 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
1391 	}
1392 	if (cmd->sc_flags & SCSA1394_CMD_EXT) {
1393 		scsa1394_cmd_ext_free(sp, cmd);
1394 	}
1395 
1396 	kmem_cache_free(sp->s_cmd_cache, cmd);
1397 }
1398 
1399 static void
1400 scsa1394_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1401 {
1402 	scsa1394_state_t *sp = ADDR2STATE(ap);
1403 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1404 
1405 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1406 		scsa1394_cmd_buf_dma_free(sp, cmd);
1407 	}
1408 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
1409 		bp_mapout(cmd->sc_bp);
1410 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
1411 	}
1412 }
1413 
1414 /*ARGSUSED*/
1415 static int
1416 scsa1394_cmd_cache_constructor(void *buf, void *cdrarg, int kf)
1417 {
1418 	scsa1394_cmd_t	*cmd = buf;
1419 
1420 	bzero(buf, SCSA1394_CMD_SIZE);
1421 	cmd->sc_task.ts_drv_priv = cmd;
1422 
1423 	return (0);
1424 }
1425 
1426 /*ARGSUSED*/
1427 static void
1428 scsa1394_cmd_cache_destructor(void *buf, void *cdrarg)
1429 {
1430 }
1431 
1432 /*
1433  * allocate and deallocate external cmd space (ie. not part of scsa1394_cmd_t)
1434  * for non-standard length cdb, pkt_private, status areas
1435  */
1436 static int
1437 scsa1394_cmd_ext_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd, int kf)
1438 {
1439 	struct scsi_pkt	*pkt = cmd->sc_pkt;
1440 	void		*buf;
1441 
1442 	if (cmd->sc_cdb_len > sizeof (cmd->sc_pkt_cdb)) {
1443 		if ((buf = kmem_zalloc(cmd->sc_cdb_len, kf)) == NULL) {
1444 			return (DDI_FAILURE);
1445 		}
1446 		pkt->pkt_cdbp = buf;
1447 		cmd->sc_flags |= SCSA1394_CMD_CDB_EXT;
1448 	}
1449 
1450 	if (cmd->sc_scb_len > sizeof (cmd->sc_scb)) {
1451 		if ((buf = kmem_zalloc(cmd->sc_scb_len, kf)) == NULL) {
1452 			scsa1394_cmd_ext_free(sp, cmd);
1453 			return (DDI_FAILURE);
1454 		}
1455 		pkt->pkt_scbp = buf;
1456 		cmd->sc_flags |= SCSA1394_CMD_SCB_EXT;
1457 	}
1458 
1459 	if (cmd->sc_priv_len > sizeof (cmd->sc_priv)) {
1460 		if ((buf = kmem_zalloc(cmd->sc_priv_len, kf)) == NULL) {
1461 			scsa1394_cmd_ext_free(sp, cmd);
1462 			return (DDI_FAILURE);
1463 		}
1464 		pkt->pkt_private = buf;
1465 		cmd->sc_flags |= SCSA1394_CMD_PRIV_EXT;
1466 	}
1467 
1468 	return (DDI_SUCCESS);
1469 }
1470 
1471 /*ARGSUSED*/
1472 static void
1473 scsa1394_cmd_ext_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1474 {
1475 	struct scsi_pkt	*pkt = cmd->sc_pkt;
1476 
1477 	if (cmd->sc_flags & SCSA1394_CMD_CDB_EXT) {
1478 		kmem_free(pkt->pkt_cdbp, cmd->sc_cdb_len);
1479 	}
1480 	if (cmd->sc_flags & SCSA1394_CMD_SCB_EXT) {
1481 		kmem_free(pkt->pkt_scbp, cmd->sc_scb_len);
1482 	}
1483 	if (cmd->sc_flags & SCSA1394_CMD_PRIV_EXT) {
1484 		kmem_free(pkt->pkt_private, cmd->sc_priv_len);
1485 	}
1486 	cmd->sc_flags &= ~SCSA1394_CMD_EXT;
1487 }
1488 
1489 /*ARGSUSED*/
1490 static int
1491 scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1492     int flags, int (*callback)(), caddr_t arg)
1493 {
1494 	if (sbp2_task_orb_alloc(cmd->sc_lun->l_lun, &cmd->sc_task,
1495 	    sizeof (scsa1394_cmd_orb_t)) != SBP2_SUCCESS) {
1496 		return (DDI_FAILURE);
1497 	}
1498 
1499 	cmd->sc_flags |= SCSA1394_CMD_DMA_CDB_VALID;
1500 	return (DDI_SUCCESS);
1501 }
1502 
1503 /*ARGSUSED*/
1504 static void
1505 scsa1394_cmd_cdb_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1506 {
1507 	sbp2_task_orb_free(cmd->sc_lun->l_lun, &cmd->sc_task);
1508 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_CDB_VALID;
1509 }
1510 
1511 /*
1512  * buffer resources
1513  */
1514 static int
1515 scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1516     int flags, int (*callback)(), caddr_t arg, struct buf *bp)
1517 {
1518 	scsa1394_lun_t	*lp = cmd->sc_lun;
1519 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
1520 	int		dma_flags;
1521 	ddi_dma_cookie_t dmac;
1522 	uint_t		ccount;
1523 	int		error;
1524 	int		ret;
1525 
1526 	cmd->sc_bp = bp;
1527 
1528 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_buf_dma_attr, callback,
1529 	    NULL, &cmd->sc_buf_dma_hdl)) != DDI_SUCCESS) {
1530 		bioerror(bp, 0);
1531 		return (DDI_FAILURE);
1532 	}
1533 
1534 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
1535 	if (bp->b_flags & B_READ) {
1536 		dma_flags = DDI_DMA_READ;
1537 		cmd->sc_flags |= SCSA1394_CMD_READ;
1538 	} else {
1539 		dma_flags = DDI_DMA_WRITE;
1540 		cmd->sc_flags |= SCSA1394_CMD_WRITE;
1541 	}
1542 	if (flags & PKT_CONSISTENT) {
1543 		dma_flags |= DDI_DMA_CONSISTENT;
1544 	}
1545 	if (flags & PKT_DMA_PARTIAL) {
1546 		dma_flags |= DDI_DMA_PARTIAL;
1547 	}
1548 
1549 	ret = ddi_dma_buf_bind_handle(cmd->sc_buf_dma_hdl, bp, dma_flags,
1550 	    callback, arg, &dmac, &ccount);
1551 
1552 	switch (ret) {
1553 	case DDI_DMA_MAPPED:
1554 		cmd->sc_nwin = 1;
1555 		cmd->sc_curwin = 0;
1556 		cmd->sc_win_offset = 0;
1557 		cmd->sc_win_len = bp->b_bcount;
1558 		break;
1559 
1560 	case DDI_DMA_PARTIAL_MAP:
1561 		/* retrieve number of windows and first window cookie */
1562 		cmd->sc_curwin = 0;
1563 		if ((ddi_dma_numwin(cmd->sc_buf_dma_hdl, &cmd->sc_nwin) !=
1564 		    DDI_SUCCESS) ||
1565 		    (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
1566 		    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
1567 		    DDI_SUCCESS)) {
1568 			(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
1569 			ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1570 			return (DDI_FAILURE);
1571 		}
1572 		lp->l_stat.stat_cmd_buf_dma_partial++;
1573 		break;
1574 
1575 	case DDI_DMA_NORESOURCES:
1576 		error = 0;
1577 		goto map_error;
1578 
1579 	case DDI_DMA_BADATTR:
1580 	case DDI_DMA_NOMAPPING:
1581 		error = EFAULT;
1582 		goto map_error;
1583 
1584 	default:
1585 		error = EINVAL;
1586 
1587 	map_error:
1588 		bioerror(bp, error);
1589 		lp->l_stat.stat_err_cmd_buf_dbind++;
1590 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1591 		return (DDI_FAILURE);
1592 	}
1593 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_BIND_VALID;
1594 
1595 	/*
1596 	 * setup page table if needed
1597 	 */
1598 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1599 	    (!sp->s_symbios ||
1600 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
1601 		cmd->sc_buf_nsegs = 1;
1602 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
1603 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
1604 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
1605 	} else {
1606 		/* break window into segments */
1607 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, kf) !=
1608 		    DDI_SUCCESS) {
1609 			scsa1394_cmd_buf_dma_free(sp, cmd);
1610 			bioerror(bp, 0);
1611 			return (DDI_FAILURE);
1612 		}
1613 
1614 		/* allocate DMA resources for page table */
1615 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, callback, arg,
1616 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
1617 			scsa1394_cmd_buf_dma_free(sp, cmd);
1618 			bioerror(bp, 0);
1619 			return (DDI_FAILURE);
1620 		}
1621 	}
1622 
1623 	/* allocate 1394 addresses for segments */
1624 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
1625 		scsa1394_cmd_buf_dma_free(sp, cmd);
1626 		bioerror(bp, 0);
1627 		return (DDI_FAILURE);
1628 	}
1629 
1630 	return (DDI_SUCCESS);
1631 }
1632 
1633 static void
1634 scsa1394_cmd_buf_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1635 {
1636 	scsa1394_cmd_buf_addr_free(sp, cmd);
1637 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1638 		scsa1394_cmd_pt_dma_free(sp, cmd);
1639 	}
1640 	scsa1394_cmd_seg_free(sp, cmd);
1641 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_BIND_VALID) {
1642 		(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
1643 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1644 	}
1645 	cmd->sc_flags &= ~(SCSA1394_CMD_DMA_BUF_VALID | SCSA1394_CMD_RDWR);
1646 }
1647 
1648 /*
1649  * Break a set DMA cookies into segments suitable for SBP-2 page table.
1650  * This routine can reuse/reallocate segment array from previous calls.
1651  */
1652 static int
1653 scsa1394_cmd_dmac2seg(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1654     ddi_dma_cookie_t *dmac, uint_t ccount, int kf)
1655 {
1656 	scsa1394_lun_t	*lp = cmd->sc_lun;
1657 	int		i;
1658 	int		nsegs;
1659 	size_t		segsize_max;
1660 	size_t		dmac_resid;
1661 	uint32_t	dmac_addr;
1662 	scsa1394_cmd_seg_t *seg;
1663 
1664 	if (!sp->s_symbios) {
1665 		/*
1666 		 * Number of segments is unknown at this point. Start with
1667 		 * a reasonable estimate and grow it later if needed.
1668 		 */
1669 		nsegs = max(ccount, cmd->sc_win_len / SBP2_PT_SEGSIZE_MAX) * 2;
1670 		segsize_max = SBP2_PT_SEGSIZE_MAX;
1671 	} else {
1672 		/*
1673 		 * For Symbios workaround we know exactly the number of segments
1674 		 * Additional segment may be needed if buffer is not aligned.
1675 		 */
1676 		nsegs =
1677 		    howmany(cmd->sc_win_len, scsa1394_symbios_page_size) + 1;
1678 		segsize_max = scsa1394_symbios_page_size;
1679 	}
1680 
1681 	if (nsegs > cmd->sc_buf_nsegs_alloc) {
1682 		if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(cmd->sc_buf_seg,
1683 		    cmd->sc_buf_nsegs_alloc, nsegs,
1684 		    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
1685 			cmd->sc_buf_nsegs_alloc = 0;
1686 			return (DDI_FAILURE);
1687 		}
1688 		cmd->sc_buf_nsegs_alloc = nsegs;
1689 	}
1690 
1691 	/* each cookie maps into one or more segments */
1692 	cmd->sc_buf_nsegs = 0;
1693 	i = ccount;
1694 	for (;;) {
1695 		dmac_resid = dmac->dmac_size;
1696 		dmac_addr = dmac->dmac_address;
1697 		while (dmac_resid > 0) {
1698 			/* grow array if needed */
1699 			if (cmd->sc_buf_nsegs >= cmd->sc_buf_nsegs_alloc) {
1700 				if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(
1701 				    cmd->sc_buf_seg,
1702 				    cmd->sc_buf_nsegs_alloc,
1703 				    cmd->sc_buf_nsegs_alloc + ccount,
1704 				    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
1705 					return (DDI_FAILURE);
1706 				}
1707 				cmd->sc_buf_nsegs_alloc += ccount;
1708 			}
1709 
1710 			seg = &cmd->sc_buf_seg[cmd->sc_buf_nsegs];
1711 			seg->ss_len = min(dmac_resid, segsize_max);
1712 			seg->ss_daddr = (uint64_t)dmac_addr;
1713 			dmac_addr += seg->ss_len;
1714 			dmac_resid -= seg->ss_len;
1715 			cmd->sc_buf_nsegs++;
1716 		}
1717 		ASSERT(dmac_resid == 0);
1718 
1719 		/* grab next cookie */
1720 		if (--i <= 0) {
1721 			break;
1722 		}
1723 		ddi_dma_nextcookie(cmd->sc_buf_dma_hdl, dmac);
1724 	}
1725 
1726 	if (cmd->sc_buf_nsegs > lp->l_stat.stat_cmd_buf_max_nsegs) {
1727 		lp->l_stat.stat_cmd_buf_max_nsegs = cmd->sc_buf_nsegs;
1728 	}
1729 
1730 	return (DDI_SUCCESS);
1731 }
1732 
1733 /*ARGSUSED*/
1734 static void
1735 scsa1394_cmd_seg_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1736 {
1737 	if (cmd->sc_buf_nsegs_alloc > 0) {
1738 		kmem_free(cmd->sc_buf_seg, cmd->sc_buf_nsegs_alloc *
1739 		    sizeof (scsa1394_cmd_seg_t));
1740 	}
1741 	cmd->sc_buf_seg = NULL;
1742 	cmd->sc_buf_nsegs = 0;
1743 	cmd->sc_buf_nsegs_alloc = 0;
1744 }
1745 
1746 static int
1747 scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1748     int (*callback)(), caddr_t arg, int cnt)
1749 {
1750 	scsa1394_lun_t	*lp = cmd->sc_lun;
1751 	size_t		len, rlen;
1752 	uint_t		ccount;
1753 	t1394_alloc_addr_t aa;
1754 	int		result;
1755 
1756 	/* allocate DMA memory for page table */
1757 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_pt_dma_attr,
1758 	    callback, NULL, &cmd->sc_pt_dma_hdl)) != DDI_SUCCESS) {
1759 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1760 		return (DDI_FAILURE);
1761 	}
1762 
1763 	cmd->sc_pt_ent_alloc = cnt;
1764 	len = cmd->sc_pt_ent_alloc * SBP2_PT_ENT_SIZE;
1765 	if (ddi_dma_mem_alloc(cmd->sc_pt_dma_hdl, len,
1766 	    &sp->s_attachinfo.acc_attr, DDI_DMA_CONSISTENT, callback, arg,
1767 	    &cmd->sc_pt_kaddr, &rlen, &cmd->sc_pt_acc_hdl) != DDI_SUCCESS) {
1768 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1769 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1770 		return (DDI_FAILURE);
1771 	}
1772 
1773 	if (ddi_dma_addr_bind_handle(cmd->sc_pt_dma_hdl, NULL,
1774 	    cmd->sc_pt_kaddr, len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
1775 	    callback, arg, &cmd->sc_pt_dmac, &ccount) != DDI_DMA_MAPPED) {
1776 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1777 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1778 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1779 		return (DDI_FAILURE);
1780 	}
1781 	ASSERT(ccount == 1);	/* because dma_attr_sgllen is 1 */
1782 
1783 	/* allocate 1394 address for page table */
1784 	aa.aa_type = T1394_ADDR_FIXED;
1785 	aa.aa_length = len;
1786 	aa.aa_address = cmd->sc_pt_dmac.dmac_address;
1787 	aa.aa_evts.recv_read_request = NULL;
1788 	aa.aa_evts.recv_write_request = NULL;
1789 	aa.aa_evts.recv_lock_request = NULL;
1790 	aa.aa_arg = NULL;
1791 	aa.aa_kmem_bufp = NULL;
1792 	aa.aa_enable = T1394_ADDR_RDENBL;
1793 	if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) != DDI_SUCCESS) {
1794 		(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
1795 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1796 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1797 		lp->l_stat.stat_err_cmd_pt_addr_alloc++;
1798 		return (DDI_FAILURE);
1799 	}
1800 	ASSERT(aa.aa_address != 0);
1801 	cmd->sc_pt_baddr = aa.aa_address;
1802 	cmd->sc_pt_addr_hdl = aa.aa_hdl;
1803 
1804 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_PT_VALID;
1805 
1806 	return (DDI_SUCCESS);
1807 }
1808 
1809 static void
1810 scsa1394_cmd_pt_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1811 {
1812 	(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
1813 	ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1814 	ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1815 	(void) t1394_free_addr(sp->s_t1394_hdl, &cmd->sc_pt_addr_hdl, 0);
1816 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_PT_VALID;
1817 }
1818 
1819 /*
1820  * allocate 1394 addresses for all buffer segments
1821  */
1822 static int
1823 scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1824 {
1825 	scsa1394_lun_t	*lp = cmd->sc_lun;
1826 	t1394_alloc_addr_t aa;
1827 	scsa1394_cmd_seg_t *seg;
1828 	int		result;
1829 	int		i;
1830 
1831 	aa.aa_type = T1394_ADDR_FIXED;
1832 	aa.aa_evts.recv_read_request = NULL;
1833 	aa.aa_evts.recv_write_request = NULL;
1834 	aa.aa_evts.recv_lock_request = NULL;
1835 	aa.aa_arg = NULL;
1836 	aa.aa_kmem_bufp = NULL;
1837 	if (cmd->sc_flags & SCSA1394_CMD_READ) {
1838 		aa.aa_enable = T1394_ADDR_RDENBL;
1839 	} else {
1840 		aa.aa_enable = T1394_ADDR_WRENBL;
1841 	}
1842 
1843 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
1844 		seg = &cmd->sc_buf_seg[i];
1845 
1846 		/* segment bus address */
1847 		aa.aa_length = seg->ss_len;
1848 		aa.aa_address = seg->ss_daddr;
1849 
1850 		if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) !=
1851 		    DDI_SUCCESS) {
1852 			lp->l_stat.stat_err_cmd_buf_addr_alloc++;
1853 			return (DDI_FAILURE);
1854 		}
1855 		ASSERT(aa.aa_address != 0);
1856 		seg->ss_baddr = aa.aa_address;
1857 		seg->ss_addr_hdl = aa.aa_hdl;
1858 	}
1859 
1860 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_ADDR_VALID;
1861 
1862 	return (DDI_SUCCESS);
1863 }
1864 
1865 static void
1866 scsa1394_cmd_buf_addr_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1867 {
1868 	int		i;
1869 
1870 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
1871 		if (cmd->sc_buf_seg[i].ss_addr_hdl) {
1872 			(void) t1394_free_addr(sp->s_t1394_hdl,
1873 			    &cmd->sc_buf_seg[i].ss_addr_hdl, 0);
1874 		}
1875 	}
1876 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_ADDR_VALID;
1877 }
1878 
1879 /*
1880  * move to next DMA window
1881  */
1882 static int
1883 scsa1394_cmd_buf_dma_move(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1884 {
1885 	/* scsa1394_lun_t	*lp = cmd->sc_lun; */
1886 	ddi_dma_cookie_t dmac;
1887 	uint_t		ccount;
1888 
1889 	/* for small pkts, leave things where they are (says WDD) */
1890 	if ((cmd->sc_curwin == cmd->sc_nwin) && (cmd->sc_nwin == 1)) {
1891 		return (DDI_SUCCESS);
1892 	}
1893 	if (++cmd->sc_curwin >= cmd->sc_nwin) {
1894 		return (DDI_FAILURE);
1895 	}
1896 	if (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
1897 	    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
1898 	    DDI_SUCCESS) {
1899 		return (DDI_FAILURE);
1900 	}
1901 
1902 	scsa1394_cmd_buf_addr_free(sp, cmd);
1903 
1904 	/*
1905 	 * setup page table if needed
1906 	 */
1907 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1908 	    (!sp->s_symbios ||
1909 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
1910 		/* but first, free old resources */
1911 		if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1912 			scsa1394_cmd_pt_dma_free(sp, cmd);
1913 		}
1914 		scsa1394_cmd_seg_free(sp, cmd);
1915 
1916 		cmd->sc_buf_nsegs = 1;
1917 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
1918 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
1919 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
1920 	} else {
1921 		/* break window into segments */
1922 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, KM_NOSLEEP) !=
1923 		    DDI_SUCCESS) {
1924 			return (DDI_FAILURE);
1925 		}
1926 
1927 		/* allocate DMA resources */
1928 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, NULL_FUNC, NULL,
1929 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
1930 			return (DDI_FAILURE);
1931 		}
1932 	}
1933 
1934 	/* allocate 1394 addresses for segments */
1935 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
1936 		return (DDI_FAILURE);
1937 	}
1938 
1939 	return (DDI_SUCCESS);
1940 }
1941 
1942 /*
1943  *
1944  * --- pkt and data transfer routines
1945  *
1946  */
1947 static int
1948 scsa1394_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
1949 {
1950 	scsa1394_state_t *sp = ADDR2STATE(ap);
1951 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1952 	scsa1394_lun_t	*lp = cmd->sc_lun;
1953 	int		ret;
1954 
1955 	/*
1956 	 * since we don't support polled I/O, just accept the packet
1957 	 * so the rest of the file systems get synced properly
1958 	 */
1959 	if (ddi_in_panic()) {
1960 		scsa1394_prepare_pkt(sp, pkt);
1961 		return (TRAN_ACCEPT);
1962 	}
1963 
1964 	/* polling not supported yet */
1965 	if (pkt->pkt_flags & FLAG_NOINTR) {
1966 		return (TRAN_BADPKT);
1967 	}
1968 
1969 	mutex_enter(&sp->s_mutex);
1970 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
1971 		/*
1972 		 * If device is temporarily gone due to bus reset,
1973 		 * return busy to prevent prevent scary console messages.
1974 		 * If permanently gone, leave it to scsa1394_cmd_fake_comp().
1975 		 */
1976 		if (sp->s_dev_state == SCSA1394_DEV_BUS_RESET) {
1977 			mutex_exit(&sp->s_mutex);
1978 			return (TRAN_BUSY);
1979 		}
1980 	}
1981 	mutex_exit(&sp->s_mutex);
1982 
1983 	if ((ap->a_lun >= sp->s_nluns) ||
1984 	    (ap->a_lun != pkt->pkt_address.a_lun)) {
1985 		return (TRAN_BADPKT);
1986 	}
1987 
1988 	scsa1394_prepare_pkt(sp, pkt);
1989 
1990 	/* some commands may require fake completion */
1991 	if ((ret = scsa1394_cmd_fake_comp(sp, cmd)) == DDI_SUCCESS) {
1992 		return (TRAN_ACCEPT);
1993 	}
1994 
1995 	scsa1394_cmd_fill_cdb(lp, cmd);
1996 
1997 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1998 		scsa1394_sbp2_seg2pt(lp, cmd);
1999 	}
2000 
2001 	scsa1394_sbp2_cmd2orb(lp, cmd);		/* convert into ORB */
2002 
2003 	if ((ret = scsa1394_sbp2_start(lp, cmd)) != TRAN_BUSY) {
2004 		scsa1394_sbp2_nudge(lp);
2005 	}
2006 
2007 	return (ret);
2008 }
2009 
2010 /*ARGSUSED*/
2011 static void
2012 scsa1394_prepare_pkt(scsa1394_state_t *sp, struct scsi_pkt *pkt)
2013 {
2014 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
2015 
2016 	pkt->pkt_reason = CMD_CMPLT;
2017 	pkt->pkt_state = 0;
2018 	pkt->pkt_statistics = 0;
2019 	*(pkt->pkt_scbp) = STATUS_GOOD;
2020 
2021 	if (cmd) {
2022 		cmd->sc_timeout = pkt->pkt_time;
2023 
2024 		/* workarounds */
2025 		switch (pkt->pkt_cdbp[0]) {
2026 		/*
2027 		 * sd does START_STOP_UNIT during attach with a 200 sec timeout.
2028 		 * at this time devi_lock is held, prtconf will be stuck.
2029 		 * reduce timeout for the time being.
2030 		 */
2031 		case SCMD_START_STOP:
2032 			cmd->sc_timeout = min(cmd->sc_timeout,
2033 			    scsa1394_start_stop_timeout_max);
2034 			break;
2035 		default:
2036 			break;
2037 		}
2038 	}
2039 }
2040 
2041 static void
2042 scsa1394_cmd_fill_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2043 {
2044 	cmd->sc_cdb_actual_len = cmd->sc_cdb_len;
2045 
2046 	mutex_enter(&lp->l_mutex);
2047 
2048 	switch (lp->l_dtype_orig) {
2049 	case DTYPE_DIRECT:
2050 	case DTYPE_RODIRECT:
2051 	case DTYPE_OPTICAL:
2052 	case SCSA1394_DTYPE_RBC:
2053 		scsa1394_cmd_fill_cdb_rbc(lp, cmd);
2054 		break;
2055 	default:
2056 		scsa1394_cmd_fill_cdb_other(lp, cmd);
2057 		break;
2058 	}
2059 
2060 	mutex_exit(&lp->l_mutex);
2061 }
2062 
2063 static void
2064 scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2065 {
2066 	scsa1394_state_t *sp = lp->l_sp;
2067 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2068 	int		lba, opcode;
2069 	struct buf	*bp = cmd->sc_bp;
2070 	size_t		len;
2071 	size_t		blk_size;
2072 	int		sz;
2073 
2074 	opcode = pkt->pkt_cdbp[0];
2075 	blk_size  = lp->l_lba_size;
2076 
2077 	switch (opcode) {
2078 	case SCMD_READ:
2079 		/* RBC only supports 10-byte read/write */
2080 		lba = SCSA1394_LBA_6BYTE(pkt);
2081 		len = SCSA1394_LEN_6BYTE(pkt);
2082 		opcode = SCMD_READ_G1;
2083 		cmd->sc_cdb_actual_len = CDB_GROUP1;
2084 		break;
2085 	case SCMD_WRITE:
2086 		lba = SCSA1394_LBA_6BYTE(pkt);
2087 		len = SCSA1394_LEN_6BYTE(pkt);
2088 		opcode = SCMD_WRITE_G1;
2089 		cmd->sc_cdb_actual_len = CDB_GROUP1;
2090 		break;
2091 	case SCMD_READ_G1:
2092 	case SCMD_READ_LONG:
2093 		lba = SCSA1394_LBA_10BYTE(pkt);
2094 		len = SCSA1394_LEN_10BYTE(pkt);
2095 		break;
2096 	case SCMD_WRITE_G1:
2097 	case SCMD_WRITE_LONG:
2098 		lba = SCSA1394_LBA_10BYTE(pkt);
2099 		len = SCSA1394_LEN_10BYTE(pkt);
2100 		if ((lp->l_dtype_orig == DTYPE_RODIRECT) &&
2101 		    (bp != NULL) && (len != 0)) {
2102 			sz = SCSA1394_CDRW_BLKSZ(bp->b_bcount, len);
2103 			if (SCSA1394_VALID_CDRW_BLKSZ(sz)) {
2104 				blk_size = sz;
2105 			}
2106 		}
2107 		break;
2108 	case SCMD_READ_CD:
2109 		lba = SCSA1394_LBA_10BYTE(pkt);
2110 		len = SCSA1394_LEN_READ_CD(pkt);
2111 		blk_size = scsa1394_cmd_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2);
2112 		break;
2113 	case SCMD_READ_G5:
2114 		lba = SCSA1394_LBA_12BYTE(pkt);
2115 		len = SCSA1394_LEN_12BYTE(pkt);
2116 		break;
2117 	case SCMD_WRITE_G5:
2118 		lba = SCSA1394_LBA_12BYTE(pkt);
2119 		len = SCSA1394_LEN_12BYTE(pkt);
2120 		break;
2121 	default:
2122 		/* no special mapping for other commands */
2123 		scsa1394_cmd_fill_cdb_other(lp, cmd);
2124 		return;
2125 	}
2126 	cmd->sc_blk_size = blk_size;
2127 
2128 	/* limit xfer length for Symbios workaround */
2129 	if (sp->s_symbios && (len * blk_size > scsa1394_symbios_size_max)) {
2130 		cmd->sc_flags |= SCSA1394_CMD_SYMBIOS_BREAKUP;
2131 
2132 		cmd->sc_total_blks = cmd->sc_resid_blks = len;
2133 
2134 		len = scsa1394_symbios_size_max / blk_size;
2135 	}
2136 	cmd->sc_xfer_blks = len;
2137 	cmd->sc_xfer_bytes = len * blk_size;
2138 
2139 	/* finalize new CDB */
2140 	switch (pkt->pkt_cdbp[0]) {
2141 	case SCMD_READ:
2142 	case SCMD_WRITE:
2143 		/*
2144 		 * We rewrite READ/WRITE G0 commands as READ/WRITE G1.
2145 		 * Build new cdb from scatch.
2146 		 * The lba and length fields is updated below.
2147 		 */
2148 		bzero(cmd->sc_cdb, cmd->sc_cdb_actual_len);
2149 		break;
2150 	default:
2151 		/*
2152 		 * Copy the non lba/len fields.
2153 		 * The lba and length fields is updated below.
2154 		 */
2155 		bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_actual_len);
2156 		break;
2157 	}
2158 
2159 	cmd->sc_cdb[0] = (uchar_t)opcode;
2160 	scsa1394_cmd_fill_cdb_lba(cmd, lba);
2161 	switch (opcode) {
2162 	case SCMD_READ_CD:
2163 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
2164 		break;
2165 	case SCMD_WRITE_G5:
2166 	case SCMD_READ_G5:
2167 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
2168 		break;
2169 	default:
2170 		scsa1394_cmd_fill_cdb_len(cmd, len);
2171 		break;
2172 	}
2173 }
2174 
2175 /*ARGSUSED*/
2176 static void
2177 scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2178 {
2179 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2180 
2181 	cmd->sc_xfer_bytes = cmd->sc_win_len;
2182 	cmd->sc_xfer_blks = cmd->sc_xfer_bytes / lp->l_lba_size;
2183 	cmd->sc_total_blks = cmd->sc_xfer_blks;
2184 	cmd->sc_lba = 0;
2185 
2186 	bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_len);
2187 }
2188 
2189 /*
2190  * fill up parts of CDB
2191  */
2192 static void
2193 scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *cmd, int len)
2194 {
2195 	cmd->sc_cdb[7] = len >> 8;
2196 	cmd->sc_cdb[8] = (uchar_t)len;
2197 }
2198 
2199 static void
2200 scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *cmd, int lba)
2201 {
2202 	cmd->sc_cdb[2] = lba >> 24;
2203 	cmd->sc_cdb[3] = lba >> 16;
2204 	cmd->sc_cdb[4] = lba >> 8;
2205 	cmd->sc_cdb[5] = (uchar_t)lba;
2206 	cmd->sc_lba = lba;
2207 }
2208 
2209 static void
2210 scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *cmd, int len)
2211 {
2212 	cmd->sc_cdb[6] = len >> 24;
2213 	cmd->sc_cdb[7] = len >> 16;
2214 	cmd->sc_cdb[8] = len >> 8;
2215 	cmd->sc_cdb[9] = (uchar_t)len;
2216 }
2217 
2218 static void
2219 scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *cmd, int len)
2220 {
2221 	cmd->sc_cdb[6] = len >> 16;
2222 	cmd->sc_cdb[7] = len >> 8;
2223 	cmd->sc_cdb[8] = (uchar_t)len;
2224 }
2225 
2226 /*
2227  * For SCMD_READ_CD, figure out the block size based on expected sector type.
2228  * See MMC SCSI Specs section 6.1.15
2229  */
2230 static int
2231 scsa1394_cmd_read_cd_blk_size(uchar_t expected_sector_type)
2232 {
2233 	int blk_size;
2234 
2235 	switch (expected_sector_type) {
2236 	case READ_CD_EST_CDDA:
2237 		blk_size = CDROM_BLK_2352;
2238 		break;
2239 	case READ_CD_EST_MODE2:
2240 		blk_size = CDROM_BLK_2336;
2241 		break;
2242 	case READ_CD_EST_MODE2FORM2:
2243 		blk_size = CDROM_BLK_2324;
2244 		break;
2245 	case READ_CD_EST_MODE2FORM1:
2246 	case READ_CD_EST_ALLTYPE:
2247 	case READ_CD_EST_MODE1:
2248 	default:
2249 		blk_size = CDROM_BLK_2048;
2250 	}
2251 
2252 	return (blk_size);
2253 }
2254 
2255 /*ARGSUSED*/
2256 static int
2257 scsa1394_cmd_fake_mode_sense(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2258 {
2259 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2260 	struct scsi_arq_status *arqp = (struct scsi_arq_status *)pkt->pkt_scbp;
2261 	struct scsi_extended_sense *esp = &arqp->sts_sensedata;
2262 
2263 	*(pkt->pkt_scbp) = STATUS_CHECK;
2264 	*(uint8_t *)&arqp->sts_rqpkt_status = STATUS_GOOD;
2265 	arqp->sts_rqpkt_reason = CMD_CMPLT;
2266 	arqp->sts_rqpkt_resid = 0;
2267 	arqp->sts_rqpkt_state |= STATE_XFERRED_DATA;
2268 	arqp->sts_rqpkt_statistics = 0;
2269 
2270 	bzero(esp, sizeof (struct scsi_extended_sense));
2271 
2272 	esp->es_class = CLASS_EXTENDED_SENSE;
2273 
2274 	esp->es_key = KEY_ILLEGAL_REQUEST;
2275 
2276 	pkt->pkt_reason = CMD_CMPLT;
2277 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2278 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2279 
2280 	if (pkt->pkt_comp) {
2281 		(*pkt->pkt_comp)(pkt);
2282 	}
2283 	return (DDI_SUCCESS);
2284 }
2285 
2286 /*ARGSUSED*/
2287 static int
2288 scsa1394_cmd_fake_inquiry(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2289 {
2290 	scsa1394_lun_t	*lp = cmd->sc_lun;
2291 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2292 	struct scsi_inquiry *inq;
2293 
2294 	/* copy fabricated inquiry data */
2295 	inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
2296 	bcopy(&lp->l_fake_inq, inq, sizeof (struct scsi_inquiry));
2297 
2298 	pkt->pkt_resid -= sizeof (struct scsi_inquiry);
2299 	pkt->pkt_reason = CMD_CMPLT;
2300 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2301 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2302 
2303 	if (pkt->pkt_comp) {
2304 		(*pkt->pkt_comp)(pkt);
2305 	}
2306 	return (DDI_SUCCESS);
2307 }
2308 
2309 /*
2310  * If command allows fake completion (without actually being transported),
2311  * call completion callback and return DDI_SUCCESS.
2312  * Otherwise return DDI_FAILURE.
2313  */
2314 static int
2315 scsa1394_cmd_fake_comp(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2316 {
2317 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2318 	scsa1394_lun_t	*lp = cmd->sc_lun;
2319 	int		ret = DDI_SUCCESS;
2320 
2321 	/*
2322 	 * agreement with sd in case of device hot removal
2323 	 * is to fake completion with CMD_DEV_GONE
2324 	 */
2325 	mutex_enter(&sp->s_mutex);
2326 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
2327 		mutex_exit(&sp->s_mutex);
2328 		pkt->pkt_reason = CMD_DEV_GONE;
2329 		if (pkt->pkt_comp) {
2330 			(*pkt->pkt_comp)(pkt);
2331 		}
2332 		return (DDI_SUCCESS);
2333 	}
2334 	mutex_exit(&sp->s_mutex);
2335 
2336 	mutex_enter(&lp->l_mutex);
2337 
2338 	switch (pkt->pkt_cdbp[0]) {
2339 	/*
2340 	 * RBC support for PRIN/PROUT is optional
2341 	 */
2342 	case SCMD_PRIN:
2343 	case SCMD_PROUT:
2344 		if (!scsa1394_wrka_fake_prin) {
2345 			ret = DDI_FAILURE;
2346 		}
2347 		break;
2348 	/*
2349 	 * Some fixed disks don't like doorlock cmd. And they don't need it.
2350 	 */
2351 	case SCMD_DOORLOCK:
2352 		if (lp->l_rmb_orig != 0) {
2353 			ret = DDI_FAILURE;
2354 		}
2355 		break;
2356 	case SCMD_TEST_UNIT_READY:
2357 		if (!lp->l_nosup_tur) {
2358 			ret = DDI_FAILURE;
2359 		}
2360 		break;
2361 	case SCMD_START_STOP:
2362 		if (!lp->l_nosup_start_stop) {
2363 			ret = DDI_FAILURE;
2364 		}
2365 		break;
2366 	case SCMD_INQUIRY:
2367 		if (!lp->l_nosup_inquiry) {
2368 			ret = DDI_FAILURE;
2369 		} else {
2370 			mutex_exit(&lp->l_mutex);
2371 			return (scsa1394_cmd_fake_inquiry(sp, cmd));
2372 		}
2373 		break;
2374 	case SCMD_MODE_SENSE:
2375 		if (!lp->l_mode_sense_fake) {
2376 			ret = DDI_FAILURE;
2377 		} else {
2378 			mutex_exit(&lp->l_mutex);
2379 			return (scsa1394_cmd_fake_mode_sense(sp, cmd));
2380 		}
2381 	default:
2382 		ret = DDI_FAILURE;
2383 	}
2384 
2385 	mutex_exit(&lp->l_mutex);
2386 
2387 	if (ret != DDI_SUCCESS) {
2388 		return (ret);
2389 	}
2390 
2391 	ASSERT(*(pkt->pkt_scbp) == STATUS_GOOD);
2392 	ASSERT(pkt->pkt_reason == CMD_CMPLT);
2393 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2394 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2395 
2396 	if (pkt->pkt_comp) {
2397 		(*pkt->pkt_comp)(pkt);
2398 	}
2399 	return (DDI_SUCCESS);
2400 }
2401 
2402 /*
2403  * Returns DDI_SUCCESS if next xfer setup successfully, DDI_FAILURE otherwise.
2404  */
2405 static int
2406 scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2407 {
2408 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
2409 
2410 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
2411 
2412 	cmd->sc_resid_blks -= cmd->sc_xfer_blks;
2413 	if (cmd->sc_resid_blks <= 0) {
2414 		pkt->pkt_resid = 0;
2415 		return (DDI_FAILURE);
2416 	}
2417 
2418 	scsa1394_cmd_adjust_cdb(lp, cmd);
2419 
2420 	scsa1394_sbp2_seg2pt(lp, cmd);
2421 
2422 	scsa1394_sbp2_cmd2orb(lp, cmd);
2423 
2424 	if (scsa1394_sbp2_start(lp, cmd) != TRAN_ACCEPT) {
2425 		pkt->pkt_resid = cmd->sc_resid_blks * cmd->sc_blk_size;
2426 		return (DDI_FAILURE);
2427 	}
2428 
2429 	return (DDI_SUCCESS);
2430 }
2431 
2432 /*
2433  * new lba = current lba + previous xfer len
2434  */
2435 /*ARGSUSED*/
2436 static void
2437 scsa1394_cmd_adjust_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2438 {
2439 	int		len;
2440 
2441 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
2442 
2443 	cmd->sc_lba += cmd->sc_xfer_blks;
2444 	len = cmd->sc_resid_blks;
2445 
2446 	/* limit xfer length for Symbios workaround */
2447 	if (len * cmd->sc_blk_size > scsa1394_symbios_size_max) {
2448 		len = scsa1394_symbios_size_max / cmd->sc_blk_size;
2449 	}
2450 
2451 	switch (cmd->sc_cdb[0]) {
2452 	case SCMD_READ_CD:
2453 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
2454 		break;
2455 	case SCMD_WRITE_G5:
2456 	case SCMD_READ_G5:
2457 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
2458 		break;
2459 	case SCMD_WRITE_G1:
2460 	case SCMD_WRITE_LONG:
2461 	default:
2462 		scsa1394_cmd_fill_cdb_len(cmd, len);
2463 	}
2464 
2465 	scsa1394_cmd_fill_cdb_lba(cmd, cmd->sc_lba);
2466 
2467 	cmd->sc_xfer_blks = len;
2468 	cmd->sc_xfer_bytes = len * cmd->sc_blk_size;
2469 }
2470 
2471 void
2472 scsa1394_cmd_status_proc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2473 {
2474 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
2475 
2476 	/* next iteration of partial xfer? */
2477 	if ((pkt->pkt_reason == CMD_CMPLT) &&
2478 	    (cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP)) {
2479 		if (scsa1394_cmd_setup_next_xfer(lp, cmd) == DDI_SUCCESS) {
2480 			return;
2481 		}
2482 	}
2483 	cmd->sc_flags &= ~SCSA1394_CMD_SYMBIOS_BREAKUP;
2484 
2485 	/* apply workarounds */
2486 	if (pkt->pkt_reason == CMD_CMPLT) {
2487 		scsa1394_cmd_status_wrka(lp, cmd);
2488 	}
2489 
2490 	mutex_enter(&lp->l_mutex);
2491 
2492 	/* mode sense workaround */
2493 	if (pkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
2494 		if (pkt->pkt_reason == CMD_CMPLT) {
2495 			lp->l_mode_sense_fail_cnt = 0;
2496 		} else if (++lp->l_mode_sense_fail_cnt >=
2497 		    scsa1394_mode_sense_fail_max) {
2498 			lp->l_mode_sense_fake = B_TRUE;
2499 		}
2500 	} else {
2501 		lp->l_mode_sense_fail_cnt = 0;
2502 	}
2503 
2504 	mutex_exit(&lp->l_mutex);
2505 
2506 	if (pkt->pkt_comp) {
2507 		(*pkt->pkt_comp)(pkt);
2508 	}
2509 }
2510 
2511 static void
2512 scsa1394_cmd_status_wrka(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2513 {
2514 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2515 
2516 	mutex_enter(&lp->l_mutex);
2517 
2518 	switch (pkt->pkt_cdbp[0]) {
2519 	case SCMD_INQUIRY: {
2520 		struct scsi_inquiry *inq;
2521 
2522 		inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
2523 
2524 		/* change dtype RBC to DIRECT, sd doesn't support RBC */
2525 		lp->l_dtype_orig = inq->inq_dtype;
2526 		if ((inq->inq_dtype == SCSA1394_DTYPE_RBC) &&
2527 		    scsa1394_wrka_rbc2direct) {
2528 			inq->inq_dtype = DTYPE_DIRECT;
2529 		}
2530 
2531 		/* force RMB to 1 */
2532 		lp->l_rmb_orig = inq->inq_rmb;
2533 		if (scsa1394_wrka_fake_rmb) {
2534 			inq->inq_rmb = 1;
2535 		}
2536 		break;
2537 	}
2538 	case SCMD_READ_CAPACITY: {
2539 		uint32_t	*capacity_buf;
2540 
2541 		capacity_buf = (uint32_t *)cmd->sc_bp->b_un.b_addr;
2542 
2543 		if (lp->l_dtype_orig != DTYPE_RODIRECT) {
2544 			lp->l_lba_size = min(BE_32(capacity_buf[1]), DEV_BSIZE);
2545 			if (lp->l_lba_size == 0) {
2546 				cmn_err(CE_WARN, "zero LBA size reported, "
2547 				    "possibly broken device");
2548 				lp->l_lba_size = DEV_BSIZE;
2549 			}
2550 		} else {
2551 			lp->l_lba_size = 2048;
2552 		}
2553 	}
2554 	default:
2555 		break;
2556 	}
2557 
2558 	mutex_exit(&lp->l_mutex);
2559 }
2560 
2561 /*
2562  * --- thread management
2563  *
2564  * dispatch a thread
2565  */
2566 int
2567 scsa1394_thr_dispatch(scsa1394_thread_t *thr)
2568 {
2569 	scsa1394_lun_t		*lp = thr->thr_lun;
2570 	scsa1394_state_t	*sp = lp->l_sp;
2571 	int			ret;
2572 
2573 	ASSERT(mutex_owned(&lp->l_mutex));
2574 	ASSERT(thr->thr_state == SCSA1394_THR_INIT);
2575 
2576 	thr->thr_state = SCSA1394_THR_RUN;
2577 
2578 	ret = ddi_taskq_dispatch(sp->s_taskq, thr->thr_func, thr->thr_arg,
2579 	    KM_SLEEP);
2580 	return (ret);
2581 }
2582 
2583 /*
2584  * cancel thread
2585  */
2586 void
2587 scsa1394_thr_cancel(scsa1394_thread_t *thr)
2588 {
2589 	scsa1394_lun_t		*lp = thr->thr_lun;
2590 
2591 	ASSERT(mutex_owned(&lp->l_mutex));
2592 
2593 	thr->thr_req |= SCSA1394_THREQ_EXIT;
2594 	cv_signal(&thr->thr_cv);
2595 
2596 	/* wait until the thread actually exits */
2597 	do {
2598 		if (cv_wait_sig(&thr->thr_cv, &lp->l_mutex) == 0) {
2599 			break;
2600 		}
2601 	} while (thr->thr_state != SCSA1394_THR_EXIT);
2602 }
2603 
2604 /*
2605  * wake thread
2606  */
2607 void
2608 scsa1394_thr_wake(scsa1394_thread_t *thr, int req)
2609 {
2610 	scsa1394_lun_t		*lp = thr->thr_lun;
2611 
2612 	ASSERT(mutex_owned(&lp->l_mutex));
2613 
2614 	thr->thr_req |= req;
2615 	cv_signal(&thr->thr_cv);
2616 }
2617 
2618 void
2619 scsa1394_thr_clear_req(scsa1394_thread_t *thr, int mask)
2620 {
2621 	scsa1394_lun_t		*lp = thr->thr_lun;
2622 
2623 	mutex_enter(&lp->l_mutex);
2624 	thr->thr_req &= ~mask;
2625 	mutex_exit(&lp->l_mutex);
2626 }
2627 
2628 /*
2629  *
2630  * --- other routines
2631  *
2632  */
2633 static boolean_t
2634 scsa1394_is_my_child(dev_info_t *dip)
2635 {
2636 	return ((dip != NULL) && (ddi_prop_exists(DDI_DEV_T_ANY, dip,
2637 	    DDI_PROP_DONTPASS, "scsa1394") == 1));
2638 }
2639 
2640 boolean_t
2641 scsa1394_dev_is_online(scsa1394_state_t *sp)
2642 {
2643 	boolean_t	ret;
2644 
2645 	mutex_enter(&sp->s_mutex);
2646 	ret = (sp->s_dev_state == SCSA1394_DEV_ONLINE);
2647 	mutex_exit(&sp->s_mutex);
2648 
2649 	return (ret);
2650 }
2651 
2652 static void *
2653 scsa1394_kmem_realloc(void *old_buf, int old_size, int new_size, size_t elsize,
2654     int kf)
2655 {
2656 	void	*new_buf;
2657 
2658 	new_buf = kmem_zalloc(new_size * elsize, kf);
2659 
2660 	if (old_size > 0) {
2661 		if (new_buf != NULL) {
2662 			bcopy(old_buf, new_buf, old_size * elsize);
2663 		}
2664 		kmem_free(old_buf, old_size * elsize);
2665 	}
2666 
2667 	return (new_buf);
2668 }
2669