xref: /onnv-gate/usr/src/uts/common/io/1394/s1394_asynch.c (revision 2273:965cd64c1689)
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
5*2273Sap25164  * Common Development and Distribution License (the "License").
6*2273Sap25164  * 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 /*
22*2273Sap25164  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * s1394_asynch.c
300Sstevel@tonic-gate  *    1394 Services Layer Asynchronous Communications Routines
310Sstevel@tonic-gate  *    These routines handle all of the tasks relating to asynch commands
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <sys/conf.h>
350Sstevel@tonic-gate #include <sys/ddi.h>
360Sstevel@tonic-gate #include <sys/sunddi.h>
370Sstevel@tonic-gate #include <sys/cmn_err.h>
380Sstevel@tonic-gate #include <sys/types.h>
390Sstevel@tonic-gate #include <sys/kmem.h>
40*2273Sap25164 #include <sys/disp.h>
410Sstevel@tonic-gate #include <sys/tnf_probe.h>
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #include <sys/1394/t1394.h>
440Sstevel@tonic-gate #include <sys/1394/s1394.h>
450Sstevel@tonic-gate #include <sys/1394/h1394.h>
460Sstevel@tonic-gate #include <sys/1394/ieee1394.h>
470Sstevel@tonic-gate #include <sys/1394/ieee1212.h>
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static void s1394_handle_lock(cmd1394_cmd_t *cmd);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate static cmd1394_cmd_t *s1394_pending_q_remove(s1394_hal_t *hal);
520Sstevel@tonic-gate 
530Sstevel@tonic-gate static boolean_t s1394_process_pending_q(s1394_hal_t *hal);
540Sstevel@tonic-gate 
550Sstevel@tonic-gate static boolean_t s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd);
560Sstevel@tonic-gate 
570Sstevel@tonic-gate static int s1394_process_split_lock(cmd1394_cmd_t *cmd,
580Sstevel@tonic-gate     cmd1394_cmd_t *target_cmd);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate static int s1394_finish_split_lock(cmd1394_cmd_t *cmd,
610Sstevel@tonic-gate     cmd1394_cmd_t *target_cmd);
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate  * s1394_alloc_cmd()
650Sstevel@tonic-gate  *    is used to allocate a command for a target or for a HAL.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate int
s1394_alloc_cmd(s1394_hal_t * hal,uint_t flags,cmd1394_cmd_t ** cmdp)680Sstevel@tonic-gate s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp)
690Sstevel@tonic-gate {
700Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
710Sstevel@tonic-gate 	void		 *hal_overhead;
720Sstevel@tonic-gate 	uint_t		 cmd_size;
730Sstevel@tonic-gate 	int		 alloc_sleep;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_alloc_cmd_enter, S1394_TNF_SL_STACK, "");
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	alloc_sleep = (flags & T1394_ALLOC_CMD_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if ((alloc_sleep == KM_SLEEP) &&
80*2273Sap25164 	    (servicing_interrupt())) {
810Sstevel@tonic-gate 		TNF_PROBE_1(s1394_alloc_cmd_error, S1394_TNF_SL_ATREQ_ERROR,
820Sstevel@tonic-gate 		    "", tnf_string, msg, "Tried to sleep in intr context");
830Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
840Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
850Sstevel@tonic-gate 		ASSERT(alloc_sleep != KM_SLEEP);	/* fail */
860Sstevel@tonic-gate 		return (DDI_FAILURE);
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	/* either FCP command or response, but not both */
900Sstevel@tonic-gate 	if ((flags &
910Sstevel@tonic-gate 	    (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) ==
920Sstevel@tonic-gate 	    (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) {
930Sstevel@tonic-gate 		TNF_PROBE_1(s1394_alloc_cmd_error, S1394_TNF_SL_ATREQ_ERROR,
940Sstevel@tonic-gate 		    "", tnf_string, msg, "Both FCP cmd and resp flags");
950Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
960Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
970Sstevel@tonic-gate 		return (DDI_FAILURE);
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	*cmdp = kmem_cache_alloc(hal->hal_kmem_cachep, alloc_sleep);
1010Sstevel@tonic-gate 	if (*cmdp == NULL) {
1020Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
1030Sstevel@tonic-gate 		    S1394_TNF_SL_STACK, "");
1040Sstevel@tonic-gate 		return (DDI_FAILURE);
1050Sstevel@tonic-gate 	}
1060Sstevel@tonic-gate 	cmd_size = sizeof (cmd1394_cmd_t) +
1070Sstevel@tonic-gate 	    sizeof (s1394_cmd_priv_t) + hal->halinfo.hal_overhead;
1080Sstevel@tonic-gate 	bzero((void *)*cmdp, cmd_size);
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	(*cmdp)->cmd_version = T1394_VERSION_V1;
1110Sstevel@tonic-gate 	(*cmdp)->cmd_result = CMD1394_NOSTATUS;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	/* Get the Services Layer private area */
1140Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	/* Set extension type */
1170Sstevel@tonic-gate 	if (flags & T1394_ALLOC_CMD_FCP_COMMAND) {
1180Sstevel@tonic-gate 		s1394_fa_init_cmd(s_priv, S1394_FA_TYPE_FCP_CTL);
1190Sstevel@tonic-gate 	} else if (flags & T1394_ALLOC_CMD_FCP_RESPONSE) {
1200Sstevel@tonic-gate 		s1394_fa_init_cmd(s_priv, S1394_FA_TYPE_FCP_TGT);
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	/* Set up the hal_overhead ptr in the hal_cmd_private */
1240Sstevel@tonic-gate 	hal_overhead = (uchar_t *)s_priv + sizeof (s1394_cmd_priv_t);
1250Sstevel@tonic-gate 	s_priv->hal_cmd_private.hal_overhead = (void *)hal_overhead;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_alloc_cmd, S1394_TNF_SL_STACK, "",
1280Sstevel@tonic-gate 	    tnf_opaque, cmd, *cmdp);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	/* kstats - number of cmd allocs */
1310Sstevel@tonic-gate 	hal->hal_kstats->cmd_alloc++;
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit, S1394_TNF_SL_STACK, "");
1340Sstevel@tonic-gate 	return (DDI_SUCCESS);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate /*
1380Sstevel@tonic-gate  * s1394_free_cmd()
1390Sstevel@tonic-gate  *    is used to free a command that had been previously allocated by
1400Sstevel@tonic-gate  *    s1394_alloc_cmd().
1410Sstevel@tonic-gate  */
1420Sstevel@tonic-gate int
s1394_free_cmd(s1394_hal_t * hal,cmd1394_cmd_t ** cmdp)1430Sstevel@tonic-gate s1394_free_cmd(s1394_hal_t *hal, cmd1394_cmd_t **cmdp)
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_free_cmd_enter, S1394_TNF_SL_STACK, "");
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/* Get the Services Layer private area */
1500Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	/* Check that command isn't in use */
1530Sstevel@tonic-gate 	if (s_priv->cmd_in_use == B_TRUE) {
1540Sstevel@tonic-gate 		TNF_PROBE_1(s1394_free_cmd_error, S1394_TNF_SL_ERROR, "",
1550Sstevel@tonic-gate 		    tnf_string, msg,  "Attempted to free an in-use command");
1560Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_free_cmd_exit, S1394_TNF_SL_STACK, "");
1570Sstevel@tonic-gate 		ASSERT(s_priv->cmd_in_use == B_FALSE);
1580Sstevel@tonic-gate 		return (DDI_FAILURE);
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_free_cmd, S1394_TNF_SL_STACK, "",
1610Sstevel@tonic-gate 	    tnf_opaque, cmd, *cmdp);
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	/* kstats - number of cmd allocs */
1640Sstevel@tonic-gate 	kmem_cache_free(hal->hal_kmem_cachep, *cmdp);
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	/* Command pointer is set to NULL before returning */
1670Sstevel@tonic-gate 	*cmdp = NULL;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/* kstats - number of cmd frees */
1700Sstevel@tonic-gate 	hal->hal_kstats->cmd_free++;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_free_cmd_exit, S1394_TNF_SL_STACK, "");
1730Sstevel@tonic-gate 	return (DDI_SUCCESS);
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate /*
1770Sstevel@tonic-gate  * s1394_xfer_asynch_command()
1780Sstevel@tonic-gate  *    is used to send an asynch command down to the HAL.  Based upon the type
1790Sstevel@tonic-gate  *    of command that is being sent, the appropriate HAL function is called.
1800Sstevel@tonic-gate  *    Command failures are handled be returning an error and/or shutting down
1810Sstevel@tonic-gate  *    the HAL, depending on the severity of the error.
1820Sstevel@tonic-gate  */
1830Sstevel@tonic-gate int
s1394_xfer_asynch_command(s1394_hal_t * hal,cmd1394_cmd_t * cmd,int * err)1840Sstevel@tonic-gate s1394_xfer_asynch_command(s1394_hal_t *hal, cmd1394_cmd_t *cmd, int *err)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	s1394_cmd_priv_t  *s_priv;
1870Sstevel@tonic-gate 	h1394_cmd_priv_t  *h_priv;
1880Sstevel@tonic-gate 	s1394_hal_state_t state;
1890Sstevel@tonic-gate 	dev_info_t	  *dip;
1900Sstevel@tonic-gate 	int		  result_from_hal;
1910Sstevel@tonic-gate 	int		  ret;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_enter,
1940Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
1990Sstevel@tonic-gate 	state = hal->hal_state;
2000Sstevel@tonic-gate 	if (((state != S1394_HAL_NORMAL) && (state != S1394_HAL_RESET)) ||
2010Sstevel@tonic-gate 	    (hal->disable_requests_bit == 1)) {
2020Sstevel@tonic-gate 		*err = s1394_HAL_asynch_error(hal, cmd, state);
2030Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
2040Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
2050Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
2060Sstevel@tonic-gate 		return (DDI_FAILURE);
2070Sstevel@tonic-gate 	}
2080Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	/* Get the Services Layer private area */
2110Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
2140Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	/* kstats - number of AT requests sent */
2170Sstevel@tonic-gate 	switch (cmd->cmd_type) {
2180Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_QUAD:
2190Sstevel@tonic-gate 		hal->hal_kstats->atreq_quad_rd++;
2200Sstevel@tonic-gate 		break;
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_BLOCK:
2230Sstevel@tonic-gate 		hal->hal_kstats->atreq_blk_rd++;
2240Sstevel@tonic-gate 		break;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_QUAD:
2270Sstevel@tonic-gate 		hal->hal_kstats->atreq_quad_wr++;
2280Sstevel@tonic-gate 		break;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_BLOCK:
2310Sstevel@tonic-gate 		hal->hal_kstats->atreq_blk_wr++;
2320Sstevel@tonic-gate 		hal->hal_kstats->atreq_blk_wr_size += h_priv->mblk.length;
2330Sstevel@tonic-gate 		break;
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_32:
2360Sstevel@tonic-gate 		hal->hal_kstats->atreq_lock32++;
2370Sstevel@tonic-gate 		break;
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_64:
2400Sstevel@tonic-gate 		hal->hal_kstats->atreq_lock64++;
2410Sstevel@tonic-gate 		break;
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	switch (s_priv->cmd_priv_xfer_type) {
2450Sstevel@tonic-gate 	/* Call the HAL's read entry point */
2460Sstevel@tonic-gate 	case S1394_CMD_READ:
2470Sstevel@tonic-gate 		ret = HAL_CALL(hal).read(hal->halinfo.hal_private,
2480Sstevel@tonic-gate 		    (cmd1394_cmd_t *)cmd,
2490Sstevel@tonic-gate 		    (h1394_cmd_priv_t *)&s_priv->hal_cmd_private,
2500Sstevel@tonic-gate 		    &result_from_hal);
2510Sstevel@tonic-gate 		break;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	/* Call the HAL's write entry point */
2540Sstevel@tonic-gate 	case S1394_CMD_WRITE:
2550Sstevel@tonic-gate 		ret = HAL_CALL(hal).write(hal->halinfo.hal_private,
2560Sstevel@tonic-gate 		    (cmd1394_cmd_t *)cmd,
2570Sstevel@tonic-gate 		    (h1394_cmd_priv_t *)&s_priv->hal_cmd_private,
2580Sstevel@tonic-gate 		    &result_from_hal);
2590Sstevel@tonic-gate 		break;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	/* Call the HAL's lock entry point */
2620Sstevel@tonic-gate 	case S1394_CMD_LOCK:
2630Sstevel@tonic-gate 		ret = HAL_CALL(hal).lock(hal->halinfo.hal_private,
2640Sstevel@tonic-gate 		    (cmd1394_cmd_t *)cmd,
2650Sstevel@tonic-gate 		    (h1394_cmd_priv_t *)&s_priv->hal_cmd_private,
2660Sstevel@tonic-gate 		    &result_from_hal);
2670Sstevel@tonic-gate 		break;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	default:
2700Sstevel@tonic-gate 		*err = CMD1394_EUNKNOWN_ERROR;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 		TNF_PROBE_1(s1394_xfer_asynch_command_error,
2730Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg,
2740Sstevel@tonic-gate 		    "Invalid command type specified");
2750Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
2760Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
2770Sstevel@tonic-gate 		return (DDI_FAILURE);
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_return_from_HAL,
2810Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	if (ret == DDI_FAILURE) {
2840Sstevel@tonic-gate 		switch (result_from_hal) {
2850Sstevel@tonic-gate 		case H1394_STATUS_EMPTY_TLABEL:
2860Sstevel@tonic-gate 			/* Out of TLABELs - Unable to send AT req */
2870Sstevel@tonic-gate 			*err = CMD1394_ENO_ATREQ;
2880Sstevel@tonic-gate 			break;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 		case H1394_STATUS_INVALID_BUSGEN:
2910Sstevel@tonic-gate 			/* Out of TLABELs - Unable to send AT req */
2920Sstevel@tonic-gate 			*err = CMD1394_ESTALE_GENERATION;
2930Sstevel@tonic-gate 			break;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		case H1394_STATUS_NOMORE_SPACE:
2960Sstevel@tonic-gate 			/* No more space on HAL's HW queue */
2970Sstevel@tonic-gate 			*err = CMD1394_ENO_ATREQ;
2980Sstevel@tonic-gate 			break;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 		case H1394_STATUS_INTERNAL_ERROR:
3010Sstevel@tonic-gate 			dip = hal->halinfo.dip;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 			/* An unexpected error in the HAL */
3040Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
3050Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 			/* Disable the HAL */
3080Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 			*err = CMD1394_EFATAL_ERROR;
3110Sstevel@tonic-gate 			break;
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 		default:
3140Sstevel@tonic-gate 			dip = hal->halinfo.dip;
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 			/* An unexpected error in the HAL */
3170Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
3180Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 			/* Disable the HAL */
3210Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 			*err = CMD1394_EFATAL_ERROR;
3240Sstevel@tonic-gate 			break;
3250Sstevel@tonic-gate 		}
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 		TNF_PROBE_2_DEBUG(s1394_xfer_asynch_command_exit,
3280Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "",
3290Sstevel@tonic-gate 		    tnf_int, result_from_hal, result_from_hal,
3300Sstevel@tonic-gate 		    tnf_int, err, *err);
3310Sstevel@tonic-gate 		return (DDI_FAILURE);
3320Sstevel@tonic-gate 	}
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/* No errors, return success */
3350Sstevel@tonic-gate 	*err = CMD1394_NOSTATUS;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
3380Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
3390Sstevel@tonic-gate 	return (DDI_SUCCESS);
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate /*
3430Sstevel@tonic-gate  * s1394_setup_asynch_command()
3440Sstevel@tonic-gate  *    is used to setup an asynch command to be sent down to the HAL and out
3450Sstevel@tonic-gate  *    onto the bus.  This function handles setting up the destination address
3460Sstevel@tonic-gate  *    (if necessary), speed, max_payload, putting the command onto the
3470Sstevel@tonic-gate  *    outstanding Q list, and any other things that must be done prior to
3480Sstevel@tonic-gate  *    calling the HAL.
3490Sstevel@tonic-gate  */
3500Sstevel@tonic-gate int
s1394_setup_asynch_command(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd,uint32_t xfer_type,int * err)3510Sstevel@tonic-gate s1394_setup_asynch_command(s1394_hal_t *hal, s1394_target_t *target,
3520Sstevel@tonic-gate     cmd1394_cmd_t *cmd, uint32_t xfer_type, int *err)
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate 	s1394_cmd_priv_t  *s_priv;
3550Sstevel@tonic-gate 	h1394_cmd_priv_t  *h_priv;
3560Sstevel@tonic-gate 	uint64_t	  node;
3570Sstevel@tonic-gate 	uint32_t	  from_node;
3580Sstevel@tonic-gate 	uint32_t	  to_node;
3590Sstevel@tonic-gate 	uint32_t	  bus_capabilities;
3600Sstevel@tonic-gate 	uint_t		  current_max_payload;
3610Sstevel@tonic-gate 	uint_t		  max_rec;
3620Sstevel@tonic-gate 	uint_t		  max_blk;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_enter,
3650Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	switch (cmd->cmd_type) {
3700Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_QUAD:
3710Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_QUAD:
3720Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_BLOCK:
3730Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_BLOCK:
3740Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_32:
3750Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_64:
3760Sstevel@tonic-gate 		break;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	default:
3790Sstevel@tonic-gate 		*err = CMD1394_EINVALID_COMMAND;
3800Sstevel@tonic-gate 		TNF_PROBE_1(s1394_setup_asynch_command_error,
3810Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg,
3820Sstevel@tonic-gate 		    "Invalid command type specified");
3830Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
3840Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
3850Sstevel@tonic-gate 		return (DDI_FAILURE);
3860Sstevel@tonic-gate 	}
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	/* Check for potential address roll-over */
3890Sstevel@tonic-gate 	if (s1394_address_rollover(cmd) != B_FALSE) {
3900Sstevel@tonic-gate 		*err = CMD1394_EADDRESS_ERROR;
3910Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
3920Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
3930Sstevel@tonic-gate 		return (DDI_FAILURE);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	/* Get the Services Layer private area */
3970Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	/* Set up who sent command on which hal */
4000Sstevel@tonic-gate 	s_priv->sent_by_target	= (s1394_target_t *)target;
4010Sstevel@tonic-gate 	s_priv->sent_on_hal	= (s1394_hal_t *)hal;
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	/* Set up command transfer type */
4040Sstevel@tonic-gate 	s_priv->cmd_priv_xfer_type = xfer_type;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) {
4070Sstevel@tonic-gate 		/* Compare the current generation from the HAL struct */
4080Sstevel@tonic-gate 		/* to the one given by the target */
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 		/* Speed is to be filled in from speed map */
4110Sstevel@tonic-gate 		from_node = IEEE1394_NODE_NUM(hal->node_id);
4120Sstevel@tonic-gate 		to_node	  = IEEE1394_ADDR_PHY_ID(cmd->cmd_addr);
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 		if (cmd->bus_generation != hal->generation_count) {
4150Sstevel@tonic-gate 			*err = CMD1394_ESTALE_GENERATION;
4160Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4170Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4180Sstevel@tonic-gate 			return (DDI_FAILURE);
4190Sstevel@tonic-gate 		}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	} else {
4220Sstevel@tonic-gate 		/* Set the generation */
4230Sstevel@tonic-gate 		cmd->bus_generation = hal->generation_count;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 		/* If not OVERRIDE_ADDR, then target may not be NULL */
4260Sstevel@tonic-gate 		ASSERT(target != NULL);
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 		rw_enter(&hal->target_list_rwlock, RW_READER);
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 		if ((target->target_state & S1394_TARG_GONE) != 0 ||
4310Sstevel@tonic-gate 		    target->on_node == NULL) {
4320Sstevel@tonic-gate 			rw_exit(&hal->target_list_rwlock);
4330Sstevel@tonic-gate 			*err = CMD1394_EDEVICE_REMOVED;
4340Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4350Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4360Sstevel@tonic-gate 			return (DDI_FAILURE);
4370Sstevel@tonic-gate 		}
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 		ASSERT((target->target_state & S1394_TARG_GONE) == 0);
4400Sstevel@tonic-gate 		node = target->on_node->node_num;
4410Sstevel@tonic-gate 		rw_exit(&hal->target_list_rwlock);
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 		/* Mask in the top 16-bits */
4440Sstevel@tonic-gate 		cmd->cmd_addr = (cmd->cmd_addr & IEEE1394_ADDR_OFFSET_MASK);
4450Sstevel@tonic-gate 		cmd->cmd_addr = (cmd->cmd_addr |
4460Sstevel@tonic-gate 		    (node << IEEE1394_ADDR_PHY_ID_SHIFT));
4470Sstevel@tonic-gate 		cmd->cmd_addr = (cmd->cmd_addr | IEEE1394_ADDR_BUS_ID_MASK);
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 		/* Speed is to be filled in from speed map */
4500Sstevel@tonic-gate 		from_node = IEEE1394_NODE_NUM(hal->node_id);
4510Sstevel@tonic-gate 		to_node = (uint32_t)node;
4520Sstevel@tonic-gate 	}
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
4550Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	/* Copy the generation into the HAL's private field */
4580Sstevel@tonic-gate 	h_priv->bus_generation = cmd->bus_generation;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	/* Fill in the nodeID */
4610Sstevel@tonic-gate 	cmd->nodeID = (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >>
4620Sstevel@tonic-gate 	    IEEE1394_ADDR_NODE_ID_SHIFT;
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 	if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) {
4650Sstevel@tonic-gate 		if (cmd->cmd_speed > IEEE1394_S400) {
4660Sstevel@tonic-gate 			*err = CMD1394_EINVALID_COMMAND;
4670Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4680Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4690Sstevel@tonic-gate 			return (DDI_FAILURE);
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 		} else {
4720Sstevel@tonic-gate 			s_priv->hal_cmd_private.speed = (int)cmd->cmd_speed;
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	} else {
4760Sstevel@tonic-gate 		/* Speed is to be filled in from speed map */
4770Sstevel@tonic-gate 		s_priv->hal_cmd_private.speed = (int)s1394_speed_map_get(hal,
4780Sstevel@tonic-gate 		    from_node, to_node);
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	/* Is it a block request? */
4820Sstevel@tonic-gate 	if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
4830Sstevel@tonic-gate 	    (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 		if (cmd->cmd_u.b.data_block == NULL) {
4860Sstevel@tonic-gate 			*err = CMD1394_ENULL_MBLK;
4870Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4880Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4890Sstevel@tonic-gate 			return (DDI_FAILURE);
4900Sstevel@tonic-gate 		}
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 		/* Also need to check for MBLK_TOO_SMALL */
4930Sstevel@tonic-gate 		if (s1394_mblk_too_small(cmd) != B_FALSE) {
4940Sstevel@tonic-gate 			*err = CMD1394_EMBLK_TOO_SMALL;
4950Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4960Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4970Sstevel@tonic-gate 			return (DDI_FAILURE);
4980Sstevel@tonic-gate 		}
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 		/* Initialize bytes_transferred to zero */
5010Sstevel@tonic-gate 		cmd->cmd_u.b.bytes_transferred = 0;
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 		/* Handle the MAX_PAYLOAD size */
5040Sstevel@tonic-gate 		if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) {
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 			current_max_payload = 512 <<
5070Sstevel@tonic-gate 			    (s_priv->hal_cmd_private.speed);
5080Sstevel@tonic-gate 			if (hal->topology_tree[to_node].cfgrom) {
5090Sstevel@tonic-gate 				bus_capabilities =
5100Sstevel@tonic-gate 				    hal->topology_tree[to_node].cfgrom[
5110Sstevel@tonic-gate 					IEEE1212_NODE_CAP_QUAD];
5120Sstevel@tonic-gate 				max_rec = (bus_capabilities &
5130Sstevel@tonic-gate 				    IEEE1394_BIB_MAXREC_MASK) >>
5140Sstevel@tonic-gate 				    IEEE1394_BIB_MAXREC_SHIFT;
5150Sstevel@tonic-gate 			} else {
5160Sstevel@tonic-gate 				max_rec = 0;
5170Sstevel@tonic-gate 			}
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 			if ((max_rec > 0) && (max_rec < 14)) {
5200Sstevel@tonic-gate 				max_blk = 1 << (max_rec + 1);
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 			} else {
5230Sstevel@tonic-gate 				/* These are either unspecified or reserved */
5240Sstevel@tonic-gate 				max_blk = 4;
5250Sstevel@tonic-gate 			}
5260Sstevel@tonic-gate 			if (max_blk < current_max_payload)
5270Sstevel@tonic-gate 				current_max_payload = max_blk;
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 		} else {
5300Sstevel@tonic-gate 			rw_enter(&hal->target_list_rwlock, RW_READER);
5310Sstevel@tonic-gate 			current_max_payload = target->current_max_payload;
5320Sstevel@tonic-gate 			rw_exit(&hal->target_list_rwlock);
5330Sstevel@tonic-gate 		}
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 		if (cmd->cmd_options & CMD1394_OVERRIDE_MAX_PAYLOAD) {
5360Sstevel@tonic-gate 			if (current_max_payload > cmd->cmd_u.b.max_payload)
5370Sstevel@tonic-gate 				current_max_payload = cmd->cmd_u.b.max_payload;
5380Sstevel@tonic-gate 		}
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 		h_priv->mblk.curr_mblk = cmd->cmd_u.b.data_block;
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK) {
5430Sstevel@tonic-gate 			h_priv->mblk.curr_offset =
5440Sstevel@tonic-gate 			    cmd->cmd_u.b.data_block->b_rptr;
5450Sstevel@tonic-gate 		} else {
5460Sstevel@tonic-gate 			h_priv->mblk.curr_offset =
5470Sstevel@tonic-gate 			    cmd->cmd_u.b.data_block->b_wptr;
5480Sstevel@tonic-gate 		}
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 		if (cmd->cmd_u.b.blk_length > current_max_payload) {
5510Sstevel@tonic-gate 			h_priv->mblk.length = current_max_payload;
5520Sstevel@tonic-gate 			s_priv->data_remaining = cmd->cmd_u.b.blk_length;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 		} else {
5550Sstevel@tonic-gate 			h_priv->mblk.length = cmd->cmd_u.b.blk_length;
5560Sstevel@tonic-gate 			s_priv->data_remaining = cmd->cmd_u.b.blk_length;
5570Sstevel@tonic-gate 		}
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	/* Mark command as being used */
5610Sstevel@tonic-gate 	s_priv->cmd_in_use = B_TRUE;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	/* Put command on the HAL's outstanding request Q */
5640Sstevel@tonic-gate 	s1394_insert_q_asynch_cmd(hal, cmd);
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
5670Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
5680Sstevel@tonic-gate 	return (DDI_SUCCESS);
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate /*
5720Sstevel@tonic-gate  * s1394_insert_q_asynch_cmd()
5730Sstevel@tonic-gate  *    is used to insert a given command structure onto a HAL's outstanding
5740Sstevel@tonic-gate  *    asynch queue.
5750Sstevel@tonic-gate  */
5760Sstevel@tonic-gate void
s1394_insert_q_asynch_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)5770Sstevel@tonic-gate s1394_insert_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
5780Sstevel@tonic-gate {
5790Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
5800Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
5810Sstevel@tonic-gate 	cmd1394_cmd_t	 *temp_cmd;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_enter,
5840Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	mutex_enter(&hal->outstanding_q_mutex);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	/* Get the Services Layer private area */
5890Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	/* Is the outstanding request queue empty? */
5920Sstevel@tonic-gate 	if ((hal->outstanding_q_head == NULL) &&
5930Sstevel@tonic-gate 	    (hal->outstanding_q_tail == NULL)) {
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 		hal->outstanding_q_head = (cmd1394_cmd_t *)cmd;
5960Sstevel@tonic-gate 		hal->outstanding_q_tail = (cmd1394_cmd_t *)cmd;
5970Sstevel@tonic-gate 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
5980Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	} else {
6010Sstevel@tonic-gate 		s_priv->cmd_priv_next = hal->outstanding_q_head;
6020Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 		temp_cmd = (cmd1394_cmd_t *)hal->outstanding_q_head;
6050Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd +
6060Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
6070Sstevel@tonic-gate 		c_priv->cmd_priv_prev = (cmd1394_cmd_t *)cmd;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 		hal->outstanding_q_head = (cmd1394_cmd_t *)cmd;
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	mutex_exit(&hal->outstanding_q_mutex);
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_exit,
6150Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6160Sstevel@tonic-gate }
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate /*
6190Sstevel@tonic-gate  * s1394_remove_q_asynch_cmd()
6200Sstevel@tonic-gate  *    is used to remove a given command structure from a HAL's outstanding
6210Sstevel@tonic-gate  *    asynch queue.
6220Sstevel@tonic-gate  */
6230Sstevel@tonic-gate void
s1394_remove_q_asynch_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)6240Sstevel@tonic-gate s1394_remove_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
6250Sstevel@tonic-gate {
6260Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
6270Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
6280Sstevel@tonic-gate 	cmd1394_cmd_t	 *prev_cmd;
6290Sstevel@tonic-gate 	cmd1394_cmd_t	 *next_cmd;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_enter,
6320Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	mutex_enter(&hal->outstanding_q_mutex);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	/* Get the Services Layer private area */
6370Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev;
6400Sstevel@tonic-gate 	next_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_next;
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
6430Sstevel@tonic-gate 	s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	if (prev_cmd != NULL) {
6460Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)prev_cmd +
6470Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
6480Sstevel@tonic-gate 		c_priv->cmd_priv_next = (cmd1394_cmd_t *)next_cmd;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	} else {
6510Sstevel@tonic-gate 		if (hal->outstanding_q_head == (cmd1394_cmd_t *)cmd)
6520Sstevel@tonic-gate 			hal->outstanding_q_head = (cmd1394_cmd_t *)next_cmd;
6530Sstevel@tonic-gate 	}
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	if (next_cmd != NULL) {
6560Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)next_cmd +
6570Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
6580Sstevel@tonic-gate 		c_priv->cmd_priv_prev = (cmd1394_cmd_t *)prev_cmd;
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	} else {
6610Sstevel@tonic-gate 		if (hal->outstanding_q_tail == (cmd1394_cmd_t *)cmd)
6620Sstevel@tonic-gate 			hal->outstanding_q_tail = (cmd1394_cmd_t *)prev_cmd;
6630Sstevel@tonic-gate 	}
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 	mutex_exit(&hal->outstanding_q_mutex);
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_exit,
6680Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate  * s1394_atreq_cmd_complete()
6730Sstevel@tonic-gate  *    is called by h1394_cmd_is_complete() when an AT request has completed.
6740Sstevel@tonic-gate  *    Based upon a command's completion status, s1394_atreq_cmd_complete()
6750Sstevel@tonic-gate  *    determines whether to call the target (or unblock), put the command onto
6760Sstevel@tonic-gate  *    the pending Q to be sent out later, or to resend the command
6770Sstevel@tonic-gate  *    (multi-part command).
6780Sstevel@tonic-gate  */
6790Sstevel@tonic-gate void
s1394_atreq_cmd_complete(s1394_hal_t * hal,cmd1394_cmd_t * req,int status)6800Sstevel@tonic-gate s1394_atreq_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *req, int status)
6810Sstevel@tonic-gate {
6820Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
6830Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
6840Sstevel@tonic-gate 	dev_info_t	 *dip;
6850Sstevel@tonic-gate 	int		 ret;
6860Sstevel@tonic-gate 	int		 cmd_result;
6870Sstevel@tonic-gate 	int		 err;
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_enter,
6900Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	/* Get the Services Layer private area */
6930Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(req);
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	/* If not an ack_complete... */
6960Sstevel@tonic-gate 	if (status != H1394_CMD_SUCCESS) {
6970Sstevel@tonic-gate 		/* kstats - number of failure AT responses */
6980Sstevel@tonic-gate 		switch (req->cmd_type) {
6990Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_QUAD:
7000Sstevel@tonic-gate 			hal->hal_kstats->atresp_quad_rd_fail++;
7010Sstevel@tonic-gate 			break;
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_BLOCK:
7040Sstevel@tonic-gate 			hal->hal_kstats->atresp_blk_rd_fail++;
7050Sstevel@tonic-gate 			break;
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_QUAD:
7080Sstevel@tonic-gate 			hal->hal_kstats->atresp_quad_wr_fail++;
7090Sstevel@tonic-gate 			break;
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_BLOCK:
7120Sstevel@tonic-gate 			hal->hal_kstats->atresp_blk_wr_fail++;
7130Sstevel@tonic-gate 			break;
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_32:
7160Sstevel@tonic-gate 			hal->hal_kstats->atresp_lock32_fail++;
7170Sstevel@tonic-gate 			break;
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_64:
7200Sstevel@tonic-gate 			hal->hal_kstats->atresp_lock64_fail++;
7210Sstevel@tonic-gate 			break;
7220Sstevel@tonic-gate 		}
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 		switch (status) {
7260Sstevel@tonic-gate 		/* evt_missing_ack */
7270Sstevel@tonic-gate 		case H1394_CMD_ETIMEOUT:
7280Sstevel@tonic-gate 			cmd_result = CMD1394_ETIMEOUT;
7290Sstevel@tonic-gate 			break;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 		/* evt_flushed */
7320Sstevel@tonic-gate 		case H1394_CMD_EBUSRESET:
7330Sstevel@tonic-gate 			/* Move request to pending Q if cancel on */
7340Sstevel@tonic-gate 			/* reset is not set */
7350Sstevel@tonic-gate 			if (req->cmd_options & CMD1394_CANCEL_ON_BUS_RESET) {
7360Sstevel@tonic-gate 				cmd_result = CMD1394_EBUSRESET;
7370Sstevel@tonic-gate 				break;
7380Sstevel@tonic-gate 			}
7390Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, req);
7400Sstevel@tonic-gate 			s1394_pending_q_insert(hal, req, S1394_PENDING_Q_REAR);
7410Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
7420Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
7430Sstevel@tonic-gate 			return;
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 		/* ack_busy_X */
7460Sstevel@tonic-gate 		/* ack_busy_A */
7470Sstevel@tonic-gate 		/* ack_busy_B */
7480Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_BUSY:
7490Sstevel@tonic-gate 			cmd_result = CMD1394_EDEVICE_BUSY;
7500Sstevel@tonic-gate 			break;
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 		/* ack_data_error */
7530Sstevel@tonic-gate 		case H1394_CMD_EDATA_ERROR:
7540Sstevel@tonic-gate 			cmd_result = CMD1394_EDATA_ERROR;
7550Sstevel@tonic-gate 			break;
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 		/* ack_type_error */
7580Sstevel@tonic-gate 		case H1394_CMD_ETYPE_ERROR:
7590Sstevel@tonic-gate 			cmd_result = CMD1394_ETYPE_ERROR;
7600Sstevel@tonic-gate 			break;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 		/* resp_address_error */
7630Sstevel@tonic-gate 		/* ack_address_error */
7640Sstevel@tonic-gate 		case H1394_CMD_EADDR_ERROR:
7650Sstevel@tonic-gate 			cmd_result = CMD1394_EADDRESS_ERROR;
7660Sstevel@tonic-gate 			break;
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 		/* resp_conflict_error */
7690Sstevel@tonic-gate 		/* ack_conflict_error */
7700Sstevel@tonic-gate 		case H1394_CMD_ERSRC_CONFLICT:
7710Sstevel@tonic-gate 			cmd_result = CMD1394_ERSRC_CONFLICT;
7720Sstevel@tonic-gate 			break;
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 		/* ack_tardy */
7750Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_POWERUP:
7760Sstevel@tonic-gate 			cmd_result = CMD1394_EDEVICE_BUSY;
7770Sstevel@tonic-gate 			break;
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 		/* device errors (bad tcodes, ACKs, etc...) */
7800Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_ERROR:
7810Sstevel@tonic-gate 			cmd_result = CMD1394_EDEVICE_ERROR;
7820Sstevel@tonic-gate 			break;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 		/* Unknown error type */
7850Sstevel@tonic-gate 		case H1394_CMD_EUNKNOWN_ERROR:
7860Sstevel@tonic-gate 			cmd_result = CMD1394_EUNKNOWN_ERROR;
7870Sstevel@tonic-gate 			break;
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 		/* Unrecognized error */
7900Sstevel@tonic-gate 		default:
7910Sstevel@tonic-gate 			dip = hal->halinfo.dip;
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 			/* An unexpected error in the HAL */
7940Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
7950Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 			/* Disable the HAL */
7980Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 			TNF_PROBE_2(s1394_atreq_cmd_complete_error,
8010Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg,
8020Sstevel@tonic-gate 			    "Unrecognized cmd status code",
8030Sstevel@tonic-gate 			    tnf_int, status, status);
8040Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8050Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
8060Sstevel@tonic-gate 			return;
8070Sstevel@tonic-gate 		}
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 		/* Remove command from the HAL's outstanding request Q */
8100Sstevel@tonic-gate 		s1394_remove_q_asynch_cmd(hal, req);
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 		s_priv->cmd_in_use = B_FALSE;
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 		req->cmd_result = cmd_result;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 		/* Is this a blocking command? */
8170Sstevel@tonic-gate 		if (req->cmd_options & CMD1394_BLOCKING) {
8180Sstevel@tonic-gate 			/* Unblock the waiting command */
8190Sstevel@tonic-gate 			mutex_enter(&s_priv->blocking_mutex);
8200Sstevel@tonic-gate 			s_priv->blocking_flag = B_TRUE;
8210Sstevel@tonic-gate 			cv_signal(&s_priv->blocking_cv);
8220Sstevel@tonic-gate 			mutex_exit(&s_priv->blocking_mutex);
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8250Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
8260Sstevel@tonic-gate 			return;
8270Sstevel@tonic-gate 		}
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 		/* Call the target's completion_callback() */
8300Sstevel@tonic-gate 		if (req->completion_callback != NULL) {
8310Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback,
8320Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
8330Sstevel@tonic-gate 			req->completion_callback(req);
8340Sstevel@tonic-gate 		}
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8370Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
8380Sstevel@tonic-gate 		return;
8390Sstevel@tonic-gate 	}
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	/* Successful unless otherwise modified */
8420Sstevel@tonic-gate 	err = CMD1394_CMDSUCCESS;
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	if ((req->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
8450Sstevel@tonic-gate 	    (req->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 		/* Get a pointer to the HAL private struct */
8480Sstevel@tonic-gate 		h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 		/* Update data_remaining */
8510Sstevel@tonic-gate 		s_priv->data_remaining -= h_priv->mblk.length;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 		/* Increment bytes_transferred */
8540Sstevel@tonic-gate 		req->cmd_u.b.bytes_transferred += h_priv->mblk.length;
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 		if (req->cmd_type == CMD1394_ASYNCH_RD_BLOCK)
8570Sstevel@tonic-gate 			hal->hal_kstats->atreq_blk_rd_size +=
8580Sstevel@tonic-gate 			    h_priv->mblk.length;
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 		/* Is there still more to send? */
8610Sstevel@tonic-gate 		if (s_priv->data_remaining > 0) {
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 			/* Setup the new mblk and offset */
8640Sstevel@tonic-gate 			h_priv->mblk.curr_mblk = h_priv->mblk.next_mblk;
8650Sstevel@tonic-gate 			h_priv->mblk.curr_offset = h_priv->mblk.next_offset;
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate 			/* Update destination address */
8680Sstevel@tonic-gate 			if (!(req->cmd_options &
8690Sstevel@tonic-gate 			    CMD1394_DISABLE_ADDR_INCREMENT)) {
8700Sstevel@tonic-gate 				req->cmd_addr += h_priv->mblk.length;
8710Sstevel@tonic-gate 			}
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 			/*
8740Sstevel@tonic-gate 			 * Use the current MAX_PAYLOAD size.  This value
8750Sstevel@tonic-gate 			 * doesn't need to be recalculated because we must
8760Sstevel@tonic-gate 			 * be in the same generation on the bus, else we
8770Sstevel@tonic-gate 			 * would have seen a bus reset error.
8780Sstevel@tonic-gate 			 */
8790Sstevel@tonic-gate 			if (s_priv->data_remaining < h_priv->mblk.length) {
8800Sstevel@tonic-gate 				h_priv->mblk.length = s_priv->data_remaining;
8810Sstevel@tonic-gate 			}
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate 			/* Send command out again */
8840Sstevel@tonic-gate 			ret = s1394_xfer_asynch_command(hal, req, &err);
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 			if (ret == DDI_SUCCESS) {
8870Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8880Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
8890Sstevel@tonic-gate 				return;
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 			} else if (err == CMD1394_ESTALE_GENERATION) {
8920Sstevel@tonic-gate 				/* Remove cmd from outstanding request Q */
8930Sstevel@tonic-gate 				s1394_remove_q_asynch_cmd(hal, req);
8940Sstevel@tonic-gate 				s1394_pending_q_insert(hal, req,
8950Sstevel@tonic-gate 				    S1394_PENDING_Q_REAR);
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8980Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
8990Sstevel@tonic-gate 				return;
9000Sstevel@tonic-gate 			}
9010Sstevel@tonic-gate 		}
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	/* Remove command from the HAL's outstanding request Q */
9050Sstevel@tonic-gate 	s1394_remove_q_asynch_cmd(hal, req);
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	s_priv->cmd_in_use = B_FALSE;
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 	/* Set status */
9100Sstevel@tonic-gate 	req->cmd_result = err;
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	/* Is this a blocking command? */
9130Sstevel@tonic-gate 	if (req->cmd_options & CMD1394_BLOCKING) {
9140Sstevel@tonic-gate 		/* Unblock the waiting command */
9150Sstevel@tonic-gate 		mutex_enter(&s_priv->blocking_mutex);
9160Sstevel@tonic-gate 		s_priv->blocking_flag = B_TRUE;
9170Sstevel@tonic-gate 		cv_signal(&s_priv->blocking_cv);
9180Sstevel@tonic-gate 		mutex_exit(&s_priv->blocking_mutex);
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
9210Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
9220Sstevel@tonic-gate 		return;
9230Sstevel@tonic-gate 	}
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	/* Set status and call completion_callback() */
9260Sstevel@tonic-gate 	if (req->completion_callback != NULL) {
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback,
9290Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 		req->completion_callback(req);
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
9340Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
9350Sstevel@tonic-gate 		return;
9360Sstevel@tonic-gate 	}
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
9390Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate /*
9430Sstevel@tonic-gate  * s1394_atresp_cmd_complete()
9440Sstevel@tonic-gate  *    is similar to s1394_atreq_cmd_complete(). It is also called by
9450Sstevel@tonic-gate  *    h1394_cmd_is_complete(), but when an AT response has completed.
9460Sstevel@tonic-gate  *    Again, based upon the command's completion status,
9470Sstevel@tonic-gate  *    s1394_atresp_cmd_complete() determines whether to call the target or
9480Sstevel@tonic-gate  *    to simply cleanup the command and return.
9490Sstevel@tonic-gate  */
9500Sstevel@tonic-gate void
s1394_atresp_cmd_complete(s1394_hal_t * hal,cmd1394_cmd_t * resp,int status)9510Sstevel@tonic-gate s1394_atresp_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *resp, int status)
9520Sstevel@tonic-gate {
9530Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
9540Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
9550Sstevel@tonic-gate 	dev_info_t	 *dip;
9560Sstevel@tonic-gate 	boolean_t	 valid_addr_blk;
9570Sstevel@tonic-gate 	int		 target_status;
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_enter,
9600Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "");
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 	target_status = CMD1394_CMDSUCCESS;
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 	/* If not an ack_complete */
9650Sstevel@tonic-gate 	if (status != H1394_CMD_SUCCESS) {
9660Sstevel@tonic-gate 		switch (status) {
9670Sstevel@tonic-gate 		/* evt_missing_ack */
9680Sstevel@tonic-gate 		case H1394_CMD_ETIMEOUT:
9690Sstevel@tonic-gate 			target_status = CMD1394_ETIMEOUT;
9700Sstevel@tonic-gate 			break;
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 		/* evt_flushed */
9730Sstevel@tonic-gate 		case H1394_CMD_EBUSRESET:
9740Sstevel@tonic-gate 			target_status = CMD1394_EBUSRESET;
9750Sstevel@tonic-gate 			break;
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 		/* ack_busy_X */
9780Sstevel@tonic-gate 		/* ack_busy_A */
9790Sstevel@tonic-gate 		/* ack_busy_B */
9800Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_BUSY:
9810Sstevel@tonic-gate 			target_status = CMD1394_EDEVICE_BUSY;
9820Sstevel@tonic-gate 			break;
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 		/* ack_data_error */
9850Sstevel@tonic-gate 		case H1394_CMD_EDATA_ERROR:
9860Sstevel@tonic-gate 			target_status = CMD1394_EDATA_ERROR;
9870Sstevel@tonic-gate 			break;
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 		/* ack_type_error */
9900Sstevel@tonic-gate 		case H1394_CMD_ETYPE_ERROR:
9910Sstevel@tonic-gate 			target_status = CMD1394_ETYPE_ERROR;
9920Sstevel@tonic-gate 			break;
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 		/* ack_address_error */
9950Sstevel@tonic-gate 		case H1394_CMD_EADDR_ERROR:
9960Sstevel@tonic-gate 			target_status = CMD1394_EADDRESS_ERROR;
9970Sstevel@tonic-gate 			break;
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 		/* ack_conflict_error */
10000Sstevel@tonic-gate 		case H1394_CMD_ERSRC_CONFLICT:
10010Sstevel@tonic-gate 			target_status = CMD1394_ERSRC_CONFLICT;
10020Sstevel@tonic-gate 			break;
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 		/* ack_tardy */
10050Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_POWERUP:
10060Sstevel@tonic-gate 			target_status = CMD1394_EDEVICE_BUSY;
10070Sstevel@tonic-gate 			break;
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 		/* device errors (bad tcodes, ACKs, etc...) */
10100Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_ERROR:
10110Sstevel@tonic-gate 			target_status = CMD1394_EDEVICE_ERROR;
10120Sstevel@tonic-gate 			break;
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate 		/* Unknown error type */
10150Sstevel@tonic-gate 		case H1394_CMD_EUNKNOWN_ERROR:
10160Sstevel@tonic-gate 			target_status = CMD1394_EUNKNOWN_ERROR;
10170Sstevel@tonic-gate 			break;
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 		/* Unrecognized error */
10200Sstevel@tonic-gate 		default:
10210Sstevel@tonic-gate 			dip = hal->halinfo.dip;
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 			/* An unexpected error in the HAL */
10240Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
10250Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 			/* Disable the HAL */
10280Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate 			TNF_PROBE_2(s1394_atresp_cmd_complete_error,
10310Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
10320Sstevel@tonic-gate 			    "Unrecognized cmd status code",
10330Sstevel@tonic-gate 			    tnf_int, status, status);
10340Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_exit,
10350Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_STACK, "");
10360Sstevel@tonic-gate 			return;
10370Sstevel@tonic-gate 		}
10380Sstevel@tonic-gate 	}
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	/* Get the Services Layer private area */
10410Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(resp);
10420Sstevel@tonic-gate 
10430Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
10440Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	valid_addr_blk = s_priv->arreq_valid_addr;
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	if (valid_addr_blk == B_TRUE) {
10490Sstevel@tonic-gate 		/* Set the command status */
10500Sstevel@tonic-gate 		resp->cmd_result = target_status;
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 		switch (s_priv->cmd_priv_xfer_type) {
10530Sstevel@tonic-gate 		case S1394_CMD_READ:
10540Sstevel@tonic-gate 		case S1394_CMD_WRITE:
10550Sstevel@tonic-gate 		case S1394_CMD_LOCK:
10560Sstevel@tonic-gate 			if (resp->completion_callback != NULL) {
10570Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
10580Sstevel@tonic-gate 				    s1394_atresp_cmd_complete_do_callback,
10590Sstevel@tonic-gate 				    S1394_TNF_SL_ATRESP_STACK, "");
10600Sstevel@tonic-gate 				resp->completion_callback(resp);
10610Sstevel@tonic-gate 			}
10620Sstevel@tonic-gate 			break;
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 		default:
10650Sstevel@tonic-gate 			dip = hal->halinfo.dip;
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 			/* An unexpected error in the HAL */
10680Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
10690Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
10700Sstevel@tonic-gate 
10710Sstevel@tonic-gate 			/* Disable the HAL */
10720Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 			TNF_PROBE_1(s1394_atresp_cmd_complete_error,
10750Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
10760Sstevel@tonic-gate 			    "Unrecognized transfer type");
10770Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_exit,
10780Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_STACK, "");
10790Sstevel@tonic-gate 			return;
10800Sstevel@tonic-gate 		}
10810Sstevel@tonic-gate 	}
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_call_hal_cmplt,
10840Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "");
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 	/* Free the command - Pass it back to the HAL */
10870Sstevel@tonic-gate 	HAL_CALL(hal).response_complete(hal->halinfo.hal_private, resp, h_priv);
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_atresp_cmd_complete_exit,
10900Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "", tnf_int, status, target_status);
10910Sstevel@tonic-gate }
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate /*
10940Sstevel@tonic-gate  * s1394_send_response()
10950Sstevel@tonic-gate  *    is used to send a response to an AR request.  Depending on whether the
10960Sstevel@tonic-gate  *    request was a broadcast request, a write to posted write address space,
10970Sstevel@tonic-gate  *    or some other request, either a response packet is sent, or the command
10980Sstevel@tonic-gate  *    is returned to the HAL.  A return value of DDI_SUCCESS means that the
10990Sstevel@tonic-gate  *    command has been handled correctly.  It was either successfully sent to
11000Sstevel@tonic-gate  *    the HAL, or, if it was posted_write of broadcast, it was freed up.  A
11010Sstevel@tonic-gate  *    return value of DDI_FAILURE indicates either a serious error, in which
11020Sstevel@tonic-gate  *    case the HAL is shutdown, or a failure returned by the HAL, in which
11030Sstevel@tonic-gate  *    case the command is freed up and notice of the failure is returned.
11040Sstevel@tonic-gate  */
11050Sstevel@tonic-gate int
s1394_send_response(s1394_hal_t * hal,cmd1394_cmd_t * resp)11060Sstevel@tonic-gate s1394_send_response(s1394_hal_t *hal, cmd1394_cmd_t *resp)
11070Sstevel@tonic-gate {
11080Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
11090Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
11100Sstevel@tonic-gate 	dev_info_t	 *dip;
11110Sstevel@tonic-gate 	int		 ret;
11120Sstevel@tonic-gate 	int		 result;
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_send_response_enter, S1394_TNF_SL_ATRESP_STACK,
11150Sstevel@tonic-gate 	    "");
11160Sstevel@tonic-gate 
11170Sstevel@tonic-gate 	/* Get the Services Layer private area */
11180Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(resp);
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
11210Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 	/*
11240Sstevel@tonic-gate 	 * If request was broadcast or a write request to a posted write
11250Sstevel@tonic-gate 	 * address, don't send a response
11260Sstevel@tonic-gate 	 */
11270Sstevel@tonic-gate 	if ((resp->broadcast == 1) || ((s_priv->posted_write == B_TRUE) &&
11280Sstevel@tonic-gate 	    ((resp->cmd_result == CMD1394_ASYNCH_WR_QUAD) ||
11290Sstevel@tonic-gate 	    (resp->cmd_result == CMD1394_ASYNCH_WR_BLOCK)))) {
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt,
11320Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 		/* Free the command - Pass it back to the HAL */
11350Sstevel@tonic-gate 		HAL_CALL(hal).response_complete(hal->halinfo.hal_private,
11360Sstevel@tonic-gate 		    resp, h_priv);
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
11390Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
11400Sstevel@tonic-gate 		return (DDI_SUCCESS);
11410Sstevel@tonic-gate 	}
11420Sstevel@tonic-gate 
11430Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_resp,
11440Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "");
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 	/* kstats - number of failure responses sent */
11470Sstevel@tonic-gate 	if (resp->cmd_result != IEEE1394_RESP_COMPLETE) {
11480Sstevel@tonic-gate 		switch (resp->cmd_type) {
11490Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_QUAD:
11500Sstevel@tonic-gate 			hal->hal_kstats->arresp_quad_rd_fail++;
11510Sstevel@tonic-gate 			break;
11520Sstevel@tonic-gate 
11530Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_BLOCK:
11540Sstevel@tonic-gate 			hal->hal_kstats->arresp_blk_rd_fail++;
11550Sstevel@tonic-gate 			break;
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_QUAD:
11580Sstevel@tonic-gate 			hal->hal_kstats->arresp_quad_wr_fail++;
11590Sstevel@tonic-gate 			break;
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_BLOCK:
11620Sstevel@tonic-gate 			hal->hal_kstats->arresp_blk_wr_fail++;
11630Sstevel@tonic-gate 			break;
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_32:
11660Sstevel@tonic-gate 			hal->hal_kstats->arresp_lock32_fail++;
11670Sstevel@tonic-gate 			break;
11680Sstevel@tonic-gate 
11690Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_64:
11700Sstevel@tonic-gate 			hal->hal_kstats->arresp_lock64_fail++;
11710Sstevel@tonic-gate 			break;
11720Sstevel@tonic-gate 		}
11730Sstevel@tonic-gate 	} else {
11740Sstevel@tonic-gate 		if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK)
11750Sstevel@tonic-gate 			hal->hal_kstats->arreq_blk_rd_size +=
11760Sstevel@tonic-gate 			    resp->cmd_u.b.blk_length;
11770Sstevel@tonic-gate 	}
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK) {
11800Sstevel@tonic-gate 		h_priv->mblk.curr_mblk = resp->cmd_u.b.data_block;
11810Sstevel@tonic-gate 		h_priv->mblk.curr_offset = resp->cmd_u.b.data_block->b_rptr;
11820Sstevel@tonic-gate 		h_priv->mblk.length = resp->cmd_u.b.blk_length;
11830Sstevel@tonic-gate 	}
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 	switch (s_priv->cmd_priv_xfer_type) {
11860Sstevel@tonic-gate 	case S1394_CMD_READ:
11870Sstevel@tonic-gate 		ret = HAL_CALL(hal).read_response(hal->halinfo.hal_private,
11880Sstevel@tonic-gate 		    resp, h_priv, &result);
11890Sstevel@tonic-gate 		break;
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	case S1394_CMD_WRITE:
11920Sstevel@tonic-gate 		ret = HAL_CALL(hal).write_response(hal->halinfo.hal_private,
11930Sstevel@tonic-gate 		    resp, h_priv, &result);
11940Sstevel@tonic-gate 		break;
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 	case S1394_CMD_LOCK:
11970Sstevel@tonic-gate 		ret = HAL_CALL(hal).lock_response(hal->halinfo.hal_private,
11980Sstevel@tonic-gate 		    resp, h_priv, &result);
11990Sstevel@tonic-gate 		break;
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate 	default:
12020Sstevel@tonic-gate 		dip = hal->halinfo.dip;
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 		/* An unexpected error in the HAL */
12050Sstevel@tonic-gate 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
12060Sstevel@tonic-gate 		    ddi_node_name(dip), ddi_get_instance(dip));
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 		/* Disable the HAL */
12090Sstevel@tonic-gate 		s1394_hal_shutdown(hal, B_TRUE);
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 		TNF_PROBE_1(s1394_send_response_error,
12120Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12130Sstevel@tonic-gate 		    "Unrecognized transfer type");
12140Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
12150Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
12160Sstevel@tonic-gate 		return (DDI_FAILURE);
12170Sstevel@tonic-gate 	}
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 	/* Unable to send a response */
12200Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
12210Sstevel@tonic-gate 		if (result == H1394_STATUS_INVALID_BUSGEN) {
12220Sstevel@tonic-gate 			TNF_PROBE_1(s1394_send_response_error,
12230Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12240Sstevel@tonic-gate 			    "Invalid generation in response");
12250Sstevel@tonic-gate 		} else if (result == H1394_STATUS_NOMORE_SPACE) {
12260Sstevel@tonic-gate 			TNF_PROBE_1(s1394_send_response_error,
12270Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12280Sstevel@tonic-gate 			    "No more space on AT response queue");
12290Sstevel@tonic-gate 		} else {
12300Sstevel@tonic-gate 			TNF_PROBE_1(s1394_send_response_error,
12310Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12320Sstevel@tonic-gate 			    "Unknown problem in s1394_send_response");
12330Sstevel@tonic-gate 		}
12340Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt,
12350Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 		/* Free the command - Pass it back to the HAL */
12380Sstevel@tonic-gate 		HAL_CALL(hal).response_complete(hal->halinfo.hal_private,
12390Sstevel@tonic-gate 		    resp, h_priv);
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
12420Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
12430Sstevel@tonic-gate 		return (DDI_FAILURE);
12440Sstevel@tonic-gate 	}
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_send_response_exit, S1394_TNF_SL_ATRESP_STACK,
12470Sstevel@tonic-gate 	    "");
12480Sstevel@tonic-gate 	return (DDI_SUCCESS);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate /*
12520Sstevel@tonic-gate  * s1394_compare_swap()
12530Sstevel@tonic-gate  *    is used by t1394_lock() to send a lock request.  Any of the lock
12540Sstevel@tonic-gate  *    requests specified explicitly by the 1394 spec will pass thru here,
12550Sstevel@tonic-gate  *    i.e compare-swap, mask-swap, etc.
12560Sstevel@tonic-gate  */
12570Sstevel@tonic-gate int
s1394_compare_swap(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd)12580Sstevel@tonic-gate s1394_compare_swap(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd)
12590Sstevel@tonic-gate {
12600Sstevel@tonic-gate 	s1394_cmd_priv_t	*s_priv;
12610Sstevel@tonic-gate 	s1394_hal_state_t	state;
12620Sstevel@tonic-gate 	int			err;
12630Sstevel@tonic-gate 	int			ret;
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_compare_swap_enter, S1394_TNF_SL_ATREQ_STACK,
12660Sstevel@tonic-gate 	    "");
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
12690Sstevel@tonic-gate 
12700Sstevel@tonic-gate 	/* Lock the topology tree - protect from bus reset */
12710Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 	ret = s1394_setup_asynch_command(hal, target, cmd, S1394_CMD_LOCK,
12740Sstevel@tonic-gate 	    &err);
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate 	/* Unlock the topology tree */
12770Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 	/* Get the Services Layer private area */
12800Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	/* Command has now been put onto the queue! */
12830Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
12840Sstevel@tonic-gate 		/* Copy error code into result */
12850Sstevel@tonic-gate 		cmd->cmd_result = err;
12860Sstevel@tonic-gate 
12870Sstevel@tonic-gate 		TNF_PROBE_0(s1394_compare_swap_error_in_setup_asynch,
12880Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "");
12890Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
12900Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
12910Sstevel@tonic-gate 		return (DDI_FAILURE);
12920Sstevel@tonic-gate 	}
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
12950Sstevel@tonic-gate 	state = hal->hal_state;
12960Sstevel@tonic-gate 	/* If this command was sent during a bus reset, */
12970Sstevel@tonic-gate 	/* then put it onto the pending Q. */
12980Sstevel@tonic-gate 	if (state == S1394_HAL_RESET) {
12990Sstevel@tonic-gate 		/* Remove cmd from outstanding request Q */
13000Sstevel@tonic-gate 		s1394_remove_q_asynch_cmd(hal, cmd);
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate 		/* Are we on the bus reset event stack? */
13030Sstevel@tonic-gate 		if (s1394_on_br_thread(hal) == B_TRUE) {
13040Sstevel@tonic-gate 			/* Blocking commands are not allowed */
13050Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_BLOCKING) {
13060Sstevel@tonic-gate 				mutex_exit(&hal->topology_tree_mutex);
13070Sstevel@tonic-gate 
13080Sstevel@tonic-gate 				s_priv->cmd_in_use = B_FALSE;
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 				cmd->cmd_result = CMD1394_EINVALID_CONTEXT;
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate 				TNF_PROBE_1(s1394_compare_swap_error,
13130Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string,
13140Sstevel@tonic-gate 				    msg, "CMD1394_BLOCKING in bus reset ctxt");
13150Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13160Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
13170Sstevel@tonic-gate 				return (DDI_FAILURE);
13180Sstevel@tonic-gate 			}
13190Sstevel@tonic-gate 		}
13200Sstevel@tonic-gate 
13210Sstevel@tonic-gate 		s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
13220Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 		/* Block (if necessary) */
13250Sstevel@tonic-gate 		s1394_block_on_asynch_cmd(cmd);
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK,
13280Sstevel@tonic-gate 		    "");
13290Sstevel@tonic-gate 		return (DDI_SUCCESS);
13300Sstevel@tonic-gate 	}
13310Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	/* Send the command out */
13340Sstevel@tonic-gate 	ret = s1394_xfer_asynch_command(hal, cmd, &err);
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
13370Sstevel@tonic-gate 		if (err == CMD1394_ESTALE_GENERATION) {
13380Sstevel@tonic-gate 			/* Remove cmd from outstanding request Q */
13390Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
13400Sstevel@tonic-gate 			s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 			/* Block (if necessary) */
13430Sstevel@tonic-gate 			s1394_block_on_asynch_cmd(cmd);
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13460Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
13470Sstevel@tonic-gate 			return (DDI_SUCCESS);
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 		} else {
13500Sstevel@tonic-gate 			/* Remove cmd from outstanding request Q */
13510Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 			s_priv->cmd_in_use = B_FALSE;
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 			/* Copy error code into result */
13560Sstevel@tonic-gate 			cmd->cmd_result = err;
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 			TNF_PROBE_0(s1394_compare_swap_error_in_xfer,
13590Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_ERROR, "");
13600Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13610Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
13620Sstevel@tonic-gate 			return (DDI_FAILURE);
13630Sstevel@tonic-gate 		}
13640Sstevel@tonic-gate 	} else {
13650Sstevel@tonic-gate 		/* Block (if necessary) */
13660Sstevel@tonic-gate 		s1394_block_on_asynch_cmd(cmd);
13670Sstevel@tonic-gate 
13680Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13690Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
13700Sstevel@tonic-gate 		return (DDI_SUCCESS);
13710Sstevel@tonic-gate 	}
13720Sstevel@tonic-gate }
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate /*
13750Sstevel@tonic-gate  * s1394_split_lock_req()
13760Sstevel@tonic-gate  *    is also used by t1394_lock() to send a lock request.  The difference
13770Sstevel@tonic-gate  *    is that s1394_split_lock_req() is used to send the software supported
13780Sstevel@tonic-gate  *    lock types, i.e. bit_and, bit_or, etc.  These lock requests require
13790Sstevel@tonic-gate  *    more than one transaction, typically compare-swap's.
13800Sstevel@tonic-gate  */
13810Sstevel@tonic-gate int
s1394_split_lock_req(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd)13820Sstevel@tonic-gate s1394_split_lock_req(s1394_hal_t *hal, s1394_target_t *target,
13830Sstevel@tonic-gate     cmd1394_cmd_t *cmd)
13840Sstevel@tonic-gate {
13850Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
13860Sstevel@tonic-gate 	cmd1394_cmd_t	 *tmp_cmd;
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_split_lock_req_enter,
13890Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	/* Allocate a temporary command */
13920Sstevel@tonic-gate 	if (s1394_alloc_cmd(hal, T1394_ALLOC_CMD_NOSLEEP, &tmp_cmd) !=
13930Sstevel@tonic-gate 	    DDI_SUCCESS) {
13940Sstevel@tonic-gate 		cmd->cmd_result = CMD1394_EUNKNOWN_ERROR;
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 		TNF_PROBE_0(s1394_split_lock_req_error_alloc_cmd,
13970Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "");
13980Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
13990Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
14000Sstevel@tonic-gate 		return (DDI_FAILURE);
14010Sstevel@tonic-gate 	}
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 	/* Get the Services Layer private area */
14040Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(tmp_cmd);
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	tmp_cmd->completion_callback	= s1394_handle_lock;
14070Sstevel@tonic-gate 	tmp_cmd->cmd_callback_arg	= (opaque_t)cmd;
14080Sstevel@tonic-gate 	tmp_cmd->cmd_type		= cmd->cmd_type;
14090Sstevel@tonic-gate 	tmp_cmd->cmd_addr		= cmd->cmd_addr;
14100Sstevel@tonic-gate 	tmp_cmd->cmd_options		= cmd->cmd_options;
14110Sstevel@tonic-gate 	tmp_cmd->bus_generation		= cmd->bus_generation;
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate 	/* The temporary command can not block */
14140Sstevel@tonic-gate 	tmp_cmd->cmd_options = tmp_cmd->cmd_options & ~CMD1394_BLOCKING;
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate 	/* Setup compare-swap with data_value == arg_value (read) */
14170Sstevel@tonic-gate 	if (tmp_cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
14180Sstevel@tonic-gate 		tmp_cmd->cmd_u.l32.data_value	= 0;
14190Sstevel@tonic-gate 		tmp_cmd->cmd_u.l32.arg_value	= 0;
14200Sstevel@tonic-gate 		tmp_cmd->cmd_u.l32.lock_type	= CMD1394_LOCK_COMPARE_SWAP;
14210Sstevel@tonic-gate 		s_priv->temp_num_retries	= cmd->cmd_u.l32.num_retries;
14220Sstevel@tonic-gate 	} else {
14230Sstevel@tonic-gate 		tmp_cmd->cmd_u.l64.data_value	= 0;
14240Sstevel@tonic-gate 		tmp_cmd->cmd_u.l64.arg_value	= 0;
14250Sstevel@tonic-gate 		tmp_cmd->cmd_u.l64.lock_type	= CMD1394_LOCK_COMPARE_SWAP;
14260Sstevel@tonic-gate 		s_priv->temp_num_retries	= cmd->cmd_u.l64.num_retries;
14270Sstevel@tonic-gate 	}
14280Sstevel@tonic-gate 
14290Sstevel@tonic-gate 	/* Initialize lock_req_step */
14300Sstevel@tonic-gate 	s_priv->lock_req_step = 0;
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate 	/* Get the Services Layer private area for the target cmd */
14330Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate 	s_priv->cmd_in_use = B_TRUE;
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate 	/* Send the request */
14380Sstevel@tonic-gate 	if (s1394_compare_swap(hal, target, tmp_cmd) != DDI_SUCCESS) {
14390Sstevel@tonic-gate 		s_priv->cmd_in_use = B_FALSE;
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 		/* Free the temporary command */
14420Sstevel@tonic-gate 		if (s1394_free_cmd(hal, &tmp_cmd) != DDI_SUCCESS)
14430Sstevel@tonic-gate 			cmd->cmd_result = CMD1394_EUNKNOWN_ERROR;
14440Sstevel@tonic-gate 
14450Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
14460Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
14470Sstevel@tonic-gate 		return (DDI_FAILURE);
14480Sstevel@tonic-gate 	}
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 	/* Block (if necessary) */
14510Sstevel@tonic-gate 	s1394_block_on_asynch_cmd(cmd);
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
14540Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
14550Sstevel@tonic-gate 	return (DDI_SUCCESS);
14560Sstevel@tonic-gate }
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate /*
14590Sstevel@tonic-gate  * s1394_handle_lock()
14600Sstevel@tonic-gate  *    is the callback for s1394_split_lock_req().  It does all of the real
14610Sstevel@tonic-gate  *    work.  Based on the specific lock type all necessary manipulation is
14620Sstevel@tonic-gate  *    performed and another compare swap is sent out.  If the transaction
14630Sstevel@tonic-gate  *    is unsuccessful, it is retried.
14640Sstevel@tonic-gate  */
14650Sstevel@tonic-gate static void
s1394_handle_lock(cmd1394_cmd_t * cmd)14660Sstevel@tonic-gate s1394_handle_lock(cmd1394_cmd_t *cmd)
14670Sstevel@tonic-gate {
14680Sstevel@tonic-gate 	s1394_hal_t	 *to_hal;
14690Sstevel@tonic-gate 	s1394_target_t	 *target;
14700Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
14710Sstevel@tonic-gate 	cmd1394_cmd_t	 *target_cmd;
14720Sstevel@tonic-gate 	uint32_t	 lock_req_step;
14730Sstevel@tonic-gate 	int		 tcmd_result;
14740Sstevel@tonic-gate 	int		 ret;
14750Sstevel@tonic-gate 
14760Sstevel@tonic-gate 
14770Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_handle_lock_enter, S1394_TNF_SL_ATREQ_STACK,
14780Sstevel@tonic-gate 	    "");
14790Sstevel@tonic-gate 
14800Sstevel@tonic-gate 	/* Get the Services Layer private area */
14810Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 	lock_req_step = s_priv->lock_req_step;
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	/* Get the target's command */
14860Sstevel@tonic-gate 	target_cmd = (cmd1394_cmd_t *)cmd->cmd_callback_arg;
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 	/* Get the destination of the command */
14890Sstevel@tonic-gate 	to_hal = s_priv->sent_on_hal;
14900Sstevel@tonic-gate 
14910Sstevel@tonic-gate lock_req_step_0:
14920Sstevel@tonic-gate 	/* Is this step 0 completing? */
14930Sstevel@tonic-gate 	if (lock_req_step == 0) {
14940Sstevel@tonic-gate 		/* Was the request successful? */
14950Sstevel@tonic-gate 		if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
14960Sstevel@tonic-gate 			/* Do any math, bit ops, or byte-swapping necessary */
14970Sstevel@tonic-gate 			ret = s1394_process_split_lock(cmd, target_cmd);
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate 			if (ret != DDI_SUCCESS) {
15000Sstevel@tonic-gate 				tcmd_result = target_cmd->cmd_result;
15010Sstevel@tonic-gate 				goto lock_req_done;
15020Sstevel@tonic-gate 			}
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 			s_priv->lock_req_step = 1;
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate 			target = s_priv->sent_by_target;
15070Sstevel@tonic-gate 
15080Sstevel@tonic-gate 			if (s1394_compare_swap(to_hal, target, cmd) !=
15090Sstevel@tonic-gate 			    DDI_SUCCESS) {
15100Sstevel@tonic-gate 				tcmd_result = cmd->cmd_result;
15110Sstevel@tonic-gate 				goto lock_req_done;
15120Sstevel@tonic-gate 			} else {
15130Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
15140Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
15150Sstevel@tonic-gate 				return;
15160Sstevel@tonic-gate 			}
15170Sstevel@tonic-gate 		} else {
15180Sstevel@tonic-gate 			/* Command failed for some reason */
15190Sstevel@tonic-gate 			tcmd_result = cmd->cmd_result;
15200Sstevel@tonic-gate 			goto lock_req_done;
15210Sstevel@tonic-gate 		}
15220Sstevel@tonic-gate 	} else {	/* lock_req_step == 1 */
15230Sstevel@tonic-gate 		/* Was the request successful? */
15240Sstevel@tonic-gate 		if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
15250Sstevel@tonic-gate 			/* Do whatever's necessary to finish up the lock */
15260Sstevel@tonic-gate 			ret = s1394_finish_split_lock(cmd, target_cmd);
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 			if (ret != DDI_SUCCESS) {
15290Sstevel@tonic-gate 				lock_req_step = 0;
15300Sstevel@tonic-gate 				goto lock_req_step_0;
15310Sstevel@tonic-gate 			} else {
15320Sstevel@tonic-gate 				tcmd_result = cmd->cmd_result;
15330Sstevel@tonic-gate 				goto lock_req_done;
15340Sstevel@tonic-gate 			}
15350Sstevel@tonic-gate 		} else {
15360Sstevel@tonic-gate 			/* Command failed for some reason */
15370Sstevel@tonic-gate 			tcmd_result = cmd->cmd_result;
15380Sstevel@tonic-gate 			goto lock_req_done;
15390Sstevel@tonic-gate 		}
15400Sstevel@tonic-gate 	}
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate lock_req_done:
15430Sstevel@tonic-gate 	if (s1394_free_cmd(to_hal, &cmd) != DDI_SUCCESS) {
15440Sstevel@tonic-gate 		TNF_PROBE_0(s1394_handle_lock_error_in_freecmd,
15450Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "");
15460Sstevel@tonic-gate 	}
15470Sstevel@tonic-gate 
15480Sstevel@tonic-gate 	/* Get the Services Layer private area */
15490Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(target_cmd);
15500Sstevel@tonic-gate 
15510Sstevel@tonic-gate 	s_priv->cmd_in_use = B_FALSE;
15520Sstevel@tonic-gate 
15530Sstevel@tonic-gate 	target_cmd->cmd_result = tcmd_result;
15540Sstevel@tonic-gate 
15550Sstevel@tonic-gate 	/* Is this a blocking command? */
15560Sstevel@tonic-gate 	if (target_cmd->cmd_options & CMD1394_BLOCKING) {
15570Sstevel@tonic-gate 		/* Unblock the waiting command */
15580Sstevel@tonic-gate 		mutex_enter(&s_priv->blocking_mutex);
15590Sstevel@tonic-gate 		s_priv->blocking_flag = B_TRUE;
15600Sstevel@tonic-gate 		cv_signal(&s_priv->blocking_cv);
15610Sstevel@tonic-gate 		mutex_exit(&s_priv->blocking_mutex);
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
15640Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
15650Sstevel@tonic-gate 		return;
15660Sstevel@tonic-gate 	}
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate 	/* Call the target's completion_callback() */
15690Sstevel@tonic-gate 	if (target_cmd->completion_callback != NULL)
15700Sstevel@tonic-gate 		target_cmd->completion_callback(target_cmd);
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
15730Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
15740Sstevel@tonic-gate }
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate /*
15770Sstevel@tonic-gate  * s1394_pending_q_insert()
15780Sstevel@tonic-gate  *    is used to insert a given command structure onto a HAL's pending queue
15790Sstevel@tonic-gate  *    for later processing (after the bus reset).  All commands returned by
15800Sstevel@tonic-gate  *    the HAL, are inserted onto the rear of the list (first priority), and
15810Sstevel@tonic-gate  *    all other commands (from targets during bus reset) are put onto the front.
15820Sstevel@tonic-gate  */
15830Sstevel@tonic-gate void
s1394_pending_q_insert(s1394_hal_t * hal,cmd1394_cmd_t * cmd,uint_t flags)15840Sstevel@tonic-gate s1394_pending_q_insert(s1394_hal_t *hal, cmd1394_cmd_t *cmd, uint_t flags)
15850Sstevel@tonic-gate {
15860Sstevel@tonic-gate 	cmd1394_cmd_t *temp_cmd;
15870Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
15880Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
15890Sstevel@tonic-gate 
15900Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_insert_enter,
15910Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
15920Sstevel@tonic-gate 
15930Sstevel@tonic-gate 	mutex_enter(&hal->pending_q_mutex);
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate 	/* Get the Services Layer private area */
15960Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
15970Sstevel@tonic-gate 
15980Sstevel@tonic-gate 	/* Is the outstanding request queue empty? */
15990Sstevel@tonic-gate 	if ((hal->pending_q_head == NULL) && (hal->pending_q_tail == NULL)) {
16000Sstevel@tonic-gate 
16010Sstevel@tonic-gate 		hal->pending_q_head = (cmd1394_cmd_t *)cmd;
16020Sstevel@tonic-gate 		hal->pending_q_tail = (cmd1394_cmd_t *)cmd;
16030Sstevel@tonic-gate 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16040Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 	} else if (flags == S1394_PENDING_Q_FRONT) {
16070Sstevel@tonic-gate 		s_priv->cmd_priv_next = hal->pending_q_head;
16080Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate 		temp_cmd = (cmd1394_cmd_t *)hal->pending_q_head;
16110Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd +
16120Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
16130Sstevel@tonic-gate 		c_priv->cmd_priv_prev = (cmd1394_cmd_t *)cmd;
16140Sstevel@tonic-gate 
16150Sstevel@tonic-gate 		hal->pending_q_head = (cmd1394_cmd_t *)cmd;
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 	} else {
16180Sstevel@tonic-gate 		s_priv->cmd_priv_prev = hal->pending_q_tail;
16190Sstevel@tonic-gate 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16200Sstevel@tonic-gate 
16210Sstevel@tonic-gate 		temp_cmd = (cmd1394_cmd_t *)hal->pending_q_tail;
16220Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd +
16230Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
16240Sstevel@tonic-gate 		c_priv->cmd_priv_next = (cmd1394_cmd_t *)cmd;
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 		hal->pending_q_tail = (cmd1394_cmd_t *)cmd;
16270Sstevel@tonic-gate 	}
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate 	mutex_exit(&hal->pending_q_mutex);
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate 	/* kstats - number of pending Q insertions */
16320Sstevel@tonic-gate 	hal->hal_kstats->pending_q_insert++;
16330Sstevel@tonic-gate 
16340Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_insert_exit,
16350Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
16360Sstevel@tonic-gate }
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate /*
16390Sstevel@tonic-gate  * s1394_pending_q_remove()
16400Sstevel@tonic-gate  *    is used to remove a command structure from a HAL's pending queue for
16410Sstevel@tonic-gate  *    processing.
16420Sstevel@tonic-gate  */
16430Sstevel@tonic-gate static cmd1394_cmd_t *
s1394_pending_q_remove(s1394_hal_t * hal)16440Sstevel@tonic-gate s1394_pending_q_remove(s1394_hal_t *hal)
16450Sstevel@tonic-gate {
16460Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
16470Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
16480Sstevel@tonic-gate 	cmd1394_cmd_t	 *cmd;
16490Sstevel@tonic-gate 	cmd1394_cmd_t	 *prev_cmd;
16500Sstevel@tonic-gate 
16510Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_remove_enter,
16520Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
16530Sstevel@tonic-gate 
16540Sstevel@tonic-gate 	mutex_enter(&hal->pending_q_mutex);
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 	cmd = (cmd1394_cmd_t *)hal->pending_q_tail;
16570Sstevel@tonic-gate 	if (cmd == NULL) {
16580Sstevel@tonic-gate 		mutex_exit(&hal->pending_q_mutex);
16590Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit,
16600Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
16610Sstevel@tonic-gate 		return (NULL);
16620Sstevel@tonic-gate 	}
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 	/* Get the Services Layer private area */
16650Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
16660Sstevel@tonic-gate 
16670Sstevel@tonic-gate 	prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev;
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 	s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
16700Sstevel@tonic-gate 	s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	if (prev_cmd != NULL) {
16730Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)prev_cmd +
16740Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
16750Sstevel@tonic-gate 		c_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate 	} else {
16780Sstevel@tonic-gate 		hal->pending_q_head = (cmd1394_cmd_t *)NULL;
16790Sstevel@tonic-gate 	}
16800Sstevel@tonic-gate 	hal->pending_q_tail = (cmd1394_cmd_t *)prev_cmd;
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate 	mutex_exit(&hal->pending_q_mutex);
16830Sstevel@tonic-gate 
16840Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit,
16850Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
16860Sstevel@tonic-gate 	return (cmd);
16870Sstevel@tonic-gate }
16880Sstevel@tonic-gate 
16890Sstevel@tonic-gate /*
16900Sstevel@tonic-gate  * s1394_resend_pending_cmds()
16910Sstevel@tonic-gate  *    is called when the pending queue is to be flushed.  After most of the
16920Sstevel@tonic-gate  *    bus reset processing is completed, the pending commands are sent/resent.
16930Sstevel@tonic-gate  */
16940Sstevel@tonic-gate void
s1394_resend_pending_cmds(s1394_hal_t * hal)16950Sstevel@tonic-gate s1394_resend_pending_cmds(s1394_hal_t *hal)
16960Sstevel@tonic-gate {
16970Sstevel@tonic-gate 	int done;
16980Sstevel@tonic-gate 
16990Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_enter,
17000Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
17030Sstevel@tonic-gate 
17040Sstevel@tonic-gate 	do {
17050Sstevel@tonic-gate 		done = s1394_process_pending_q(hal);
17060Sstevel@tonic-gate 	} while (done == B_FALSE);
17070Sstevel@tonic-gate 
17080Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_exit,
17110Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
17120Sstevel@tonic-gate }
17130Sstevel@tonic-gate 
17140Sstevel@tonic-gate /*
17150Sstevel@tonic-gate  * s1394_process_pending_q()
17160Sstevel@tonic-gate  *    is called to send/resend the commands on the pending queue.  All command
17170Sstevel@tonic-gate  *    handling can be done here, including notifying the target of failed
17180Sstevel@tonic-gate  *    commands, etc.  If it is necessary to recompute the address, speed,
17190Sstevel@tonic-gate  *    or max_payload for a command, that can be done here too.  And if there
17200Sstevel@tonic-gate  *    is no reason not to continue sending commands from the pending queue,
17210Sstevel@tonic-gate  *    then a B_FALSE is returned, else B_TRUE is returned.
17220Sstevel@tonic-gate  */
17230Sstevel@tonic-gate static boolean_t
s1394_process_pending_q(s1394_hal_t * hal)17240Sstevel@tonic-gate s1394_process_pending_q(s1394_hal_t *hal)
17250Sstevel@tonic-gate {
17260Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
17270Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
17280Sstevel@tonic-gate 	s1394_target_t	 *target;
17290Sstevel@tonic-gate 	cmd1394_cmd_t	 *cmd;
17300Sstevel@tonic-gate 	uint64_t	 node;
17310Sstevel@tonic-gate 	uint32_t	 from_node;
17320Sstevel@tonic-gate 	uint32_t	 to_node;
17330Sstevel@tonic-gate 	uint_t		 current_max_payload;
17340Sstevel@tonic-gate 	int		 ret;
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_process_pending_q_enter,
17370Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate 	/* Pull a command from the Pending Q */
17420Sstevel@tonic-gate 	cmd = s1394_pending_q_remove(hal);
17430Sstevel@tonic-gate 
17440Sstevel@tonic-gate 	if (cmd == NULL) {
17450Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
17460Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
17470Sstevel@tonic-gate 		return (B_TRUE);
17480Sstevel@tonic-gate 	}
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 	/* Get the Services Layer private area */
17510Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
17520Sstevel@tonic-gate 
17530Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
17540Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 	if ((cmd->cmd_options & CMD1394_OVERRIDE_ADDR) ||
17570Sstevel@tonic-gate 	    (cmd->cmd_options & CMD1394_CANCEL_ON_BUS_RESET)) {
17580Sstevel@tonic-gate 		if (h_priv->bus_generation == hal->generation_count) {
17590Sstevel@tonic-gate 			ret = s1394_pending_q_helper(hal, cmd);
17600Sstevel@tonic-gate 			return (ret);
17610Sstevel@tonic-gate 		} else {
17620Sstevel@tonic-gate 
17630Sstevel@tonic-gate 			s_priv->cmd_in_use = B_FALSE;
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate 			cmd->cmd_result = CMD1394_EBUSRESET;
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate 			/* Is this a blocking command? */
17680Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_BLOCKING) {
17690Sstevel@tonic-gate 				/* Unblock the waiting command */
17700Sstevel@tonic-gate 				mutex_enter(&s_priv->blocking_mutex);
17710Sstevel@tonic-gate 				s_priv->blocking_flag = B_TRUE;
17720Sstevel@tonic-gate 				cv_signal(&s_priv->blocking_cv);
17730Sstevel@tonic-gate 				mutex_exit(&s_priv->blocking_mutex);
17740Sstevel@tonic-gate 
17750Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
17760Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
17770Sstevel@tonic-gate 				return (B_FALSE);
17780Sstevel@tonic-gate 			}
17790Sstevel@tonic-gate 
17800Sstevel@tonic-gate 			/* Call the target's completion_callback() */
17810Sstevel@tonic-gate 			if (cmd->completion_callback != NULL) {
17820Sstevel@tonic-gate 				cmd->completion_callback(cmd);
17830Sstevel@tonic-gate 			}
17840Sstevel@tonic-gate 
17850Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
17860Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
17870Sstevel@tonic-gate 			return (B_FALSE);
17880Sstevel@tonic-gate 		}
17890Sstevel@tonic-gate 	} else {
17900Sstevel@tonic-gate 		if (h_priv->bus_generation == hal->generation_count) {
17910Sstevel@tonic-gate 			ret = s1394_pending_q_helper(hal, cmd);
17920Sstevel@tonic-gate 			return (ret);
17930Sstevel@tonic-gate 		} else {
17940Sstevel@tonic-gate 			/* Make sure we can get the topology_tree_mutex */
17950Sstevel@tonic-gate 			if (s1394_lock_tree(hal) != DDI_SUCCESS)
17960Sstevel@tonic-gate 				return (B_TRUE);
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 			/* Set the generation */
17990Sstevel@tonic-gate 			cmd->bus_generation = hal->generation_count;
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate 			/* Copy the generation into the HAL's private field */
18020Sstevel@tonic-gate 			h_priv->bus_generation = cmd->bus_generation;
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 			target = s_priv->sent_by_target;
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate 			/* If not OVERRIDE_ADDR, then target may not be NULL */
18070Sstevel@tonic-gate 			ASSERT(target != NULL);
18080Sstevel@tonic-gate 
18090Sstevel@tonic-gate 			rw_enter(&hal->target_list_rwlock, RW_READER);
18100Sstevel@tonic-gate 
18110Sstevel@tonic-gate 			if (((target->target_state & S1394_TARG_GONE) == 0) &&
18120Sstevel@tonic-gate 			    (target->on_node != NULL)) {
18130Sstevel@tonic-gate 				node = target->on_node->node_num;
18140Sstevel@tonic-gate 				rw_exit(&hal->target_list_rwlock);
18150Sstevel@tonic-gate 			} else {
18160Sstevel@tonic-gate 				rw_exit(&hal->target_list_rwlock);
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate 				s_priv->cmd_in_use = B_FALSE;
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate 				cmd->cmd_result = CMD1394_EDEVICE_REMOVED;
18210Sstevel@tonic-gate 
18220Sstevel@tonic-gate 				/* Is this a blocking command? */
18230Sstevel@tonic-gate 				if (cmd->cmd_options & CMD1394_BLOCKING) {
18240Sstevel@tonic-gate 					s1394_unlock_tree(hal);
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 					/* Unblock the waiting command */
18270Sstevel@tonic-gate 					mutex_enter(&s_priv->blocking_mutex);
18280Sstevel@tonic-gate 					s_priv->blocking_flag = B_TRUE;
18290Sstevel@tonic-gate 					cv_signal(&s_priv->blocking_cv);
18300Sstevel@tonic-gate 					mutex_exit(&s_priv->blocking_mutex);
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
18330Sstevel@tonic-gate 					    s1394_process_pending_q_exit,
18340Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK,
18350Sstevel@tonic-gate 					    "");
18360Sstevel@tonic-gate 					return (B_FALSE);
18370Sstevel@tonic-gate 				}
18380Sstevel@tonic-gate 
18390Sstevel@tonic-gate 				/* Call the target's completion_callback() */
18400Sstevel@tonic-gate 				if (cmd->completion_callback != NULL) {
18410Sstevel@tonic-gate 					s1394_unlock_tree(hal);
18420Sstevel@tonic-gate 					cmd->completion_callback(cmd);
18430Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
18440Sstevel@tonic-gate 					    s1394_process_pending_q_exit,
18450Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "");
18460Sstevel@tonic-gate 					return (B_FALSE);
18470Sstevel@tonic-gate 				} else {
18480Sstevel@tonic-gate 					s1394_unlock_tree(hal);
18490Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
18500Sstevel@tonic-gate 					    s1394_process_pending_q_exit,
18510Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "");
18520Sstevel@tonic-gate 					return (B_FALSE);
18530Sstevel@tonic-gate 				}
18540Sstevel@tonic-gate 			}
18550Sstevel@tonic-gate 
18560Sstevel@tonic-gate 			/* Mask in the top 16-bits */
18570Sstevel@tonic-gate 			cmd->cmd_addr = cmd->cmd_addr &
18580Sstevel@tonic-gate 			    IEEE1394_ADDR_OFFSET_MASK;
18590Sstevel@tonic-gate 			cmd->cmd_addr = cmd->cmd_addr |
18600Sstevel@tonic-gate 			    (node << IEEE1394_ADDR_PHY_ID_SHIFT);
18610Sstevel@tonic-gate 			cmd->cmd_addr = cmd->cmd_addr |
18620Sstevel@tonic-gate 			    IEEE1394_ADDR_BUS_ID_MASK;
18630Sstevel@tonic-gate 
18640Sstevel@tonic-gate 			/* Speed is to be filled in from speed map */
18650Sstevel@tonic-gate 			from_node = IEEE1394_NODE_NUM(hal->node_id);
18660Sstevel@tonic-gate 			to_node	  = (uint32_t)node;
18670Sstevel@tonic-gate 
18680Sstevel@tonic-gate 			/* Fill in the nodeID */
18690Sstevel@tonic-gate 			cmd->nodeID =
18700Sstevel@tonic-gate 			    (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >>
18710Sstevel@tonic-gate 				IEEE1394_ADDR_NODE_ID_SHIFT;
18720Sstevel@tonic-gate 
18730Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) {
18740Sstevel@tonic-gate 				s_priv->hal_cmd_private.speed =
18750Sstevel@tonic-gate 				    (int)cmd->cmd_speed;
18760Sstevel@tonic-gate 			} else {
18770Sstevel@tonic-gate 				/* Speed is to be filled in from speed map */
18780Sstevel@tonic-gate 				s_priv->hal_cmd_private.speed =
18790Sstevel@tonic-gate 				    (int)s1394_speed_map_get(hal, from_node,
18800Sstevel@tonic-gate 				    to_node);
18810Sstevel@tonic-gate 			}
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 			/* Is it a block request? */
18840Sstevel@tonic-gate 			if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
18850Sstevel@tonic-gate 			    (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 				/* Get a pointer to the HAL private struct */
18880Sstevel@tonic-gate 				h_priv = (h1394_cmd_priv_t *)&s_priv->
18890Sstevel@tonic-gate 				    hal_cmd_private;
18900Sstevel@tonic-gate 
18910Sstevel@tonic-gate 				/* Handle the MAX_PAYLOAD size */
18920Sstevel@tonic-gate 				if (s_priv->sent_by_target != NULL) {
18930Sstevel@tonic-gate 					current_max_payload =
18940Sstevel@tonic-gate 					    s_priv->sent_by_target->
18950Sstevel@tonic-gate 					    current_max_payload;
18960Sstevel@tonic-gate 				} else {
18970Sstevel@tonic-gate 					current_max_payload = 4;
18980Sstevel@tonic-gate 				}
18990Sstevel@tonic-gate 				if (cmd->cmd_options &
19000Sstevel@tonic-gate 				    CMD1394_OVERRIDE_MAX_PAYLOAD) {
19010Sstevel@tonic-gate 					if (current_max_payload >
19020Sstevel@tonic-gate 					    cmd->cmd_u.b.max_payload)
19030Sstevel@tonic-gate 					    current_max_payload =
19040Sstevel@tonic-gate 						    cmd->cmd_u.b.max_payload;
19050Sstevel@tonic-gate 				}
19060Sstevel@tonic-gate 				if (s_priv->data_remaining <
19070Sstevel@tonic-gate 				    current_max_payload) {
19080Sstevel@tonic-gate 					h_priv->mblk.length =
19090Sstevel@tonic-gate 					    s_priv->data_remaining;
19100Sstevel@tonic-gate 				} else {
19110Sstevel@tonic-gate 					h_priv->mblk.length =
19120Sstevel@tonic-gate 					    current_max_payload;
19130Sstevel@tonic-gate 				}
19140Sstevel@tonic-gate 			}
19150Sstevel@tonic-gate 			s1394_unlock_tree(hal);
19160Sstevel@tonic-gate 			ret = s1394_pending_q_helper(hal, cmd);
19170Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
19180Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
19190Sstevel@tonic-gate 			return (ret);
19200Sstevel@tonic-gate 		}
19210Sstevel@tonic-gate 	}
19220Sstevel@tonic-gate }
19230Sstevel@tonic-gate 
19240Sstevel@tonic-gate /*
19250Sstevel@tonic-gate  * s1394_pending_q_helper()
19260Sstevel@tonic-gate  *    is a "helper" function for s1394_process_pending_q().  It attempts to
19270Sstevel@tonic-gate  *    resend commands, handling error conditions whenever necessary.
19280Sstevel@tonic-gate  */
19290Sstevel@tonic-gate static boolean_t
s1394_pending_q_helper(s1394_hal_t * hal,cmd1394_cmd_t * cmd)19300Sstevel@tonic-gate s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
19310Sstevel@tonic-gate {
19320Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
19330Sstevel@tonic-gate 	int		 err;
19340Sstevel@tonic-gate 	int		 ret;
19350Sstevel@tonic-gate 
19360Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_helper_enter,
19370Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
19380Sstevel@tonic-gate 
19390Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
19400Sstevel@tonic-gate 
19410Sstevel@tonic-gate 	/* Get the Services Layer private area */
19420Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate 	/* Put cmd on outstanding request Q */
19450Sstevel@tonic-gate 	s1394_insert_q_asynch_cmd(hal, cmd);
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate 	/* Send command out again */
19480Sstevel@tonic-gate 	ret = s1394_xfer_asynch_command(hal, cmd, &err);
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
19510Sstevel@tonic-gate 		if (err == CMD1394_ESTALE_GENERATION) {
19520Sstevel@tonic-gate 			/* Remove cmd outstanding req Q */
19530Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
19540Sstevel@tonic-gate 			s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19570Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
19580Sstevel@tonic-gate 			return (B_TRUE);
19590Sstevel@tonic-gate 		} else {
19600Sstevel@tonic-gate 			/* Remove cmd from outstanding request Q */
19610Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
19620Sstevel@tonic-gate 
19630Sstevel@tonic-gate 			s_priv->cmd_in_use = B_FALSE;
19640Sstevel@tonic-gate 
19650Sstevel@tonic-gate 			cmd->cmd_result = err;
19660Sstevel@tonic-gate 
19670Sstevel@tonic-gate 			/* Is this a blocking command? */
19680Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_BLOCKING) {
19690Sstevel@tonic-gate 				/* Unblock waiting command */
19700Sstevel@tonic-gate 				mutex_enter(&s_priv->blocking_mutex);
19710Sstevel@tonic-gate 				s_priv->blocking_flag = B_TRUE;
19720Sstevel@tonic-gate 				cv_signal(&s_priv->blocking_cv);
19730Sstevel@tonic-gate 				mutex_exit(&s_priv->blocking_mutex);
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19760Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
19770Sstevel@tonic-gate 				return (B_FALSE);
19780Sstevel@tonic-gate 			}
19790Sstevel@tonic-gate 
19800Sstevel@tonic-gate 			/* Call target completion_callback() */
19810Sstevel@tonic-gate 			if (cmd->completion_callback != NULL) {
19820Sstevel@tonic-gate 				cmd->completion_callback(cmd);
19830Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19840Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
19850Sstevel@tonic-gate 				return (B_FALSE);
19860Sstevel@tonic-gate 			} else {
19870Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19880Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
19890Sstevel@tonic-gate 				return (B_FALSE);
19900Sstevel@tonic-gate 			}
19910Sstevel@tonic-gate 		}
19920Sstevel@tonic-gate 	}
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19950Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
19960Sstevel@tonic-gate 	return (B_FALSE);
19970Sstevel@tonic-gate }
19980Sstevel@tonic-gate 
19990Sstevel@tonic-gate /*
20000Sstevel@tonic-gate  * s1394_process_split_lock()
20010Sstevel@tonic-gate  *    is a "helper" function for the s1394_handle_lock() callback.  Its
20020Sstevel@tonic-gate  *    job is to perform whatever manipulation is required for the given
20030Sstevel@tonic-gate  *    request.
20040Sstevel@tonic-gate  */
20050Sstevel@tonic-gate static int
s1394_process_split_lock(cmd1394_cmd_t * cmd,cmd1394_cmd_t * target_cmd)20060Sstevel@tonic-gate s1394_process_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd)
20070Sstevel@tonic-gate {
20080Sstevel@tonic-gate 	uint64_t	 new_value64;
20090Sstevel@tonic-gate 	uint64_t	 data_value64;
20100Sstevel@tonic-gate 	uint64_t	 arg_value64;
20110Sstevel@tonic-gate 	uint64_t	 old_value64;
20120Sstevel@tonic-gate 	uint64_t	 temp_value64;
20130Sstevel@tonic-gate 	uint32_t	 new_value32;
20140Sstevel@tonic-gate 	uint32_t	 data_value32;
20150Sstevel@tonic-gate 	uint32_t	 arg_value32;
20160Sstevel@tonic-gate 	uint32_t	 old_value32;
20170Sstevel@tonic-gate 	uint32_t	 temp_value32;
20180Sstevel@tonic-gate 
20190Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_process_split_lock_enter,
20200Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
20210Sstevel@tonic-gate 
20220Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
20230Sstevel@tonic-gate 		old_value32  = cmd->cmd_u.l32.old_value;
20240Sstevel@tonic-gate 		data_value32 = target_cmd->cmd_u.l32.data_value;
20250Sstevel@tonic-gate 		arg_value32  = target_cmd->cmd_u.l32.arg_value;
20260Sstevel@tonic-gate 
20270Sstevel@tonic-gate 		/* Lock type specific */
20280Sstevel@tonic-gate 		switch (target_cmd->cmd_u.l32.lock_type) {
20290Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_AND:
20300Sstevel@tonic-gate 			new_value32 = old_value32 & data_value32;
20310Sstevel@tonic-gate 			break;
20320Sstevel@tonic-gate 
20330Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_OR:
20340Sstevel@tonic-gate 			new_value32 = old_value32 | data_value32;
20350Sstevel@tonic-gate 			break;
20360Sstevel@tonic-gate 
20370Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_XOR:
20380Sstevel@tonic-gate 			new_value32 = old_value32 ^ data_value32;
20390Sstevel@tonic-gate 			break;
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate 		case CMD1394_LOCK_INCREMENT:
20420Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20430Sstevel@tonic-gate 			new_value32 = old_value32 + 1;
20440Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20450Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20460Sstevel@tonic-gate 			break;
20470Sstevel@tonic-gate 
20480Sstevel@tonic-gate 		case CMD1394_LOCK_DECREMENT:
20490Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20500Sstevel@tonic-gate 			new_value32 = old_value32 - 1;
20510Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20520Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20530Sstevel@tonic-gate 			break;
20540Sstevel@tonic-gate 
20550Sstevel@tonic-gate 		case CMD1394_LOCK_ADD:
20560Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20570Sstevel@tonic-gate 			new_value32 = old_value32 + data_value32;
20580Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20590Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20600Sstevel@tonic-gate 			break;
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate 		case CMD1394_LOCK_SUBTRACT:
20630Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20640Sstevel@tonic-gate 			new_value32 = old_value32 - data_value32;
20650Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20660Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20670Sstevel@tonic-gate 			break;
20680Sstevel@tonic-gate 
20690Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_ADD:
20700Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20710Sstevel@tonic-gate 			temp_value32 = (old_value32 + data_value32);
20720Sstevel@tonic-gate 			if ((temp_value32 >= old_value32) &&
20730Sstevel@tonic-gate 			    (temp_value32 <= arg_value32)) {
20740Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
20750Sstevel@tonic-gate 				old_value32 = T1394_DATA32(old_value32);
20760Sstevel@tonic-gate 			} else {
20770Sstevel@tonic-gate 				/* Failed threshold add */
20780Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value =
20790Sstevel@tonic-gate 				    T1394_DATA32(cmd->cmd_u.l32.old_value);
20800Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
20810Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
20820Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
20830Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
20840Sstevel@tonic-gate 				return (DDI_FAILURE);
20850Sstevel@tonic-gate 			}
20860Sstevel@tonic-gate 			break;
20870Sstevel@tonic-gate 
20880Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_SUBTRACT:
20890Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20900Sstevel@tonic-gate 			temp_value32 = (old_value32 - data_value32);
20910Sstevel@tonic-gate 			if ((old_value32 >= data_value32) &&
20920Sstevel@tonic-gate 			    (temp_value32 >= arg_value32)) {
20930Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
20940Sstevel@tonic-gate 				old_value32 = T1394_DATA32(old_value32);
20950Sstevel@tonic-gate 			} else {
20960Sstevel@tonic-gate 				/* Failed threshold subtract */
20970Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value =
20980Sstevel@tonic-gate 				    T1394_DATA32(cmd->cmd_u.l32.old_value);
20990Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
21000Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
21010Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
21020Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
21030Sstevel@tonic-gate 				return (DDI_FAILURE);
21040Sstevel@tonic-gate 			}
21050Sstevel@tonic-gate 			break;
21060Sstevel@tonic-gate 
21070Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_ADD:
21080Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21090Sstevel@tonic-gate 			temp_value32 = (old_value32 + data_value32);
21100Sstevel@tonic-gate 			if ((temp_value32 < old_value32) ||
21110Sstevel@tonic-gate 			    (temp_value32 > arg_value32))
21120Sstevel@tonic-gate 				new_value32 = T1394_DATA32(arg_value32);
21130Sstevel@tonic-gate 			else
21140Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
21150Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21160Sstevel@tonic-gate 			break;
21170Sstevel@tonic-gate 
21180Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_SUBTRACT:
21190Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21200Sstevel@tonic-gate 			temp_value32 = (old_value32 - data_value32);
21210Sstevel@tonic-gate 			if ((data_value32 > old_value32) ||
21220Sstevel@tonic-gate 			    (temp_value32 < arg_value32))
21230Sstevel@tonic-gate 				new_value32 = T1394_DATA32(arg_value32);
21240Sstevel@tonic-gate 			else
21250Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
21260Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21270Sstevel@tonic-gate 			break;
21280Sstevel@tonic-gate 		}
21290Sstevel@tonic-gate 
21300Sstevel@tonic-gate 		/* Send compare-swap lock request */
21310Sstevel@tonic-gate 		cmd->cmd_u.l32.arg_value  = old_value32;
21320Sstevel@tonic-gate 		cmd->cmd_u.l32.data_value = new_value32;
21330Sstevel@tonic-gate 	} else {
21340Sstevel@tonic-gate 		old_value64  = cmd->cmd_u.l64.old_value;
21350Sstevel@tonic-gate 		data_value64 = target_cmd->cmd_u.l64.data_value;
21360Sstevel@tonic-gate 		arg_value64  = target_cmd->cmd_u.l64.arg_value;
21370Sstevel@tonic-gate 
21380Sstevel@tonic-gate 		/* Lock type specific */
21390Sstevel@tonic-gate 		switch (target_cmd->cmd_u.l64.lock_type) {
21400Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_AND:
21410Sstevel@tonic-gate 			new_value64 = old_value64 & data_value64;
21420Sstevel@tonic-gate 			break;
21430Sstevel@tonic-gate 
21440Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_OR:
21450Sstevel@tonic-gate 			new_value64 = old_value64 | data_value64;
21460Sstevel@tonic-gate 			break;
21470Sstevel@tonic-gate 
21480Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_XOR:
21490Sstevel@tonic-gate 			new_value64 = old_value64 ^ data_value64;
21500Sstevel@tonic-gate 			break;
21510Sstevel@tonic-gate 
21520Sstevel@tonic-gate 		case CMD1394_LOCK_INCREMENT:
21530Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21540Sstevel@tonic-gate 			new_value64 = old_value64 + 1;
21550Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21560Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21570Sstevel@tonic-gate 			break;
21580Sstevel@tonic-gate 
21590Sstevel@tonic-gate 		case CMD1394_LOCK_DECREMENT:
21600Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21610Sstevel@tonic-gate 			new_value64 = old_value64 - 1;
21620Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21630Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21640Sstevel@tonic-gate 			break;
21650Sstevel@tonic-gate 
21660Sstevel@tonic-gate 		case CMD1394_LOCK_ADD:
21670Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21680Sstevel@tonic-gate 			new_value64 = old_value64 + data_value64;
21690Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21700Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21710Sstevel@tonic-gate 			break;
21720Sstevel@tonic-gate 
21730Sstevel@tonic-gate 		case CMD1394_LOCK_SUBTRACT:
21740Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21750Sstevel@tonic-gate 			new_value64 = old_value64 - data_value64;
21760Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21770Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21780Sstevel@tonic-gate 			break;
21790Sstevel@tonic-gate 
21800Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_ADD:
21810Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21820Sstevel@tonic-gate 			temp_value64 = (old_value64 + data_value64);
21830Sstevel@tonic-gate 			if ((temp_value64 >= old_value64) &&
21840Sstevel@tonic-gate 			    (temp_value64 <= arg_value64)) {
21850Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
21860Sstevel@tonic-gate 				old_value64 = T1394_DATA64(old_value64);
21870Sstevel@tonic-gate 			} else {
21880Sstevel@tonic-gate 				/* Failed threshold add */
21890Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value =
21900Sstevel@tonic-gate 				    T1394_DATA64(cmd->cmd_u.l64.old_value);
21910Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
21920Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
21930Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
21940Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
21950Sstevel@tonic-gate 				return (DDI_FAILURE);
21960Sstevel@tonic-gate 			}
21970Sstevel@tonic-gate 			break;
21980Sstevel@tonic-gate 
21990Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_SUBTRACT:
22000Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22010Sstevel@tonic-gate 			temp_value64 = (old_value64 - data_value64);
22020Sstevel@tonic-gate 			if ((old_value64 >= data_value64) &&
22030Sstevel@tonic-gate 			    (temp_value64 >= arg_value64)) {
22040Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
22050Sstevel@tonic-gate 				old_value64 = T1394_DATA64(old_value64);
22060Sstevel@tonic-gate 			} else {
22070Sstevel@tonic-gate 				/* Failed threshold subtract */
22080Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value =
22090Sstevel@tonic-gate 				    T1394_DATA64(cmd->cmd_u.l64.old_value);
22100Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
22110Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
22120Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
22130Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
22140Sstevel@tonic-gate 				return (DDI_FAILURE);
22150Sstevel@tonic-gate 			}
22160Sstevel@tonic-gate 			break;
22170Sstevel@tonic-gate 
22180Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_ADD:
22190Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22200Sstevel@tonic-gate 			temp_value64 = (old_value64 + data_value64);
22210Sstevel@tonic-gate 			if ((temp_value64 < old_value64) ||
22220Sstevel@tonic-gate 			    (temp_value64 > arg_value64))
22230Sstevel@tonic-gate 				new_value64 = T1394_DATA64(arg_value64);
22240Sstevel@tonic-gate 			else
22250Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
22260Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22270Sstevel@tonic-gate 			break;
22280Sstevel@tonic-gate 
22290Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_SUBTRACT:
22300Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22310Sstevel@tonic-gate 			temp_value64 = (old_value64 - data_value64);
22320Sstevel@tonic-gate 			if ((data_value64 > old_value64) ||
22330Sstevel@tonic-gate 			    (temp_value64 < arg_value64))
22340Sstevel@tonic-gate 				new_value64 = T1394_DATA64(arg_value64);
22350Sstevel@tonic-gate 			else
22360Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
22370Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22380Sstevel@tonic-gate 			break;
22390Sstevel@tonic-gate 		}
22400Sstevel@tonic-gate 
22410Sstevel@tonic-gate 		/* Send compare-swap lock request */
22420Sstevel@tonic-gate 		cmd->cmd_u.l64.arg_value  = old_value64;
22430Sstevel@tonic-gate 		cmd->cmd_u.l64.data_value = new_value64;
22440Sstevel@tonic-gate 	}
22450Sstevel@tonic-gate 
22460Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_process_split_lock_exit,
22470Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
22480Sstevel@tonic-gate 	return (DDI_SUCCESS);
22490Sstevel@tonic-gate }
22500Sstevel@tonic-gate 
22510Sstevel@tonic-gate /*
22520Sstevel@tonic-gate  * s1394_finish_split_lock()
22530Sstevel@tonic-gate  *    is another "helper" function for the s1394_handle_lock() callback.
22540Sstevel@tonic-gate  *    Its job is to finish up whatever lock request procesing is necessary.
22550Sstevel@tonic-gate  */
22560Sstevel@tonic-gate static int
s1394_finish_split_lock(cmd1394_cmd_t * cmd,cmd1394_cmd_t * target_cmd)22570Sstevel@tonic-gate s1394_finish_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd)
22580Sstevel@tonic-gate {
22590Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
22600Sstevel@tonic-gate 	uint64_t	 tmp_value64;
22610Sstevel@tonic-gate 	uint32_t	 tmp_value32;
22620Sstevel@tonic-gate 
22630Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_finish_split_lock_enter,
22640Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
22650Sstevel@tonic-gate 
22660Sstevel@tonic-gate 	/* Get the Services Layer private area */
22670Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
22680Sstevel@tonic-gate 
22690Sstevel@tonic-gate 	if (((cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) &&
22700Sstevel@tonic-gate 	    (cmd->cmd_u.l32.old_value == cmd->cmd_u.l32.arg_value)) ||
22710Sstevel@tonic-gate 	    ((cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) &&
22720Sstevel@tonic-gate 	    (cmd->cmd_u.l64.old_value == cmd->cmd_u.l64.arg_value))) {
22730Sstevel@tonic-gate 
22740Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
22750Sstevel@tonic-gate 			switch (cmd->cmd_u.l32.lock_type) {
22760Sstevel@tonic-gate 			case CMD1394_LOCK_INCREMENT:
22770Sstevel@tonic-gate 			case CMD1394_LOCK_DECREMENT:
22780Sstevel@tonic-gate 			case CMD1394_LOCK_ADD:
22790Sstevel@tonic-gate 			case CMD1394_LOCK_SUBTRACT:
22800Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_ADD:
22810Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_SUBTRACT:
22820Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_ADD:
22830Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_SUBTRACT:
22840Sstevel@tonic-gate 				tmp_value32 = cmd->cmd_u.l32.old_value;
22850Sstevel@tonic-gate 				tmp_value32 = T1394_DATA32(tmp_value32);
22860Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value = tmp_value32;
22870Sstevel@tonic-gate 				break;
22880Sstevel@tonic-gate 			default:
22890Sstevel@tonic-gate 				tmp_value32 = cmd->cmd_u.l32.old_value;
22900Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value = tmp_value32;
22910Sstevel@tonic-gate 				break;
22920Sstevel@tonic-gate 			}
22930Sstevel@tonic-gate 		} else {
22940Sstevel@tonic-gate 			switch (cmd->cmd_u.l64.lock_type) {
22950Sstevel@tonic-gate 			case CMD1394_LOCK_INCREMENT:
22960Sstevel@tonic-gate 			case CMD1394_LOCK_DECREMENT:
22970Sstevel@tonic-gate 			case CMD1394_LOCK_ADD:
22980Sstevel@tonic-gate 			case CMD1394_LOCK_SUBTRACT:
22990Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_ADD:
23000Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_SUBTRACT:
23010Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_ADD:
23020Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_SUBTRACT:
23030Sstevel@tonic-gate 				tmp_value64 = cmd->cmd_u.l64.old_value;
23040Sstevel@tonic-gate 				tmp_value64 = T1394_DATA64(tmp_value64);
23050Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value = tmp_value64;
23060Sstevel@tonic-gate 				break;
23070Sstevel@tonic-gate 			default:
23080Sstevel@tonic-gate 				tmp_value64 = cmd->cmd_u.l64.old_value;
23090Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value = tmp_value64;
23100Sstevel@tonic-gate 				break;
23110Sstevel@tonic-gate 			}
23120Sstevel@tonic-gate 		}
23130Sstevel@tonic-gate 		/* Set status */
23140Sstevel@tonic-gate 		target_cmd->cmd_result = CMD1394_CMDSUCCESS;
23150Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit,
23160Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
23170Sstevel@tonic-gate 		return (DDI_SUCCESS);
23180Sstevel@tonic-gate 	} else {
23190Sstevel@tonic-gate 		if (s_priv->temp_num_retries > 0) {
23200Sstevel@tonic-gate 			/* Decrement retry count */
23210Sstevel@tonic-gate 			s_priv->temp_num_retries--;
23220Sstevel@tonic-gate 
23230Sstevel@tonic-gate 			/* Reset lock_req_step */
23240Sstevel@tonic-gate 			s_priv->lock_req_step = 0;
23250Sstevel@tonic-gate 
23260Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_finish_split_lock_start_over,
23270Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
23280Sstevel@tonic-gate 			/* Resend... start at step 0 again */
23290Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit,
23300Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
23310Sstevel@tonic-gate 			return (DDI_FAILURE);
23320Sstevel@tonic-gate 		} else {
23330Sstevel@tonic-gate 			/* Failed... RETRIES_EXCEEDED */
23340Sstevel@tonic-gate 			target_cmd->cmd_result = CMD1394_ERETRIES_EXCEEDED;
23350Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit,
23360Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
23370Sstevel@tonic-gate 			return (DDI_SUCCESS);
23380Sstevel@tonic-gate 		}
23390Sstevel@tonic-gate 	}
23400Sstevel@tonic-gate }
2341