xref: /titanic_50/usr/src/uts/common/io/1394/s1394_asynch.c (revision 80a70ef316c0bf76271850dd8713d36bd4e96192)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*80a70ef3Sap25164  * Common Development and Distribution License (the "License").
6*80a70ef3Sap25164  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*80a70ef3Sap25164  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * s1394_asynch.c
307c478bd9Sstevel@tonic-gate  *    1394 Services Layer Asynchronous Communications Routines
317c478bd9Sstevel@tonic-gate  *    These routines handle all of the tasks relating to asynch commands
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <sys/conf.h>
357c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
377c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
40*80a70ef3Sap25164 #include <sys/disp.h>
417c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h>
447c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h>
457c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
467c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1394.h>
477c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1212.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate static void s1394_handle_lock(cmd1394_cmd_t *cmd);
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static cmd1394_cmd_t *s1394_pending_q_remove(s1394_hal_t *hal);
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate static boolean_t s1394_process_pending_q(s1394_hal_t *hal);
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate static boolean_t s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd);
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate static int s1394_process_split_lock(cmd1394_cmd_t *cmd,
587c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *target_cmd);
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate static int s1394_finish_split_lock(cmd1394_cmd_t *cmd,
617c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *target_cmd);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * s1394_alloc_cmd()
657c478bd9Sstevel@tonic-gate  *    is used to allocate a command for a target or for a HAL.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate int
s1394_alloc_cmd(s1394_hal_t * hal,uint_t flags,cmd1394_cmd_t ** cmdp)687c478bd9Sstevel@tonic-gate s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
717c478bd9Sstevel@tonic-gate 	void		 *hal_overhead;
727c478bd9Sstevel@tonic-gate 	uint_t		 cmd_size;
737c478bd9Sstevel@tonic-gate 	int		 alloc_sleep;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_alloc_cmd_enter, S1394_TNF_SL_STACK, "");
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	alloc_sleep = (flags & T1394_ALLOC_CMD_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	if ((alloc_sleep == KM_SLEEP) &&
80*80a70ef3Sap25164 	    (servicing_interrupt())) {
817c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_alloc_cmd_error, S1394_TNF_SL_ATREQ_ERROR,
827c478bd9Sstevel@tonic-gate 		    "", tnf_string, msg, "Tried to sleep in intr context");
837c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
847c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
857c478bd9Sstevel@tonic-gate 		ASSERT(alloc_sleep != KM_SLEEP);	/* fail */
867c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
877c478bd9Sstevel@tonic-gate 	}
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	/* either FCP command or response, but not both */
907c478bd9Sstevel@tonic-gate 	if ((flags &
917c478bd9Sstevel@tonic-gate 	    (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) ==
927c478bd9Sstevel@tonic-gate 	    (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) {
937c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_alloc_cmd_error, S1394_TNF_SL_ATREQ_ERROR,
947c478bd9Sstevel@tonic-gate 		    "", tnf_string, msg, "Both FCP cmd and resp flags");
957c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
967c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
977c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	*cmdp = kmem_cache_alloc(hal->hal_kmem_cachep, alloc_sleep);
1017c478bd9Sstevel@tonic-gate 	if (*cmdp == NULL) {
1027c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
1037c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_STACK, "");
1047c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 	cmd_size = sizeof (cmd1394_cmd_t) +
1077c478bd9Sstevel@tonic-gate 	    sizeof (s1394_cmd_priv_t) + hal->halinfo.hal_overhead;
1087c478bd9Sstevel@tonic-gate 	bzero((void *)*cmdp, cmd_size);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	(*cmdp)->cmd_version = T1394_VERSION_V1;
1117c478bd9Sstevel@tonic-gate 	(*cmdp)->cmd_result = CMD1394_NOSTATUS;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
1147c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	/* Set extension type */
1177c478bd9Sstevel@tonic-gate 	if (flags & T1394_ALLOC_CMD_FCP_COMMAND) {
1187c478bd9Sstevel@tonic-gate 		s1394_fa_init_cmd(s_priv, S1394_FA_TYPE_FCP_CTL);
1197c478bd9Sstevel@tonic-gate 	} else if (flags & T1394_ALLOC_CMD_FCP_RESPONSE) {
1207c478bd9Sstevel@tonic-gate 		s1394_fa_init_cmd(s_priv, S1394_FA_TYPE_FCP_TGT);
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	/* Set up the hal_overhead ptr in the hal_cmd_private */
1247c478bd9Sstevel@tonic-gate 	hal_overhead = (uchar_t *)s_priv + sizeof (s1394_cmd_priv_t);
1257c478bd9Sstevel@tonic-gate 	s_priv->hal_cmd_private.hal_overhead = (void *)hal_overhead;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_alloc_cmd, S1394_TNF_SL_STACK, "",
1287c478bd9Sstevel@tonic-gate 	    tnf_opaque, cmd, *cmdp);
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/* kstats - number of cmd allocs */
1317c478bd9Sstevel@tonic-gate 	hal->hal_kstats->cmd_alloc++;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit, S1394_TNF_SL_STACK, "");
1347c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate  * s1394_free_cmd()
1397c478bd9Sstevel@tonic-gate  *    is used to free a command that had been previously allocated by
1407c478bd9Sstevel@tonic-gate  *    s1394_alloc_cmd().
1417c478bd9Sstevel@tonic-gate  */
1427c478bd9Sstevel@tonic-gate int
s1394_free_cmd(s1394_hal_t * hal,cmd1394_cmd_t ** cmdp)1437c478bd9Sstevel@tonic-gate s1394_free_cmd(s1394_hal_t *hal, cmd1394_cmd_t **cmdp)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_free_cmd_enter, S1394_TNF_SL_STACK, "");
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
1507c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	/* Check that command isn't in use */
1537c478bd9Sstevel@tonic-gate 	if (s_priv->cmd_in_use == B_TRUE) {
1547c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_free_cmd_error, S1394_TNF_SL_ERROR, "",
1557c478bd9Sstevel@tonic-gate 		    tnf_string, msg,  "Attempted to free an in-use command");
1567c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_free_cmd_exit, S1394_TNF_SL_STACK, "");
1577c478bd9Sstevel@tonic-gate 		ASSERT(s_priv->cmd_in_use == B_FALSE);
1587c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_free_cmd, S1394_TNF_SL_STACK, "",
1617c478bd9Sstevel@tonic-gate 	    tnf_opaque, cmd, *cmdp);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	/* kstats - number of cmd allocs */
1647c478bd9Sstevel@tonic-gate 	kmem_cache_free(hal->hal_kmem_cachep, *cmdp);
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	/* Command pointer is set to NULL before returning */
1677c478bd9Sstevel@tonic-gate 	*cmdp = NULL;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	/* kstats - number of cmd frees */
1707c478bd9Sstevel@tonic-gate 	hal->hal_kstats->cmd_free++;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_free_cmd_exit, S1394_TNF_SL_STACK, "");
1737c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate  * s1394_xfer_asynch_command()
1787c478bd9Sstevel@tonic-gate  *    is used to send an asynch command down to the HAL.  Based upon the type
1797c478bd9Sstevel@tonic-gate  *    of command that is being sent, the appropriate HAL function is called.
1807c478bd9Sstevel@tonic-gate  *    Command failures are handled be returning an error and/or shutting down
1817c478bd9Sstevel@tonic-gate  *    the HAL, depending on the severity of the error.
1827c478bd9Sstevel@tonic-gate  */
1837c478bd9Sstevel@tonic-gate int
s1394_xfer_asynch_command(s1394_hal_t * hal,cmd1394_cmd_t * cmd,int * err)1847c478bd9Sstevel@tonic-gate s1394_xfer_asynch_command(s1394_hal_t *hal, cmd1394_cmd_t *cmd, int *err)
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t  *s_priv;
1877c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t  *h_priv;
1887c478bd9Sstevel@tonic-gate 	s1394_hal_state_t state;
1897c478bd9Sstevel@tonic-gate 	dev_info_t	  *dip;
1907c478bd9Sstevel@tonic-gate 	int		  result_from_hal;
1917c478bd9Sstevel@tonic-gate 	int		  ret;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_enter,
1947c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
1997c478bd9Sstevel@tonic-gate 	state = hal->hal_state;
2007c478bd9Sstevel@tonic-gate 	if (((state != S1394_HAL_NORMAL) && (state != S1394_HAL_RESET)) ||
2017c478bd9Sstevel@tonic-gate 	    (hal->disable_requests_bit == 1)) {
2027c478bd9Sstevel@tonic-gate 		*err = s1394_HAL_asynch_error(hal, cmd, state);
2037c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
2047c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
2057c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
2067c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
2117c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
2147c478bd9Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	/* kstats - number of AT requests sent */
2177c478bd9Sstevel@tonic-gate 	switch (cmd->cmd_type) {
2187c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_QUAD:
2197c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_quad_rd++;
2207c478bd9Sstevel@tonic-gate 		break;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_BLOCK:
2237c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_blk_rd++;
2247c478bd9Sstevel@tonic-gate 		break;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_QUAD:
2277c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_quad_wr++;
2287c478bd9Sstevel@tonic-gate 		break;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_BLOCK:
2317c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_blk_wr++;
2327c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_blk_wr_size += h_priv->mblk.length;
2337c478bd9Sstevel@tonic-gate 		break;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_32:
2367c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_lock32++;
2377c478bd9Sstevel@tonic-gate 		break;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_64:
2407c478bd9Sstevel@tonic-gate 		hal->hal_kstats->atreq_lock64++;
2417c478bd9Sstevel@tonic-gate 		break;
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	switch (s_priv->cmd_priv_xfer_type) {
2457c478bd9Sstevel@tonic-gate 	/* Call the HAL's read entry point */
2467c478bd9Sstevel@tonic-gate 	case S1394_CMD_READ:
2477c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).read(hal->halinfo.hal_private,
2487c478bd9Sstevel@tonic-gate 		    (cmd1394_cmd_t *)cmd,
2497c478bd9Sstevel@tonic-gate 		    (h1394_cmd_priv_t *)&s_priv->hal_cmd_private,
2507c478bd9Sstevel@tonic-gate 		    &result_from_hal);
2517c478bd9Sstevel@tonic-gate 		break;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	/* Call the HAL's write entry point */
2547c478bd9Sstevel@tonic-gate 	case S1394_CMD_WRITE:
2557c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).write(hal->halinfo.hal_private,
2567c478bd9Sstevel@tonic-gate 		    (cmd1394_cmd_t *)cmd,
2577c478bd9Sstevel@tonic-gate 		    (h1394_cmd_priv_t *)&s_priv->hal_cmd_private,
2587c478bd9Sstevel@tonic-gate 		    &result_from_hal);
2597c478bd9Sstevel@tonic-gate 		break;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	/* Call the HAL's lock entry point */
2627c478bd9Sstevel@tonic-gate 	case S1394_CMD_LOCK:
2637c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).lock(hal->halinfo.hal_private,
2647c478bd9Sstevel@tonic-gate 		    (cmd1394_cmd_t *)cmd,
2657c478bd9Sstevel@tonic-gate 		    (h1394_cmd_priv_t *)&s_priv->hal_cmd_private,
2667c478bd9Sstevel@tonic-gate 		    &result_from_hal);
2677c478bd9Sstevel@tonic-gate 		break;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	default:
2707c478bd9Sstevel@tonic-gate 		*err = CMD1394_EUNKNOWN_ERROR;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_xfer_asynch_command_error,
2737c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg,
2747c478bd9Sstevel@tonic-gate 		    "Invalid command type specified");
2757c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
2767c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
2777c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_return_from_HAL,
2817c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	if (ret == DDI_FAILURE) {
2847c478bd9Sstevel@tonic-gate 		switch (result_from_hal) {
2857c478bd9Sstevel@tonic-gate 		case H1394_STATUS_EMPTY_TLABEL:
2867c478bd9Sstevel@tonic-gate 			/* Out of TLABELs - Unable to send AT req */
2877c478bd9Sstevel@tonic-gate 			*err = CMD1394_ENO_ATREQ;
2887c478bd9Sstevel@tonic-gate 			break;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 		case H1394_STATUS_INVALID_BUSGEN:
2917c478bd9Sstevel@tonic-gate 			/* Out of TLABELs - Unable to send AT req */
2927c478bd9Sstevel@tonic-gate 			*err = CMD1394_ESTALE_GENERATION;
2937c478bd9Sstevel@tonic-gate 			break;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		case H1394_STATUS_NOMORE_SPACE:
2967c478bd9Sstevel@tonic-gate 			/* No more space on HAL's HW queue */
2977c478bd9Sstevel@tonic-gate 			*err = CMD1394_ENO_ATREQ;
2987c478bd9Sstevel@tonic-gate 			break;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		case H1394_STATUS_INTERNAL_ERROR:
3017c478bd9Sstevel@tonic-gate 			dip = hal->halinfo.dip;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 			/* An unexpected error in the HAL */
3047c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
3057c478bd9Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 			/* Disable the HAL */
3087c478bd9Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 			*err = CMD1394_EFATAL_ERROR;
3117c478bd9Sstevel@tonic-gate 			break;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		default:
3147c478bd9Sstevel@tonic-gate 			dip = hal->halinfo.dip;
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 			/* An unexpected error in the HAL */
3177c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
3187c478bd9Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 			/* Disable the HAL */
3217c478bd9Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 			*err = CMD1394_EFATAL_ERROR;
3247c478bd9Sstevel@tonic-gate 			break;
3257c478bd9Sstevel@tonic-gate 		}
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 		TNF_PROBE_2_DEBUG(s1394_xfer_asynch_command_exit,
3287c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "",
3297c478bd9Sstevel@tonic-gate 		    tnf_int, result_from_hal, result_from_hal,
3307c478bd9Sstevel@tonic-gate 		    tnf_int, err, *err);
3317c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/* No errors, return success */
3357c478bd9Sstevel@tonic-gate 	*err = CMD1394_NOSTATUS;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
3387c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
3397c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate  * s1394_setup_asynch_command()
3447c478bd9Sstevel@tonic-gate  *    is used to setup an asynch command to be sent down to the HAL and out
3457c478bd9Sstevel@tonic-gate  *    onto the bus.  This function handles setting up the destination address
3467c478bd9Sstevel@tonic-gate  *    (if necessary), speed, max_payload, putting the command onto the
3477c478bd9Sstevel@tonic-gate  *    outstanding Q list, and any other things that must be done prior to
3487c478bd9Sstevel@tonic-gate  *    calling the HAL.
3497c478bd9Sstevel@tonic-gate  */
3507c478bd9Sstevel@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)3517c478bd9Sstevel@tonic-gate s1394_setup_asynch_command(s1394_hal_t *hal, s1394_target_t *target,
3527c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd, uint32_t xfer_type, int *err)
3537c478bd9Sstevel@tonic-gate {
3547c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t  *s_priv;
3557c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t  *h_priv;
3567c478bd9Sstevel@tonic-gate 	uint64_t	  node;
3577c478bd9Sstevel@tonic-gate 	uint32_t	  from_node;
3587c478bd9Sstevel@tonic-gate 	uint32_t	  to_node;
3597c478bd9Sstevel@tonic-gate 	uint32_t	  bus_capabilities;
3607c478bd9Sstevel@tonic-gate 	uint_t		  current_max_payload;
3617c478bd9Sstevel@tonic-gate 	uint_t		  max_rec;
3627c478bd9Sstevel@tonic-gate 	uint_t		  max_blk;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_enter,
3657c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	switch (cmd->cmd_type) {
3707c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_QUAD:
3717c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_QUAD:
3727c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_BLOCK:
3737c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_BLOCK:
3747c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_32:
3757c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_64:
3767c478bd9Sstevel@tonic-gate 		break;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	default:
3797c478bd9Sstevel@tonic-gate 		*err = CMD1394_EINVALID_COMMAND;
3807c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_setup_asynch_command_error,
3817c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg,
3827c478bd9Sstevel@tonic-gate 		    "Invalid command type specified");
3837c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
3847c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
3857c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3867c478bd9Sstevel@tonic-gate 	}
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* Check for potential address roll-over */
3897c478bd9Sstevel@tonic-gate 	if (s1394_address_rollover(cmd) != B_FALSE) {
3907c478bd9Sstevel@tonic-gate 		*err = CMD1394_EADDRESS_ERROR;
3917c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
3927c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
3937c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
3977c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	/* Set up who sent command on which hal */
4007c478bd9Sstevel@tonic-gate 	s_priv->sent_by_target	= (s1394_target_t *)target;
4017c478bd9Sstevel@tonic-gate 	s_priv->sent_on_hal	= (s1394_hal_t *)hal;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	/* Set up command transfer type */
4047c478bd9Sstevel@tonic-gate 	s_priv->cmd_priv_xfer_type = xfer_type;
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) {
4077c478bd9Sstevel@tonic-gate 		/* Compare the current generation from the HAL struct */
4087c478bd9Sstevel@tonic-gate 		/* to the one given by the target */
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		/* Speed is to be filled in from speed map */
4117c478bd9Sstevel@tonic-gate 		from_node = IEEE1394_NODE_NUM(hal->node_id);
4127c478bd9Sstevel@tonic-gate 		to_node	  = IEEE1394_ADDR_PHY_ID(cmd->cmd_addr);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 		if (cmd->bus_generation != hal->generation_count) {
4157c478bd9Sstevel@tonic-gate 			*err = CMD1394_ESTALE_GENERATION;
4167c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4177c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4187c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	} else {
4227c478bd9Sstevel@tonic-gate 		/* Set the generation */
4237c478bd9Sstevel@tonic-gate 		cmd->bus_generation = hal->generation_count;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 		/* If not OVERRIDE_ADDR, then target may not be NULL */
4267c478bd9Sstevel@tonic-gate 		ASSERT(target != NULL);
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 		rw_enter(&hal->target_list_rwlock, RW_READER);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 		if ((target->target_state & S1394_TARG_GONE) != 0 ||
4317c478bd9Sstevel@tonic-gate 		    target->on_node == NULL) {
4327c478bd9Sstevel@tonic-gate 			rw_exit(&hal->target_list_rwlock);
4337c478bd9Sstevel@tonic-gate 			*err = CMD1394_EDEVICE_REMOVED;
4347c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4357c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4367c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4377c478bd9Sstevel@tonic-gate 		}
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 		ASSERT((target->target_state & S1394_TARG_GONE) == 0);
4407c478bd9Sstevel@tonic-gate 		node = target->on_node->node_num;
4417c478bd9Sstevel@tonic-gate 		rw_exit(&hal->target_list_rwlock);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 		/* Mask in the top 16-bits */
4447c478bd9Sstevel@tonic-gate 		cmd->cmd_addr = (cmd->cmd_addr & IEEE1394_ADDR_OFFSET_MASK);
4457c478bd9Sstevel@tonic-gate 		cmd->cmd_addr = (cmd->cmd_addr |
4467c478bd9Sstevel@tonic-gate 		    (node << IEEE1394_ADDR_PHY_ID_SHIFT));
4477c478bd9Sstevel@tonic-gate 		cmd->cmd_addr = (cmd->cmd_addr | IEEE1394_ADDR_BUS_ID_MASK);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		/* Speed is to be filled in from speed map */
4507c478bd9Sstevel@tonic-gate 		from_node = IEEE1394_NODE_NUM(hal->node_id);
4517c478bd9Sstevel@tonic-gate 		to_node = (uint32_t)node;
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
4557c478bd9Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/* Copy the generation into the HAL's private field */
4587c478bd9Sstevel@tonic-gate 	h_priv->bus_generation = cmd->bus_generation;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	/* Fill in the nodeID */
4617c478bd9Sstevel@tonic-gate 	cmd->nodeID = (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >>
4627c478bd9Sstevel@tonic-gate 	    IEEE1394_ADDR_NODE_ID_SHIFT;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) {
4657c478bd9Sstevel@tonic-gate 		if (cmd->cmd_speed > IEEE1394_S400) {
4667c478bd9Sstevel@tonic-gate 			*err = CMD1394_EINVALID_COMMAND;
4677c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4687c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4697c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		} else {
4727c478bd9Sstevel@tonic-gate 			s_priv->hal_cmd_private.speed = (int)cmd->cmd_speed;
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	} else {
4767c478bd9Sstevel@tonic-gate 		/* Speed is to be filled in from speed map */
4777c478bd9Sstevel@tonic-gate 		s_priv->hal_cmd_private.speed = (int)s1394_speed_map_get(hal,
4787c478bd9Sstevel@tonic-gate 		    from_node, to_node);
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	/* Is it a block request? */
4827c478bd9Sstevel@tonic-gate 	if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
4837c478bd9Sstevel@tonic-gate 	    (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 		if (cmd->cmd_u.b.data_block == NULL) {
4867c478bd9Sstevel@tonic-gate 			*err = CMD1394_ENULL_MBLK;
4877c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4887c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4897c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4907c478bd9Sstevel@tonic-gate 		}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 		/* Also need to check for MBLK_TOO_SMALL */
4937c478bd9Sstevel@tonic-gate 		if (s1394_mblk_too_small(cmd) != B_FALSE) {
4947c478bd9Sstevel@tonic-gate 			*err = CMD1394_EMBLK_TOO_SMALL;
4957c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
4967c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
4977c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		/* Initialize bytes_transferred to zero */
5017c478bd9Sstevel@tonic-gate 		cmd->cmd_u.b.bytes_transferred = 0;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 		/* Handle the MAX_PAYLOAD size */
5047c478bd9Sstevel@tonic-gate 		if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) {
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 			current_max_payload = 512 <<
5077c478bd9Sstevel@tonic-gate 			    (s_priv->hal_cmd_private.speed);
5087c478bd9Sstevel@tonic-gate 			if (hal->topology_tree[to_node].cfgrom) {
5097c478bd9Sstevel@tonic-gate 				bus_capabilities =
5107c478bd9Sstevel@tonic-gate 				    hal->topology_tree[to_node].cfgrom[
5117c478bd9Sstevel@tonic-gate 					IEEE1212_NODE_CAP_QUAD];
5127c478bd9Sstevel@tonic-gate 				max_rec = (bus_capabilities &
5137c478bd9Sstevel@tonic-gate 				    IEEE1394_BIB_MAXREC_MASK) >>
5147c478bd9Sstevel@tonic-gate 				    IEEE1394_BIB_MAXREC_SHIFT;
5157c478bd9Sstevel@tonic-gate 			} else {
5167c478bd9Sstevel@tonic-gate 				max_rec = 0;
5177c478bd9Sstevel@tonic-gate 			}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 			if ((max_rec > 0) && (max_rec < 14)) {
5207c478bd9Sstevel@tonic-gate 				max_blk = 1 << (max_rec + 1);
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 			} else {
5237c478bd9Sstevel@tonic-gate 				/* These are either unspecified or reserved */
5247c478bd9Sstevel@tonic-gate 				max_blk = 4;
5257c478bd9Sstevel@tonic-gate 			}
5267c478bd9Sstevel@tonic-gate 			if (max_blk < current_max_payload)
5277c478bd9Sstevel@tonic-gate 				current_max_payload = max_blk;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 		} else {
5307c478bd9Sstevel@tonic-gate 			rw_enter(&hal->target_list_rwlock, RW_READER);
5317c478bd9Sstevel@tonic-gate 			current_max_payload = target->current_max_payload;
5327c478bd9Sstevel@tonic-gate 			rw_exit(&hal->target_list_rwlock);
5337c478bd9Sstevel@tonic-gate 		}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		if (cmd->cmd_options & CMD1394_OVERRIDE_MAX_PAYLOAD) {
5367c478bd9Sstevel@tonic-gate 			if (current_max_payload > cmd->cmd_u.b.max_payload)
5377c478bd9Sstevel@tonic-gate 				current_max_payload = cmd->cmd_u.b.max_payload;
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 		h_priv->mblk.curr_mblk = cmd->cmd_u.b.data_block;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK) {
5437c478bd9Sstevel@tonic-gate 			h_priv->mblk.curr_offset =
5447c478bd9Sstevel@tonic-gate 			    cmd->cmd_u.b.data_block->b_rptr;
5457c478bd9Sstevel@tonic-gate 		} else {
5467c478bd9Sstevel@tonic-gate 			h_priv->mblk.curr_offset =
5477c478bd9Sstevel@tonic-gate 			    cmd->cmd_u.b.data_block->b_wptr;
5487c478bd9Sstevel@tonic-gate 		}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 		if (cmd->cmd_u.b.blk_length > current_max_payload) {
5517c478bd9Sstevel@tonic-gate 			h_priv->mblk.length = current_max_payload;
5527c478bd9Sstevel@tonic-gate 			s_priv->data_remaining = cmd->cmd_u.b.blk_length;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		} else {
5557c478bd9Sstevel@tonic-gate 			h_priv->mblk.length = cmd->cmd_u.b.blk_length;
5567c478bd9Sstevel@tonic-gate 			s_priv->data_remaining = cmd->cmd_u.b.blk_length;
5577c478bd9Sstevel@tonic-gate 		}
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	/* Mark command as being used */
5617c478bd9Sstevel@tonic-gate 	s_priv->cmd_in_use = B_TRUE;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	/* Put command on the HAL's outstanding request Q */
5647c478bd9Sstevel@tonic-gate 	s1394_insert_q_asynch_cmd(hal, cmd);
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
5677c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
5687c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate /*
5727c478bd9Sstevel@tonic-gate  * s1394_insert_q_asynch_cmd()
5737c478bd9Sstevel@tonic-gate  *    is used to insert a given command structure onto a HAL's outstanding
5747c478bd9Sstevel@tonic-gate  *    asynch queue.
5757c478bd9Sstevel@tonic-gate  */
5767c478bd9Sstevel@tonic-gate void
s1394_insert_q_asynch_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)5777c478bd9Sstevel@tonic-gate s1394_insert_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
5787c478bd9Sstevel@tonic-gate {
5797c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
5807c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
5817c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *temp_cmd;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_enter,
5847c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->outstanding_q_mutex);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
5897c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	/* Is the outstanding request queue empty? */
5927c478bd9Sstevel@tonic-gate 	if ((hal->outstanding_q_head == NULL) &&
5937c478bd9Sstevel@tonic-gate 	    (hal->outstanding_q_tail == NULL)) {
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 		hal->outstanding_q_head = (cmd1394_cmd_t *)cmd;
5967c478bd9Sstevel@tonic-gate 		hal->outstanding_q_tail = (cmd1394_cmd_t *)cmd;
5977c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
5987c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	} else {
6017c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_next = hal->outstanding_q_head;
6027c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 		temp_cmd = (cmd1394_cmd_t *)hal->outstanding_q_head;
6057c478bd9Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd +
6067c478bd9Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
6077c478bd9Sstevel@tonic-gate 		c_priv->cmd_priv_prev = (cmd1394_cmd_t *)cmd;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 		hal->outstanding_q_head = (cmd1394_cmd_t *)cmd;
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->outstanding_q_mutex);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_exit,
6157c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate /*
6197c478bd9Sstevel@tonic-gate  * s1394_remove_q_asynch_cmd()
6207c478bd9Sstevel@tonic-gate  *    is used to remove a given command structure from a HAL's outstanding
6217c478bd9Sstevel@tonic-gate  *    asynch queue.
6227c478bd9Sstevel@tonic-gate  */
6237c478bd9Sstevel@tonic-gate void
s1394_remove_q_asynch_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)6247c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
6277c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
6287c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *prev_cmd;
6297c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *next_cmd;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_enter,
6327c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->outstanding_q_mutex);
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
6377c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev;
6407c478bd9Sstevel@tonic-gate 	next_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_next;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
6437c478bd9Sstevel@tonic-gate 	s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	if (prev_cmd != NULL) {
6467c478bd9Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)prev_cmd +
6477c478bd9Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
6487c478bd9Sstevel@tonic-gate 		c_priv->cmd_priv_next = (cmd1394_cmd_t *)next_cmd;
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	} else {
6517c478bd9Sstevel@tonic-gate 		if (hal->outstanding_q_head == (cmd1394_cmd_t *)cmd)
6527c478bd9Sstevel@tonic-gate 			hal->outstanding_q_head = (cmd1394_cmd_t *)next_cmd;
6537c478bd9Sstevel@tonic-gate 	}
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	if (next_cmd != NULL) {
6567c478bd9Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)next_cmd +
6577c478bd9Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
6587c478bd9Sstevel@tonic-gate 		c_priv->cmd_priv_prev = (cmd1394_cmd_t *)prev_cmd;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	} else {
6617c478bd9Sstevel@tonic-gate 		if (hal->outstanding_q_tail == (cmd1394_cmd_t *)cmd)
6627c478bd9Sstevel@tonic-gate 			hal->outstanding_q_tail = (cmd1394_cmd_t *)prev_cmd;
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->outstanding_q_mutex);
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_exit,
6687c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate /*
6727c478bd9Sstevel@tonic-gate  * s1394_atreq_cmd_complete()
6737c478bd9Sstevel@tonic-gate  *    is called by h1394_cmd_is_complete() when an AT request has completed.
6747c478bd9Sstevel@tonic-gate  *    Based upon a command's completion status, s1394_atreq_cmd_complete()
6757c478bd9Sstevel@tonic-gate  *    determines whether to call the target (or unblock), put the command onto
6767c478bd9Sstevel@tonic-gate  *    the pending Q to be sent out later, or to resend the command
6777c478bd9Sstevel@tonic-gate  *    (multi-part command).
6787c478bd9Sstevel@tonic-gate  */
6797c478bd9Sstevel@tonic-gate void
s1394_atreq_cmd_complete(s1394_hal_t * hal,cmd1394_cmd_t * req,int status)6807c478bd9Sstevel@tonic-gate s1394_atreq_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *req, int status)
6817c478bd9Sstevel@tonic-gate {
6827c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
6837c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
6847c478bd9Sstevel@tonic-gate 	dev_info_t	 *dip;
6857c478bd9Sstevel@tonic-gate 	int		 ret;
6867c478bd9Sstevel@tonic-gate 	int		 cmd_result;
6877c478bd9Sstevel@tonic-gate 	int		 err;
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_enter,
6907c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
6937c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(req);
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/* If not an ack_complete... */
6967c478bd9Sstevel@tonic-gate 	if (status != H1394_CMD_SUCCESS) {
6977c478bd9Sstevel@tonic-gate 		/* kstats - number of failure AT responses */
6987c478bd9Sstevel@tonic-gate 		switch (req->cmd_type) {
6997c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_QUAD:
7007c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atresp_quad_rd_fail++;
7017c478bd9Sstevel@tonic-gate 			break;
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_BLOCK:
7047c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atresp_blk_rd_fail++;
7057c478bd9Sstevel@tonic-gate 			break;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_QUAD:
7087c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atresp_quad_wr_fail++;
7097c478bd9Sstevel@tonic-gate 			break;
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_BLOCK:
7127c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atresp_blk_wr_fail++;
7137c478bd9Sstevel@tonic-gate 			break;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_32:
7167c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atresp_lock32_fail++;
7177c478bd9Sstevel@tonic-gate 			break;
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_64:
7207c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atresp_lock64_fail++;
7217c478bd9Sstevel@tonic-gate 			break;
7227c478bd9Sstevel@tonic-gate 		}
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 		switch (status) {
7267c478bd9Sstevel@tonic-gate 		/* evt_missing_ack */
7277c478bd9Sstevel@tonic-gate 		case H1394_CMD_ETIMEOUT:
7287c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_ETIMEOUT;
7297c478bd9Sstevel@tonic-gate 			break;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		/* evt_flushed */
7327c478bd9Sstevel@tonic-gate 		case H1394_CMD_EBUSRESET:
7337c478bd9Sstevel@tonic-gate 			/* Move request to pending Q if cancel on */
7347c478bd9Sstevel@tonic-gate 			/* reset is not set */
7357c478bd9Sstevel@tonic-gate 			if (req->cmd_options & CMD1394_CANCEL_ON_BUS_RESET) {
7367c478bd9Sstevel@tonic-gate 				cmd_result = CMD1394_EBUSRESET;
7377c478bd9Sstevel@tonic-gate 				break;
7387c478bd9Sstevel@tonic-gate 			}
7397c478bd9Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, req);
7407c478bd9Sstevel@tonic-gate 			s1394_pending_q_insert(hal, req, S1394_PENDING_Q_REAR);
7417c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
7427c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
7437c478bd9Sstevel@tonic-gate 			return;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 		/* ack_busy_X */
7467c478bd9Sstevel@tonic-gate 		/* ack_busy_A */
7477c478bd9Sstevel@tonic-gate 		/* ack_busy_B */
7487c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_BUSY:
7497c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_EDEVICE_BUSY;
7507c478bd9Sstevel@tonic-gate 			break;
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 		/* ack_data_error */
7537c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDATA_ERROR:
7547c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_EDATA_ERROR;
7557c478bd9Sstevel@tonic-gate 			break;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 		/* ack_type_error */
7587c478bd9Sstevel@tonic-gate 		case H1394_CMD_ETYPE_ERROR:
7597c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_ETYPE_ERROR;
7607c478bd9Sstevel@tonic-gate 			break;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 		/* resp_address_error */
7637c478bd9Sstevel@tonic-gate 		/* ack_address_error */
7647c478bd9Sstevel@tonic-gate 		case H1394_CMD_EADDR_ERROR:
7657c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_EADDRESS_ERROR;
7667c478bd9Sstevel@tonic-gate 			break;
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 		/* resp_conflict_error */
7697c478bd9Sstevel@tonic-gate 		/* ack_conflict_error */
7707c478bd9Sstevel@tonic-gate 		case H1394_CMD_ERSRC_CONFLICT:
7717c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_ERSRC_CONFLICT;
7727c478bd9Sstevel@tonic-gate 			break;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 		/* ack_tardy */
7757c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_POWERUP:
7767c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_EDEVICE_BUSY;
7777c478bd9Sstevel@tonic-gate 			break;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		/* device errors (bad tcodes, ACKs, etc...) */
7807c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_ERROR:
7817c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_EDEVICE_ERROR;
7827c478bd9Sstevel@tonic-gate 			break;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		/* Unknown error type */
7857c478bd9Sstevel@tonic-gate 		case H1394_CMD_EUNKNOWN_ERROR:
7867c478bd9Sstevel@tonic-gate 			cmd_result = CMD1394_EUNKNOWN_ERROR;
7877c478bd9Sstevel@tonic-gate 			break;
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 		/* Unrecognized error */
7907c478bd9Sstevel@tonic-gate 		default:
7917c478bd9Sstevel@tonic-gate 			dip = hal->halinfo.dip;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 			/* An unexpected error in the HAL */
7947c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
7957c478bd9Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 			/* Disable the HAL */
7987c478bd9Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 			TNF_PROBE_2(s1394_atreq_cmd_complete_error,
8017c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg,
8027c478bd9Sstevel@tonic-gate 			    "Unrecognized cmd status code",
8037c478bd9Sstevel@tonic-gate 			    tnf_int, status, status);
8047c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8057c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
8067c478bd9Sstevel@tonic-gate 			return;
8077c478bd9Sstevel@tonic-gate 		}
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 		/* Remove command from the HAL's outstanding request Q */
8107c478bd9Sstevel@tonic-gate 		s1394_remove_q_asynch_cmd(hal, req);
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 		s_priv->cmd_in_use = B_FALSE;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 		req->cmd_result = cmd_result;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 		/* Is this a blocking command? */
8177c478bd9Sstevel@tonic-gate 		if (req->cmd_options & CMD1394_BLOCKING) {
8187c478bd9Sstevel@tonic-gate 			/* Unblock the waiting command */
8197c478bd9Sstevel@tonic-gate 			mutex_enter(&s_priv->blocking_mutex);
8207c478bd9Sstevel@tonic-gate 			s_priv->blocking_flag = B_TRUE;
8217c478bd9Sstevel@tonic-gate 			cv_signal(&s_priv->blocking_cv);
8227c478bd9Sstevel@tonic-gate 			mutex_exit(&s_priv->blocking_mutex);
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8257c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
8267c478bd9Sstevel@tonic-gate 			return;
8277c478bd9Sstevel@tonic-gate 		}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 		/* Call the target's completion_callback() */
8307c478bd9Sstevel@tonic-gate 		if (req->completion_callback != NULL) {
8317c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback,
8327c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
8337c478bd9Sstevel@tonic-gate 			req->completion_callback(req);
8347c478bd9Sstevel@tonic-gate 		}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8377c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
8387c478bd9Sstevel@tonic-gate 		return;
8397c478bd9Sstevel@tonic-gate 	}
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	/* Successful unless otherwise modified */
8427c478bd9Sstevel@tonic-gate 	err = CMD1394_CMDSUCCESS;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	if ((req->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
8457c478bd9Sstevel@tonic-gate 	    (req->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 		/* Get a pointer to the HAL private struct */
8487c478bd9Sstevel@tonic-gate 		h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 		/* Update data_remaining */
8517c478bd9Sstevel@tonic-gate 		s_priv->data_remaining -= h_priv->mblk.length;
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 		/* Increment bytes_transferred */
8547c478bd9Sstevel@tonic-gate 		req->cmd_u.b.bytes_transferred += h_priv->mblk.length;
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 		if (req->cmd_type == CMD1394_ASYNCH_RD_BLOCK)
8577c478bd9Sstevel@tonic-gate 			hal->hal_kstats->atreq_blk_rd_size +=
8587c478bd9Sstevel@tonic-gate 			    h_priv->mblk.length;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 		/* Is there still more to send? */
8617c478bd9Sstevel@tonic-gate 		if (s_priv->data_remaining > 0) {
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 			/* Setup the new mblk and offset */
8647c478bd9Sstevel@tonic-gate 			h_priv->mblk.curr_mblk = h_priv->mblk.next_mblk;
8657c478bd9Sstevel@tonic-gate 			h_priv->mblk.curr_offset = h_priv->mblk.next_offset;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 			/* Update destination address */
8687c478bd9Sstevel@tonic-gate 			if (!(req->cmd_options &
8697c478bd9Sstevel@tonic-gate 			    CMD1394_DISABLE_ADDR_INCREMENT)) {
8707c478bd9Sstevel@tonic-gate 				req->cmd_addr += h_priv->mblk.length;
8717c478bd9Sstevel@tonic-gate 			}
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 			/*
8747c478bd9Sstevel@tonic-gate 			 * Use the current MAX_PAYLOAD size.  This value
8757c478bd9Sstevel@tonic-gate 			 * doesn't need to be recalculated because we must
8767c478bd9Sstevel@tonic-gate 			 * be in the same generation on the bus, else we
8777c478bd9Sstevel@tonic-gate 			 * would have seen a bus reset error.
8787c478bd9Sstevel@tonic-gate 			 */
8797c478bd9Sstevel@tonic-gate 			if (s_priv->data_remaining < h_priv->mblk.length) {
8807c478bd9Sstevel@tonic-gate 				h_priv->mblk.length = s_priv->data_remaining;
8817c478bd9Sstevel@tonic-gate 			}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 			/* Send command out again */
8847c478bd9Sstevel@tonic-gate 			ret = s1394_xfer_asynch_command(hal, req, &err);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 			if (ret == DDI_SUCCESS) {
8877c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8887c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
8897c478bd9Sstevel@tonic-gate 				return;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 			} else if (err == CMD1394_ESTALE_GENERATION) {
8927c478bd9Sstevel@tonic-gate 				/* Remove cmd from outstanding request Q */
8937c478bd9Sstevel@tonic-gate 				s1394_remove_q_asynch_cmd(hal, req);
8947c478bd9Sstevel@tonic-gate 				s1394_pending_q_insert(hal, req,
8957c478bd9Sstevel@tonic-gate 				    S1394_PENDING_Q_REAR);
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
8987c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
8997c478bd9Sstevel@tonic-gate 				return;
9007c478bd9Sstevel@tonic-gate 			}
9017c478bd9Sstevel@tonic-gate 		}
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	/* Remove command from the HAL's outstanding request Q */
9057c478bd9Sstevel@tonic-gate 	s1394_remove_q_asynch_cmd(hal, req);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	s_priv->cmd_in_use = B_FALSE;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 	/* Set status */
9107c478bd9Sstevel@tonic-gate 	req->cmd_result = err;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	/* Is this a blocking command? */
9137c478bd9Sstevel@tonic-gate 	if (req->cmd_options & CMD1394_BLOCKING) {
9147c478bd9Sstevel@tonic-gate 		/* Unblock the waiting command */
9157c478bd9Sstevel@tonic-gate 		mutex_enter(&s_priv->blocking_mutex);
9167c478bd9Sstevel@tonic-gate 		s_priv->blocking_flag = B_TRUE;
9177c478bd9Sstevel@tonic-gate 		cv_signal(&s_priv->blocking_cv);
9187c478bd9Sstevel@tonic-gate 		mutex_exit(&s_priv->blocking_mutex);
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
9217c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
9227c478bd9Sstevel@tonic-gate 		return;
9237c478bd9Sstevel@tonic-gate 	}
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	/* Set status and call completion_callback() */
9267c478bd9Sstevel@tonic-gate 	if (req->completion_callback != NULL) {
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback,
9297c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 		req->completion_callback(req);
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
9347c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
9357c478bd9Sstevel@tonic-gate 		return;
9367c478bd9Sstevel@tonic-gate 	}
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
9397c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate /*
9437c478bd9Sstevel@tonic-gate  * s1394_atresp_cmd_complete()
9447c478bd9Sstevel@tonic-gate  *    is similar to s1394_atreq_cmd_complete(). It is also called by
9457c478bd9Sstevel@tonic-gate  *    h1394_cmd_is_complete(), but when an AT response has completed.
9467c478bd9Sstevel@tonic-gate  *    Again, based upon the command's completion status,
9477c478bd9Sstevel@tonic-gate  *    s1394_atresp_cmd_complete() determines whether to call the target or
9487c478bd9Sstevel@tonic-gate  *    to simply cleanup the command and return.
9497c478bd9Sstevel@tonic-gate  */
9507c478bd9Sstevel@tonic-gate void
s1394_atresp_cmd_complete(s1394_hal_t * hal,cmd1394_cmd_t * resp,int status)9517c478bd9Sstevel@tonic-gate s1394_atresp_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *resp, int status)
9527c478bd9Sstevel@tonic-gate {
9537c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
9547c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
9557c478bd9Sstevel@tonic-gate 	dev_info_t	 *dip;
9567c478bd9Sstevel@tonic-gate 	boolean_t	 valid_addr_blk;
9577c478bd9Sstevel@tonic-gate 	int		 target_status;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_enter,
9607c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "");
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	target_status = CMD1394_CMDSUCCESS;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	/* If not an ack_complete */
9657c478bd9Sstevel@tonic-gate 	if (status != H1394_CMD_SUCCESS) {
9667c478bd9Sstevel@tonic-gate 		switch (status) {
9677c478bd9Sstevel@tonic-gate 		/* evt_missing_ack */
9687c478bd9Sstevel@tonic-gate 		case H1394_CMD_ETIMEOUT:
9697c478bd9Sstevel@tonic-gate 			target_status = CMD1394_ETIMEOUT;
9707c478bd9Sstevel@tonic-gate 			break;
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 		/* evt_flushed */
9737c478bd9Sstevel@tonic-gate 		case H1394_CMD_EBUSRESET:
9747c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EBUSRESET;
9757c478bd9Sstevel@tonic-gate 			break;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 		/* ack_busy_X */
9787c478bd9Sstevel@tonic-gate 		/* ack_busy_A */
9797c478bd9Sstevel@tonic-gate 		/* ack_busy_B */
9807c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_BUSY:
9817c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EDEVICE_BUSY;
9827c478bd9Sstevel@tonic-gate 			break;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 		/* ack_data_error */
9857c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDATA_ERROR:
9867c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EDATA_ERROR;
9877c478bd9Sstevel@tonic-gate 			break;
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 		/* ack_type_error */
9907c478bd9Sstevel@tonic-gate 		case H1394_CMD_ETYPE_ERROR:
9917c478bd9Sstevel@tonic-gate 			target_status = CMD1394_ETYPE_ERROR;
9927c478bd9Sstevel@tonic-gate 			break;
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 		/* ack_address_error */
9957c478bd9Sstevel@tonic-gate 		case H1394_CMD_EADDR_ERROR:
9967c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EADDRESS_ERROR;
9977c478bd9Sstevel@tonic-gate 			break;
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 		/* ack_conflict_error */
10007c478bd9Sstevel@tonic-gate 		case H1394_CMD_ERSRC_CONFLICT:
10017c478bd9Sstevel@tonic-gate 			target_status = CMD1394_ERSRC_CONFLICT;
10027c478bd9Sstevel@tonic-gate 			break;
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 		/* ack_tardy */
10057c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_POWERUP:
10067c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EDEVICE_BUSY;
10077c478bd9Sstevel@tonic-gate 			break;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 		/* device errors (bad tcodes, ACKs, etc...) */
10107c478bd9Sstevel@tonic-gate 		case H1394_CMD_EDEVICE_ERROR:
10117c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EDEVICE_ERROR;
10127c478bd9Sstevel@tonic-gate 			break;
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 		/* Unknown error type */
10157c478bd9Sstevel@tonic-gate 		case H1394_CMD_EUNKNOWN_ERROR:
10167c478bd9Sstevel@tonic-gate 			target_status = CMD1394_EUNKNOWN_ERROR;
10177c478bd9Sstevel@tonic-gate 			break;
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 		/* Unrecognized error */
10207c478bd9Sstevel@tonic-gate 		default:
10217c478bd9Sstevel@tonic-gate 			dip = hal->halinfo.dip;
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 			/* An unexpected error in the HAL */
10247c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
10257c478bd9Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 			/* Disable the HAL */
10287c478bd9Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 			TNF_PROBE_2(s1394_atresp_cmd_complete_error,
10317c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
10327c478bd9Sstevel@tonic-gate 			    "Unrecognized cmd status code",
10337c478bd9Sstevel@tonic-gate 			    tnf_int, status, status);
10347c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_exit,
10357c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_STACK, "");
10367c478bd9Sstevel@tonic-gate 			return;
10377c478bd9Sstevel@tonic-gate 		}
10387c478bd9Sstevel@tonic-gate 	}
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
10417c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(resp);
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
10447c478bd9Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 	valid_addr_blk = s_priv->arreq_valid_addr;
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 	if (valid_addr_blk == B_TRUE) {
10497c478bd9Sstevel@tonic-gate 		/* Set the command status */
10507c478bd9Sstevel@tonic-gate 		resp->cmd_result = target_status;
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 		switch (s_priv->cmd_priv_xfer_type) {
10537c478bd9Sstevel@tonic-gate 		case S1394_CMD_READ:
10547c478bd9Sstevel@tonic-gate 		case S1394_CMD_WRITE:
10557c478bd9Sstevel@tonic-gate 		case S1394_CMD_LOCK:
10567c478bd9Sstevel@tonic-gate 			if (resp->completion_callback != NULL) {
10577c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
10587c478bd9Sstevel@tonic-gate 				    s1394_atresp_cmd_complete_do_callback,
10597c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATRESP_STACK, "");
10607c478bd9Sstevel@tonic-gate 				resp->completion_callback(resp);
10617c478bd9Sstevel@tonic-gate 			}
10627c478bd9Sstevel@tonic-gate 			break;
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 		default:
10657c478bd9Sstevel@tonic-gate 			dip = hal->halinfo.dip;
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 			/* An unexpected error in the HAL */
10687c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
10697c478bd9Sstevel@tonic-gate 			    ddi_node_name(dip), ddi_get_instance(dip));
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 			/* Disable the HAL */
10727c478bd9Sstevel@tonic-gate 			s1394_hal_shutdown(hal, B_TRUE);
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 			TNF_PROBE_1(s1394_atresp_cmd_complete_error,
10757c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
10767c478bd9Sstevel@tonic-gate 			    "Unrecognized transfer type");
10777c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_exit,
10787c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_STACK, "");
10797c478bd9Sstevel@tonic-gate 			return;
10807c478bd9Sstevel@tonic-gate 		}
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_call_hal_cmplt,
10847c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "");
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	/* Free the command - Pass it back to the HAL */
10877c478bd9Sstevel@tonic-gate 	HAL_CALL(hal).response_complete(hal->halinfo.hal_private, resp, h_priv);
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_atresp_cmd_complete_exit,
10907c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "", tnf_int, status, target_status);
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate /*
10947c478bd9Sstevel@tonic-gate  * s1394_send_response()
10957c478bd9Sstevel@tonic-gate  *    is used to send a response to an AR request.  Depending on whether the
10967c478bd9Sstevel@tonic-gate  *    request was a broadcast request, a write to posted write address space,
10977c478bd9Sstevel@tonic-gate  *    or some other request, either a response packet is sent, or the command
10987c478bd9Sstevel@tonic-gate  *    is returned to the HAL.  A return value of DDI_SUCCESS means that the
10997c478bd9Sstevel@tonic-gate  *    command has been handled correctly.  It was either successfully sent to
11007c478bd9Sstevel@tonic-gate  *    the HAL, or, if it was posted_write of broadcast, it was freed up.  A
11017c478bd9Sstevel@tonic-gate  *    return value of DDI_FAILURE indicates either a serious error, in which
11027c478bd9Sstevel@tonic-gate  *    case the HAL is shutdown, or a failure returned by the HAL, in which
11037c478bd9Sstevel@tonic-gate  *    case the command is freed up and notice of the failure is returned.
11047c478bd9Sstevel@tonic-gate  */
11057c478bd9Sstevel@tonic-gate int
s1394_send_response(s1394_hal_t * hal,cmd1394_cmd_t * resp)11067c478bd9Sstevel@tonic-gate s1394_send_response(s1394_hal_t *hal, cmd1394_cmd_t *resp)
11077c478bd9Sstevel@tonic-gate {
11087c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
11097c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
11107c478bd9Sstevel@tonic-gate 	dev_info_t	 *dip;
11117c478bd9Sstevel@tonic-gate 	int		 ret;
11127c478bd9Sstevel@tonic-gate 	int		 result;
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_send_response_enter, S1394_TNF_SL_ATRESP_STACK,
11157c478bd9Sstevel@tonic-gate 	    "");
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
11187c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(resp);
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
11217c478bd9Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	/*
11247c478bd9Sstevel@tonic-gate 	 * If request was broadcast or a write request to a posted write
11257c478bd9Sstevel@tonic-gate 	 * address, don't send a response
11267c478bd9Sstevel@tonic-gate 	 */
11277c478bd9Sstevel@tonic-gate 	if ((resp->broadcast == 1) || ((s_priv->posted_write == B_TRUE) &&
11287c478bd9Sstevel@tonic-gate 	    ((resp->cmd_result == CMD1394_ASYNCH_WR_QUAD) ||
11297c478bd9Sstevel@tonic-gate 	    (resp->cmd_result == CMD1394_ASYNCH_WR_BLOCK)))) {
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt,
11327c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 		/* Free the command - Pass it back to the HAL */
11357c478bd9Sstevel@tonic-gate 		HAL_CALL(hal).response_complete(hal->halinfo.hal_private,
11367c478bd9Sstevel@tonic-gate 		    resp, h_priv);
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
11397c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
11407c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
11417c478bd9Sstevel@tonic-gate 	}
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_resp,
11447c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATRESP_STACK, "");
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 	/* kstats - number of failure responses sent */
11477c478bd9Sstevel@tonic-gate 	if (resp->cmd_result != IEEE1394_RESP_COMPLETE) {
11487c478bd9Sstevel@tonic-gate 		switch (resp->cmd_type) {
11497c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_QUAD:
11507c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arresp_quad_rd_fail++;
11517c478bd9Sstevel@tonic-gate 			break;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_RD_BLOCK:
11547c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arresp_blk_rd_fail++;
11557c478bd9Sstevel@tonic-gate 			break;
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_QUAD:
11587c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arresp_quad_wr_fail++;
11597c478bd9Sstevel@tonic-gate 			break;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_WR_BLOCK:
11627c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arresp_blk_wr_fail++;
11637c478bd9Sstevel@tonic-gate 			break;
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_32:
11667c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arresp_lock32_fail++;
11677c478bd9Sstevel@tonic-gate 			break;
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 		case CMD1394_ASYNCH_LOCK_64:
11707c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arresp_lock64_fail++;
11717c478bd9Sstevel@tonic-gate 			break;
11727c478bd9Sstevel@tonic-gate 		}
11737c478bd9Sstevel@tonic-gate 	} else {
11747c478bd9Sstevel@tonic-gate 		if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK)
11757c478bd9Sstevel@tonic-gate 			hal->hal_kstats->arreq_blk_rd_size +=
11767c478bd9Sstevel@tonic-gate 			    resp->cmd_u.b.blk_length;
11777c478bd9Sstevel@tonic-gate 	}
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK) {
11807c478bd9Sstevel@tonic-gate 		h_priv->mblk.curr_mblk = resp->cmd_u.b.data_block;
11817c478bd9Sstevel@tonic-gate 		h_priv->mblk.curr_offset = resp->cmd_u.b.data_block->b_rptr;
11827c478bd9Sstevel@tonic-gate 		h_priv->mblk.length = resp->cmd_u.b.blk_length;
11837c478bd9Sstevel@tonic-gate 	}
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	switch (s_priv->cmd_priv_xfer_type) {
11867c478bd9Sstevel@tonic-gate 	case S1394_CMD_READ:
11877c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).read_response(hal->halinfo.hal_private,
11887c478bd9Sstevel@tonic-gate 		    resp, h_priv, &result);
11897c478bd9Sstevel@tonic-gate 		break;
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 	case S1394_CMD_WRITE:
11927c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).write_response(hal->halinfo.hal_private,
11937c478bd9Sstevel@tonic-gate 		    resp, h_priv, &result);
11947c478bd9Sstevel@tonic-gate 		break;
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 	case S1394_CMD_LOCK:
11977c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).lock_response(hal->halinfo.hal_private,
11987c478bd9Sstevel@tonic-gate 		    resp, h_priv, &result);
11997c478bd9Sstevel@tonic-gate 		break;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 	default:
12027c478bd9Sstevel@tonic-gate 		dip = hal->halinfo.dip;
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 		/* An unexpected error in the HAL */
12057c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
12067c478bd9Sstevel@tonic-gate 		    ddi_node_name(dip), ddi_get_instance(dip));
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 		/* Disable the HAL */
12097c478bd9Sstevel@tonic-gate 		s1394_hal_shutdown(hal, B_TRUE);
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_send_response_error,
12127c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12137c478bd9Sstevel@tonic-gate 		    "Unrecognized transfer type");
12147c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
12157c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
12167c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12177c478bd9Sstevel@tonic-gate 	}
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate 	/* Unable to send a response */
12207c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
12217c478bd9Sstevel@tonic-gate 		if (result == H1394_STATUS_INVALID_BUSGEN) {
12227c478bd9Sstevel@tonic-gate 			TNF_PROBE_1(s1394_send_response_error,
12237c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12247c478bd9Sstevel@tonic-gate 			    "Invalid generation in response");
12257c478bd9Sstevel@tonic-gate 		} else if (result == H1394_STATUS_NOMORE_SPACE) {
12267c478bd9Sstevel@tonic-gate 			TNF_PROBE_1(s1394_send_response_error,
12277c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12287c478bd9Sstevel@tonic-gate 			    "No more space on AT response queue");
12297c478bd9Sstevel@tonic-gate 		} else {
12307c478bd9Sstevel@tonic-gate 			TNF_PROBE_1(s1394_send_response_error,
12317c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
12327c478bd9Sstevel@tonic-gate 			    "Unknown problem in s1394_send_response");
12337c478bd9Sstevel@tonic-gate 		}
12347c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt,
12357c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate 		/* Free the command - Pass it back to the HAL */
12387c478bd9Sstevel@tonic-gate 		HAL_CALL(hal).response_complete(hal->halinfo.hal_private,
12397c478bd9Sstevel@tonic-gate 		    resp, h_priv);
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
12427c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATRESP_STACK, "");
12437c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12447c478bd9Sstevel@tonic-gate 	}
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_send_response_exit, S1394_TNF_SL_ATRESP_STACK,
12477c478bd9Sstevel@tonic-gate 	    "");
12487c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
12497c478bd9Sstevel@tonic-gate }
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate /*
12527c478bd9Sstevel@tonic-gate  * s1394_compare_swap()
12537c478bd9Sstevel@tonic-gate  *    is used by t1394_lock() to send a lock request.  Any of the lock
12547c478bd9Sstevel@tonic-gate  *    requests specified explicitly by the 1394 spec will pass thru here,
12557c478bd9Sstevel@tonic-gate  *    i.e compare-swap, mask-swap, etc.
12567c478bd9Sstevel@tonic-gate  */
12577c478bd9Sstevel@tonic-gate int
s1394_compare_swap(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd)12587c478bd9Sstevel@tonic-gate s1394_compare_swap(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd)
12597c478bd9Sstevel@tonic-gate {
12607c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t	*s_priv;
12617c478bd9Sstevel@tonic-gate 	s1394_hal_state_t	state;
12627c478bd9Sstevel@tonic-gate 	int			err;
12637c478bd9Sstevel@tonic-gate 	int			ret;
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_compare_swap_enter, S1394_TNF_SL_ATREQ_STACK,
12667c478bd9Sstevel@tonic-gate 	    "");
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 	/* Lock the topology tree - protect from bus reset */
12717c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
12727c478bd9Sstevel@tonic-gate 
12737c478bd9Sstevel@tonic-gate 	ret = s1394_setup_asynch_command(hal, target, cmd, S1394_CMD_LOCK,
12747c478bd9Sstevel@tonic-gate 	    &err);
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	/* Unlock the topology tree */
12777c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
12807c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	/* Command has now been put onto the queue! */
12837c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
12847c478bd9Sstevel@tonic-gate 		/* Copy error code into result */
12857c478bd9Sstevel@tonic-gate 		cmd->cmd_result = err;
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(s1394_compare_swap_error_in_setup_asynch,
12887c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "");
12897c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
12907c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
12917c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12927c478bd9Sstevel@tonic-gate 	}
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
12957c478bd9Sstevel@tonic-gate 	state = hal->hal_state;
12967c478bd9Sstevel@tonic-gate 	/* If this command was sent during a bus reset, */
12977c478bd9Sstevel@tonic-gate 	/* then put it onto the pending Q. */
12987c478bd9Sstevel@tonic-gate 	if (state == S1394_HAL_RESET) {
12997c478bd9Sstevel@tonic-gate 		/* Remove cmd from outstanding request Q */
13007c478bd9Sstevel@tonic-gate 		s1394_remove_q_asynch_cmd(hal, cmd);
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 		/* Are we on the bus reset event stack? */
13037c478bd9Sstevel@tonic-gate 		if (s1394_on_br_thread(hal) == B_TRUE) {
13047c478bd9Sstevel@tonic-gate 			/* Blocking commands are not allowed */
13057c478bd9Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_BLOCKING) {
13067c478bd9Sstevel@tonic-gate 				mutex_exit(&hal->topology_tree_mutex);
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 				s_priv->cmd_in_use = B_FALSE;
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 				cmd->cmd_result = CMD1394_EINVALID_CONTEXT;
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate 				TNF_PROBE_1(s1394_compare_swap_error,
13137c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_ERROR, "", tnf_string,
13147c478bd9Sstevel@tonic-gate 				    msg, "CMD1394_BLOCKING in bus reset ctxt");
13157c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13167c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
13177c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
13187c478bd9Sstevel@tonic-gate 			}
13197c478bd9Sstevel@tonic-gate 		}
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 		s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
13227c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 		/* Block (if necessary) */
13257c478bd9Sstevel@tonic-gate 		s1394_block_on_asynch_cmd(cmd);
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK,
13287c478bd9Sstevel@tonic-gate 		    "");
13297c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
13307c478bd9Sstevel@tonic-gate 	}
13317c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	/* Send the command out */
13347c478bd9Sstevel@tonic-gate 	ret = s1394_xfer_asynch_command(hal, cmd, &err);
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
13377c478bd9Sstevel@tonic-gate 		if (err == CMD1394_ESTALE_GENERATION) {
13387c478bd9Sstevel@tonic-gate 			/* Remove cmd from outstanding request Q */
13397c478bd9Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
13407c478bd9Sstevel@tonic-gate 			s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 			/* Block (if necessary) */
13437c478bd9Sstevel@tonic-gate 			s1394_block_on_asynch_cmd(cmd);
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13467c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
13477c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 		} else {
13507c478bd9Sstevel@tonic-gate 			/* Remove cmd from outstanding request Q */
13517c478bd9Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 			s_priv->cmd_in_use = B_FALSE;
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 			/* Copy error code into result */
13567c478bd9Sstevel@tonic-gate 			cmd->cmd_result = err;
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate 			TNF_PROBE_0(s1394_compare_swap_error_in_xfer,
13597c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_ERROR, "");
13607c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13617c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
13627c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
13637c478bd9Sstevel@tonic-gate 		}
13647c478bd9Sstevel@tonic-gate 	} else {
13657c478bd9Sstevel@tonic-gate 		/* Block (if necessary) */
13667c478bd9Sstevel@tonic-gate 		s1394_block_on_asynch_cmd(cmd);
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
13697c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
13707c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
13717c478bd9Sstevel@tonic-gate 	}
13727c478bd9Sstevel@tonic-gate }
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate /*
13757c478bd9Sstevel@tonic-gate  * s1394_split_lock_req()
13767c478bd9Sstevel@tonic-gate  *    is also used by t1394_lock() to send a lock request.  The difference
13777c478bd9Sstevel@tonic-gate  *    is that s1394_split_lock_req() is used to send the software supported
13787c478bd9Sstevel@tonic-gate  *    lock types, i.e. bit_and, bit_or, etc.  These lock requests require
13797c478bd9Sstevel@tonic-gate  *    more than one transaction, typically compare-swap's.
13807c478bd9Sstevel@tonic-gate  */
13817c478bd9Sstevel@tonic-gate int
s1394_split_lock_req(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd)13827c478bd9Sstevel@tonic-gate s1394_split_lock_req(s1394_hal_t *hal, s1394_target_t *target,
13837c478bd9Sstevel@tonic-gate     cmd1394_cmd_t *cmd)
13847c478bd9Sstevel@tonic-gate {
13857c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
13867c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *tmp_cmd;
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_split_lock_req_enter,
13897c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 	/* Allocate a temporary command */
13927c478bd9Sstevel@tonic-gate 	if (s1394_alloc_cmd(hal, T1394_ALLOC_CMD_NOSLEEP, &tmp_cmd) !=
13937c478bd9Sstevel@tonic-gate 	    DDI_SUCCESS) {
13947c478bd9Sstevel@tonic-gate 		cmd->cmd_result = CMD1394_EUNKNOWN_ERROR;
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(s1394_split_lock_req_error_alloc_cmd,
13977c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "");
13987c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
13997c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
14007c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
14017c478bd9Sstevel@tonic-gate 	}
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
14047c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(tmp_cmd);
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	tmp_cmd->completion_callback	= s1394_handle_lock;
14077c478bd9Sstevel@tonic-gate 	tmp_cmd->cmd_callback_arg	= (opaque_t)cmd;
14087c478bd9Sstevel@tonic-gate 	tmp_cmd->cmd_type		= cmd->cmd_type;
14097c478bd9Sstevel@tonic-gate 	tmp_cmd->cmd_addr		= cmd->cmd_addr;
14107c478bd9Sstevel@tonic-gate 	tmp_cmd->cmd_options		= cmd->cmd_options;
14117c478bd9Sstevel@tonic-gate 	tmp_cmd->bus_generation		= cmd->bus_generation;
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	/* The temporary command can not block */
14147c478bd9Sstevel@tonic-gate 	tmp_cmd->cmd_options = tmp_cmd->cmd_options & ~CMD1394_BLOCKING;
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	/* Setup compare-swap with data_value == arg_value (read) */
14177c478bd9Sstevel@tonic-gate 	if (tmp_cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
14187c478bd9Sstevel@tonic-gate 		tmp_cmd->cmd_u.l32.data_value	= 0;
14197c478bd9Sstevel@tonic-gate 		tmp_cmd->cmd_u.l32.arg_value	= 0;
14207c478bd9Sstevel@tonic-gate 		tmp_cmd->cmd_u.l32.lock_type	= CMD1394_LOCK_COMPARE_SWAP;
14217c478bd9Sstevel@tonic-gate 		s_priv->temp_num_retries	= cmd->cmd_u.l32.num_retries;
14227c478bd9Sstevel@tonic-gate 	} else {
14237c478bd9Sstevel@tonic-gate 		tmp_cmd->cmd_u.l64.data_value	= 0;
14247c478bd9Sstevel@tonic-gate 		tmp_cmd->cmd_u.l64.arg_value	= 0;
14257c478bd9Sstevel@tonic-gate 		tmp_cmd->cmd_u.l64.lock_type	= CMD1394_LOCK_COMPARE_SWAP;
14267c478bd9Sstevel@tonic-gate 		s_priv->temp_num_retries	= cmd->cmd_u.l64.num_retries;
14277c478bd9Sstevel@tonic-gate 	}
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 	/* Initialize lock_req_step */
14307c478bd9Sstevel@tonic-gate 	s_priv->lock_req_step = 0;
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area for the target cmd */
14337c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	s_priv->cmd_in_use = B_TRUE;
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 	/* Send the request */
14387c478bd9Sstevel@tonic-gate 	if (s1394_compare_swap(hal, target, tmp_cmd) != DDI_SUCCESS) {
14397c478bd9Sstevel@tonic-gate 		s_priv->cmd_in_use = B_FALSE;
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 		/* Free the temporary command */
14427c478bd9Sstevel@tonic-gate 		if (s1394_free_cmd(hal, &tmp_cmd) != DDI_SUCCESS)
14437c478bd9Sstevel@tonic-gate 			cmd->cmd_result = CMD1394_EUNKNOWN_ERROR;
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
14467c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
14477c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
14487c478bd9Sstevel@tonic-gate 	}
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	/* Block (if necessary) */
14517c478bd9Sstevel@tonic-gate 	s1394_block_on_asynch_cmd(cmd);
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
14547c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
14557c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
14567c478bd9Sstevel@tonic-gate }
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate /*
14597c478bd9Sstevel@tonic-gate  * s1394_handle_lock()
14607c478bd9Sstevel@tonic-gate  *    is the callback for s1394_split_lock_req().  It does all of the real
14617c478bd9Sstevel@tonic-gate  *    work.  Based on the specific lock type all necessary manipulation is
14627c478bd9Sstevel@tonic-gate  *    performed and another compare swap is sent out.  If the transaction
14637c478bd9Sstevel@tonic-gate  *    is unsuccessful, it is retried.
14647c478bd9Sstevel@tonic-gate  */
14657c478bd9Sstevel@tonic-gate static void
s1394_handle_lock(cmd1394_cmd_t * cmd)14667c478bd9Sstevel@tonic-gate s1394_handle_lock(cmd1394_cmd_t *cmd)
14677c478bd9Sstevel@tonic-gate {
14687c478bd9Sstevel@tonic-gate 	s1394_hal_t	 *to_hal;
14697c478bd9Sstevel@tonic-gate 	s1394_target_t	 *target;
14707c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
14717c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *target_cmd;
14727c478bd9Sstevel@tonic-gate 	uint32_t	 lock_req_step;
14737c478bd9Sstevel@tonic-gate 	int		 tcmd_result;
14747c478bd9Sstevel@tonic-gate 	int		 ret;
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_handle_lock_enter, S1394_TNF_SL_ATREQ_STACK,
14787c478bd9Sstevel@tonic-gate 	    "");
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
14817c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate 	lock_req_step = s_priv->lock_req_step;
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	/* Get the target's command */
14867c478bd9Sstevel@tonic-gate 	target_cmd = (cmd1394_cmd_t *)cmd->cmd_callback_arg;
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate 	/* Get the destination of the command */
14897c478bd9Sstevel@tonic-gate 	to_hal = s_priv->sent_on_hal;
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate lock_req_step_0:
14927c478bd9Sstevel@tonic-gate 	/* Is this step 0 completing? */
14937c478bd9Sstevel@tonic-gate 	if (lock_req_step == 0) {
14947c478bd9Sstevel@tonic-gate 		/* Was the request successful? */
14957c478bd9Sstevel@tonic-gate 		if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
14967c478bd9Sstevel@tonic-gate 			/* Do any math, bit ops, or byte-swapping necessary */
14977c478bd9Sstevel@tonic-gate 			ret = s1394_process_split_lock(cmd, target_cmd);
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate 			if (ret != DDI_SUCCESS) {
15007c478bd9Sstevel@tonic-gate 				tcmd_result = target_cmd->cmd_result;
15017c478bd9Sstevel@tonic-gate 				goto lock_req_done;
15027c478bd9Sstevel@tonic-gate 			}
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 			s_priv->lock_req_step = 1;
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 			target = s_priv->sent_by_target;
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 			if (s1394_compare_swap(to_hal, target, cmd) !=
15097c478bd9Sstevel@tonic-gate 			    DDI_SUCCESS) {
15107c478bd9Sstevel@tonic-gate 				tcmd_result = cmd->cmd_result;
15117c478bd9Sstevel@tonic-gate 				goto lock_req_done;
15127c478bd9Sstevel@tonic-gate 			} else {
15137c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
15147c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
15157c478bd9Sstevel@tonic-gate 				return;
15167c478bd9Sstevel@tonic-gate 			}
15177c478bd9Sstevel@tonic-gate 		} else {
15187c478bd9Sstevel@tonic-gate 			/* Command failed for some reason */
15197c478bd9Sstevel@tonic-gate 			tcmd_result = cmd->cmd_result;
15207c478bd9Sstevel@tonic-gate 			goto lock_req_done;
15217c478bd9Sstevel@tonic-gate 		}
15227c478bd9Sstevel@tonic-gate 	} else {	/* lock_req_step == 1 */
15237c478bd9Sstevel@tonic-gate 		/* Was the request successful? */
15247c478bd9Sstevel@tonic-gate 		if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
15257c478bd9Sstevel@tonic-gate 			/* Do whatever's necessary to finish up the lock */
15267c478bd9Sstevel@tonic-gate 			ret = s1394_finish_split_lock(cmd, target_cmd);
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate 			if (ret != DDI_SUCCESS) {
15297c478bd9Sstevel@tonic-gate 				lock_req_step = 0;
15307c478bd9Sstevel@tonic-gate 				goto lock_req_step_0;
15317c478bd9Sstevel@tonic-gate 			} else {
15327c478bd9Sstevel@tonic-gate 				tcmd_result = cmd->cmd_result;
15337c478bd9Sstevel@tonic-gate 				goto lock_req_done;
15347c478bd9Sstevel@tonic-gate 			}
15357c478bd9Sstevel@tonic-gate 		} else {
15367c478bd9Sstevel@tonic-gate 			/* Command failed for some reason */
15377c478bd9Sstevel@tonic-gate 			tcmd_result = cmd->cmd_result;
15387c478bd9Sstevel@tonic-gate 			goto lock_req_done;
15397c478bd9Sstevel@tonic-gate 		}
15407c478bd9Sstevel@tonic-gate 	}
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate lock_req_done:
15437c478bd9Sstevel@tonic-gate 	if (s1394_free_cmd(to_hal, &cmd) != DDI_SUCCESS) {
15447c478bd9Sstevel@tonic-gate 		TNF_PROBE_0(s1394_handle_lock_error_in_freecmd,
15457c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_ERROR, "");
15467c478bd9Sstevel@tonic-gate 	}
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
15497c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(target_cmd);
15507c478bd9Sstevel@tonic-gate 
15517c478bd9Sstevel@tonic-gate 	s_priv->cmd_in_use = B_FALSE;
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	target_cmd->cmd_result = tcmd_result;
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 	/* Is this a blocking command? */
15567c478bd9Sstevel@tonic-gate 	if (target_cmd->cmd_options & CMD1394_BLOCKING) {
15577c478bd9Sstevel@tonic-gate 		/* Unblock the waiting command */
15587c478bd9Sstevel@tonic-gate 		mutex_enter(&s_priv->blocking_mutex);
15597c478bd9Sstevel@tonic-gate 		s_priv->blocking_flag = B_TRUE;
15607c478bd9Sstevel@tonic-gate 		cv_signal(&s_priv->blocking_cv);
15617c478bd9Sstevel@tonic-gate 		mutex_exit(&s_priv->blocking_mutex);
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
15647c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
15657c478bd9Sstevel@tonic-gate 		return;
15667c478bd9Sstevel@tonic-gate 	}
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	/* Call the target's completion_callback() */
15697c478bd9Sstevel@tonic-gate 	if (target_cmd->completion_callback != NULL)
15707c478bd9Sstevel@tonic-gate 		target_cmd->completion_callback(target_cmd);
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
15737c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate /*
15777c478bd9Sstevel@tonic-gate  * s1394_pending_q_insert()
15787c478bd9Sstevel@tonic-gate  *    is used to insert a given command structure onto a HAL's pending queue
15797c478bd9Sstevel@tonic-gate  *    for later processing (after the bus reset).  All commands returned by
15807c478bd9Sstevel@tonic-gate  *    the HAL, are inserted onto the rear of the list (first priority), and
15817c478bd9Sstevel@tonic-gate  *    all other commands (from targets during bus reset) are put onto the front.
15827c478bd9Sstevel@tonic-gate  */
15837c478bd9Sstevel@tonic-gate void
s1394_pending_q_insert(s1394_hal_t * hal,cmd1394_cmd_t * cmd,uint_t flags)15847c478bd9Sstevel@tonic-gate s1394_pending_q_insert(s1394_hal_t *hal, cmd1394_cmd_t *cmd, uint_t flags)
15857c478bd9Sstevel@tonic-gate {
15867c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t *temp_cmd;
15877c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
15887c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
15897c478bd9Sstevel@tonic-gate 
15907c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_insert_enter,
15917c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->pending_q_mutex);
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
15967c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 	/* Is the outstanding request queue empty? */
15997c478bd9Sstevel@tonic-gate 	if ((hal->pending_q_head == NULL) && (hal->pending_q_tail == NULL)) {
16007c478bd9Sstevel@tonic-gate 
16017c478bd9Sstevel@tonic-gate 		hal->pending_q_head = (cmd1394_cmd_t *)cmd;
16027c478bd9Sstevel@tonic-gate 		hal->pending_q_tail = (cmd1394_cmd_t *)cmd;
16037c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16047c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 	} else if (flags == S1394_PENDING_Q_FRONT) {
16077c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_next = hal->pending_q_head;
16087c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 		temp_cmd = (cmd1394_cmd_t *)hal->pending_q_head;
16117c478bd9Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd +
16127c478bd9Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
16137c478bd9Sstevel@tonic-gate 		c_priv->cmd_priv_prev = (cmd1394_cmd_t *)cmd;
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 		hal->pending_q_head = (cmd1394_cmd_t *)cmd;
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	} else {
16187c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_prev = hal->pending_q_tail;
16197c478bd9Sstevel@tonic-gate 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16207c478bd9Sstevel@tonic-gate 
16217c478bd9Sstevel@tonic-gate 		temp_cmd = (cmd1394_cmd_t *)hal->pending_q_tail;
16227c478bd9Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd +
16237c478bd9Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
16247c478bd9Sstevel@tonic-gate 		c_priv->cmd_priv_next = (cmd1394_cmd_t *)cmd;
16257c478bd9Sstevel@tonic-gate 
16267c478bd9Sstevel@tonic-gate 		hal->pending_q_tail = (cmd1394_cmd_t *)cmd;
16277c478bd9Sstevel@tonic-gate 	}
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->pending_q_mutex);
16307c478bd9Sstevel@tonic-gate 
16317c478bd9Sstevel@tonic-gate 	/* kstats - number of pending Q insertions */
16327c478bd9Sstevel@tonic-gate 	hal->hal_kstats->pending_q_insert++;
16337c478bd9Sstevel@tonic-gate 
16347c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_insert_exit,
16357c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
16367c478bd9Sstevel@tonic-gate }
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate /*
16397c478bd9Sstevel@tonic-gate  * s1394_pending_q_remove()
16407c478bd9Sstevel@tonic-gate  *    is used to remove a command structure from a HAL's pending queue for
16417c478bd9Sstevel@tonic-gate  *    processing.
16427c478bd9Sstevel@tonic-gate  */
16437c478bd9Sstevel@tonic-gate static cmd1394_cmd_t *
s1394_pending_q_remove(s1394_hal_t * hal)16447c478bd9Sstevel@tonic-gate s1394_pending_q_remove(s1394_hal_t *hal)
16457c478bd9Sstevel@tonic-gate {
16467c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
16477c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *c_priv;
16487c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *cmd;
16497c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *prev_cmd;
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_remove_enter,
16527c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->pending_q_mutex);
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	cmd = (cmd1394_cmd_t *)hal->pending_q_tail;
16577c478bd9Sstevel@tonic-gate 	if (cmd == NULL) {
16587c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->pending_q_mutex);
16597c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit,
16607c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
16617c478bd9Sstevel@tonic-gate 		return (NULL);
16627c478bd9Sstevel@tonic-gate 	}
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
16657c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev;
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate 	s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
16707c478bd9Sstevel@tonic-gate 	s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16717c478bd9Sstevel@tonic-gate 
16727c478bd9Sstevel@tonic-gate 	if (prev_cmd != NULL) {
16737c478bd9Sstevel@tonic-gate 		c_priv = (s1394_cmd_priv_t *)((uchar_t *)prev_cmd +
16747c478bd9Sstevel@tonic-gate 		    sizeof (cmd1394_cmd_t));
16757c478bd9Sstevel@tonic-gate 		c_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate 	} else {
16787c478bd9Sstevel@tonic-gate 		hal->pending_q_head = (cmd1394_cmd_t *)NULL;
16797c478bd9Sstevel@tonic-gate 	}
16807c478bd9Sstevel@tonic-gate 	hal->pending_q_tail = (cmd1394_cmd_t *)prev_cmd;
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->pending_q_mutex);
16837c478bd9Sstevel@tonic-gate 
16847c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit,
16857c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
16867c478bd9Sstevel@tonic-gate 	return (cmd);
16877c478bd9Sstevel@tonic-gate }
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate /*
16907c478bd9Sstevel@tonic-gate  * s1394_resend_pending_cmds()
16917c478bd9Sstevel@tonic-gate  *    is called when the pending queue is to be flushed.  After most of the
16927c478bd9Sstevel@tonic-gate  *    bus reset processing is completed, the pending commands are sent/resent.
16937c478bd9Sstevel@tonic-gate  */
16947c478bd9Sstevel@tonic-gate void
s1394_resend_pending_cmds(s1394_hal_t * hal)16957c478bd9Sstevel@tonic-gate s1394_resend_pending_cmds(s1394_hal_t *hal)
16967c478bd9Sstevel@tonic-gate {
16977c478bd9Sstevel@tonic-gate 	int done;
16987c478bd9Sstevel@tonic-gate 
16997c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_enter,
17007c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 	do {
17057c478bd9Sstevel@tonic-gate 		done = s1394_process_pending_q(hal);
17067c478bd9Sstevel@tonic-gate 	} while (done == B_FALSE);
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
17097c478bd9Sstevel@tonic-gate 
17107c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_exit,
17117c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
17127c478bd9Sstevel@tonic-gate }
17137c478bd9Sstevel@tonic-gate 
17147c478bd9Sstevel@tonic-gate /*
17157c478bd9Sstevel@tonic-gate  * s1394_process_pending_q()
17167c478bd9Sstevel@tonic-gate  *    is called to send/resend the commands on the pending queue.  All command
17177c478bd9Sstevel@tonic-gate  *    handling can be done here, including notifying the target of failed
17187c478bd9Sstevel@tonic-gate  *    commands, etc.  If it is necessary to recompute the address, speed,
17197c478bd9Sstevel@tonic-gate  *    or max_payload for a command, that can be done here too.  And if there
17207c478bd9Sstevel@tonic-gate  *    is no reason not to continue sending commands from the pending queue,
17217c478bd9Sstevel@tonic-gate  *    then a B_FALSE is returned, else B_TRUE is returned.
17227c478bd9Sstevel@tonic-gate  */
17237c478bd9Sstevel@tonic-gate static boolean_t
s1394_process_pending_q(s1394_hal_t * hal)17247c478bd9Sstevel@tonic-gate s1394_process_pending_q(s1394_hal_t *hal)
17257c478bd9Sstevel@tonic-gate {
17267c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
17277c478bd9Sstevel@tonic-gate 	h1394_cmd_priv_t *h_priv;
17287c478bd9Sstevel@tonic-gate 	s1394_target_t	 *target;
17297c478bd9Sstevel@tonic-gate 	cmd1394_cmd_t	 *cmd;
17307c478bd9Sstevel@tonic-gate 	uint64_t	 node;
17317c478bd9Sstevel@tonic-gate 	uint32_t	 from_node;
17327c478bd9Sstevel@tonic-gate 	uint32_t	 to_node;
17337c478bd9Sstevel@tonic-gate 	uint_t		 current_max_payload;
17347c478bd9Sstevel@tonic-gate 	int		 ret;
17357c478bd9Sstevel@tonic-gate 
17367c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_process_pending_q_enter,
17377c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 	/* Pull a command from the Pending Q */
17427c478bd9Sstevel@tonic-gate 	cmd = s1394_pending_q_remove(hal);
17437c478bd9Sstevel@tonic-gate 
17447c478bd9Sstevel@tonic-gate 	if (cmd == NULL) {
17457c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
17467c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
17477c478bd9Sstevel@tonic-gate 		return (B_TRUE);
17487c478bd9Sstevel@tonic-gate 	}
17497c478bd9Sstevel@tonic-gate 
17507c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
17517c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate 	/* Get a pointer to the HAL private struct */
17547c478bd9Sstevel@tonic-gate 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 	if ((cmd->cmd_options & CMD1394_OVERRIDE_ADDR) ||
17577c478bd9Sstevel@tonic-gate 	    (cmd->cmd_options & CMD1394_CANCEL_ON_BUS_RESET)) {
17587c478bd9Sstevel@tonic-gate 		if (h_priv->bus_generation == hal->generation_count) {
17597c478bd9Sstevel@tonic-gate 			ret = s1394_pending_q_helper(hal, cmd);
17607c478bd9Sstevel@tonic-gate 			return (ret);
17617c478bd9Sstevel@tonic-gate 		} else {
17627c478bd9Sstevel@tonic-gate 
17637c478bd9Sstevel@tonic-gate 			s_priv->cmd_in_use = B_FALSE;
17647c478bd9Sstevel@tonic-gate 
17657c478bd9Sstevel@tonic-gate 			cmd->cmd_result = CMD1394_EBUSRESET;
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate 			/* Is this a blocking command? */
17687c478bd9Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_BLOCKING) {
17697c478bd9Sstevel@tonic-gate 				/* Unblock the waiting command */
17707c478bd9Sstevel@tonic-gate 				mutex_enter(&s_priv->blocking_mutex);
17717c478bd9Sstevel@tonic-gate 				s_priv->blocking_flag = B_TRUE;
17727c478bd9Sstevel@tonic-gate 				cv_signal(&s_priv->blocking_cv);
17737c478bd9Sstevel@tonic-gate 				mutex_exit(&s_priv->blocking_mutex);
17747c478bd9Sstevel@tonic-gate 
17757c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
17767c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
17777c478bd9Sstevel@tonic-gate 				return (B_FALSE);
17787c478bd9Sstevel@tonic-gate 			}
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 			/* Call the target's completion_callback() */
17817c478bd9Sstevel@tonic-gate 			if (cmd->completion_callback != NULL) {
17827c478bd9Sstevel@tonic-gate 				cmd->completion_callback(cmd);
17837c478bd9Sstevel@tonic-gate 			}
17847c478bd9Sstevel@tonic-gate 
17857c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
17867c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
17877c478bd9Sstevel@tonic-gate 			return (B_FALSE);
17887c478bd9Sstevel@tonic-gate 		}
17897c478bd9Sstevel@tonic-gate 	} else {
17907c478bd9Sstevel@tonic-gate 		if (h_priv->bus_generation == hal->generation_count) {
17917c478bd9Sstevel@tonic-gate 			ret = s1394_pending_q_helper(hal, cmd);
17927c478bd9Sstevel@tonic-gate 			return (ret);
17937c478bd9Sstevel@tonic-gate 		} else {
17947c478bd9Sstevel@tonic-gate 			/* Make sure we can get the topology_tree_mutex */
17957c478bd9Sstevel@tonic-gate 			if (s1394_lock_tree(hal) != DDI_SUCCESS)
17967c478bd9Sstevel@tonic-gate 				return (B_TRUE);
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 			/* Set the generation */
17997c478bd9Sstevel@tonic-gate 			cmd->bus_generation = hal->generation_count;
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate 			/* Copy the generation into the HAL's private field */
18027c478bd9Sstevel@tonic-gate 			h_priv->bus_generation = cmd->bus_generation;
18037c478bd9Sstevel@tonic-gate 
18047c478bd9Sstevel@tonic-gate 			target = s_priv->sent_by_target;
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 			/* If not OVERRIDE_ADDR, then target may not be NULL */
18077c478bd9Sstevel@tonic-gate 			ASSERT(target != NULL);
18087c478bd9Sstevel@tonic-gate 
18097c478bd9Sstevel@tonic-gate 			rw_enter(&hal->target_list_rwlock, RW_READER);
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate 			if (((target->target_state & S1394_TARG_GONE) == 0) &&
18127c478bd9Sstevel@tonic-gate 			    (target->on_node != NULL)) {
18137c478bd9Sstevel@tonic-gate 				node = target->on_node->node_num;
18147c478bd9Sstevel@tonic-gate 				rw_exit(&hal->target_list_rwlock);
18157c478bd9Sstevel@tonic-gate 			} else {
18167c478bd9Sstevel@tonic-gate 				rw_exit(&hal->target_list_rwlock);
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 				s_priv->cmd_in_use = B_FALSE;
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 				cmd->cmd_result = CMD1394_EDEVICE_REMOVED;
18217c478bd9Sstevel@tonic-gate 
18227c478bd9Sstevel@tonic-gate 				/* Is this a blocking command? */
18237c478bd9Sstevel@tonic-gate 				if (cmd->cmd_options & CMD1394_BLOCKING) {
18247c478bd9Sstevel@tonic-gate 					s1394_unlock_tree(hal);
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 					/* Unblock the waiting command */
18277c478bd9Sstevel@tonic-gate 					mutex_enter(&s_priv->blocking_mutex);
18287c478bd9Sstevel@tonic-gate 					s_priv->blocking_flag = B_TRUE;
18297c478bd9Sstevel@tonic-gate 					cv_signal(&s_priv->blocking_cv);
18307c478bd9Sstevel@tonic-gate 					mutex_exit(&s_priv->blocking_mutex);
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
18337c478bd9Sstevel@tonic-gate 					    s1394_process_pending_q_exit,
18347c478bd9Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK,
18357c478bd9Sstevel@tonic-gate 					    "");
18367c478bd9Sstevel@tonic-gate 					return (B_FALSE);
18377c478bd9Sstevel@tonic-gate 				}
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 				/* Call the target's completion_callback() */
18407c478bd9Sstevel@tonic-gate 				if (cmd->completion_callback != NULL) {
18417c478bd9Sstevel@tonic-gate 					s1394_unlock_tree(hal);
18427c478bd9Sstevel@tonic-gate 					cmd->completion_callback(cmd);
18437c478bd9Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
18447c478bd9Sstevel@tonic-gate 					    s1394_process_pending_q_exit,
18457c478bd9Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "");
18467c478bd9Sstevel@tonic-gate 					return (B_FALSE);
18477c478bd9Sstevel@tonic-gate 				} else {
18487c478bd9Sstevel@tonic-gate 					s1394_unlock_tree(hal);
18497c478bd9Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
18507c478bd9Sstevel@tonic-gate 					    s1394_process_pending_q_exit,
18517c478bd9Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "");
18527c478bd9Sstevel@tonic-gate 					return (B_FALSE);
18537c478bd9Sstevel@tonic-gate 				}
18547c478bd9Sstevel@tonic-gate 			}
18557c478bd9Sstevel@tonic-gate 
18567c478bd9Sstevel@tonic-gate 			/* Mask in the top 16-bits */
18577c478bd9Sstevel@tonic-gate 			cmd->cmd_addr = cmd->cmd_addr &
18587c478bd9Sstevel@tonic-gate 			    IEEE1394_ADDR_OFFSET_MASK;
18597c478bd9Sstevel@tonic-gate 			cmd->cmd_addr = cmd->cmd_addr |
18607c478bd9Sstevel@tonic-gate 			    (node << IEEE1394_ADDR_PHY_ID_SHIFT);
18617c478bd9Sstevel@tonic-gate 			cmd->cmd_addr = cmd->cmd_addr |
18627c478bd9Sstevel@tonic-gate 			    IEEE1394_ADDR_BUS_ID_MASK;
18637c478bd9Sstevel@tonic-gate 
18647c478bd9Sstevel@tonic-gate 			/* Speed is to be filled in from speed map */
18657c478bd9Sstevel@tonic-gate 			from_node = IEEE1394_NODE_NUM(hal->node_id);
18667c478bd9Sstevel@tonic-gate 			to_node	  = (uint32_t)node;
18677c478bd9Sstevel@tonic-gate 
18687c478bd9Sstevel@tonic-gate 			/* Fill in the nodeID */
18697c478bd9Sstevel@tonic-gate 			cmd->nodeID =
18707c478bd9Sstevel@tonic-gate 			    (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >>
18717c478bd9Sstevel@tonic-gate 				IEEE1394_ADDR_NODE_ID_SHIFT;
18727c478bd9Sstevel@tonic-gate 
18737c478bd9Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) {
18747c478bd9Sstevel@tonic-gate 				s_priv->hal_cmd_private.speed =
18757c478bd9Sstevel@tonic-gate 				    (int)cmd->cmd_speed;
18767c478bd9Sstevel@tonic-gate 			} else {
18777c478bd9Sstevel@tonic-gate 				/* Speed is to be filled in from speed map */
18787c478bd9Sstevel@tonic-gate 				s_priv->hal_cmd_private.speed =
18797c478bd9Sstevel@tonic-gate 				    (int)s1394_speed_map_get(hal, from_node,
18807c478bd9Sstevel@tonic-gate 				    to_node);
18817c478bd9Sstevel@tonic-gate 			}
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 			/* Is it a block request? */
18847c478bd9Sstevel@tonic-gate 			if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
18857c478bd9Sstevel@tonic-gate 			    (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
18867c478bd9Sstevel@tonic-gate 
18877c478bd9Sstevel@tonic-gate 				/* Get a pointer to the HAL private struct */
18887c478bd9Sstevel@tonic-gate 				h_priv = (h1394_cmd_priv_t *)&s_priv->
18897c478bd9Sstevel@tonic-gate 				    hal_cmd_private;
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 				/* Handle the MAX_PAYLOAD size */
18927c478bd9Sstevel@tonic-gate 				if (s_priv->sent_by_target != NULL) {
18937c478bd9Sstevel@tonic-gate 					current_max_payload =
18947c478bd9Sstevel@tonic-gate 					    s_priv->sent_by_target->
18957c478bd9Sstevel@tonic-gate 					    current_max_payload;
18967c478bd9Sstevel@tonic-gate 				} else {
18977c478bd9Sstevel@tonic-gate 					current_max_payload = 4;
18987c478bd9Sstevel@tonic-gate 				}
18997c478bd9Sstevel@tonic-gate 				if (cmd->cmd_options &
19007c478bd9Sstevel@tonic-gate 				    CMD1394_OVERRIDE_MAX_PAYLOAD) {
19017c478bd9Sstevel@tonic-gate 					if (current_max_payload >
19027c478bd9Sstevel@tonic-gate 					    cmd->cmd_u.b.max_payload)
19037c478bd9Sstevel@tonic-gate 					    current_max_payload =
19047c478bd9Sstevel@tonic-gate 						    cmd->cmd_u.b.max_payload;
19057c478bd9Sstevel@tonic-gate 				}
19067c478bd9Sstevel@tonic-gate 				if (s_priv->data_remaining <
19077c478bd9Sstevel@tonic-gate 				    current_max_payload) {
19087c478bd9Sstevel@tonic-gate 					h_priv->mblk.length =
19097c478bd9Sstevel@tonic-gate 					    s_priv->data_remaining;
19107c478bd9Sstevel@tonic-gate 				} else {
19117c478bd9Sstevel@tonic-gate 					h_priv->mblk.length =
19127c478bd9Sstevel@tonic-gate 					    current_max_payload;
19137c478bd9Sstevel@tonic-gate 				}
19147c478bd9Sstevel@tonic-gate 			}
19157c478bd9Sstevel@tonic-gate 			s1394_unlock_tree(hal);
19167c478bd9Sstevel@tonic-gate 			ret = s1394_pending_q_helper(hal, cmd);
19177c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
19187c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
19197c478bd9Sstevel@tonic-gate 			return (ret);
19207c478bd9Sstevel@tonic-gate 		}
19217c478bd9Sstevel@tonic-gate 	}
19227c478bd9Sstevel@tonic-gate }
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate /*
19257c478bd9Sstevel@tonic-gate  * s1394_pending_q_helper()
19267c478bd9Sstevel@tonic-gate  *    is a "helper" function for s1394_process_pending_q().  It attempts to
19277c478bd9Sstevel@tonic-gate  *    resend commands, handling error conditions whenever necessary.
19287c478bd9Sstevel@tonic-gate  */
19297c478bd9Sstevel@tonic-gate static boolean_t
s1394_pending_q_helper(s1394_hal_t * hal,cmd1394_cmd_t * cmd)19307c478bd9Sstevel@tonic-gate s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
19317c478bd9Sstevel@tonic-gate {
19327c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
19337c478bd9Sstevel@tonic-gate 	int		 err;
19347c478bd9Sstevel@tonic-gate 	int		 ret;
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_helper_enter,
19377c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
19387c478bd9Sstevel@tonic-gate 
19397c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
19407c478bd9Sstevel@tonic-gate 
19417c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
19427c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate 	/* Put cmd on outstanding request Q */
19457c478bd9Sstevel@tonic-gate 	s1394_insert_q_asynch_cmd(hal, cmd);
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 	/* Send command out again */
19487c478bd9Sstevel@tonic-gate 	ret = s1394_xfer_asynch_command(hal, cmd, &err);
19497c478bd9Sstevel@tonic-gate 
19507c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
19517c478bd9Sstevel@tonic-gate 		if (err == CMD1394_ESTALE_GENERATION) {
19527c478bd9Sstevel@tonic-gate 			/* Remove cmd outstanding req Q */
19537c478bd9Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
19547c478bd9Sstevel@tonic-gate 			s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19577c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
19587c478bd9Sstevel@tonic-gate 			return (B_TRUE);
19597c478bd9Sstevel@tonic-gate 		} else {
19607c478bd9Sstevel@tonic-gate 			/* Remove cmd from outstanding request Q */
19617c478bd9Sstevel@tonic-gate 			s1394_remove_q_asynch_cmd(hal, cmd);
19627c478bd9Sstevel@tonic-gate 
19637c478bd9Sstevel@tonic-gate 			s_priv->cmd_in_use = B_FALSE;
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 			cmd->cmd_result = err;
19667c478bd9Sstevel@tonic-gate 
19677c478bd9Sstevel@tonic-gate 			/* Is this a blocking command? */
19687c478bd9Sstevel@tonic-gate 			if (cmd->cmd_options & CMD1394_BLOCKING) {
19697c478bd9Sstevel@tonic-gate 				/* Unblock waiting command */
19707c478bd9Sstevel@tonic-gate 				mutex_enter(&s_priv->blocking_mutex);
19717c478bd9Sstevel@tonic-gate 				s_priv->blocking_flag = B_TRUE;
19727c478bd9Sstevel@tonic-gate 				cv_signal(&s_priv->blocking_cv);
19737c478bd9Sstevel@tonic-gate 				mutex_exit(&s_priv->blocking_mutex);
19747c478bd9Sstevel@tonic-gate 
19757c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19767c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
19777c478bd9Sstevel@tonic-gate 				return (B_FALSE);
19787c478bd9Sstevel@tonic-gate 			}
19797c478bd9Sstevel@tonic-gate 
19807c478bd9Sstevel@tonic-gate 			/* Call target completion_callback() */
19817c478bd9Sstevel@tonic-gate 			if (cmd->completion_callback != NULL) {
19827c478bd9Sstevel@tonic-gate 				cmd->completion_callback(cmd);
19837c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19847c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
19857c478bd9Sstevel@tonic-gate 				return (B_FALSE);
19867c478bd9Sstevel@tonic-gate 			} else {
19877c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19887c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_BR_STACK, "");
19897c478bd9Sstevel@tonic-gate 				return (B_FALSE);
19907c478bd9Sstevel@tonic-gate 			}
19917c478bd9Sstevel@tonic-gate 		}
19927c478bd9Sstevel@tonic-gate 	}
19937c478bd9Sstevel@tonic-gate 
19947c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
19957c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
19967c478bd9Sstevel@tonic-gate 	return (B_FALSE);
19977c478bd9Sstevel@tonic-gate }
19987c478bd9Sstevel@tonic-gate 
19997c478bd9Sstevel@tonic-gate /*
20007c478bd9Sstevel@tonic-gate  * s1394_process_split_lock()
20017c478bd9Sstevel@tonic-gate  *    is a "helper" function for the s1394_handle_lock() callback.  Its
20027c478bd9Sstevel@tonic-gate  *    job is to perform whatever manipulation is required for the given
20037c478bd9Sstevel@tonic-gate  *    request.
20047c478bd9Sstevel@tonic-gate  */
20057c478bd9Sstevel@tonic-gate static int
s1394_process_split_lock(cmd1394_cmd_t * cmd,cmd1394_cmd_t * target_cmd)20067c478bd9Sstevel@tonic-gate s1394_process_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd)
20077c478bd9Sstevel@tonic-gate {
20087c478bd9Sstevel@tonic-gate 	uint64_t	 new_value64;
20097c478bd9Sstevel@tonic-gate 	uint64_t	 data_value64;
20107c478bd9Sstevel@tonic-gate 	uint64_t	 arg_value64;
20117c478bd9Sstevel@tonic-gate 	uint64_t	 old_value64;
20127c478bd9Sstevel@tonic-gate 	uint64_t	 temp_value64;
20137c478bd9Sstevel@tonic-gate 	uint32_t	 new_value32;
20147c478bd9Sstevel@tonic-gate 	uint32_t	 data_value32;
20157c478bd9Sstevel@tonic-gate 	uint32_t	 arg_value32;
20167c478bd9Sstevel@tonic-gate 	uint32_t	 old_value32;
20177c478bd9Sstevel@tonic-gate 	uint32_t	 temp_value32;
20187c478bd9Sstevel@tonic-gate 
20197c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_process_split_lock_enter,
20207c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate 	if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
20237c478bd9Sstevel@tonic-gate 		old_value32  = cmd->cmd_u.l32.old_value;
20247c478bd9Sstevel@tonic-gate 		data_value32 = target_cmd->cmd_u.l32.data_value;
20257c478bd9Sstevel@tonic-gate 		arg_value32  = target_cmd->cmd_u.l32.arg_value;
20267c478bd9Sstevel@tonic-gate 
20277c478bd9Sstevel@tonic-gate 		/* Lock type specific */
20287c478bd9Sstevel@tonic-gate 		switch (target_cmd->cmd_u.l32.lock_type) {
20297c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_AND:
20307c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 & data_value32;
20317c478bd9Sstevel@tonic-gate 			break;
20327c478bd9Sstevel@tonic-gate 
20337c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_OR:
20347c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 | data_value32;
20357c478bd9Sstevel@tonic-gate 			break;
20367c478bd9Sstevel@tonic-gate 
20377c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_XOR:
20387c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 ^ data_value32;
20397c478bd9Sstevel@tonic-gate 			break;
20407c478bd9Sstevel@tonic-gate 
20417c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_INCREMENT:
20427c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20437c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 + 1;
20447c478bd9Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20457c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20467c478bd9Sstevel@tonic-gate 			break;
20477c478bd9Sstevel@tonic-gate 
20487c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_DECREMENT:
20497c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20507c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 - 1;
20517c478bd9Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20527c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20537c478bd9Sstevel@tonic-gate 			break;
20547c478bd9Sstevel@tonic-gate 
20557c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_ADD:
20567c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20577c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 + data_value32;
20587c478bd9Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20597c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20607c478bd9Sstevel@tonic-gate 			break;
20617c478bd9Sstevel@tonic-gate 
20627c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_SUBTRACT:
20637c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20647c478bd9Sstevel@tonic-gate 			new_value32 = old_value32 - data_value32;
20657c478bd9Sstevel@tonic-gate 			new_value32 = T1394_DATA32(new_value32);
20667c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20677c478bd9Sstevel@tonic-gate 			break;
20687c478bd9Sstevel@tonic-gate 
20697c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_ADD:
20707c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20717c478bd9Sstevel@tonic-gate 			temp_value32 = (old_value32 + data_value32);
20727c478bd9Sstevel@tonic-gate 			if ((temp_value32 >= old_value32) &&
20737c478bd9Sstevel@tonic-gate 			    (temp_value32 <= arg_value32)) {
20747c478bd9Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
20757c478bd9Sstevel@tonic-gate 				old_value32 = T1394_DATA32(old_value32);
20767c478bd9Sstevel@tonic-gate 			} else {
20777c478bd9Sstevel@tonic-gate 				/* Failed threshold add */
20787c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value =
20797c478bd9Sstevel@tonic-gate 				    T1394_DATA32(cmd->cmd_u.l32.old_value);
20807c478bd9Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
20817c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
20827c478bd9Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
20837c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
20847c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
20857c478bd9Sstevel@tonic-gate 			}
20867c478bd9Sstevel@tonic-gate 			break;
20877c478bd9Sstevel@tonic-gate 
20887c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_SUBTRACT:
20897c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
20907c478bd9Sstevel@tonic-gate 			temp_value32 = (old_value32 - data_value32);
20917c478bd9Sstevel@tonic-gate 			if ((old_value32 >= data_value32) &&
20927c478bd9Sstevel@tonic-gate 			    (temp_value32 >= arg_value32)) {
20937c478bd9Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
20947c478bd9Sstevel@tonic-gate 				old_value32 = T1394_DATA32(old_value32);
20957c478bd9Sstevel@tonic-gate 			} else {
20967c478bd9Sstevel@tonic-gate 				/* Failed threshold subtract */
20977c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value =
20987c478bd9Sstevel@tonic-gate 				    T1394_DATA32(cmd->cmd_u.l32.old_value);
20997c478bd9Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
21007c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
21017c478bd9Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
21027c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
21037c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
21047c478bd9Sstevel@tonic-gate 			}
21057c478bd9Sstevel@tonic-gate 			break;
21067c478bd9Sstevel@tonic-gate 
21077c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_ADD:
21087c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21097c478bd9Sstevel@tonic-gate 			temp_value32 = (old_value32 + data_value32);
21107c478bd9Sstevel@tonic-gate 			if ((temp_value32 < old_value32) ||
21117c478bd9Sstevel@tonic-gate 			    (temp_value32 > arg_value32))
21127c478bd9Sstevel@tonic-gate 				new_value32 = T1394_DATA32(arg_value32);
21137c478bd9Sstevel@tonic-gate 			else
21147c478bd9Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
21157c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21167c478bd9Sstevel@tonic-gate 			break;
21177c478bd9Sstevel@tonic-gate 
21187c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_SUBTRACT:
21197c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21207c478bd9Sstevel@tonic-gate 			temp_value32 = (old_value32 - data_value32);
21217c478bd9Sstevel@tonic-gate 			if ((data_value32 > old_value32) ||
21227c478bd9Sstevel@tonic-gate 			    (temp_value32 < arg_value32))
21237c478bd9Sstevel@tonic-gate 				new_value32 = T1394_DATA32(arg_value32);
21247c478bd9Sstevel@tonic-gate 			else
21257c478bd9Sstevel@tonic-gate 				new_value32 = T1394_DATA32(temp_value32);
21267c478bd9Sstevel@tonic-gate 			old_value32 = T1394_DATA32(old_value32);
21277c478bd9Sstevel@tonic-gate 			break;
21287c478bd9Sstevel@tonic-gate 		}
21297c478bd9Sstevel@tonic-gate 
21307c478bd9Sstevel@tonic-gate 		/* Send compare-swap lock request */
21317c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l32.arg_value  = old_value32;
21327c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l32.data_value = new_value32;
21337c478bd9Sstevel@tonic-gate 	} else {
21347c478bd9Sstevel@tonic-gate 		old_value64  = cmd->cmd_u.l64.old_value;
21357c478bd9Sstevel@tonic-gate 		data_value64 = target_cmd->cmd_u.l64.data_value;
21367c478bd9Sstevel@tonic-gate 		arg_value64  = target_cmd->cmd_u.l64.arg_value;
21377c478bd9Sstevel@tonic-gate 
21387c478bd9Sstevel@tonic-gate 		/* Lock type specific */
21397c478bd9Sstevel@tonic-gate 		switch (target_cmd->cmd_u.l64.lock_type) {
21407c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_AND:
21417c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 & data_value64;
21427c478bd9Sstevel@tonic-gate 			break;
21437c478bd9Sstevel@tonic-gate 
21447c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_OR:
21457c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 | data_value64;
21467c478bd9Sstevel@tonic-gate 			break;
21477c478bd9Sstevel@tonic-gate 
21487c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_BIT_XOR:
21497c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 ^ data_value64;
21507c478bd9Sstevel@tonic-gate 			break;
21517c478bd9Sstevel@tonic-gate 
21527c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_INCREMENT:
21537c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21547c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 + 1;
21557c478bd9Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21567c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21577c478bd9Sstevel@tonic-gate 			break;
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_DECREMENT:
21607c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21617c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 - 1;
21627c478bd9Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21637c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21647c478bd9Sstevel@tonic-gate 			break;
21657c478bd9Sstevel@tonic-gate 
21667c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_ADD:
21677c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21687c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 + data_value64;
21697c478bd9Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21707c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21717c478bd9Sstevel@tonic-gate 			break;
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_SUBTRACT:
21747c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21757c478bd9Sstevel@tonic-gate 			new_value64 = old_value64 - data_value64;
21767c478bd9Sstevel@tonic-gate 			new_value64 = T1394_DATA64(new_value64);
21777c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21787c478bd9Sstevel@tonic-gate 			break;
21797c478bd9Sstevel@tonic-gate 
21807c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_ADD:
21817c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
21827c478bd9Sstevel@tonic-gate 			temp_value64 = (old_value64 + data_value64);
21837c478bd9Sstevel@tonic-gate 			if ((temp_value64 >= old_value64) &&
21847c478bd9Sstevel@tonic-gate 			    (temp_value64 <= arg_value64)) {
21857c478bd9Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
21867c478bd9Sstevel@tonic-gate 				old_value64 = T1394_DATA64(old_value64);
21877c478bd9Sstevel@tonic-gate 			} else {
21887c478bd9Sstevel@tonic-gate 				/* Failed threshold add */
21897c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value =
21907c478bd9Sstevel@tonic-gate 				    T1394_DATA64(cmd->cmd_u.l64.old_value);
21917c478bd9Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
21927c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
21937c478bd9Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
21947c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
21957c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
21967c478bd9Sstevel@tonic-gate 			}
21977c478bd9Sstevel@tonic-gate 			break;
21987c478bd9Sstevel@tonic-gate 
21997c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_THRESH_SUBTRACT:
22007c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22017c478bd9Sstevel@tonic-gate 			temp_value64 = (old_value64 - data_value64);
22027c478bd9Sstevel@tonic-gate 			if ((old_value64 >= data_value64) &&
22037c478bd9Sstevel@tonic-gate 			    (temp_value64 >= arg_value64)) {
22047c478bd9Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
22057c478bd9Sstevel@tonic-gate 				old_value64 = T1394_DATA64(old_value64);
22067c478bd9Sstevel@tonic-gate 			} else {
22077c478bd9Sstevel@tonic-gate 				/* Failed threshold subtract */
22087c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value =
22097c478bd9Sstevel@tonic-gate 				    T1394_DATA64(cmd->cmd_u.l64.old_value);
22107c478bd9Sstevel@tonic-gate 				target_cmd->cmd_result = CMD1394_CMDSUCCESS;
22117c478bd9Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
22127c478bd9Sstevel@tonic-gate 				    s1394_process_split_lock_exit,
22137c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ATREQ_STACK, "");
22147c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
22157c478bd9Sstevel@tonic-gate 			}
22167c478bd9Sstevel@tonic-gate 			break;
22177c478bd9Sstevel@tonic-gate 
22187c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_ADD:
22197c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22207c478bd9Sstevel@tonic-gate 			temp_value64 = (old_value64 + data_value64);
22217c478bd9Sstevel@tonic-gate 			if ((temp_value64 < old_value64) ||
22227c478bd9Sstevel@tonic-gate 			    (temp_value64 > arg_value64))
22237c478bd9Sstevel@tonic-gate 				new_value64 = T1394_DATA64(arg_value64);
22247c478bd9Sstevel@tonic-gate 			else
22257c478bd9Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
22267c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22277c478bd9Sstevel@tonic-gate 			break;
22287c478bd9Sstevel@tonic-gate 
22297c478bd9Sstevel@tonic-gate 		case CMD1394_LOCK_CLIP_SUBTRACT:
22307c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22317c478bd9Sstevel@tonic-gate 			temp_value64 = (old_value64 - data_value64);
22327c478bd9Sstevel@tonic-gate 			if ((data_value64 > old_value64) ||
22337c478bd9Sstevel@tonic-gate 			    (temp_value64 < arg_value64))
22347c478bd9Sstevel@tonic-gate 				new_value64 = T1394_DATA64(arg_value64);
22357c478bd9Sstevel@tonic-gate 			else
22367c478bd9Sstevel@tonic-gate 				new_value64 = T1394_DATA64(temp_value64);
22377c478bd9Sstevel@tonic-gate 			old_value64 = T1394_DATA64(old_value64);
22387c478bd9Sstevel@tonic-gate 			break;
22397c478bd9Sstevel@tonic-gate 		}
22407c478bd9Sstevel@tonic-gate 
22417c478bd9Sstevel@tonic-gate 		/* Send compare-swap lock request */
22427c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l64.arg_value  = old_value64;
22437c478bd9Sstevel@tonic-gate 		cmd->cmd_u.l64.data_value = new_value64;
22447c478bd9Sstevel@tonic-gate 	}
22457c478bd9Sstevel@tonic-gate 
22467c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_process_split_lock_exit,
22477c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
22487c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
22497c478bd9Sstevel@tonic-gate }
22507c478bd9Sstevel@tonic-gate 
22517c478bd9Sstevel@tonic-gate /*
22527c478bd9Sstevel@tonic-gate  * s1394_finish_split_lock()
22537c478bd9Sstevel@tonic-gate  *    is another "helper" function for the s1394_handle_lock() callback.
22547c478bd9Sstevel@tonic-gate  *    Its job is to finish up whatever lock request procesing is necessary.
22557c478bd9Sstevel@tonic-gate  */
22567c478bd9Sstevel@tonic-gate static int
s1394_finish_split_lock(cmd1394_cmd_t * cmd,cmd1394_cmd_t * target_cmd)22577c478bd9Sstevel@tonic-gate s1394_finish_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd)
22587c478bd9Sstevel@tonic-gate {
22597c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv;
22607c478bd9Sstevel@tonic-gate 	uint64_t	 tmp_value64;
22617c478bd9Sstevel@tonic-gate 	uint32_t	 tmp_value32;
22627c478bd9Sstevel@tonic-gate 
22637c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_finish_split_lock_enter,
22647c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
22657c478bd9Sstevel@tonic-gate 
22667c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
22677c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
22687c478bd9Sstevel@tonic-gate 
22697c478bd9Sstevel@tonic-gate 	if (((cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) &&
22707c478bd9Sstevel@tonic-gate 	    (cmd->cmd_u.l32.old_value == cmd->cmd_u.l32.arg_value)) ||
22717c478bd9Sstevel@tonic-gate 	    ((cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) &&
22727c478bd9Sstevel@tonic-gate 	    (cmd->cmd_u.l64.old_value == cmd->cmd_u.l64.arg_value))) {
22737c478bd9Sstevel@tonic-gate 
22747c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
22757c478bd9Sstevel@tonic-gate 			switch (cmd->cmd_u.l32.lock_type) {
22767c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_INCREMENT:
22777c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_DECREMENT:
22787c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_ADD:
22797c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_SUBTRACT:
22807c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_ADD:
22817c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_SUBTRACT:
22827c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_ADD:
22837c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_SUBTRACT:
22847c478bd9Sstevel@tonic-gate 				tmp_value32 = cmd->cmd_u.l32.old_value;
22857c478bd9Sstevel@tonic-gate 				tmp_value32 = T1394_DATA32(tmp_value32);
22867c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value = tmp_value32;
22877c478bd9Sstevel@tonic-gate 				break;
22887c478bd9Sstevel@tonic-gate 			default:
22897c478bd9Sstevel@tonic-gate 				tmp_value32 = cmd->cmd_u.l32.old_value;
22907c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l32.old_value = tmp_value32;
22917c478bd9Sstevel@tonic-gate 				break;
22927c478bd9Sstevel@tonic-gate 			}
22937c478bd9Sstevel@tonic-gate 		} else {
22947c478bd9Sstevel@tonic-gate 			switch (cmd->cmd_u.l64.lock_type) {
22957c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_INCREMENT:
22967c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_DECREMENT:
22977c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_ADD:
22987c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_SUBTRACT:
22997c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_ADD:
23007c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_THRESH_SUBTRACT:
23017c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_ADD:
23027c478bd9Sstevel@tonic-gate 			case CMD1394_LOCK_CLIP_SUBTRACT:
23037c478bd9Sstevel@tonic-gate 				tmp_value64 = cmd->cmd_u.l64.old_value;
23047c478bd9Sstevel@tonic-gate 				tmp_value64 = T1394_DATA64(tmp_value64);
23057c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value = tmp_value64;
23067c478bd9Sstevel@tonic-gate 				break;
23077c478bd9Sstevel@tonic-gate 			default:
23087c478bd9Sstevel@tonic-gate 				tmp_value64 = cmd->cmd_u.l64.old_value;
23097c478bd9Sstevel@tonic-gate 				target_cmd->cmd_u.l64.old_value = tmp_value64;
23107c478bd9Sstevel@tonic-gate 				break;
23117c478bd9Sstevel@tonic-gate 			}
23127c478bd9Sstevel@tonic-gate 		}
23137c478bd9Sstevel@tonic-gate 		/* Set status */
23147c478bd9Sstevel@tonic-gate 		target_cmd->cmd_result = CMD1394_CMDSUCCESS;
23157c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit,
23167c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
23177c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
23187c478bd9Sstevel@tonic-gate 	} else {
23197c478bd9Sstevel@tonic-gate 		if (s_priv->temp_num_retries > 0) {
23207c478bd9Sstevel@tonic-gate 			/* Decrement retry count */
23217c478bd9Sstevel@tonic-gate 			s_priv->temp_num_retries--;
23227c478bd9Sstevel@tonic-gate 
23237c478bd9Sstevel@tonic-gate 			/* Reset lock_req_step */
23247c478bd9Sstevel@tonic-gate 			s_priv->lock_req_step = 0;
23257c478bd9Sstevel@tonic-gate 
23267c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_finish_split_lock_start_over,
23277c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
23287c478bd9Sstevel@tonic-gate 			/* Resend... start at step 0 again */
23297c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit,
23307c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
23317c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
23327c478bd9Sstevel@tonic-gate 		} else {
23337c478bd9Sstevel@tonic-gate 			/* Failed... RETRIES_EXCEEDED */
23347c478bd9Sstevel@tonic-gate 			target_cmd->cmd_result = CMD1394_ERETRIES_EXCEEDED;
23357c478bd9Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit,
23367c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ATREQ_STACK, "");
23377c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
23387c478bd9Sstevel@tonic-gate 		}
23397c478bd9Sstevel@tonic-gate 	}
23407c478bd9Sstevel@tonic-gate }
2341