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 580a70ef3Sap25164 * Common Development and Distribution License (the "License"). 680a70ef3Sap25164 * 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 /* 2280a70ef3Sap25164 * 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 /* 277c478bd9Sstevel@tonic-gate * t1394.c 287c478bd9Sstevel@tonic-gate * 1394 Target Driver Interface 297c478bd9Sstevel@tonic-gate * This file contains all of the 1394 Software Framework routines called 307c478bd9Sstevel@tonic-gate * by target drivers 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 33*de710d24SJosef 'Jeff' Sipek #include <sys/sysmacros.h> 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/types.h> 387c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 3980a70ef3Sap25164 #include <sys/disp.h> 407c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h> 437c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h> 447c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h> 457c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1394.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static int s1394_allow_detach = 0; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * Function: t1394_attach() 517c478bd9Sstevel@tonic-gate * Input(s): dip The dip given to the target driver 527c478bd9Sstevel@tonic-gate * in it's attach() routine 537c478bd9Sstevel@tonic-gate * version The version of the target driver - 547c478bd9Sstevel@tonic-gate * T1394_VERSION_V1 557c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 567c478bd9Sstevel@tonic-gate * 577c478bd9Sstevel@tonic-gate * Output(s): attachinfo Used to pass info back to target, 587c478bd9Sstevel@tonic-gate * including bus generation, local 597c478bd9Sstevel@tonic-gate * node ID, dma attribute, etc. 607c478bd9Sstevel@tonic-gate * t1394_hdl The target "handle" to be used for 617c478bd9Sstevel@tonic-gate * all subsequent calls into the 627c478bd9Sstevel@tonic-gate * 1394 Software Framework 637c478bd9Sstevel@tonic-gate * 647c478bd9Sstevel@tonic-gate * Description: t1394_attach() registers the target (based on its dip) with 657c478bd9Sstevel@tonic-gate * the 1394 Software Framework. It returns the bus_generation, 667c478bd9Sstevel@tonic-gate * local_nodeID, iblock_cookie and other useful information to 677c478bd9Sstevel@tonic-gate * the target, as well as a handle (t1394_hdl) that will be used 687c478bd9Sstevel@tonic-gate * in all subsequent calls into this framework. 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate /* ARGSUSED */ 717c478bd9Sstevel@tonic-gate int 727c478bd9Sstevel@tonic-gate t1394_attach(dev_info_t *dip, int version, uint_t flags, 737c478bd9Sstevel@tonic-gate t1394_attachinfo_t *attachinfo, t1394_handle_t *t1394_hdl) 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 767c478bd9Sstevel@tonic-gate s1394_target_t *target; 777c478bd9Sstevel@tonic-gate uint_t dev; 787c478bd9Sstevel@tonic-gate uint_t curr; 797c478bd9Sstevel@tonic-gate uint_t unit_dir; 807c478bd9Sstevel@tonic-gate int hp_node = 0; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 837c478bd9Sstevel@tonic-gate ASSERT(attachinfo != NULL); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_attach_enter, S1394_TNF_SL_HOTPLUG_STACK, ""); 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate *t1394_hdl = NULL; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if (version != T1394_VERSION_V1) { 907c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_attach_error, S1394_TNF_SL_HOTPLUG_ERROR, "", 917c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid version"); 927c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_attach_exit, 937c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 947c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate hal = s1394_dip_to_hal(ddi_get_parent(dip)); 987c478bd9Sstevel@tonic-gate if (hal == NULL) { 997c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_attach_error, S1394_TNF_SL_HOTPLUG_ERROR, "", 1007c478bd9Sstevel@tonic-gate tnf_string, msg, "No parent dip found for target"); 1017c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_attach_exit, 1027c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 1037c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate hp_node = ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1097c478bd9Sstevel@tonic-gate "hp-node"); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* Allocate space for s1394_target_t */ 1127c478bd9Sstevel@tonic-gate target = kmem_zalloc(sizeof (s1394_target_t), KM_SLEEP); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate target->target_version = version; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* Copy in the params */ 1197c478bd9Sstevel@tonic-gate target->target_dip = dip; 1207c478bd9Sstevel@tonic-gate target->on_hal = hal; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* Place the target on the appropriate node */ 1237c478bd9Sstevel@tonic-gate target->on_node = NULL; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate rw_enter(&target->on_hal->target_list_rwlock, RW_WRITER); 1267c478bd9Sstevel@tonic-gate if (hp_node != 0) { 1277c478bd9Sstevel@tonic-gate s1394_add_target_to_node(target); 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * on_node can be NULL if the node got unplugged 1307c478bd9Sstevel@tonic-gate * while the target driver is in its attach routine. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate if (target->on_node == NULL) { 1337c478bd9Sstevel@tonic-gate s1394_remove_target_from_node(target); 1347c478bd9Sstevel@tonic-gate rw_exit(&target->on_hal->target_list_rwlock); 1357c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 1367c478bd9Sstevel@tonic-gate kmem_free(target, sizeof (s1394_target_t)); 1377c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_attach_error, 1387c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, msg, 1397c478bd9Sstevel@tonic-gate "on_node == NULL"); 1407c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_attach_exit, 1417c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 1427c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate target->target_state = S1394_TARG_HP_NODE; 1467c478bd9Sstevel@tonic-gate if (S1394_NODE_BUS_PWR_CONSUMER(target->on_node) == B_TRUE) 1477c478bd9Sstevel@tonic-gate target->target_state |= S1394_TARG_BUS_PWR_CONSUMER; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* Return the current generation */ 1517c478bd9Sstevel@tonic-gate attachinfo->localinfo.bus_generation = target->on_hal->generation_count; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* Fill in hal node id */ 1547c478bd9Sstevel@tonic-gate attachinfo->localinfo.local_nodeID = target->on_hal->node_id; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* Give the target driver the iblock_cookie */ 1577c478bd9Sstevel@tonic-gate attachinfo->iblock_cookie = target->on_hal->halinfo.hw_interrupt; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* Give the target driver the attributes */ 1607c478bd9Sstevel@tonic-gate attachinfo->acc_attr = target->on_hal->halinfo.acc_attr; 1617c478bd9Sstevel@tonic-gate attachinfo->dma_attr = target->on_hal->halinfo.dma_attr; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate unit_dir = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 1647c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit-dir-offset", 0); 1657c478bd9Sstevel@tonic-gate target->unit_dir = unit_dir; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* By default, disable all physical AR requests */ 1687c478bd9Sstevel@tonic-gate target->physical_arreq_enabled = 0; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* Get dev_max_payload & current_max_payload */ 1727c478bd9Sstevel@tonic-gate s1394_get_maxpayload(target, &dev, &curr); 1737c478bd9Sstevel@tonic-gate target->dev_max_payload = dev; 1747c478bd9Sstevel@tonic-gate target->current_max_payload = curr; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* Add into linked list */ 1777c478bd9Sstevel@tonic-gate if ((target->on_hal->target_head == NULL) && 1787c478bd9Sstevel@tonic-gate (target->on_hal->target_tail == NULL)) { 1797c478bd9Sstevel@tonic-gate target->on_hal->target_head = target; 1807c478bd9Sstevel@tonic-gate target->on_hal->target_tail = target; 1817c478bd9Sstevel@tonic-gate } else { 1827c478bd9Sstevel@tonic-gate target->on_hal->target_tail->target_next = target; 1837c478bd9Sstevel@tonic-gate target->target_prev = target->on_hal->target_tail; 1847c478bd9Sstevel@tonic-gate target->on_hal->target_tail = target; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate rw_exit(&target->on_hal->target_list_rwlock); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* Fill in services layer private info */ 1897c478bd9Sstevel@tonic-gate *t1394_hdl = (t1394_handle_t)target; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_attach_exit, S1394_TNF_SL_HOTPLUG_STACK, ""); 1947c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* 1987c478bd9Sstevel@tonic-gate * Function: t1394_detach() 1997c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 2007c478bd9Sstevel@tonic-gate * t1394_attach() 2017c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 2027c478bd9Sstevel@tonic-gate * 2037c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully detached 2047c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to detach 2057c478bd9Sstevel@tonic-gate * 2067c478bd9Sstevel@tonic-gate * Description: t1394_detach() unregisters the target from the 1394 Software 2077c478bd9Sstevel@tonic-gate * Framework. t1394_detach() can fail if the target has any 2087c478bd9Sstevel@tonic-gate * allocated commands that haven't been freed. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2117c478bd9Sstevel@tonic-gate int 2127c478bd9Sstevel@tonic-gate t1394_detach(t1394_handle_t *t1394_hdl, uint_t flags) 2137c478bd9Sstevel@tonic-gate { 2147c478bd9Sstevel@tonic-gate s1394_target_t *target; 2157c478bd9Sstevel@tonic-gate uint_t num_cmds; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_detach_enter, S1394_TNF_SL_HOTPLUG_STACK, ""); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate target = (s1394_target_t *)(*t1394_hdl); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate ASSERT(target->on_hal); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate mutex_enter(&target->on_hal->topology_tree_mutex); 2267c478bd9Sstevel@tonic-gate rw_enter(&target->on_hal->target_list_rwlock, RW_WRITER); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* How many cmds has this target allocated? */ 2297c478bd9Sstevel@tonic-gate num_cmds = target->target_num_cmds; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate if (num_cmds != 0) { 2327c478bd9Sstevel@tonic-gate rw_exit(&target->on_hal->target_list_rwlock); 2337c478bd9Sstevel@tonic-gate mutex_exit(&target->on_hal->topology_tree_mutex); 2347c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_detach_error, S1394_TNF_SL_HOTPLUG_ERROR, "", 2357c478bd9Sstevel@tonic-gate tnf_string, msg, "Must free all commands before detach()"); 2367c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_detach_exit, 2377c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 2387c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * Remove from linked lists. Topology tree is already locked 2437c478bd9Sstevel@tonic-gate * so that the node won't go away while we are looking at it. 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate if ((target->on_hal->target_head == target) && 2467c478bd9Sstevel@tonic-gate (target->on_hal->target_tail == target)) { 2477c478bd9Sstevel@tonic-gate target->on_hal->target_head = NULL; 2487c478bd9Sstevel@tonic-gate target->on_hal->target_tail = NULL; 2497c478bd9Sstevel@tonic-gate } else { 2507c478bd9Sstevel@tonic-gate if (target->target_prev) 2517c478bd9Sstevel@tonic-gate target->target_prev->target_next = target->target_next; 2527c478bd9Sstevel@tonic-gate if (target->target_next) 2537c478bd9Sstevel@tonic-gate target->target_next->target_prev = target->target_prev; 2547c478bd9Sstevel@tonic-gate if (target->on_hal->target_head == target) 2557c478bd9Sstevel@tonic-gate target->on_hal->target_head = target->target_next; 2567c478bd9Sstevel@tonic-gate if (target->on_hal->target_tail == target) 2577c478bd9Sstevel@tonic-gate target->on_hal->target_tail = target->target_prev; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate s1394_remove_target_from_node(target); 2617c478bd9Sstevel@tonic-gate rw_exit(&target->on_hal->target_list_rwlock); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate mutex_exit(&target->on_hal->topology_tree_mutex); 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* Free memory */ 2667c478bd9Sstevel@tonic-gate kmem_free(target, sizeof (s1394_target_t)); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate *t1394_hdl = NULL; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_detach_exit, S1394_TNF_SL_HOTPLUG_STACK, ""); 2717c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Function: t1394_alloc_cmd() 2767c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 2777c478bd9Sstevel@tonic-gate * t1394_attach() 2787c478bd9Sstevel@tonic-gate * flags The flags parameter is described below 2797c478bd9Sstevel@tonic-gate * 2807c478bd9Sstevel@tonic-gate * Output(s): cmdp Pointer to the newly allocated command 2817c478bd9Sstevel@tonic-gate * 2827c478bd9Sstevel@tonic-gate * Description: t1394_alloc_cmd() allocates a command for use with the 2837c478bd9Sstevel@tonic-gate * t1394_read(), t1394_write(), or t1394_lock() interfaces 2847c478bd9Sstevel@tonic-gate * of the 1394 Software Framework. By default, t1394_alloc_cmd() 2857c478bd9Sstevel@tonic-gate * may sleep while allocating memory for the command structure. 2867c478bd9Sstevel@tonic-gate * If this is undesirable, the target may set the 2877c478bd9Sstevel@tonic-gate * T1394_ALLOC_CMD_NOSLEEP bit in the flags parameter. Also, 2887c478bd9Sstevel@tonic-gate * this call may fail because a target driver has already 2897c478bd9Sstevel@tonic-gate * allocated MAX_NUMBER_ALLOC_CMDS commands. 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate int 2927c478bd9Sstevel@tonic-gate t1394_alloc_cmd(t1394_handle_t t1394_hdl, uint_t flags, cmd1394_cmd_t **cmdp) 2937c478bd9Sstevel@tonic-gate { 2947c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 2957c478bd9Sstevel@tonic-gate s1394_target_t *target; 2967c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 2977c478bd9Sstevel@tonic-gate uint_t num_cmds; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_cmd_enter, S1394_TNF_SL_ATREQ_STACK, ""); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 3067c478bd9Sstevel@tonic-gate hal = target->on_hal; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate /* How many cmds has this target allocated? */ 3117c478bd9Sstevel@tonic-gate num_cmds = target->target_num_cmds; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate if (num_cmds >= MAX_NUMBER_ALLOC_CMDS) { 3147c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 3157c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_cmd_error, S1394_TNF_SL_ATREQ_ERROR, 3167c478bd9Sstevel@tonic-gate "", tnf_string, msg, "Attempted to alloc > " 3177c478bd9Sstevel@tonic-gate "MAX_NUMBER_ALLOC_CMDS"); 3187c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_cmd_exit, 3197c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 3207c478bd9Sstevel@tonic-gate /* kstats - cmd alloc failures */ 3217c478bd9Sstevel@tonic-gate hal->hal_kstats->cmd_alloc_fail++; 3227c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* Increment the number of cmds this target has allocated? */ 3267c478bd9Sstevel@tonic-gate target->target_num_cmds = num_cmds + 1; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (s1394_alloc_cmd(hal, flags, cmdp) != DDI_SUCCESS) { 3297c478bd9Sstevel@tonic-gate target->target_num_cmds = num_cmds; /* Undo increment */ 3307c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 3317c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_cmd_error, S1394_TNF_SL_ATREQ_ERROR, "", 3327c478bd9Sstevel@tonic-gate tnf_string, msg, "Failed to allocate command structure"); 3337c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_cmd_exit, 3347c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 3357c478bd9Sstevel@tonic-gate /* kstats - cmd alloc failures */ 3367c478bd9Sstevel@tonic-gate hal->hal_kstats->cmd_alloc_fail++; 3377c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 3437c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(*cmdp); 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* Initialize the command's blocking mutex */ 3467c478bd9Sstevel@tonic-gate mutex_init(&s_priv->blocking_mutex, NULL, MUTEX_DRIVER, 3477c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* Initialize the command's blocking condition variable */ 3507c478bd9Sstevel@tonic-gate cv_init(&s_priv->blocking_cv, NULL, CV_DRIVER, NULL); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_cmd_exit, S1394_TNF_SL_ATREQ_STACK, ""); 3537c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * Function: t1394_free_cmd() 3587c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 3597c478bd9Sstevel@tonic-gate * t1394_attach() 3607c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 3617c478bd9Sstevel@tonic-gate * cmdp Pointer to the command to be freed 3627c478bd9Sstevel@tonic-gate * 3637c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully freed command 3647c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to free command 3657c478bd9Sstevel@tonic-gate * 3667c478bd9Sstevel@tonic-gate * Description: t1394_free_cmd() attempts to free a command that has previously 3677c478bd9Sstevel@tonic-gate * been allocated by the target driver. It is possible for 3687c478bd9Sstevel@tonic-gate * t1394_free_cmd() to fail because the command is currently 3697c478bd9Sstevel@tonic-gate * in-use by the 1394 Software Framework. 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3727c478bd9Sstevel@tonic-gate int 3737c478bd9Sstevel@tonic-gate t1394_free_cmd(t1394_handle_t t1394_hdl, uint_t flags, cmd1394_cmd_t **cmdp) 3747c478bd9Sstevel@tonic-gate { 3757c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 3767c478bd9Sstevel@tonic-gate s1394_target_t *target; 3777c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 3787c478bd9Sstevel@tonic-gate uint_t num_cmds; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_cmd_enter, S1394_TNF_SL_ATREQ_STACK, ""); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 3877c478bd9Sstevel@tonic-gate hal = target->on_hal; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER); 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate /* How many cmds has this target allocated? */ 3927c478bd9Sstevel@tonic-gate num_cmds = target->target_num_cmds; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if (num_cmds == 0) { 3957c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 3967c478bd9Sstevel@tonic-gate TNF_PROBE_2(t1394_free_cmd_error, S1394_TNF_SL_ATREQ_ERROR, "", 3977c478bd9Sstevel@tonic-gate tnf_string, msg, "No commands left to be freed " 3987c478bd9Sstevel@tonic-gate "(num_cmds <= 0)", tnf_uint, num_cmds, num_cmds); 3997c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_cmd_exit, 4007c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 4017c478bd9Sstevel@tonic-gate ASSERT(num_cmds != 0); 4027c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 4067c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(*cmdp); 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* Check that command isn't in use */ 4097c478bd9Sstevel@tonic-gate if (s_priv->cmd_in_use == B_TRUE) { 4107c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 4117c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_free_cmd_error, S1394_TNF_SL_ATREQ_ERROR, "", 4127c478bd9Sstevel@tonic-gate tnf_string, msg, "Attempted to free an in-use command"); 4137c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_cmd_exit, 4147c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 4157c478bd9Sstevel@tonic-gate ASSERT(s_priv->cmd_in_use == B_FALSE); 4167c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* Decrement the number of cmds this target has allocated */ 4207c478bd9Sstevel@tonic-gate target->target_num_cmds--; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* Destroy the command's blocking condition variable */ 4257c478bd9Sstevel@tonic-gate cv_destroy(&s_priv->blocking_cv); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* Destroy the command's blocking mutex */ 4287c478bd9Sstevel@tonic-gate mutex_destroy(&s_priv->blocking_mutex); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate kmem_cache_free(hal->hal_kmem_cachep, *cmdp); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* Command pointer is set to NULL before returning */ 4337c478bd9Sstevel@tonic-gate *cmdp = NULL; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* kstats - number of cmd frees */ 4367c478bd9Sstevel@tonic-gate hal->hal_kstats->cmd_free++; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_cmd_exit, S1394_TNF_SL_ATREQ_STACK, ""); 4397c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * Function: t1394_read() 4447c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 4457c478bd9Sstevel@tonic-gate * t1394_attach() 4467c478bd9Sstevel@tonic-gate * cmd Pointer to the command to send 4477c478bd9Sstevel@tonic-gate * 4487c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successful sent the command 4497c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to send command 4507c478bd9Sstevel@tonic-gate * 4517c478bd9Sstevel@tonic-gate * Description: t1394_read() attempts to send an asynchronous read request 4527c478bd9Sstevel@tonic-gate * onto the 1394 bus. 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate int 4557c478bd9Sstevel@tonic-gate t1394_read(t1394_handle_t t1394_hdl, cmd1394_cmd_t *cmd) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate s1394_hal_t *to_hal; 4587c478bd9Sstevel@tonic-gate s1394_target_t *target; 4597c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 4607c478bd9Sstevel@tonic-gate s1394_hal_state_t state; 4617c478bd9Sstevel@tonic-gate int ret; 4627c478bd9Sstevel@tonic-gate int err; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_enter, S1394_TNF_SL_ATREQ_STACK, ""); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 4677c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 4707c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(cmd); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate /* Is this command currently in use? */ 4737c478bd9Sstevel@tonic-gate if (s_priv->cmd_in_use == B_TRUE) { 4747c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_read_error, S1394_TNF_SL_ATREQ_ERROR, "", 4757c478bd9Sstevel@tonic-gate tnf_string, msg, "Attempted to resend an in-use command"); 4767c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, S1394_TNF_SL_ATREQ_STACK, 4777c478bd9Sstevel@tonic-gate ""); 4787c478bd9Sstevel@tonic-gate ASSERT(s_priv->cmd_in_use == B_FALSE); 4797c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* Set-up the destination of the command */ 4857c478bd9Sstevel@tonic-gate to_hal = target->on_hal; 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* No status (default) */ 4887c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_NOSTATUS; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* Check for proper command type */ 4917c478bd9Sstevel@tonic-gate if ((cmd->cmd_type != CMD1394_ASYNCH_RD_QUAD) && 4927c478bd9Sstevel@tonic-gate (cmd->cmd_type != CMD1394_ASYNCH_RD_BLOCK)) { 4937c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_COMMAND; 4947c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_read_error, S1394_TNF_SL_ATREQ_ERROR, "", 4957c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid command type specified"); 4967c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, 4977c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 4987c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate /* Is this a blocking command on interrupt stack? */ 5027c478bd9Sstevel@tonic-gate if ((cmd->cmd_options & CMD1394_BLOCKING) && 50380a70ef3Sap25164 (servicing_interrupt())) { 5047c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_CONTEXT; 5057c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_read_error, S1394_TNF_SL_ATREQ_ERROR, "", 5067c478bd9Sstevel@tonic-gate tnf_string, msg, "Tried to use CMD1394_BLOCKING in " 5077c478bd9Sstevel@tonic-gate "intr context"); 5087c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, 5097c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 5107c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate mutex_enter(&to_hal->topology_tree_mutex); 5147c478bd9Sstevel@tonic-gate state = to_hal->hal_state; 5157c478bd9Sstevel@tonic-gate if (state != S1394_HAL_NORMAL) { 5167c478bd9Sstevel@tonic-gate ret = s1394_HAL_asynch_error(to_hal, cmd, state); 5177c478bd9Sstevel@tonic-gate if (ret != CMD1394_CMDSUCCESS) { 5187c478bd9Sstevel@tonic-gate cmd->cmd_result = ret; 5197c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 5207c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate ret = s1394_setup_asynch_command(to_hal, target, cmd, 5257c478bd9Sstevel@tonic-gate S1394_CMD_READ, &err); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* Command has now been put onto the queue! */ 5287c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 5297c478bd9Sstevel@tonic-gate /* Copy error code into result */ 5307c478bd9Sstevel@tonic-gate cmd->cmd_result = err; 5317c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 5327c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_read_error, S1394_TNF_SL_ATREQ_ERROR, "", 5337c478bd9Sstevel@tonic-gate tnf_string, msg, "Failed in s1394_setup_asynch_command()"); 5347c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, 5357c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 5367c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * If this command was sent during a bus reset, 5417c478bd9Sstevel@tonic-gate * then put it onto the pending Q. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate if (state == S1394_HAL_RESET) { 5447c478bd9Sstevel@tonic-gate /* Remove cmd from outstanding request Q */ 5457c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(to_hal, cmd); 5467c478bd9Sstevel@tonic-gate /* Are we on the bus reset event stack? */ 5477c478bd9Sstevel@tonic-gate if (s1394_on_br_thread(to_hal) == B_TRUE) { 5487c478bd9Sstevel@tonic-gate /* Blocking commands are not allowed */ 5497c478bd9Sstevel@tonic-gate if (cmd->cmd_options & CMD1394_BLOCKING) { 5507c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 5517c478bd9Sstevel@tonic-gate s_priv->cmd_in_use = B_FALSE; 5527c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_CONTEXT; 5537c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_read_error, 5547c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, 5557c478bd9Sstevel@tonic-gate msg, "CMD1394_BLOCKING in bus reset " 5567c478bd9Sstevel@tonic-gate "context"); 5577c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, 5587c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 5597c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate s1394_pending_q_insert(to_hal, cmd, S1394_PENDING_Q_FRONT); 5647c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate /* Block (if necessary) */ 5677c478bd9Sstevel@tonic-gate goto block_on_asynch_cmd; 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* Send the command out */ 5727c478bd9Sstevel@tonic-gate ret = s1394_xfer_asynch_command(to_hal, cmd, &err); 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 5757c478bd9Sstevel@tonic-gate if (err == CMD1394_ESTALE_GENERATION) { 5767c478bd9Sstevel@tonic-gate /* Remove cmd from outstanding request Q */ 5777c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(to_hal, cmd); 5787c478bd9Sstevel@tonic-gate s1394_pending_q_insert(to_hal, cmd, 5797c478bd9Sstevel@tonic-gate S1394_PENDING_Q_FRONT); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* Block (if necessary) */ 5827c478bd9Sstevel@tonic-gate goto block_on_asynch_cmd; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate } else { 5857c478bd9Sstevel@tonic-gate /* Remove cmd from outstanding request Q */ 5867c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(to_hal, cmd); 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate s_priv->cmd_in_use = B_FALSE; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* Copy error code into result */ 5917c478bd9Sstevel@tonic-gate cmd->cmd_result = err; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_read_error, S1394_TNF_SL_ATREQ_ERROR, 5947c478bd9Sstevel@tonic-gate "", tnf_string, msg, "Failed in " 5957c478bd9Sstevel@tonic-gate "s1394_xfer_asynch_command()"); 5967c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, 5977c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 5987c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate } else { 6017c478bd9Sstevel@tonic-gate /* Block (if necessary) */ 6027c478bd9Sstevel@tonic-gate goto block_on_asynch_cmd; 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate block_on_asynch_cmd: 6067c478bd9Sstevel@tonic-gate s1394_block_on_asynch_cmd(cmd); 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_read_exit, 6097c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 6107c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Function: t1394_write() 6157c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 6167c478bd9Sstevel@tonic-gate * t1394_attach() 6177c478bd9Sstevel@tonic-gate * cmd Pointer to the command to send 6187c478bd9Sstevel@tonic-gate * 6197c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successful sent the command 6207c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to send command 6217c478bd9Sstevel@tonic-gate * 6227c478bd9Sstevel@tonic-gate * Description: t1394_write() attempts to send an asynchronous write request 6237c478bd9Sstevel@tonic-gate * onto the 1394 bus. 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate int 6267c478bd9Sstevel@tonic-gate t1394_write(t1394_handle_t t1394_hdl, cmd1394_cmd_t *cmd) 6277c478bd9Sstevel@tonic-gate { 6287c478bd9Sstevel@tonic-gate s1394_hal_t *to_hal; 6297c478bd9Sstevel@tonic-gate s1394_target_t *target; 6307c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 6317c478bd9Sstevel@tonic-gate s1394_hal_state_t state; 6327c478bd9Sstevel@tonic-gate int ret; 6337c478bd9Sstevel@tonic-gate int err; 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_enter, S1394_TNF_SL_ATREQ_STACK, ""); 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 6387c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 6417c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(cmd); 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate /* Is this command currently in use? */ 6447c478bd9Sstevel@tonic-gate if (s_priv->cmd_in_use == B_TRUE) { 6457c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_write_error, S1394_TNF_SL_ATREQ_ERROR, "", 6467c478bd9Sstevel@tonic-gate tnf_string, msg, "Attempted to resend an in-use command"); 6477c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK, 6487c478bd9Sstevel@tonic-gate ""); 6497c478bd9Sstevel@tonic-gate ASSERT(s_priv->cmd_in_use == B_FALSE); 6507c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* Set-up the destination of the command */ 6567c478bd9Sstevel@tonic-gate to_hal = target->on_hal; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* Is this an FA request? */ 6597c478bd9Sstevel@tonic-gate if (s_priv->cmd_ext_type == S1394_CMD_EXT_FA) { 6607c478bd9Sstevel@tonic-gate if (S1394_IS_CMD_FCP(s_priv) && 6617c478bd9Sstevel@tonic-gate (s1394_fcp_write_check_cmd(cmd) != DDI_SUCCESS)) { 6627c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, 6637c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 6647c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate s1394_fa_convert_cmd(to_hal, cmd); 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate /* No status (default) */ 6707c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_NOSTATUS; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* Check for proper command type */ 6737c478bd9Sstevel@tonic-gate if ((cmd->cmd_type != CMD1394_ASYNCH_WR_QUAD) && 6747c478bd9Sstevel@tonic-gate (cmd->cmd_type != CMD1394_ASYNCH_WR_BLOCK)) { 6757c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_COMMAND; 6767c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(to_hal, cmd); 6777c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_write_error, S1394_TNF_SL_ATREQ_ERROR, "", 6787c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid command type specified"); 6797c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK, 6807c478bd9Sstevel@tonic-gate ""); 6817c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* Is this a blocking command on interrupt stack? */ 6857c478bd9Sstevel@tonic-gate if ((cmd->cmd_options & CMD1394_BLOCKING) && 68680a70ef3Sap25164 (servicing_interrupt())) { 6877c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_CONTEXT; 6887c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(to_hal, cmd); 6897c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_write_error, S1394_TNF_SL_ATREQ_ERROR, "", 6907c478bd9Sstevel@tonic-gate tnf_string, msg, "Tried to use CMD1394_BLOCKING in intr " 6917c478bd9Sstevel@tonic-gate "context"); 6927c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK, 6937c478bd9Sstevel@tonic-gate ""); 6947c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate mutex_enter(&to_hal->topology_tree_mutex); 6987c478bd9Sstevel@tonic-gate state = to_hal->hal_state; 6997c478bd9Sstevel@tonic-gate if (state != S1394_HAL_NORMAL) { 7007c478bd9Sstevel@tonic-gate ret = s1394_HAL_asynch_error(to_hal, cmd, state); 7017c478bd9Sstevel@tonic-gate if (ret != CMD1394_CMDSUCCESS) { 7027c478bd9Sstevel@tonic-gate cmd->cmd_result = ret; 7037c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 7047c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(to_hal, cmd); 7057c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate ret = s1394_setup_asynch_command(to_hal, target, cmd, 7107c478bd9Sstevel@tonic-gate S1394_CMD_WRITE, &err); 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate /* Command has now been put onto the queue! */ 7137c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 7147c478bd9Sstevel@tonic-gate /* Copy error code into result */ 7157c478bd9Sstevel@tonic-gate cmd->cmd_result = err; 7167c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 7177c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(to_hal, cmd); 7187c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_write_error, S1394_TNF_SL_ATREQ_ERROR, "", 7197c478bd9Sstevel@tonic-gate tnf_string, msg, "Failed in s1394_setup_asynch_command()"); 7207c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK, 7217c478bd9Sstevel@tonic-gate ""); 7227c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate /* 7267c478bd9Sstevel@tonic-gate * If this command was sent during a bus reset, 7277c478bd9Sstevel@tonic-gate * then put it onto the pending Q. 7287c478bd9Sstevel@tonic-gate */ 7297c478bd9Sstevel@tonic-gate if (state == S1394_HAL_RESET) { 7307c478bd9Sstevel@tonic-gate /* Remove cmd from outstanding request Q */ 7317c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(to_hal, cmd); 7327c478bd9Sstevel@tonic-gate /* Are we on the bus reset event stack? */ 7337c478bd9Sstevel@tonic-gate if (s1394_on_br_thread(to_hal) == B_TRUE) { 7347c478bd9Sstevel@tonic-gate /* Blocking commands are not allowed */ 7357c478bd9Sstevel@tonic-gate if (cmd->cmd_options & CMD1394_BLOCKING) { 7367c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 7377c478bd9Sstevel@tonic-gate s_priv->cmd_in_use = B_FALSE; 7387c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_CONTEXT; 7397c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(to_hal, cmd); 7407c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_write_error, 7417c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, 7427c478bd9Sstevel@tonic-gate msg, "CMD1394_BLOCKING in bus reset cntxt"); 7437c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, 7447c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 7457c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate s1394_pending_q_insert(to_hal, cmd, S1394_PENDING_Q_FRONT); 7507c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* Block (if necessary) */ 7537c478bd9Sstevel@tonic-gate s1394_block_on_asynch_cmd(cmd); 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK, 7567c478bd9Sstevel@tonic-gate ""); 7577c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate /* Send the command out */ 7627c478bd9Sstevel@tonic-gate ret = s1394_xfer_asynch_command(to_hal, cmd, &err); 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 7657c478bd9Sstevel@tonic-gate if (err == CMD1394_ESTALE_GENERATION) { 7667c478bd9Sstevel@tonic-gate /* Remove cmd from outstanding request Q */ 7677c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(to_hal, cmd); 7687c478bd9Sstevel@tonic-gate s1394_pending_q_insert(to_hal, cmd, 7697c478bd9Sstevel@tonic-gate S1394_PENDING_Q_FRONT); 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* Block (if necessary) */ 7727c478bd9Sstevel@tonic-gate s1394_block_on_asynch_cmd(cmd); 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, 7757c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 7767c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 7777c478bd9Sstevel@tonic-gate } else { 7787c478bd9Sstevel@tonic-gate /* Remove cmd from outstanding request Q */ 7797c478bd9Sstevel@tonic-gate s1394_remove_q_asynch_cmd(to_hal, cmd); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate s_priv->cmd_in_use = B_FALSE; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate /* Copy error code into result */ 7847c478bd9Sstevel@tonic-gate cmd->cmd_result = err; 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(to_hal, cmd); 7877c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_write_error, 7887c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_ERROR, "", tnf_string, msg, 7897c478bd9Sstevel@tonic-gate "Failed in s1394_xfer_asynch_command()"); 7907c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, 7917c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_STACK, ""); 7927c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate } else { 7957c478bd9Sstevel@tonic-gate /* Block (if necessary) */ 7967c478bd9Sstevel@tonic-gate s1394_block_on_asynch_cmd(cmd); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK, 7997c478bd9Sstevel@tonic-gate ""); 8007c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * Function: t1394_lock() 8067c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 8077c478bd9Sstevel@tonic-gate * t1394_attach() 8087c478bd9Sstevel@tonic-gate * cmd Pointer to the command to send 8097c478bd9Sstevel@tonic-gate * 8107c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successful sent the command 8117c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to send command 8127c478bd9Sstevel@tonic-gate * 8137c478bd9Sstevel@tonic-gate * Description: t1394_lock() attempts to send an asynchronous lock request 8147c478bd9Sstevel@tonic-gate * onto the 1394 bus. 8157c478bd9Sstevel@tonic-gate */ 8167c478bd9Sstevel@tonic-gate int 8177c478bd9Sstevel@tonic-gate t1394_lock(t1394_handle_t t1394_hdl, cmd1394_cmd_t *cmd) 8187c478bd9Sstevel@tonic-gate { 8197c478bd9Sstevel@tonic-gate s1394_hal_t *to_hal; 8207c478bd9Sstevel@tonic-gate s1394_target_t *target; 8217c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 8227c478bd9Sstevel@tonic-gate s1394_hal_state_t state; 8237c478bd9Sstevel@tonic-gate cmd1394_lock_type_t lock_type; 8247c478bd9Sstevel@tonic-gate uint_t num_retries; 8257c478bd9Sstevel@tonic-gate int ret; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_lock_enter, S1394_TNF_SL_ATREQ_STACK, ""); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 8307c478bd9Sstevel@tonic-gate ASSERT(cmd != NULL); 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 8337c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(cmd); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate /* Is this command currently in use? */ 8367c478bd9Sstevel@tonic-gate if (s_priv->cmd_in_use == B_TRUE) { 8377c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_lock_error, S1394_TNF_SL_ATREQ_ERROR, "", 8387c478bd9Sstevel@tonic-gate tnf_string, msg, "Attempted to resend an in-use command"); 8397c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_lock_exit, S1394_TNF_SL_ATREQ_STACK, 8407c478bd9Sstevel@tonic-gate ""); 8417c478bd9Sstevel@tonic-gate ASSERT(s_priv->cmd_in_use == B_FALSE); 8427c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* Set-up the destination of the command */ 8487c478bd9Sstevel@tonic-gate to_hal = target->on_hal; 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate mutex_enter(&to_hal->topology_tree_mutex); 8517c478bd9Sstevel@tonic-gate state = to_hal->hal_state; 8527c478bd9Sstevel@tonic-gate if (state != S1394_HAL_NORMAL) { 8537c478bd9Sstevel@tonic-gate ret = s1394_HAL_asynch_error(to_hal, cmd, state); 8547c478bd9Sstevel@tonic-gate if (ret != CMD1394_CMDSUCCESS) { 8557c478bd9Sstevel@tonic-gate cmd->cmd_result = ret; 8567c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 8577c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate mutex_exit(&to_hal->topology_tree_mutex); 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate /* Check for proper command type */ 8637c478bd9Sstevel@tonic-gate if ((cmd->cmd_type != CMD1394_ASYNCH_LOCK_32) && 8647c478bd9Sstevel@tonic-gate (cmd->cmd_type != CMD1394_ASYNCH_LOCK_64)) { 8657c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_COMMAND; 8667c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_lock_error, S1394_TNF_SL_ATREQ_ERROR, "", 8677c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid command type sent to " 8687c478bd9Sstevel@tonic-gate "t1394_lock()"); 8697c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_lock_exit, S1394_TNF_SL_ATREQ_STACK, 8707c478bd9Sstevel@tonic-gate ""); 8717c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate /* No status (default) */ 8757c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_NOSTATUS; 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate /* Is this a blocking command on interrupt stack? */ 8787c478bd9Sstevel@tonic-gate if ((cmd->cmd_options & CMD1394_BLOCKING) && 87980a70ef3Sap25164 (servicing_interrupt())) { 8807c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_CONTEXT; 8817c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_lock_error, S1394_TNF_SL_ATREQ_ERROR, "", 8827c478bd9Sstevel@tonic-gate tnf_string, msg, "Tried to use CMD1394_BLOCKING in intr " 8837c478bd9Sstevel@tonic-gate "context"); 8847c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_lock_exit, S1394_TNF_SL_ATREQ_STACK, 8857c478bd9Sstevel@tonic-gate ""); 8867c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) { 8907c478bd9Sstevel@tonic-gate lock_type = cmd->cmd_u.l32.lock_type; 8917c478bd9Sstevel@tonic-gate num_retries = cmd->cmd_u.l32.num_retries; 8927c478bd9Sstevel@tonic-gate } else { /* (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) */ 8937c478bd9Sstevel@tonic-gate lock_type = cmd->cmd_u.l64.lock_type; 8947c478bd9Sstevel@tonic-gate num_retries = cmd->cmd_u.l64.num_retries; 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate /* Make sure num_retries is reasonable */ 8987c478bd9Sstevel@tonic-gate ASSERT(num_retries <= MAX_NUMBER_OF_LOCK_RETRIES); 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate switch (lock_type) { 9017c478bd9Sstevel@tonic-gate case CMD1394_LOCK_MASK_SWAP: 9027c478bd9Sstevel@tonic-gate case CMD1394_LOCK_FETCH_ADD: 9037c478bd9Sstevel@tonic-gate case CMD1394_LOCK_LITTLE_ADD: 9047c478bd9Sstevel@tonic-gate case CMD1394_LOCK_BOUNDED_ADD: 9057c478bd9Sstevel@tonic-gate case CMD1394_LOCK_WRAP_ADD: 9067c478bd9Sstevel@tonic-gate case CMD1394_LOCK_COMPARE_SWAP: 9077c478bd9Sstevel@tonic-gate ret = s1394_compare_swap(to_hal, target, cmd); 9087c478bd9Sstevel@tonic-gate break; 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate case CMD1394_LOCK_BIT_AND: 9117c478bd9Sstevel@tonic-gate case CMD1394_LOCK_BIT_OR: 9127c478bd9Sstevel@tonic-gate case CMD1394_LOCK_BIT_XOR: 9137c478bd9Sstevel@tonic-gate case CMD1394_LOCK_INCREMENT: 9147c478bd9Sstevel@tonic-gate case CMD1394_LOCK_DECREMENT: 9157c478bd9Sstevel@tonic-gate case CMD1394_LOCK_ADD: 9167c478bd9Sstevel@tonic-gate case CMD1394_LOCK_SUBTRACT: 9177c478bd9Sstevel@tonic-gate case CMD1394_LOCK_THRESH_ADD: 9187c478bd9Sstevel@tonic-gate case CMD1394_LOCK_THRESH_SUBTRACT: 9197c478bd9Sstevel@tonic-gate case CMD1394_LOCK_CLIP_ADD: 9207c478bd9Sstevel@tonic-gate case CMD1394_LOCK_CLIP_SUBTRACT: 9217c478bd9Sstevel@tonic-gate ret = s1394_split_lock_req(to_hal, target, cmd); 9227c478bd9Sstevel@tonic-gate break; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate default: 9257c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_lock_error, S1394_TNF_SL_ATREQ_ERROR, "", 9267c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid lock_type in command"); 9277c478bd9Sstevel@tonic-gate cmd->cmd_result = CMD1394_EINVALID_COMMAND; 9287c478bd9Sstevel@tonic-gate ret = DDI_FAILURE; 9297c478bd9Sstevel@tonic-gate break; 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_lock_exit, S1394_TNF_SL_ATREQ_STACK, ""); 9337c478bd9Sstevel@tonic-gate return (ret); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate * Function: t1394_alloc_addr() 9387c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 9397c478bd9Sstevel@tonic-gate * t1394_attach() 9407c478bd9Sstevel@tonic-gate * addr_allocp The structure used to specify the type, 9417c478bd9Sstevel@tonic-gate * size, permissions, and callbacks 9427c478bd9Sstevel@tonic-gate * (if any) for the requested block 9437c478bd9Sstevel@tonic-gate * of 1394 address space 9447c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 9457c478bd9Sstevel@tonic-gate * 9467c478bd9Sstevel@tonic-gate * Output(s): result Used to pass more specific info back 9477c478bd9Sstevel@tonic-gate * to target 9487c478bd9Sstevel@tonic-gate * 9497c478bd9Sstevel@tonic-gate * Description: t1394_alloc_addr() requests that part of the 1394 Address Space 9507c478bd9Sstevel@tonic-gate * on the local node be set aside for this target driver, and 9517c478bd9Sstevel@tonic-gate * associated with this address space should be some permissions 9527c478bd9Sstevel@tonic-gate * and callbacks. If the request is unable to be fulfilled, 9537c478bd9Sstevel@tonic-gate * t1394_alloc_addr() will return DDI_FAILURE and result will 9547c478bd9Sstevel@tonic-gate * indicate the reason. T1394_EINVALID_PARAM indicates that the 9557c478bd9Sstevel@tonic-gate * combination of flags given is invalid, and T1394_EALLOC_ADDR 9567c478bd9Sstevel@tonic-gate * indicates that the requested type of address space is 9577c478bd9Sstevel@tonic-gate * unavailable. 9587c478bd9Sstevel@tonic-gate */ 9597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9607c478bd9Sstevel@tonic-gate int 9617c478bd9Sstevel@tonic-gate t1394_alloc_addr(t1394_handle_t t1394_hdl, t1394_alloc_addr_t *addr_allocp, 9627c478bd9Sstevel@tonic-gate uint_t flags, int *result) 9637c478bd9Sstevel@tonic-gate { 9647c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 9657c478bd9Sstevel@tonic-gate s1394_target_t *target; 9667c478bd9Sstevel@tonic-gate uint64_t addr_lo; 9677c478bd9Sstevel@tonic-gate uint64_t addr_hi; 9687c478bd9Sstevel@tonic-gate int err; 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_addr_enter, S1394_TNF_SL_ARREQ_STACK, 9717c478bd9Sstevel@tonic-gate ""); 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 9747c478bd9Sstevel@tonic-gate ASSERT(addr_allocp != NULL); 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 9797c478bd9Sstevel@tonic-gate hal = target->on_hal; 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate /* Get the bounds of the request */ 9827c478bd9Sstevel@tonic-gate addr_lo = addr_allocp->aa_address; 9837c478bd9Sstevel@tonic-gate addr_hi = addr_lo + addr_allocp->aa_length; 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate /* Check combination of flags */ 9867c478bd9Sstevel@tonic-gate if ((addr_allocp->aa_enable & T1394_ADDR_RDENBL) && 9877c478bd9Sstevel@tonic-gate (addr_allocp->aa_evts.recv_read_request == NULL) && 9887c478bd9Sstevel@tonic-gate (addr_allocp->aa_kmem_bufp == NULL)) { 9897c478bd9Sstevel@tonic-gate if ((addr_allocp->aa_type != T1394_ADDR_FIXED) || 9907c478bd9Sstevel@tonic-gate (addr_lo < hal->physical_addr_lo) || 9917c478bd9Sstevel@tonic-gate (addr_hi > hal->physical_addr_hi)) { 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate /* 9947c478bd9Sstevel@tonic-gate * Reads are enabled, but target doesn't want to 9957c478bd9Sstevel@tonic-gate * be notified and hasn't given backing store 9967c478bd9Sstevel@tonic-gate */ 9977c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_PARAM; 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_addr_error, 10007c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 10017c478bd9Sstevel@tonic-gate "Invalid flags " 10027c478bd9Sstevel@tonic-gate "(RDs on, notify off, no backing store)"); 10037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_addr_exit, 10047c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate /* kstats - addr alloc failures */ 10077c478bd9Sstevel@tonic-gate hal->hal_kstats->addr_alloc_fail++; 10087c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10097c478bd9Sstevel@tonic-gate } else { 10107c478bd9Sstevel@tonic-gate addr_allocp->aa_enable &= ~T1394_ADDR_RDENBL; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate if ((addr_allocp->aa_enable & T1394_ADDR_WRENBL) && 10157c478bd9Sstevel@tonic-gate (addr_allocp->aa_evts.recv_write_request == NULL) && 10167c478bd9Sstevel@tonic-gate (addr_allocp->aa_kmem_bufp == NULL)) { 10177c478bd9Sstevel@tonic-gate if ((addr_allocp->aa_type != T1394_ADDR_FIXED) || 10187c478bd9Sstevel@tonic-gate (addr_lo < hal->physical_addr_lo) || 10197c478bd9Sstevel@tonic-gate (addr_hi > hal->physical_addr_hi)) { 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* 10227c478bd9Sstevel@tonic-gate * Writes are enabled, but target doesn't want to 10237c478bd9Sstevel@tonic-gate * be notified and hasn't given backing store 10247c478bd9Sstevel@tonic-gate */ 10257c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_PARAM; 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_addr_error, 10287c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 10297c478bd9Sstevel@tonic-gate "Invalid flags " 10307c478bd9Sstevel@tonic-gate "(WRs on, notify off, no backing store)"); 10317c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_addr_exit, 10327c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate /* kstats - addr alloc failures */ 10357c478bd9Sstevel@tonic-gate hal->hal_kstats->addr_alloc_fail++; 10367c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10377c478bd9Sstevel@tonic-gate } else { 10387c478bd9Sstevel@tonic-gate addr_allocp->aa_enable &= ~T1394_ADDR_WRENBL; 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate if ((addr_allocp->aa_enable & T1394_ADDR_LKENBL) && 10437c478bd9Sstevel@tonic-gate (addr_allocp->aa_evts.recv_lock_request == NULL) && 10447c478bd9Sstevel@tonic-gate (addr_allocp->aa_kmem_bufp == NULL)) { 10457c478bd9Sstevel@tonic-gate if ((addr_allocp->aa_type != T1394_ADDR_FIXED) || 10467c478bd9Sstevel@tonic-gate (addr_lo < hal->physical_addr_lo) || 10477c478bd9Sstevel@tonic-gate (addr_hi > hal->physical_addr_hi)) { 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate /* 10507c478bd9Sstevel@tonic-gate * Locks are enabled, but target doesn't want to 10517c478bd9Sstevel@tonic-gate * be notified and hasn't given backing store 10527c478bd9Sstevel@tonic-gate */ 10537c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_PARAM; 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_addr_error, 10567c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 10577c478bd9Sstevel@tonic-gate "Invalid flags " 10587c478bd9Sstevel@tonic-gate "(LKs on, notify off, no backing store)"); 10597c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_addr_exit, 10607c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate /* kstats - addr alloc failures */ 10637c478bd9Sstevel@tonic-gate hal->hal_kstats->addr_alloc_fail++; 10647c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10657c478bd9Sstevel@tonic-gate } else { 10667c478bd9Sstevel@tonic-gate addr_allocp->aa_enable &= ~T1394_ADDR_LKENBL; 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate /* If not T1394_ADDR_FIXED, then allocate a block */ 10717c478bd9Sstevel@tonic-gate if (addr_allocp->aa_type != T1394_ADDR_FIXED) { 10727c478bd9Sstevel@tonic-gate err = s1394_request_addr_blk((s1394_hal_t *)target->on_hal, 10737c478bd9Sstevel@tonic-gate addr_allocp); 10747c478bd9Sstevel@tonic-gate if (err != DDI_SUCCESS) { 10757c478bd9Sstevel@tonic-gate *result = T1394_EALLOC_ADDR; 10767c478bd9Sstevel@tonic-gate /* kstats - addr alloc failures */ 10777c478bd9Sstevel@tonic-gate hal->hal_kstats->addr_alloc_fail++; 10787c478bd9Sstevel@tonic-gate } else { 10797c478bd9Sstevel@tonic-gate *result = T1394_NOERROR; 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_addr_exit, 10827c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 10837c478bd9Sstevel@tonic-gate return (err); 10847c478bd9Sstevel@tonic-gate } else { 10857c478bd9Sstevel@tonic-gate err = s1394_claim_addr_blk((s1394_hal_t *)target->on_hal, 10867c478bd9Sstevel@tonic-gate addr_allocp); 10877c478bd9Sstevel@tonic-gate if (err != DDI_SUCCESS) { 10887c478bd9Sstevel@tonic-gate *result = T1394_EALLOC_ADDR; 10897c478bd9Sstevel@tonic-gate /* kstats - addr alloc failures */ 10907c478bd9Sstevel@tonic-gate hal->hal_kstats->addr_alloc_fail++; 10917c478bd9Sstevel@tonic-gate } else { 10927c478bd9Sstevel@tonic-gate *result = T1394_NOERROR; 10937c478bd9Sstevel@tonic-gate /* If physical, update the AR request counter */ 10947c478bd9Sstevel@tonic-gate if ((addr_lo >= hal->physical_addr_lo) && 10957c478bd9Sstevel@tonic-gate (addr_hi <= hal->physical_addr_hi)) { 10967c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER); 10977c478bd9Sstevel@tonic-gate target->physical_arreq_enabled++; 10987c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate s1394_physical_arreq_set_one(target); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate } 11037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_addr_exit, 11047c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 11057c478bd9Sstevel@tonic-gate return (err); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate /* 11107c478bd9Sstevel@tonic-gate * Function: t1394_free_addr() 11117c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 11127c478bd9Sstevel@tonic-gate * t1394_attach() 11137c478bd9Sstevel@tonic-gate * addr_hdl The address "handle" returned by the 11147c478bd9Sstevel@tonic-gate * the t1394_alloc_addr() routine 11157c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 11167c478bd9Sstevel@tonic-gate * 11177c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully freed memory 11187c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to free the memory block 11197c478bd9Sstevel@tonic-gate * 11207c478bd9Sstevel@tonic-gate * Description: t1394_free_addr() attempts to free up memory that has been 11217c478bd9Sstevel@tonic-gate * allocated by the target using t1394_alloc_addr(). 11227c478bd9Sstevel@tonic-gate */ 11237c478bd9Sstevel@tonic-gate /* ARGSUSED */ 11247c478bd9Sstevel@tonic-gate int 11257c478bd9Sstevel@tonic-gate t1394_free_addr(t1394_handle_t t1394_hdl, t1394_addr_handle_t *addr_hdl, 11267c478bd9Sstevel@tonic-gate uint_t flags) 11277c478bd9Sstevel@tonic-gate { 11287c478bd9Sstevel@tonic-gate s1394_addr_space_blk_t *curr_blk; 11297c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 11307c478bd9Sstevel@tonic-gate s1394_target_t *target; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_addr_enter, S1394_TNF_SL_ARREQ_STACK, ""); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 11357c478bd9Sstevel@tonic-gate ASSERT(addr_hdl != NULL); 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 11407c478bd9Sstevel@tonic-gate hal = target->on_hal; 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate curr_blk = (s1394_addr_space_blk_t *)(*addr_hdl); 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate if (s1394_free_addr_blk(hal, curr_blk) != DDI_SUCCESS) { 11457c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_addr_exit, 11467c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 11477c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* If physical, update the AR request counter */ 11517c478bd9Sstevel@tonic-gate if (curr_blk->addr_type == T1394_ADDR_FIXED) { 11527c478bd9Sstevel@tonic-gate target->physical_arreq_enabled--; 11537c478bd9Sstevel@tonic-gate s1394_physical_arreq_clear_one(target); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate *addr_hdl = NULL; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate /* kstats - number of addr frees */ 11597c478bd9Sstevel@tonic-gate hal->hal_kstats->addr_space_free++; 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_addr_exit, S1394_TNF_SL_ARREQ_STACK, ""); 11627c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate /* 11667c478bd9Sstevel@tonic-gate * Function: t1394_recv_request_done() 11677c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 11687c478bd9Sstevel@tonic-gate * t1394_attach() 11697c478bd9Sstevel@tonic-gate * resp Pointer to the command which the 11707c478bd9Sstevel@tonic-gate * target received in it's callback 11717c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 11727c478bd9Sstevel@tonic-gate * 11737c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully returned command 11747c478bd9Sstevel@tonic-gate * to the 1394 Software Framework, 11757c478bd9Sstevel@tonic-gate * and, if necessary, sent response 11767c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to return the command to 11777c478bd9Sstevel@tonic-gate * the 1394 Software Framework 11787c478bd9Sstevel@tonic-gate * 11797c478bd9Sstevel@tonic-gate * Description: t1394_recv_request_done() takes the command that is given and 11807c478bd9Sstevel@tonic-gate * determines whether that command requires a response to be 11817c478bd9Sstevel@tonic-gate * sent on the 1394 bus. If it is necessary and it's response 11827c478bd9Sstevel@tonic-gate * code (cmd_result) has been set appropriately, then a response 11837c478bd9Sstevel@tonic-gate * will be sent. If no response is necessary (broadcast or 11847c478bd9Sstevel@tonic-gate * posted write), then the command resources are reclaimed. 11857c478bd9Sstevel@tonic-gate */ 11867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 11877c478bd9Sstevel@tonic-gate int 11887c478bd9Sstevel@tonic-gate t1394_recv_request_done(t1394_handle_t t1394_hdl, cmd1394_cmd_t *resp, 11897c478bd9Sstevel@tonic-gate uint_t flags) 11907c478bd9Sstevel@tonic-gate { 11917c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 11927c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 11937c478bd9Sstevel@tonic-gate h1394_cmd_priv_t *h_priv; 11947c478bd9Sstevel@tonic-gate mblk_t *curr_blk; 11957c478bd9Sstevel@tonic-gate size_t msgb_len; 11967c478bd9Sstevel@tonic-gate size_t size; 11977c478bd9Sstevel@tonic-gate int ret; 11987c478bd9Sstevel@tonic-gate boolean_t response = B_TRUE; 11997c478bd9Sstevel@tonic-gate boolean_t posted_write = B_FALSE; 12007c478bd9Sstevel@tonic-gate boolean_t write_cmd = B_FALSE; 12017c478bd9Sstevel@tonic-gate boolean_t mblk_too_small; 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_recv_request_done_enter, 12047c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 12077c478bd9Sstevel@tonic-gate ASSERT(resp != NULL); 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 12107c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 12137c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(resp); 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate /* Get a pointer to the HAL private struct */ 12167c478bd9Sstevel@tonic-gate h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* Is this an FA request? */ 12197c478bd9Sstevel@tonic-gate if (s_priv->cmd_ext_type == S1394_CMD_EXT_FA) { 12207c478bd9Sstevel@tonic-gate s1394_fa_convert_cmd(hal, resp); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate /* Is this a write request? */ 12247c478bd9Sstevel@tonic-gate if ((resp->cmd_type == CMD1394_ASYNCH_WR_QUAD) || 12257c478bd9Sstevel@tonic-gate (resp->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) { 12267c478bd9Sstevel@tonic-gate write_cmd = B_TRUE; 12277c478bd9Sstevel@tonic-gate /* Is this a posted write request? */ 12287c478bd9Sstevel@tonic-gate posted_write = s_priv->posted_write; 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate /* If broadcast or posted write cmd, don't send response */ 12327c478bd9Sstevel@tonic-gate if ((resp->broadcast == 1) || 12337c478bd9Sstevel@tonic-gate ((write_cmd == B_TRUE) && (posted_write == B_TRUE))) 12347c478bd9Sstevel@tonic-gate response = B_FALSE; 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate if (response == B_FALSE) { 12377c478bd9Sstevel@tonic-gate if ((write_cmd == B_TRUE) && (posted_write == B_TRUE)) { 12387c478bd9Sstevel@tonic-gate /* kstats - Posted Write error */ 12397c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_posted_write_error++; 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate /* Free the command - Pass it back to the HAL */ 12437c478bd9Sstevel@tonic-gate HAL_CALL(hal).response_complete(hal->halinfo.hal_private, resp, 12447c478bd9Sstevel@tonic-gate h_priv); 12457c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_recv_request_done_exit, 12467c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 12477c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate ASSERT(response == B_TRUE); 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate /* Verify valid response code */ 12537c478bd9Sstevel@tonic-gate switch (resp->cmd_result) { 12547c478bd9Sstevel@tonic-gate case IEEE1394_RESP_COMPLETE: 12557c478bd9Sstevel@tonic-gate /* Is the mblk_t too small? */ 12567c478bd9Sstevel@tonic-gate if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK) { 12577c478bd9Sstevel@tonic-gate curr_blk = resp->cmd_u.b.data_block; 12587c478bd9Sstevel@tonic-gate size = resp->cmd_u.b.blk_length; 12597c478bd9Sstevel@tonic-gate msgb_len = 0; 12607c478bd9Sstevel@tonic-gate mblk_too_small = B_TRUE; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate if (curr_blk == NULL) { 12637c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_recv_request_done_error, 12647c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, 12657c478bd9Sstevel@tonic-gate msg, "mblk_t is NULL in response"); 12667c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_recv_request_done_exit, 12677c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 12687c478bd9Sstevel@tonic-gate /* 12697c478bd9Sstevel@tonic-gate * Free the command - Pass it back 12707c478bd9Sstevel@tonic-gate * to the HAL 12717c478bd9Sstevel@tonic-gate */ 12727c478bd9Sstevel@tonic-gate HAL_CALL(hal).response_complete( 12737c478bd9Sstevel@tonic-gate hal->halinfo.hal_private, resp, h_priv); 12747c478bd9Sstevel@tonic-gate ASSERT(curr_blk != NULL); 12757c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate while (curr_blk != NULL) { 12797c478bd9Sstevel@tonic-gate msgb_len += 12807c478bd9Sstevel@tonic-gate (curr_blk->b_wptr - curr_blk->b_rptr); 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate if (msgb_len >= size) { 12837c478bd9Sstevel@tonic-gate mblk_too_small = B_FALSE; 12847c478bd9Sstevel@tonic-gate break; 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate curr_blk = curr_blk->b_cont; 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate if (mblk_too_small == B_TRUE) { 12907c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_recv_request_done_error, 12917c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, 12927c478bd9Sstevel@tonic-gate msg, "mblk_t too small in response"); 12937c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_recv_request_done_exit, 12947c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 12957c478bd9Sstevel@tonic-gate /* 12967c478bd9Sstevel@tonic-gate * Free the command - Pass it back 12977c478bd9Sstevel@tonic-gate * to the HAL 12987c478bd9Sstevel@tonic-gate */ 12997c478bd9Sstevel@tonic-gate HAL_CALL(hal).response_complete( 13007c478bd9Sstevel@tonic-gate hal->halinfo.hal_private, resp, h_priv); 13017c478bd9Sstevel@tonic-gate ASSERT(mblk_too_small != B_TRUE); 13027c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 13067c478bd9Sstevel@tonic-gate case IEEE1394_RESP_CONFLICT_ERROR: 13077c478bd9Sstevel@tonic-gate case IEEE1394_RESP_DATA_ERROR: 13087c478bd9Sstevel@tonic-gate case IEEE1394_RESP_TYPE_ERROR: 13097c478bd9Sstevel@tonic-gate case IEEE1394_RESP_ADDRESS_ERROR: 13107c478bd9Sstevel@tonic-gate ret = s1394_send_response(hal, resp); 13117c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_recv_request_done_exit, 13127c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 13137c478bd9Sstevel@tonic-gate return (ret); 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate default: 13167c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_recv_request_done_error, 13177c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 13187c478bd9Sstevel@tonic-gate "Invalid response code"); 13197c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_recv_request_done_exit, 13207c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 13217c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate /* 13277c478bd9Sstevel@tonic-gate * Function: t1394_fcp_register_controller() 13287c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 13297c478bd9Sstevel@tonic-gate * t1394_attach() 13307c478bd9Sstevel@tonic-gate * evts The structure in which the target 13317c478bd9Sstevel@tonic-gate * specifies its callback routines 13327c478bd9Sstevel@tonic-gate * 13337c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 13347c478bd9Sstevel@tonic-gate * 13357c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully registered. 13367c478bd9Sstevel@tonic-gate * 13377c478bd9Sstevel@tonic-gate * DDI_FAILURE Not registered due to failure. 13387c478bd9Sstevel@tonic-gate * 13397c478bd9Sstevel@tonic-gate * Description: Used to register the target within the Framework as an FCP 13407c478bd9Sstevel@tonic-gate * controller. 13417c478bd9Sstevel@tonic-gate */ 13427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 13437c478bd9Sstevel@tonic-gate int 13447c478bd9Sstevel@tonic-gate t1394_fcp_register_controller(t1394_handle_t t1394_hdl, t1394_fcp_evts_t *evts, 13457c478bd9Sstevel@tonic-gate uint_t flags) 13467c478bd9Sstevel@tonic-gate { 13477c478bd9Sstevel@tonic-gate int result; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_register_controller_enter, 13507c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate result = s1394_fcp_register_ctl((s1394_target_t *)t1394_hdl, evts); 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_register_controller_exit, 13577c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 13587c478bd9Sstevel@tonic-gate return (result); 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate /* 13627c478bd9Sstevel@tonic-gate * Function: t1394_fcp_unregister_controller() 13637c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 13647c478bd9Sstevel@tonic-gate * t1394_attach() 13657c478bd9Sstevel@tonic-gate * 13667c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully unregistered. 13677c478bd9Sstevel@tonic-gate * 13687c478bd9Sstevel@tonic-gate * DDI_FAILURE Not unregistered due to failure. 13697c478bd9Sstevel@tonic-gate * 13707c478bd9Sstevel@tonic-gate * Description: Used to unregister the target within the Framework as an FCP 13717c478bd9Sstevel@tonic-gate * controller. 13727c478bd9Sstevel@tonic-gate */ 13737c478bd9Sstevel@tonic-gate int 13747c478bd9Sstevel@tonic-gate t1394_fcp_unregister_controller(t1394_handle_t t1394_hdl) 13757c478bd9Sstevel@tonic-gate { 13767c478bd9Sstevel@tonic-gate int result; 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_unregister_controller_enter, 13797c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate result = s1394_fcp_unregister_ctl((s1394_target_t *)t1394_hdl); 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_unregister_controller_exit, 13867c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 13877c478bd9Sstevel@tonic-gate return (result); 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate /* 13917c478bd9Sstevel@tonic-gate * Function: t1394_fcp_register_target() 13927c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 13937c478bd9Sstevel@tonic-gate * t1394_attach() 13947c478bd9Sstevel@tonic-gate * evts The structure in which the target 13957c478bd9Sstevel@tonic-gate * specifies its callback routines 13967c478bd9Sstevel@tonic-gate * 13977c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 13987c478bd9Sstevel@tonic-gate * 13997c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully registered. 14007c478bd9Sstevel@tonic-gate * 14017c478bd9Sstevel@tonic-gate * DDI_FAILURE Not registered due to failure. 14027c478bd9Sstevel@tonic-gate * 14037c478bd9Sstevel@tonic-gate * Description: Used to register the target within the Framework as an FCP 14047c478bd9Sstevel@tonic-gate * target. 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14077c478bd9Sstevel@tonic-gate int 14087c478bd9Sstevel@tonic-gate t1394_fcp_register_target(t1394_handle_t t1394_hdl, t1394_fcp_evts_t *evts, 14097c478bd9Sstevel@tonic-gate uint_t flags) 14107c478bd9Sstevel@tonic-gate { 14117c478bd9Sstevel@tonic-gate int result; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_register_target_enter, 14147c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate result = s1394_fcp_register_tgt((s1394_target_t *)t1394_hdl, evts); 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_register_target_exit, 14217c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 14227c478bd9Sstevel@tonic-gate return (result); 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate /* 14267c478bd9Sstevel@tonic-gate * Function: t1394_fcp_unregister_target() 14277c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 14287c478bd9Sstevel@tonic-gate * t1394_attach() 14297c478bd9Sstevel@tonic-gate * 14307c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully unregistered. 14317c478bd9Sstevel@tonic-gate * 14327c478bd9Sstevel@tonic-gate * DDI_FAILURE Not unregistered due to failure. 14337c478bd9Sstevel@tonic-gate * 14347c478bd9Sstevel@tonic-gate * Description: Used to unregister the target within the Framework as an FCP 14357c478bd9Sstevel@tonic-gate * target. 14367c478bd9Sstevel@tonic-gate */ 14377c478bd9Sstevel@tonic-gate int 14387c478bd9Sstevel@tonic-gate t1394_fcp_unregister_target(t1394_handle_t t1394_hdl) 14397c478bd9Sstevel@tonic-gate { 14407c478bd9Sstevel@tonic-gate int result; 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_unregister_target_enter, 14437c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate result = s1394_fcp_unregister_tgt((s1394_target_t *)t1394_hdl); 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_fcp_unregister_target_exit, 14507c478bd9Sstevel@tonic-gate S1394_TNF_SL_FCP_STACK, ""); 14517c478bd9Sstevel@tonic-gate return (result); 14527c478bd9Sstevel@tonic-gate } 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate /* 14557c478bd9Sstevel@tonic-gate * Function: t1394_cmp_register() 14567c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 14577c478bd9Sstevel@tonic-gate * t1394_attach() 14587c478bd9Sstevel@tonic-gate * evts The structure in which the target 14597c478bd9Sstevel@tonic-gate * specifies its callback routines 14607c478bd9Sstevel@tonic-gate * 14617c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully registered. 14627c478bd9Sstevel@tonic-gate * 14637c478bd9Sstevel@tonic-gate * DDI_FAILURE Not registered due to failure. 14647c478bd9Sstevel@tonic-gate * 14657c478bd9Sstevel@tonic-gate * Description: Used to register the target within the Framework as a CMP 14667c478bd9Sstevel@tonic-gate * device. 14677c478bd9Sstevel@tonic-gate */ 14687c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14697c478bd9Sstevel@tonic-gate int 14707c478bd9Sstevel@tonic-gate t1394_cmp_register(t1394_handle_t t1394_hdl, t1394_cmp_evts_t *evts, 14717c478bd9Sstevel@tonic-gate uint_t flags) 14727c478bd9Sstevel@tonic-gate { 14737c478bd9Sstevel@tonic-gate int result; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_register_enter, S1394_TNF_SL_CMP_STACK, ""); 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate result = s1394_cmp_register((s1394_target_t *)t1394_hdl, evts); 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_register_exit, S1394_TNF_SL_CMP_STACK, ""); 14827c478bd9Sstevel@tonic-gate return (result); 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate /* 14867c478bd9Sstevel@tonic-gate * Function: t1394_cmp_unregister() 14877c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 14887c478bd9Sstevel@tonic-gate * t1394_attach() 14897c478bd9Sstevel@tonic-gate * evts The structure in which the target 14907c478bd9Sstevel@tonic-gate * specifies its callback routines 14917c478bd9Sstevel@tonic-gate * 14927c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully registered. 14937c478bd9Sstevel@tonic-gate * 14947c478bd9Sstevel@tonic-gate * DDI_FAILURE Not registered due to failure. 14957c478bd9Sstevel@tonic-gate * 14967c478bd9Sstevel@tonic-gate * Description: Used to unregister the target within the Framework as a CMP 14977c478bd9Sstevel@tonic-gate * device. 14987c478bd9Sstevel@tonic-gate */ 14997c478bd9Sstevel@tonic-gate int 15007c478bd9Sstevel@tonic-gate t1394_cmp_unregister(t1394_handle_t t1394_hdl) 15017c478bd9Sstevel@tonic-gate { 15027c478bd9Sstevel@tonic-gate int result; 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_unregister_enter, S1394_TNF_SL_CMP_STACK, 15057c478bd9Sstevel@tonic-gate ""); 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate result = s1394_cmp_unregister((s1394_target_t *)t1394_hdl); 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_unregister_exit, S1394_TNF_SL_CMP_STACK, 15127c478bd9Sstevel@tonic-gate ""); 15137c478bd9Sstevel@tonic-gate return (result); 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate /* 15177c478bd9Sstevel@tonic-gate * Function: t1394_cmp_read() 15187c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 15197c478bd9Sstevel@tonic-gate * t1394_attach() 15207c478bd9Sstevel@tonic-gate * reg Register type. 15217c478bd9Sstevel@tonic-gate * valp Returned register value. 15227c478bd9Sstevel@tonic-gate * 15237c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully registered. 15247c478bd9Sstevel@tonic-gate * 15257c478bd9Sstevel@tonic-gate * DDI_FAILURE Not registered due to failure. 15267c478bd9Sstevel@tonic-gate * 15277c478bd9Sstevel@tonic-gate * Description: Used to read a CMP register value. 15287c478bd9Sstevel@tonic-gate */ 15297c478bd9Sstevel@tonic-gate int 15307c478bd9Sstevel@tonic-gate t1394_cmp_read(t1394_handle_t t1394_hdl, t1394_cmp_reg_t reg, uint32_t *valp) 15317c478bd9Sstevel@tonic-gate { 15327c478bd9Sstevel@tonic-gate int result; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_read_enter, S1394_TNF_SL_CMP_STACK, ""); 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate result = s1394_cmp_read((s1394_target_t *)t1394_hdl, reg, valp); 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_read_exit, S1394_TNF_SL_CMP_STACK, ""); 15417c478bd9Sstevel@tonic-gate return (result); 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate /* 15457c478bd9Sstevel@tonic-gate * Function: t1394_cmp_cas() 15467c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 15477c478bd9Sstevel@tonic-gate * t1394_attach() 15487c478bd9Sstevel@tonic-gate * reg Register type. 15497c478bd9Sstevel@tonic-gate * arg_val Compare argument. 15507c478bd9Sstevel@tonic-gate * new_val New register value. 15517c478bd9Sstevel@tonic-gate * old_valp Returned original register value. 15527c478bd9Sstevel@tonic-gate * 15537c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Successfully registered. 15547c478bd9Sstevel@tonic-gate * 15557c478bd9Sstevel@tonic-gate * DDI_FAILURE Not registered due to failure. 15567c478bd9Sstevel@tonic-gate * 15577c478bd9Sstevel@tonic-gate * Description: Used to compare-swap a CMP register value. 15587c478bd9Sstevel@tonic-gate */ 15597c478bd9Sstevel@tonic-gate int 15607c478bd9Sstevel@tonic-gate t1394_cmp_cas(t1394_handle_t t1394_hdl, t1394_cmp_reg_t reg, uint32_t arg_val, 15617c478bd9Sstevel@tonic-gate uint32_t new_val, uint32_t *old_valp) 15627c478bd9Sstevel@tonic-gate { 15637c478bd9Sstevel@tonic-gate int result; 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_read_enter, S1394_TNF_SL_CMP_STACK, ""); 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate result = s1394_cmp_cas((s1394_target_t *)t1394_hdl, reg, arg_val, 15707c478bd9Sstevel@tonic-gate new_val, old_valp); 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_cmp_read_exit, S1394_TNF_SL_CMP_STACK, ""); 15737c478bd9Sstevel@tonic-gate return (result); 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate /* 15777c478bd9Sstevel@tonic-gate * Function: t1394_alloc_isoch_single() 15787c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 15797c478bd9Sstevel@tonic-gate * t1394_attach() 15807c478bd9Sstevel@tonic-gate * sii The structure used to set up the 15817c478bd9Sstevel@tonic-gate * overall characteristics of the 15827c478bd9Sstevel@tonic-gate * isochronous stream 15837c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 15847c478bd9Sstevel@tonic-gate * 15857c478bd9Sstevel@tonic-gate * Output(s): setup_args Contains the channel number that was 15867c478bd9Sstevel@tonic-gate * allocated 15877c478bd9Sstevel@tonic-gate * t1394_single_hdl This in the isoch "handle" used in 15887c478bd9Sstevel@tonic-gate * t1394_free_isoch_single() 15897c478bd9Sstevel@tonic-gate * result Used to pass more specific info back 15907c478bd9Sstevel@tonic-gate * to target 15917c478bd9Sstevel@tonic-gate * 15927c478bd9Sstevel@tonic-gate * Description: t1394_alloc_isoch_single() is used to direct the 1394 Software 15937c478bd9Sstevel@tonic-gate * Framework to allocate an isochronous channel and bandwidth 15947c478bd9Sstevel@tonic-gate * from the Isochronous Resource Manager (IRM). If a bus reset 15957c478bd9Sstevel@tonic-gate * occurs, the 1394 Software Framework attempts to reallocate the 15967c478bd9Sstevel@tonic-gate * same resources, calling the rsrc_fail_target() callback if 15977c478bd9Sstevel@tonic-gate * it is unsuccessful. 15987c478bd9Sstevel@tonic-gate */ 15997c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16007c478bd9Sstevel@tonic-gate int 16017c478bd9Sstevel@tonic-gate t1394_alloc_isoch_single(t1394_handle_t t1394_hdl, 16027c478bd9Sstevel@tonic-gate t1394_isoch_singleinfo_t *sii, uint_t flags, 16037c478bd9Sstevel@tonic-gate t1394_isoch_single_out_t *output_args, 16047c478bd9Sstevel@tonic-gate t1394_isoch_single_handle_t *t1394_single_hdl, int *result) 16057c478bd9Sstevel@tonic-gate { 16067c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 16077c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_new; 16087c478bd9Sstevel@tonic-gate t1394_join_isochinfo_t jii; 16097c478bd9Sstevel@tonic-gate int ret; 16107c478bd9Sstevel@tonic-gate int err; 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_enter, 16137c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 16167c478bd9Sstevel@tonic-gate ASSERT(t1394_single_hdl != NULL); 16177c478bd9Sstevel@tonic-gate ASSERT(sii != NULL); 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate /* Check for invalid channel_mask */ 16227c478bd9Sstevel@tonic-gate if (sii->si_channel_mask == 0) { 16237c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 16247c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 16257c478bd9Sstevel@tonic-gate "Invalid channel mask"); 16267c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_exit, 16277c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 16287c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate /* Check for invalid bandwidth */ 16327c478bd9Sstevel@tonic-gate if ((sii->si_bandwidth <= IEEE1394_BANDWIDTH_MIN) || 16337c478bd9Sstevel@tonic-gate (sii->si_bandwidth > IEEE1394_BANDWIDTH_MAX)) { 16347c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 16357c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 16367c478bd9Sstevel@tonic-gate "Invalid bandwidth requirements"); 16377c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_exit, 16387c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 16397c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 16407c478bd9Sstevel@tonic-gate } 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate /* Verify that rsrc_fail_target() callback is non-NULL */ 16437c478bd9Sstevel@tonic-gate if (sii->rsrc_fail_target == NULL) { 16447c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 16457c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 16467c478bd9Sstevel@tonic-gate "Invalid callback specified"); 16477c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_exit, 16487c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 16497c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate /* 16537c478bd9Sstevel@tonic-gate * Allocate an Isoch CEC of type S1394_SINGLE 16547c478bd9Sstevel@tonic-gate */ 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* Allocate the Isoch CEC structure */ 16577c478bd9Sstevel@tonic-gate cec_new = kmem_zalloc(sizeof (s1394_isoch_cec_t), KM_SLEEP); 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate /* Initialize the structure type */ 16607c478bd9Sstevel@tonic-gate cec_new->cec_type = S1394_SINGLE; 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate /* Create the mutex and "in_callbacks" cv */ 16637c478bd9Sstevel@tonic-gate mutex_init(&cec_new->isoch_cec_mutex, NULL, MUTEX_DRIVER, 16647c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 16657c478bd9Sstevel@tonic-gate cv_init(&cec_new->in_callbacks_cv, NULL, CV_DRIVER, 16667c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate /* Initialize the Isoch CEC's member list */ 16697c478bd9Sstevel@tonic-gate cec_new->cec_member_list_head = NULL; 16707c478bd9Sstevel@tonic-gate cec_new->cec_member_list_tail = NULL; 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate /* Initialize the filters */ 16737c478bd9Sstevel@tonic-gate cec_new->filter_min_speed = sii->si_speed; 16747c478bd9Sstevel@tonic-gate cec_new->filter_max_speed = sii->si_speed; 16757c478bd9Sstevel@tonic-gate cec_new->filter_current_speed = cec_new->filter_max_speed; 16767c478bd9Sstevel@tonic-gate cec_new->filter_channel_mask = sii->si_channel_mask; 16777c478bd9Sstevel@tonic-gate cec_new->bandwidth = sii->si_bandwidth; 16787c478bd9Sstevel@tonic-gate cec_new->state_transitions = ISOCH_CEC_FREE | ISOCH_CEC_JOIN | 16797c478bd9Sstevel@tonic-gate ISOCH_CEC_SETUP; 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate mutex_enter(&hal->isoch_cec_list_mutex); 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate /* Insert Isoch CEC into the HAL's list */ 16847c478bd9Sstevel@tonic-gate s1394_isoch_cec_list_insert(hal, cec_new); 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate mutex_exit(&hal->isoch_cec_list_mutex); 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate /* 16897c478bd9Sstevel@tonic-gate * Join the newly created Isoch CEC 16907c478bd9Sstevel@tonic-gate */ 16917c478bd9Sstevel@tonic-gate jii.req_channel_mask = sii->si_channel_mask; 16927c478bd9Sstevel@tonic-gate jii.req_max_speed = sii->si_speed; 16937c478bd9Sstevel@tonic-gate jii.jii_options = T1394_TALKER; 16947c478bd9Sstevel@tonic-gate jii.isoch_cec_evts_arg = sii->single_evt_arg; 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate /* All events are NULL except rsrc_fail_target() */ 16977c478bd9Sstevel@tonic-gate jii.isoch_cec_evts.setup_target = NULL; 16987c478bd9Sstevel@tonic-gate jii.isoch_cec_evts.start_target = NULL; 16997c478bd9Sstevel@tonic-gate jii.isoch_cec_evts.stop_target = NULL; 17007c478bd9Sstevel@tonic-gate jii.isoch_cec_evts.stop_target = NULL; 17017c478bd9Sstevel@tonic-gate jii.isoch_cec_evts.teardown_target = NULL; 17027c478bd9Sstevel@tonic-gate jii.isoch_cec_evts.rsrc_fail_target = sii->rsrc_fail_target; 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate ret = t1394_join_isoch_cec(t1394_hdl, 17057c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t)cec_new, 0, &jii); 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 17087c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 17097c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 17107c478bd9Sstevel@tonic-gate "Unexpected error from t1394_join_isoch_cec()"); 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate ret = t1394_free_isoch_cec(t1394_hdl, flags, 17137c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t *)&cec_new); 17147c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 17157c478bd9Sstevel@tonic-gate /* Unable to free the Isoch CEC */ 17167c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 17177c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 17187c478bd9Sstevel@tonic-gate "Unexpected error from t1394_free_isoch_cec()"); 17197c478bd9Sstevel@tonic-gate ASSERT(0); 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate /* Handle is nulled out before returning */ 17237c478bd9Sstevel@tonic-gate *t1394_single_hdl = NULL; 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_exit, 17267c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 17277c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 17287c478bd9Sstevel@tonic-gate } 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate /* 17317c478bd9Sstevel@tonic-gate * Setup the isoch resources, etc. 17327c478bd9Sstevel@tonic-gate */ 17337c478bd9Sstevel@tonic-gate ret = t1394_setup_isoch_cec(t1394_hdl, 17347c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t)cec_new, 0, &err); 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 17377c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 17387c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 17397c478bd9Sstevel@tonic-gate "Unexpected error from t1394_setup_isoch_cec()"); 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate *result = err; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate /* Leave the Isoch CEC */ 17447c478bd9Sstevel@tonic-gate ret = t1394_leave_isoch_cec(t1394_hdl, 17457c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t)cec_new, 0); 17467c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 17477c478bd9Sstevel@tonic-gate /* Unable to leave the Isoch CEC */ 17487c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 17497c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 17507c478bd9Sstevel@tonic-gate "Unexpected error from t1394_leave_isoch_cec()"); 17517c478bd9Sstevel@tonic-gate ASSERT(0); 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate /* Free up the Isoch CEC */ 17557c478bd9Sstevel@tonic-gate ret = t1394_free_isoch_cec(t1394_hdl, flags, 17567c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t *)&cec_new); 17577c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 17587c478bd9Sstevel@tonic-gate /* Unable to free the Isoch CEC */ 17597c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_single_error, 17607c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 17617c478bd9Sstevel@tonic-gate "Unexpected error from t1394_free_isoch_cec()"); 17627c478bd9Sstevel@tonic-gate ASSERT(0); 17637c478bd9Sstevel@tonic-gate } 17647c478bd9Sstevel@tonic-gate 17657c478bd9Sstevel@tonic-gate /* Handle is nulled out before returning */ 17667c478bd9Sstevel@tonic-gate *t1394_single_hdl = NULL; 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_exit, 17697c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 17707c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 17717c478bd9Sstevel@tonic-gate } 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate /* Return the setup_args - channel num and speed */ 17747c478bd9Sstevel@tonic-gate mutex_enter(&cec_new->isoch_cec_mutex); 17757c478bd9Sstevel@tonic-gate output_args->channel_num = cec_new->realloc_chnl_num; 17767c478bd9Sstevel@tonic-gate mutex_exit(&cec_new->isoch_cec_mutex); 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate /* Update the handle */ 17797c478bd9Sstevel@tonic-gate *t1394_single_hdl = (t1394_isoch_single_handle_t)cec_new; 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_single_exit, 17827c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 17837c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 17847c478bd9Sstevel@tonic-gate } 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate /* 17877c478bd9Sstevel@tonic-gate * Function: t1394_free_isoch_single() 17887c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 17897c478bd9Sstevel@tonic-gate * t1394_attach() 17907c478bd9Sstevel@tonic-gate * t1394_single_hdl The isoch "handle" return by 17917c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_single() 17927c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 17937c478bd9Sstevel@tonic-gate * 17947c478bd9Sstevel@tonic-gate * Output(s): None 17957c478bd9Sstevel@tonic-gate * 17967c478bd9Sstevel@tonic-gate * Description: t1394_free_isoch_single() frees the isochronous resources 17977c478bd9Sstevel@tonic-gate * and the handle that were allocated during the call to 17987c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_single(). 17997c478bd9Sstevel@tonic-gate */ 18007c478bd9Sstevel@tonic-gate /* ARGSUSED */ 18017c478bd9Sstevel@tonic-gate void 18027c478bd9Sstevel@tonic-gate t1394_free_isoch_single(t1394_handle_t t1394_hdl, 18037c478bd9Sstevel@tonic-gate t1394_isoch_single_handle_t *t1394_single_hdl, uint_t flags) 18047c478bd9Sstevel@tonic-gate { 18057c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 18067c478bd9Sstevel@tonic-gate int ret; 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_single_enter, 18097c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 18127c478bd9Sstevel@tonic-gate ASSERT(t1394_single_hdl != NULL); 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 18157c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)(*t1394_single_hdl); 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate /* 18187c478bd9Sstevel@tonic-gate * Teardown the isoch resources, etc. 18197c478bd9Sstevel@tonic-gate */ 18207c478bd9Sstevel@tonic-gate ret = t1394_teardown_isoch_cec(t1394_hdl, 18217c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t)cec_curr, 0); 18227c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 18237c478bd9Sstevel@tonic-gate /* Unable to teardown the Isoch CEC */ 18247c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_free_isoch_single_error, 18257c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 18267c478bd9Sstevel@tonic-gate "Unexpected error from t1394_teardown_isoch_cec()"); 18277c478bd9Sstevel@tonic-gate ASSERT(0); 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate /* 18317c478bd9Sstevel@tonic-gate * Leave the Isoch CEC 18327c478bd9Sstevel@tonic-gate */ 18337c478bd9Sstevel@tonic-gate ret = t1394_leave_isoch_cec(t1394_hdl, 18347c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t)cec_curr, 0); 18357c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 18367c478bd9Sstevel@tonic-gate /* Unable to leave the Isoch CEC */ 18377c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_free_isoch_single_error, 18387c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 18397c478bd9Sstevel@tonic-gate "Unexpected error from t1394_leave_isoch_cec()"); 18407c478bd9Sstevel@tonic-gate ASSERT(0); 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate /* 18447c478bd9Sstevel@tonic-gate * Free the Isoch CEC 18457c478bd9Sstevel@tonic-gate */ 18467c478bd9Sstevel@tonic-gate ret = t1394_free_isoch_cec(t1394_hdl, flags, 18477c478bd9Sstevel@tonic-gate (t1394_isoch_cec_handle_t *)&cec_curr); 18487c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 18497c478bd9Sstevel@tonic-gate /* Unable to free the Isoch CEC */ 18507c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_free_isoch_single_error, 18517c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 18527c478bd9Sstevel@tonic-gate "Unexpected error from t1394_free_isoch_cec()"); 18537c478bd9Sstevel@tonic-gate ASSERT(0); 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate /* Handle is nulled out before returning */ 18577c478bd9Sstevel@tonic-gate *t1394_single_hdl = NULL; 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_single_exit, 18607c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate /* 18647c478bd9Sstevel@tonic-gate * Function: t1394_alloc_isoch_cec() 18657c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 18667c478bd9Sstevel@tonic-gate * t1394_attach() 18677c478bd9Sstevel@tonic-gate * props The structure used to set up the 18687c478bd9Sstevel@tonic-gate * overall characteristics of for 18697c478bd9Sstevel@tonic-gate * the Isoch CEC. 18707c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 18717c478bd9Sstevel@tonic-gate * 18727c478bd9Sstevel@tonic-gate * Output(s): t1394_isoch_cec_hdl The Isoch CEC "handle" used in all 18737c478bd9Sstevel@tonic-gate * subsequent isoch_cec() calls 18747c478bd9Sstevel@tonic-gate * 18757c478bd9Sstevel@tonic-gate * Description: t1394_alloc_isoch_cec() allocates and initializes an 18767c478bd9Sstevel@tonic-gate * isochronous channel event coordinator (Isoch CEC) for use 18777c478bd9Sstevel@tonic-gate * in managing and coordinating activity for an isoch channel 18787c478bd9Sstevel@tonic-gate */ 18797c478bd9Sstevel@tonic-gate /* ARGSUSED */ 18807c478bd9Sstevel@tonic-gate int 18817c478bd9Sstevel@tonic-gate t1394_alloc_isoch_cec(t1394_handle_t t1394_hdl, t1394_isoch_cec_props_t *props, 18827c478bd9Sstevel@tonic-gate uint_t flags, t1394_isoch_cec_handle_t *t1394_isoch_cec_hdl) 18837c478bd9Sstevel@tonic-gate { 18847c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 18857c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_new; 18867c478bd9Sstevel@tonic-gate uint64_t temp; 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_cec_enter, 18897c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 18927c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 18937c478bd9Sstevel@tonic-gate ASSERT(props != NULL); 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate /* Check for invalid channel_mask */ 18987c478bd9Sstevel@tonic-gate if (props->cec_channel_mask == 0) { 18997c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_cec_error, 19007c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 19017c478bd9Sstevel@tonic-gate "Invalid channel mask"); 19027c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_cec_exit, 19037c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 19047c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate /* Test conditions specific to T1394_NO_IRM_ALLOC */ 19087c478bd9Sstevel@tonic-gate temp = props->cec_channel_mask; 19097c478bd9Sstevel@tonic-gate if (props->cec_options & T1394_NO_IRM_ALLOC) { 19107c478bd9Sstevel@tonic-gate /* If T1394_NO_IRM_ALLOC, then only one bit should be set */ 1911*de710d24SJosef 'Jeff' Sipek if (!ISP2(temp)) { 19127c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_cec_error, 19137c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 19147c478bd9Sstevel@tonic-gate "Invalid channel mask"); 19157c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_cec_exit, 19167c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 19177c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate /* If T1394_NO_IRM_ALLOC, then speeds should be equal */ 19217c478bd9Sstevel@tonic-gate if (props->cec_min_speed != props->cec_max_speed) { 19227c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_cec_error, 19237c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 19247c478bd9Sstevel@tonic-gate "Invalid speeds (min != max)"); 19257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_cec_exit, 19267c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 19277c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 19287c478bd9Sstevel@tonic-gate } 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate /* Check for invalid bandwidth */ 19327c478bd9Sstevel@tonic-gate if ((props->cec_bandwidth <= IEEE1394_BANDWIDTH_MIN) || 19337c478bd9Sstevel@tonic-gate (props->cec_bandwidth > IEEE1394_BANDWIDTH_MAX)) { 19347c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_cec_error, 19357c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 19367c478bd9Sstevel@tonic-gate "Invalid bandwidth requirements"); 19377c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_cec_exit, 19387c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 19397c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 19407c478bd9Sstevel@tonic-gate } 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* Allocate the Isoch CEC structure */ 19437c478bd9Sstevel@tonic-gate cec_new = kmem_zalloc(sizeof (s1394_isoch_cec_t), KM_SLEEP); 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate /* Initialize the structure type */ 19467c478bd9Sstevel@tonic-gate cec_new->cec_type = S1394_PEER_TO_PEER; 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate /* Create the mutex and "in_callbacks" cv */ 19497c478bd9Sstevel@tonic-gate mutex_init(&cec_new->isoch_cec_mutex, NULL, MUTEX_DRIVER, 19507c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 19517c478bd9Sstevel@tonic-gate cv_init(&cec_new->in_callbacks_cv, NULL, CV_DRIVER, 19527c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate /* Initialize the Isoch CEC's member list */ 19557c478bd9Sstevel@tonic-gate cec_new->cec_member_list_head = NULL; 19567c478bd9Sstevel@tonic-gate cec_new->cec_member_list_tail = NULL; 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate /* Initialize the filters */ 19597c478bd9Sstevel@tonic-gate cec_new->filter_min_speed = props->cec_min_speed; 19607c478bd9Sstevel@tonic-gate cec_new->filter_max_speed = props->cec_max_speed; 19617c478bd9Sstevel@tonic-gate cec_new->filter_current_speed = cec_new->filter_max_speed; 19627c478bd9Sstevel@tonic-gate cec_new->filter_channel_mask = props->cec_channel_mask; 19637c478bd9Sstevel@tonic-gate cec_new->bandwidth = props->cec_bandwidth; 19647c478bd9Sstevel@tonic-gate cec_new->cec_options = props->cec_options; 19657c478bd9Sstevel@tonic-gate cec_new->state_transitions = ISOCH_CEC_FREE | ISOCH_CEC_JOIN | 19667c478bd9Sstevel@tonic-gate ISOCH_CEC_SETUP; 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate mutex_enter(&hal->isoch_cec_list_mutex); 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate /* Insert Isoch CEC into the HAL's list */ 19717c478bd9Sstevel@tonic-gate s1394_isoch_cec_list_insert(hal, cec_new); 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate mutex_exit(&hal->isoch_cec_list_mutex); 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate /* Update the handle and return */ 19767c478bd9Sstevel@tonic-gate *t1394_isoch_cec_hdl = (t1394_isoch_cec_handle_t)cec_new; 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_cec_exit, 19797c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 19807c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate /* 19847c478bd9Sstevel@tonic-gate * Function: t1394_free_isoch_cec() 19857c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 19867c478bd9Sstevel@tonic-gate * t1394_attach() 19877c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 19887c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 19897c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 19907c478bd9Sstevel@tonic-gate * 19917c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully freed the Isoch CEC 19927c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to free the Isoch CEC 19937c478bd9Sstevel@tonic-gate * 19947c478bd9Sstevel@tonic-gate * Description: t1394_free_isoch_cec() attempts to free the Isoch CEC 19957c478bd9Sstevel@tonic-gate * structure. It will fail (DDI_FAILURE) if there are any 19967c478bd9Sstevel@tonic-gate * remaining members who have not yet left. 19977c478bd9Sstevel@tonic-gate */ 19987c478bd9Sstevel@tonic-gate /* ARGSUSED */ 19997c478bd9Sstevel@tonic-gate int 20007c478bd9Sstevel@tonic-gate t1394_free_isoch_cec(t1394_handle_t t1394_hdl, uint_t flags, 20017c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t *t1394_isoch_cec_hdl) 20027c478bd9Sstevel@tonic-gate { 20037c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 20047c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_cec_enter, 20077c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 20107c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 20117c478bd9Sstevel@tonic-gate 20127c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 20137c478bd9Sstevel@tonic-gate 20147c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 20157c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)(*t1394_isoch_cec_hdl); 20167c478bd9Sstevel@tonic-gate 20177c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 20187c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate /* Are we in any callbacks? */ 20217c478bd9Sstevel@tonic-gate if (CEC_IN_ANY_CALLBACKS(cec_curr)) { 20227c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 20237c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 20247c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_free_isoch_cec_error, 20257c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 20267c478bd9Sstevel@tonic-gate "Not allowed to free Isoch CEC (in callbacks)"); 20277c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_cec_exit, 20287c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 20297c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate 20327c478bd9Sstevel@tonic-gate /* Is "free" a legal state transition? */ 20337c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_FREE) == 0) { 20347c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 20357c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 20367c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_free_isoch_cec_error, 20377c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 20387c478bd9Sstevel@tonic-gate "Not allowed to free Isoch CEC"); 20397c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_cec_exit, 20407c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 20417c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate mutex_enter(&hal->isoch_cec_list_mutex); 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate /* Remove Isoch CEC from HAL's list */ 20487c478bd9Sstevel@tonic-gate s1394_isoch_cec_list_remove(hal, cec_curr); 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate mutex_exit(&hal->isoch_cec_list_mutex); 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate /* Destroy the Isoch CEC's mutex and cv */ 20537c478bd9Sstevel@tonic-gate cv_destroy(&cec_curr->in_callbacks_cv); 20547c478bd9Sstevel@tonic-gate mutex_destroy(&cec_curr->isoch_cec_mutex); 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate /* Free up the memory for the Isoch CEC struct */ 20577c478bd9Sstevel@tonic-gate kmem_free(cec_curr, sizeof (s1394_isoch_cec_t)); 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate /* Update the handle and return */ 20607c478bd9Sstevel@tonic-gate *t1394_isoch_cec_hdl = NULL; 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_cec_exit, 20637c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 20647c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate /* 20687c478bd9Sstevel@tonic-gate * Function: t1394_join_isoch_cec() 20697c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 20707c478bd9Sstevel@tonic-gate * t1394_attach() 20717c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 20727c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 20737c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 20747c478bd9Sstevel@tonic-gate * join_isoch_info This structure provides infomation 20757c478bd9Sstevel@tonic-gate * about a target that wishes to join 20767c478bd9Sstevel@tonic-gate * the given Isoch CEC. It gives 20777c478bd9Sstevel@tonic-gate * max_speed, channel_mask, etc. 20787c478bd9Sstevel@tonic-gate * 20797c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully joined the 20807c478bd9Sstevel@tonic-gate * Isoch CEC 20817c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to join the Isoch CEC 20827c478bd9Sstevel@tonic-gate * 20837c478bd9Sstevel@tonic-gate * Description: t1394_join_isoch_cec() determines, based on the information 20847c478bd9Sstevel@tonic-gate * given in the join_isoch_info structure, if the target may 20857c478bd9Sstevel@tonic-gate * join the Isoch CEC. If it is determined that the target may 20867c478bd9Sstevel@tonic-gate * join, the specified callback routines are stored away for 20877c478bd9Sstevel@tonic-gate * later use in the coordination tasks. 20887c478bd9Sstevel@tonic-gate */ 20897c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20907c478bd9Sstevel@tonic-gate int 20917c478bd9Sstevel@tonic-gate t1394_join_isoch_cec(t1394_handle_t t1394_hdl, 20927c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags, 20937c478bd9Sstevel@tonic-gate t1394_join_isochinfo_t *join_isoch_info) 20947c478bd9Sstevel@tonic-gate { 20957c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 20967c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 20977c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_new; 20987c478bd9Sstevel@tonic-gate uint64_t check_mask; 20997c478bd9Sstevel@tonic-gate uint_t curr_max_speed; 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_enter, 21027c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 21057c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 21087c478bd9Sstevel@tonic-gate 21097c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 21107c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)t1394_isoch_cec_hdl; 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate /* Allocate a new Isoch CEC member structure */ 21137c478bd9Sstevel@tonic-gate member_new = kmem_zalloc(sizeof (s1394_isoch_cec_member_t), KM_SLEEP); 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 21167c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate /* Are we in any callbacks? (Wait for them to finish) */ 21197c478bd9Sstevel@tonic-gate while (CEC_IN_ANY_CALLBACKS(cec_curr)) { 21207c478bd9Sstevel@tonic-gate cec_curr->cec_want_wakeup = B_TRUE; 21217c478bd9Sstevel@tonic-gate cv_wait(&cec_curr->in_callbacks_cv, 21227c478bd9Sstevel@tonic-gate &cec_curr->isoch_cec_mutex); 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate /* Is "join" a legal state transition? */ 21267c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_JOIN) == 0) { 21277c478bd9Sstevel@tonic-gate kmem_free(member_new, sizeof (s1394_isoch_cec_member_t)); 21287c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 21297c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 21307c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_join_isoch_cec_error, 21317c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 21327c478bd9Sstevel@tonic-gate "Not allowed to join Isoch CEC"); 21337c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_exit, 21347c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 21357c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate /* Check the channel mask for consistency */ 21397c478bd9Sstevel@tonic-gate check_mask = join_isoch_info->req_channel_mask & 21407c478bd9Sstevel@tonic-gate cec_curr->filter_channel_mask; 21417c478bd9Sstevel@tonic-gate if (check_mask == 0) { 21427c478bd9Sstevel@tonic-gate kmem_free(member_new, sizeof (s1394_isoch_cec_member_t)); 21437c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 21447c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 21457c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_join_isoch_cec_error, 21467c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 21477c478bd9Sstevel@tonic-gate "Inconsistent channel mask specified"); 21487c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_exit, 21497c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 21507c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 21517c478bd9Sstevel@tonic-gate } 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate /* Check for consistent speeds */ 21547c478bd9Sstevel@tonic-gate if (join_isoch_info->req_max_speed < cec_curr->filter_min_speed) { 21557c478bd9Sstevel@tonic-gate kmem_free(member_new, sizeof (s1394_isoch_cec_member_t)); 21567c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 21577c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 21587c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_join_isoch_cec_error, 21597c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 21607c478bd9Sstevel@tonic-gate "Inconsistent speed specified"); 21617c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_exit, 21627c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 21637c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 21647c478bd9Sstevel@tonic-gate } else if (join_isoch_info->req_max_speed < 21657c478bd9Sstevel@tonic-gate cec_curr->filter_current_speed) { 21667c478bd9Sstevel@tonic-gate curr_max_speed = join_isoch_info->req_max_speed; 21677c478bd9Sstevel@tonic-gate } else { 21687c478bd9Sstevel@tonic-gate curr_max_speed = cec_curr->filter_current_speed; 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate /* Check for no more than one talker */ 21727c478bd9Sstevel@tonic-gate if ((join_isoch_info->jii_options & T1394_TALKER) && 21737c478bd9Sstevel@tonic-gate (cec_curr->cec_member_talker != NULL)) { 21747c478bd9Sstevel@tonic-gate kmem_free(member_new, sizeof (s1394_isoch_cec_member_t)); 21757c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 21767c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 21777c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_join_isoch_cec_error, 21787c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 21797c478bd9Sstevel@tonic-gate "Multiple talkers specified"); 21807c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_exit, 21817c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 21827c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 21837c478bd9Sstevel@tonic-gate } 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate /* Verify that all callbacks are non-NULL (for PEER_TO_PEER) */ 21867c478bd9Sstevel@tonic-gate if ((cec_curr->cec_type == S1394_PEER_TO_PEER) && 21877c478bd9Sstevel@tonic-gate ((join_isoch_info->isoch_cec_evts.setup_target == NULL) || 21887c478bd9Sstevel@tonic-gate (join_isoch_info->isoch_cec_evts.start_target == NULL) || 21897c478bd9Sstevel@tonic-gate (join_isoch_info->isoch_cec_evts.stop_target == NULL) || 21907c478bd9Sstevel@tonic-gate (join_isoch_info->isoch_cec_evts.rsrc_fail_target == NULL) || 21917c478bd9Sstevel@tonic-gate (join_isoch_info->isoch_cec_evts.teardown_target == NULL))) { 21927c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 21937c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 21947c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_join_isoch_cec_error, 21957c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 21967c478bd9Sstevel@tonic-gate "Invalid callbacks specified"); 21977c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_exit, 21987c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 21997c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 22007c478bd9Sstevel@tonic-gate } 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate /* Copy the events information into the struct */ 22037c478bd9Sstevel@tonic-gate member_new->isoch_cec_evts = join_isoch_info->isoch_cec_evts; 22047c478bd9Sstevel@tonic-gate member_new->isoch_cec_evts_arg = join_isoch_info->isoch_cec_evts_arg; 22057c478bd9Sstevel@tonic-gate member_new->cec_mem_options = join_isoch_info->jii_options; 22067c478bd9Sstevel@tonic-gate member_new->cec_mem_target = (s1394_target_t *)t1394_hdl; 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate /* Insert new member into Isoch CEC's member list */ 22097c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_list_insert(hal, cec_curr, member_new); 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate /* Update the channel mask filter */ 22127c478bd9Sstevel@tonic-gate cec_curr->filter_channel_mask = check_mask; 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate /* Update the speed filter */ 22157c478bd9Sstevel@tonic-gate cec_curr->filter_current_speed = curr_max_speed; 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate /* Update the talker pointer (if necessary) */ 22187c478bd9Sstevel@tonic-gate if (join_isoch_info->jii_options & T1394_TALKER) 22197c478bd9Sstevel@tonic-gate cec_curr->cec_member_talker = cec_curr->cec_member_list_head; 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate /* 22227c478bd9Sstevel@tonic-gate * Now "leave" is a legal state transition 22237c478bd9Sstevel@tonic-gate * and "free" is an illegal state transition 22247c478bd9Sstevel@tonic-gate */ 22257c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, ISOCH_CEC_LEAVE); 22267c478bd9Sstevel@tonic-gate CEC_SET_ILLEGAL(cec_curr, ISOCH_CEC_FREE); 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 22297c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 22307c478bd9Sstevel@tonic-gate 22317c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_join_isoch_cec_exit, 22327c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 22337c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate /* 22377c478bd9Sstevel@tonic-gate * Function: t1394_leave_isoch_cec() 22387c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 22397c478bd9Sstevel@tonic-gate * t1394_attach() 22407c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 22417c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 22427c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 22437c478bd9Sstevel@tonic-gate * 22447c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully left the 22457c478bd9Sstevel@tonic-gate * Isoch CEC 22467c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to leave the Isoch CEC 22477c478bd9Sstevel@tonic-gate * 22487c478bd9Sstevel@tonic-gate * Description: t1394_leave_isoch_cec() is used by a target driver to remove 22497c478bd9Sstevel@tonic-gate * itself from the Isoch CEC's member list. It is possible 22507c478bd9Sstevel@tonic-gate * for this call to fail because the target is not found in 22517c478bd9Sstevel@tonic-gate * the current member list, or because it is not an appropriate 22527c478bd9Sstevel@tonic-gate * time for a target to leave. 22537c478bd9Sstevel@tonic-gate */ 22547c478bd9Sstevel@tonic-gate /* ARGSUSED */ 22557c478bd9Sstevel@tonic-gate int 22567c478bd9Sstevel@tonic-gate t1394_leave_isoch_cec(t1394_handle_t t1394_hdl, 22577c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags) 22587c478bd9Sstevel@tonic-gate { 22597c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 22607c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 22617c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_curr; 22627c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_temp; 22637c478bd9Sstevel@tonic-gate boolean_t found; 22647c478bd9Sstevel@tonic-gate uint64_t temp_channel_mask; 22657c478bd9Sstevel@tonic-gate uint_t temp_max_speed; 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_leave_isoch_cec_enter, 22687c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 22717c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 22727c478bd9Sstevel@tonic-gate 22737c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 22767c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)t1394_isoch_cec_hdl; 22777c478bd9Sstevel@tonic-gate 22787c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 22797c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate /* Are we in any callbacks? (Wait for them to finish) */ 22827c478bd9Sstevel@tonic-gate while (CEC_IN_ANY_CALLBACKS(cec_curr)) { 22837c478bd9Sstevel@tonic-gate cec_curr->cec_want_wakeup = B_TRUE; 22847c478bd9Sstevel@tonic-gate cv_wait(&cec_curr->in_callbacks_cv, 22857c478bd9Sstevel@tonic-gate &cec_curr->isoch_cec_mutex); 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate /* Is "leave" a legal state transition? */ 22897c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_LEAVE) == 0) { 22907c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 22917c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 22927c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_leave_isoch_cec_error, 22937c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 22947c478bd9Sstevel@tonic-gate "Not allowed to leave Isoch CEC"); 22957c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_leave_isoch_cec_exit, 22967c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 22977c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 22987c478bd9Sstevel@tonic-gate } 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate /* Find the Target on the CEC's member list */ 23017c478bd9Sstevel@tonic-gate found = B_FALSE; 23027c478bd9Sstevel@tonic-gate temp_channel_mask = cec_curr->cec_alloc_props.cec_channel_mask; 23037c478bd9Sstevel@tonic-gate temp_max_speed = cec_curr->cec_alloc_props.cec_max_speed; 23047c478bd9Sstevel@tonic-gate member_curr = cec_curr->cec_member_list_head; 23057c478bd9Sstevel@tonic-gate while (member_curr != NULL) { 23067c478bd9Sstevel@tonic-gate if (member_curr->cec_mem_target == 23077c478bd9Sstevel@tonic-gate (s1394_target_t *)t1394_hdl) { 23087c478bd9Sstevel@tonic-gate member_temp = member_curr; 23097c478bd9Sstevel@tonic-gate found = B_TRUE; 23107c478bd9Sstevel@tonic-gate } else { 23117c478bd9Sstevel@tonic-gate /* Keep track of channel mask and max speed info */ 23127c478bd9Sstevel@tonic-gate temp_channel_mask &= member_curr->req_channel_mask; 23137c478bd9Sstevel@tonic-gate if (member_curr->req_max_speed < temp_max_speed) 23147c478bd9Sstevel@tonic-gate temp_max_speed = member_curr->req_max_speed; 23157c478bd9Sstevel@tonic-gate } 23167c478bd9Sstevel@tonic-gate member_curr = member_curr->cec_mem_next; 23177c478bd9Sstevel@tonic-gate } 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate /* Target not found on this Isoch CEC */ 23207c478bd9Sstevel@tonic-gate if (found == B_FALSE) { 23217c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 23227c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 23237c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_leave_isoch_cec_error, 23247c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 23257c478bd9Sstevel@tonic-gate "Target not found in Isoch CEC member list"); 23267c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_leave_isoch_cec_exit, 23277c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 23287c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 23297c478bd9Sstevel@tonic-gate } else { 23307c478bd9Sstevel@tonic-gate /* This member's departure may change filter constraints */ 23317c478bd9Sstevel@tonic-gate cec_curr->filter_current_speed = temp_max_speed; 23327c478bd9Sstevel@tonic-gate cec_curr->filter_channel_mask = temp_channel_mask; 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate /* Remove member from Isoch CEC's member list */ 23367c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_list_remove(hal, cec_curr, member_temp); 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate /* If we are removing the talker, then update the pointer */ 23397c478bd9Sstevel@tonic-gate if (cec_curr->cec_member_talker == member_temp) 23407c478bd9Sstevel@tonic-gate cec_curr->cec_member_talker = NULL; 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate /* Is the Isoch CEC's member list empty? */ 23437c478bd9Sstevel@tonic-gate if ((cec_curr->cec_member_list_head == NULL) && 23447c478bd9Sstevel@tonic-gate (cec_curr->cec_member_list_tail == NULL)) { 23457c478bd9Sstevel@tonic-gate /* 23467c478bd9Sstevel@tonic-gate * Now "free" _might_ be a legal state transition 23477c478bd9Sstevel@tonic-gate * if we aren't in setup or start phases and "leave" 23487c478bd9Sstevel@tonic-gate * is definitely an illegal state transition 23497c478bd9Sstevel@tonic-gate */ 23507c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_JOIN) != 0) 23517c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, ISOCH_CEC_FREE); 23527c478bd9Sstevel@tonic-gate CEC_SET_ILLEGAL(cec_curr, ISOCH_CEC_LEAVE); 23537c478bd9Sstevel@tonic-gate } 23547c478bd9Sstevel@tonic-gate 23557c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 23567c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate /* Free the Isoch CEC member structure */ 23597c478bd9Sstevel@tonic-gate kmem_free(member_temp, sizeof (s1394_isoch_cec_member_t)); 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_leave_isoch_cec_exit, 23627c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 23637c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate /* 23677c478bd9Sstevel@tonic-gate * Function: t1394_setup_isoch_cec() 23687c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 23697c478bd9Sstevel@tonic-gate * t1394_attach() 23707c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 23717c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 23727c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 23737c478bd9Sstevel@tonic-gate * 23747c478bd9Sstevel@tonic-gate * Output(s): result Used to pass more specific info back 23757c478bd9Sstevel@tonic-gate * to target 23767c478bd9Sstevel@tonic-gate * 23777c478bd9Sstevel@tonic-gate * Description: t1394_setup_isoch_cec() directs the 1394 Software Framework 23787c478bd9Sstevel@tonic-gate * to allocate isochronous resources and invoke the setup_target() 23797c478bd9Sstevel@tonic-gate * callback for each member of the Isoch CEC. This call may 23807c478bd9Sstevel@tonic-gate * fail because bandwidth was unavailable (T1394_ENO_BANDWIDTH), 23817c478bd9Sstevel@tonic-gate * channels were unavailable (T1394_ENO_CHANNEL), or one of the 23827c478bd9Sstevel@tonic-gate * member targets returned failure from its setup_target() 23837c478bd9Sstevel@tonic-gate * callback. 23847c478bd9Sstevel@tonic-gate */ 23857c478bd9Sstevel@tonic-gate /* ARGSUSED */ 23867c478bd9Sstevel@tonic-gate int 23877c478bd9Sstevel@tonic-gate t1394_setup_isoch_cec(t1394_handle_t t1394_hdl, 23887c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags, int *result) 23897c478bd9Sstevel@tonic-gate { 23907c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 23917c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 23927c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_curr; 23937c478bd9Sstevel@tonic-gate t1394_setup_target_args_t target_args; 23947c478bd9Sstevel@tonic-gate uint64_t temp_chnl_mask; 23957c478bd9Sstevel@tonic-gate uint32_t old_chnl; 23967c478bd9Sstevel@tonic-gate uint32_t try_chnl; 23977c478bd9Sstevel@tonic-gate uint_t bw_alloc_units; 23987c478bd9Sstevel@tonic-gate uint_t generation; 23997c478bd9Sstevel@tonic-gate int chnl_num; 24007c478bd9Sstevel@tonic-gate int err; 24017c478bd9Sstevel@tonic-gate int ret; 24027c478bd9Sstevel@tonic-gate int j; 24037c478bd9Sstevel@tonic-gate int (*setup_callback)(t1394_isoch_cec_handle_t, opaque_t, 24047c478bd9Sstevel@tonic-gate t1394_setup_target_args_t *); 24057c478bd9Sstevel@tonic-gate 24067c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_enter, 24077c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 24107c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 24117c478bd9Sstevel@tonic-gate 24127c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 24157c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)t1394_isoch_cec_hdl; 24167c478bd9Sstevel@tonic-gate 24177c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 24187c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate /* Are we in any callbacks? */ 24217c478bd9Sstevel@tonic-gate if (CEC_IN_ANY_CALLBACKS(cec_curr)) { 24227c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 24237c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 24247c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 24257c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 24267c478bd9Sstevel@tonic-gate "Not allowed to setup Isoch CEC (in callbacks)"); 24277c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 24287c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 24297c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 24307c478bd9Sstevel@tonic-gate } 24317c478bd9Sstevel@tonic-gate 24327c478bd9Sstevel@tonic-gate /* Is "setup" a legal state transition? */ 24337c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_SETUP) == 0) { 24347c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 24357c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 24367c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 24377c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 24387c478bd9Sstevel@tonic-gate "Not allowed to setup Isoch CEC"); 24397c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 24407c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 24417c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 24427c478bd9Sstevel@tonic-gate } 24437c478bd9Sstevel@tonic-gate 24447c478bd9Sstevel@tonic-gate /* If T1394_NO_IRM_ALLOC is set then don't allocate... do callbacks */ 24457c478bd9Sstevel@tonic-gate if (cec_curr->cec_options & T1394_NO_IRM_ALLOC) { 24467c478bd9Sstevel@tonic-gate goto setup_do_callbacks; 24477c478bd9Sstevel@tonic-gate } 24487c478bd9Sstevel@tonic-gate 24497c478bd9Sstevel@tonic-gate /* Allocate bandwidth and channels */ 24507c478bd9Sstevel@tonic-gate for (j = 0; j < S1394_ISOCH_ALLOC_RETRIES; j++) { 24517c478bd9Sstevel@tonic-gate /* 24527c478bd9Sstevel@tonic-gate * Get the current generation number - don't 24537c478bd9Sstevel@tonic-gate * need the lock because we are read only here 24547c478bd9Sstevel@tonic-gate */ 24557c478bd9Sstevel@tonic-gate generation = hal->generation_count; 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate /* Compute how much bandwidth is needed */ 24587c478bd9Sstevel@tonic-gate bw_alloc_units = s1394_compute_bw_alloc_units(hal, 24597c478bd9Sstevel@tonic-gate cec_curr->bandwidth, cec_curr->filter_current_speed); 24607c478bd9Sstevel@tonic-gate 24617c478bd9Sstevel@tonic-gate /* Check that the generation has not changed - */ 24627c478bd9Sstevel@tonic-gate /* don't need the lock (read only) */ 24637c478bd9Sstevel@tonic-gate if (generation != hal->generation_count) 24647c478bd9Sstevel@tonic-gate continue; 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 24677c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate /* Try to allocate the bandwidth */ 24707c478bd9Sstevel@tonic-gate ret = s1394_bandwidth_alloc(hal, bw_alloc_units, generation, 24717c478bd9Sstevel@tonic-gate &err); 24727c478bd9Sstevel@tonic-gate 24737c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 24747c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate /* If there was a bus reset, start over */ 24777c478bd9Sstevel@tonic-gate if (ret == DDI_FAILURE) { 24787c478bd9Sstevel@tonic-gate if (err == CMD1394_EBUSRESET) { 24797c478bd9Sstevel@tonic-gate continue; /* start over and try again */ 24807c478bd9Sstevel@tonic-gate } else { 24817c478bd9Sstevel@tonic-gate *result = T1394_ENO_BANDWIDTH; 24827c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 24837c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 24847c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 24857c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, 24867c478bd9Sstevel@tonic-gate msg, "Unable to allocate isoch bandwidth"); 24877c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 24887c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 24897c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 24907c478bd9Sstevel@tonic-gate } 24917c478bd9Sstevel@tonic-gate } 24927c478bd9Sstevel@tonic-gate 24937c478bd9Sstevel@tonic-gate /* Check that the generation has not changed - */ 24947c478bd9Sstevel@tonic-gate /* don't need the lock (read only) */ 24957c478bd9Sstevel@tonic-gate if (generation != hal->generation_count) 24967c478bd9Sstevel@tonic-gate continue; 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate /* 24997c478bd9Sstevel@tonic-gate * Allocate a channel 25007c478bd9Sstevel@tonic-gate * From IEEE 1394-1995, Section 8.3.2.3.8: "Bits 25017c478bd9Sstevel@tonic-gate * allocated in the CHANNELS_AVAILABLE_HI field of 25027c478bd9Sstevel@tonic-gate * this register shall start at bit zero (channel 25037c478bd9Sstevel@tonic-gate * number zero), and additional channel numbers shall 25047c478bd9Sstevel@tonic-gate * be represented in a monotonically increasing sequence 25057c478bd9Sstevel@tonic-gate * of bit numbers up to a maximum of bit 31 (channel 25067c478bd9Sstevel@tonic-gate * number 31). Bits allocated in the CHANNELS_AVAILABLE_LO 25077c478bd9Sstevel@tonic-gate * field of this register shall start at bit zero 25087c478bd9Sstevel@tonic-gate * (channel number 32), and additional channel numbers 25097c478bd9Sstevel@tonic-gate * shall be represented in a monotonically increasing 25107c478bd9Sstevel@tonic-gate * sequence of bit numbers up to a maximum of bit 31 25117c478bd9Sstevel@tonic-gate * (channel number 63). 25127c478bd9Sstevel@tonic-gate */ 25137c478bd9Sstevel@tonic-gate temp_chnl_mask = cec_curr->filter_channel_mask; 25147c478bd9Sstevel@tonic-gate for (chnl_num = 63; chnl_num >= 0; chnl_num--) { 25157c478bd9Sstevel@tonic-gate if ((temp_chnl_mask & 1) == 1) { 25167c478bd9Sstevel@tonic-gate try_chnl = (1 << ((63 - chnl_num) % 32)); 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 25197c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 25207c478bd9Sstevel@tonic-gate if (chnl_num < 32) { 25217c478bd9Sstevel@tonic-gate ret = s1394_channel_alloc(hal, 25227c478bd9Sstevel@tonic-gate try_chnl, generation, 25237c478bd9Sstevel@tonic-gate S1394_CHANNEL_ALLOC_HI, &old_chnl, 25247c478bd9Sstevel@tonic-gate &err); 25257c478bd9Sstevel@tonic-gate } else { 25267c478bd9Sstevel@tonic-gate ret = s1394_channel_alloc(hal, 25277c478bd9Sstevel@tonic-gate try_chnl, generation, 25287c478bd9Sstevel@tonic-gate S1394_CHANNEL_ALLOC_LO, &old_chnl, 25297c478bd9Sstevel@tonic-gate &err); 25307c478bd9Sstevel@tonic-gate } 25317c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 25327c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate /* Did we get a channel? (or a bus reset) */ 25357c478bd9Sstevel@tonic-gate if ((ret == DDI_SUCCESS) || 25367c478bd9Sstevel@tonic-gate (err == CMD1394_EBUSRESET)) 25377c478bd9Sstevel@tonic-gate break; 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate temp_chnl_mask = temp_chnl_mask >> 1; 25407c478bd9Sstevel@tonic-gate } 25417c478bd9Sstevel@tonic-gate 25427c478bd9Sstevel@tonic-gate /* If we've tried all the possible channels, then fail */ 25437c478bd9Sstevel@tonic-gate if (chnl_num == 0) { 25447c478bd9Sstevel@tonic-gate *result = T1394_ENO_CHANNEL; 25457c478bd9Sstevel@tonic-gate /* 25467c478bd9Sstevel@tonic-gate * If we successfully allocate bandwidth, and 25477c478bd9Sstevel@tonic-gate * then fail getting a channel, we need to 25487c478bd9Sstevel@tonic-gate * free up the bandwidth 25497c478bd9Sstevel@tonic-gate */ 25507c478bd9Sstevel@tonic-gate 25517c478bd9Sstevel@tonic-gate /* Check that the generation has not changed */ 25527c478bd9Sstevel@tonic-gate /* lock not needed here (read only) */ 25537c478bd9Sstevel@tonic-gate if (generation != hal->generation_count) 25547c478bd9Sstevel@tonic-gate continue; 25557c478bd9Sstevel@tonic-gate 25567c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 25577c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 25587c478bd9Sstevel@tonic-gate 25597c478bd9Sstevel@tonic-gate /* Try to free up the bandwidth */ 25607c478bd9Sstevel@tonic-gate ret = s1394_bandwidth_free(hal, bw_alloc_units, 25617c478bd9Sstevel@tonic-gate generation, &err); 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 25647c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 25657c478bd9Sstevel@tonic-gate 25667c478bd9Sstevel@tonic-gate if (ret == DDI_FAILURE) { 25677c478bd9Sstevel@tonic-gate if (err == CMD1394_EBUSRESET) { 25687c478bd9Sstevel@tonic-gate continue; 25697c478bd9Sstevel@tonic-gate } else { 25707c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 25717c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", 25727c478bd9Sstevel@tonic-gate tnf_string, msg, 25737c478bd9Sstevel@tonic-gate "Unable to free isoch bandwidth"); 25747c478bd9Sstevel@tonic-gate } 25757c478bd9Sstevel@tonic-gate } 25767c478bd9Sstevel@tonic-gate 25777c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 25787c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 25797c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 25807c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 25817c478bd9Sstevel@tonic-gate "Unable to allocate isoch channel"); 25827c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 25837c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 25847c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 25857c478bd9Sstevel@tonic-gate } 25867c478bd9Sstevel@tonic-gate 25877c478bd9Sstevel@tonic-gate /* If we got a channel, we're done (else start over) */ 25887c478bd9Sstevel@tonic-gate if (ret == DDI_SUCCESS) 25897c478bd9Sstevel@tonic-gate break; 25907c478bd9Sstevel@tonic-gate else if (err == CMD1394_EBUSRESET) 25917c478bd9Sstevel@tonic-gate continue; 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate /* Have we gotten too many bus resets? */ 25957c478bd9Sstevel@tonic-gate if (j == S1394_ISOCH_ALLOC_RETRIES) { 25967c478bd9Sstevel@tonic-gate *result = T1394_ENO_BANDWIDTH; 25977c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 25987c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 25997c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 26007c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 26017c478bd9Sstevel@tonic-gate "Unable to allocate isoch channel"); 26027c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 26037c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 26047c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 26057c478bd9Sstevel@tonic-gate } 26067c478bd9Sstevel@tonic-gate 26077c478bd9Sstevel@tonic-gate cec_curr->realloc_valid = B_TRUE; 26087c478bd9Sstevel@tonic-gate cec_curr->realloc_chnl_num = chnl_num; 26097c478bd9Sstevel@tonic-gate cec_curr->realloc_bandwidth = cec_curr->bandwidth; 26107c478bd9Sstevel@tonic-gate cec_curr->realloc_speed = cec_curr->filter_current_speed; 26117c478bd9Sstevel@tonic-gate 26127c478bd9Sstevel@tonic-gate setup_do_callbacks: 26137c478bd9Sstevel@tonic-gate /* Call all of the setup_target() callbacks */ 26147c478bd9Sstevel@tonic-gate target_args.channel_num = chnl_num; 26157c478bd9Sstevel@tonic-gate target_args.channel_speed = cec_curr->filter_current_speed; 26167c478bd9Sstevel@tonic-gate 26177c478bd9Sstevel@tonic-gate /* Now we are going into the callbacks */ 26187c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_TRUE; 26197c478bd9Sstevel@tonic-gate 26207c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 26217c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 26227c478bd9Sstevel@tonic-gate 26237c478bd9Sstevel@tonic-gate member_curr = cec_curr->cec_member_list_head; 26247c478bd9Sstevel@tonic-gate *result = 0; 26257c478bd9Sstevel@tonic-gate while (member_curr != NULL) { 26267c478bd9Sstevel@tonic-gate if (member_curr->isoch_cec_evts.setup_target != NULL) { 26277c478bd9Sstevel@tonic-gate setup_callback = 26287c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts.setup_target; 26297c478bd9Sstevel@tonic-gate ret = setup_callback(t1394_isoch_cec_hdl, 26307c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts_arg, &target_args); 26317c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) 26327c478bd9Sstevel@tonic-gate *result = T1394_ETARGET; 26337c478bd9Sstevel@tonic-gate } 26347c478bd9Sstevel@tonic-gate member_curr = member_curr->cec_mem_next; 26357c478bd9Sstevel@tonic-gate } 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 26387c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 26397c478bd9Sstevel@tonic-gate 26407c478bd9Sstevel@tonic-gate /* We are finished with the callbacks */ 26417c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_FALSE; 26427c478bd9Sstevel@tonic-gate if (cec_curr->cec_want_wakeup == B_TRUE) { 26437c478bd9Sstevel@tonic-gate cec_curr->cec_want_wakeup = B_FALSE; 26447c478bd9Sstevel@tonic-gate cv_broadcast(&cec_curr->in_callbacks_cv); 26457c478bd9Sstevel@tonic-gate } 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate /* 26487c478bd9Sstevel@tonic-gate * Now "start" and "teardown" are legal state transitions 26497c478bd9Sstevel@tonic-gate * and "join", "free", and "setup" are illegal state transitions 26507c478bd9Sstevel@tonic-gate */ 26517c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, (ISOCH_CEC_START | ISOCH_CEC_TEARDOWN)); 26527c478bd9Sstevel@tonic-gate CEC_SET_ILLEGAL(cec_curr, (ISOCH_CEC_JOIN | ISOCH_CEC_FREE | 26537c478bd9Sstevel@tonic-gate ISOCH_CEC_SETUP)); 26547c478bd9Sstevel@tonic-gate 26557c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 26567c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 26577c478bd9Sstevel@tonic-gate 26587c478bd9Sstevel@tonic-gate /* Return DDI_FAILURE if any targets failed setup */ 26597c478bd9Sstevel@tonic-gate if (*result != 0) { 26607c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_setup_isoch_cec_error, 26617c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 26627c478bd9Sstevel@tonic-gate "Target returned error in setup_target()"); 26637c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 26647c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 26657c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 26667c478bd9Sstevel@tonic-gate } 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_setup_isoch_cec_exit, 26697c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 26707c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 26717c478bd9Sstevel@tonic-gate } 26727c478bd9Sstevel@tonic-gate 26737c478bd9Sstevel@tonic-gate /* 26747c478bd9Sstevel@tonic-gate * Function: t1394_start_isoch_cec() 26757c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 26767c478bd9Sstevel@tonic-gate * t1394_attach() 26777c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 26787c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 26797c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 26807c478bd9Sstevel@tonic-gate * 26817c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS All start_target() callbacks returned 26827c478bd9Sstevel@tonic-gate * successfully 26837c478bd9Sstevel@tonic-gate * DDI_FAILURE One or more start_target() callbacks 26847c478bd9Sstevel@tonic-gate * returned failure 26857c478bd9Sstevel@tonic-gate * 26867c478bd9Sstevel@tonic-gate * Description: t1394_start_isoch_cec() directs the 1394 Software Framework 26877c478bd9Sstevel@tonic-gate * to invoke each of the start_target() callbacks, first for 26887c478bd9Sstevel@tonic-gate * each listener, then for the talker. 26897c478bd9Sstevel@tonic-gate */ 26907c478bd9Sstevel@tonic-gate /* ARGSUSED */ 26917c478bd9Sstevel@tonic-gate int 26927c478bd9Sstevel@tonic-gate t1394_start_isoch_cec(t1394_handle_t t1394_hdl, 26937c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags) 26947c478bd9Sstevel@tonic-gate { 26957c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 26967c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_curr; 26977c478bd9Sstevel@tonic-gate int ret; 26987c478bd9Sstevel@tonic-gate boolean_t err; 26997c478bd9Sstevel@tonic-gate int (*start_callback)(t1394_isoch_cec_handle_t, opaque_t); 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_cec_enter, 27027c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 27037c478bd9Sstevel@tonic-gate 27047c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 27057c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 27087c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)t1394_isoch_cec_hdl; 27097c478bd9Sstevel@tonic-gate 27107c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 27117c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 27127c478bd9Sstevel@tonic-gate 27137c478bd9Sstevel@tonic-gate /* Are we in any callbacks? */ 27147c478bd9Sstevel@tonic-gate if (CEC_IN_ANY_CALLBACKS(cec_curr)) { 27157c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 27167c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 27177c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_start_isoch_cec_error, 27187c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 27197c478bd9Sstevel@tonic-gate "Not allowed to start Isoch CEC (in callbacks)"); 27207c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_cec_exit, 27217c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 27227c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 27237c478bd9Sstevel@tonic-gate } 27247c478bd9Sstevel@tonic-gate 27257c478bd9Sstevel@tonic-gate /* Is "start" a legal state transition? */ 27267c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_START) == 0) { 27277c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 27287c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 27297c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_start_isoch_cec_error, 27307c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 27317c478bd9Sstevel@tonic-gate "Not allowed to start Isoch CEC"); 27327c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_cec_exit, 27337c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 27347c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 27357c478bd9Sstevel@tonic-gate } 27367c478bd9Sstevel@tonic-gate 27377c478bd9Sstevel@tonic-gate /* Now we are going into the callbacks */ 27387c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_TRUE; 27397c478bd9Sstevel@tonic-gate 27407c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 27417c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate /* 27447c478bd9Sstevel@tonic-gate * Call all of the start_target() callbacks 27457c478bd9Sstevel@tonic-gate * Start at the tail (listeners first) and 27467c478bd9Sstevel@tonic-gate * go toward the head (talker last) 27477c478bd9Sstevel@tonic-gate */ 27487c478bd9Sstevel@tonic-gate member_curr = cec_curr->cec_member_list_tail; 27497c478bd9Sstevel@tonic-gate err = B_FALSE; 27507c478bd9Sstevel@tonic-gate while (member_curr != NULL) { 27517c478bd9Sstevel@tonic-gate if (member_curr->isoch_cec_evts.start_target != NULL) { 27527c478bd9Sstevel@tonic-gate start_callback = 27537c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts.start_target; 27547c478bd9Sstevel@tonic-gate ret = start_callback(t1394_isoch_cec_hdl, 27557c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts_arg); 27567c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) 27577c478bd9Sstevel@tonic-gate err = B_TRUE; 27587c478bd9Sstevel@tonic-gate } 27597c478bd9Sstevel@tonic-gate member_curr = member_curr->cec_mem_prev; 27607c478bd9Sstevel@tonic-gate } 27617c478bd9Sstevel@tonic-gate 27627c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 27637c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 27647c478bd9Sstevel@tonic-gate 27657c478bd9Sstevel@tonic-gate /* We are finished with the callbacks */ 27667c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_FALSE; 27677c478bd9Sstevel@tonic-gate if (cec_curr->cec_want_wakeup == B_TRUE) { 27687c478bd9Sstevel@tonic-gate cec_curr->cec_want_wakeup = B_FALSE; 27697c478bd9Sstevel@tonic-gate cv_broadcast(&cec_curr->in_callbacks_cv); 27707c478bd9Sstevel@tonic-gate } 27717c478bd9Sstevel@tonic-gate 27727c478bd9Sstevel@tonic-gate /* 27737c478bd9Sstevel@tonic-gate * Now "stop" is a legal state transitions 27747c478bd9Sstevel@tonic-gate * and "start" and "teardown" are illegal state transitions 27757c478bd9Sstevel@tonic-gate */ 27767c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, ISOCH_CEC_STOP); 27777c478bd9Sstevel@tonic-gate CEC_SET_ILLEGAL(cec_curr, (ISOCH_CEC_START | ISOCH_CEC_TEARDOWN)); 27787c478bd9Sstevel@tonic-gate 27797c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 27807c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 27817c478bd9Sstevel@tonic-gate 27827c478bd9Sstevel@tonic-gate /* Return DDI_FAILURE if any targets failed start */ 27837c478bd9Sstevel@tonic-gate if (err == B_TRUE) { 27847c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_start_isoch_cec_error, 27857c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 27867c478bd9Sstevel@tonic-gate "Target returned error in start_target()"); 27877c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_cec_exit, 27887c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 27897c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 27907c478bd9Sstevel@tonic-gate } 27917c478bd9Sstevel@tonic-gate 27927c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_cec_exit, 27937c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 27947c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 27957c478bd9Sstevel@tonic-gate } 27967c478bd9Sstevel@tonic-gate 27977c478bd9Sstevel@tonic-gate /* 27987c478bd9Sstevel@tonic-gate * Function: t1394_stop_isoch_cec() 27997c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 28007c478bd9Sstevel@tonic-gate * t1394_attach() 28017c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 28027c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 28037c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 28047c478bd9Sstevel@tonic-gate * 28057c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully stopped the 28067c478bd9Sstevel@tonic-gate * Isoch CEC 28077c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to stop the Isoch CEC 28087c478bd9Sstevel@tonic-gate * 28097c478bd9Sstevel@tonic-gate * Description: t1394_stop_isoch_cec() directs the 1394 Software Framework 28107c478bd9Sstevel@tonic-gate * to invoke each of the stop_target() callbacks, first for 28117c478bd9Sstevel@tonic-gate * the talker, then for each listener. 28127c478bd9Sstevel@tonic-gate * (This call will fail if it is called at an 28137c478bd9Sstevel@tonic-gate * inappropriate time, i.e. before the t1394_start_isoch_cec() 28147c478bd9Sstevel@tonic-gate * call, etc.) 28157c478bd9Sstevel@tonic-gate */ 28167c478bd9Sstevel@tonic-gate /* ARGSUSED */ 28177c478bd9Sstevel@tonic-gate int 28187c478bd9Sstevel@tonic-gate t1394_stop_isoch_cec(t1394_handle_t t1394_hdl, 28197c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags) 28207c478bd9Sstevel@tonic-gate { 28217c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 28227c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_curr; 28237c478bd9Sstevel@tonic-gate void (*stop_callback)(t1394_isoch_cec_handle_t, opaque_t); 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_stop_isoch_cec_enter, 28267c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 28277c478bd9Sstevel@tonic-gate 28287c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 28297c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 28307c478bd9Sstevel@tonic-gate 28317c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 28327c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)t1394_isoch_cec_hdl; 28337c478bd9Sstevel@tonic-gate 28347c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 28357c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 28367c478bd9Sstevel@tonic-gate 28377c478bd9Sstevel@tonic-gate /* Are we in any callbacks? */ 28387c478bd9Sstevel@tonic-gate if (CEC_IN_ANY_CALLBACKS(cec_curr)) { 28397c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 28407c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 28417c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_stop_isoch_cec_error, 28427c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 28437c478bd9Sstevel@tonic-gate "Not allowed to stop Isoch CEC (in callbacks)"); 28447c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_stop_isoch_cec_exit, 28457c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 28467c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 28477c478bd9Sstevel@tonic-gate } 28487c478bd9Sstevel@tonic-gate 28497c478bd9Sstevel@tonic-gate /* Is "stop" a legal state transition? */ 28507c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_STOP) == 0) { 28517c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 28527c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 28537c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_stop_isoch_cec_error, 28547c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 28557c478bd9Sstevel@tonic-gate "Not allowed to stop Isoch CEC"); 28567c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_stop_isoch_cec_exit, 28577c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 28587c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 28597c478bd9Sstevel@tonic-gate } 28607c478bd9Sstevel@tonic-gate 28617c478bd9Sstevel@tonic-gate /* Now we are going into the callbacks */ 28627c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_TRUE; 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 28657c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 28667c478bd9Sstevel@tonic-gate 28677c478bd9Sstevel@tonic-gate /* 28687c478bd9Sstevel@tonic-gate * Call all of the stop_target() callbacks 28697c478bd9Sstevel@tonic-gate * Start at the head (talker first) and 28707c478bd9Sstevel@tonic-gate * go toward the tail (listeners last) 28717c478bd9Sstevel@tonic-gate */ 28727c478bd9Sstevel@tonic-gate member_curr = cec_curr->cec_member_list_head; 28737c478bd9Sstevel@tonic-gate while (member_curr != NULL) { 28747c478bd9Sstevel@tonic-gate if (member_curr->isoch_cec_evts.stop_target != NULL) { 28757c478bd9Sstevel@tonic-gate stop_callback = 28767c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts.stop_target; 28777c478bd9Sstevel@tonic-gate stop_callback(t1394_isoch_cec_hdl, 28787c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts_arg); 28797c478bd9Sstevel@tonic-gate } 28807c478bd9Sstevel@tonic-gate member_curr = member_curr->cec_mem_next; 28817c478bd9Sstevel@tonic-gate } 28827c478bd9Sstevel@tonic-gate 28837c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 28847c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 28857c478bd9Sstevel@tonic-gate 28867c478bd9Sstevel@tonic-gate /* We are finished with the callbacks */ 28877c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_FALSE; 28887c478bd9Sstevel@tonic-gate if (cec_curr->cec_want_wakeup == B_TRUE) { 28897c478bd9Sstevel@tonic-gate cec_curr->cec_want_wakeup = B_FALSE; 28907c478bd9Sstevel@tonic-gate cv_broadcast(&cec_curr->in_callbacks_cv); 28917c478bd9Sstevel@tonic-gate } 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate /* 28947c478bd9Sstevel@tonic-gate * Now "start" and "teardown" are legal state transitions 28957c478bd9Sstevel@tonic-gate * and "stop" is an illegal state transitions 28967c478bd9Sstevel@tonic-gate */ 28977c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, (ISOCH_CEC_START | ISOCH_CEC_TEARDOWN)); 28987c478bd9Sstevel@tonic-gate CEC_SET_ILLEGAL(cec_curr, ISOCH_CEC_STOP); 28997c478bd9Sstevel@tonic-gate 29007c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 29017c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_stop_isoch_cec_exit, 29047c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 29057c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 29067c478bd9Sstevel@tonic-gate } 29077c478bd9Sstevel@tonic-gate 29087c478bd9Sstevel@tonic-gate /* 29097c478bd9Sstevel@tonic-gate * Function: t1394_teardown_isoch_cec() 29107c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 29117c478bd9Sstevel@tonic-gate * t1394_attach() 29127c478bd9Sstevel@tonic-gate * t1394_isoch_cec_hdl The Isoch CEC "handle" returned by 29137c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_cec() 29147c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 29157c478bd9Sstevel@tonic-gate * 29167c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS Target successfully tore down the 29177c478bd9Sstevel@tonic-gate * Isoch CEC 29187c478bd9Sstevel@tonic-gate * DDI_FAILURE Target failed to tear down the 29197c478bd9Sstevel@tonic-gate * Isoch CEC 29207c478bd9Sstevel@tonic-gate * 29217c478bd9Sstevel@tonic-gate * Description: t1394_teardown_isoch_cec() directs the 1394 Software Framework 29227c478bd9Sstevel@tonic-gate * to free up any isochronous resources we might be holding and 29237c478bd9Sstevel@tonic-gate * call all of the teardown_target() callbacks. 29247c478bd9Sstevel@tonic-gate * (This call will fail if it is called at an 29257c478bd9Sstevel@tonic-gate * inappropriate time, i.e. before the t1394_start_isoch_cec() 29267c478bd9Sstevel@tonic-gate * call, before the t1394_stop_isoch_cec, etc. 29277c478bd9Sstevel@tonic-gate */ 29287c478bd9Sstevel@tonic-gate /* ARGSUSED */ 29297c478bd9Sstevel@tonic-gate int 29307c478bd9Sstevel@tonic-gate t1394_teardown_isoch_cec(t1394_handle_t t1394_hdl, 29317c478bd9Sstevel@tonic-gate t1394_isoch_cec_handle_t t1394_isoch_cec_hdl, uint_t flags) 29327c478bd9Sstevel@tonic-gate { 29337c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 29347c478bd9Sstevel@tonic-gate s1394_isoch_cec_t *cec_curr; 29357c478bd9Sstevel@tonic-gate s1394_isoch_cec_member_t *member_curr; 29367c478bd9Sstevel@tonic-gate uint32_t chnl_mask; 29377c478bd9Sstevel@tonic-gate uint32_t old_chnl_mask; 29387c478bd9Sstevel@tonic-gate uint_t bw_alloc_units; 29397c478bd9Sstevel@tonic-gate uint_t generation; 29407c478bd9Sstevel@tonic-gate int ret; 29417c478bd9Sstevel@tonic-gate int err; 29427c478bd9Sstevel@tonic-gate void (*teardown_callback)(t1394_isoch_cec_handle_t, opaque_t); 29437c478bd9Sstevel@tonic-gate 29447c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_teardown_isoch_cec_enter, 29457c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 29467c478bd9Sstevel@tonic-gate 29477c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 29487c478bd9Sstevel@tonic-gate ASSERT(t1394_isoch_cec_hdl != NULL); 29497c478bd9Sstevel@tonic-gate 29507c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 29517c478bd9Sstevel@tonic-gate 29527c478bd9Sstevel@tonic-gate /* Convert the handle to an Isoch CEC pointer */ 29537c478bd9Sstevel@tonic-gate cec_curr = (s1394_isoch_cec_t *)t1394_isoch_cec_hdl; 29547c478bd9Sstevel@tonic-gate 29557c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 29567c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 29577c478bd9Sstevel@tonic-gate 29587c478bd9Sstevel@tonic-gate /* Are we in any callbacks? */ 29597c478bd9Sstevel@tonic-gate if (CEC_IN_ANY_CALLBACKS(cec_curr)) { 29607c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 29617c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 29627c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_teardown_isoch_cec_error, 29637c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 29647c478bd9Sstevel@tonic-gate "Not allowed to teardown Isoch CEC (in callbacks)"); 29657c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_teardown_isoch_cec_exit, 29667c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 29677c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 29687c478bd9Sstevel@tonic-gate } 29697c478bd9Sstevel@tonic-gate 29707c478bd9Sstevel@tonic-gate /* Is "teardown" a legal state transition? */ 29717c478bd9Sstevel@tonic-gate if (CEC_TRANSITION_LEGAL(cec_curr, ISOCH_CEC_TEARDOWN) == 0) { 29727c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 29737c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 29747c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_teardown_isoch_cec_error, 29757c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 29767c478bd9Sstevel@tonic-gate "Not allowed to teardown Isoch CEC"); 29777c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_teardown_isoch_cec_exit, 29787c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 29797c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 29807c478bd9Sstevel@tonic-gate } 29817c478bd9Sstevel@tonic-gate 29827c478bd9Sstevel@tonic-gate /* If T1394_NO_IRM_ALLOC is set then don't free... do callbacks */ 29837c478bd9Sstevel@tonic-gate if (cec_curr->cec_options & T1394_NO_IRM_ALLOC) { 29847c478bd9Sstevel@tonic-gate goto teardown_do_callbacks; 29857c478bd9Sstevel@tonic-gate } 29867c478bd9Sstevel@tonic-gate 29877c478bd9Sstevel@tonic-gate /* If nothing has been allocated or we failed to */ 29887c478bd9Sstevel@tonic-gate /* reallocate, then we are done... call the callbacks */ 29897c478bd9Sstevel@tonic-gate if ((cec_curr->realloc_valid == B_FALSE) || 29907c478bd9Sstevel@tonic-gate (cec_curr->realloc_failed == B_TRUE)) { 29917c478bd9Sstevel@tonic-gate goto teardown_do_callbacks; 29927c478bd9Sstevel@tonic-gate } 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate /* 29957c478bd9Sstevel@tonic-gate * Get the current generation number - don't need the 29967c478bd9Sstevel@tonic-gate * topology tree mutex here because it is read-only, and 29977c478bd9Sstevel@tonic-gate * there is a race condition with or without it. 29987c478bd9Sstevel@tonic-gate */ 29997c478bd9Sstevel@tonic-gate generation = hal->generation_count; 30007c478bd9Sstevel@tonic-gate 30017c478bd9Sstevel@tonic-gate /* Compute the amount bandwidth to free */ 30027c478bd9Sstevel@tonic-gate bw_alloc_units = s1394_compute_bw_alloc_units(hal, 30037c478bd9Sstevel@tonic-gate cec_curr->bandwidth, cec_curr->realloc_speed); 30047c478bd9Sstevel@tonic-gate 30057c478bd9Sstevel@tonic-gate /* Check that the generation has not changed - */ 30067c478bd9Sstevel@tonic-gate /* don't need the lock (read only) */ 30077c478bd9Sstevel@tonic-gate if (generation != hal->generation_count) 30087c478bd9Sstevel@tonic-gate goto teardown_do_callbacks; 30097c478bd9Sstevel@tonic-gate 30107c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 30117c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 30127c478bd9Sstevel@tonic-gate 30137c478bd9Sstevel@tonic-gate /* Try to free up the bandwidth */ 30147c478bd9Sstevel@tonic-gate ret = s1394_bandwidth_free(hal, bw_alloc_units, generation, &err); 30157c478bd9Sstevel@tonic-gate 30167c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 30177c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 30187c478bd9Sstevel@tonic-gate 30197c478bd9Sstevel@tonic-gate if (ret == DDI_FAILURE) { 30207c478bd9Sstevel@tonic-gate if (err == CMD1394_EBUSRESET) { 30217c478bd9Sstevel@tonic-gate goto teardown_do_callbacks; 30227c478bd9Sstevel@tonic-gate } else { 30237c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_teardown_isoch_cec_error, 30247c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 30257c478bd9Sstevel@tonic-gate "Unable to free allocated bandwidth"); 30267c478bd9Sstevel@tonic-gate } 30277c478bd9Sstevel@tonic-gate } 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate /* Free the allocated channel */ 30307c478bd9Sstevel@tonic-gate chnl_mask = (1 << ((63 - cec_curr->realloc_chnl_num) % 32)); 30317c478bd9Sstevel@tonic-gate 30327c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 30337c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 30347c478bd9Sstevel@tonic-gate if (cec_curr->realloc_chnl_num < 32) { 30357c478bd9Sstevel@tonic-gate ret = s1394_channel_free(hal, chnl_mask, generation, 30367c478bd9Sstevel@tonic-gate S1394_CHANNEL_ALLOC_HI, &old_chnl_mask, &err); 30377c478bd9Sstevel@tonic-gate } else { 30387c478bd9Sstevel@tonic-gate ret = s1394_channel_free(hal, chnl_mask, generation, 30397c478bd9Sstevel@tonic-gate S1394_CHANNEL_ALLOC_LO, &old_chnl_mask, &err); 30407c478bd9Sstevel@tonic-gate } 30417c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 30427c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 30437c478bd9Sstevel@tonic-gate 30447c478bd9Sstevel@tonic-gate if (ret == DDI_FAILURE) { 30457c478bd9Sstevel@tonic-gate if (err == CMD1394_EBUSRESET) { 30467c478bd9Sstevel@tonic-gate goto teardown_do_callbacks; 30477c478bd9Sstevel@tonic-gate } else { 30487c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_teardown_isoch_cec_error, 30497c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 30507c478bd9Sstevel@tonic-gate "Unable to free allocated bandwidth"); 30517c478bd9Sstevel@tonic-gate } 30527c478bd9Sstevel@tonic-gate } 30537c478bd9Sstevel@tonic-gate 30547c478bd9Sstevel@tonic-gate teardown_do_callbacks: 30557c478bd9Sstevel@tonic-gate /* From here on reallocation is unnecessary */ 30567c478bd9Sstevel@tonic-gate cec_curr->realloc_valid = B_FALSE; 30577c478bd9Sstevel@tonic-gate cec_curr->realloc_chnl_num = 0; 30587c478bd9Sstevel@tonic-gate cec_curr->realloc_bandwidth = 0; 30597c478bd9Sstevel@tonic-gate 30607c478bd9Sstevel@tonic-gate /* Now we are going into the callbacks */ 30617c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_TRUE; 30627c478bd9Sstevel@tonic-gate 30637c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 30647c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 30657c478bd9Sstevel@tonic-gate 30667c478bd9Sstevel@tonic-gate /* Call all of the teardown_target() callbacks */ 30677c478bd9Sstevel@tonic-gate member_curr = cec_curr->cec_member_list_head; 30687c478bd9Sstevel@tonic-gate while (member_curr != NULL) { 30697c478bd9Sstevel@tonic-gate if (member_curr->isoch_cec_evts.teardown_target != NULL) { 30707c478bd9Sstevel@tonic-gate teardown_callback = 30717c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts.teardown_target; 30727c478bd9Sstevel@tonic-gate teardown_callback(t1394_isoch_cec_hdl, 30737c478bd9Sstevel@tonic-gate member_curr->isoch_cec_evts_arg); 30747c478bd9Sstevel@tonic-gate } 30757c478bd9Sstevel@tonic-gate member_curr = member_curr->cec_mem_next; 30767c478bd9Sstevel@tonic-gate } 30777c478bd9Sstevel@tonic-gate 30787c478bd9Sstevel@tonic-gate /* Lock the Isoch CEC member list */ 30797c478bd9Sstevel@tonic-gate mutex_enter(&cec_curr->isoch_cec_mutex); 30807c478bd9Sstevel@tonic-gate 30817c478bd9Sstevel@tonic-gate /* We are finished with the callbacks */ 30827c478bd9Sstevel@tonic-gate cec_curr->in_callbacks = B_FALSE; 30837c478bd9Sstevel@tonic-gate if (cec_curr->cec_want_wakeup == B_TRUE) { 30847c478bd9Sstevel@tonic-gate cec_curr->cec_want_wakeup = B_FALSE; 30857c478bd9Sstevel@tonic-gate cv_broadcast(&cec_curr->in_callbacks_cv); 30867c478bd9Sstevel@tonic-gate } 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate /* 30897c478bd9Sstevel@tonic-gate * Now "join" and "setup" are legal state transitions 30907c478bd9Sstevel@tonic-gate * and "start" and "teardown" are illegal state transitions 30917c478bd9Sstevel@tonic-gate */ 30927c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, (ISOCH_CEC_JOIN | ISOCH_CEC_SETUP)); 30937c478bd9Sstevel@tonic-gate CEC_SET_ILLEGAL(cec_curr, (ISOCH_CEC_START | ISOCH_CEC_TEARDOWN)); 30947c478bd9Sstevel@tonic-gate 30957c478bd9Sstevel@tonic-gate /* And if the member list is empty, then "free" is legal too */ 30967c478bd9Sstevel@tonic-gate if ((cec_curr->cec_member_list_head == NULL) && 30977c478bd9Sstevel@tonic-gate (cec_curr->cec_member_list_tail == NULL)) { 30987c478bd9Sstevel@tonic-gate CEC_SET_LEGAL(cec_curr, ISOCH_CEC_FREE); 30997c478bd9Sstevel@tonic-gate } 31007c478bd9Sstevel@tonic-gate 31017c478bd9Sstevel@tonic-gate /* Unlock the Isoch CEC member list */ 31027c478bd9Sstevel@tonic-gate mutex_exit(&cec_curr->isoch_cec_mutex); 31037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_teardown_isoch_cec_exit, 31047c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 31057c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 31067c478bd9Sstevel@tonic-gate } 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate /* 31097c478bd9Sstevel@tonic-gate * Function: t1394_alloc_isoch_dma() 31107c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 31117c478bd9Sstevel@tonic-gate * t1394_attach() 31127c478bd9Sstevel@tonic-gate * idi This structure contains information 31137c478bd9Sstevel@tonic-gate * for configuring the data flow for 31147c478bd9Sstevel@tonic-gate * isochronous DMA 31157c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 31167c478bd9Sstevel@tonic-gate * 31177c478bd9Sstevel@tonic-gate * Output(s): t1394_idma_hdl The IDMA "handle" used in all 31187c478bd9Sstevel@tonic-gate * subsequent isoch_dma() calls 31197c478bd9Sstevel@tonic-gate * result Used to pass more specific info back 31207c478bd9Sstevel@tonic-gate * to target 31217c478bd9Sstevel@tonic-gate * 31227c478bd9Sstevel@tonic-gate * Description: t1394_alloc_isoch_dma() allocates and initializes an 31237c478bd9Sstevel@tonic-gate * isochronous DMA resource for transmitting or receiving 31247c478bd9Sstevel@tonic-gate * isochronous data. If it fails, result may hold 31257c478bd9Sstevel@tonic-gate * T1394_EIDMA_NO_RESRCS, indicating that no isoch DMA resource 31267c478bd9Sstevel@tonic-gate * are available. 31277c478bd9Sstevel@tonic-gate */ 31287c478bd9Sstevel@tonic-gate /* ARGSUSED */ 31297c478bd9Sstevel@tonic-gate int 31307c478bd9Sstevel@tonic-gate t1394_alloc_isoch_dma(t1394_handle_t t1394_hdl, 31317c478bd9Sstevel@tonic-gate id1394_isoch_dmainfo_t *idi, uint_t flags, 31327c478bd9Sstevel@tonic-gate t1394_isoch_dma_handle_t *t1394_idma_hdl, int *result) 31337c478bd9Sstevel@tonic-gate { 31347c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 31357c478bd9Sstevel@tonic-gate int ret; 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_dma_enter, 31387c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 31397c478bd9Sstevel@tonic-gate 31407c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 31417c478bd9Sstevel@tonic-gate ASSERT(idi != NULL); 31427c478bd9Sstevel@tonic-gate ASSERT(t1394_idma_hdl != NULL); 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 31457c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 31467c478bd9Sstevel@tonic-gate 31477c478bd9Sstevel@tonic-gate /* Sanity check dma options. If talk enabled, listen should be off */ 31487c478bd9Sstevel@tonic-gate if ((idi->idma_options & ID1394_TALK) && 31497c478bd9Sstevel@tonic-gate (idi->idma_options != ID1394_TALK)) { 31507c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_dma_talk_conflict_error, 31517c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 31527c478bd9Sstevel@tonic-gate "conflicting idma options; talker and listener"); 31537c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_dma_exit, 31547c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 31557c478bd9Sstevel@tonic-gate 31567c478bd9Sstevel@tonic-gate *result = T1394_EIDMA_CONFLICT; 31577c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 31587c478bd9Sstevel@tonic-gate } 31597c478bd9Sstevel@tonic-gate 31607c478bd9Sstevel@tonic-gate /* Only one listen mode allowed */ 31617c478bd9Sstevel@tonic-gate if ((idi->idma_options & ID1394_LISTEN_PKT_MODE) && 31627c478bd9Sstevel@tonic-gate (idi->idma_options & ID1394_LISTEN_BUF_MODE)) { 31637c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_dma_listen_conflict_error, 31647c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 31657c478bd9Sstevel@tonic-gate "conflicting idma options; both listener modes set"); 31667c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_dma_exit, 31677c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate *result = T1394_EIDMA_CONFLICT; 31707c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 31717c478bd9Sstevel@tonic-gate } 31727c478bd9Sstevel@tonic-gate 31737c478bd9Sstevel@tonic-gate /* Have HAL alloc a resource and compile ixl */ 31747c478bd9Sstevel@tonic-gate ret = HAL_CALL(hal).alloc_isoch_dma(hal->halinfo.hal_private, idi, 31757c478bd9Sstevel@tonic-gate (void **)t1394_idma_hdl, result); 31767c478bd9Sstevel@tonic-gate 31777c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 31787c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_alloc_isoch_dma_hal_error, 31797c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg, 31807c478bd9Sstevel@tonic-gate "HAL alloc_isoch_dma error, maybe IXL compilation"); 31817c478bd9Sstevel@tonic-gate if (*result == IXL1394_ENO_DMA_RESRCS) { 31827c478bd9Sstevel@tonic-gate *result = T1394_EIDMA_NO_RESRCS; 31837c478bd9Sstevel@tonic-gate } 31847c478bd9Sstevel@tonic-gate } 31857c478bd9Sstevel@tonic-gate 31867c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_alloc_isoch_dma_exit, 31877c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 31887c478bd9Sstevel@tonic-gate return (ret); 31897c478bd9Sstevel@tonic-gate } 31907c478bd9Sstevel@tonic-gate 31917c478bd9Sstevel@tonic-gate /* 31927c478bd9Sstevel@tonic-gate * Function: t1394_free_isoch_dma() 31937c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 31947c478bd9Sstevel@tonic-gate * t1394_attach() 31957c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 31967c478bd9Sstevel@tonic-gate * t1394_idma_hdl The IDMA "handle" returned by 31977c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_dma() 31987c478bd9Sstevel@tonic-gate * 31997c478bd9Sstevel@tonic-gate * Output(s): None 32007c478bd9Sstevel@tonic-gate * 32017c478bd9Sstevel@tonic-gate * Description: t1394_free_isoch_dma() is used to free all DMA resources 32027c478bd9Sstevel@tonic-gate * allocated for the isoch stream associated with t1394_idma_hdl. 32037c478bd9Sstevel@tonic-gate */ 32047c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32057c478bd9Sstevel@tonic-gate void 32067c478bd9Sstevel@tonic-gate t1394_free_isoch_dma(t1394_handle_t t1394_hdl, uint_t flags, 32077c478bd9Sstevel@tonic-gate t1394_isoch_dma_handle_t *t1394_idma_hdl) 32087c478bd9Sstevel@tonic-gate { 32097c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 32107c478bd9Sstevel@tonic-gate 32117c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_dma_enter, 32127c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 32157c478bd9Sstevel@tonic-gate ASSERT(*t1394_idma_hdl != NULL); 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 32187c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 32197c478bd9Sstevel@tonic-gate 32207c478bd9Sstevel@tonic-gate /* Tell HAL to release local isoch dma resources */ 32217c478bd9Sstevel@tonic-gate HAL_CALL(hal).free_isoch_dma(hal->halinfo.hal_private, *t1394_idma_hdl); 32227c478bd9Sstevel@tonic-gate 32237c478bd9Sstevel@tonic-gate /* Null out isoch handle */ 32247c478bd9Sstevel@tonic-gate *t1394_idma_hdl = NULL; 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_free_isoch_dma_exit, 32277c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 32287c478bd9Sstevel@tonic-gate } 32297c478bd9Sstevel@tonic-gate 32307c478bd9Sstevel@tonic-gate /* 32317c478bd9Sstevel@tonic-gate * Function: t1394_start_isoch_dma() 32327c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 32337c478bd9Sstevel@tonic-gate * t1394_attach() 32347c478bd9Sstevel@tonic-gate * t1394_idma_hdl The IDMA "handle" returned by 32357c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_dma() 32367c478bd9Sstevel@tonic-gate * idma_ctrlinfo This structure contains control args 32377c478bd9Sstevel@tonic-gate * used when starting isoch DMA for 32387c478bd9Sstevel@tonic-gate * the allocated resource 32397c478bd9Sstevel@tonic-gate * flags One flag defined - ID1394_START_ON_CYCLE 32407c478bd9Sstevel@tonic-gate * 32417c478bd9Sstevel@tonic-gate * Output(s): result Used to pass more specific info back 32427c478bd9Sstevel@tonic-gate * to target 32437c478bd9Sstevel@tonic-gate * 32447c478bd9Sstevel@tonic-gate * Description: t1394_start_isoch_dma() is used to start DMA for the isoch 32457c478bd9Sstevel@tonic-gate * stream associated with t1394_idma_hdl. 32467c478bd9Sstevel@tonic-gate */ 32477c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32487c478bd9Sstevel@tonic-gate int 32497c478bd9Sstevel@tonic-gate t1394_start_isoch_dma(t1394_handle_t t1394_hdl, 32507c478bd9Sstevel@tonic-gate t1394_isoch_dma_handle_t t1394_idma_hdl, 32517c478bd9Sstevel@tonic-gate id1394_isoch_dma_ctrlinfo_t *idma_ctrlinfo, uint_t flags, 32527c478bd9Sstevel@tonic-gate int *result) 32537c478bd9Sstevel@tonic-gate { 32547c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 32557c478bd9Sstevel@tonic-gate int ret; 32567c478bd9Sstevel@tonic-gate 32577c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_dma_enter, 32587c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 32597c478bd9Sstevel@tonic-gate 32607c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 32617c478bd9Sstevel@tonic-gate ASSERT(t1394_idma_hdl != NULL); 32627c478bd9Sstevel@tonic-gate ASSERT(idma_ctrlinfo != NULL); 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 32657c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 32667c478bd9Sstevel@tonic-gate 32677c478bd9Sstevel@tonic-gate ret = HAL_CALL(hal).start_isoch_dma(hal->halinfo.hal_private, 32687c478bd9Sstevel@tonic-gate (void *)t1394_idma_hdl, idma_ctrlinfo, flags, result); 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_start_isoch_dma_exit, 32717c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 32727c478bd9Sstevel@tonic-gate return (ret); 32737c478bd9Sstevel@tonic-gate } 32747c478bd9Sstevel@tonic-gate 32757c478bd9Sstevel@tonic-gate /* 32767c478bd9Sstevel@tonic-gate * Function: t1394_stop_isoch_dma() 32777c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 32787c478bd9Sstevel@tonic-gate * t1394_attach() 32797c478bd9Sstevel@tonic-gate * t1394_idma_hdl The IDMA "handle" returned by 32807c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_dma() 32817c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 32827c478bd9Sstevel@tonic-gate * 32837c478bd9Sstevel@tonic-gate * Output(s): None 32847c478bd9Sstevel@tonic-gate * 32857c478bd9Sstevel@tonic-gate * Description: t1394_stop_isoch_dma() is used to stop DMA for the isoch 32867c478bd9Sstevel@tonic-gate * stream associated with t1394_idma_hdl. 32877c478bd9Sstevel@tonic-gate */ 32887c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32897c478bd9Sstevel@tonic-gate void 32907c478bd9Sstevel@tonic-gate t1394_stop_isoch_dma(t1394_handle_t t1394_hdl, 32917c478bd9Sstevel@tonic-gate t1394_isoch_dma_handle_t t1394_idma_hdl, uint_t flags) 32927c478bd9Sstevel@tonic-gate { 32937c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 32947c478bd9Sstevel@tonic-gate int result; 32957c478bd9Sstevel@tonic-gate 32967c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_stop_isoch_dma_enter, 32977c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 33007c478bd9Sstevel@tonic-gate ASSERT(t1394_idma_hdl != NULL); 33017c478bd9Sstevel@tonic-gate 33027c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 33037c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 33047c478bd9Sstevel@tonic-gate 33057c478bd9Sstevel@tonic-gate HAL_CALL(hal).stop_isoch_dma(hal->halinfo.hal_private, 33067c478bd9Sstevel@tonic-gate (void *)t1394_idma_hdl, &result); 33077c478bd9Sstevel@tonic-gate 33087c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_stop_isoch_dma_exit, 33097c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 33107c478bd9Sstevel@tonic-gate } 33117c478bd9Sstevel@tonic-gate 33127c478bd9Sstevel@tonic-gate /* 33137c478bd9Sstevel@tonic-gate * Function: t1394_update_isoch_dma() 33147c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 33157c478bd9Sstevel@tonic-gate * t1394_attach() 33167c478bd9Sstevel@tonic-gate * t1394_idma_hdl The IDMA "handle" returned by 33177c478bd9Sstevel@tonic-gate * t1394_alloc_isoch_dma() 33187c478bd9Sstevel@tonic-gate * idma_updateinfo This structure contains ixl command args 33197c478bd9Sstevel@tonic-gate * used when updating args in an 33207c478bd9Sstevel@tonic-gate * existing list of ixl commands with 33217c478bd9Sstevel@tonic-gate * args in a new list of ixl commands. 33227c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 33237c478bd9Sstevel@tonic-gate * 33247c478bd9Sstevel@tonic-gate * Output(s): result Used to pass more specific info back 33257c478bd9Sstevel@tonic-gate * to target 33267c478bd9Sstevel@tonic-gate * 33277c478bd9Sstevel@tonic-gate * Description: t1394_update_isoch_dma() is used to alter an IXL program that 33287c478bd9Sstevel@tonic-gate * has already been built (compiled) by t1394_alloc_isoch_dma(). 33297c478bd9Sstevel@tonic-gate */ 33307c478bd9Sstevel@tonic-gate /* ARGSUSED */ 33317c478bd9Sstevel@tonic-gate int 33327c478bd9Sstevel@tonic-gate t1394_update_isoch_dma(t1394_handle_t t1394_hdl, 33337c478bd9Sstevel@tonic-gate t1394_isoch_dma_handle_t t1394_idma_hdl, 33347c478bd9Sstevel@tonic-gate id1394_isoch_dma_updateinfo_t *idma_updateinfo, uint_t flags, 33357c478bd9Sstevel@tonic-gate int *result) 33367c478bd9Sstevel@tonic-gate { 33377c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 33387c478bd9Sstevel@tonic-gate int ret; 33397c478bd9Sstevel@tonic-gate 33407c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_update_isoch_dma_enter, 33417c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 33427c478bd9Sstevel@tonic-gate 33437c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 33447c478bd9Sstevel@tonic-gate ASSERT(t1394_idma_hdl != NULL); 33457c478bd9Sstevel@tonic-gate ASSERT(idma_updateinfo != NULL); 33467c478bd9Sstevel@tonic-gate 33477c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 33487c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate ret = HAL_CALL(hal).update_isoch_dma(hal->halinfo.hal_private, 33517c478bd9Sstevel@tonic-gate (void *)t1394_idma_hdl, idma_updateinfo, flags, result); 33527c478bd9Sstevel@tonic-gate 33537c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_update_isoch_dma_exit, 33547c478bd9Sstevel@tonic-gate S1394_TNF_SL_ISOCH_STACK, ""); 33557c478bd9Sstevel@tonic-gate return (ret); 33567c478bd9Sstevel@tonic-gate } 33577c478bd9Sstevel@tonic-gate 33587c478bd9Sstevel@tonic-gate /* 33597c478bd9Sstevel@tonic-gate * Function: t1394_initiate_bus_reset() 33607c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 33617c478bd9Sstevel@tonic-gate * t1394_attach() 33627c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 33637c478bd9Sstevel@tonic-gate * 33647c478bd9Sstevel@tonic-gate * Output(s): None 33657c478bd9Sstevel@tonic-gate * 33667c478bd9Sstevel@tonic-gate * Description: t1394_initiate_bus_reset() determines whether the local 33677c478bd9Sstevel@tonic-gate * device has a P1394A PHY and will support the arbitrated 33687c478bd9Sstevel@tonic-gate * short bus reset. If not, it will initiate a normal bus reset. 33697c478bd9Sstevel@tonic-gate */ 33707c478bd9Sstevel@tonic-gate /* ARGSUSED */ 33717c478bd9Sstevel@tonic-gate void 33727c478bd9Sstevel@tonic-gate t1394_initiate_bus_reset(t1394_handle_t t1394_hdl, uint_t flags) 33737c478bd9Sstevel@tonic-gate { 33747c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 33757c478bd9Sstevel@tonic-gate int ret; 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_initiate_bus_reset_enter, 33787c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, ""); 33797c478bd9Sstevel@tonic-gate 33807c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 33817c478bd9Sstevel@tonic-gate 33827c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 33837c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 33847c478bd9Sstevel@tonic-gate 33857c478bd9Sstevel@tonic-gate /* Reset the bus */ 33867c478bd9Sstevel@tonic-gate if (hal->halinfo.phy == H1394_PHY_1394A) { 33877c478bd9Sstevel@tonic-gate ret = HAL_CALL(hal).short_bus_reset(hal->halinfo.hal_private); 33887c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 33897c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_initiate_bus_reset_error, 33907c478bd9Sstevel@tonic-gate S1394_TNF_SL_ERROR, "", tnf_string, msg, 33917c478bd9Sstevel@tonic-gate "Error initiating short bus reset"); 33927c478bd9Sstevel@tonic-gate } 33937c478bd9Sstevel@tonic-gate } else { 33947c478bd9Sstevel@tonic-gate ret = HAL_CALL(hal).bus_reset(hal->halinfo.hal_private); 33957c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 33967c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_initiate_bus_reset_error, 33977c478bd9Sstevel@tonic-gate S1394_TNF_SL_ERROR, "", tnf_string, msg, 33987c478bd9Sstevel@tonic-gate "Error initiating bus reset"); 33997c478bd9Sstevel@tonic-gate } 34007c478bd9Sstevel@tonic-gate } 34017c478bd9Sstevel@tonic-gate 34027c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_initiate_bus_reset_exit, 34037c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, ""); 34047c478bd9Sstevel@tonic-gate } 34057c478bd9Sstevel@tonic-gate 34067c478bd9Sstevel@tonic-gate /* 34077c478bd9Sstevel@tonic-gate * Function: t1394_get_topology_map() 34087c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 34097c478bd9Sstevel@tonic-gate * t1394_attach() 34107c478bd9Sstevel@tonic-gate * bus_generation The current generation 34117c478bd9Sstevel@tonic-gate * tm_length The size of the tm_buffer given 34127c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 34137c478bd9Sstevel@tonic-gate * 34147c478bd9Sstevel@tonic-gate * Output(s): tm_buffer Filled in by the 1394 Software Framework 34157c478bd9Sstevel@tonic-gate * with the contents of the local 34167c478bd9Sstevel@tonic-gate * TOPOLOGY_MAP 34177c478bd9Sstevel@tonic-gate * 34187c478bd9Sstevel@tonic-gate * Description: t1394_get_topology_map() returns the 1394 TOPLOGY_MAP. See 34197c478bd9Sstevel@tonic-gate * IEEE 1394-1995 Section 8.2.3.4.1 for format information. This 34207c478bd9Sstevel@tonic-gate * call can fail if there is a generation mismatch or the 34217c478bd9Sstevel@tonic-gate * tm_buffer is too small to hold the TOPOLOGY_MAP. 34227c478bd9Sstevel@tonic-gate */ 34237c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34247c478bd9Sstevel@tonic-gate int 34257c478bd9Sstevel@tonic-gate t1394_get_topology_map(t1394_handle_t t1394_hdl, uint_t bus_generation, 34267c478bd9Sstevel@tonic-gate size_t tm_length, uint_t flags, uint32_t *tm_buffer) 34277c478bd9Sstevel@tonic-gate { 34287c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 34297c478bd9Sstevel@tonic-gate uint32_t *tm_ptr; 34307c478bd9Sstevel@tonic-gate uint_t length; 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_get_topology_map_enter, S1394_TNF_SL_CSR_STACK, 34337c478bd9Sstevel@tonic-gate ""); 34347c478bd9Sstevel@tonic-gate 34357c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 34367c478bd9Sstevel@tonic-gate 34377c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 34387c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 34397c478bd9Sstevel@tonic-gate 34407c478bd9Sstevel@tonic-gate /* Lock the topology tree */ 34417c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 34427c478bd9Sstevel@tonic-gate 34437c478bd9Sstevel@tonic-gate /* Check the bus_generation for the Topology Map */ 34447c478bd9Sstevel@tonic-gate if (bus_generation != hal->generation_count) { 34457c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 34467c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 34477c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_get_topology_map_error, 34487c478bd9Sstevel@tonic-gate S1394_TNF_SL_CSR_ERROR, "", tnf_string, msg, 34497c478bd9Sstevel@tonic-gate "Generation mismatch"); 34507c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_get_topology_map_exit, 34517c478bd9Sstevel@tonic-gate S1394_TNF_SL_CSR_STACK, ""); 34527c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 34537c478bd9Sstevel@tonic-gate } 34547c478bd9Sstevel@tonic-gate 34557c478bd9Sstevel@tonic-gate tm_ptr = (uint32_t *)hal->CSR_topology_map; 34567c478bd9Sstevel@tonic-gate length = tm_ptr[0] >> 16; 34577c478bd9Sstevel@tonic-gate length = length * 4; /* Bytes instead of quadlets */ 34587c478bd9Sstevel@tonic-gate length = length + 4; /* don't forget the first quad */ 34597c478bd9Sstevel@tonic-gate 34607c478bd9Sstevel@tonic-gate /* Check that the buffer is big enough */ 34617c478bd9Sstevel@tonic-gate if (length > (uint_t)tm_length) { 34627c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 34637c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 34647c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_get_topology_map_error, 34657c478bd9Sstevel@tonic-gate S1394_TNF_SL_CSR_ERROR, "", tnf_string, msg, 34667c478bd9Sstevel@tonic-gate "Buffer size too small"); 34677c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_get_topology_map_exit, 34687c478bd9Sstevel@tonic-gate S1394_TNF_SL_CSR_STACK, ""); 34697c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 34707c478bd9Sstevel@tonic-gate } 34717c478bd9Sstevel@tonic-gate 34727c478bd9Sstevel@tonic-gate /* Do the copy */ 34737c478bd9Sstevel@tonic-gate bcopy(tm_ptr, tm_buffer, length); 34747c478bd9Sstevel@tonic-gate 34757c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 34767c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 34777c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_get_topology_map_exit, S1394_TNF_SL_CSR_STACK, 34787c478bd9Sstevel@tonic-gate ""); 34797c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 34807c478bd9Sstevel@tonic-gate } 34817c478bd9Sstevel@tonic-gate 34827c478bd9Sstevel@tonic-gate /* 34837c478bd9Sstevel@tonic-gate * Function: t1394_CRC16() 34847c478bd9Sstevel@tonic-gate * Input(s): d The data to compute the CRC-16 for 34857c478bd9Sstevel@tonic-gate * crc_length The length into the data to compute for 34867c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 34877c478bd9Sstevel@tonic-gate * 34887c478bd9Sstevel@tonic-gate * Output(s): CRC The CRC-16 computed for the length 34897c478bd9Sstevel@tonic-gate * of data specified 34907c478bd9Sstevel@tonic-gate * 34917c478bd9Sstevel@tonic-gate * Description: t1394_CRC16() implements ISO/IEC 13213:1994, ANSI/IEEE Std 34927c478bd9Sstevel@tonic-gate * 1212, 1994 - 8.1.5. 34937c478bd9Sstevel@tonic-gate */ 34947c478bd9Sstevel@tonic-gate /* ARGSUSED */ 34957c478bd9Sstevel@tonic-gate uint_t 34967c478bd9Sstevel@tonic-gate t1394_CRC16(uint32_t *d, size_t crc_length, uint_t flags) 34977c478bd9Sstevel@tonic-gate { 34987c478bd9Sstevel@tonic-gate /* Implements ISO/IEC 13213:1994, */ 34997c478bd9Sstevel@tonic-gate /* ANSI/IEEE Std 1212, 1994 - 8.1.5 */ 35007c478bd9Sstevel@tonic-gate uint_t ret; 35017c478bd9Sstevel@tonic-gate 35027c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_CRC16_enter, S1394_TNF_SL_STACK, ""); 35037c478bd9Sstevel@tonic-gate 35047c478bd9Sstevel@tonic-gate ret = s1394_CRC16((uint_t *)d, (uint_t)crc_length); 35057c478bd9Sstevel@tonic-gate 35067c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_CRC16_exit, S1394_TNF_SL_STACK, ""); 35077c478bd9Sstevel@tonic-gate return (ret); 35087c478bd9Sstevel@tonic-gate } 35097c478bd9Sstevel@tonic-gate 35107c478bd9Sstevel@tonic-gate /* 35117c478bd9Sstevel@tonic-gate * Function: t1394_add_cfgrom_entry() 35127c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 35137c478bd9Sstevel@tonic-gate * t1394_attach() 35147c478bd9Sstevel@tonic-gate * cfgrom_entryinfo This structure holds the cfgrom key, 35157c478bd9Sstevel@tonic-gate * buffer, and size 35167c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 35177c478bd9Sstevel@tonic-gate * 35187c478bd9Sstevel@tonic-gate * Output(s): t1394_cfgrom_hdl The ConfigROM "handle" used in 35197c478bd9Sstevel@tonic-gate * t1394_rem_cfgrom_entry() 35207c478bd9Sstevel@tonic-gate * result Used to pass more specific info back 35217c478bd9Sstevel@tonic-gate * to target 35227c478bd9Sstevel@tonic-gate * 35237c478bd9Sstevel@tonic-gate * Description: t1394_add_cfgrom_entry() adds an entry to the local Config ROM, 35247c478bd9Sstevel@tonic-gate * updating the directory entries as necessary. This call could 35257c478bd9Sstevel@tonic-gate * fail because there is no room for the new entry in Config ROM 35267c478bd9Sstevel@tonic-gate * (T1394_ECFGROM_FULL), the key is invalid (T1394_EINVALID_PARAM), 35277c478bd9Sstevel@tonic-gate * or it was called in interrupt context (T1394_EINVALID_CONTEXT). 35287c478bd9Sstevel@tonic-gate */ 35297c478bd9Sstevel@tonic-gate /* ARGSUSED */ 35307c478bd9Sstevel@tonic-gate int 35317c478bd9Sstevel@tonic-gate t1394_add_cfgrom_entry(t1394_handle_t t1394_hdl, 35327c478bd9Sstevel@tonic-gate t1394_cfgrom_entryinfo_t *cfgrom_entryinfo, uint_t flags, 35337c478bd9Sstevel@tonic-gate t1394_cfgrom_handle_t *t1394_cfgrom_hdl, int *result) 35347c478bd9Sstevel@tonic-gate { 35357c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 35367c478bd9Sstevel@tonic-gate s1394_target_t *target; 35377c478bd9Sstevel@tonic-gate int ret; 35387c478bd9Sstevel@tonic-gate uint_t key; 35397c478bd9Sstevel@tonic-gate uint_t size; 35407c478bd9Sstevel@tonic-gate uint32_t *buffer; 35417c478bd9Sstevel@tonic-gate 35427c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_add_cfgrom_entry_enter, 35437c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 35447c478bd9Sstevel@tonic-gate 35457c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 35467c478bd9Sstevel@tonic-gate 35477c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 35487c478bd9Sstevel@tonic-gate 35497c478bd9Sstevel@tonic-gate key = cfgrom_entryinfo->ce_key; 35507c478bd9Sstevel@tonic-gate buffer = cfgrom_entryinfo->ce_buffer; 35517c478bd9Sstevel@tonic-gate size = (uint_t)cfgrom_entryinfo->ce_size; 35527c478bd9Sstevel@tonic-gate 35537c478bd9Sstevel@tonic-gate /* Check for a valid size */ 35547c478bd9Sstevel@tonic-gate if (size == 0) { 35557c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_PARAM; 35567c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(t1394_add_cfgrom_entry_error, 35577c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_ERROR, "", tnf_string, msg, 35587c478bd9Sstevel@tonic-gate "Invalid size of Config ROM buffer (== 0)"); 35597c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_add_cfgrom_entry_exit, 35607c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 35617c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 35627c478bd9Sstevel@tonic-gate } 35637c478bd9Sstevel@tonic-gate 35647c478bd9Sstevel@tonic-gate /* Check for a valid key type */ 35657c478bd9Sstevel@tonic-gate if (((key << IEEE1212_KEY_VALUE_SHIFT) & IEEE1212_KEY_TYPE_MASK) == 0) { 35667c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_PARAM; 35677c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(t1394_add_cfgrom_entry_error, 35687c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_ERROR, "", tnf_string, msg, 35697c478bd9Sstevel@tonic-gate "Invalid key_type in Config ROM key"); 35707c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_add_cfgrom_entry_exit, 35717c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 35727c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 35737c478bd9Sstevel@tonic-gate } 35747c478bd9Sstevel@tonic-gate 35757c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 35767c478bd9Sstevel@tonic-gate hal = target->on_hal; 35777c478bd9Sstevel@tonic-gate 35787c478bd9Sstevel@tonic-gate /* Is this on the interrupt stack? */ 357980a70ef3Sap25164 if (servicing_interrupt()) { 35807c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_CONTEXT; 35817c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_add_cfgrom_entry_exit, 35827c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 35837c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 35847c478bd9Sstevel@tonic-gate } 35857c478bd9Sstevel@tonic-gate 35867c478bd9Sstevel@tonic-gate /* Lock the Config ROM buffer */ 35877c478bd9Sstevel@tonic-gate mutex_enter(&hal->local_config_rom_mutex); 35887c478bd9Sstevel@tonic-gate 35897c478bd9Sstevel@tonic-gate ret = s1394_add_config_rom_entry(hal, key, buffer, size, 35907c478bd9Sstevel@tonic-gate (void **)t1394_cfgrom_hdl, result); 35917c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 35927c478bd9Sstevel@tonic-gate if (*result == CMD1394_ERSRC_CONFLICT) 35937c478bd9Sstevel@tonic-gate *result = T1394_ECFGROM_FULL; 35947c478bd9Sstevel@tonic-gate mutex_exit(&hal->local_config_rom_mutex); 35957c478bd9Sstevel@tonic-gate 35967c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_add_cfgrom_entry_error, 35977c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_ERROR, "", tnf_string, msg, 35987c478bd9Sstevel@tonic-gate "Failed in s1394_add_cfgrom_entry()"); 35997c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_add_cfgrom_entry_exit, 36007c478bd9Sstevel@tonic-gate "stacktrace 1394 s1394", ""); 36017c478bd9Sstevel@tonic-gate return (ret); 36027c478bd9Sstevel@tonic-gate } 36037c478bd9Sstevel@tonic-gate 36047c478bd9Sstevel@tonic-gate /* Setup the timeout function */ 36057c478bd9Sstevel@tonic-gate if (hal->config_rom_timer_set == B_FALSE) { 36067c478bd9Sstevel@tonic-gate hal->config_rom_timer_set = B_TRUE; 36077c478bd9Sstevel@tonic-gate mutex_exit(&hal->local_config_rom_mutex); 36087c478bd9Sstevel@tonic-gate hal->config_rom_timer = 36097c478bd9Sstevel@tonic-gate timeout(s1394_update_config_rom_callback, hal, 36107c478bd9Sstevel@tonic-gate drv_usectohz(CONFIG_ROM_UPDATE_DELAY * 1000)); 36117c478bd9Sstevel@tonic-gate } else { 36127c478bd9Sstevel@tonic-gate mutex_exit(&hal->local_config_rom_mutex); 36137c478bd9Sstevel@tonic-gate } 36147c478bd9Sstevel@tonic-gate 36157c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_add_cfgrom_entry_exit, 36167c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 36177c478bd9Sstevel@tonic-gate return (ret); 36187c478bd9Sstevel@tonic-gate } 36197c478bd9Sstevel@tonic-gate 36207c478bd9Sstevel@tonic-gate /* 36217c478bd9Sstevel@tonic-gate * Function: t1394_rem_cfgrom_entry() 36227c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 36237c478bd9Sstevel@tonic-gate * t1394_attach() 36247c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 36257c478bd9Sstevel@tonic-gate * t1394_cfgrom_hdl The ConfigROM "handle" returned by 36267c478bd9Sstevel@tonic-gate * t1394_add_cfgrom_entry() 36277c478bd9Sstevel@tonic-gate * 36287c478bd9Sstevel@tonic-gate * Output(s): result Used to pass more specific info back 36297c478bd9Sstevel@tonic-gate * to target 36307c478bd9Sstevel@tonic-gate * 36317c478bd9Sstevel@tonic-gate * Description: t1394_rem_cfgrom_entry() is used to remove a previously added 36327c478bd9Sstevel@tonic-gate * Config ROM entry (indicated by t1394_cfgrom_hdl). 36337c478bd9Sstevel@tonic-gate */ 36347c478bd9Sstevel@tonic-gate /* ARGSUSED */ 36357c478bd9Sstevel@tonic-gate int 36367c478bd9Sstevel@tonic-gate t1394_rem_cfgrom_entry(t1394_handle_t t1394_hdl, uint_t flags, 36377c478bd9Sstevel@tonic-gate t1394_cfgrom_handle_t *t1394_cfgrom_hdl, int *result) 36387c478bd9Sstevel@tonic-gate { 36397c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 36407c478bd9Sstevel@tonic-gate s1394_target_t *target; 36417c478bd9Sstevel@tonic-gate int ret; 36427c478bd9Sstevel@tonic-gate 36437c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_rem_cfgrom_entry_enter, 36447c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 36457c478bd9Sstevel@tonic-gate 36467c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 36477c478bd9Sstevel@tonic-gate 36487c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 36497c478bd9Sstevel@tonic-gate 36507c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 36517c478bd9Sstevel@tonic-gate hal = target->on_hal; 36527c478bd9Sstevel@tonic-gate 36537c478bd9Sstevel@tonic-gate /* Is this on the interrupt stack? */ 365480a70ef3Sap25164 if (servicing_interrupt()) { 36557c478bd9Sstevel@tonic-gate *result = T1394_EINVALID_CONTEXT; 36567c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_rem_cfgrom_entry_exit, 36577c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 36587c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 36597c478bd9Sstevel@tonic-gate } 36607c478bd9Sstevel@tonic-gate 36617c478bd9Sstevel@tonic-gate /* Lock the Config ROM buffer */ 36627c478bd9Sstevel@tonic-gate mutex_enter(&hal->local_config_rom_mutex); 36637c478bd9Sstevel@tonic-gate 36647c478bd9Sstevel@tonic-gate ret = s1394_remove_config_rom_entry(hal, (void **)t1394_cfgrom_hdl, 36657c478bd9Sstevel@tonic-gate result); 36667c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 36677c478bd9Sstevel@tonic-gate mutex_exit(&hal->local_config_rom_mutex); 36687c478bd9Sstevel@tonic-gate TNF_PROBE_1(t1394_rem_cfgrom_entry_error, 36697c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_ERROR, "", tnf_string, msg, 36707c478bd9Sstevel@tonic-gate "Failed in s1394_remove_cfgrom_entry()"); 36717c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_rem_cfgrom_entry_exit, 36727c478bd9Sstevel@tonic-gate "stacktrace 1394 s1394", ""); 36737c478bd9Sstevel@tonic-gate return (ret); 36747c478bd9Sstevel@tonic-gate } 36757c478bd9Sstevel@tonic-gate 36767c478bd9Sstevel@tonic-gate /* Setup the timeout function */ 36777c478bd9Sstevel@tonic-gate if (hal->config_rom_timer_set == B_FALSE) { 36787c478bd9Sstevel@tonic-gate hal->config_rom_timer_set = B_TRUE; 36797c478bd9Sstevel@tonic-gate mutex_exit(&hal->local_config_rom_mutex); 36807c478bd9Sstevel@tonic-gate hal->config_rom_timer = 36817c478bd9Sstevel@tonic-gate timeout(s1394_update_config_rom_callback, hal, 36827c478bd9Sstevel@tonic-gate drv_usectohz(CONFIG_ROM_UPDATE_DELAY * 1000)); 36837c478bd9Sstevel@tonic-gate } else { 36847c478bd9Sstevel@tonic-gate mutex_exit(&hal->local_config_rom_mutex); 36857c478bd9Sstevel@tonic-gate } 36867c478bd9Sstevel@tonic-gate 36877c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_rem_cfgrom_entry_exit, 36887c478bd9Sstevel@tonic-gate S1394_TNF_SL_CFGROM_STACK, ""); 36897c478bd9Sstevel@tonic-gate return (ret); 36907c478bd9Sstevel@tonic-gate } 36917c478bd9Sstevel@tonic-gate 36927c478bd9Sstevel@tonic-gate /* 36937c478bd9Sstevel@tonic-gate * Function: t1394_get_targetinfo() 36947c478bd9Sstevel@tonic-gate * Input(s): t1394_hdl The target "handle" returned by 36957c478bd9Sstevel@tonic-gate * t1394_attach() 36967c478bd9Sstevel@tonic-gate * bus_generation The current generation 36977c478bd9Sstevel@tonic-gate * flags The flags parameter is unused (for now) 36987c478bd9Sstevel@tonic-gate * 36997c478bd9Sstevel@tonic-gate * Output(s): targetinfo Structure containing max_payload, 37007c478bd9Sstevel@tonic-gate * max_speed, and target node ID. 37017c478bd9Sstevel@tonic-gate * 37027c478bd9Sstevel@tonic-gate * Description: t1394_get_targetinfo() is used to retrieve information specific 37037c478bd9Sstevel@tonic-gate * to a target device. It will fail if the generation given 37047c478bd9Sstevel@tonic-gate * does not match the current generation. 37057c478bd9Sstevel@tonic-gate */ 37067c478bd9Sstevel@tonic-gate /* ARGSUSED */ 37077c478bd9Sstevel@tonic-gate int 37087c478bd9Sstevel@tonic-gate t1394_get_targetinfo(t1394_handle_t t1394_hdl, uint_t bus_generation, 37097c478bd9Sstevel@tonic-gate uint_t flags, t1394_targetinfo_t *targetinfo) 37107c478bd9Sstevel@tonic-gate { 37117c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 37127c478bd9Sstevel@tonic-gate s1394_target_t *target; 37137c478bd9Sstevel@tonic-gate uint_t dev; 37147c478bd9Sstevel@tonic-gate uint_t curr; 37157c478bd9Sstevel@tonic-gate uint_t from_node; 37167c478bd9Sstevel@tonic-gate uint_t to_node; 37177c478bd9Sstevel@tonic-gate 37187c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(t1394_get_targetinfo_enter, S1394_TNF_SL_STACK, ""); 37197c478bd9Sstevel@tonic-gate 37207c478bd9Sstevel@tonic-gate ASSERT(t1394_hdl != NULL); 37217c478bd9Sstevel@tonic-gate 37227c478bd9Sstevel@tonic-gate /* Find the HAL this target resides on */ 37237c478bd9Sstevel@tonic-gate hal = ((s1394_target_t *)t1394_hdl)->on_hal; 37247c478bd9Sstevel@tonic-gate 37257c478bd9Sstevel@tonic-gate target = (s1394_target_t *)t1394_hdl; 37267c478bd9Sstevel@tonic-gate 37277c478bd9Sstevel@tonic-gate /* Lock the topology tree */ 37287c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 37297c478bd9Sstevel@tonic-gate 37307c478bd9Sstevel@tonic-gate /* Check the bus_generation */ 37317c478bd9Sstevel@tonic-gate if (bus_generation != hal->generation_count) { 37327c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 37337c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 37347c478bd9Sstevel@tonic-gate TNF_PROBE_3(t1394_get_targetinfo_error, S1394_TNF_SL_STACK, "", 37357c478bd9Sstevel@tonic-gate tnf_string, msg, "Generation mismatch", 37367c478bd9Sstevel@tonic-gate tnf_uint, gen, bus_generation, 37377c478bd9Sstevel@tonic-gate tnf_uint, current_gen, hal->generation_count); 37387c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 37397c478bd9Sstevel@tonic-gate } 37407c478bd9Sstevel@tonic-gate 37417c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_READER); 37427c478bd9Sstevel@tonic-gate /* 37437c478bd9Sstevel@tonic-gate * If there is no node, report T1394_INVALID_NODEID for target_nodeID; 37447c478bd9Sstevel@tonic-gate * current_max_speed and current_max_payload are undefined for this 37457c478bd9Sstevel@tonic-gate * case. 37467c478bd9Sstevel@tonic-gate */ 37477c478bd9Sstevel@tonic-gate if (((target->target_state & S1394_TARG_GONE) != 0) || 37487c478bd9Sstevel@tonic-gate (target->on_node == NULL)) { 37497c478bd9Sstevel@tonic-gate targetinfo->target_nodeID = T1394_INVALID_NODEID; 37507c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(t1394_get_targetinfo_exit, 37517c478bd9Sstevel@tonic-gate S1394_TNF_SL_STACK, "", tnf_string, msg, "No device"); 37527c478bd9Sstevel@tonic-gate } else { 37537c478bd9Sstevel@tonic-gate targetinfo->target_nodeID = 37547c478bd9Sstevel@tonic-gate (target->on_hal->node_id & IEEE1394_BUS_NUM_MASK) | 37557c478bd9Sstevel@tonic-gate target->on_node->node_num; 37567c478bd9Sstevel@tonic-gate 37577c478bd9Sstevel@tonic-gate from_node = (target->on_hal->node_id) & IEEE1394_NODE_NUM_MASK; 37587c478bd9Sstevel@tonic-gate to_node = target->on_node->node_num; 37597c478bd9Sstevel@tonic-gate 37607c478bd9Sstevel@tonic-gate targetinfo->current_max_speed = (uint_t)s1394_speed_map_get( 37617c478bd9Sstevel@tonic-gate hal, from_node, to_node); 37627c478bd9Sstevel@tonic-gate 37637c478bd9Sstevel@tonic-gate /* Get current_max_payload */ 37647c478bd9Sstevel@tonic-gate s1394_get_maxpayload(target, &dev, &curr); 37657c478bd9Sstevel@tonic-gate targetinfo->current_max_payload = curr; 37667c478bd9Sstevel@tonic-gate 37677c478bd9Sstevel@tonic-gate TNF_PROBE_3_DEBUG(t1394_get_targetinfo_exit, 37687c478bd9Sstevel@tonic-gate S1394_TNF_SL_STACK, "", 37697c478bd9Sstevel@tonic-gate tnf_uint, payload, targetinfo->current_max_payload, 37707c478bd9Sstevel@tonic-gate tnf_uint, speed, targetinfo->current_max_speed, 37717c478bd9Sstevel@tonic-gate tnf_uint, nodeid, targetinfo->target_nodeID); 37727c478bd9Sstevel@tonic-gate } 37737c478bd9Sstevel@tonic-gate 37747c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 37757c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 37767c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 37777c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 37787c478bd9Sstevel@tonic-gate } 3779