xref: /illumos-gate/usr/src/uts/common/io/1394/targets/scsa1394/hba.c (revision 65a89a64c60f3061bbe2381edaacc81660af9a95)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * 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_fake_rmb = 0;
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 		    (pnode_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 		/*
736 		 * Some devices don't support LOG SENSE, so tell
737 		 * sd driver not to send this command.
738 		 */
739 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
740 		    "pm-capable", 1);
741 		if (ret != DDI_PROP_SUCCESS) {
742 			ddi_prop_remove_all(cdip);
743 			(void) ndi_devi_free(cdip);
744 			continue;
745 		}
746 
747 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
748 		    "hotpluggable");
749 		if (ret != DDI_PROP_SUCCESS) {
750 			ddi_prop_remove_all(cdip);
751 			(void) ndi_devi_free(cdip);
752 			continue;
753 		}
754 
755 		if (driver_name) {
756 			compatible[0] = driver_name;
757 			ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
758 			    "compatible", (char **)compatible,
759 			    SCSA1394_COMPAT_MAX);
760 			if (ret != DDI_PROP_SUCCESS) {
761 				ddi_prop_remove_all(cdip);
762 				(void) ndi_devi_free(cdip);
763 				continue;
764 			}
765 		}
766 
767 		/*
768 		 * add property "scsa1394" to distinguish from others' children
769 		 */
770 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
771 		if (ret != DDI_PROP_SUCCESS) {
772 			ddi_prop_remove_all(cdip);
773 			(void) ndi_devi_free(cdip);
774 			continue;
775 		}
776 
777 		(void) ddi_initchild(sp->s_dip, cdip);
778 	}
779 }
780 
781 /*ARGSUSED*/
782 static void
783 scsa1394_bus_reset(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
784     void *data)
785 {
786 	scsa1394_state_t	*sp = arg;
787 
788 	if (sp != NULL) {
789 		mutex_enter(&sp->s_mutex);
790 		if (sp->s_dev_state == SCSA1394_DEV_DISCONNECTED) {
791 			mutex_exit(&sp->s_mutex);
792 			return;
793 		}
794 		sp->s_stat.stat_bus_reset_cnt++;
795 		sp->s_dev_state = SCSA1394_DEV_BUS_RESET;
796 		sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
797 		mutex_exit(&sp->s_mutex);
798 
799 		scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_BUS_RESET);
800 	}
801 }
802 
803 /*ARGSUSED*/
804 static void
805 scsa1394_disconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
806     void *data)
807 {
808 	scsa1394_state_t	*sp = arg;
809 	int			circ;
810 	dev_info_t		*cdip, *cdip_next;
811 
812 	if (sp == NULL) {
813 		return;
814 	}
815 
816 	mutex_enter(&sp->s_mutex);
817 	sp->s_stat.stat_disconnect_cnt++;
818 	sp->s_dev_state = SCSA1394_DEV_DISCONNECTED;
819 	mutex_exit(&sp->s_mutex);
820 
821 	scsa1394_sbp2_disconnect(sp);
822 
823 	ndi_devi_enter(dip, &circ);
824 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
825 		cdip_next = ddi_get_next_sibling(cdip);
826 
827 		mutex_enter(&DEVI(cdip)->devi_lock);
828 		DEVI_SET_DEVICE_REMOVED(cdip);
829 		mutex_exit(&DEVI(cdip)->devi_lock);
830 	}
831 	ndi_devi_exit(dip, circ);
832 }
833 
834 /*ARGSUSED*/
835 static void
836 scsa1394_reconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
837     void *data)
838 {
839 	scsa1394_state_t	*sp = arg;
840 	int			circ;
841 	dev_info_t		*cdip, *cdip_next;
842 
843 	if (sp == NULL) {
844 		return;
845 	}
846 
847 	mutex_enter(&sp->s_mutex);
848 	sp->s_stat.stat_reconnect_cnt++;
849 	sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
850 	sp->s_disconnect_warned = B_FALSE;
851 	mutex_exit(&sp->s_mutex);
852 
853 	ndi_devi_enter(dip, &circ);
854 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
855 		cdip_next = ddi_get_next_sibling(cdip);
856 
857 		mutex_enter(&DEVI(cdip)->devi_lock);
858 		DEVI_SET_DEVICE_REINSERTED(cdip);
859 		mutex_exit(&DEVI(cdip)->devi_lock);
860 	}
861 	ndi_devi_exit(dip, circ);
862 
863 	scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_RECONNECT);
864 }
865 
866 /*
867  *
868  * --- SCSA entry points
869  *
870  */
871 /*ARGSUSED*/
872 static int
873 scsa1394_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
874     struct scsi_device *sd)
875 {
876 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
877 	int		lun;
878 	int		plen = sizeof (int);
879 	int		ret = DDI_FAILURE;
880 
881 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
882 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun,
883 	    &plen) != DDI_PROP_SUCCESS) {
884 		return (DDI_FAILURE);
885 	}
886 
887 	if (!scsa1394_is_my_child(cdip)) {
888 		/*
889 		 * add property "scsa1394" to distinguish from others' children
890 		 */
891 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
892 		if (ret != DDI_PROP_SUCCESS) {
893 			return (DDI_FAILURE);
894 		}
895 
896 		if (scsa1394_dev_is_online(sp)) {
897 			return (scsa1394_sbp2_login(sp, lun));
898 		} else {
899 			return (DDI_FAILURE);
900 		}
901 	}
902 
903 	if ((lun >= sp->s_nluns) || (sp->s_lun[lun].l_cdip != NULL) ||
904 	    !scsa1394_dev_is_online(sp)) {
905 		return (DDI_FAILURE);
906 	}
907 
908 	if ((ret = scsa1394_sbp2_login(sp, lun)) == DDI_SUCCESS) {
909 		sp->s_lun[lun].l_cdip = cdip;
910 	}
911 	return (ret);
912 }
913 
914 /*ARGSUSED*/
915 static void
916 scsa1394_scsi_tgt_free(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
917     struct scsi_device *sd)
918 {
919 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
920 	int		lun;
921 	int		plen = sizeof (int);
922 
923 	if (!scsa1394_is_my_child(cdip)) {
924 		return;
925 	}
926 
927 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
928 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun,
929 	    &plen) != DDI_PROP_SUCCESS) {
930 		return;
931 	}
932 
933 	if ((lun < sp->s_nluns) && (sp->s_lun[lun].l_cdip == cdip)) {
934 		if (scsa1394_dev_is_online(sp)) {
935 			scsa1394_sbp2_logout(sp, lun, B_TRUE);
936 		}
937 		sp->s_lun[lun].l_cdip = NULL;
938 	}
939 }
940 
941 static int
942 scsa1394_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
943 {
944 	dev_info_t	*dip = ddi_get_parent(sd->sd_dev);
945 	scsi_hba_tran_t	*tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
946 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
947 	scsa1394_lun_t	*lp;
948 
949 	if (!scsa1394_dev_is_online(sp)) {
950 		return (SCSIPROBE_FAILURE);
951 	}
952 	lp = &sp->s_lun[sd->sd_address.a_lun];
953 
954 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
955 	    SCMD_TEST_UNIT_READY, 0, 0) != SCSIPROBE_EXISTS) {
956 		lp->l_nosup_tur = B_TRUE;
957 		(void) scsa1394_sbp2_reset(lp, RESET_LUN, NULL);
958 	}
959 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
960 	    SCMD_START_STOP, 0, 1) != SCSIPROBE_EXISTS) {
961 		lp->l_nosup_start_stop = B_TRUE;
962 	}
963 
964 	/* standard probe issues INQUIRY, which some devices may not support */
965 	if (scsi_hba_probe(sd, waitfunc) != SCSIPROBE_EXISTS) {
966 		lp->l_nosup_inquiry = B_TRUE;
967 		scsa1394_sbp2_fake_inquiry(sp, &lp->l_fake_inq);
968 		bcopy(&lp->l_fake_inq, sd->sd_inq, SUN_INQSIZE);
969 #ifndef __lock_lint
970 		lp->l_rmb_orig = 1;
971 #endif
972 	}
973 
974 	if (scsa1394_wrka_fake_rmb) {
975 		sd->sd_inq->inq_rmb = 1;
976 	}
977 
978 	return (SCSIPROBE_EXISTS);
979 }
980 
981 static int
982 scsa1394_probe_g0_nodata(struct scsi_device *sd, int (*waitfunc)(),
983     uchar_t cmd, uint_t addr, uint_t cnt)
984 {
985 	struct scsi_pkt	*pkt;
986 	int		ret = SCSIPROBE_EXISTS;
987 
988 	pkt = scsi_init_pkt(&sd->sd_address, NULL, NULL, CDB_GROUP0,
989 	    sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, waitfunc, NULL);
990 
991 	if (pkt == NULL) {
992 		return (SCSIPROBE_NOMEM);
993 	}
994 
995 	(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp, cmd, addr, cnt,
996 	    0);
997 	((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = sd->sd_address.a_lun;
998 	pkt->pkt_flags = FLAG_NOINTR;
999 
1000 	if (scsa1394_probe_tran(pkt) < 0) {
1001 		if (pkt->pkt_reason == CMD_INCOMPLETE) {
1002 			ret = SCSIPROBE_NORESP;
1003 		} else {
1004 			ret = SCSIPROBE_FAILURE;
1005 		}
1006 	}
1007 
1008 	scsi_destroy_pkt(pkt);
1009 
1010 	return (ret);
1011 }
1012 
1013 static int
1014 scsa1394_probe_tran(struct scsi_pkt *pkt)
1015 {
1016 	pkt->pkt_time = SCSA1394_PROBE_TIMEOUT;
1017 
1018 	if (scsi_transport(pkt) != TRAN_ACCEPT) {
1019 		return (-1);
1020 	} else if ((pkt->pkt_reason == CMD_INCOMPLETE) &&
1021 	    (pkt->pkt_state == 0)) {
1022 		return (-1);
1023 	} else if (pkt->pkt_reason != CMD_CMPLT) {
1024 		return (-1);
1025 	} else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) {
1026 		return (0);
1027 	}
1028 	return (0);
1029 }
1030 
1031 /*ARGSUSED*/
1032 static int
1033 scsa1394_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1034 {
1035 	return (0);
1036 }
1037 
1038 static int
1039 scsa1394_scsi_reset(struct scsi_address *ap, int level)
1040 {
1041 	scsa1394_state_t *sp = ADDR2STATE(ap);
1042 	scsa1394_lun_t	*lp;
1043 	int		ret;
1044 
1045 	switch (level) {
1046 	case RESET_ALL:
1047 	case RESET_TARGET:
1048 		lp = &sp->s_lun[0];
1049 		break;
1050 	case RESET_LUN:
1051 		lp = &sp->s_lun[ap->a_lun];
1052 		break;
1053 	default:
1054 		return (DDI_FAILURE);
1055 	}
1056 
1057 	ret = scsa1394_sbp2_reset(lp, level, NULL);
1058 
1059 	return ((ret == SBP2_SUCCESS) ? 1 : 0);
1060 }
1061 
1062 /*ARGSUSED*/
1063 static int
1064 scsa1394_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
1065 {
1066 	scsa1394_state_t *sp = ADDR2STATE(ap);
1067 	size_t		dev_bsize_cap;
1068 	int		ret = -1;
1069 
1070 	if (!scsa1394_dev_is_online(sp)) {
1071 		return (-1);
1072 	}
1073 
1074 	if (cap == NULL) {
1075 		return (-1);
1076 	}
1077 
1078 	switch (scsi_hba_lookup_capstr(cap)) {
1079 	case SCSI_CAP_DMA_MAX:
1080 		ret = sp->s_attachinfo.dma_attr.dma_attr_maxxfer;
1081 		break;
1082 	case SCSI_CAP_SCSI_VERSION:
1083 		ret = SCSI_VERSION_2;
1084 		break;
1085 	case SCSI_CAP_ARQ:
1086 		ret = 1;
1087 		break;
1088 	case SCSI_CAP_UNTAGGED_QING:
1089 		ret = 1;
1090 		break;
1091 	case SCSI_CAP_GEOMETRY:
1092 		dev_bsize_cap = sp->s_totalsec;
1093 
1094 		if (sp->s_secsz > DEV_BSIZE) {
1095 			dev_bsize_cap *= sp->s_secsz / DEV_BSIZE;
1096 		} else if (sp->s_secsz < DEV_BSIZE) {
1097 			dev_bsize_cap /= DEV_BSIZE / sp->s_secsz;
1098 		}
1099 
1100 		if (dev_bsize_cap < 65536 * 2 * 18) {		/* < ~1GB */
1101 			/* unlabeled floppy, 18k per cylinder */
1102 			ret = ((2 << 16) | 18);
1103 		} else if (dev_bsize_cap < 65536 * 64 * 32) {	/* < 64GB */
1104 			/* 1024k per cylinder */
1105 			ret = ((64 << 16) | 32);
1106 		} else if (dev_bsize_cap < 65536 * 255 * 63) {	/* < ~500GB */
1107 			/* ~8m per cylinder */
1108 			ret = ((255 << 16) | 63);
1109 		} else {					/* .. 8TB */
1110 			/* 64m per cylinder */
1111 			ret = ((512 << 16) | 256);
1112 		}
1113 		break;
1114 	default:
1115 		break;
1116 	}
1117 
1118 	return (ret);
1119 }
1120 
1121 /*ARGSUSED*/
1122 static int
1123 scsa1394_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1124 {
1125 	scsa1394_state_t *sp = ADDR2STATE(ap);
1126 	int		ret = -1;
1127 
1128 	if (!scsa1394_dev_is_online(sp)) {
1129 		return (-1);
1130 	}
1131 
1132 	switch (scsi_hba_lookup_capstr(cap)) {
1133 	case SCSI_CAP_ARQ:
1134 		ret = 1;
1135 		break;
1136 	case SCSI_CAP_DMA_MAX:
1137 	case SCSI_CAP_SCSI_VERSION:
1138 	case SCSI_CAP_UNTAGGED_QING:
1139 		/* supported but not settable */
1140 		ret = 0;
1141 		break;
1142 	case SCSI_CAP_SECTOR_SIZE:
1143 		if (value) {
1144 			sp->s_secsz = value;
1145 		}
1146 		break;
1147 	case SCSI_CAP_TOTAL_SECTORS:
1148 		if (value) {
1149 			sp->s_totalsec = value;
1150 		}
1151 		break;
1152 	default:
1153 		break;
1154 	}
1155 
1156 	return (ret);
1157 }
1158 
1159 /*ARGSUSED*/
1160 static void
1161 scsa1394_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1162 {
1163 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1164 
1165 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1166 		(void) ddi_dma_sync(cmd->sc_buf_dma_hdl, 0, 0,
1167 		    (cmd->sc_flags & SCSA1394_CMD_READ) ?
1168 		    DDI_DMA_SYNC_FORCPU : DDI_DMA_SYNC_FORDEV);
1169 	}
1170 }
1171 
1172 /*
1173  *
1174  * --- pkt resource allocation routines
1175  *
1176  */
1177 static struct scsi_pkt *
1178 scsa1394_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
1179     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
1180     int (*callback)(), caddr_t arg)
1181 {
1182 	scsa1394_state_t *sp = ADDR2STATE(ap);
1183 	scsa1394_lun_t	*lp;
1184 	scsa1394_cmd_t	*cmd;
1185 	boolean_t	is_new;	/* new cmd is being allocated */
1186 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
1187 
1188 	if (ap->a_lun >= sp->s_nluns) {
1189 		return (NULL);
1190 	}
1191 	lp = &sp->s_lun[ap->a_lun];
1192 
1193 	/*
1194 	 * allocate cmd space
1195 	 */
1196 	if (pkt == NULL) {
1197 		is_new = B_TRUE;
1198 		if ((cmd = kmem_cache_alloc(sp->s_cmd_cache, kf)) == NULL) {
1199 			return (NULL);
1200 		}
1201 
1202 		/* initialize cmd */
1203 		pkt = &cmd->sc_scsi_pkt;
1204 		pkt->pkt_ha_private	= cmd;
1205 		pkt->pkt_address	= *ap;
1206 		pkt->pkt_private	= cmd->sc_priv;
1207 		pkt->pkt_scbp		= (uchar_t *)&cmd->sc_scb;
1208 		pkt->pkt_cdbp		= (uchar_t *)&cmd->sc_pkt_cdb;
1209 		pkt->pkt_resid		= 0;
1210 
1211 		cmd->sc_lun		= lp;
1212 		cmd->sc_pkt		= pkt;
1213 		cmd->sc_cdb_len		= cmdlen;
1214 		cmd->sc_scb_len		= statuslen;
1215 		cmd->sc_priv_len	= tgtlen;
1216 
1217 		/* need external space? */
1218 		if ((cmdlen > sizeof (cmd->sc_pkt_cdb)) ||
1219 		    (statuslen > sizeof (cmd->sc_scb)) ||
1220 		    (tgtlen > sizeof (cmd->sc_priv))) {
1221 			if (scsa1394_cmd_ext_alloc(sp, cmd, kf) !=
1222 			    DDI_SUCCESS) {
1223 				kmem_cache_free(sp->s_cmd_cache, cmd);
1224 				lp->l_stat.stat_err_pkt_kmem_alloc++;
1225 				return (NULL);
1226 			}
1227 		}
1228 
1229 		/* allocate DMA resources for CDB */
1230 		if (scsa1394_cmd_cdb_dma_alloc(sp, cmd, flags, callback, arg) !=
1231 		    DDI_SUCCESS) {
1232 			scsa1394_scsi_destroy_pkt(ap, pkt);
1233 			return (NULL);
1234 		}
1235 	} else {
1236 		is_new = B_FALSE;
1237 		cmd = PKT2CMD(pkt);
1238 	}
1239 
1240 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
1241 
1242 	/* allocate/move DMA resources for data buffer */
1243 	if ((bp != NULL) && (bp->b_bcount > 0)) {
1244 		if ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) == 0) {
1245 			if (scsa1394_cmd_buf_dma_alloc(sp, cmd, flags, callback,
1246 			    arg, bp) != DDI_SUCCESS) {
1247 				if (is_new) {
1248 					scsa1394_scsi_destroy_pkt(ap, pkt);
1249 				}
1250 				return (NULL);
1251 			}
1252 		} else {
1253 			if (scsa1394_cmd_buf_dma_move(sp, cmd) != DDI_SUCCESS) {
1254 				return (NULL);
1255 			}
1256 		}
1257 
1258 		ASSERT(cmd->sc_win_len > 0);
1259 		pkt->pkt_resid = bp->b_bcount - cmd->sc_win_len;
1260 	}
1261 
1262 	/*
1263 	 * kernel virtual address may be required for certain workarounds
1264 	 * and in case of B_PHYS or B_PAGEIO, bp_mapin() will get it for us
1265 	 */
1266 	if ((bp != NULL) && ((bp->b_flags & (B_PAGEIO | B_PHYS)) != 0) &&
1267 	    (bp->b_bcount < SCSA1394_MAPIN_SIZE_MAX) &&
1268 	    ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) == 0)) {
1269 		bp_mapin(bp);
1270 		cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_MAPIN;
1271 	}
1272 
1273 	return (pkt);
1274 }
1275 
1276 static void
1277 scsa1394_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1278 {
1279 	scsa1394_state_t *sp = ADDR2STATE(ap);
1280 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1281 
1282 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1283 		scsa1394_cmd_buf_dma_free(sp, cmd);
1284 	}
1285 	if (cmd->sc_flags & SCSA1394_CMD_DMA_CDB_VALID) {
1286 		scsa1394_cmd_cdb_dma_free(sp, cmd);
1287 	}
1288 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
1289 		bp_mapout(cmd->sc_bp);
1290 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
1291 	}
1292 	if (cmd->sc_flags & SCSA1394_CMD_EXT) {
1293 		scsa1394_cmd_ext_free(sp, cmd);
1294 	}
1295 
1296 	kmem_cache_free(sp->s_cmd_cache, cmd);
1297 }
1298 
1299 static void
1300 scsa1394_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1301 {
1302 	scsa1394_state_t *sp = ADDR2STATE(ap);
1303 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1304 
1305 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1306 		scsa1394_cmd_buf_dma_free(sp, cmd);
1307 	}
1308 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
1309 		bp_mapout(cmd->sc_bp);
1310 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
1311 	}
1312 }
1313 
1314 /*ARGSUSED*/
1315 static int
1316 scsa1394_cmd_cache_constructor(void *buf, void *cdrarg, int kf)
1317 {
1318 	scsa1394_cmd_t	*cmd = buf;
1319 
1320 	bzero(buf, sizeof (scsa1394_cmd_t));
1321 	cmd->sc_task.ts_drv_priv = cmd;
1322 
1323 	return (0);
1324 }
1325 
1326 /*ARGSUSED*/
1327 static void
1328 scsa1394_cmd_cache_destructor(void *buf, void *cdrarg)
1329 {
1330 }
1331 
1332 /*
1333  * allocate and deallocate external cmd space (ie. not part of scsa1394_cmd_t)
1334  * for non-standard length cdb, pkt_private, status areas
1335  */
1336 static int
1337 scsa1394_cmd_ext_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd, int kf)
1338 {
1339 	struct scsi_pkt	*pkt = cmd->sc_pkt;
1340 	void		*buf;
1341 
1342 	if (cmd->sc_cdb_len > sizeof (cmd->sc_pkt_cdb)) {
1343 		if ((buf = kmem_zalloc(cmd->sc_cdb_len, kf)) == NULL) {
1344 			return (DDI_FAILURE);
1345 		}
1346 		pkt->pkt_cdbp = buf;
1347 		cmd->sc_flags |= SCSA1394_CMD_CDB_EXT;
1348 	}
1349 
1350 	if (cmd->sc_scb_len > sizeof (cmd->sc_scb)) {
1351 		if ((buf = kmem_zalloc(cmd->sc_scb_len, kf)) == NULL) {
1352 			scsa1394_cmd_ext_free(sp, cmd);
1353 			return (DDI_FAILURE);
1354 		}
1355 		pkt->pkt_scbp = buf;
1356 		cmd->sc_flags |= SCSA1394_CMD_SCB_EXT;
1357 	}
1358 
1359 	if (cmd->sc_priv_len > sizeof (cmd->sc_priv)) {
1360 		if ((buf = kmem_zalloc(cmd->sc_priv_len, kf)) == NULL) {
1361 			scsa1394_cmd_ext_free(sp, cmd);
1362 			return (DDI_FAILURE);
1363 		}
1364 		pkt->pkt_private = buf;
1365 		cmd->sc_flags |= SCSA1394_CMD_PRIV_EXT;
1366 	}
1367 
1368 	return (DDI_SUCCESS);
1369 }
1370 
1371 /*ARGSUSED*/
1372 static void
1373 scsa1394_cmd_ext_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1374 {
1375 	struct scsi_pkt	*pkt = cmd->sc_pkt;
1376 
1377 	if (cmd->sc_flags & SCSA1394_CMD_CDB_EXT) {
1378 		kmem_free(pkt->pkt_cdbp, cmd->sc_cdb_len);
1379 	}
1380 	if (cmd->sc_flags & SCSA1394_CMD_SCB_EXT) {
1381 		kmem_free(pkt->pkt_scbp, cmd->sc_scb_len);
1382 	}
1383 	if (cmd->sc_flags & SCSA1394_CMD_PRIV_EXT) {
1384 		kmem_free(pkt->pkt_private, cmd->sc_priv_len);
1385 	}
1386 	cmd->sc_flags &= ~SCSA1394_CMD_EXT;
1387 }
1388 
1389 /*ARGSUSED*/
1390 static int
1391 scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1392     int flags, int (*callback)(), caddr_t arg)
1393 {
1394 	if (sbp2_task_orb_alloc(cmd->sc_lun->l_lun, &cmd->sc_task,
1395 	    sizeof (scsa1394_cmd_orb_t)) != SBP2_SUCCESS) {
1396 		return (DDI_FAILURE);
1397 	}
1398 
1399 	cmd->sc_flags |= SCSA1394_CMD_DMA_CDB_VALID;
1400 	return (DDI_SUCCESS);
1401 }
1402 
1403 /*ARGSUSED*/
1404 static void
1405 scsa1394_cmd_cdb_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1406 {
1407 	sbp2_task_orb_free(cmd->sc_lun->l_lun, &cmd->sc_task);
1408 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_CDB_VALID;
1409 }
1410 
1411 /*
1412  * buffer resources
1413  */
1414 static int
1415 scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1416     int flags, int (*callback)(), caddr_t arg, struct buf *bp)
1417 {
1418 	scsa1394_lun_t	*lp = cmd->sc_lun;
1419 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
1420 	int		dma_flags;
1421 	ddi_dma_cookie_t dmac;
1422 	uint_t		ccount;
1423 	int		error;
1424 	int		ret;
1425 
1426 	cmd->sc_bp = bp;
1427 
1428 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_buf_dma_attr, callback,
1429 	    NULL, &cmd->sc_buf_dma_hdl)) != DDI_SUCCESS) {
1430 		bioerror(bp, 0);
1431 		return (DDI_FAILURE);
1432 	}
1433 
1434 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
1435 	if (bp->b_flags & B_READ) {
1436 		dma_flags = DDI_DMA_READ;
1437 		cmd->sc_flags |= SCSA1394_CMD_READ;
1438 	} else {
1439 		dma_flags = DDI_DMA_WRITE;
1440 		cmd->sc_flags |= SCSA1394_CMD_WRITE;
1441 	}
1442 	if (flags & PKT_CONSISTENT) {
1443 		dma_flags |= DDI_DMA_CONSISTENT;
1444 	}
1445 	if (flags & PKT_DMA_PARTIAL) {
1446 		dma_flags |= DDI_DMA_PARTIAL;
1447 	}
1448 
1449 	ret = ddi_dma_buf_bind_handle(cmd->sc_buf_dma_hdl, bp, dma_flags,
1450 	    callback, arg, &dmac, &ccount);
1451 
1452 	switch (ret) {
1453 	case DDI_DMA_MAPPED:
1454 		cmd->sc_nwin = 1;
1455 		cmd->sc_curwin = 0;
1456 		cmd->sc_win_offset = 0;
1457 		cmd->sc_win_len = bp->b_bcount;
1458 		break;
1459 
1460 	case DDI_DMA_PARTIAL_MAP:
1461 		/* retrieve number of windows and first window cookie */
1462 		cmd->sc_curwin = 0;
1463 		if ((ddi_dma_numwin(cmd->sc_buf_dma_hdl, &cmd->sc_nwin) !=
1464 		    DDI_SUCCESS) ||
1465 		    (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
1466 		    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
1467 		    DDI_SUCCESS)) {
1468 			(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
1469 			ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1470 			return (DDI_FAILURE);
1471 		}
1472 		lp->l_stat.stat_cmd_buf_dma_partial++;
1473 		break;
1474 
1475 	case DDI_DMA_NORESOURCES:
1476 		error = 0;
1477 		goto map_error;
1478 
1479 	case DDI_DMA_BADATTR:
1480 	case DDI_DMA_NOMAPPING:
1481 		error = EFAULT;
1482 		goto map_error;
1483 
1484 	default:
1485 		error = EINVAL;
1486 
1487 	map_error:
1488 		bioerror(bp, error);
1489 		lp->l_stat.stat_err_cmd_buf_dbind++;
1490 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1491 		return (DDI_FAILURE);
1492 	}
1493 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_BIND_VALID;
1494 
1495 	/*
1496 	 * setup page table if needed
1497 	 */
1498 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1499 	    (!sp->s_symbios ||
1500 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
1501 		cmd->sc_buf_nsegs = 1;
1502 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
1503 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
1504 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
1505 	} else {
1506 		/* break window into segments */
1507 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, kf) !=
1508 		    DDI_SUCCESS) {
1509 			scsa1394_cmd_buf_dma_free(sp, cmd);
1510 			bioerror(bp, 0);
1511 			return (DDI_FAILURE);
1512 		}
1513 
1514 		/* allocate DMA resources for page table */
1515 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, callback, arg,
1516 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
1517 			scsa1394_cmd_buf_dma_free(sp, cmd);
1518 			bioerror(bp, 0);
1519 			return (DDI_FAILURE);
1520 		}
1521 	}
1522 
1523 	/* allocate 1394 addresses for segments */
1524 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
1525 		scsa1394_cmd_buf_dma_free(sp, cmd);
1526 		bioerror(bp, 0);
1527 		return (DDI_FAILURE);
1528 	}
1529 
1530 	return (DDI_SUCCESS);
1531 }
1532 
1533 static void
1534 scsa1394_cmd_buf_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1535 {
1536 	scsa1394_cmd_buf_addr_free(sp, cmd);
1537 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1538 		scsa1394_cmd_pt_dma_free(sp, cmd);
1539 	}
1540 	scsa1394_cmd_seg_free(sp, cmd);
1541 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_BIND_VALID) {
1542 		(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
1543 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1544 	}
1545 	cmd->sc_flags &= ~(SCSA1394_CMD_DMA_BUF_VALID | SCSA1394_CMD_RDWR);
1546 }
1547 
1548 /*
1549  * Break a set DMA cookies into segments suitable for SBP-2 page table.
1550  * This routine can reuse/reallocate segment array from previous calls.
1551  */
1552 static int
1553 scsa1394_cmd_dmac2seg(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1554     ddi_dma_cookie_t *dmac, uint_t ccount, int kf)
1555 {
1556 	scsa1394_lun_t	*lp = cmd->sc_lun;
1557 	int		i;
1558 	int		nsegs;
1559 	size_t		segsize_max;
1560 	size_t		dmac_resid;
1561 	uint32_t	dmac_addr;
1562 	scsa1394_cmd_seg_t *seg;
1563 
1564 	if (!sp->s_symbios) {
1565 		/*
1566 		 * Number of segments is unknown at this point. Start with
1567 		 * a reasonable estimate and grow it later if needed.
1568 		 */
1569 		nsegs = max(ccount, cmd->sc_win_len / SBP2_PT_SEGSIZE_MAX) * 2;
1570 		segsize_max = SBP2_PT_SEGSIZE_MAX;
1571 	} else {
1572 		/*
1573 		 * For Symbios workaround we know exactly the number of segments
1574 		 * Additional segment may be needed if buffer is not aligned.
1575 		 */
1576 		nsegs =
1577 		    howmany(cmd->sc_win_len, scsa1394_symbios_page_size) + 1;
1578 		segsize_max = scsa1394_symbios_page_size;
1579 	}
1580 
1581 	if (nsegs > cmd->sc_buf_nsegs_alloc) {
1582 		if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(cmd->sc_buf_seg,
1583 		    cmd->sc_buf_nsegs_alloc, nsegs,
1584 		    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
1585 			cmd->sc_buf_nsegs_alloc = 0;
1586 			return (DDI_FAILURE);
1587 		}
1588 		cmd->sc_buf_nsegs_alloc = nsegs;
1589 	}
1590 
1591 	/* each cookie maps into one or more segments */
1592 	cmd->sc_buf_nsegs = 0;
1593 	i = ccount;
1594 	for (;;) {
1595 		dmac_resid = dmac->dmac_size;
1596 		dmac_addr = dmac->dmac_address;
1597 		while (dmac_resid > 0) {
1598 			/* grow array if needed */
1599 			if (cmd->sc_buf_nsegs >= cmd->sc_buf_nsegs_alloc) {
1600 				if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(
1601 				    cmd->sc_buf_seg,
1602 				    cmd->sc_buf_nsegs_alloc,
1603 				    cmd->sc_buf_nsegs_alloc + ccount,
1604 				    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
1605 					return (DDI_FAILURE);
1606 				}
1607 				cmd->sc_buf_nsegs_alloc += ccount;
1608 			}
1609 
1610 			seg = &cmd->sc_buf_seg[cmd->sc_buf_nsegs];
1611 			seg->ss_len = min(dmac_resid, segsize_max);
1612 			seg->ss_daddr = (uint64_t)dmac_addr;
1613 			dmac_addr += seg->ss_len;
1614 			dmac_resid -= seg->ss_len;
1615 			cmd->sc_buf_nsegs++;
1616 		}
1617 		ASSERT(dmac_resid == 0);
1618 
1619 		/* grab next cookie */
1620 		if (--i <= 0) {
1621 			break;
1622 		}
1623 		ddi_dma_nextcookie(cmd->sc_buf_dma_hdl, dmac);
1624 	}
1625 
1626 	if (cmd->sc_buf_nsegs > lp->l_stat.stat_cmd_buf_max_nsegs) {
1627 		lp->l_stat.stat_cmd_buf_max_nsegs = cmd->sc_buf_nsegs;
1628 	}
1629 
1630 	return (DDI_SUCCESS);
1631 }
1632 
1633 /*ARGSUSED*/
1634 static void
1635 scsa1394_cmd_seg_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1636 {
1637 	if (cmd->sc_buf_nsegs_alloc > 0) {
1638 		kmem_free(cmd->sc_buf_seg, cmd->sc_buf_nsegs_alloc *
1639 		    sizeof (scsa1394_cmd_seg_t));
1640 	}
1641 	cmd->sc_buf_seg = NULL;
1642 	cmd->sc_buf_nsegs = 0;
1643 	cmd->sc_buf_nsegs_alloc = 0;
1644 }
1645 
1646 static int
1647 scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1648     int (*callback)(), caddr_t arg, int cnt)
1649 {
1650 	scsa1394_lun_t	*lp = cmd->sc_lun;
1651 	size_t		len, rlen;
1652 	uint_t		ccount;
1653 	t1394_alloc_addr_t aa;
1654 	int		result;
1655 
1656 	/* allocate DMA memory for page table */
1657 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_pt_dma_attr,
1658 	    callback, NULL, &cmd->sc_pt_dma_hdl)) != DDI_SUCCESS) {
1659 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1660 		return (DDI_FAILURE);
1661 	}
1662 
1663 	cmd->sc_pt_ent_alloc = cnt;
1664 	len = cmd->sc_pt_ent_alloc * SBP2_PT_ENT_SIZE;
1665 	if (ddi_dma_mem_alloc(cmd->sc_pt_dma_hdl, len,
1666 	    &sp->s_attachinfo.acc_attr, DDI_DMA_CONSISTENT, callback, arg,
1667 	    &cmd->sc_pt_kaddr, &rlen, &cmd->sc_pt_acc_hdl) != DDI_SUCCESS) {
1668 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1669 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1670 		return (DDI_FAILURE);
1671 	}
1672 
1673 	if (ddi_dma_addr_bind_handle(cmd->sc_pt_dma_hdl, NULL,
1674 	    cmd->sc_pt_kaddr, len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
1675 	    callback, arg, &cmd->sc_pt_dmac, &ccount) != DDI_DMA_MAPPED) {
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_dmem_alloc++;
1679 		return (DDI_FAILURE);
1680 	}
1681 	ASSERT(ccount == 1);	/* because dma_attr_sgllen is 1 */
1682 
1683 	/* allocate 1394 address for page table */
1684 	aa.aa_type = T1394_ADDR_FIXED;
1685 	aa.aa_length = len;
1686 	aa.aa_address = cmd->sc_pt_dmac.dmac_address;
1687 	aa.aa_evts.recv_read_request = NULL;
1688 	aa.aa_evts.recv_write_request = NULL;
1689 	aa.aa_evts.recv_lock_request = NULL;
1690 	aa.aa_arg = NULL;
1691 	aa.aa_kmem_bufp = NULL;
1692 	aa.aa_enable = T1394_ADDR_RDENBL;
1693 	if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) != DDI_SUCCESS) {
1694 		(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
1695 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1696 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1697 		lp->l_stat.stat_err_cmd_pt_addr_alloc++;
1698 		return (DDI_FAILURE);
1699 	}
1700 	ASSERT(aa.aa_address != 0);
1701 	cmd->sc_pt_baddr = aa.aa_address;
1702 	cmd->sc_pt_addr_hdl = aa.aa_hdl;
1703 
1704 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_PT_VALID;
1705 
1706 	return (DDI_SUCCESS);
1707 }
1708 
1709 static void
1710 scsa1394_cmd_pt_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1711 {
1712 	(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
1713 	ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1714 	ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1715 	(void) t1394_free_addr(sp->s_t1394_hdl, &cmd->sc_pt_addr_hdl, 0);
1716 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_PT_VALID;
1717 }
1718 
1719 /*
1720  * allocate 1394 addresses for all buffer segments
1721  */
1722 static int
1723 scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1724 {
1725 	scsa1394_lun_t	*lp = cmd->sc_lun;
1726 	t1394_alloc_addr_t aa;
1727 	scsa1394_cmd_seg_t *seg;
1728 	int		result;
1729 	int		i;
1730 
1731 	aa.aa_type = T1394_ADDR_FIXED;
1732 	aa.aa_evts.recv_read_request = NULL;
1733 	aa.aa_evts.recv_write_request = NULL;
1734 	aa.aa_evts.recv_lock_request = NULL;
1735 	aa.aa_arg = NULL;
1736 	aa.aa_kmem_bufp = NULL;
1737 	if (cmd->sc_flags & SCSA1394_CMD_READ) {
1738 		aa.aa_enable = T1394_ADDR_RDENBL;
1739 	} else {
1740 		aa.aa_enable = T1394_ADDR_WRENBL;
1741 	}
1742 
1743 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
1744 		seg = &cmd->sc_buf_seg[i];
1745 
1746 		/* segment bus address */
1747 		aa.aa_length = seg->ss_len;
1748 		aa.aa_address = seg->ss_daddr;
1749 
1750 		if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) !=
1751 		    DDI_SUCCESS) {
1752 			lp->l_stat.stat_err_cmd_buf_addr_alloc++;
1753 			return (DDI_FAILURE);
1754 		}
1755 		ASSERT(aa.aa_address != 0);
1756 		seg->ss_baddr = aa.aa_address;
1757 		seg->ss_addr_hdl = aa.aa_hdl;
1758 	}
1759 
1760 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_ADDR_VALID;
1761 
1762 	return (DDI_SUCCESS);
1763 }
1764 
1765 static void
1766 scsa1394_cmd_buf_addr_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1767 {
1768 	int		i;
1769 
1770 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
1771 		if (cmd->sc_buf_seg[i].ss_addr_hdl) {
1772 			(void) t1394_free_addr(sp->s_t1394_hdl,
1773 			    &cmd->sc_buf_seg[i].ss_addr_hdl, 0);
1774 		}
1775 	}
1776 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_ADDR_VALID;
1777 }
1778 
1779 /*
1780  * move to next DMA window
1781  */
1782 static int
1783 scsa1394_cmd_buf_dma_move(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1784 {
1785 	/* scsa1394_lun_t	*lp = cmd->sc_lun; */
1786 	ddi_dma_cookie_t dmac;
1787 	uint_t		ccount;
1788 
1789 	/* for small pkts, leave things where they are (says WDD) */
1790 	if ((cmd->sc_curwin == cmd->sc_nwin) && (cmd->sc_nwin == 1)) {
1791 		return (DDI_SUCCESS);
1792 	}
1793 	if (++cmd->sc_curwin >= cmd->sc_nwin) {
1794 		return (DDI_FAILURE);
1795 	}
1796 	if (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
1797 	    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
1798 	    DDI_SUCCESS) {
1799 		return (DDI_FAILURE);
1800 	}
1801 
1802 	scsa1394_cmd_buf_addr_free(sp, cmd);
1803 
1804 	/*
1805 	 * setup page table if needed
1806 	 */
1807 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1808 	    (!sp->s_symbios ||
1809 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
1810 		/* but first, free old resources */
1811 		if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1812 			scsa1394_cmd_pt_dma_free(sp, cmd);
1813 		}
1814 		scsa1394_cmd_seg_free(sp, cmd);
1815 
1816 		cmd->sc_buf_nsegs = 1;
1817 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
1818 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
1819 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
1820 	} else {
1821 		/* break window into segments */
1822 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, KM_NOSLEEP) !=
1823 		    DDI_SUCCESS) {
1824 			return (DDI_FAILURE);
1825 		}
1826 
1827 		/* allocate DMA resources */
1828 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, NULL_FUNC, NULL,
1829 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
1830 			return (DDI_FAILURE);
1831 		}
1832 	}
1833 
1834 	/* allocate 1394 addresses for segments */
1835 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
1836 		return (DDI_FAILURE);
1837 	}
1838 
1839 	return (DDI_SUCCESS);
1840 }
1841 
1842 /*
1843  *
1844  * --- pkt and data transfer routines
1845  *
1846  */
1847 static int
1848 scsa1394_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
1849 {
1850 	scsa1394_state_t *sp = ADDR2STATE(ap);
1851 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1852 	scsa1394_lun_t	*lp = cmd->sc_lun;
1853 	int		ret;
1854 
1855 	/*
1856 	 * since we don't support polled I/O, just accept the packet
1857 	 * so the rest of the file systems get synced properly
1858 	 */
1859 	if (ddi_in_panic()) {
1860 		scsa1394_prepare_pkt(sp, pkt);
1861 		return (TRAN_ACCEPT);
1862 	}
1863 
1864 	/* polling not supported yet */
1865 	if (pkt->pkt_flags & FLAG_NOINTR) {
1866 		return (TRAN_BADPKT);
1867 	}
1868 
1869 	mutex_enter(&sp->s_mutex);
1870 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
1871 		/*
1872 		 * If device is temporarily gone due to bus reset,
1873 		 * return busy to prevent prevent scary console messages.
1874 		 * If permanently gone, leave it to scsa1394_cmd_fake_comp().
1875 		 */
1876 		if (sp->s_dev_state == SCSA1394_DEV_BUS_RESET) {
1877 			mutex_exit(&sp->s_mutex);
1878 			return (TRAN_BUSY);
1879 		}
1880 	}
1881 	mutex_exit(&sp->s_mutex);
1882 
1883 	if ((ap->a_lun >= sp->s_nluns) ||
1884 	    (ap->a_lun != pkt->pkt_address.a_lun)) {
1885 		return (TRAN_BADPKT);
1886 	}
1887 
1888 	scsa1394_prepare_pkt(sp, pkt);
1889 
1890 	/* some commands may require fake completion */
1891 	if ((ret = scsa1394_cmd_fake_comp(sp, cmd)) == DDI_SUCCESS) {
1892 		return (TRAN_ACCEPT);
1893 	}
1894 
1895 	scsa1394_cmd_fill_cdb(lp, cmd);
1896 
1897 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1898 		scsa1394_sbp2_seg2pt(lp, cmd);
1899 	}
1900 
1901 	scsa1394_sbp2_cmd2orb(lp, cmd);		/* convert into ORB */
1902 
1903 	if ((ret = scsa1394_sbp2_start(lp, cmd)) != DDI_SUCCESS) {
1904 		scsa1394_sbp2_nudge(lp);
1905 	}
1906 
1907 	return (ret);
1908 }
1909 
1910 /*ARGSUSED*/
1911 static void
1912 scsa1394_prepare_pkt(scsa1394_state_t *sp, struct scsi_pkt *pkt)
1913 {
1914 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1915 
1916 	pkt->pkt_reason = CMD_CMPLT;
1917 	pkt->pkt_state = 0;
1918 	pkt->pkt_statistics = 0;
1919 	*(pkt->pkt_scbp) = STATUS_GOOD;
1920 
1921 	if (cmd) {
1922 		cmd->sc_timeout = pkt->pkt_time;
1923 
1924 		/* workarounds */
1925 		switch (pkt->pkt_cdbp[0]) {
1926 		/*
1927 		 * sd does START_STOP_UNIT during attach with a 200 sec timeout.
1928 		 * at this time devi_lock is held, prtconf will be stuck.
1929 		 * reduce timeout for the time being.
1930 		 */
1931 		case SCMD_START_STOP:
1932 			cmd->sc_timeout = min(cmd->sc_timeout,
1933 			    scsa1394_start_stop_timeout_max);
1934 			break;
1935 		default:
1936 			break;
1937 		}
1938 	}
1939 }
1940 
1941 static void
1942 scsa1394_cmd_fill_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
1943 {
1944 	cmd->sc_cdb_actual_len = cmd->sc_cdb_len;
1945 
1946 	mutex_enter(&lp->l_mutex);
1947 
1948 	switch (lp->l_dtype_orig) {
1949 	case DTYPE_DIRECT:
1950 	case DTYPE_RODIRECT:
1951 	case DTYPE_OPTICAL:
1952 	case SCSA1394_DTYPE_RBC:
1953 		scsa1394_cmd_fill_cdb_rbc(lp, cmd);
1954 		break;
1955 	default:
1956 		scsa1394_cmd_fill_cdb_other(lp, cmd);
1957 		break;
1958 	}
1959 
1960 	mutex_exit(&lp->l_mutex);
1961 }
1962 
1963 static void
1964 scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
1965 {
1966 	scsa1394_state_t *sp = lp->l_sp;
1967 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
1968 	int		lba, opcode;
1969 	struct buf	*bp = cmd->sc_bp;
1970 	size_t		len;
1971 	size_t		blk_size;
1972 	int		sz;
1973 
1974 	opcode = pkt->pkt_cdbp[0];
1975 	blk_size  = lp->l_lba_size;
1976 
1977 	switch (opcode) {
1978 	case SCMD_READ:
1979 		/* RBC only supports 10-byte read/write */
1980 		lba = SCSA1394_LBA_6BYTE(pkt);
1981 		len = SCSA1394_LEN_6BYTE(pkt);
1982 		opcode = SCMD_READ_G1;
1983 		cmd->sc_cdb_actual_len = CDB_GROUP1;
1984 		break;
1985 	case SCMD_WRITE:
1986 		lba = SCSA1394_LBA_6BYTE(pkt);
1987 		len = SCSA1394_LEN_6BYTE(pkt);
1988 		opcode = SCMD_WRITE_G1;
1989 		cmd->sc_cdb_actual_len = CDB_GROUP1;
1990 		break;
1991 	case SCMD_READ_G1:
1992 	case SCMD_READ_LONG:
1993 		lba = SCSA1394_LBA_10BYTE(pkt);
1994 		len = SCSA1394_LEN_10BYTE(pkt);
1995 		break;
1996 	case SCMD_WRITE_G1:
1997 	case SCMD_WRITE_LONG:
1998 		lba = SCSA1394_LBA_10BYTE(pkt);
1999 		len = SCSA1394_LEN_10BYTE(pkt);
2000 		if ((lp->l_dtype_orig == DTYPE_RODIRECT) &&
2001 		    (bp != NULL) && (len != 0)) {
2002 			sz = SCSA1394_CDRW_BLKSZ(bp->b_bcount, len);
2003 			if (SCSA1394_VALID_CDRW_BLKSZ(sz)) {
2004 				blk_size = sz;
2005 			}
2006 		}
2007 		break;
2008 	case SCMD_READ_CD:
2009 		lba = SCSA1394_LBA_10BYTE(pkt);
2010 		len = SCSA1394_LEN_READ_CD(pkt);
2011 		blk_size = scsa1394_cmd_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2);
2012 		break;
2013 	case SCMD_READ_G5:
2014 		lba = SCSA1394_LBA_12BYTE(pkt);
2015 		len = SCSA1394_LEN_12BYTE(pkt);
2016 		break;
2017 	case SCMD_WRITE_G5:
2018 		lba = SCSA1394_LBA_12BYTE(pkt);
2019 		len = SCSA1394_LEN_12BYTE(pkt);
2020 		break;
2021 	default:
2022 		/* no special mapping for other commands */
2023 		scsa1394_cmd_fill_cdb_other(lp, cmd);
2024 		return;
2025 	}
2026 	cmd->sc_blk_size = blk_size;
2027 
2028 	/* limit xfer length for Symbios workaround */
2029 	if (sp->s_symbios && (len * blk_size > scsa1394_symbios_size_max)) {
2030 		cmd->sc_flags |= SCSA1394_CMD_SYMBIOS_BREAKUP;
2031 
2032 		cmd->sc_total_blks = cmd->sc_resid_blks = len;
2033 
2034 		len = scsa1394_symbios_size_max / blk_size;
2035 	}
2036 	cmd->sc_xfer_blks = len;
2037 	cmd->sc_xfer_bytes = len * blk_size;
2038 
2039 	/* finalize new CDB */
2040 	cmd->sc_cdb[0] = (uchar_t)opcode;
2041 	scsa1394_cmd_fill_cdb_lba(cmd, lba);
2042 	switch (opcode) {
2043 	case SCMD_READ_CD:
2044 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
2045 		break;
2046 	case SCMD_WRITE_G5:
2047 	case SCMD_READ_G5:
2048 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
2049 		break;
2050 	default:
2051 		scsa1394_cmd_fill_cdb_len(cmd, len);
2052 		break;
2053 	}
2054 }
2055 
2056 /*ARGSUSED*/
2057 static void
2058 scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2059 {
2060 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2061 
2062 	cmd->sc_xfer_bytes = cmd->sc_win_len;
2063 	cmd->sc_xfer_blks = cmd->sc_xfer_bytes / lp->l_lba_size;
2064 	cmd->sc_total_blks = cmd->sc_xfer_blks;
2065 	cmd->sc_lba = 0;
2066 
2067 	bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_len);
2068 }
2069 
2070 /*
2071  * fill up parts of CDB
2072  */
2073 static void
2074 scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *cmd, int len)
2075 {
2076 	cmd->sc_cdb[7] = len >> 8;
2077 	cmd->sc_cdb[8] = (uchar_t)len;
2078 }
2079 
2080 static void
2081 scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *cmd, int lba)
2082 {
2083 	cmd->sc_cdb[2] = lba >> 24;
2084 	cmd->sc_cdb[3] = lba >> 16;
2085 	cmd->sc_cdb[4] = lba >> 8;
2086 	cmd->sc_cdb[5] = (uchar_t)lba;
2087 	cmd->sc_lba = lba;
2088 }
2089 
2090 static void
2091 scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *cmd, int len)
2092 {
2093 	cmd->sc_cdb[6] = len >> 24;
2094 	cmd->sc_cdb[7] = len >> 16;
2095 	cmd->sc_cdb[8] = len >> 8;
2096 	cmd->sc_cdb[9] = (uchar_t)len;
2097 }
2098 
2099 static void
2100 scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *cmd, int len)
2101 {
2102 	cmd->sc_cdb[6] = len >> 16;
2103 	cmd->sc_cdb[7] = len >> 8;
2104 	cmd->sc_cdb[8] = (uchar_t)len;
2105 }
2106 
2107 /*
2108  * For SCMD_READ_CD, figure out the block size based on expected sector type.
2109  * See MMC SCSI Specs section 6.1.15
2110  */
2111 static int
2112 scsa1394_cmd_read_cd_blk_size(uchar_t expected_sector_type)
2113 {
2114 	int blk_size;
2115 
2116 	switch (expected_sector_type) {
2117 	case READ_CD_EST_CDDA:
2118 		blk_size = CDROM_BLK_2352;
2119 		break;
2120 	case READ_CD_EST_MODE2:
2121 		blk_size = CDROM_BLK_2336;
2122 		break;
2123 	case READ_CD_EST_MODE2FORM2:
2124 		blk_size = CDROM_BLK_2324;
2125 		break;
2126 	case READ_CD_EST_MODE2FORM1:
2127 	case READ_CD_EST_ALLTYPE:
2128 	case READ_CD_EST_MODE1:
2129 	default:
2130 		blk_size = CDROM_BLK_2048;
2131 	}
2132 
2133 	return (blk_size);
2134 }
2135 
2136 /*ARGSUSED*/
2137 static int
2138 scsa1394_cmd_fake_mode_sense(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2139 {
2140 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2141 	struct scsi_arq_status *arqp = (struct scsi_arq_status *)pkt->pkt_scbp;
2142 	struct scsi_extended_sense *esp = &arqp->sts_sensedata;
2143 
2144 	*(pkt->pkt_scbp) = STATUS_CHECK;
2145 	*(uint8_t *)&arqp->sts_rqpkt_status = STATUS_GOOD;
2146 	arqp->sts_rqpkt_reason = CMD_CMPLT;
2147 	arqp->sts_rqpkt_resid = 0;
2148 	arqp->sts_rqpkt_state |= STATE_XFERRED_DATA;
2149 	arqp->sts_rqpkt_statistics = 0;
2150 
2151 	bzero(esp, sizeof (struct scsi_extended_sense));
2152 
2153 	esp->es_class = CLASS_EXTENDED_SENSE;
2154 
2155 	esp->es_key = KEY_ILLEGAL_REQUEST;
2156 
2157 	pkt->pkt_reason = CMD_CMPLT;
2158 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2159 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2160 
2161 	if (pkt->pkt_comp) {
2162 		(*pkt->pkt_comp)(pkt);
2163 	}
2164 	return (DDI_SUCCESS);
2165 }
2166 
2167 /*ARGSUSED*/
2168 static int
2169 scsa1394_cmd_fake_inquiry(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2170 {
2171 	scsa1394_lun_t	*lp = cmd->sc_lun;
2172 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2173 	struct scsi_inquiry *inq;
2174 
2175 	/* copy fabricated inquiry data */
2176 	inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
2177 	bcopy(&lp->l_fake_inq, inq, sizeof (struct scsi_inquiry));
2178 
2179 	pkt->pkt_resid -= sizeof (struct scsi_inquiry);
2180 	pkt->pkt_reason = CMD_CMPLT;
2181 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2182 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2183 
2184 	if (pkt->pkt_comp) {
2185 		(*pkt->pkt_comp)(pkt);
2186 	}
2187 	return (DDI_SUCCESS);
2188 }
2189 
2190 /*
2191  * If command allows fake completion (without actually being transported),
2192  * call completion callback and return DDI_SUCCESS.
2193  * Otherwise return DDI_FAILURE.
2194  */
2195 static int
2196 scsa1394_cmd_fake_comp(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2197 {
2198 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2199 	scsa1394_lun_t	*lp = cmd->sc_lun;
2200 	int		ret = DDI_SUCCESS;
2201 
2202 	/*
2203 	 * agreement with sd in case of device hot removal
2204 	 * is to fake completion with CMD_DEV_GONE
2205 	 */
2206 	mutex_enter(&sp->s_mutex);
2207 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
2208 		mutex_exit(&sp->s_mutex);
2209 		pkt->pkt_reason = CMD_DEV_GONE;
2210 		if (pkt->pkt_comp) {
2211 			(*pkt->pkt_comp)(pkt);
2212 		}
2213 		return (DDI_SUCCESS);
2214 	}
2215 	mutex_exit(&sp->s_mutex);
2216 
2217 	mutex_enter(&lp->l_mutex);
2218 
2219 	switch (pkt->pkt_cdbp[0]) {
2220 	/*
2221 	 * RBC support for PRIN/PROUT is optional
2222 	 */
2223 	case SCMD_PRIN:
2224 	case SCMD_PROUT:
2225 		if (!scsa1394_wrka_fake_prin) {
2226 			ret = DDI_FAILURE;
2227 		}
2228 		break;
2229 	/*
2230 	 * Some fixed disks don't like doorlock cmd. And they don't need it.
2231 	 */
2232 	case SCMD_DOORLOCK:
2233 		if (lp->l_rmb_orig != 0) {
2234 			ret = DDI_FAILURE;
2235 		}
2236 		break;
2237 	case SCMD_TEST_UNIT_READY:
2238 		if (!lp->l_nosup_tur) {
2239 			ret = DDI_FAILURE;
2240 		}
2241 		break;
2242 	case SCMD_START_STOP:
2243 		if (!lp->l_nosup_start_stop) {
2244 			ret = DDI_FAILURE;
2245 		}
2246 		break;
2247 	case SCMD_INQUIRY:
2248 		if (!lp->l_nosup_inquiry) {
2249 			ret = DDI_FAILURE;
2250 		} else {
2251 			mutex_exit(&lp->l_mutex);
2252 			return (scsa1394_cmd_fake_inquiry(sp, cmd));
2253 		}
2254 		break;
2255 	case SCMD_MODE_SENSE:
2256 		if (!lp->l_mode_sense_fake) {
2257 			ret = DDI_FAILURE;
2258 		} else {
2259 			mutex_exit(&lp->l_mutex);
2260 			return (scsa1394_cmd_fake_mode_sense(sp, cmd));
2261 		}
2262 	default:
2263 		ret = DDI_FAILURE;
2264 	}
2265 
2266 	mutex_exit(&lp->l_mutex);
2267 
2268 	if (ret != DDI_SUCCESS) {
2269 		return (ret);
2270 	}
2271 
2272 	ASSERT(*(pkt->pkt_scbp) == STATUS_GOOD);
2273 	ASSERT(pkt->pkt_reason == CMD_CMPLT);
2274 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2275 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2276 
2277 	if (pkt->pkt_comp) {
2278 		(*pkt->pkt_comp)(pkt);
2279 	}
2280 	return (DDI_SUCCESS);
2281 }
2282 
2283 /*
2284  * Returns DDI_SUCCESS if next xfer setup successfully, DDI_FAILURE otherwise.
2285  */
2286 static int
2287 scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2288 {
2289 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
2290 
2291 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
2292 
2293 	cmd->sc_resid_blks -= cmd->sc_xfer_blks;
2294 	if (cmd->sc_resid_blks <= 0) {
2295 		pkt->pkt_resid = 0;
2296 		return (DDI_FAILURE);
2297 	}
2298 
2299 	scsa1394_cmd_adjust_cdb(lp, cmd);
2300 
2301 	scsa1394_sbp2_seg2pt(lp, cmd);
2302 
2303 	scsa1394_sbp2_cmd2orb(lp, cmd);
2304 
2305 	if (scsa1394_sbp2_start(lp, cmd) != TRAN_ACCEPT) {
2306 		pkt->pkt_resid = cmd->sc_resid_blks * cmd->sc_blk_size;
2307 		return (DDI_FAILURE);
2308 	}
2309 
2310 	return (DDI_SUCCESS);
2311 }
2312 
2313 /*
2314  * new lba = current lba + previous xfer len
2315  */
2316 /*ARGSUSED*/
2317 static void
2318 scsa1394_cmd_adjust_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2319 {
2320 	int		len;
2321 
2322 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
2323 
2324 	cmd->sc_lba += cmd->sc_xfer_blks;
2325 	len = cmd->sc_resid_blks;
2326 
2327 	/* limit xfer length for Symbios workaround */
2328 	if (len * cmd->sc_blk_size > scsa1394_symbios_size_max) {
2329 		len = scsa1394_symbios_size_max / cmd->sc_blk_size;
2330 	}
2331 
2332 	switch (cmd->sc_cdb[0]) {
2333 	case SCMD_READ_CD:
2334 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
2335 		break;
2336 	case SCMD_WRITE_G5:
2337 	case SCMD_READ_G5:
2338 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
2339 		break;
2340 	case SCMD_WRITE_G1:
2341 	case SCMD_WRITE_LONG:
2342 	default:
2343 		scsa1394_cmd_fill_cdb_len(cmd, len);
2344 	}
2345 
2346 	scsa1394_cmd_fill_cdb_lba(cmd, cmd->sc_lba);
2347 
2348 	cmd->sc_xfer_blks = len;
2349 	cmd->sc_xfer_bytes = len * cmd->sc_blk_size;
2350 }
2351 
2352 void
2353 scsa1394_cmd_status_proc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2354 {
2355 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
2356 
2357 	/* next iteration of partial xfer? */
2358 	if ((pkt->pkt_reason == CMD_CMPLT) &&
2359 	    (cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP)) {
2360 		if (scsa1394_cmd_setup_next_xfer(lp, cmd) == DDI_SUCCESS) {
2361 			return;
2362 		}
2363 	}
2364 	cmd->sc_flags &= ~SCSA1394_CMD_SYMBIOS_BREAKUP;
2365 
2366 	/* apply workarounds */
2367 	if (pkt->pkt_reason == CMD_CMPLT) {
2368 		scsa1394_cmd_status_wrka(lp, cmd);
2369 	}
2370 
2371 	mutex_enter(&lp->l_mutex);
2372 
2373 	/* mode sense workaround */
2374 	if (pkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
2375 		if (pkt->pkt_reason == CMD_CMPLT) {
2376 			lp->l_mode_sense_fail_cnt = 0;
2377 		} else if (++lp->l_mode_sense_fail_cnt >=
2378 		    scsa1394_mode_sense_fail_max) {
2379 			lp->l_mode_sense_fake = B_TRUE;
2380 		}
2381 	} else {
2382 		lp->l_mode_sense_fail_cnt = 0;
2383 	}
2384 
2385 	mutex_exit(&lp->l_mutex);
2386 
2387 	if (pkt->pkt_comp) {
2388 		(*pkt->pkt_comp)(pkt);
2389 	}
2390 }
2391 
2392 static void
2393 scsa1394_cmd_status_wrka(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2394 {
2395 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2396 
2397 	mutex_enter(&lp->l_mutex);
2398 
2399 	switch (pkt->pkt_cdbp[0]) {
2400 	case SCMD_INQUIRY: {
2401 		struct scsi_inquiry *inq;
2402 
2403 		inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
2404 
2405 		/* change dtype RBC to DIRECT, sd doesn't support RBC */
2406 		lp->l_dtype_orig = inq->inq_dtype;
2407 		if ((inq->inq_dtype == SCSA1394_DTYPE_RBC) &&
2408 		    scsa1394_wrka_rbc2direct) {
2409 			inq->inq_dtype = DTYPE_DIRECT;
2410 		}
2411 
2412 		/* force RMB to 1 */
2413 		lp->l_rmb_orig = inq->inq_rmb;
2414 		if (scsa1394_wrka_fake_rmb) {
2415 			inq->inq_rmb = 1;
2416 		}
2417 		break;
2418 	}
2419 	case SCMD_READ_CAPACITY: {
2420 		uint32_t	*capacity_buf;
2421 
2422 		capacity_buf = (uint32_t *)cmd->sc_bp->b_un.b_addr;
2423 
2424 		if (lp->l_dtype_orig != DTYPE_RODIRECT) {
2425 			lp->l_lba_size = min(BE_32(capacity_buf[1]), DEV_BSIZE);
2426 			if (lp->l_lba_size == 0) {
2427 				cmn_err(CE_WARN, "zero LBA size reported, "
2428 				    "possibly broken device");
2429 				lp->l_lba_size = DEV_BSIZE;
2430 			}
2431 		} else {
2432 			lp->l_lba_size = 2048;
2433 		}
2434 	}
2435 	default:
2436 		break;
2437 	}
2438 
2439 	mutex_exit(&lp->l_mutex);
2440 }
2441 
2442 /*
2443  * --- thread management
2444  *
2445  * dispatch a thread
2446  */
2447 int
2448 scsa1394_thr_dispatch(scsa1394_thread_t *thr)
2449 {
2450 	scsa1394_lun_t		*lp = thr->thr_lun;
2451 	scsa1394_state_t	*sp = lp->l_sp;
2452 	int			ret;
2453 
2454 	ASSERT(mutex_owned(&lp->l_mutex));
2455 	ASSERT(thr->thr_state == SCSA1394_THR_INIT);
2456 
2457 	thr->thr_state = SCSA1394_THR_RUN;
2458 
2459 	ret = ddi_taskq_dispatch(sp->s_taskq, thr->thr_func, thr->thr_arg,
2460 	    KM_SLEEP);
2461 	return (ret);
2462 }
2463 
2464 /*
2465  * cancel thread
2466  */
2467 void
2468 scsa1394_thr_cancel(scsa1394_thread_t *thr)
2469 {
2470 	scsa1394_lun_t		*lp = thr->thr_lun;
2471 
2472 	ASSERT(mutex_owned(&lp->l_mutex));
2473 
2474 	thr->thr_req |= SCSA1394_THREQ_EXIT;
2475 	cv_signal(&thr->thr_cv);
2476 
2477 	/* wait until the thread actually exits */
2478 	do {
2479 		if (cv_wait_sig(&thr->thr_cv, &lp->l_mutex) == 0) {
2480 			break;
2481 		}
2482 	} while (thr->thr_state != SCSA1394_THR_EXIT);
2483 }
2484 
2485 /*
2486  * wake thread
2487  */
2488 void
2489 scsa1394_thr_wake(scsa1394_thread_t *thr, int req)
2490 {
2491 	scsa1394_lun_t		*lp = thr->thr_lun;
2492 
2493 	ASSERT(mutex_owned(&lp->l_mutex));
2494 
2495 	thr->thr_req |= req;
2496 	cv_signal(&thr->thr_cv);
2497 }
2498 
2499 void
2500 scsa1394_thr_clear_req(scsa1394_thread_t *thr, int mask)
2501 {
2502 	scsa1394_lun_t		*lp = thr->thr_lun;
2503 
2504 	mutex_enter(&lp->l_mutex);
2505 	thr->thr_req &= ~mask;
2506 	mutex_exit(&lp->l_mutex);
2507 }
2508 
2509 /*
2510  *
2511  * --- other routines
2512  *
2513  */
2514 static boolean_t
2515 scsa1394_is_my_child(dev_info_t *dip)
2516 {
2517 	return ((dip != NULL) && (ddi_prop_exists(DDI_DEV_T_ANY, dip,
2518 	    DDI_PROP_DONTPASS, "scsa1394") == 1));
2519 }
2520 
2521 boolean_t
2522 scsa1394_dev_is_online(scsa1394_state_t *sp)
2523 {
2524 	boolean_t	ret;
2525 
2526 	mutex_enter(&sp->s_mutex);
2527 	ret = (sp->s_dev_state == SCSA1394_DEV_ONLINE);
2528 	mutex_exit(&sp->s_mutex);
2529 
2530 	return (ret);
2531 }
2532 
2533 static void *
2534 scsa1394_kmem_realloc(void *old_buf, int old_size, int new_size, size_t elsize,
2535     int kf)
2536 {
2537 	void	*new_buf;
2538 
2539 	new_buf = kmem_zalloc(new_size * elsize, kf);
2540 
2541 	if (old_size > 0) {
2542 		if (new_buf != NULL) {
2543 			bcopy(old_buf, new_buf, old_size * elsize);
2544 		}
2545 		kmem_free(old_buf, old_size * elsize);
2546 	}
2547 
2548 	return (new_buf);
2549 }
2550