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
t1394_attach(dev_info_t * dip,int version,uint_t flags,t1394_attachinfo_t * attachinfo,t1394_handle_t * t1394_hdl)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
t1394_detach(t1394_handle_t * t1394_hdl,uint_t flags)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
t1394_alloc_cmd(t1394_handle_t t1394_hdl,uint_t flags,cmd1394_cmd_t ** cmdp)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
t1394_free_cmd(t1394_handle_t t1394_hdl,uint_t flags,cmd1394_cmd_t ** cmdp)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
t1394_read(t1394_handle_t t1394_hdl,cmd1394_cmd_t * cmd)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
t1394_write(t1394_handle_t t1394_hdl,cmd1394_cmd_t * cmd)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
t1394_lock(t1394_handle_t t1394_hdl,cmd1394_cmd_t * cmd)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
t1394_alloc_addr(t1394_handle_t t1394_hdl,t1394_alloc_addr_t * addr_allocp,uint_t flags,int * result)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
t1394_free_addr(t1394_handle_t t1394_hdl,t1394_addr_handle_t * addr_hdl,uint_t flags)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
t1394_recv_request_done(t1394_handle_t t1394_hdl,cmd1394_cmd_t * resp,uint_t flags)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
t1394_fcp_register_controller(t1394_handle_t t1394_hdl,t1394_fcp_evts_t * evts,uint_t flags)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
t1394_fcp_unregister_controller(t1394_handle_t t1394_hdl)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
t1394_fcp_register_target(t1394_handle_t t1394_hdl,t1394_fcp_evts_t * evts,uint_t flags)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
t1394_fcp_unregister_target(t1394_handle_t t1394_hdl)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
t1394_cmp_register(t1394_handle_t t1394_hdl,t1394_cmp_evts_t * evts,uint_t flags)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
t1394_cmp_unregister(t1394_handle_t t1394_hdl)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
t1394_cmp_read(t1394_handle_t t1394_hdl,t1394_cmp_reg_t reg,uint32_t * valp)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
t1394_cmp_cas(t1394_handle_t t1394_hdl,t1394_cmp_reg_t reg,uint32_t arg_val,uint32_t new_val,uint32_t * old_valp)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
t1394_alloc_isoch_single(t1394_handle_t t1394_hdl,t1394_isoch_singleinfo_t * sii,uint_t flags,t1394_isoch_single_out_t * output_args,t1394_isoch_single_handle_t * t1394_single_hdl,int * result)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
t1394_free_isoch_single(t1394_handle_t t1394_hdl,t1394_isoch_single_handle_t * t1394_single_hdl,uint_t flags)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
t1394_alloc_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_props_t * props,uint_t flags,t1394_isoch_cec_handle_t * t1394_isoch_cec_hdl)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
t1394_free_isoch_cec(t1394_handle_t t1394_hdl,uint_t flags,t1394_isoch_cec_handle_t * t1394_isoch_cec_hdl)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
t1394_join_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_handle_t t1394_isoch_cec_hdl,uint_t flags,t1394_join_isochinfo_t * join_isoch_info)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
t1394_leave_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_handle_t t1394_isoch_cec_hdl,uint_t flags)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
t1394_setup_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_handle_t t1394_isoch_cec_hdl,uint_t flags,int * result)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
t1394_start_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_handle_t t1394_isoch_cec_hdl,uint_t flags)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
t1394_stop_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_handle_t t1394_isoch_cec_hdl,uint_t flags)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
t1394_teardown_isoch_cec(t1394_handle_t t1394_hdl,t1394_isoch_cec_handle_t t1394_isoch_cec_hdl,uint_t flags)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
t1394_alloc_isoch_dma(t1394_handle_t t1394_hdl,id1394_isoch_dmainfo_t * idi,uint_t flags,t1394_isoch_dma_handle_t * t1394_idma_hdl,int * result)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
t1394_free_isoch_dma(t1394_handle_t t1394_hdl,uint_t flags,t1394_isoch_dma_handle_t * t1394_idma_hdl)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
t1394_start_isoch_dma(t1394_handle_t t1394_hdl,t1394_isoch_dma_handle_t t1394_idma_hdl,id1394_isoch_dma_ctrlinfo_t * idma_ctrlinfo,uint_t flags,int * result)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
t1394_stop_isoch_dma(t1394_handle_t t1394_hdl,t1394_isoch_dma_handle_t t1394_idma_hdl,uint_t flags)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
t1394_update_isoch_dma(t1394_handle_t t1394_hdl,t1394_isoch_dma_handle_t t1394_idma_hdl,id1394_isoch_dma_updateinfo_t * idma_updateinfo,uint_t flags,int * result)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
t1394_initiate_bus_reset(t1394_handle_t t1394_hdl,uint_t flags)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
t1394_get_topology_map(t1394_handle_t t1394_hdl,uint_t bus_generation,size_t tm_length,uint_t flags,uint32_t * tm_buffer)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
t1394_CRC16(uint32_t * d,size_t crc_length,uint_t flags)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
t1394_add_cfgrom_entry(t1394_handle_t t1394_hdl,t1394_cfgrom_entryinfo_t * cfgrom_entryinfo,uint_t flags,t1394_cfgrom_handle_t * t1394_cfgrom_hdl,int * result)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
t1394_rem_cfgrom_entry(t1394_handle_t t1394_hdl,uint_t flags,t1394_cfgrom_handle_t * t1394_cfgrom_hdl,int * result)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
t1394_get_targetinfo(t1394_handle_t t1394_hdl,uint_t bus_generation,uint_t flags,t1394_targetinfo_t * targetinfo)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