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