xref: /onnv-gate/usr/src/uts/common/io/1394/targets/scsa1394/hba.c (revision 10696:cd0f390dd9e2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51963Sap25164  * Common Development and Distribution License (the "License").
61963Sap25164  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
228763SAlan.Perry@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * 1394 mass storage HBA driver
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <sys/errno.h>
330Sstevel@tonic-gate #include <sys/cred.h>
340Sstevel@tonic-gate #include <sys/conf.h>
350Sstevel@tonic-gate #include <sys/modctl.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include <sys/byteorder.h>
380Sstevel@tonic-gate #include <sys/ddi.h>
390Sstevel@tonic-gate #include <sys/sunddi.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include <sys/1394/targets/scsa1394/impl.h>
420Sstevel@tonic-gate #include <sys/1394/targets/scsa1394/cmd.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /* DDI/DKI entry points */
450Sstevel@tonic-gate static int	scsa1394_attach(dev_info_t *, ddi_attach_cmd_t);
460Sstevel@tonic-gate static int	scsa1394_detach(dev_info_t *, ddi_detach_cmd_t);
470Sstevel@tonic-gate static int	scsa1394_power(dev_info_t *, int, int);
486881Sbharding static int	scsa1394_cpr_suspend(dev_info_t *);
496881Sbharding static void	scsa1394_cpr_resume(dev_info_t *);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /* configuration routines */
520Sstevel@tonic-gate static void	scsa1394_cleanup(scsa1394_state_t *, int);
530Sstevel@tonic-gate static int	scsa1394_attach_1394(scsa1394_state_t *);
540Sstevel@tonic-gate static void	scsa1394_detach_1394(scsa1394_state_t *);
550Sstevel@tonic-gate static int	scsa1394_attach_threads(scsa1394_state_t *);
560Sstevel@tonic-gate static void	scsa1394_detach_threads(scsa1394_state_t *);
570Sstevel@tonic-gate static int	scsa1394_attach_scsa(scsa1394_state_t *);
580Sstevel@tonic-gate static void	scsa1394_detach_scsa(scsa1394_state_t *);
590Sstevel@tonic-gate static int	scsa1394_create_cmd_cache(scsa1394_state_t *);
600Sstevel@tonic-gate static void	scsa1394_destroy_cmd_cache(scsa1394_state_t *);
610Sstevel@tonic-gate static int	scsa1394_add_events(scsa1394_state_t *);
620Sstevel@tonic-gate static void	scsa1394_remove_events(scsa1394_state_t *);
630Sstevel@tonic-gate 
640Sstevel@tonic-gate /* device configuration */
650Sstevel@tonic-gate static int	scsa1394_scsi_bus_config(dev_info_t *, uint_t,
660Sstevel@tonic-gate 		ddi_bus_config_op_t, void *, dev_info_t **);
670Sstevel@tonic-gate static int	scsa1394_scsi_bus_unconfig(dev_info_t *, uint_t,
680Sstevel@tonic-gate 		ddi_bus_config_op_t, void *);
690Sstevel@tonic-gate static void	scsa1394_create_children(scsa1394_state_t *);
700Sstevel@tonic-gate static void	scsa1394_bus_reset(dev_info_t *, ddi_eventcookie_t, void *,
710Sstevel@tonic-gate 		void *);
720Sstevel@tonic-gate static void	scsa1394_disconnect(dev_info_t *, ddi_eventcookie_t, void *,
730Sstevel@tonic-gate 		void *);
740Sstevel@tonic-gate static void	scsa1394_reconnect(dev_info_t *, ddi_eventcookie_t, void *,
750Sstevel@tonic-gate 		void *);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /* SCSA HBA entry points */
780Sstevel@tonic-gate static int	scsa1394_scsi_tgt_init(dev_info_t *, dev_info_t *,
790Sstevel@tonic-gate 		scsi_hba_tran_t *, struct scsi_device *);
800Sstevel@tonic-gate static void	scsa1394_scsi_tgt_free(dev_info_t *, dev_info_t *,
810Sstevel@tonic-gate 		scsi_hba_tran_t *, struct scsi_device *);
820Sstevel@tonic-gate static int	scsa1394_scsi_tgt_probe(struct scsi_device *, int (*)());
830Sstevel@tonic-gate static int	scsa1394_probe_g0_nodata(struct scsi_device *, int (*)(),
840Sstevel@tonic-gate 		uchar_t, uint_t, uint_t);
850Sstevel@tonic-gate static int	scsa1394_probe_tran(struct scsi_pkt *);
860Sstevel@tonic-gate static struct scsi_pkt *scsa1394_scsi_init_pkt(struct scsi_address *,
870Sstevel@tonic-gate 		struct scsi_pkt *, struct buf *, int, int, int, int,
880Sstevel@tonic-gate 		int (*)(), caddr_t arg);
890Sstevel@tonic-gate static void	scsa1394_scsi_destroy_pkt(struct scsi_address *,
900Sstevel@tonic-gate 		struct scsi_pkt *);
910Sstevel@tonic-gate static int	scsa1394_scsi_start(struct scsi_address *, struct scsi_pkt *);
920Sstevel@tonic-gate static int	scsa1394_scsi_abort(struct scsi_address *, struct scsi_pkt *);
930Sstevel@tonic-gate static int	scsa1394_scsi_reset(struct scsi_address *, int);
940Sstevel@tonic-gate static int	scsa1394_scsi_getcap(struct scsi_address *, char *, int);
950Sstevel@tonic-gate static int	scsa1394_scsi_setcap(struct scsi_address *, char *, int, int);
960Sstevel@tonic-gate static void	scsa1394_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
970Sstevel@tonic-gate static void	scsa1394_scsi_sync_pkt(struct scsi_address *,
980Sstevel@tonic-gate 		struct scsi_pkt *);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /* pkt resource allocation routines */
1010Sstevel@tonic-gate static int	scsa1394_cmd_cache_constructor(void *, void *, int);
1020Sstevel@tonic-gate static void	scsa1394_cmd_cache_destructor(void *, void *);
1030Sstevel@tonic-gate static int	scsa1394_cmd_ext_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
1040Sstevel@tonic-gate 		int);
1050Sstevel@tonic-gate static void	scsa1394_cmd_ext_free(scsa1394_state_t *, scsa1394_cmd_t *);
1060Sstevel@tonic-gate static int	scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
1070Sstevel@tonic-gate 		int, int (*)(), caddr_t);
1080Sstevel@tonic-gate static void	scsa1394_cmd_cdb_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
1090Sstevel@tonic-gate static int	scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
1100Sstevel@tonic-gate 		int, int (*)(), caddr_t, struct buf *);
1110Sstevel@tonic-gate static void	scsa1394_cmd_buf_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
1120Sstevel@tonic-gate static int	scsa1394_cmd_dmac2seg(scsa1394_state_t *, scsa1394_cmd_t *,
1130Sstevel@tonic-gate 		ddi_dma_cookie_t *, uint_t, int);
1140Sstevel@tonic-gate static void	scsa1394_cmd_seg_free(scsa1394_state_t *, scsa1394_cmd_t *);
1150Sstevel@tonic-gate static int	scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
1160Sstevel@tonic-gate 		int (*)(), caddr_t, int);
1170Sstevel@tonic-gate static void	scsa1394_cmd_pt_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
1180Sstevel@tonic-gate static int	scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *,
1190Sstevel@tonic-gate 		scsa1394_cmd_t *);
1200Sstevel@tonic-gate static void	scsa1394_cmd_buf_addr_free(scsa1394_state_t *,
1210Sstevel@tonic-gate 		scsa1394_cmd_t *);
1220Sstevel@tonic-gate static int	scsa1394_cmd_buf_dma_move(scsa1394_state_t *, scsa1394_cmd_t *);
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /* pkt and data transfer routines */
1260Sstevel@tonic-gate static void	scsa1394_prepare_pkt(scsa1394_state_t *, struct scsi_pkt *);
1270Sstevel@tonic-gate static void	scsa1394_cmd_fill_cdb(scsa1394_lun_t *, scsa1394_cmd_t *);
1280Sstevel@tonic-gate static void	scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *, scsa1394_cmd_t *);
1290Sstevel@tonic-gate static void	scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *, scsa1394_cmd_t *);
1300Sstevel@tonic-gate static void	scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *, int);
1310Sstevel@tonic-gate static void	scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *, int);
1320Sstevel@tonic-gate static void	scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *, int);
1330Sstevel@tonic-gate static void	scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *, int);
1340Sstevel@tonic-gate static int	scsa1394_cmd_read_cd_blk_size(uchar_t);
1350Sstevel@tonic-gate static int	scsa1394_cmd_fake_mode_sense(scsa1394_state_t *,
1360Sstevel@tonic-gate 		scsa1394_cmd_t *);
1370Sstevel@tonic-gate static int	scsa1394_cmd_fake_inquiry(scsa1394_state_t *, scsa1394_cmd_t *);
1380Sstevel@tonic-gate static int	scsa1394_cmd_fake_comp(scsa1394_state_t *, scsa1394_cmd_t *);
1390Sstevel@tonic-gate static int	scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *,
1400Sstevel@tonic-gate 		scsa1394_cmd_t *);
1410Sstevel@tonic-gate static void	scsa1394_cmd_adjust_cdb(scsa1394_lun_t *, scsa1394_cmd_t *);
1420Sstevel@tonic-gate static void	scsa1394_cmd_status_wrka(scsa1394_lun_t *, scsa1394_cmd_t *);
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate /* other routines */
1450Sstevel@tonic-gate static boolean_t scsa1394_is_my_child(dev_info_t *);
1460Sstevel@tonic-gate static void *	scsa1394_kmem_realloc(void *, int, int, size_t, int);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate static void	*scsa1394_statep;
1490Sstevel@tonic-gate #define	SCSA1394_INST2STATE(inst) (ddi_get_soft_state(scsa1394_statep, inst))
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate static struct cb_ops scsa1394_cb_ops = {
1520Sstevel@tonic-gate 	nodev,			/* open */
1530Sstevel@tonic-gate 	nodev,			/* close */
1540Sstevel@tonic-gate 	nodev,			/* strategy */
1550Sstevel@tonic-gate 	nodev,			/* print */
1560Sstevel@tonic-gate 	nodev,			/* dump */
1570Sstevel@tonic-gate 	nodev,			/* read */
1580Sstevel@tonic-gate 	nodev,			/* write */
1590Sstevel@tonic-gate 	NULL,			/* ioctl */
1600Sstevel@tonic-gate 	nodev,			/* devmap */
1610Sstevel@tonic-gate 	nodev,			/* mmap */
1620Sstevel@tonic-gate 	nodev,			/* segmap */
1630Sstevel@tonic-gate 	nochpoll,		/* poll */
1640Sstevel@tonic-gate 	ddi_prop_op,		/* prop_op */
1650Sstevel@tonic-gate 	NULL,			/* stream */
1660Sstevel@tonic-gate 	D_MP,			/* cb_flag */
1676881Sbharding 	CB_REV,			/* rev */
1680Sstevel@tonic-gate 	nodev,			/* aread */
1690Sstevel@tonic-gate 	nodev			/* awrite */
1700Sstevel@tonic-gate };
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate static struct dev_ops scsa1394_ops = {
1730Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev, */
1740Sstevel@tonic-gate 	0,			/* refcnt  */
1750Sstevel@tonic-gate 	ddi_no_info,		/* info */
1760Sstevel@tonic-gate 	nulldev,		/* identify */
1770Sstevel@tonic-gate 	nulldev,		/* probe */
1780Sstevel@tonic-gate 	scsa1394_attach,	/* attach */
1790Sstevel@tonic-gate 	scsa1394_detach,	/* detach */
1800Sstevel@tonic-gate 	nodev,			/* reset */
1810Sstevel@tonic-gate 	&scsa1394_cb_ops,	/* driver operations */
1820Sstevel@tonic-gate 	NULL,			/* bus operations */
1837656SSherry.Moore@Sun.COM 	scsa1394_power,		/* power */
1847656SSherry.Moore@Sun.COM 	ddi_quiesce_not_supported,	/* devo_quiesce */
1850Sstevel@tonic-gate };
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate static struct modldrv scsa1394_modldrv = {
1880Sstevel@tonic-gate 	&mod_driverops,			/* module type */
1896881Sbharding 	"1394 Mass Storage HBA Driver", /* name of the module */
1900Sstevel@tonic-gate 	&scsa1394_ops,			/* driver ops */
1910Sstevel@tonic-gate };
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate static struct modlinkage scsa1394_modlinkage = {
1940Sstevel@tonic-gate 	MODREV_1, (void *)&scsa1394_modldrv, NULL
1950Sstevel@tonic-gate };
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate /* tunables */
1980Sstevel@tonic-gate int scsa1394_bus_config_debug = 0;
1990Sstevel@tonic-gate int scsa1394_start_stop_fail_max = SCSA1394_START_STOP_FAIL_MAX;
2000Sstevel@tonic-gate int scsa1394_mode_sense_fail_max = SCSA1394_MODE_SENSE_FAIL_MAX;
2010Sstevel@tonic-gate int scsa1394_start_stop_timeout_max = SCSA1394_START_STOP_TIMEOUT_MAX;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate /* workarounds */
2040Sstevel@tonic-gate int scsa1394_wrka_rbc2direct = 1;
2051415Scg149915 int scsa1394_wrka_fake_rmb = 0;
2060Sstevel@tonic-gate int scsa1394_wrka_fake_prin = 1;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate int scsa1394_wrka_symbios = 1;
2090Sstevel@tonic-gate int scsa1394_symbios_page_size = 4 * 1024;	/* must be <= _pagesize */
2100Sstevel@tonic-gate int scsa1394_symbios_size_max = 512 * 248;	/* multiple of page size */
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate /*
2130Sstevel@tonic-gate  *
2140Sstevel@tonic-gate  * --- DDI/DKI entry points
2150Sstevel@tonic-gate  *
2160Sstevel@tonic-gate  */
2170Sstevel@tonic-gate int
_init(void)2180Sstevel@tonic-gate _init(void)
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate 	int	ret;
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	if (((ret = ddi_soft_state_init(&scsa1394_statep,
2230Sstevel@tonic-gate 	    sizeof (scsa1394_state_t), 1)) != 0)) {
2240Sstevel@tonic-gate 		return (ret);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	if ((ret = scsi_hba_init(&scsa1394_modlinkage)) != 0) {
2280Sstevel@tonic-gate 		ddi_soft_state_fini(&scsa1394_statep);
2290Sstevel@tonic-gate 		return (ret);
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	if ((ret = mod_install(&scsa1394_modlinkage)) != 0) {
2330Sstevel@tonic-gate 		scsi_hba_fini(&scsa1394_modlinkage);
2340Sstevel@tonic-gate 		ddi_soft_state_fini(&scsa1394_statep);
2350Sstevel@tonic-gate 		return (ret);
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	return (ret);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate int
_fini(void)2420Sstevel@tonic-gate _fini(void)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	int	ret;
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	if ((ret = mod_remove(&scsa1394_modlinkage)) == 0) {
2470Sstevel@tonic-gate 		scsi_hba_fini(&scsa1394_modlinkage);
2480Sstevel@tonic-gate 		ddi_soft_state_fini(&scsa1394_statep);
2490Sstevel@tonic-gate 	}
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	return (ret);
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2550Sstevel@tonic-gate _info(struct modinfo *modinfop)
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate 	return (mod_info(&scsa1394_modlinkage, modinfop));
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate static int
scsa1394_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2610Sstevel@tonic-gate scsa1394_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate 	int		instance = ddi_get_instance(dip);
2640Sstevel@tonic-gate 	scsa1394_state_t *sp;
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	switch (cmd) {
2670Sstevel@tonic-gate 	case DDI_ATTACH:
2680Sstevel@tonic-gate 		break;
2690Sstevel@tonic-gate 	case DDI_RESUME:
2706881Sbharding 		scsa1394_cpr_resume(dip);
2710Sstevel@tonic-gate 		return (DDI_SUCCESS);
2720Sstevel@tonic-gate 	default:
2730Sstevel@tonic-gate 		return (DDI_FAILURE);
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	if (ddi_soft_state_zalloc(scsa1394_statep, instance) != 0) {
2770Sstevel@tonic-gate 		return (DDI_FAILURE);
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 	sp = SCSA1394_INST2STATE(instance);
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate #ifndef __lock_lint
2820Sstevel@tonic-gate 	sp->s_dip = dip;
2830Sstevel@tonic-gate 	sp->s_instance = instance;
2840Sstevel@tonic-gate #endif
2850Sstevel@tonic-gate 	mutex_init(&sp->s_mutex, NULL, MUTEX_DRIVER,
2860Sstevel@tonic-gate 	    sp->s_attachinfo.iblock_cookie);
2870Sstevel@tonic-gate 	cv_init(&sp->s_event_cv, NULL, CV_DRIVER, NULL);
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	if (scsa1394_attach_1394(sp) != DDI_SUCCESS) {
2900Sstevel@tonic-gate 		scsa1394_cleanup(sp, 1);
2910Sstevel@tonic-gate 		return (DDI_FAILURE);
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if (scsa1394_sbp2_attach(sp) != DDI_SUCCESS) {
2950Sstevel@tonic-gate 		scsa1394_cleanup(sp, 2);
2960Sstevel@tonic-gate 		return (DDI_FAILURE);
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if (scsa1394_attach_threads(sp) != DDI_SUCCESS) {
3000Sstevel@tonic-gate 		scsa1394_cleanup(sp, 3);
3010Sstevel@tonic-gate 		return (DDI_FAILURE);
3020Sstevel@tonic-gate 	}
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	if (scsa1394_attach_scsa(sp) != DDI_SUCCESS) {
3050Sstevel@tonic-gate 		scsa1394_cleanup(sp, 4);
3060Sstevel@tonic-gate 		return (DDI_FAILURE);
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if (scsa1394_create_cmd_cache(sp) != DDI_SUCCESS) {
3100Sstevel@tonic-gate 		scsa1394_cleanup(sp, 5);
3110Sstevel@tonic-gate 		return (DDI_FAILURE);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if (scsa1394_add_events(sp) != DDI_SUCCESS) {
3150Sstevel@tonic-gate 		scsa1394_cleanup(sp, 6);
3160Sstevel@tonic-gate 		return (DDI_FAILURE);
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 
3196881Sbharding 	/* prevent async PM changes until we are done */
3206881Sbharding 	(void) pm_busy_component(dip, 0);
3216881Sbharding 
3226881Sbharding 	/* Set power to full on */
3236881Sbharding 	(void) pm_raise_power(dip, 0, PM_LEVEL_D0);
3246881Sbharding 
3256881Sbharding 	/* we are done */
3266881Sbharding 	(void) pm_idle_component(dip, 0);
3276881Sbharding 
3280Sstevel@tonic-gate #ifndef __lock_lint
3290Sstevel@tonic-gate 	sp->s_dev_state = SCSA1394_DEV_ONLINE;
3300Sstevel@tonic-gate #endif
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	ddi_report_dev(dip);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	return (DDI_SUCCESS);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate static int
scsa1394_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3380Sstevel@tonic-gate scsa1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate 	int		instance = ddi_get_instance(dip);
3410Sstevel@tonic-gate 	scsa1394_state_t *sp;
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	if ((sp = SCSA1394_INST2STATE(instance)) == NULL) {
3440Sstevel@tonic-gate 		return (DDI_FAILURE);
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	switch (cmd) {
3480Sstevel@tonic-gate 	case DDI_DETACH:
3496881Sbharding 		/* Cycle power state to off and idle  where done/gone */
3506881Sbharding 		(void) pm_lower_power(dip, 0, PM_LEVEL_D3);
3516881Sbharding 
3520Sstevel@tonic-gate 		scsa1394_cleanup(sp, SCSA1394_CLEANUP_LEVEL_MAX);
3530Sstevel@tonic-gate 		return (DDI_SUCCESS);
3540Sstevel@tonic-gate 	case DDI_SUSPEND:
3556881Sbharding 		return (scsa1394_cpr_suspend(dip));
3560Sstevel@tonic-gate 	default:
3570Sstevel@tonic-gate 		return (DDI_FAILURE);
3580Sstevel@tonic-gate 	}
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate /*ARGSUSED*/
3620Sstevel@tonic-gate static int
scsa1394_power(dev_info_t * dip,int comp,int level)3630Sstevel@tonic-gate scsa1394_power(dev_info_t *dip, int comp, int level)
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate 	return (DDI_SUCCESS);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate /*
3696881Sbharding  * scsa1394_cpr_suspend
3706881Sbharding  *	determine if the device's state can be changed to SUSPENDED
3716881Sbharding  */
3726881Sbharding /* ARGSUSED */
3736881Sbharding static int
scsa1394_cpr_suspend(dev_info_t * dip)3746881Sbharding scsa1394_cpr_suspend(dev_info_t *dip)
3756881Sbharding {
3766881Sbharding 	int		instance = ddi_get_instance(dip);
3776881Sbharding 	scsa1394_state_t *sp;
3786881Sbharding 	int		rval = DDI_FAILURE;
3796881Sbharding 
3806881Sbharding 	sp = SCSA1394_INST2STATE(instance);
3816881Sbharding 
3826881Sbharding 	ASSERT(sp != NULL);
3836881Sbharding 
3846881Sbharding 
3856881Sbharding 	mutex_enter(&sp->s_mutex);
3866881Sbharding 	switch (sp->s_dev_state) {
3876881Sbharding 	case SCSA1394_DEV_ONLINE:
3886881Sbharding 	case SCSA1394_DEV_PWRED_DOWN:
3896881Sbharding 	case SCSA1394_DEV_DISCONNECTED:
3906881Sbharding 		sp->s_dev_state = SCSA1394_DEV_SUSPENDED;
3916881Sbharding 
3926881Sbharding 		/*  Power down and make device idle */
3936881Sbharding 		(void) pm_lower_power(dip, 0, PM_LEVEL_D3);
3946881Sbharding 
3956881Sbharding 		rval = DDI_SUCCESS;
3966881Sbharding 		break;
3976881Sbharding 	case SCSA1394_DEV_SUSPENDED:
3986881Sbharding 	default:
3996881Sbharding 		if (scsa1394_bus_config_debug)
4006881Sbharding 			cmn_err(CE_WARN,
4016881Sbharding 			    "scsa1304_cpr_suspend: Illegal dev state: %d",
4026881Sbharding 			    sp->s_dev_state);
4036881Sbharding 
4046881Sbharding 		rval = DDI_SUCCESS;
4056881Sbharding 		break;
4066881Sbharding 	}
4076881Sbharding 	mutex_exit(&sp->s_mutex);
4086881Sbharding 
4096881Sbharding 	return (rval);
4106881Sbharding }
4116881Sbharding 
4126881Sbharding /*
4136881Sbharding  * scsa2usb_cpr_resume:
4146881Sbharding  *	restore device's state
4156881Sbharding  */
4166881Sbharding static void
scsa1394_cpr_resume(dev_info_t * dip)4176881Sbharding scsa1394_cpr_resume(dev_info_t *dip)
4186881Sbharding {
4196881Sbharding 	int		instance = ddi_get_instance(dip);
4206881Sbharding 	scsa1394_state_t *sp;
4216881Sbharding 	int		i;
4226881Sbharding 	scsa1394_lun_t	*lp;
4236881Sbharding 
4246881Sbharding 	sp = SCSA1394_INST2STATE(instance);
4256881Sbharding 
4266881Sbharding 	ASSERT(sp != NULL);
4276881Sbharding 
4286881Sbharding 	if (sp->s_dev_state != SCSA1394_DEV_SUSPENDED)
4296881Sbharding 		return;
4306881Sbharding 
4316881Sbharding 	/*
4326881Sbharding 	 * Go through each lun and reset it to force a reconnect.
4336881Sbharding 	 */
4346881Sbharding 	for (i = 0; i < sp->s_nluns; i++) {
4356881Sbharding 		lp = &sp->s_lun[i];
4366881Sbharding 		if (lp->l_ses != NULL) {  /* Are we loged in? */
4376881Sbharding 			scsa1394_sbp2_req_bus_reset(lp);
4386881Sbharding 			scsa1394_sbp2_req_reconnect(lp);
4396881Sbharding 		}
4406881Sbharding 	}
4416881Sbharding 
4426881Sbharding 	/* we are down so let the power get managed */
4436881Sbharding 	(void) pm_idle_component(dip, 0);
4446881Sbharding }
4456881Sbharding 
4466881Sbharding 
4476881Sbharding 
4486881Sbharding /*
4490Sstevel@tonic-gate  *
4500Sstevel@tonic-gate  * --- configuration routines
4510Sstevel@tonic-gate  *
4520Sstevel@tonic-gate  */
4530Sstevel@tonic-gate static void
scsa1394_cleanup(scsa1394_state_t * sp,int level)4540Sstevel@tonic-gate scsa1394_cleanup(scsa1394_state_t *sp, int level)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate 	ASSERT((level > 0) && (level <= SCSA1394_CLEANUP_LEVEL_MAX));
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	switch (level) {
4590Sstevel@tonic-gate 	default:
4600Sstevel@tonic-gate 		scsa1394_remove_events(sp);
4610Sstevel@tonic-gate 		/* FALLTHRU */
4620Sstevel@tonic-gate 	case 6:
4630Sstevel@tonic-gate 		scsa1394_detach_scsa(sp);
4640Sstevel@tonic-gate 		/* FALLTHRU */
4650Sstevel@tonic-gate 	case 5:
4660Sstevel@tonic-gate 		scsa1394_destroy_cmd_cache(sp);
4670Sstevel@tonic-gate 		/* FALLTHRU */
4680Sstevel@tonic-gate 	case 4:
4690Sstevel@tonic-gate 		scsa1394_detach_threads(sp);
4700Sstevel@tonic-gate 		/* FALLTHRU */
4710Sstevel@tonic-gate 	case 3:
4720Sstevel@tonic-gate 		scsa1394_sbp2_detach(sp);
4730Sstevel@tonic-gate 		/* FALLTHRU */
4740Sstevel@tonic-gate 	case 2:
4750Sstevel@tonic-gate 		scsa1394_detach_1394(sp);
4760Sstevel@tonic-gate 		/* FALLTHRU */
4770Sstevel@tonic-gate 	case 1:
4780Sstevel@tonic-gate 		cv_destroy(&sp->s_event_cv);
4790Sstevel@tonic-gate 		mutex_destroy(&sp->s_mutex);
4800Sstevel@tonic-gate 		ddi_soft_state_free(scsa1394_statep, sp->s_instance);
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate static int
scsa1394_attach_1394(scsa1394_state_t * sp)4850Sstevel@tonic-gate scsa1394_attach_1394(scsa1394_state_t *sp)
4860Sstevel@tonic-gate {
4870Sstevel@tonic-gate 	int	ret;
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	if ((ret = t1394_attach(sp->s_dip, T1394_VERSION_V1, 0,
4900Sstevel@tonic-gate 	    &sp->s_attachinfo, &sp->s_t1394_hdl)) != DDI_SUCCESS) {
4910Sstevel@tonic-gate 		return (ret);
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	/* DMA attributes for data buffers */
4950Sstevel@tonic-gate 	sp->s_buf_dma_attr = sp->s_attachinfo.dma_attr;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	/* DMA attributes for page tables */
4980Sstevel@tonic-gate 	sp->s_pt_dma_attr = sp->s_attachinfo.dma_attr;
4990Sstevel@tonic-gate 	sp->s_pt_dma_attr.dma_attr_sgllen = 1;	/* pt must be contiguous */
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	if ((ret = t1394_get_targetinfo(sp->s_t1394_hdl, SCSA1394_BUSGEN(sp), 0,
5020Sstevel@tonic-gate 	    &sp->s_targetinfo)) != DDI_SUCCESS) {
5030Sstevel@tonic-gate 		(void) t1394_detach(&sp->s_t1394_hdl, 0);
5040Sstevel@tonic-gate 		return (ret);
5050Sstevel@tonic-gate 	}
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	return (DDI_SUCCESS);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate static void
scsa1394_detach_1394(scsa1394_state_t * sp)5110Sstevel@tonic-gate scsa1394_detach_1394(scsa1394_state_t *sp)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	(void) t1394_detach(&sp->s_t1394_hdl, 0);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate static int
scsa1394_attach_threads(scsa1394_state_t * sp)5170Sstevel@tonic-gate scsa1394_attach_threads(scsa1394_state_t *sp)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	char		name[16];
5200Sstevel@tonic-gate 	int		nthr;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	nthr = sp->s_nluns;
5230Sstevel@tonic-gate 	(void) snprintf(name, sizeof (name), "scsa1394%d", sp->s_instance);
5240Sstevel@tonic-gate 	if ((sp->s_taskq = ddi_taskq_create(sp->s_dip, name, nthr,
5250Sstevel@tonic-gate 	    TASKQ_DEFAULTPRI, 0)) == NULL) {
5260Sstevel@tonic-gate 		return (DDI_FAILURE);
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	if (scsa1394_sbp2_threads_init(sp) != DDI_SUCCESS) {
5300Sstevel@tonic-gate 		ddi_taskq_destroy(sp->s_taskq);
5310Sstevel@tonic-gate 		return (DDI_FAILURE);
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	return (DDI_SUCCESS);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate static void
scsa1394_detach_threads(scsa1394_state_t * sp)5380Sstevel@tonic-gate scsa1394_detach_threads(scsa1394_state_t *sp)
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 	scsa1394_sbp2_threads_fini(sp);
5410Sstevel@tonic-gate 	ddi_taskq_destroy(sp->s_taskq);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate static int
scsa1394_attach_scsa(scsa1394_state_t * sp)5450Sstevel@tonic-gate scsa1394_attach_scsa(scsa1394_state_t *sp)
5460Sstevel@tonic-gate {
5470Sstevel@tonic-gate 	scsi_hba_tran_t	*tran;
5480Sstevel@tonic-gate 	int		ret;
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	sp->s_tran = tran = scsi_hba_tran_alloc(sp->s_dip, SCSI_HBA_CANSLEEP);
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	tran->tran_hba_private	= sp;
5530Sstevel@tonic-gate 	tran->tran_tgt_private	= NULL;
5540Sstevel@tonic-gate 	tran->tran_tgt_init	= scsa1394_scsi_tgt_init;
5550Sstevel@tonic-gate 	tran->tran_tgt_probe	= scsa1394_scsi_tgt_probe;
5560Sstevel@tonic-gate 	tran->tran_tgt_free	= scsa1394_scsi_tgt_free;
5570Sstevel@tonic-gate 	tran->tran_start	= scsa1394_scsi_start;
5580Sstevel@tonic-gate 	tran->tran_abort	= scsa1394_scsi_abort;
5590Sstevel@tonic-gate 	tran->tran_reset	= scsa1394_scsi_reset;
5600Sstevel@tonic-gate 	tran->tran_getcap	= scsa1394_scsi_getcap;
5610Sstevel@tonic-gate 	tran->tran_setcap	= scsa1394_scsi_setcap;
5620Sstevel@tonic-gate 	tran->tran_init_pkt	= scsa1394_scsi_init_pkt;
5630Sstevel@tonic-gate 	tran->tran_destroy_pkt	= scsa1394_scsi_destroy_pkt;
5640Sstevel@tonic-gate 	tran->tran_dmafree	= scsa1394_scsi_dmafree;
5650Sstevel@tonic-gate 	tran->tran_sync_pkt	= scsa1394_scsi_sync_pkt;
5660Sstevel@tonic-gate 	tran->tran_reset_notify	= NULL;
5670Sstevel@tonic-gate 	tran->tran_get_bus_addr	= NULL;
5680Sstevel@tonic-gate 	tran->tran_get_name	= NULL;
5690Sstevel@tonic-gate 	tran->tran_bus_reset	= NULL;
5700Sstevel@tonic-gate 	tran->tran_quiesce	= NULL;
5710Sstevel@tonic-gate 	tran->tran_unquiesce	= NULL;
5720Sstevel@tonic-gate 	tran->tran_get_eventcookie = NULL;
5730Sstevel@tonic-gate 	tran->tran_add_eventcall = NULL;
5740Sstevel@tonic-gate 	tran->tran_remove_eventcall = NULL;
5750Sstevel@tonic-gate 	tran->tran_post_event	= NULL;
5760Sstevel@tonic-gate 	tran->tran_bus_config	= scsa1394_scsi_bus_config;
5770Sstevel@tonic-gate 	tran->tran_bus_unconfig	= scsa1394_scsi_bus_unconfig;
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	if ((ret = scsi_hba_attach_setup(sp->s_dip, &sp->s_attachinfo.dma_attr,
5800Sstevel@tonic-gate 	    tran, 0)) != DDI_SUCCESS) {
5810Sstevel@tonic-gate 		scsi_hba_tran_free(tran);
5820Sstevel@tonic-gate 		return (ret);
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	return (DDI_SUCCESS);
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate static void
scsa1394_detach_scsa(scsa1394_state_t * sp)5890Sstevel@tonic-gate scsa1394_detach_scsa(scsa1394_state_t *sp)
5900Sstevel@tonic-gate {
5910Sstevel@tonic-gate 	int	ret;
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	ret = scsi_hba_detach(sp->s_dip);
5940Sstevel@tonic-gate 	ASSERT(ret == DDI_SUCCESS);
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	scsi_hba_tran_free(sp->s_tran);
5970Sstevel@tonic-gate }
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate static int
scsa1394_create_cmd_cache(scsa1394_state_t * sp)6000Sstevel@tonic-gate scsa1394_create_cmd_cache(scsa1394_state_t *sp)
6010Sstevel@tonic-gate {
6020Sstevel@tonic-gate 	char	name[64];
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	(void) sprintf(name, "scsa1394%d_cache", sp->s_instance);
6050Sstevel@tonic-gate 	sp->s_cmd_cache = kmem_cache_create(name,
6066640Scth 	    SCSA1394_CMD_SIZE, sizeof (void *),
6070Sstevel@tonic-gate 	    scsa1394_cmd_cache_constructor, scsa1394_cmd_cache_destructor,
6080Sstevel@tonic-gate 	    NULL, (void *)sp, NULL, 0);
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	return ((sp->s_cmd_cache == NULL) ? DDI_FAILURE : DDI_SUCCESS);
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate static void
scsa1394_destroy_cmd_cache(scsa1394_state_t * sp)6140Sstevel@tonic-gate scsa1394_destroy_cmd_cache(scsa1394_state_t *sp)
6150Sstevel@tonic-gate {
6160Sstevel@tonic-gate 	kmem_cache_destroy(sp->s_cmd_cache);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate static int
scsa1394_add_events(scsa1394_state_t * sp)6200Sstevel@tonic-gate scsa1394_add_events(scsa1394_state_t *sp)
6210Sstevel@tonic-gate {
6220Sstevel@tonic-gate 	ddi_eventcookie_t	br_evc, rem_evc, ins_evc;
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,
6250Sstevel@tonic-gate 	    &br_evc) != DDI_SUCCESS) {
6260Sstevel@tonic-gate 		return (DDI_FAILURE);
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate 	if (ddi_add_event_handler(sp->s_dip, br_evc, scsa1394_bus_reset,
6290Sstevel@tonic-gate 	    sp, &sp->s_reset_cb_id) != DDI_SUCCESS) {
6300Sstevel@tonic-gate 		return (DDI_FAILURE);
6310Sstevel@tonic-gate 	}
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_REMOVE_EVENT,
6340Sstevel@tonic-gate 	    &rem_evc) != DDI_SUCCESS) {
6350Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
6360Sstevel@tonic-gate 		return (DDI_FAILURE);
6370Sstevel@tonic-gate 	}
6380Sstevel@tonic-gate 	if (ddi_add_event_handler(sp->s_dip, rem_evc, scsa1394_disconnect,
6390Sstevel@tonic-gate 	    sp, &sp->s_remove_cb_id) != DDI_SUCCESS) {
6400Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
6410Sstevel@tonic-gate 		return (DDI_FAILURE);
6420Sstevel@tonic-gate 	}
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_INSERT_EVENT,
6450Sstevel@tonic-gate 	    &ins_evc) != DDI_SUCCESS) {
6460Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
6470Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
6480Sstevel@tonic-gate 		return (DDI_FAILURE);
6490Sstevel@tonic-gate 	}
6500Sstevel@tonic-gate 	if (ddi_add_event_handler(sp->s_dip, ins_evc, scsa1394_reconnect,
6510Sstevel@tonic-gate 	    sp, &sp->s_insert_cb_id) != DDI_SUCCESS) {
6520Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
6530Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
6540Sstevel@tonic-gate 		return (DDI_FAILURE);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	return (DDI_SUCCESS);
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate static void
scsa1394_remove_events(scsa1394_state_t * sp)6610Sstevel@tonic-gate scsa1394_remove_events(scsa1394_state_t *sp)
6620Sstevel@tonic-gate {
6630Sstevel@tonic-gate 	ddi_eventcookie_t	evc;
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_INSERT_EVENT,
6660Sstevel@tonic-gate 	    &evc) == DDI_SUCCESS) {
6670Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_insert_cb_id);
6680Sstevel@tonic-gate 	}
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_REMOVE_EVENT,
6710Sstevel@tonic-gate 	    &evc) == DDI_SUCCESS) {
6720Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
6730Sstevel@tonic-gate 	}
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,
6760Sstevel@tonic-gate 	    &evc) == DDI_SUCCESS) {
6770Sstevel@tonic-gate 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
6780Sstevel@tonic-gate 	}
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate /*
6820Sstevel@tonic-gate  *
6830Sstevel@tonic-gate  * --- device configuration
6840Sstevel@tonic-gate  *
6850Sstevel@tonic-gate  */
6860Sstevel@tonic-gate static int
scsa1394_scsi_bus_config(dev_info_t * dip,uint_t flag,ddi_bus_config_op_t op,void * arg,dev_info_t ** child)6870Sstevel@tonic-gate scsa1394_scsi_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
6880Sstevel@tonic-gate     void *arg, dev_info_t **child)
6890Sstevel@tonic-gate {
6900Sstevel@tonic-gate 	scsa1394_state_t *sp = SCSA1394_INST2STATE(ddi_get_instance(dip));
6910Sstevel@tonic-gate 	int		circ;
6920Sstevel@tonic-gate 	int		ret;
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	if (scsa1394_bus_config_debug) {
6950Sstevel@tonic-gate 		flag |= NDI_DEVI_DEBUG;
6960Sstevel@tonic-gate 	}
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	ndi_devi_enter(dip, &circ);
6990Sstevel@tonic-gate 	if (DEVI(dip)->devi_child == NULL) {
7000Sstevel@tonic-gate 		scsa1394_create_children(sp);
7010Sstevel@tonic-gate 	}
7020Sstevel@tonic-gate 	ret = ndi_busop_bus_config(dip, flag, op, arg, child, 0);
7030Sstevel@tonic-gate 	ndi_devi_exit(dip, circ);
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	return (ret);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate static int
scsa1394_scsi_bus_unconfig(dev_info_t * dip,uint_t flag,ddi_bus_config_op_t op,void * arg)7090Sstevel@tonic-gate scsa1394_scsi_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
7100Sstevel@tonic-gate     void *arg)
7110Sstevel@tonic-gate {
7120Sstevel@tonic-gate 	scsa1394_state_t *sp = SCSA1394_INST2STATE(ddi_get_instance(dip));
7130Sstevel@tonic-gate 	int		circ;
7140Sstevel@tonic-gate 	int		ret;
7150Sstevel@tonic-gate 	uint_t		saved_flag = flag;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	if (scsa1394_bus_config_debug) {
7180Sstevel@tonic-gate 		flag |= NDI_DEVI_DEBUG;
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	/*
7220Sstevel@tonic-gate 	 * First offline and if offlining successful, then remove children.
7230Sstevel@tonic-gate 	 */
7240Sstevel@tonic-gate 	if (op == BUS_UNCONFIG_ALL) {
7250Sstevel@tonic-gate 		flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG);
7260Sstevel@tonic-gate 	}
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	ndi_devi_enter(dip, &circ);
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	ret = ndi_busop_bus_unconfig(dip, flag, op, arg);
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	/*
7330Sstevel@tonic-gate 	 * If previous step was successful and not part of modunload daemon,
7340Sstevel@tonic-gate 	 * attempt to remove children.
7350Sstevel@tonic-gate 	 */
7360Sstevel@tonic-gate 	if ((op == BUS_UNCONFIG_ALL) && (ret == NDI_SUCCESS) &&
7370Sstevel@tonic-gate 	    ((flag & NDI_AUTODETACH) == 0)) {
7380Sstevel@tonic-gate 		flag |= NDI_DEVI_REMOVE;
7390Sstevel@tonic-gate 		ret = ndi_busop_bus_unconfig(dip, flag, op, arg);
7400Sstevel@tonic-gate 	}
7410Sstevel@tonic-gate 	ndi_devi_exit(dip, circ);
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	if ((ret != NDI_SUCCESS) && (op == BUS_UNCONFIG_ALL) &&
7440Sstevel@tonic-gate 	    ((saved_flag & NDI_DEVI_REMOVE) != 0)) {
7450Sstevel@tonic-gate 		mutex_enter(&sp->s_mutex);
7460Sstevel@tonic-gate 		if (!sp->s_disconnect_warned) {
7470Sstevel@tonic-gate 			cmn_err(CE_WARN, "scsa1394(%d): "
7480Sstevel@tonic-gate 			    "Disconnected device was busy, please reconnect.\n",
7490Sstevel@tonic-gate 			    sp->s_instance);
7500Sstevel@tonic-gate 			sp->s_disconnect_warned = B_TRUE;
7510Sstevel@tonic-gate 		}
7520Sstevel@tonic-gate 		mutex_exit(&sp->s_mutex);
7530Sstevel@tonic-gate 	}
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	return (ret);
7560Sstevel@tonic-gate }
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate void
scsa1394_dtype2name(int dtype,char ** node_name,char ** driver_name)7590Sstevel@tonic-gate scsa1394_dtype2name(int dtype, char **node_name, char **driver_name)
7600Sstevel@tonic-gate {
7610Sstevel@tonic-gate 	static struct {
7620Sstevel@tonic-gate 		char	*node_name;
7630Sstevel@tonic-gate 		char	*driver_name;
7640Sstevel@tonic-gate 	} dtype2name[] = {
7650Sstevel@tonic-gate 		{ "disk",	"sd" },		/* DTYPE_DIRECT		0x00 */
7660Sstevel@tonic-gate 		{ "tape",	"st" },		/* DTYPE_SEQUENTIAL	0x01 */
7670Sstevel@tonic-gate 		{ "printer",	NULL },		/* DTYPE_PRINTER	0x02 */
7680Sstevel@tonic-gate 		{ "processor",	NULL },		/* DTYPE_PROCESSOR	0x03 */
7690Sstevel@tonic-gate 		{ "worm",	NULL },		/* DTYPE_WORM		0x04 */
7700Sstevel@tonic-gate 		{ "disk",	"sd" },		/* DTYPE_RODIRECT	0x05 */
7710Sstevel@tonic-gate 		{ "scanner",	NULL },		/* DTYPE_SCANNER	0x06 */
7720Sstevel@tonic-gate 		{ "disk",	"sd" },		/* DTYPE_OPTICAL	0x07 */
7730Sstevel@tonic-gate 		{ "changer",	NULL },		/* DTYPE_CHANGER	0x08 */
7740Sstevel@tonic-gate 		{ "comm",	NULL },		/* DTYPE_COMM		0x09 */
7750Sstevel@tonic-gate 		{ "generic",	NULL },		/* DTYPE_???		0x0A */
7760Sstevel@tonic-gate 		{ "generic",	NULL },		/* DTYPE_???		0x0B */
7770Sstevel@tonic-gate 		{ "array_ctrl",	NULL },		/* DTYPE_ARRAY_CTRL	0x0C */
7786881Sbharding 		{ "esi",	"ses" },	/* DTYPE_ESI		0x0D */
7790Sstevel@tonic-gate 		{ "disk",	"sd" }		/* DTYPE_RBC		0x0E */
7800Sstevel@tonic-gate 	};
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	if (dtype < NELEM(dtype2name)) {
7830Sstevel@tonic-gate 		*node_name = dtype2name[dtype].node_name;
7840Sstevel@tonic-gate 		*driver_name = dtype2name[dtype].driver_name;
7850Sstevel@tonic-gate 	} else {
7860Sstevel@tonic-gate 		*node_name = "generic";
7870Sstevel@tonic-gate 		*driver_name = NULL;
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate static void
scsa1394_create_children(scsa1394_state_t * sp)7920Sstevel@tonic-gate scsa1394_create_children(scsa1394_state_t *sp)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate 	char		name[SCSA1394_COMPAT_MAX][16];
7950Sstevel@tonic-gate 	char		*compatible[SCSA1394_COMPAT_MAX];
7960Sstevel@tonic-gate 	dev_info_t	*cdip;
7970Sstevel@tonic-gate 	int		i;
7980Sstevel@tonic-gate 	int		dtype;
7990Sstevel@tonic-gate 	char		*node_name;
8000Sstevel@tonic-gate 	char		*driver_name;
8010Sstevel@tonic-gate 	int		ret;
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	bzero(name, sizeof (name));
8040Sstevel@tonic-gate 	(void) strcpy(name[0], "sd");
8050Sstevel@tonic-gate 	for (i = 0; i < SCSA1394_COMPAT_MAX; i++) {
8060Sstevel@tonic-gate 		compatible[i] = name[i];
8070Sstevel@tonic-gate 	}
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	for (i = 0; i < sp->s_nluns; i++) {
8100Sstevel@tonic-gate 		dtype = scsa1394_sbp2_get_lun_type(&sp->s_lun[i]);
8110Sstevel@tonic-gate 		scsa1394_dtype2name(dtype, &node_name, &driver_name);
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 		ndi_devi_alloc_sleep(sp->s_dip, node_name,
814789Sahrens 		    (pnode_t)DEVI_SID_NODEID, &cdip);
8150Sstevel@tonic-gate 
816*10696SDavid.Hollister@Sun.COM 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
817*10696SDavid.Hollister@Sun.COM 		    SCSI_ADDR_PROP_TARGET, 0);
8180Sstevel@tonic-gate 		if (ret != DDI_PROP_SUCCESS) {
8190Sstevel@tonic-gate 			(void) ndi_devi_free(cdip);
8200Sstevel@tonic-gate 			continue;
8210Sstevel@tonic-gate 		}
8220Sstevel@tonic-gate 
823*10696SDavid.Hollister@Sun.COM 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
824*10696SDavid.Hollister@Sun.COM 		    SCSI_ADDR_PROP_LUN, i);
8250Sstevel@tonic-gate 		if (ret != DDI_PROP_SUCCESS) {
8260Sstevel@tonic-gate 			ddi_prop_remove_all(cdip);
8270Sstevel@tonic-gate 			(void) ndi_devi_free(cdip);
8280Sstevel@tonic-gate 			continue;
8290Sstevel@tonic-gate 		}
8300Sstevel@tonic-gate 
8311415Scg149915 		/*
8321415Scg149915 		 * Some devices don't support LOG SENSE, so tell
8331415Scg149915 		 * sd driver not to send this command.
8341415Scg149915 		 */
8351415Scg149915 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
8361415Scg149915 		    "pm-capable", 1);
8371415Scg149915 		if (ret != DDI_PROP_SUCCESS) {
8381415Scg149915 			ddi_prop_remove_all(cdip);
8391415Scg149915 			(void) ndi_devi_free(cdip);
8401415Scg149915 			continue;
8411415Scg149915 		}
8421415Scg149915 
8431415Scg149915 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
8441415Scg149915 		    "hotpluggable");
8451415Scg149915 		if (ret != DDI_PROP_SUCCESS) {
8461415Scg149915 			ddi_prop_remove_all(cdip);
8471415Scg149915 			(void) ndi_devi_free(cdip);
8481415Scg149915 			continue;
8491415Scg149915 		}
8501415Scg149915 
8510Sstevel@tonic-gate 		if (driver_name) {
8520Sstevel@tonic-gate 			compatible[0] = driver_name;
8530Sstevel@tonic-gate 			ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
8540Sstevel@tonic-gate 			    "compatible", (char **)compatible,
8550Sstevel@tonic-gate 			    SCSA1394_COMPAT_MAX);
8560Sstevel@tonic-gate 			if (ret != DDI_PROP_SUCCESS) {
8570Sstevel@tonic-gate 				ddi_prop_remove_all(cdip);
8580Sstevel@tonic-gate 				(void) ndi_devi_free(cdip);
8590Sstevel@tonic-gate 				continue;
8600Sstevel@tonic-gate 			}
8610Sstevel@tonic-gate 		}
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 		/*
8640Sstevel@tonic-gate 		 * add property "scsa1394" to distinguish from others' children
8650Sstevel@tonic-gate 		 */
8660Sstevel@tonic-gate 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
8670Sstevel@tonic-gate 		if (ret != DDI_PROP_SUCCESS) {
8680Sstevel@tonic-gate 			ddi_prop_remove_all(cdip);
8690Sstevel@tonic-gate 			(void) ndi_devi_free(cdip);
8700Sstevel@tonic-gate 			continue;
8710Sstevel@tonic-gate 		}
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 		(void) ddi_initchild(sp->s_dip, cdip);
8740Sstevel@tonic-gate 	}
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate /*ARGSUSED*/
8780Sstevel@tonic-gate static void
scsa1394_bus_reset(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)8790Sstevel@tonic-gate scsa1394_bus_reset(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
8800Sstevel@tonic-gate     void *data)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate 	scsa1394_state_t	*sp = arg;
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate 	if (sp != NULL) {
8850Sstevel@tonic-gate 		mutex_enter(&sp->s_mutex);
8860Sstevel@tonic-gate 		if (sp->s_dev_state == SCSA1394_DEV_DISCONNECTED) {
8870Sstevel@tonic-gate 			mutex_exit(&sp->s_mutex);
8880Sstevel@tonic-gate 			return;
8890Sstevel@tonic-gate 		}
8900Sstevel@tonic-gate 		sp->s_stat.stat_bus_reset_cnt++;
8910Sstevel@tonic-gate 		sp->s_dev_state = SCSA1394_DEV_BUS_RESET;
8920Sstevel@tonic-gate 		sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
8930Sstevel@tonic-gate 		mutex_exit(&sp->s_mutex);
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 		scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_BUS_RESET);
8960Sstevel@tonic-gate 	}
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate /*ARGSUSED*/
9000Sstevel@tonic-gate static void
scsa1394_disconnect(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)9010Sstevel@tonic-gate scsa1394_disconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
9020Sstevel@tonic-gate     void *data)
9030Sstevel@tonic-gate {
9040Sstevel@tonic-gate 	scsa1394_state_t	*sp = arg;
9050Sstevel@tonic-gate 	int			circ;
9060Sstevel@tonic-gate 	dev_info_t		*cdip, *cdip_next;
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	if (sp == NULL) {
9090Sstevel@tonic-gate 		return;
9100Sstevel@tonic-gate 	}
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	mutex_enter(&sp->s_mutex);
9130Sstevel@tonic-gate 	sp->s_stat.stat_disconnect_cnt++;
9140Sstevel@tonic-gate 	sp->s_dev_state = SCSA1394_DEV_DISCONNECTED;
9150Sstevel@tonic-gate 	mutex_exit(&sp->s_mutex);
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	scsa1394_sbp2_disconnect(sp);
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 	ndi_devi_enter(dip, &circ);
9200Sstevel@tonic-gate 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
9210Sstevel@tonic-gate 		cdip_next = ddi_get_next_sibling(cdip);
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate 		mutex_enter(&DEVI(cdip)->devi_lock);
9240Sstevel@tonic-gate 		DEVI_SET_DEVICE_REMOVED(cdip);
9250Sstevel@tonic-gate 		mutex_exit(&DEVI(cdip)->devi_lock);
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 	ndi_devi_exit(dip, circ);
9280Sstevel@tonic-gate }
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate /*ARGSUSED*/
9310Sstevel@tonic-gate static void
scsa1394_reconnect(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)9320Sstevel@tonic-gate scsa1394_reconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
9330Sstevel@tonic-gate     void *data)
9340Sstevel@tonic-gate {
9350Sstevel@tonic-gate 	scsa1394_state_t	*sp = arg;
9360Sstevel@tonic-gate 	int			circ;
9370Sstevel@tonic-gate 	dev_info_t		*cdip, *cdip_next;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	if (sp == NULL) {
9400Sstevel@tonic-gate 		return;
9410Sstevel@tonic-gate 	}
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	mutex_enter(&sp->s_mutex);
9440Sstevel@tonic-gate 	sp->s_stat.stat_reconnect_cnt++;
9450Sstevel@tonic-gate 	sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
9460Sstevel@tonic-gate 	sp->s_disconnect_warned = B_FALSE;
9470Sstevel@tonic-gate 	mutex_exit(&sp->s_mutex);
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	ndi_devi_enter(dip, &circ);
9500Sstevel@tonic-gate 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
9510Sstevel@tonic-gate 		cdip_next = ddi_get_next_sibling(cdip);
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 		mutex_enter(&DEVI(cdip)->devi_lock);
9540Sstevel@tonic-gate 		DEVI_SET_DEVICE_REINSERTED(cdip);
9550Sstevel@tonic-gate 		mutex_exit(&DEVI(cdip)->devi_lock);
9560Sstevel@tonic-gate 	}
9570Sstevel@tonic-gate 	ndi_devi_exit(dip, circ);
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_RECONNECT);
9600Sstevel@tonic-gate }
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate /*
9630Sstevel@tonic-gate  *
9640Sstevel@tonic-gate  * --- SCSA entry points
9650Sstevel@tonic-gate  *
9660Sstevel@tonic-gate  */
9670Sstevel@tonic-gate /*ARGSUSED*/
9680Sstevel@tonic-gate static int
scsa1394_scsi_tgt_init(dev_info_t * dip,dev_info_t * cdip,scsi_hba_tran_t * tran,struct scsi_device * sd)9690Sstevel@tonic-gate scsa1394_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
9700Sstevel@tonic-gate     struct scsi_device *sd)
9710Sstevel@tonic-gate {
9720Sstevel@tonic-gate 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
9730Sstevel@tonic-gate 	int		lun;
9740Sstevel@tonic-gate 	int		plen = sizeof (int);
9750Sstevel@tonic-gate 	int		ret = DDI_FAILURE;
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
978*10696SDavid.Hollister@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, SCSI_ADDR_PROP_LUN,
979*10696SDavid.Hollister@Sun.COM 	    (caddr_t)&lun, &plen) != DDI_PROP_SUCCESS) {
9800Sstevel@tonic-gate 		return (DDI_FAILURE);
9810Sstevel@tonic-gate 	}
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	if (!scsa1394_is_my_child(cdip)) {
9840Sstevel@tonic-gate 		/*
9850Sstevel@tonic-gate 		 * add property "scsa1394" to distinguish from others' children
9860Sstevel@tonic-gate 		 */
9870Sstevel@tonic-gate 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
9880Sstevel@tonic-gate 		if (ret != DDI_PROP_SUCCESS) {
9890Sstevel@tonic-gate 			return (DDI_FAILURE);
9900Sstevel@tonic-gate 		}
9910Sstevel@tonic-gate 
992276Sartem 		if (scsa1394_dev_is_online(sp)) {
993276Sartem 			return (scsa1394_sbp2_login(sp, lun));
994276Sartem 		} else {
995276Sartem 			return (DDI_FAILURE);
996276Sartem 		}
9970Sstevel@tonic-gate 	}
9980Sstevel@tonic-gate 
999276Sartem 	if ((lun >= sp->s_nluns) || (sp->s_lun[lun].l_cdip != NULL) ||
1000276Sartem 	    !scsa1394_dev_is_online(sp)) {
10010Sstevel@tonic-gate 		return (DDI_FAILURE);
10020Sstevel@tonic-gate 	}
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	if ((ret = scsa1394_sbp2_login(sp, lun)) == DDI_SUCCESS) {
10050Sstevel@tonic-gate 		sp->s_lun[lun].l_cdip = cdip;
10060Sstevel@tonic-gate 	}
10070Sstevel@tonic-gate 	return (ret);
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate /*ARGSUSED*/
10110Sstevel@tonic-gate static void
scsa1394_scsi_tgt_free(dev_info_t * dip,dev_info_t * cdip,scsi_hba_tran_t * tran,struct scsi_device * sd)10120Sstevel@tonic-gate scsa1394_scsi_tgt_free(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
10130Sstevel@tonic-gate     struct scsi_device *sd)
10140Sstevel@tonic-gate {
10150Sstevel@tonic-gate 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
10160Sstevel@tonic-gate 	int		lun;
10170Sstevel@tonic-gate 	int		plen = sizeof (int);
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	if (!scsa1394_is_my_child(cdip)) {
10200Sstevel@tonic-gate 		return;
10210Sstevel@tonic-gate 	}
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
1024*10696SDavid.Hollister@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, SCSI_ADDR_PROP_LUN,
1025*10696SDavid.Hollister@Sun.COM 	    (caddr_t)&lun, &plen) != DDI_PROP_SUCCESS) {
10260Sstevel@tonic-gate 		return;
10270Sstevel@tonic-gate 	}
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	if ((lun < sp->s_nluns) && (sp->s_lun[lun].l_cdip == cdip)) {
10300Sstevel@tonic-gate 		if (scsa1394_dev_is_online(sp)) {
10310Sstevel@tonic-gate 			scsa1394_sbp2_logout(sp, lun, B_TRUE);
10320Sstevel@tonic-gate 		}
10330Sstevel@tonic-gate 		sp->s_lun[lun].l_cdip = NULL;
10340Sstevel@tonic-gate 	}
10350Sstevel@tonic-gate }
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate static int
scsa1394_scsi_tgt_probe(struct scsi_device * sd,int (* waitfunc)())10380Sstevel@tonic-gate scsa1394_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
10390Sstevel@tonic-gate {
10400Sstevel@tonic-gate 	dev_info_t	*dip = ddi_get_parent(sd->sd_dev);
10410Sstevel@tonic-gate 	scsi_hba_tran_t	*tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
10420Sstevel@tonic-gate 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
10430Sstevel@tonic-gate 	scsa1394_lun_t	*lp;
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 	if (!scsa1394_dev_is_online(sp)) {
10460Sstevel@tonic-gate 		return (SCSIPROBE_FAILURE);
10470Sstevel@tonic-gate 	}
10480Sstevel@tonic-gate 	lp = &sp->s_lun[sd->sd_address.a_lun];
10490Sstevel@tonic-gate 
10500Sstevel@tonic-gate 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
10510Sstevel@tonic-gate 	    SCMD_TEST_UNIT_READY, 0, 0) != SCSIPROBE_EXISTS) {
10520Sstevel@tonic-gate 		lp->l_nosup_tur = B_TRUE;
10530Sstevel@tonic-gate 		(void) scsa1394_sbp2_reset(lp, RESET_LUN, NULL);
10540Sstevel@tonic-gate 	}
10550Sstevel@tonic-gate 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
10560Sstevel@tonic-gate 	    SCMD_START_STOP, 0, 1) != SCSIPROBE_EXISTS) {
10570Sstevel@tonic-gate 		lp->l_nosup_start_stop = B_TRUE;
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	/* standard probe issues INQUIRY, which some devices may not support */
10610Sstevel@tonic-gate 	if (scsi_hba_probe(sd, waitfunc) != SCSIPROBE_EXISTS) {
10620Sstevel@tonic-gate 		lp->l_nosup_inquiry = B_TRUE;
10630Sstevel@tonic-gate 		scsa1394_sbp2_fake_inquiry(sp, &lp->l_fake_inq);
10640Sstevel@tonic-gate 		bcopy(&lp->l_fake_inq, sd->sd_inq, SUN_INQSIZE);
10650Sstevel@tonic-gate #ifndef __lock_lint
10660Sstevel@tonic-gate 		lp->l_rmb_orig = 1;
10670Sstevel@tonic-gate #endif
10680Sstevel@tonic-gate 	}
10690Sstevel@tonic-gate 
10701415Scg149915 	if (scsa1394_wrka_fake_rmb) {
10710Sstevel@tonic-gate 		sd->sd_inq->inq_rmb = 1;
10720Sstevel@tonic-gate 	}
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 	return (SCSIPROBE_EXISTS);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate static int
scsa1394_probe_g0_nodata(struct scsi_device * sd,int (* waitfunc)(),uchar_t cmd,uint_t addr,uint_t cnt)10780Sstevel@tonic-gate scsa1394_probe_g0_nodata(struct scsi_device *sd, int (*waitfunc)(),
10790Sstevel@tonic-gate     uchar_t cmd, uint_t addr, uint_t cnt)
10800Sstevel@tonic-gate {
10810Sstevel@tonic-gate 	struct scsi_pkt	*pkt;
10820Sstevel@tonic-gate 	int		ret = SCSIPROBE_EXISTS;
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 	pkt = scsi_init_pkt(&sd->sd_address, NULL, NULL, CDB_GROUP0,
10850Sstevel@tonic-gate 	    sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, waitfunc, NULL);
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	if (pkt == NULL) {
10880Sstevel@tonic-gate 		return (SCSIPROBE_NOMEM);
10890Sstevel@tonic-gate 	}
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate 	(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp, cmd, addr, cnt,
10920Sstevel@tonic-gate 	    0);
10930Sstevel@tonic-gate 	((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = sd->sd_address.a_lun;
10940Sstevel@tonic-gate 	pkt->pkt_flags = FLAG_NOINTR;
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	if (scsa1394_probe_tran(pkt) < 0) {
10970Sstevel@tonic-gate 		if (pkt->pkt_reason == CMD_INCOMPLETE) {
10980Sstevel@tonic-gate 			ret = SCSIPROBE_NORESP;
10998763SAlan.Perry@Sun.COM 		} else if ((pkt->pkt_reason == CMD_TRAN_ERR) &&
11008763SAlan.Perry@Sun.COM 		    ((*(pkt->pkt_scbp) & STATUS_MASK) == STATUS_CHECK) &&
11018763SAlan.Perry@Sun.COM 		    (pkt->pkt_state & STATE_ARQ_DONE)) {
11028763SAlan.Perry@Sun.COM 			ret = SCSIPROBE_EXISTS;
11030Sstevel@tonic-gate 		} else {
11040Sstevel@tonic-gate 			ret = SCSIPROBE_FAILURE;
11050Sstevel@tonic-gate 		}
11060Sstevel@tonic-gate 	}
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 	scsi_destroy_pkt(pkt);
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	return (ret);
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate static int
scsa1394_probe_tran(struct scsi_pkt * pkt)11140Sstevel@tonic-gate scsa1394_probe_tran(struct scsi_pkt *pkt)
11150Sstevel@tonic-gate {
11160Sstevel@tonic-gate 	pkt->pkt_time = SCSA1394_PROBE_TIMEOUT;
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 	if (scsi_transport(pkt) != TRAN_ACCEPT) {
11190Sstevel@tonic-gate 		return (-1);
11200Sstevel@tonic-gate 	} else if ((pkt->pkt_reason == CMD_INCOMPLETE) &&
11210Sstevel@tonic-gate 	    (pkt->pkt_state == 0)) {
11220Sstevel@tonic-gate 		return (-1);
11230Sstevel@tonic-gate 	} else if (pkt->pkt_reason != CMD_CMPLT) {
11240Sstevel@tonic-gate 		return (-1);
11250Sstevel@tonic-gate 	} else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) {
11260Sstevel@tonic-gate 		return (0);
11270Sstevel@tonic-gate 	}
11280Sstevel@tonic-gate 	return (0);
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate /*ARGSUSED*/
11320Sstevel@tonic-gate static int
scsa1394_scsi_abort(struct scsi_address * ap,struct scsi_pkt * pkt)11330Sstevel@tonic-gate scsa1394_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11340Sstevel@tonic-gate {
11350Sstevel@tonic-gate 	return (0);
11360Sstevel@tonic-gate }
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate static int
scsa1394_scsi_reset(struct scsi_address * ap,int level)11390Sstevel@tonic-gate scsa1394_scsi_reset(struct scsi_address *ap, int level)
11400Sstevel@tonic-gate {
11410Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
11420Sstevel@tonic-gate 	scsa1394_lun_t	*lp;
11430Sstevel@tonic-gate 	int		ret;
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 	switch (level) {
11460Sstevel@tonic-gate 	case RESET_ALL:
11470Sstevel@tonic-gate 	case RESET_TARGET:
11480Sstevel@tonic-gate 		lp = &sp->s_lun[0];
11490Sstevel@tonic-gate 		break;
11500Sstevel@tonic-gate 	case RESET_LUN:
11510Sstevel@tonic-gate 		lp = &sp->s_lun[ap->a_lun];
11520Sstevel@tonic-gate 		break;
11530Sstevel@tonic-gate 	default:
11540Sstevel@tonic-gate 		return (DDI_FAILURE);
11550Sstevel@tonic-gate 	}
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 	ret = scsa1394_sbp2_reset(lp, level, NULL);
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	return ((ret == SBP2_SUCCESS) ? 1 : 0);
11600Sstevel@tonic-gate }
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate /*ARGSUSED*/
11630Sstevel@tonic-gate static int
scsa1394_scsi_getcap(struct scsi_address * ap,char * cap,int whom)11640Sstevel@tonic-gate scsa1394_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11650Sstevel@tonic-gate {
11660Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
11670Sstevel@tonic-gate 	size_t		dev_bsize_cap;
11680Sstevel@tonic-gate 	int		ret = -1;
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	if (!scsa1394_dev_is_online(sp)) {
11710Sstevel@tonic-gate 		return (-1);
11720Sstevel@tonic-gate 	}
11730Sstevel@tonic-gate 
11740Sstevel@tonic-gate 	if (cap == NULL) {
11750Sstevel@tonic-gate 		return (-1);
11760Sstevel@tonic-gate 	}
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 	switch (scsi_hba_lookup_capstr(cap)) {
11790Sstevel@tonic-gate 	case SCSI_CAP_DMA_MAX:
11800Sstevel@tonic-gate 		ret = sp->s_attachinfo.dma_attr.dma_attr_maxxfer;
11810Sstevel@tonic-gate 		break;
11820Sstevel@tonic-gate 	case SCSI_CAP_SCSI_VERSION:
11830Sstevel@tonic-gate 		ret = SCSI_VERSION_2;
11840Sstevel@tonic-gate 		break;
11850Sstevel@tonic-gate 	case SCSI_CAP_ARQ:
11860Sstevel@tonic-gate 		ret = 1;
11870Sstevel@tonic-gate 		break;
11880Sstevel@tonic-gate 	case SCSI_CAP_UNTAGGED_QING:
11890Sstevel@tonic-gate 		ret = 1;
11900Sstevel@tonic-gate 		break;
11910Sstevel@tonic-gate 	case SCSI_CAP_GEOMETRY:
11920Sstevel@tonic-gate 		dev_bsize_cap = sp->s_totalsec;
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 		if (sp->s_secsz > DEV_BSIZE) {
11950Sstevel@tonic-gate 			dev_bsize_cap *= sp->s_secsz / DEV_BSIZE;
11960Sstevel@tonic-gate 		} else if (sp->s_secsz < DEV_BSIZE) {
11970Sstevel@tonic-gate 			dev_bsize_cap /= DEV_BSIZE / sp->s_secsz;
11980Sstevel@tonic-gate 		}
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 		if (dev_bsize_cap < 65536 * 2 * 18) {		/* < ~1GB */
12010Sstevel@tonic-gate 			/* unlabeled floppy, 18k per cylinder */
12020Sstevel@tonic-gate 			ret = ((2 << 16) | 18);
12030Sstevel@tonic-gate 		} else if (dev_bsize_cap < 65536 * 64 * 32) {	/* < 64GB */
12040Sstevel@tonic-gate 			/* 1024k per cylinder */
12050Sstevel@tonic-gate 			ret = ((64 << 16) | 32);
12060Sstevel@tonic-gate 		} else if (dev_bsize_cap < 65536 * 255 * 63) {	/* < ~500GB */
12070Sstevel@tonic-gate 			/* ~8m per cylinder */
12080Sstevel@tonic-gate 			ret = ((255 << 16) | 63);
12090Sstevel@tonic-gate 		} else {					/* .. 8TB */
12100Sstevel@tonic-gate 			/* 64m per cylinder */
12110Sstevel@tonic-gate 			ret = ((512 << 16) | 256);
12120Sstevel@tonic-gate 		}
12130Sstevel@tonic-gate 		break;
12140Sstevel@tonic-gate 	default:
12150Sstevel@tonic-gate 		break;
12160Sstevel@tonic-gate 	}
12170Sstevel@tonic-gate 
12180Sstevel@tonic-gate 	return (ret);
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate /*ARGSUSED*/
12220Sstevel@tonic-gate static int
scsa1394_scsi_setcap(struct scsi_address * ap,char * cap,int value,int whom)12230Sstevel@tonic-gate scsa1394_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
12240Sstevel@tonic-gate {
12250Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
12260Sstevel@tonic-gate 	int		ret = -1;
12270Sstevel@tonic-gate 
12280Sstevel@tonic-gate 	if (!scsa1394_dev_is_online(sp)) {
12290Sstevel@tonic-gate 		return (-1);
12300Sstevel@tonic-gate 	}
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 	switch (scsi_hba_lookup_capstr(cap)) {
12330Sstevel@tonic-gate 	case SCSI_CAP_ARQ:
12340Sstevel@tonic-gate 		ret = 1;
12350Sstevel@tonic-gate 		break;
12360Sstevel@tonic-gate 	case SCSI_CAP_DMA_MAX:
12370Sstevel@tonic-gate 	case SCSI_CAP_SCSI_VERSION:
12380Sstevel@tonic-gate 	case SCSI_CAP_UNTAGGED_QING:
12390Sstevel@tonic-gate 		/* supported but not settable */
12400Sstevel@tonic-gate 		ret = 0;
12410Sstevel@tonic-gate 		break;
12420Sstevel@tonic-gate 	case SCSI_CAP_SECTOR_SIZE:
12430Sstevel@tonic-gate 		if (value) {
12440Sstevel@tonic-gate 			sp->s_secsz = value;
12450Sstevel@tonic-gate 		}
12460Sstevel@tonic-gate 		break;
12470Sstevel@tonic-gate 	case SCSI_CAP_TOTAL_SECTORS:
12480Sstevel@tonic-gate 		if (value) {
12490Sstevel@tonic-gate 			sp->s_totalsec = value;
12500Sstevel@tonic-gate 		}
12510Sstevel@tonic-gate 		break;
12520Sstevel@tonic-gate 	default:
12530Sstevel@tonic-gate 		break;
12540Sstevel@tonic-gate 	}
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 	return (ret);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate /*ARGSUSED*/
12600Sstevel@tonic-gate static void
scsa1394_scsi_sync_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)12610Sstevel@tonic-gate scsa1394_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
12620Sstevel@tonic-gate {
12630Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
12660Sstevel@tonic-gate 		(void) ddi_dma_sync(cmd->sc_buf_dma_hdl, 0, 0,
12670Sstevel@tonic-gate 		    (cmd->sc_flags & SCSA1394_CMD_READ) ?
12680Sstevel@tonic-gate 		    DDI_DMA_SYNC_FORCPU : DDI_DMA_SYNC_FORDEV);
12690Sstevel@tonic-gate 	}
12700Sstevel@tonic-gate }
12710Sstevel@tonic-gate 
12720Sstevel@tonic-gate /*
12730Sstevel@tonic-gate  *
12740Sstevel@tonic-gate  * --- pkt resource allocation routines
12750Sstevel@tonic-gate  *
12760Sstevel@tonic-gate  */
12770Sstevel@tonic-gate static struct scsi_pkt *
scsa1394_scsi_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)12780Sstevel@tonic-gate scsa1394_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
12790Sstevel@tonic-gate     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
12800Sstevel@tonic-gate     int (*callback)(), caddr_t arg)
12810Sstevel@tonic-gate {
12820Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
12830Sstevel@tonic-gate 	scsa1394_lun_t	*lp;
12840Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd;
12850Sstevel@tonic-gate 	boolean_t	is_new;	/* new cmd is being allocated */
12860Sstevel@tonic-gate 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 	if (ap->a_lun >= sp->s_nluns) {
12890Sstevel@tonic-gate 		return (NULL);
12900Sstevel@tonic-gate 	}
12910Sstevel@tonic-gate 	lp = &sp->s_lun[ap->a_lun];
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate 	/*
12940Sstevel@tonic-gate 	 * allocate cmd space
12950Sstevel@tonic-gate 	 */
12960Sstevel@tonic-gate 	if (pkt == NULL) {
12970Sstevel@tonic-gate 		is_new = B_TRUE;
12980Sstevel@tonic-gate 		if ((cmd = kmem_cache_alloc(sp->s_cmd_cache, kf)) == NULL) {
12990Sstevel@tonic-gate 			return (NULL);
13000Sstevel@tonic-gate 		}
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate 		/* initialize cmd */
13030Sstevel@tonic-gate 		pkt = &cmd->sc_scsi_pkt;
13040Sstevel@tonic-gate 		pkt->pkt_ha_private	= cmd;
13050Sstevel@tonic-gate 		pkt->pkt_address	= *ap;
13060Sstevel@tonic-gate 		pkt->pkt_private	= cmd->sc_priv;
13070Sstevel@tonic-gate 		pkt->pkt_scbp		= (uchar_t *)&cmd->sc_scb;
13080Sstevel@tonic-gate 		pkt->pkt_cdbp		= (uchar_t *)&cmd->sc_pkt_cdb;
13090Sstevel@tonic-gate 		pkt->pkt_resid		= 0;
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 		cmd->sc_lun		= lp;
13120Sstevel@tonic-gate 		cmd->sc_pkt		= pkt;
13130Sstevel@tonic-gate 		cmd->sc_cdb_len		= cmdlen;
13140Sstevel@tonic-gate 		cmd->sc_scb_len		= statuslen;
13150Sstevel@tonic-gate 		cmd->sc_priv_len	= tgtlen;
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 		/* need external space? */
13180Sstevel@tonic-gate 		if ((cmdlen > sizeof (cmd->sc_pkt_cdb)) ||
13190Sstevel@tonic-gate 		    (statuslen > sizeof (cmd->sc_scb)) ||
13200Sstevel@tonic-gate 		    (tgtlen > sizeof (cmd->sc_priv))) {
13210Sstevel@tonic-gate 			if (scsa1394_cmd_ext_alloc(sp, cmd, kf) !=
13220Sstevel@tonic-gate 			    DDI_SUCCESS) {
13230Sstevel@tonic-gate 				kmem_cache_free(sp->s_cmd_cache, cmd);
13240Sstevel@tonic-gate 				lp->l_stat.stat_err_pkt_kmem_alloc++;
13250Sstevel@tonic-gate 				return (NULL);
13260Sstevel@tonic-gate 			}
13270Sstevel@tonic-gate 		}
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 		/* allocate DMA resources for CDB */
13300Sstevel@tonic-gate 		if (scsa1394_cmd_cdb_dma_alloc(sp, cmd, flags, callback, arg) !=
13310Sstevel@tonic-gate 		    DDI_SUCCESS) {
13320Sstevel@tonic-gate 			scsa1394_scsi_destroy_pkt(ap, pkt);
13330Sstevel@tonic-gate 			return (NULL);
13340Sstevel@tonic-gate 		}
13350Sstevel@tonic-gate 	} else {
13360Sstevel@tonic-gate 		is_new = B_FALSE;
13370Sstevel@tonic-gate 		cmd = PKT2CMD(pkt);
13380Sstevel@tonic-gate 	}
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	/* allocate/move DMA resources for data buffer */
13430Sstevel@tonic-gate 	if ((bp != NULL) && (bp->b_bcount > 0)) {
13440Sstevel@tonic-gate 		if ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) == 0) {
13450Sstevel@tonic-gate 			if (scsa1394_cmd_buf_dma_alloc(sp, cmd, flags, callback,
13460Sstevel@tonic-gate 			    arg, bp) != DDI_SUCCESS) {
13470Sstevel@tonic-gate 				if (is_new) {
13480Sstevel@tonic-gate 					scsa1394_scsi_destroy_pkt(ap, pkt);
13490Sstevel@tonic-gate 				}
13500Sstevel@tonic-gate 				return (NULL);
13510Sstevel@tonic-gate 			}
13520Sstevel@tonic-gate 		} else {
13530Sstevel@tonic-gate 			if (scsa1394_cmd_buf_dma_move(sp, cmd) != DDI_SUCCESS) {
13540Sstevel@tonic-gate 				return (NULL);
13550Sstevel@tonic-gate 			}
13560Sstevel@tonic-gate 		}
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 		ASSERT(cmd->sc_win_len > 0);
13590Sstevel@tonic-gate 		pkt->pkt_resid = bp->b_bcount - cmd->sc_win_len;
13600Sstevel@tonic-gate 	}
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	/*
13630Sstevel@tonic-gate 	 * kernel virtual address may be required for certain workarounds
13640Sstevel@tonic-gate 	 * and in case of B_PHYS or B_PAGEIO, bp_mapin() will get it for us
13650Sstevel@tonic-gate 	 */
13660Sstevel@tonic-gate 	if ((bp != NULL) && ((bp->b_flags & (B_PAGEIO | B_PHYS)) != 0) &&
13670Sstevel@tonic-gate 	    (bp->b_bcount < SCSA1394_MAPIN_SIZE_MAX) &&
13680Sstevel@tonic-gate 	    ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) == 0)) {
13690Sstevel@tonic-gate 		bp_mapin(bp);
13700Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_MAPIN;
13710Sstevel@tonic-gate 	}
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 	return (pkt);
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate static void
scsa1394_scsi_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)13770Sstevel@tonic-gate scsa1394_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
13780Sstevel@tonic-gate {
13790Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
13800Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
13830Sstevel@tonic-gate 		scsa1394_cmd_buf_dma_free(sp, cmd);
13840Sstevel@tonic-gate 	}
13850Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_CDB_VALID) {
13860Sstevel@tonic-gate 		scsa1394_cmd_cdb_dma_free(sp, cmd);
13870Sstevel@tonic-gate 	}
13880Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
13890Sstevel@tonic-gate 		bp_mapout(cmd->sc_bp);
13900Sstevel@tonic-gate 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
13910Sstevel@tonic-gate 	}
13920Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_EXT) {
13930Sstevel@tonic-gate 		scsa1394_cmd_ext_free(sp, cmd);
13940Sstevel@tonic-gate 	}
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	kmem_cache_free(sp->s_cmd_cache, cmd);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate static void
scsa1394_scsi_dmafree(struct scsi_address * ap,struct scsi_pkt * pkt)14000Sstevel@tonic-gate scsa1394_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
14010Sstevel@tonic-gate {
14020Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
14030Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
14040Sstevel@tonic-gate 
14050Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
14060Sstevel@tonic-gate 		scsa1394_cmd_buf_dma_free(sp, cmd);
14070Sstevel@tonic-gate 	}
14080Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
14090Sstevel@tonic-gate 		bp_mapout(cmd->sc_bp);
14100Sstevel@tonic-gate 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
14110Sstevel@tonic-gate 	}
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate /*ARGSUSED*/
14150Sstevel@tonic-gate static int
scsa1394_cmd_cache_constructor(void * buf,void * cdrarg,int kf)14160Sstevel@tonic-gate scsa1394_cmd_cache_constructor(void *buf, void *cdrarg, int kf)
14170Sstevel@tonic-gate {
14180Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd = buf;
14190Sstevel@tonic-gate 
14206640Scth 	bzero(buf, SCSA1394_CMD_SIZE);
14210Sstevel@tonic-gate 	cmd->sc_task.ts_drv_priv = cmd;
14220Sstevel@tonic-gate 
14230Sstevel@tonic-gate 	return (0);
14240Sstevel@tonic-gate }
14250Sstevel@tonic-gate 
14260Sstevel@tonic-gate /*ARGSUSED*/
14270Sstevel@tonic-gate static void
scsa1394_cmd_cache_destructor(void * buf,void * cdrarg)14280Sstevel@tonic-gate scsa1394_cmd_cache_destructor(void *buf, void *cdrarg)
14290Sstevel@tonic-gate {
14300Sstevel@tonic-gate }
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate /*
14330Sstevel@tonic-gate  * allocate and deallocate external cmd space (ie. not part of scsa1394_cmd_t)
14340Sstevel@tonic-gate  * for non-standard length cdb, pkt_private, status areas
14350Sstevel@tonic-gate  */
14360Sstevel@tonic-gate static int
scsa1394_cmd_ext_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int kf)14370Sstevel@tonic-gate scsa1394_cmd_ext_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd, int kf)
14380Sstevel@tonic-gate {
14390Sstevel@tonic-gate 	struct scsi_pkt	*pkt = cmd->sc_pkt;
14400Sstevel@tonic-gate 	void		*buf;
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 	if (cmd->sc_cdb_len > sizeof (cmd->sc_pkt_cdb)) {
14430Sstevel@tonic-gate 		if ((buf = kmem_zalloc(cmd->sc_cdb_len, kf)) == NULL) {
14440Sstevel@tonic-gate 			return (DDI_FAILURE);
14450Sstevel@tonic-gate 		}
14460Sstevel@tonic-gate 		pkt->pkt_cdbp = buf;
14470Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_CDB_EXT;
14480Sstevel@tonic-gate 	}
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 	if (cmd->sc_scb_len > sizeof (cmd->sc_scb)) {
14510Sstevel@tonic-gate 		if ((buf = kmem_zalloc(cmd->sc_scb_len, kf)) == NULL) {
14520Sstevel@tonic-gate 			scsa1394_cmd_ext_free(sp, cmd);
14530Sstevel@tonic-gate 			return (DDI_FAILURE);
14540Sstevel@tonic-gate 		}
14550Sstevel@tonic-gate 		pkt->pkt_scbp = buf;
14560Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_SCB_EXT;
14570Sstevel@tonic-gate 	}
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate 	if (cmd->sc_priv_len > sizeof (cmd->sc_priv)) {
14600Sstevel@tonic-gate 		if ((buf = kmem_zalloc(cmd->sc_priv_len, kf)) == NULL) {
14610Sstevel@tonic-gate 			scsa1394_cmd_ext_free(sp, cmd);
14620Sstevel@tonic-gate 			return (DDI_FAILURE);
14630Sstevel@tonic-gate 		}
14640Sstevel@tonic-gate 		pkt->pkt_private = buf;
14650Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_PRIV_EXT;
14660Sstevel@tonic-gate 	}
14670Sstevel@tonic-gate 
14680Sstevel@tonic-gate 	return (DDI_SUCCESS);
14690Sstevel@tonic-gate }
14700Sstevel@tonic-gate 
14710Sstevel@tonic-gate /*ARGSUSED*/
14720Sstevel@tonic-gate static void
scsa1394_cmd_ext_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)14730Sstevel@tonic-gate scsa1394_cmd_ext_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
14740Sstevel@tonic-gate {
14750Sstevel@tonic-gate 	struct scsi_pkt	*pkt = cmd->sc_pkt;
14760Sstevel@tonic-gate 
14770Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_CDB_EXT) {
14780Sstevel@tonic-gate 		kmem_free(pkt->pkt_cdbp, cmd->sc_cdb_len);
14790Sstevel@tonic-gate 	}
14800Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_SCB_EXT) {
14810Sstevel@tonic-gate 		kmem_free(pkt->pkt_scbp, cmd->sc_scb_len);
14820Sstevel@tonic-gate 	}
14830Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_PRIV_EXT) {
14840Sstevel@tonic-gate 		kmem_free(pkt->pkt_private, cmd->sc_priv_len);
14850Sstevel@tonic-gate 	}
14860Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_EXT;
14870Sstevel@tonic-gate }
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate /*ARGSUSED*/
14900Sstevel@tonic-gate static int
scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int flags,int (* callback)(),caddr_t arg)14910Sstevel@tonic-gate scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
14920Sstevel@tonic-gate     int flags, int (*callback)(), caddr_t arg)
14930Sstevel@tonic-gate {
14940Sstevel@tonic-gate 	if (sbp2_task_orb_alloc(cmd->sc_lun->l_lun, &cmd->sc_task,
14950Sstevel@tonic-gate 	    sizeof (scsa1394_cmd_orb_t)) != SBP2_SUCCESS) {
14960Sstevel@tonic-gate 		return (DDI_FAILURE);
14970Sstevel@tonic-gate 	}
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate 	cmd->sc_flags |= SCSA1394_CMD_DMA_CDB_VALID;
15000Sstevel@tonic-gate 	return (DDI_SUCCESS);
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate /*ARGSUSED*/
15040Sstevel@tonic-gate static void
scsa1394_cmd_cdb_dma_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)15050Sstevel@tonic-gate scsa1394_cmd_cdb_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
15060Sstevel@tonic-gate {
15070Sstevel@tonic-gate 	sbp2_task_orb_free(cmd->sc_lun->l_lun, &cmd->sc_task);
15080Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_CDB_VALID;
15090Sstevel@tonic-gate }
15100Sstevel@tonic-gate 
15110Sstevel@tonic-gate /*
15120Sstevel@tonic-gate  * buffer resources
15130Sstevel@tonic-gate  */
15140Sstevel@tonic-gate static int
scsa1394_cmd_buf_dma_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int flags,int (* callback)(),caddr_t arg,struct buf * bp)15150Sstevel@tonic-gate scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
15160Sstevel@tonic-gate     int flags, int (*callback)(), caddr_t arg, struct buf *bp)
15170Sstevel@tonic-gate {
15180Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
15190Sstevel@tonic-gate 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
15200Sstevel@tonic-gate 	int		dma_flags;
15210Sstevel@tonic-gate 	ddi_dma_cookie_t dmac;
15220Sstevel@tonic-gate 	uint_t		ccount;
15230Sstevel@tonic-gate 	int		error;
15240Sstevel@tonic-gate 	int		ret;
15250Sstevel@tonic-gate 
15260Sstevel@tonic-gate 	cmd->sc_bp = bp;
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_buf_dma_attr, callback,
15290Sstevel@tonic-gate 	    NULL, &cmd->sc_buf_dma_hdl)) != DDI_SUCCESS) {
15300Sstevel@tonic-gate 		bioerror(bp, 0);
15310Sstevel@tonic-gate 		return (DDI_FAILURE);
15320Sstevel@tonic-gate 	}
15330Sstevel@tonic-gate 
15340Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
15350Sstevel@tonic-gate 	if (bp->b_flags & B_READ) {
15360Sstevel@tonic-gate 		dma_flags = DDI_DMA_READ;
15370Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_READ;
15380Sstevel@tonic-gate 	} else {
15390Sstevel@tonic-gate 		dma_flags = DDI_DMA_WRITE;
15400Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_WRITE;
15410Sstevel@tonic-gate 	}
15420Sstevel@tonic-gate 	if (flags & PKT_CONSISTENT) {
15430Sstevel@tonic-gate 		dma_flags |= DDI_DMA_CONSISTENT;
15440Sstevel@tonic-gate 	}
15450Sstevel@tonic-gate 	if (flags & PKT_DMA_PARTIAL) {
15460Sstevel@tonic-gate 		dma_flags |= DDI_DMA_PARTIAL;
15470Sstevel@tonic-gate 	}
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 	ret = ddi_dma_buf_bind_handle(cmd->sc_buf_dma_hdl, bp, dma_flags,
15500Sstevel@tonic-gate 	    callback, arg, &dmac, &ccount);
15510Sstevel@tonic-gate 
15520Sstevel@tonic-gate 	switch (ret) {
15530Sstevel@tonic-gate 	case DDI_DMA_MAPPED:
15540Sstevel@tonic-gate 		cmd->sc_nwin = 1;
15550Sstevel@tonic-gate 		cmd->sc_curwin = 0;
15560Sstevel@tonic-gate 		cmd->sc_win_offset = 0;
15570Sstevel@tonic-gate 		cmd->sc_win_len = bp->b_bcount;
15580Sstevel@tonic-gate 		break;
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 	case DDI_DMA_PARTIAL_MAP:
15610Sstevel@tonic-gate 		/* retrieve number of windows and first window cookie */
15620Sstevel@tonic-gate 		cmd->sc_curwin = 0;
15630Sstevel@tonic-gate 		if ((ddi_dma_numwin(cmd->sc_buf_dma_hdl, &cmd->sc_nwin) !=
15640Sstevel@tonic-gate 		    DDI_SUCCESS) ||
15650Sstevel@tonic-gate 		    (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
15660Sstevel@tonic-gate 		    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
15670Sstevel@tonic-gate 		    DDI_SUCCESS)) {
15680Sstevel@tonic-gate 			(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
15690Sstevel@tonic-gate 			ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
15700Sstevel@tonic-gate 			return (DDI_FAILURE);
15710Sstevel@tonic-gate 		}
1572276Sartem 		lp->l_stat.stat_cmd_buf_dma_partial++;
15730Sstevel@tonic-gate 		break;
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate 	case DDI_DMA_NORESOURCES:
15760Sstevel@tonic-gate 		error = 0;
15770Sstevel@tonic-gate 		goto map_error;
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 	case DDI_DMA_BADATTR:
15800Sstevel@tonic-gate 	case DDI_DMA_NOMAPPING:
15810Sstevel@tonic-gate 		error = EFAULT;
15820Sstevel@tonic-gate 		goto map_error;
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	default:
15850Sstevel@tonic-gate 		error = EINVAL;
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate 	map_error:
15880Sstevel@tonic-gate 		bioerror(bp, error);
15890Sstevel@tonic-gate 		lp->l_stat.stat_err_cmd_buf_dbind++;
15900Sstevel@tonic-gate 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
15910Sstevel@tonic-gate 		return (DDI_FAILURE);
15920Sstevel@tonic-gate 	}
15930Sstevel@tonic-gate 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_BIND_VALID;
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate 	/*
15960Sstevel@tonic-gate 	 * setup page table if needed
15970Sstevel@tonic-gate 	 */
15980Sstevel@tonic-gate 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
15990Sstevel@tonic-gate 	    (!sp->s_symbios ||
16000Sstevel@tonic-gate 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
16010Sstevel@tonic-gate 		cmd->sc_buf_nsegs = 1;
16020Sstevel@tonic-gate 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
16030Sstevel@tonic-gate 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
16040Sstevel@tonic-gate 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
16050Sstevel@tonic-gate 	} else {
16060Sstevel@tonic-gate 		/* break window into segments */
16070Sstevel@tonic-gate 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, kf) !=
16080Sstevel@tonic-gate 		    DDI_SUCCESS) {
16090Sstevel@tonic-gate 			scsa1394_cmd_buf_dma_free(sp, cmd);
16100Sstevel@tonic-gate 			bioerror(bp, 0);
16110Sstevel@tonic-gate 			return (DDI_FAILURE);
16120Sstevel@tonic-gate 		}
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate 		/* allocate DMA resources for page table */
16150Sstevel@tonic-gate 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, callback, arg,
16160Sstevel@tonic-gate 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
16170Sstevel@tonic-gate 			scsa1394_cmd_buf_dma_free(sp, cmd);
16180Sstevel@tonic-gate 			bioerror(bp, 0);
16190Sstevel@tonic-gate 			return (DDI_FAILURE);
16200Sstevel@tonic-gate 		}
16210Sstevel@tonic-gate 	}
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 	/* allocate 1394 addresses for segments */
16240Sstevel@tonic-gate 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
16250Sstevel@tonic-gate 		scsa1394_cmd_buf_dma_free(sp, cmd);
16260Sstevel@tonic-gate 		bioerror(bp, 0);
16270Sstevel@tonic-gate 		return (DDI_FAILURE);
16280Sstevel@tonic-gate 	}
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate 	return (DDI_SUCCESS);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate 
16330Sstevel@tonic-gate static void
scsa1394_cmd_buf_dma_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)16340Sstevel@tonic-gate scsa1394_cmd_buf_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
16350Sstevel@tonic-gate {
16360Sstevel@tonic-gate 	scsa1394_cmd_buf_addr_free(sp, cmd);
16370Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
16380Sstevel@tonic-gate 		scsa1394_cmd_pt_dma_free(sp, cmd);
16390Sstevel@tonic-gate 	}
16400Sstevel@tonic-gate 	scsa1394_cmd_seg_free(sp, cmd);
16410Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_BIND_VALID) {
16420Sstevel@tonic-gate 		(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
16430Sstevel@tonic-gate 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
16440Sstevel@tonic-gate 	}
16450Sstevel@tonic-gate 	cmd->sc_flags &= ~(SCSA1394_CMD_DMA_BUF_VALID | SCSA1394_CMD_RDWR);
16460Sstevel@tonic-gate }
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate /*
16490Sstevel@tonic-gate  * Break a set DMA cookies into segments suitable for SBP-2 page table.
16500Sstevel@tonic-gate  * This routine can reuse/reallocate segment array from previous calls.
16510Sstevel@tonic-gate  */
16520Sstevel@tonic-gate static int
scsa1394_cmd_dmac2seg(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,ddi_dma_cookie_t * dmac,uint_t ccount,int kf)16530Sstevel@tonic-gate scsa1394_cmd_dmac2seg(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
16540Sstevel@tonic-gate     ddi_dma_cookie_t *dmac, uint_t ccount, int kf)
16550Sstevel@tonic-gate {
16560Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
16570Sstevel@tonic-gate 	int		i;
16580Sstevel@tonic-gate 	int		nsegs;
16590Sstevel@tonic-gate 	size_t		segsize_max;
16600Sstevel@tonic-gate 	size_t		dmac_resid;
16610Sstevel@tonic-gate 	uint32_t	dmac_addr;
16620Sstevel@tonic-gate 	scsa1394_cmd_seg_t *seg;
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 	if (!sp->s_symbios) {
16650Sstevel@tonic-gate 		/*
16660Sstevel@tonic-gate 		 * Number of segments is unknown at this point. Start with
16670Sstevel@tonic-gate 		 * a reasonable estimate and grow it later if needed.
16680Sstevel@tonic-gate 		 */
16690Sstevel@tonic-gate 		nsegs = max(ccount, cmd->sc_win_len / SBP2_PT_SEGSIZE_MAX) * 2;
16700Sstevel@tonic-gate 		segsize_max = SBP2_PT_SEGSIZE_MAX;
16710Sstevel@tonic-gate 	} else {
1672276Sartem 		/*
1673276Sartem 		 * For Symbios workaround we know exactly the number of segments
1674276Sartem 		 * Additional segment may be needed if buffer is not aligned.
1675276Sartem 		 */
1676276Sartem 		nsegs =
1677276Sartem 		    howmany(cmd->sc_win_len, scsa1394_symbios_page_size) + 1;
16780Sstevel@tonic-gate 		segsize_max = scsa1394_symbios_page_size;
16790Sstevel@tonic-gate 	}
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 	if (nsegs > cmd->sc_buf_nsegs_alloc) {
16820Sstevel@tonic-gate 		if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(cmd->sc_buf_seg,
16830Sstevel@tonic-gate 		    cmd->sc_buf_nsegs_alloc, nsegs,
16840Sstevel@tonic-gate 		    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
16850Sstevel@tonic-gate 			cmd->sc_buf_nsegs_alloc = 0;
16860Sstevel@tonic-gate 			return (DDI_FAILURE);
16870Sstevel@tonic-gate 		}
16880Sstevel@tonic-gate 		cmd->sc_buf_nsegs_alloc = nsegs;
16890Sstevel@tonic-gate 	}
16900Sstevel@tonic-gate 
16910Sstevel@tonic-gate 	/* each cookie maps into one or more segments */
16920Sstevel@tonic-gate 	cmd->sc_buf_nsegs = 0;
16930Sstevel@tonic-gate 	i = ccount;
16940Sstevel@tonic-gate 	for (;;) {
16950Sstevel@tonic-gate 		dmac_resid = dmac->dmac_size;
16960Sstevel@tonic-gate 		dmac_addr = dmac->dmac_address;
16970Sstevel@tonic-gate 		while (dmac_resid > 0) {
16980Sstevel@tonic-gate 			/* grow array if needed */
16990Sstevel@tonic-gate 			if (cmd->sc_buf_nsegs >= cmd->sc_buf_nsegs_alloc) {
17000Sstevel@tonic-gate 				if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(
17010Sstevel@tonic-gate 				    cmd->sc_buf_seg,
17020Sstevel@tonic-gate 				    cmd->sc_buf_nsegs_alloc,
17030Sstevel@tonic-gate 				    cmd->sc_buf_nsegs_alloc + ccount,
17040Sstevel@tonic-gate 				    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
17050Sstevel@tonic-gate 					return (DDI_FAILURE);
17060Sstevel@tonic-gate 				}
17070Sstevel@tonic-gate 				cmd->sc_buf_nsegs_alloc += ccount;
17080Sstevel@tonic-gate 			}
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 			seg = &cmd->sc_buf_seg[cmd->sc_buf_nsegs];
17110Sstevel@tonic-gate 			seg->ss_len = min(dmac_resid, segsize_max);
17120Sstevel@tonic-gate 			seg->ss_daddr = (uint64_t)dmac_addr;
17130Sstevel@tonic-gate 			dmac_addr += seg->ss_len;
17140Sstevel@tonic-gate 			dmac_resid -= seg->ss_len;
17150Sstevel@tonic-gate 			cmd->sc_buf_nsegs++;
17160Sstevel@tonic-gate 		}
17170Sstevel@tonic-gate 		ASSERT(dmac_resid == 0);
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate 		/* grab next cookie */
17200Sstevel@tonic-gate 		if (--i <= 0) {
17210Sstevel@tonic-gate 			break;
17220Sstevel@tonic-gate 		}
17230Sstevel@tonic-gate 		ddi_dma_nextcookie(cmd->sc_buf_dma_hdl, dmac);
17240Sstevel@tonic-gate 	}
17250Sstevel@tonic-gate 
17260Sstevel@tonic-gate 	if (cmd->sc_buf_nsegs > lp->l_stat.stat_cmd_buf_max_nsegs) {
17270Sstevel@tonic-gate 		lp->l_stat.stat_cmd_buf_max_nsegs = cmd->sc_buf_nsegs;
17280Sstevel@tonic-gate 	}
17290Sstevel@tonic-gate 
17300Sstevel@tonic-gate 	return (DDI_SUCCESS);
17310Sstevel@tonic-gate }
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate /*ARGSUSED*/
17340Sstevel@tonic-gate static void
scsa1394_cmd_seg_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)17350Sstevel@tonic-gate scsa1394_cmd_seg_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
17360Sstevel@tonic-gate {
17370Sstevel@tonic-gate 	if (cmd->sc_buf_nsegs_alloc > 0) {
17380Sstevel@tonic-gate 		kmem_free(cmd->sc_buf_seg, cmd->sc_buf_nsegs_alloc *
17390Sstevel@tonic-gate 		    sizeof (scsa1394_cmd_seg_t));
17400Sstevel@tonic-gate 	}
17410Sstevel@tonic-gate 	cmd->sc_buf_seg = NULL;
17420Sstevel@tonic-gate 	cmd->sc_buf_nsegs = 0;
17430Sstevel@tonic-gate 	cmd->sc_buf_nsegs_alloc = 0;
17440Sstevel@tonic-gate }
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate static int
scsa1394_cmd_pt_dma_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int (* callback)(),caddr_t arg,int cnt)17470Sstevel@tonic-gate scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
17480Sstevel@tonic-gate     int (*callback)(), caddr_t arg, int cnt)
17490Sstevel@tonic-gate {
17500Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
17510Sstevel@tonic-gate 	size_t		len, rlen;
17520Sstevel@tonic-gate 	uint_t		ccount;
17530Sstevel@tonic-gate 	t1394_alloc_addr_t aa;
17540Sstevel@tonic-gate 	int		result;
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 	/* allocate DMA memory for page table */
17570Sstevel@tonic-gate 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_pt_dma_attr,
17580Sstevel@tonic-gate 	    callback, NULL, &cmd->sc_pt_dma_hdl)) != DDI_SUCCESS) {
17590Sstevel@tonic-gate 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
17600Sstevel@tonic-gate 		return (DDI_FAILURE);
17610Sstevel@tonic-gate 	}
17620Sstevel@tonic-gate 
17630Sstevel@tonic-gate 	cmd->sc_pt_ent_alloc = cnt;
17640Sstevel@tonic-gate 	len = cmd->sc_pt_ent_alloc * SBP2_PT_ENT_SIZE;
17650Sstevel@tonic-gate 	if (ddi_dma_mem_alloc(cmd->sc_pt_dma_hdl, len,
17660Sstevel@tonic-gate 	    &sp->s_attachinfo.acc_attr, DDI_DMA_CONSISTENT, callback, arg,
17670Sstevel@tonic-gate 	    &cmd->sc_pt_kaddr, &rlen, &cmd->sc_pt_acc_hdl) != DDI_SUCCESS) {
17680Sstevel@tonic-gate 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
17690Sstevel@tonic-gate 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
17700Sstevel@tonic-gate 		return (DDI_FAILURE);
17710Sstevel@tonic-gate 	}
17720Sstevel@tonic-gate 
17730Sstevel@tonic-gate 	if (ddi_dma_addr_bind_handle(cmd->sc_pt_dma_hdl, NULL,
17740Sstevel@tonic-gate 	    cmd->sc_pt_kaddr, len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
17750Sstevel@tonic-gate 	    callback, arg, &cmd->sc_pt_dmac, &ccount) != DDI_DMA_MAPPED) {
17760Sstevel@tonic-gate 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
17770Sstevel@tonic-gate 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
17780Sstevel@tonic-gate 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
17790Sstevel@tonic-gate 		return (DDI_FAILURE);
17800Sstevel@tonic-gate 	}
17810Sstevel@tonic-gate 	ASSERT(ccount == 1);	/* because dma_attr_sgllen is 1 */
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 	/* allocate 1394 address for page table */
17840Sstevel@tonic-gate 	aa.aa_type = T1394_ADDR_FIXED;
17850Sstevel@tonic-gate 	aa.aa_length = len;
17860Sstevel@tonic-gate 	aa.aa_address = cmd->sc_pt_dmac.dmac_address;
17870Sstevel@tonic-gate 	aa.aa_evts.recv_read_request = NULL;
17880Sstevel@tonic-gate 	aa.aa_evts.recv_write_request = NULL;
17890Sstevel@tonic-gate 	aa.aa_evts.recv_lock_request = NULL;
17900Sstevel@tonic-gate 	aa.aa_arg = NULL;
17910Sstevel@tonic-gate 	aa.aa_kmem_bufp = NULL;
17920Sstevel@tonic-gate 	aa.aa_enable = T1394_ADDR_RDENBL;
17930Sstevel@tonic-gate 	if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) != DDI_SUCCESS) {
17940Sstevel@tonic-gate 		(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
17950Sstevel@tonic-gate 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
17960Sstevel@tonic-gate 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
17970Sstevel@tonic-gate 		lp->l_stat.stat_err_cmd_pt_addr_alloc++;
17980Sstevel@tonic-gate 		return (DDI_FAILURE);
17990Sstevel@tonic-gate 	}
18000Sstevel@tonic-gate 	ASSERT(aa.aa_address != 0);
18010Sstevel@tonic-gate 	cmd->sc_pt_baddr = aa.aa_address;
18020Sstevel@tonic-gate 	cmd->sc_pt_addr_hdl = aa.aa_hdl;
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_PT_VALID;
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate 	return (DDI_SUCCESS);
18070Sstevel@tonic-gate }
18080Sstevel@tonic-gate 
18090Sstevel@tonic-gate static void
scsa1394_cmd_pt_dma_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)18100Sstevel@tonic-gate scsa1394_cmd_pt_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
18110Sstevel@tonic-gate {
18120Sstevel@tonic-gate 	(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
18130Sstevel@tonic-gate 	ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
18140Sstevel@tonic-gate 	ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
18150Sstevel@tonic-gate 	(void) t1394_free_addr(sp->s_t1394_hdl, &cmd->sc_pt_addr_hdl, 0);
18160Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_PT_VALID;
18170Sstevel@tonic-gate }
18180Sstevel@tonic-gate 
18190Sstevel@tonic-gate /*
18200Sstevel@tonic-gate  * allocate 1394 addresses for all buffer segments
18210Sstevel@tonic-gate  */
18220Sstevel@tonic-gate static int
scsa1394_cmd_buf_addr_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)18230Sstevel@tonic-gate scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
18240Sstevel@tonic-gate {
18250Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
18260Sstevel@tonic-gate 	t1394_alloc_addr_t aa;
18270Sstevel@tonic-gate 	scsa1394_cmd_seg_t *seg;
18280Sstevel@tonic-gate 	int		result;
18290Sstevel@tonic-gate 	int		i;
18300Sstevel@tonic-gate 
18310Sstevel@tonic-gate 	aa.aa_type = T1394_ADDR_FIXED;
18320Sstevel@tonic-gate 	aa.aa_evts.recv_read_request = NULL;
18330Sstevel@tonic-gate 	aa.aa_evts.recv_write_request = NULL;
18340Sstevel@tonic-gate 	aa.aa_evts.recv_lock_request = NULL;
18350Sstevel@tonic-gate 	aa.aa_arg = NULL;
18360Sstevel@tonic-gate 	aa.aa_kmem_bufp = NULL;
18370Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_READ) {
18380Sstevel@tonic-gate 		aa.aa_enable = T1394_ADDR_RDENBL;
18390Sstevel@tonic-gate 	} else {
18400Sstevel@tonic-gate 		aa.aa_enable = T1394_ADDR_WRENBL;
18410Sstevel@tonic-gate 	}
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
18440Sstevel@tonic-gate 		seg = &cmd->sc_buf_seg[i];
18450Sstevel@tonic-gate 
18460Sstevel@tonic-gate 		/* segment bus address */
18470Sstevel@tonic-gate 		aa.aa_length = seg->ss_len;
18480Sstevel@tonic-gate 		aa.aa_address = seg->ss_daddr;
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate 		if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) !=
18510Sstevel@tonic-gate 		    DDI_SUCCESS) {
18520Sstevel@tonic-gate 			lp->l_stat.stat_err_cmd_buf_addr_alloc++;
18530Sstevel@tonic-gate 			return (DDI_FAILURE);
18540Sstevel@tonic-gate 		}
18550Sstevel@tonic-gate 		ASSERT(aa.aa_address != 0);
18560Sstevel@tonic-gate 		seg->ss_baddr = aa.aa_address;
18570Sstevel@tonic-gate 		seg->ss_addr_hdl = aa.aa_hdl;
18580Sstevel@tonic-gate 	}
18590Sstevel@tonic-gate 
18600Sstevel@tonic-gate 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_ADDR_VALID;
18610Sstevel@tonic-gate 
18620Sstevel@tonic-gate 	return (DDI_SUCCESS);
18630Sstevel@tonic-gate }
18640Sstevel@tonic-gate 
18650Sstevel@tonic-gate static void
scsa1394_cmd_buf_addr_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)18660Sstevel@tonic-gate scsa1394_cmd_buf_addr_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
18670Sstevel@tonic-gate {
18680Sstevel@tonic-gate 	int		i;
18690Sstevel@tonic-gate 
18700Sstevel@tonic-gate 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
18710Sstevel@tonic-gate 		if (cmd->sc_buf_seg[i].ss_addr_hdl) {
18720Sstevel@tonic-gate 			(void) t1394_free_addr(sp->s_t1394_hdl,
18730Sstevel@tonic-gate 			    &cmd->sc_buf_seg[i].ss_addr_hdl, 0);
18740Sstevel@tonic-gate 		}
18750Sstevel@tonic-gate 	}
18760Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_ADDR_VALID;
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate 
18790Sstevel@tonic-gate /*
18800Sstevel@tonic-gate  * move to next DMA window
18810Sstevel@tonic-gate  */
18820Sstevel@tonic-gate static int
scsa1394_cmd_buf_dma_move(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)18830Sstevel@tonic-gate scsa1394_cmd_buf_dma_move(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
18840Sstevel@tonic-gate {
18850Sstevel@tonic-gate 	/* scsa1394_lun_t	*lp = cmd->sc_lun; */
18860Sstevel@tonic-gate 	ddi_dma_cookie_t dmac;
18870Sstevel@tonic-gate 	uint_t		ccount;
18880Sstevel@tonic-gate 
18890Sstevel@tonic-gate 	/* for small pkts, leave things where they are (says WDD) */
18900Sstevel@tonic-gate 	if ((cmd->sc_curwin == cmd->sc_nwin) && (cmd->sc_nwin == 1)) {
18910Sstevel@tonic-gate 		return (DDI_SUCCESS);
18920Sstevel@tonic-gate 	}
18930Sstevel@tonic-gate 	if (++cmd->sc_curwin >= cmd->sc_nwin) {
18940Sstevel@tonic-gate 		return (DDI_FAILURE);
18950Sstevel@tonic-gate 	}
18960Sstevel@tonic-gate 	if (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
18970Sstevel@tonic-gate 	    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
18980Sstevel@tonic-gate 	    DDI_SUCCESS) {
18990Sstevel@tonic-gate 		return (DDI_FAILURE);
19000Sstevel@tonic-gate 	}
19010Sstevel@tonic-gate 
19020Sstevel@tonic-gate 	scsa1394_cmd_buf_addr_free(sp, cmd);
19030Sstevel@tonic-gate 
19040Sstevel@tonic-gate 	/*
19050Sstevel@tonic-gate 	 * setup page table if needed
19060Sstevel@tonic-gate 	 */
1907276Sartem 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1908276Sartem 	    (!sp->s_symbios ||
1909276Sartem 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
19100Sstevel@tonic-gate 		/* but first, free old resources */
19110Sstevel@tonic-gate 		if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
19120Sstevel@tonic-gate 			scsa1394_cmd_pt_dma_free(sp, cmd);
19130Sstevel@tonic-gate 		}
19140Sstevel@tonic-gate 		scsa1394_cmd_seg_free(sp, cmd);
19150Sstevel@tonic-gate 
19160Sstevel@tonic-gate 		cmd->sc_buf_nsegs = 1;
19170Sstevel@tonic-gate 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
19180Sstevel@tonic-gate 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
19190Sstevel@tonic-gate 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
19200Sstevel@tonic-gate 	} else {
19210Sstevel@tonic-gate 		/* break window into segments */
19220Sstevel@tonic-gate 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, KM_NOSLEEP) !=
19230Sstevel@tonic-gate 		    DDI_SUCCESS) {
19240Sstevel@tonic-gate 			return (DDI_FAILURE);
19250Sstevel@tonic-gate 		}
19260Sstevel@tonic-gate 
19270Sstevel@tonic-gate 		/* allocate DMA resources */
19280Sstevel@tonic-gate 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, NULL_FUNC, NULL,
19290Sstevel@tonic-gate 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
19300Sstevel@tonic-gate 			return (DDI_FAILURE);
19310Sstevel@tonic-gate 		}
19320Sstevel@tonic-gate 	}
19330Sstevel@tonic-gate 
19340Sstevel@tonic-gate 	/* allocate 1394 addresses for segments */
19350Sstevel@tonic-gate 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
19360Sstevel@tonic-gate 		return (DDI_FAILURE);
19370Sstevel@tonic-gate 	}
19380Sstevel@tonic-gate 
19390Sstevel@tonic-gate 	return (DDI_SUCCESS);
19400Sstevel@tonic-gate }
19410Sstevel@tonic-gate 
19420Sstevel@tonic-gate /*
19430Sstevel@tonic-gate  *
19440Sstevel@tonic-gate  * --- pkt and data transfer routines
19450Sstevel@tonic-gate  *
19460Sstevel@tonic-gate  */
19470Sstevel@tonic-gate static int
scsa1394_scsi_start(struct scsi_address * ap,struct scsi_pkt * pkt)19480Sstevel@tonic-gate scsa1394_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
19490Sstevel@tonic-gate {
19500Sstevel@tonic-gate 	scsa1394_state_t *sp = ADDR2STATE(ap);
19510Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
19520Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
19530Sstevel@tonic-gate 	int		ret;
19540Sstevel@tonic-gate 
19550Sstevel@tonic-gate 	/*
19560Sstevel@tonic-gate 	 * since we don't support polled I/O, just accept the packet
19570Sstevel@tonic-gate 	 * so the rest of the file systems get synced properly
19580Sstevel@tonic-gate 	 */
19590Sstevel@tonic-gate 	if (ddi_in_panic()) {
19600Sstevel@tonic-gate 		scsa1394_prepare_pkt(sp, pkt);
19610Sstevel@tonic-gate 		return (TRAN_ACCEPT);
19620Sstevel@tonic-gate 	}
19630Sstevel@tonic-gate 
19640Sstevel@tonic-gate 	/* polling not supported yet */
19650Sstevel@tonic-gate 	if (pkt->pkt_flags & FLAG_NOINTR) {
19660Sstevel@tonic-gate 		return (TRAN_BADPKT);
19670Sstevel@tonic-gate 	}
19680Sstevel@tonic-gate 
1969276Sartem 	mutex_enter(&sp->s_mutex);
1970276Sartem 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
1971276Sartem 		/*
1972276Sartem 		 * If device is temporarily gone due to bus reset,
1973276Sartem 		 * return busy to prevent prevent scary console messages.
1974276Sartem 		 * If permanently gone, leave it to scsa1394_cmd_fake_comp().
1975276Sartem 		 */
1976276Sartem 		if (sp->s_dev_state == SCSA1394_DEV_BUS_RESET) {
1977276Sartem 			mutex_exit(&sp->s_mutex);
1978276Sartem 			return (TRAN_BUSY);
1979276Sartem 		}
1980276Sartem 	}
1981276Sartem 	mutex_exit(&sp->s_mutex);
1982276Sartem 
19830Sstevel@tonic-gate 	if ((ap->a_lun >= sp->s_nluns) ||
19840Sstevel@tonic-gate 	    (ap->a_lun != pkt->pkt_address.a_lun)) {
19850Sstevel@tonic-gate 		return (TRAN_BADPKT);
19860Sstevel@tonic-gate 	}
19870Sstevel@tonic-gate 
19880Sstevel@tonic-gate 	scsa1394_prepare_pkt(sp, pkt);
19890Sstevel@tonic-gate 
19900Sstevel@tonic-gate 	/* some commands may require fake completion */
19910Sstevel@tonic-gate 	if ((ret = scsa1394_cmd_fake_comp(sp, cmd)) == DDI_SUCCESS) {
19920Sstevel@tonic-gate 		return (TRAN_ACCEPT);
19930Sstevel@tonic-gate 	}
19940Sstevel@tonic-gate 
19950Sstevel@tonic-gate 	scsa1394_cmd_fill_cdb(lp, cmd);
19960Sstevel@tonic-gate 
19970Sstevel@tonic-gate 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
19980Sstevel@tonic-gate 		scsa1394_sbp2_seg2pt(lp, cmd);
19990Sstevel@tonic-gate 	}
20000Sstevel@tonic-gate 
20010Sstevel@tonic-gate 	scsa1394_sbp2_cmd2orb(lp, cmd);		/* convert into ORB */
20020Sstevel@tonic-gate 
20038763SAlan.Perry@Sun.COM 	if ((ret = scsa1394_sbp2_start(lp, cmd)) != TRAN_BUSY) {
20040Sstevel@tonic-gate 		scsa1394_sbp2_nudge(lp);
20050Sstevel@tonic-gate 	}
20060Sstevel@tonic-gate 
20070Sstevel@tonic-gate 	return (ret);
20080Sstevel@tonic-gate }
20090Sstevel@tonic-gate 
20100Sstevel@tonic-gate /*ARGSUSED*/
20110Sstevel@tonic-gate static void
scsa1394_prepare_pkt(scsa1394_state_t * sp,struct scsi_pkt * pkt)20120Sstevel@tonic-gate scsa1394_prepare_pkt(scsa1394_state_t *sp, struct scsi_pkt *pkt)
20130Sstevel@tonic-gate {
20140Sstevel@tonic-gate 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate 	pkt->pkt_reason = CMD_CMPLT;
20170Sstevel@tonic-gate 	pkt->pkt_state = 0;
20180Sstevel@tonic-gate 	pkt->pkt_statistics = 0;
20190Sstevel@tonic-gate 	*(pkt->pkt_scbp) = STATUS_GOOD;
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate 	if (cmd) {
20220Sstevel@tonic-gate 		cmd->sc_timeout = pkt->pkt_time;
20230Sstevel@tonic-gate 
20240Sstevel@tonic-gate 		/* workarounds */
20250Sstevel@tonic-gate 		switch (pkt->pkt_cdbp[0]) {
20260Sstevel@tonic-gate 		/*
20270Sstevel@tonic-gate 		 * sd does START_STOP_UNIT during attach with a 200 sec timeout.
20280Sstevel@tonic-gate 		 * at this time devi_lock is held, prtconf will be stuck.
20290Sstevel@tonic-gate 		 * reduce timeout for the time being.
20300Sstevel@tonic-gate 		 */
20310Sstevel@tonic-gate 		case SCMD_START_STOP:
20320Sstevel@tonic-gate 			cmd->sc_timeout = min(cmd->sc_timeout,
20330Sstevel@tonic-gate 			    scsa1394_start_stop_timeout_max);
20340Sstevel@tonic-gate 			break;
20350Sstevel@tonic-gate 		default:
20360Sstevel@tonic-gate 			break;
20370Sstevel@tonic-gate 		}
20380Sstevel@tonic-gate 	}
20390Sstevel@tonic-gate }
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate static void
scsa1394_cmd_fill_cdb(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)20420Sstevel@tonic-gate scsa1394_cmd_fill_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
20430Sstevel@tonic-gate {
20440Sstevel@tonic-gate 	cmd->sc_cdb_actual_len = cmd->sc_cdb_len;
20450Sstevel@tonic-gate 
20460Sstevel@tonic-gate 	mutex_enter(&lp->l_mutex);
20470Sstevel@tonic-gate 
20480Sstevel@tonic-gate 	switch (lp->l_dtype_orig) {
20490Sstevel@tonic-gate 	case DTYPE_DIRECT:
20500Sstevel@tonic-gate 	case DTYPE_RODIRECT:
20510Sstevel@tonic-gate 	case DTYPE_OPTICAL:
20520Sstevel@tonic-gate 	case SCSA1394_DTYPE_RBC:
20530Sstevel@tonic-gate 		scsa1394_cmd_fill_cdb_rbc(lp, cmd);
20540Sstevel@tonic-gate 		break;
20550Sstevel@tonic-gate 	default:
20560Sstevel@tonic-gate 		scsa1394_cmd_fill_cdb_other(lp, cmd);
20570Sstevel@tonic-gate 		break;
20580Sstevel@tonic-gate 	}
20590Sstevel@tonic-gate 
20600Sstevel@tonic-gate 	mutex_exit(&lp->l_mutex);
20610Sstevel@tonic-gate }
20620Sstevel@tonic-gate 
20630Sstevel@tonic-gate static void
scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)20640Sstevel@tonic-gate scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
20650Sstevel@tonic-gate {
20660Sstevel@tonic-gate 	scsa1394_state_t *sp = lp->l_sp;
20670Sstevel@tonic-gate 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
20680Sstevel@tonic-gate 	int		lba, opcode;
20690Sstevel@tonic-gate 	struct buf	*bp = cmd->sc_bp;
20700Sstevel@tonic-gate 	size_t		len;
20710Sstevel@tonic-gate 	size_t		blk_size;
20720Sstevel@tonic-gate 	int		sz;
20730Sstevel@tonic-gate 
20740Sstevel@tonic-gate 	opcode = pkt->pkt_cdbp[0];
20750Sstevel@tonic-gate 	blk_size  = lp->l_lba_size;
20760Sstevel@tonic-gate 
20770Sstevel@tonic-gate 	switch (opcode) {
20780Sstevel@tonic-gate 	case SCMD_READ:
20790Sstevel@tonic-gate 		/* RBC only supports 10-byte read/write */
20800Sstevel@tonic-gate 		lba = SCSA1394_LBA_6BYTE(pkt);
20810Sstevel@tonic-gate 		len = SCSA1394_LEN_6BYTE(pkt);
20820Sstevel@tonic-gate 		opcode = SCMD_READ_G1;
20830Sstevel@tonic-gate 		cmd->sc_cdb_actual_len = CDB_GROUP1;
20840Sstevel@tonic-gate 		break;
20850Sstevel@tonic-gate 	case SCMD_WRITE:
20860Sstevel@tonic-gate 		lba = SCSA1394_LBA_6BYTE(pkt);
20870Sstevel@tonic-gate 		len = SCSA1394_LEN_6BYTE(pkt);
20880Sstevel@tonic-gate 		opcode = SCMD_WRITE_G1;
20890Sstevel@tonic-gate 		cmd->sc_cdb_actual_len = CDB_GROUP1;
20900Sstevel@tonic-gate 		break;
20910Sstevel@tonic-gate 	case SCMD_READ_G1:
20920Sstevel@tonic-gate 	case SCMD_READ_LONG:
20930Sstevel@tonic-gate 		lba = SCSA1394_LBA_10BYTE(pkt);
20940Sstevel@tonic-gate 		len = SCSA1394_LEN_10BYTE(pkt);
20950Sstevel@tonic-gate 		break;
20960Sstevel@tonic-gate 	case SCMD_WRITE_G1:
20970Sstevel@tonic-gate 	case SCMD_WRITE_LONG:
20980Sstevel@tonic-gate 		lba = SCSA1394_LBA_10BYTE(pkt);
20990Sstevel@tonic-gate 		len = SCSA1394_LEN_10BYTE(pkt);
2100276Sartem 		if ((lp->l_dtype_orig == DTYPE_RODIRECT) &&
2101276Sartem 		    (bp != NULL) && (len != 0)) {
2102276Sartem 			sz = SCSA1394_CDRW_BLKSZ(bp->b_bcount, len);
2103276Sartem 			if (SCSA1394_VALID_CDRW_BLKSZ(sz)) {
2104276Sartem 				blk_size = sz;
2105276Sartem 			}
21060Sstevel@tonic-gate 		}
21070Sstevel@tonic-gate 		break;
21080Sstevel@tonic-gate 	case SCMD_READ_CD:
21090Sstevel@tonic-gate 		lba = SCSA1394_LBA_10BYTE(pkt);
21100Sstevel@tonic-gate 		len = SCSA1394_LEN_READ_CD(pkt);
21110Sstevel@tonic-gate 		blk_size = scsa1394_cmd_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2);
21120Sstevel@tonic-gate 		break;
21130Sstevel@tonic-gate 	case SCMD_READ_G5:
21140Sstevel@tonic-gate 		lba = SCSA1394_LBA_12BYTE(pkt);
21150Sstevel@tonic-gate 		len = SCSA1394_LEN_12BYTE(pkt);
21160Sstevel@tonic-gate 		break;
21170Sstevel@tonic-gate 	case SCMD_WRITE_G5:
21180Sstevel@tonic-gate 		lba = SCSA1394_LBA_12BYTE(pkt);
21190Sstevel@tonic-gate 		len = SCSA1394_LEN_12BYTE(pkt);
21200Sstevel@tonic-gate 		break;
21210Sstevel@tonic-gate 	default:
21220Sstevel@tonic-gate 		/* no special mapping for other commands */
21230Sstevel@tonic-gate 		scsa1394_cmd_fill_cdb_other(lp, cmd);
21240Sstevel@tonic-gate 		return;
21250Sstevel@tonic-gate 	}
2126276Sartem 	cmd->sc_blk_size = blk_size;
21270Sstevel@tonic-gate 
21280Sstevel@tonic-gate 	/* limit xfer length for Symbios workaround */
21290Sstevel@tonic-gate 	if (sp->s_symbios && (len * blk_size > scsa1394_symbios_size_max)) {
21300Sstevel@tonic-gate 		cmd->sc_flags |= SCSA1394_CMD_SYMBIOS_BREAKUP;
21310Sstevel@tonic-gate 
21320Sstevel@tonic-gate 		cmd->sc_total_blks = cmd->sc_resid_blks = len;
21330Sstevel@tonic-gate 
21340Sstevel@tonic-gate 		len = scsa1394_symbios_size_max / blk_size;
21350Sstevel@tonic-gate 	}
21360Sstevel@tonic-gate 	cmd->sc_xfer_blks = len;
21370Sstevel@tonic-gate 	cmd->sc_xfer_bytes = len * blk_size;
21380Sstevel@tonic-gate 
21390Sstevel@tonic-gate 	/* finalize new CDB */
21401963Sap25164 	switch (pkt->pkt_cdbp[0]) {
21411963Sap25164 	case SCMD_READ:
21421963Sap25164 	case SCMD_WRITE:
21431963Sap25164 		/*
21441963Sap25164 		 * We rewrite READ/WRITE G0 commands as READ/WRITE G1.
21451963Sap25164 		 * Build new cdb from scatch.
21461963Sap25164 		 * The lba and length fields is updated below.
21471963Sap25164 		 */
21481963Sap25164 		bzero(cmd->sc_cdb, cmd->sc_cdb_actual_len);
21491963Sap25164 		break;
21501963Sap25164 	default:
21511963Sap25164 		/*
21521963Sap25164 		 * Copy the non lba/len fields.
21531963Sap25164 		 * The lba and length fields is updated below.
21541963Sap25164 		 */
21551963Sap25164 		bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_actual_len);
21561963Sap25164 		break;
21571963Sap25164 	}
21581963Sap25164 
21590Sstevel@tonic-gate 	cmd->sc_cdb[0] = (uchar_t)opcode;
21600Sstevel@tonic-gate 	scsa1394_cmd_fill_cdb_lba(cmd, lba);
21610Sstevel@tonic-gate 	switch (opcode) {
21620Sstevel@tonic-gate 	case SCMD_READ_CD:
21630Sstevel@tonic-gate 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
21640Sstevel@tonic-gate 		break;
21650Sstevel@tonic-gate 	case SCMD_WRITE_G5:
21660Sstevel@tonic-gate 	case SCMD_READ_G5:
21670Sstevel@tonic-gate 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
21680Sstevel@tonic-gate 		break;
21690Sstevel@tonic-gate 	default:
21700Sstevel@tonic-gate 		scsa1394_cmd_fill_cdb_len(cmd, len);
21710Sstevel@tonic-gate 		break;
21720Sstevel@tonic-gate 	}
21730Sstevel@tonic-gate }
21740Sstevel@tonic-gate 
21750Sstevel@tonic-gate /*ARGSUSED*/
21760Sstevel@tonic-gate static void
scsa1394_cmd_fill_cdb_other(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)21770Sstevel@tonic-gate scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
21780Sstevel@tonic-gate {
21790Sstevel@tonic-gate 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
21800Sstevel@tonic-gate 
2181276Sartem 	cmd->sc_xfer_bytes = cmd->sc_win_len;
2182276Sartem 	cmd->sc_xfer_blks = cmd->sc_xfer_bytes / lp->l_lba_size;
2183276Sartem 	cmd->sc_total_blks = cmd->sc_xfer_blks;
2184276Sartem 	cmd->sc_lba = 0;
21850Sstevel@tonic-gate 
2186276Sartem 	bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_len);
21870Sstevel@tonic-gate }
21880Sstevel@tonic-gate 
21890Sstevel@tonic-gate /*
21900Sstevel@tonic-gate  * fill up parts of CDB
21910Sstevel@tonic-gate  */
21920Sstevel@tonic-gate static void
scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t * cmd,int len)21930Sstevel@tonic-gate scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *cmd, int len)
21940Sstevel@tonic-gate {
21950Sstevel@tonic-gate 	cmd->sc_cdb[7] = len >> 8;
21960Sstevel@tonic-gate 	cmd->sc_cdb[8] = (uchar_t)len;
21970Sstevel@tonic-gate }
21980Sstevel@tonic-gate 
21990Sstevel@tonic-gate static void
scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t * cmd,int lba)22000Sstevel@tonic-gate scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *cmd, int lba)
22010Sstevel@tonic-gate {
22020Sstevel@tonic-gate 	cmd->sc_cdb[2] = lba >> 24;
22030Sstevel@tonic-gate 	cmd->sc_cdb[3] = lba >> 16;
22040Sstevel@tonic-gate 	cmd->sc_cdb[4] = lba >> 8;
22050Sstevel@tonic-gate 	cmd->sc_cdb[5] = (uchar_t)lba;
22060Sstevel@tonic-gate 	cmd->sc_lba = lba;
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate 
22090Sstevel@tonic-gate static void
scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t * cmd,int len)22100Sstevel@tonic-gate scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *cmd, int len)
22110Sstevel@tonic-gate {
22120Sstevel@tonic-gate 	cmd->sc_cdb[6] = len >> 24;
22130Sstevel@tonic-gate 	cmd->sc_cdb[7] = len >> 16;
22140Sstevel@tonic-gate 	cmd->sc_cdb[8] = len >> 8;
22150Sstevel@tonic-gate 	cmd->sc_cdb[9] = (uchar_t)len;
22160Sstevel@tonic-gate }
22170Sstevel@tonic-gate 
22180Sstevel@tonic-gate static void
scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t * cmd,int len)22190Sstevel@tonic-gate scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *cmd, int len)
22200Sstevel@tonic-gate {
22210Sstevel@tonic-gate 	cmd->sc_cdb[6] = len >> 16;
22220Sstevel@tonic-gate 	cmd->sc_cdb[7] = len >> 8;
22230Sstevel@tonic-gate 	cmd->sc_cdb[8] = (uchar_t)len;
22240Sstevel@tonic-gate }
22250Sstevel@tonic-gate 
22260Sstevel@tonic-gate /*
22270Sstevel@tonic-gate  * For SCMD_READ_CD, figure out the block size based on expected sector type.
22280Sstevel@tonic-gate  * See MMC SCSI Specs section 6.1.15
22290Sstevel@tonic-gate  */
22300Sstevel@tonic-gate static int
scsa1394_cmd_read_cd_blk_size(uchar_t expected_sector_type)22310Sstevel@tonic-gate scsa1394_cmd_read_cd_blk_size(uchar_t expected_sector_type)
22320Sstevel@tonic-gate {
22330Sstevel@tonic-gate 	int blk_size;
22340Sstevel@tonic-gate 
22350Sstevel@tonic-gate 	switch (expected_sector_type) {
22360Sstevel@tonic-gate 	case READ_CD_EST_CDDA:
22370Sstevel@tonic-gate 		blk_size = CDROM_BLK_2352;
22380Sstevel@tonic-gate 		break;
22390Sstevel@tonic-gate 	case READ_CD_EST_MODE2:
22400Sstevel@tonic-gate 		blk_size = CDROM_BLK_2336;
22410Sstevel@tonic-gate 		break;
22420Sstevel@tonic-gate 	case READ_CD_EST_MODE2FORM2:
22430Sstevel@tonic-gate 		blk_size = CDROM_BLK_2324;
22440Sstevel@tonic-gate 		break;
22450Sstevel@tonic-gate 	case READ_CD_EST_MODE2FORM1:
22460Sstevel@tonic-gate 	case READ_CD_EST_ALLTYPE:
22470Sstevel@tonic-gate 	case READ_CD_EST_MODE1:
22480Sstevel@tonic-gate 	default:
22490Sstevel@tonic-gate 		blk_size = CDROM_BLK_2048;
22500Sstevel@tonic-gate 	}
22510Sstevel@tonic-gate 
22520Sstevel@tonic-gate 	return (blk_size);
22530Sstevel@tonic-gate }
22540Sstevel@tonic-gate 
22550Sstevel@tonic-gate /*ARGSUSED*/
22560Sstevel@tonic-gate static int
scsa1394_cmd_fake_mode_sense(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)22570Sstevel@tonic-gate scsa1394_cmd_fake_mode_sense(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
22580Sstevel@tonic-gate {
22590Sstevel@tonic-gate 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
22600Sstevel@tonic-gate 	struct scsi_arq_status *arqp = (struct scsi_arq_status *)pkt->pkt_scbp;
22610Sstevel@tonic-gate 	struct scsi_extended_sense *esp = &arqp->sts_sensedata;
22620Sstevel@tonic-gate 
22630Sstevel@tonic-gate 	*(pkt->pkt_scbp) = STATUS_CHECK;
22640Sstevel@tonic-gate 	*(uint8_t *)&arqp->sts_rqpkt_status = STATUS_GOOD;
22650Sstevel@tonic-gate 	arqp->sts_rqpkt_reason = CMD_CMPLT;
22660Sstevel@tonic-gate 	arqp->sts_rqpkt_resid = 0;
22670Sstevel@tonic-gate 	arqp->sts_rqpkt_state |= STATE_XFERRED_DATA;
22680Sstevel@tonic-gate 	arqp->sts_rqpkt_statistics = 0;
22690Sstevel@tonic-gate 
22700Sstevel@tonic-gate 	bzero(esp, sizeof (struct scsi_extended_sense));
22710Sstevel@tonic-gate 
22720Sstevel@tonic-gate 	esp->es_class = CLASS_EXTENDED_SENSE;
22730Sstevel@tonic-gate 
22740Sstevel@tonic-gate 	esp->es_key = KEY_ILLEGAL_REQUEST;
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate 	pkt->pkt_reason = CMD_CMPLT;
22770Sstevel@tonic-gate 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
22780Sstevel@tonic-gate 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
22790Sstevel@tonic-gate 
22800Sstevel@tonic-gate 	if (pkt->pkt_comp) {
22810Sstevel@tonic-gate 		(*pkt->pkt_comp)(pkt);
22820Sstevel@tonic-gate 	}
22830Sstevel@tonic-gate 	return (DDI_SUCCESS);
22840Sstevel@tonic-gate }
22850Sstevel@tonic-gate 
22860Sstevel@tonic-gate /*ARGSUSED*/
22870Sstevel@tonic-gate static int
scsa1394_cmd_fake_inquiry(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)22880Sstevel@tonic-gate scsa1394_cmd_fake_inquiry(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
22890Sstevel@tonic-gate {
22900Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
22910Sstevel@tonic-gate 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
22920Sstevel@tonic-gate 	struct scsi_inquiry *inq;
22930Sstevel@tonic-gate 
22940Sstevel@tonic-gate 	/* copy fabricated inquiry data */
22950Sstevel@tonic-gate 	inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
22960Sstevel@tonic-gate 	bcopy(&lp->l_fake_inq, inq, sizeof (struct scsi_inquiry));
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate 	pkt->pkt_resid -= sizeof (struct scsi_inquiry);
22990Sstevel@tonic-gate 	pkt->pkt_reason = CMD_CMPLT;
23000Sstevel@tonic-gate 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
23010Sstevel@tonic-gate 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
23020Sstevel@tonic-gate 
23030Sstevel@tonic-gate 	if (pkt->pkt_comp) {
23040Sstevel@tonic-gate 		(*pkt->pkt_comp)(pkt);
23050Sstevel@tonic-gate 	}
23060Sstevel@tonic-gate 	return (DDI_SUCCESS);
23070Sstevel@tonic-gate }
23080Sstevel@tonic-gate 
23090Sstevel@tonic-gate /*
23100Sstevel@tonic-gate  * If command allows fake completion (without actually being transported),
23110Sstevel@tonic-gate  * call completion callback and return DDI_SUCCESS.
23120Sstevel@tonic-gate  * Otherwise return DDI_FAILURE.
23130Sstevel@tonic-gate  */
23140Sstevel@tonic-gate static int
scsa1394_cmd_fake_comp(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)23150Sstevel@tonic-gate scsa1394_cmd_fake_comp(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
23160Sstevel@tonic-gate {
23170Sstevel@tonic-gate 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
23180Sstevel@tonic-gate 	scsa1394_lun_t	*lp = cmd->sc_lun;
23190Sstevel@tonic-gate 	int		ret = DDI_SUCCESS;
23200Sstevel@tonic-gate 
2321276Sartem 	/*
2322276Sartem 	 * agreement with sd in case of device hot removal
2323276Sartem 	 * is to fake completion with CMD_DEV_GONE
2324276Sartem 	 */
2325276Sartem 	mutex_enter(&sp->s_mutex);
2326276Sartem 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
2327276Sartem 		mutex_exit(&sp->s_mutex);
2328276Sartem 		pkt->pkt_reason = CMD_DEV_GONE;
2329276Sartem 		if (pkt->pkt_comp) {
2330276Sartem 			(*pkt->pkt_comp)(pkt);
2331276Sartem 		}
2332276Sartem 		return (DDI_SUCCESS);
2333276Sartem 	}
2334276Sartem 	mutex_exit(&sp->s_mutex);
2335276Sartem 
23360Sstevel@tonic-gate 	mutex_enter(&lp->l_mutex);
23370Sstevel@tonic-gate 
23380Sstevel@tonic-gate 	switch (pkt->pkt_cdbp[0]) {
23390Sstevel@tonic-gate 	/*
23400Sstevel@tonic-gate 	 * RBC support for PRIN/PROUT is optional
23410Sstevel@tonic-gate 	 */
23420Sstevel@tonic-gate 	case SCMD_PRIN:
23430Sstevel@tonic-gate 	case SCMD_PROUT:
23440Sstevel@tonic-gate 		if (!scsa1394_wrka_fake_prin) {
23450Sstevel@tonic-gate 			ret = DDI_FAILURE;
23460Sstevel@tonic-gate 		}
23470Sstevel@tonic-gate 		break;
23480Sstevel@tonic-gate 	/*
23490Sstevel@tonic-gate 	 * Some fixed disks don't like doorlock cmd. And they don't need it.
23500Sstevel@tonic-gate 	 */
23510Sstevel@tonic-gate 	case SCMD_DOORLOCK:
23520Sstevel@tonic-gate 		if (lp->l_rmb_orig != 0) {
23530Sstevel@tonic-gate 			ret = DDI_FAILURE;
23540Sstevel@tonic-gate 		}
23550Sstevel@tonic-gate 		break;
23560Sstevel@tonic-gate 	case SCMD_TEST_UNIT_READY:
23570Sstevel@tonic-gate 		if (!lp->l_nosup_tur) {
23580Sstevel@tonic-gate 			ret = DDI_FAILURE;
23590Sstevel@tonic-gate 		}
23600Sstevel@tonic-gate 		break;
23610Sstevel@tonic-gate 	case SCMD_START_STOP:
23620Sstevel@tonic-gate 		if (!lp->l_nosup_start_stop) {
23630Sstevel@tonic-gate 			ret = DDI_FAILURE;
23640Sstevel@tonic-gate 		}
23650Sstevel@tonic-gate 		break;
23660Sstevel@tonic-gate 	case SCMD_INQUIRY:
23670Sstevel@tonic-gate 		if (!lp->l_nosup_inquiry) {
23680Sstevel@tonic-gate 			ret = DDI_FAILURE;
23690Sstevel@tonic-gate 		} else {
23700Sstevel@tonic-gate 			mutex_exit(&lp->l_mutex);
23710Sstevel@tonic-gate 			return (scsa1394_cmd_fake_inquiry(sp, cmd));
23720Sstevel@tonic-gate 		}
23730Sstevel@tonic-gate 		break;
23740Sstevel@tonic-gate 	case SCMD_MODE_SENSE:
23750Sstevel@tonic-gate 		if (!lp->l_mode_sense_fake) {
23760Sstevel@tonic-gate 			ret = DDI_FAILURE;
23770Sstevel@tonic-gate 		} else {
23780Sstevel@tonic-gate 			mutex_exit(&lp->l_mutex);
23790Sstevel@tonic-gate 			return (scsa1394_cmd_fake_mode_sense(sp, cmd));
23800Sstevel@tonic-gate 		}
23810Sstevel@tonic-gate 	default:
23820Sstevel@tonic-gate 		ret = DDI_FAILURE;
23830Sstevel@tonic-gate 	}
23840Sstevel@tonic-gate 
23850Sstevel@tonic-gate 	mutex_exit(&lp->l_mutex);
23860Sstevel@tonic-gate 
23870Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
23880Sstevel@tonic-gate 		return (ret);
23890Sstevel@tonic-gate 	}
23900Sstevel@tonic-gate 
23910Sstevel@tonic-gate 	ASSERT(*(pkt->pkt_scbp) == STATUS_GOOD);
23920Sstevel@tonic-gate 	ASSERT(pkt->pkt_reason == CMD_CMPLT);
23930Sstevel@tonic-gate 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
23940Sstevel@tonic-gate 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
23950Sstevel@tonic-gate 
23960Sstevel@tonic-gate 	if (pkt->pkt_comp) {
23970Sstevel@tonic-gate 		(*pkt->pkt_comp)(pkt);
23980Sstevel@tonic-gate 	}
23990Sstevel@tonic-gate 	return (DDI_SUCCESS);
24000Sstevel@tonic-gate }
24010Sstevel@tonic-gate 
24020Sstevel@tonic-gate /*
24030Sstevel@tonic-gate  * Returns DDI_SUCCESS if next xfer setup successfully, DDI_FAILURE otherwise.
24040Sstevel@tonic-gate  */
24050Sstevel@tonic-gate static int
scsa1394_cmd_setup_next_xfer(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)24060Sstevel@tonic-gate scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
24070Sstevel@tonic-gate {
24080Sstevel@tonic-gate 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
24090Sstevel@tonic-gate 
24100Sstevel@tonic-gate 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
24110Sstevel@tonic-gate 
24120Sstevel@tonic-gate 	cmd->sc_resid_blks -= cmd->sc_xfer_blks;
24130Sstevel@tonic-gate 	if (cmd->sc_resid_blks <= 0) {
24140Sstevel@tonic-gate 		pkt->pkt_resid = 0;
24150Sstevel@tonic-gate 		return (DDI_FAILURE);
24160Sstevel@tonic-gate 	}
24170Sstevel@tonic-gate 
24180Sstevel@tonic-gate 	scsa1394_cmd_adjust_cdb(lp, cmd);
24190Sstevel@tonic-gate 
24200Sstevel@tonic-gate 	scsa1394_sbp2_seg2pt(lp, cmd);
24210Sstevel@tonic-gate 
24220Sstevel@tonic-gate 	scsa1394_sbp2_cmd2orb(lp, cmd);
24230Sstevel@tonic-gate 
24240Sstevel@tonic-gate 	if (scsa1394_sbp2_start(lp, cmd) != TRAN_ACCEPT) {
24250Sstevel@tonic-gate 		pkt->pkt_resid = cmd->sc_resid_blks * cmd->sc_blk_size;
24260Sstevel@tonic-gate 		return (DDI_FAILURE);
24270Sstevel@tonic-gate 	}
24280Sstevel@tonic-gate 
24290Sstevel@tonic-gate 	return (DDI_SUCCESS);
24300Sstevel@tonic-gate }
24310Sstevel@tonic-gate 
24320Sstevel@tonic-gate /*
24330Sstevel@tonic-gate  * new lba = current lba + previous xfer len
24340Sstevel@tonic-gate  */
24350Sstevel@tonic-gate /*ARGSUSED*/
24360Sstevel@tonic-gate static void
scsa1394_cmd_adjust_cdb(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)24370Sstevel@tonic-gate scsa1394_cmd_adjust_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
24380Sstevel@tonic-gate {
24390Sstevel@tonic-gate 	int		len;
24400Sstevel@tonic-gate 
24410Sstevel@tonic-gate 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate 	cmd->sc_lba += cmd->sc_xfer_blks;
24440Sstevel@tonic-gate 	len = cmd->sc_resid_blks;
24450Sstevel@tonic-gate 
24460Sstevel@tonic-gate 	/* limit xfer length for Symbios workaround */
24470Sstevel@tonic-gate 	if (len * cmd->sc_blk_size > scsa1394_symbios_size_max) {
24480Sstevel@tonic-gate 		len = scsa1394_symbios_size_max / cmd->sc_blk_size;
24490Sstevel@tonic-gate 	}
24500Sstevel@tonic-gate 
24510Sstevel@tonic-gate 	switch (cmd->sc_cdb[0]) {
24520Sstevel@tonic-gate 	case SCMD_READ_CD:
24530Sstevel@tonic-gate 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
24540Sstevel@tonic-gate 		break;
24550Sstevel@tonic-gate 	case SCMD_WRITE_G5:
24560Sstevel@tonic-gate 	case SCMD_READ_G5:
24570Sstevel@tonic-gate 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
24580Sstevel@tonic-gate 		break;
24590Sstevel@tonic-gate 	case SCMD_WRITE_G1:
24600Sstevel@tonic-gate 	case SCMD_WRITE_LONG:
24610Sstevel@tonic-gate 	default:
24620Sstevel@tonic-gate 		scsa1394_cmd_fill_cdb_len(cmd, len);
24630Sstevel@tonic-gate 	}
24640Sstevel@tonic-gate 
24650Sstevel@tonic-gate 	scsa1394_cmd_fill_cdb_lba(cmd, cmd->sc_lba);
24660Sstevel@tonic-gate 
24670Sstevel@tonic-gate 	cmd->sc_xfer_blks = len;
24680Sstevel@tonic-gate 	cmd->sc_xfer_bytes = len * cmd->sc_blk_size;
24690Sstevel@tonic-gate }
24700Sstevel@tonic-gate 
24710Sstevel@tonic-gate void
scsa1394_cmd_status_proc(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)24720Sstevel@tonic-gate scsa1394_cmd_status_proc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
24730Sstevel@tonic-gate {
24740Sstevel@tonic-gate 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
24750Sstevel@tonic-gate 
24760Sstevel@tonic-gate 	/* next iteration of partial xfer? */
24770Sstevel@tonic-gate 	if ((pkt->pkt_reason == CMD_CMPLT) &&
24780Sstevel@tonic-gate 	    (cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP)) {
24790Sstevel@tonic-gate 		if (scsa1394_cmd_setup_next_xfer(lp, cmd) == DDI_SUCCESS) {
24800Sstevel@tonic-gate 			return;
24810Sstevel@tonic-gate 		}
24820Sstevel@tonic-gate 	}
24830Sstevel@tonic-gate 	cmd->sc_flags &= ~SCSA1394_CMD_SYMBIOS_BREAKUP;
24840Sstevel@tonic-gate 
24850Sstevel@tonic-gate 	/* apply workarounds */
24860Sstevel@tonic-gate 	if (pkt->pkt_reason == CMD_CMPLT) {
24870Sstevel@tonic-gate 		scsa1394_cmd_status_wrka(lp, cmd);
24880Sstevel@tonic-gate 	}
24890Sstevel@tonic-gate 
24900Sstevel@tonic-gate 	mutex_enter(&lp->l_mutex);
24910Sstevel@tonic-gate 
24920Sstevel@tonic-gate 	/* mode sense workaround */
24930Sstevel@tonic-gate 	if (pkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
24940Sstevel@tonic-gate 		if (pkt->pkt_reason == CMD_CMPLT) {
24950Sstevel@tonic-gate 			lp->l_mode_sense_fail_cnt = 0;
24960Sstevel@tonic-gate 		} else if (++lp->l_mode_sense_fail_cnt >=
24970Sstevel@tonic-gate 		    scsa1394_mode_sense_fail_max) {
24980Sstevel@tonic-gate 			lp->l_mode_sense_fake = B_TRUE;
24990Sstevel@tonic-gate 		}
25000Sstevel@tonic-gate 	} else {
25010Sstevel@tonic-gate 		lp->l_mode_sense_fail_cnt = 0;
25020Sstevel@tonic-gate 	}
25030Sstevel@tonic-gate 
25040Sstevel@tonic-gate 	mutex_exit(&lp->l_mutex);
25050Sstevel@tonic-gate 
25060Sstevel@tonic-gate 	if (pkt->pkt_comp) {
25070Sstevel@tonic-gate 		(*pkt->pkt_comp)(pkt);
25080Sstevel@tonic-gate 	}
25090Sstevel@tonic-gate }
25100Sstevel@tonic-gate 
25110Sstevel@tonic-gate static void
scsa1394_cmd_status_wrka(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)25120Sstevel@tonic-gate scsa1394_cmd_status_wrka(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
25130Sstevel@tonic-gate {
25140Sstevel@tonic-gate 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
25150Sstevel@tonic-gate 
25160Sstevel@tonic-gate 	mutex_enter(&lp->l_mutex);
25170Sstevel@tonic-gate 
25180Sstevel@tonic-gate 	switch (pkt->pkt_cdbp[0]) {
25190Sstevel@tonic-gate 	case SCMD_INQUIRY: {
25200Sstevel@tonic-gate 		struct scsi_inquiry *inq;
25210Sstevel@tonic-gate 
25220Sstevel@tonic-gate 		inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
25230Sstevel@tonic-gate 
25240Sstevel@tonic-gate 		/* change dtype RBC to DIRECT, sd doesn't support RBC */
25250Sstevel@tonic-gate 		lp->l_dtype_orig = inq->inq_dtype;
25260Sstevel@tonic-gate 		if ((inq->inq_dtype == SCSA1394_DTYPE_RBC) &&
25270Sstevel@tonic-gate 		    scsa1394_wrka_rbc2direct) {
25280Sstevel@tonic-gate 			inq->inq_dtype = DTYPE_DIRECT;
25290Sstevel@tonic-gate 		}
25300Sstevel@tonic-gate 
25310Sstevel@tonic-gate 		/* force RMB to 1 */
25320Sstevel@tonic-gate 		lp->l_rmb_orig = inq->inq_rmb;
25331415Scg149915 		if (scsa1394_wrka_fake_rmb) {
25340Sstevel@tonic-gate 			inq->inq_rmb = 1;
25350Sstevel@tonic-gate 		}
25360Sstevel@tonic-gate 		break;
25370Sstevel@tonic-gate 	}
25380Sstevel@tonic-gate 	case SCMD_READ_CAPACITY: {
25390Sstevel@tonic-gate 		uint32_t	*capacity_buf;
25400Sstevel@tonic-gate 
25410Sstevel@tonic-gate 		capacity_buf = (uint32_t *)cmd->sc_bp->b_un.b_addr;
25420Sstevel@tonic-gate 
25430Sstevel@tonic-gate 		if (lp->l_dtype_orig != DTYPE_RODIRECT) {
25440Sstevel@tonic-gate 			lp->l_lba_size = min(BE_32(capacity_buf[1]), DEV_BSIZE);
25450Sstevel@tonic-gate 			if (lp->l_lba_size == 0) {
25460Sstevel@tonic-gate 				cmn_err(CE_WARN, "zero LBA size reported, "
25470Sstevel@tonic-gate 				    "possibly broken device");
25480Sstevel@tonic-gate 				lp->l_lba_size = DEV_BSIZE;
25490Sstevel@tonic-gate 			}
25500Sstevel@tonic-gate 		} else {
25510Sstevel@tonic-gate 			lp->l_lba_size = 2048;
25520Sstevel@tonic-gate 		}
25530Sstevel@tonic-gate 	}
25540Sstevel@tonic-gate 	default:
25550Sstevel@tonic-gate 		break;
25560Sstevel@tonic-gate 	}
25570Sstevel@tonic-gate 
25580Sstevel@tonic-gate 	mutex_exit(&lp->l_mutex);
25590Sstevel@tonic-gate }
25600Sstevel@tonic-gate 
25610Sstevel@tonic-gate /*
25620Sstevel@tonic-gate  * --- thread management
25630Sstevel@tonic-gate  *
25640Sstevel@tonic-gate  * dispatch a thread
25650Sstevel@tonic-gate  */
25660Sstevel@tonic-gate int
scsa1394_thr_dispatch(scsa1394_thread_t * thr)25670Sstevel@tonic-gate scsa1394_thr_dispatch(scsa1394_thread_t *thr)
25680Sstevel@tonic-gate {
25690Sstevel@tonic-gate 	scsa1394_lun_t		*lp = thr->thr_lun;
25700Sstevel@tonic-gate 	scsa1394_state_t	*sp = lp->l_sp;
25710Sstevel@tonic-gate 	int			ret;
25720Sstevel@tonic-gate 
25730Sstevel@tonic-gate 	ASSERT(mutex_owned(&lp->l_mutex));
25740Sstevel@tonic-gate 	ASSERT(thr->thr_state == SCSA1394_THR_INIT);
25750Sstevel@tonic-gate 
25760Sstevel@tonic-gate 	thr->thr_state = SCSA1394_THR_RUN;
25770Sstevel@tonic-gate 
25780Sstevel@tonic-gate 	ret = ddi_taskq_dispatch(sp->s_taskq, thr->thr_func, thr->thr_arg,
25790Sstevel@tonic-gate 	    KM_SLEEP);
25800Sstevel@tonic-gate 	return (ret);
25810Sstevel@tonic-gate }
25820Sstevel@tonic-gate 
25830Sstevel@tonic-gate /*
25840Sstevel@tonic-gate  * cancel thread
25850Sstevel@tonic-gate  */
25860Sstevel@tonic-gate void
scsa1394_thr_cancel(scsa1394_thread_t * thr)25870Sstevel@tonic-gate scsa1394_thr_cancel(scsa1394_thread_t *thr)
25880Sstevel@tonic-gate {
25890Sstevel@tonic-gate 	scsa1394_lun_t		*lp = thr->thr_lun;
25900Sstevel@tonic-gate 
25910Sstevel@tonic-gate 	ASSERT(mutex_owned(&lp->l_mutex));
25920Sstevel@tonic-gate 
25930Sstevel@tonic-gate 	thr->thr_req |= SCSA1394_THREQ_EXIT;
25940Sstevel@tonic-gate 	cv_signal(&thr->thr_cv);
25950Sstevel@tonic-gate 
25960Sstevel@tonic-gate 	/* wait until the thread actually exits */
25970Sstevel@tonic-gate 	do {
25980Sstevel@tonic-gate 		if (cv_wait_sig(&thr->thr_cv, &lp->l_mutex) == 0) {
25990Sstevel@tonic-gate 			break;
26000Sstevel@tonic-gate 		}
26010Sstevel@tonic-gate 	} while (thr->thr_state != SCSA1394_THR_EXIT);
26020Sstevel@tonic-gate }
26030Sstevel@tonic-gate 
26040Sstevel@tonic-gate /*
26050Sstevel@tonic-gate  * wake thread
26060Sstevel@tonic-gate  */
26070Sstevel@tonic-gate void
scsa1394_thr_wake(scsa1394_thread_t * thr,int req)26080Sstevel@tonic-gate scsa1394_thr_wake(scsa1394_thread_t *thr, int req)
26090Sstevel@tonic-gate {
26100Sstevel@tonic-gate 	scsa1394_lun_t		*lp = thr->thr_lun;
26110Sstevel@tonic-gate 
26120Sstevel@tonic-gate 	ASSERT(mutex_owned(&lp->l_mutex));
26130Sstevel@tonic-gate 
26140Sstevel@tonic-gate 	thr->thr_req |= req;
26150Sstevel@tonic-gate 	cv_signal(&thr->thr_cv);
26160Sstevel@tonic-gate }
26170Sstevel@tonic-gate 
26180Sstevel@tonic-gate void
scsa1394_thr_clear_req(scsa1394_thread_t * thr,int mask)26190Sstevel@tonic-gate scsa1394_thr_clear_req(scsa1394_thread_t *thr, int mask)
26200Sstevel@tonic-gate {
26210Sstevel@tonic-gate 	scsa1394_lun_t		*lp = thr->thr_lun;
26220Sstevel@tonic-gate 
26230Sstevel@tonic-gate 	mutex_enter(&lp->l_mutex);
26240Sstevel@tonic-gate 	thr->thr_req &= ~mask;
26250Sstevel@tonic-gate 	mutex_exit(&lp->l_mutex);
26260Sstevel@tonic-gate }
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate /*
26290Sstevel@tonic-gate  *
26300Sstevel@tonic-gate  * --- other routines
26310Sstevel@tonic-gate  *
26320Sstevel@tonic-gate  */
26330Sstevel@tonic-gate static boolean_t
scsa1394_is_my_child(dev_info_t * dip)26340Sstevel@tonic-gate scsa1394_is_my_child(dev_info_t *dip)
26350Sstevel@tonic-gate {
26360Sstevel@tonic-gate 	return ((dip != NULL) && (ddi_prop_exists(DDI_DEV_T_ANY, dip,
26370Sstevel@tonic-gate 	    DDI_PROP_DONTPASS, "scsa1394") == 1));
26380Sstevel@tonic-gate }
26390Sstevel@tonic-gate 
26400Sstevel@tonic-gate boolean_t
scsa1394_dev_is_online(scsa1394_state_t * sp)26410Sstevel@tonic-gate scsa1394_dev_is_online(scsa1394_state_t *sp)
26420Sstevel@tonic-gate {
26430Sstevel@tonic-gate 	boolean_t	ret;
26440Sstevel@tonic-gate 
26450Sstevel@tonic-gate 	mutex_enter(&sp->s_mutex);
26460Sstevel@tonic-gate 	ret = (sp->s_dev_state == SCSA1394_DEV_ONLINE);
26470Sstevel@tonic-gate 	mutex_exit(&sp->s_mutex);
26480Sstevel@tonic-gate 
26490Sstevel@tonic-gate 	return (ret);
26500Sstevel@tonic-gate }
26510Sstevel@tonic-gate 
26520Sstevel@tonic-gate static void *
scsa1394_kmem_realloc(void * old_buf,int old_size,int new_size,size_t elsize,int kf)26530Sstevel@tonic-gate scsa1394_kmem_realloc(void *old_buf, int old_size, int new_size, size_t elsize,
26540Sstevel@tonic-gate     int kf)
26550Sstevel@tonic-gate {
26560Sstevel@tonic-gate 	void	*new_buf;
26570Sstevel@tonic-gate 
26580Sstevel@tonic-gate 	new_buf = kmem_zalloc(new_size * elsize, kf);
26590Sstevel@tonic-gate 
26600Sstevel@tonic-gate 	if (old_size > 0) {
26610Sstevel@tonic-gate 		if (new_buf != NULL) {
26620Sstevel@tonic-gate 			bcopy(old_buf, new_buf, old_size * elsize);
26630Sstevel@tonic-gate 		}
26640Sstevel@tonic-gate 		kmem_free(old_buf, old_size * elsize);
26650Sstevel@tonic-gate 	}
26660Sstevel@tonic-gate 
26670Sstevel@tonic-gate 	return (new_buf);
26680Sstevel@tonic-gate }
2669