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