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