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