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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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