xref: /onnv-gate/usr/src/uts/common/io/1394/s1394_bus_reset.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * s1394_bus_reset.c
31*0Sstevel@tonic-gate  *    1394 Services Layer Bus Reset Routines
32*0Sstevel@tonic-gate  *    These routines handle all of the tasks relating to 1394 bus resets
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <sys/conf.h>
36*0Sstevel@tonic-gate #include <sys/ddi.h>
37*0Sstevel@tonic-gate #include <sys/sunddi.h>
38*0Sstevel@tonic-gate #include <sys/types.h>
39*0Sstevel@tonic-gate #include <sys/kmem.h>
40*0Sstevel@tonic-gate #include <sys/tnf_probe.h>
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #include <sys/1394/t1394.h>
43*0Sstevel@tonic-gate #include <sys/1394/s1394.h>
44*0Sstevel@tonic-gate #include <sys/1394/h1394.h>
45*0Sstevel@tonic-gate #include <sys/1394/ieee1394.h>
46*0Sstevel@tonic-gate #include <sys/1394/ieee1212.h>
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate static uint8_t selfid_speed(s1394_selfid_pkt_t *s);
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate static int selfid_num_ports(s1394_selfid_pkt_t *s);
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate static int selfid_port_type(s1394_selfid_pkt_t *s, int port);
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate static void s1394_hal_stack_push(s1394_hal_t *hal, void *o);
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate static void *s1394_hal_stack_pop(s1394_hal_t *hal);
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate static void s1394_hal_queue_insert(s1394_hal_t *hal, void *o);
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate static void *s1394_hal_queue_remove(s1394_hal_t *hal);
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate static void s1394_node_number_list_add(s1394_hal_t *hal, int node_num);
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate static void s1394_speed_map_fill_speed_N(s1394_hal_t *hal, int min_spd);
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static void s1394_speed_map_initialize(s1394_hal_t *hal);
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate int s1394_ignore_invalid_gap_cnt = 0; /* patch for invalid gap_cnts */
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate  * Gap_count look-up table (See IEEE P1394a Table C-2) - Draft 3.0
72*0Sstevel@tonic-gate  * (modified from original table IEEE 1394-1995 8.4.6.2)
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate static int gap_count[MAX_HOPS + 1] = {
75*0Sstevel@tonic-gate 	0, 5, 7, 8, 10, 13, 16, 18, 21,
76*0Sstevel@tonic-gate 	24, 26, 29, 32, 35, 37, 40, 43,
77*0Sstevel@tonic-gate 	46, 48, 51, 54, 57, 59, 62
78*0Sstevel@tonic-gate };
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate /*
81*0Sstevel@tonic-gate  * s1394_parse_selfid_buffer()
82*0Sstevel@tonic-gate  *    takes the SelfID data buffer and parses it, testing whether each packet
83*0Sstevel@tonic-gate  *    is valid (has a correct inverse packet) and setting the pointers in
84*0Sstevel@tonic-gate  *    selfid_ptrs[] to the appropriate offsets within the buffer.
85*0Sstevel@tonic-gate  */
86*0Sstevel@tonic-gate int
s1394_parse_selfid_buffer(s1394_hal_t * hal,void * selfid_buf_addr,uint32_t selfid_size)87*0Sstevel@tonic-gate s1394_parse_selfid_buffer(s1394_hal_t *hal, void *selfid_buf_addr,
88*0Sstevel@tonic-gate     uint32_t selfid_size)
89*0Sstevel@tonic-gate {
90*0Sstevel@tonic-gate 	s1394_selfid_pkt_t *s;
91*0Sstevel@tonic-gate 	uint32_t	   *data;
92*0Sstevel@tonic-gate 	uint_t		   i = 0;
93*0Sstevel@tonic-gate 	uint_t		   j = 0;
94*0Sstevel@tonic-gate 	boolean_t	   error = B_FALSE;
95*0Sstevel@tonic-gate 	int		   valid_pkt_id;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_parse_selfid_buffer_enter,
98*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	data = (uint32_t *)selfid_buf_addr;
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	if (selfid_size == 0) {
105*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_parse_selfid_buffer_error,
106*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
107*0Sstevel@tonic-gate 		    "SelfID buffer error - zero size");
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 		/* Initiate a bus reset */
110*0Sstevel@tonic-gate 		s1394_initiate_hal_reset(hal, CRITICAL);
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 		/* Set error status */
113*0Sstevel@tonic-gate 		error = B_TRUE;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 		/* Release HAL lock and return */
116*0Sstevel@tonic-gate 		goto parse_buffer_done;
117*0Sstevel@tonic-gate 	}
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	/* Convert bytes to quadlets */
120*0Sstevel@tonic-gate 	selfid_size = selfid_size >> 2;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	while (j < selfid_size) {
123*0Sstevel@tonic-gate 		valid_pkt_id = ((data[j] & IEEE1394_SELFID_PCKT_ID_MASK) >>
124*0Sstevel@tonic-gate 		    IEEE1394_SELFID_PCKT_ID_SHIFT);
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 		s = (s1394_selfid_pkt_t *)(&data[j]);
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 		/* Test if packet has valid inverse quadlet */
129*0Sstevel@tonic-gate 		if (IEEE1394_SELFID_ISVALID(s) &&
130*0Sstevel@tonic-gate 		    (valid_pkt_id == IEEE1394_SELFID_PCKT_ID_VALID)) {
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 			hal->selfid_ptrs[i] = s;
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 			/* While this packet contains multiple quadlets */
135*0Sstevel@tonic-gate 			j += 2;
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 			while (IEEE1394_SELFID_ISMORE(s)) {
138*0Sstevel@tonic-gate 				valid_pkt_id =
139*0Sstevel@tonic-gate 				    ((data[j] & IEEE1394_SELFID_PCKT_ID_MASK) >>
140*0Sstevel@tonic-gate 				    IEEE1394_SELFID_PCKT_ID_SHIFT);
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 				s = (s1394_selfid_pkt_t *)(&data[j]);
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 				/* Test if packet has valid inverse quadlet */
145*0Sstevel@tonic-gate 				if (IEEE1394_SELFID_ISVALID(s) &&
146*0Sstevel@tonic-gate 				    (valid_pkt_id ==
147*0Sstevel@tonic-gate 					IEEE1394_SELFID_PCKT_ID_VALID)) {
148*0Sstevel@tonic-gate 					j += 2;
149*0Sstevel@tonic-gate 				} else {
150*0Sstevel@tonic-gate 					TNF_PROBE_1(
151*0Sstevel@tonic-gate 					    s1394_parse_selfid_buffer_error,
152*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_ERROR, "",
153*0Sstevel@tonic-gate 					    tnf_string, msg, "SelfID packet "
154*0Sstevel@tonic-gate 					    "error - invalid inverse");
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 					/* Initiate a bus reset */
157*0Sstevel@tonic-gate 					s1394_initiate_hal_reset(hal, CRITICAL);
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 					/* Set error status */
160*0Sstevel@tonic-gate 					error = B_TRUE;
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 					/* Release HAL lock and return */
163*0Sstevel@tonic-gate 					goto parse_buffer_done;
164*0Sstevel@tonic-gate 				}
165*0Sstevel@tonic-gate 			}
166*0Sstevel@tonic-gate 			i++;
167*0Sstevel@tonic-gate 		} else {
168*0Sstevel@tonic-gate 			TNF_PROBE_1(s1394_parse_selfid_buffer_error,
169*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
170*0Sstevel@tonic-gate 			    "SelfID packet error - invalid inverse");
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 			/* Initiate a bus reset */
173*0Sstevel@tonic-gate 			s1394_initiate_hal_reset(hal, CRITICAL);
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 			/* Set error status */
176*0Sstevel@tonic-gate 			error = B_TRUE;
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 			/* Release HAL lock and return */
179*0Sstevel@tonic-gate 			goto parse_buffer_done;
180*0Sstevel@tonic-gate 		}
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	hal->number_of_nodes = i;
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate parse_buffer_done:
186*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_parse_selfid_buffer_exit,
187*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
188*0Sstevel@tonic-gate 	if (error == B_TRUE)
189*0Sstevel@tonic-gate 		return (DDI_FAILURE);
190*0Sstevel@tonic-gate 	else
191*0Sstevel@tonic-gate 		return (DDI_SUCCESS);
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate /*
195*0Sstevel@tonic-gate  * s1394_sort_selfids()
196*0Sstevel@tonic-gate  *    takes the selfid_ptrs[] in the HAL struct and sorts them by node number,
197*0Sstevel@tonic-gate  *    using a heapsort.
198*0Sstevel@tonic-gate  */
199*0Sstevel@tonic-gate void
s1394_sort_selfids(s1394_hal_t * hal)200*0Sstevel@tonic-gate s1394_sort_selfids(s1394_hal_t *hal)
201*0Sstevel@tonic-gate {
202*0Sstevel@tonic-gate 	s1394_selfid_pkt_t *current;
203*0Sstevel@tonic-gate 	uint_t		   number_of_nodes;
204*0Sstevel@tonic-gate 	int		   i;
205*0Sstevel@tonic-gate 	int		   j;
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_sort_selfids_enter, S1394_TNF_SL_BR_STACK, "");
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	/* We start at one because the root has no parent to check */
214*0Sstevel@tonic-gate 	for (i = 1; i < number_of_nodes; i++) {
215*0Sstevel@tonic-gate 		current = hal->selfid_ptrs[i];
216*0Sstevel@tonic-gate 		j = i;
217*0Sstevel@tonic-gate 		while ((j > 0) && (IEEE1394_SELFID_PHYID(current) >
218*0Sstevel@tonic-gate 		    IEEE1394_SELFID_PHYID(hal->selfid_ptrs[j / 2]))) {
219*0Sstevel@tonic-gate 			hal->selfid_ptrs[j] = hal->selfid_ptrs[j / 2];
220*0Sstevel@tonic-gate 			hal->selfid_ptrs[j / 2] = current;
221*0Sstevel@tonic-gate 			j = j / 2;
222*0Sstevel@tonic-gate 		}
223*0Sstevel@tonic-gate 	}
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 	for (i = number_of_nodes - 1; i > 0; i--) {
226*0Sstevel@tonic-gate 		current = hal->selfid_ptrs[i];
227*0Sstevel@tonic-gate 		hal->selfid_ptrs[i] = hal->selfid_ptrs[0];
228*0Sstevel@tonic-gate 		hal->selfid_ptrs[0] = current;
229*0Sstevel@tonic-gate 		j = 0;
230*0Sstevel@tonic-gate 		while (2 * j + 1 < i) {
231*0Sstevel@tonic-gate 			if (2 * j + 2 >= i) {
232*0Sstevel@tonic-gate 				if (IEEE1394_SELFID_PHYID(current) <
233*0Sstevel@tonic-gate 				    IEEE1394_SELFID_PHYID(
234*0Sstevel@tonic-gate 					hal->selfid_ptrs[2 * j + 1])) {
235*0Sstevel@tonic-gate 					hal->selfid_ptrs[j] =
236*0Sstevel@tonic-gate 					    hal->selfid_ptrs[2 * j + 1];
237*0Sstevel@tonic-gate 					hal->selfid_ptrs[2 * j + 1] = current;
238*0Sstevel@tonic-gate 					j = 2 * j + 1;
239*0Sstevel@tonic-gate 				}
240*0Sstevel@tonic-gate 				break;
241*0Sstevel@tonic-gate 			}
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 			if (IEEE1394_SELFID_PHYID(hal->selfid_ptrs[2 * j + 1]) >
244*0Sstevel@tonic-gate 			    IEEE1394_SELFID_PHYID(
245*0Sstevel@tonic-gate 				hal->selfid_ptrs[2 * j + 2])) {
246*0Sstevel@tonic-gate 				if (IEEE1394_SELFID_PHYID(current) <
247*0Sstevel@tonic-gate 				    IEEE1394_SELFID_PHYID(
248*0Sstevel@tonic-gate 					hal->selfid_ptrs[2 * j + 1])) {
249*0Sstevel@tonic-gate 					hal->selfid_ptrs[j] =
250*0Sstevel@tonic-gate 					    hal->selfid_ptrs[2 * j + 1];
251*0Sstevel@tonic-gate 					hal->selfid_ptrs[2 * j + 1] = current;
252*0Sstevel@tonic-gate 					j = 2 * j + 1;
253*0Sstevel@tonic-gate 				} else {
254*0Sstevel@tonic-gate 					break;
255*0Sstevel@tonic-gate 				}
256*0Sstevel@tonic-gate 			} else {
257*0Sstevel@tonic-gate 				if (IEEE1394_SELFID_PHYID(current) <
258*0Sstevel@tonic-gate 				    IEEE1394_SELFID_PHYID(
259*0Sstevel@tonic-gate 					hal->selfid_ptrs[2 * j + 2])) {
260*0Sstevel@tonic-gate 					hal->selfid_ptrs[j] =
261*0Sstevel@tonic-gate 					    hal->selfid_ptrs[2 * j + 2];
262*0Sstevel@tonic-gate 					hal->selfid_ptrs[2 * j + 2] = current;
263*0Sstevel@tonic-gate 					j = 2 * j + 2;
264*0Sstevel@tonic-gate 				} else {
265*0Sstevel@tonic-gate 					break;
266*0Sstevel@tonic-gate 				}
267*0Sstevel@tonic-gate 			}
268*0Sstevel@tonic-gate 		}
269*0Sstevel@tonic-gate 	}
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_sort_selfids_exit, S1394_TNF_SL_BR_STACK, "");
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate /*
275*0Sstevel@tonic-gate  * selfid_speed()
276*0Sstevel@tonic-gate  *    examines the "sp" bits for a given packet (see IEEE 1394-1995 4.3.4.1)
277*0Sstevel@tonic-gate  *    and returns the node's speed capabilities.
278*0Sstevel@tonic-gate  */
279*0Sstevel@tonic-gate static uint8_t
selfid_speed(s1394_selfid_pkt_t * s)280*0Sstevel@tonic-gate selfid_speed(s1394_selfid_pkt_t *s)
281*0Sstevel@tonic-gate {
282*0Sstevel@tonic-gate 	uint32_t sp;
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	sp = ((s->spkt_data & IEEE1394_SELFID_SP_MASK) >>
285*0Sstevel@tonic-gate 	    IEEE1394_SELFID_SP_SHIFT);
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	switch (sp) {
288*0Sstevel@tonic-gate 	case IEEE1394_S100:
289*0Sstevel@tonic-gate 	case IEEE1394_S200:
290*0Sstevel@tonic-gate 	case IEEE1394_S400:
291*0Sstevel@tonic-gate 		return (sp);
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 	/*
294*0Sstevel@tonic-gate 	 * To verify higher speeds we should look at PHY register #3
295*0Sstevel@tonic-gate 	 * on this node.  This will need to be done to support P1394b
296*0Sstevel@tonic-gate 	 */
297*0Sstevel@tonic-gate 	default:
298*0Sstevel@tonic-gate 		return (IEEE1394_S400);
299*0Sstevel@tonic-gate 	}
300*0Sstevel@tonic-gate }
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate /*
303*0Sstevel@tonic-gate  * selfid_num_ports()
304*0Sstevel@tonic-gate  *    determines whether a packet is multi-part or single, and from this it
305*0Sstevel@tonic-gate  *    calculates the number of ports which have been specified.
306*0Sstevel@tonic-gate  *    (See IEEE 1394-1995 4.3.4.1)
307*0Sstevel@tonic-gate  */
308*0Sstevel@tonic-gate static int
selfid_num_ports(s1394_selfid_pkt_t * s)309*0Sstevel@tonic-gate selfid_num_ports(s1394_selfid_pkt_t *s)
310*0Sstevel@tonic-gate {
311*0Sstevel@tonic-gate 	int	p = 3;
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate 	while (IEEE1394_SELFID_ISMORE(s)) {
314*0Sstevel@tonic-gate 		p += 8;
315*0Sstevel@tonic-gate 		s++;
316*0Sstevel@tonic-gate 	}
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 	/* Threshold the number of ports at the P1394A defined maximum */
319*0Sstevel@tonic-gate 	/* (see P1394A Draft 3.0 - Section 8.5.1) */
320*0Sstevel@tonic-gate 	if (p > IEEE1394_MAX_NUM_PORTS)
321*0Sstevel@tonic-gate 		p = IEEE1394_MAX_NUM_PORTS;
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 	return (p);
324*0Sstevel@tonic-gate }
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate /*
327*0Sstevel@tonic-gate  * selfid_port_type()
328*0Sstevel@tonic-gate  *    determines what type of node the specified port connects to.
329*0Sstevel@tonic-gate  *    (See IEEE 1394-1995 4.3.4.1)
330*0Sstevel@tonic-gate  */
331*0Sstevel@tonic-gate static int
selfid_port_type(s1394_selfid_pkt_t * s,int port)332*0Sstevel@tonic-gate selfid_port_type(s1394_selfid_pkt_t *s, int port)
333*0Sstevel@tonic-gate {
334*0Sstevel@tonic-gate 	int	block;
335*0Sstevel@tonic-gate 	int	offset = IEEE1394_SELFID_PORT_OFFSET_FIRST;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	if (port > selfid_num_ports(s)) {
338*0Sstevel@tonic-gate 		TNF_PROBE_1(selfid_port_type_error,
339*0Sstevel@tonic-gate 		    "1394 s1394 error",
340*0Sstevel@tonic-gate 		    "Invalid port number requested for node",
341*0Sstevel@tonic-gate 		    tnf_uint, node_num, IEEE1394_SELFID_PHYID(s));
342*0Sstevel@tonic-gate 	}
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	if (port > 2) {
345*0Sstevel@tonic-gate 		/* Calculate which quadlet and bits for this port */
346*0Sstevel@tonic-gate 		port -= 3;
347*0Sstevel@tonic-gate 		block = (port >> 3) + 1;
348*0Sstevel@tonic-gate 		port = port % 8;
349*0Sstevel@tonic-gate 		/* Move to the correct quadlet */
350*0Sstevel@tonic-gate 		s += block;
351*0Sstevel@tonic-gate 		offset = IEEE1394_SELFID_PORT_OFFSET_OTHERS;
352*0Sstevel@tonic-gate 	}
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate 	/* Shift by appropriate number of bits and mask */
355*0Sstevel@tonic-gate 	return ((s->spkt_data >> (offset - 2 * port)) & 0x00000003);
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate /*
359*0Sstevel@tonic-gate  * s1394_init_topology_tree()
360*0Sstevel@tonic-gate  *    frees any config rom's allocated in the topology tree before zapping it.
361*0Sstevel@tonic-gate  *    If it gets a bus reset before the tree is marked processed, there will
362*0Sstevel@tonic-gate  *    be memory allocated for cfgrom's being read. If there is no tree copy,
363*0Sstevel@tonic-gate  *    topology would still be topology tree from the previous generation and
364*0Sstevel@tonic-gate  *    if we bzero'd the tree, we will have a memory leak. To avoid this leak,
365*0Sstevel@tonic-gate  *    walk through the tree and free any config roms in nodes that are NOT
366*0Sstevel@tonic-gate  *    matched. (For matched nodes, we ensure that nodes in old and topology
367*0Sstevel@tonic-gate  *    tree point to the same area of memory.)
368*0Sstevel@tonic-gate  */
369*0Sstevel@tonic-gate void
s1394_init_topology_tree(s1394_hal_t * hal,boolean_t copied,ushort_t number_of_nodes)370*0Sstevel@tonic-gate s1394_init_topology_tree(s1394_hal_t *hal, boolean_t copied,
371*0Sstevel@tonic-gate     ushort_t number_of_nodes)
372*0Sstevel@tonic-gate {
373*0Sstevel@tonic-gate 	s1394_node_t	*node;
374*0Sstevel@tonic-gate 	uint32_t	*config_rom;
375*0Sstevel@tonic-gate 	uint_t		tree_size;
376*0Sstevel@tonic-gate 	int		i;
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_init_topology_tree_enter,
379*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	/*
384*0Sstevel@tonic-gate 	 * if copied is false, we want to free any cfgrom memory that is
385*0Sstevel@tonic-gate 	 * not referenced to in both topology and old trees. However, we
386*0Sstevel@tonic-gate 	 * don't use hal->number_of_nodes as the number of nodes to look at.
387*0Sstevel@tonic-gate 	 * The reason being we could be seeing the bus reset before the
388*0Sstevel@tonic-gate 	 * state is appropriate for a tree copy (which need
389*0Sstevel@tonic-gate 	 * toplogy_tree_processed to be true) and some nodes might have
390*0Sstevel@tonic-gate 	 * departed in this generation and hal->number_of_nodes reflects
391*0Sstevel@tonic-gate 	 * the number of nodes in this generation. Use number_of_nodes that
392*0Sstevel@tonic-gate 	 * gets passed into this routine as the actual number of nodes to
393*0Sstevel@tonic-gate 	 * look at.
394*0Sstevel@tonic-gate 	 */
395*0Sstevel@tonic-gate 	if (copied == B_FALSE) {
396*0Sstevel@tonic-gate 		/* Free any cfgrom alloced and zap the node */
397*0Sstevel@tonic-gate 		for (i = 0; i < number_of_nodes; i++) {
398*0Sstevel@tonic-gate 			node = &hal->topology_tree[i];
399*0Sstevel@tonic-gate 			config_rom = node->cfgrom;
400*0Sstevel@tonic-gate 			if (config_rom != NULL) {
401*0Sstevel@tonic-gate 				if (CFGROM_NEW_ALLOC(node) == B_TRUE) {
402*0Sstevel@tonic-gate 					TNF_PROBE_2_DEBUG(
403*0Sstevel@tonic-gate 					    s1394_init_top_tree_free_cfgrom,
404*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK,
405*0Sstevel@tonic-gate 					    "cfgrom free", tnf_int, node_num, i,
406*0Sstevel@tonic-gate 					    tnf_opaque, cfgrom, config_rom);
407*0Sstevel@tonic-gate 					kmem_free((void *)config_rom,
408*0Sstevel@tonic-gate 					    IEEE1394_CONFIG_ROM_SZ);
409*0Sstevel@tonic-gate 				} else {
410*0Sstevel@tonic-gate 					TNF_PROBE_2_DEBUG(s1394_init_top_tree,
411*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "",
412*0Sstevel@tonic-gate 					    tnf_int, node_num, i,
413*0Sstevel@tonic-gate 					    tnf_opaque, cfgrom, config_rom);
414*0Sstevel@tonic-gate 				}
415*0Sstevel@tonic-gate 			}
416*0Sstevel@tonic-gate 		}
417*0Sstevel@tonic-gate 	}
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 	tree_size = hal->number_of_nodes * sizeof (s1394_node_t);
420*0Sstevel@tonic-gate 	bzero((void *)hal->topology_tree, tree_size);
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_init_topology_tree_exit,
423*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate /*
427*0Sstevel@tonic-gate  * s1394_topology_tree_build()
428*0Sstevel@tonic-gate  *    takes the selfid_ptrs[] and builds the topology_tree[] by examining
429*0Sstevel@tonic-gate  *    the node numbers (the order in which the nodes responded to SelfID).
430*0Sstevel@tonic-gate  *    It sets the port pointers, leaf label, parent port, and
431*0Sstevel@tonic-gate  *    s1394_selfid_packet_t pointer in each node.
432*0Sstevel@tonic-gate  */
433*0Sstevel@tonic-gate int
s1394_topology_tree_build(s1394_hal_t * hal)434*0Sstevel@tonic-gate s1394_topology_tree_build(s1394_hal_t *hal)
435*0Sstevel@tonic-gate {
436*0Sstevel@tonic-gate 	s1394_node_t	*tmp;
437*0Sstevel@tonic-gate 	uint32_t	number_of_nodes;
438*0Sstevel@tonic-gate 	boolean_t	push_to_orphan_stack = B_FALSE;
439*0Sstevel@tonic-gate 	boolean_t	found_parent = B_FALSE;
440*0Sstevel@tonic-gate 	boolean_t	found_connection = B_FALSE;
441*0Sstevel@tonic-gate 	int		i;
442*0Sstevel@tonic-gate 	int		j;
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 	/*
445*0Sstevel@tonic-gate 	 * The method for building the tree is described in IEEE 1394-1995
446*0Sstevel@tonic-gate 	 * (Annex E.3.4).  We use an "Orphan" stack to keep track of Child
447*0Sstevel@tonic-gate 	 * nodes which have yet to find their Parent node.
448*0Sstevel@tonic-gate 	 */
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_build_enter,
451*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 	/* Flush the Stack */
458*0Sstevel@tonic-gate 	hal->hal_stack_depth = -1;
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate 	/* For each node on the bus initialize its topology_tree entry */
461*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
462*0Sstevel@tonic-gate 		/* Make sure that node numbers are correct */
463*0Sstevel@tonic-gate 		if (i != IEEE1394_SELFID_PHYID(hal->selfid_ptrs[i])) {
464*0Sstevel@tonic-gate 			TNF_PROBE_1(s1394_topology_tree_build_error,
465*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
466*0Sstevel@tonic-gate 			    "SelfIDs - Invalid node numbering");
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 			/* Initiate a bus reset */
469*0Sstevel@tonic-gate 			s1394_initiate_hal_reset(hal, CRITICAL);
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_topology_tree_build_exit,
472*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
473*0Sstevel@tonic-gate 			return (DDI_FAILURE);
474*0Sstevel@tonic-gate 		}
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate 		hal->topology_tree[i].selfid_packet = hal->selfid_ptrs[i];
477*0Sstevel@tonic-gate 		hal->topology_tree[i].parent_port = (char)NO_PARENT;
478*0Sstevel@tonic-gate 		hal->topology_tree[i].is_a_leaf = 1;
479*0Sstevel@tonic-gate 		hal->topology_tree[i].node_num = (uchar_t)i;
480*0Sstevel@tonic-gate 	}
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
483*0Sstevel@tonic-gate 		/* Current node has no parent yet */
484*0Sstevel@tonic-gate 		found_parent = B_FALSE;
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 		/* Current node has no connections yet */
487*0Sstevel@tonic-gate 		found_connection = B_FALSE;
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 		/* Initialize all ports on this node */
490*0Sstevel@tonic-gate 		for (j = 0; j < IEEE1394_MAX_NUM_PORTS; j++)
491*0Sstevel@tonic-gate 			hal->topology_tree[i].phy_port[j] = NULL;
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 		/* For each port on the node - highest to lowest */
494*0Sstevel@tonic-gate 		for (j = selfid_num_ports(hal->selfid_ptrs[i]) - 1;
495*0Sstevel@tonic-gate 		    j >= 0; j--) {
496*0Sstevel@tonic-gate 			if (selfid_port_type(hal->selfid_ptrs[i], j) ==
497*0Sstevel@tonic-gate 			    IEEE1394_SELFID_PORT_TO_PARENT) {
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate 				found_connection = B_TRUE;
500*0Sstevel@tonic-gate 				if (found_parent == B_FALSE) {
501*0Sstevel@tonic-gate 					push_to_orphan_stack = B_TRUE;
502*0Sstevel@tonic-gate 					hal->topology_tree[i].parent_port =
503*0Sstevel@tonic-gate 					    (char)j;
504*0Sstevel@tonic-gate 					found_parent = B_TRUE;
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 				} else {
507*0Sstevel@tonic-gate 					TNF_PROBE_1(
508*0Sstevel@tonic-gate 					    s1394_topology_tree_build_error,
509*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_ERROR, "",
510*0Sstevel@tonic-gate 					    tnf_string, msg, "SelfID packet - "
511*0Sstevel@tonic-gate 					    "Has multiple parents");
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 					/* Initiate a bus reset */
514*0Sstevel@tonic-gate 					s1394_initiate_hal_reset(hal, CRITICAL);
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
517*0Sstevel@tonic-gate 					    s1394_topology_tree_build_exit,
518*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "");
519*0Sstevel@tonic-gate 					return (DDI_FAILURE);
520*0Sstevel@tonic-gate 				}
521*0Sstevel@tonic-gate 			} else if (selfid_port_type(hal->selfid_ptrs[i], j) ==
522*0Sstevel@tonic-gate 			    IEEE1394_SELFID_PORT_TO_CHILD) {
523*0Sstevel@tonic-gate 
524*0Sstevel@tonic-gate 				found_connection = B_TRUE;
525*0Sstevel@tonic-gate 				tmp = (s1394_node_t *)s1394_hal_stack_pop(hal);
526*0Sstevel@tonic-gate 				if (tmp == NULL) {
527*0Sstevel@tonic-gate 					TNF_PROBE_1(
528*0Sstevel@tonic-gate 					    s1394_topology_tree_build_error,
529*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_ERROR, "",
530*0Sstevel@tonic-gate 					    tnf_string, msg, "Topology Tree "
531*0Sstevel@tonic-gate 					    "invalid - Tree build failed");
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 					/* Initiate a bus reset */
534*0Sstevel@tonic-gate 					s1394_initiate_hal_reset(hal, CRITICAL);
535*0Sstevel@tonic-gate 
536*0Sstevel@tonic-gate 					TNF_PROBE_0_DEBUG(
537*0Sstevel@tonic-gate 					    s1394_topology_tree_build_exit,
538*0Sstevel@tonic-gate 					    S1394_TNF_SL_BR_STACK, "");
539*0Sstevel@tonic-gate 					return (DDI_FAILURE);
540*0Sstevel@tonic-gate 				}
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate 				hal->topology_tree[i].phy_port[j] = tmp;
543*0Sstevel@tonic-gate 				hal->topology_tree[i].is_a_leaf = 0;
544*0Sstevel@tonic-gate 				tmp->phy_port[tmp->parent_port] =
545*0Sstevel@tonic-gate 				    &hal->topology_tree[i];
546*0Sstevel@tonic-gate 			}
547*0Sstevel@tonic-gate 		}
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 		/* If current node has no parents or children - Invalid */
550*0Sstevel@tonic-gate 		if ((found_connection == B_FALSE) && (number_of_nodes > 1)) {
551*0Sstevel@tonic-gate 			TNF_PROBE_1(s1394_topology_tree_build_error,
552*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
553*0Sstevel@tonic-gate 			    "SelfID packet - Has no connections");
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 			/* Initiate a bus reset */
556*0Sstevel@tonic-gate 			s1394_initiate_hal_reset(hal, CRITICAL);
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_topology_tree_build_exit,
559*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
560*0Sstevel@tonic-gate 			return (DDI_FAILURE);
561*0Sstevel@tonic-gate 		}
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 		/* Push it on the "Orphan" stack if it has no parent yet */
564*0Sstevel@tonic-gate 		if (push_to_orphan_stack == B_TRUE) {
565*0Sstevel@tonic-gate 			push_to_orphan_stack = B_FALSE;
566*0Sstevel@tonic-gate 			s1394_hal_stack_push(hal, &hal->topology_tree[i]);
567*0Sstevel@tonic-gate 		}
568*0Sstevel@tonic-gate 	}
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 	/* If the stack is not empty, then something has gone seriously wrong */
571*0Sstevel@tonic-gate 	if (hal->hal_stack_depth != -1) {
572*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_topology_tree_build_error,
573*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
574*0Sstevel@tonic-gate 		    "Topology Tree invalid - Tree build failed");
575*0Sstevel@tonic-gate 
576*0Sstevel@tonic-gate 		/* Initiate a bus reset */
577*0Sstevel@tonic-gate 		s1394_initiate_hal_reset(hal, CRITICAL);
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_topology_tree_build_exit,
580*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
581*0Sstevel@tonic-gate 		return (DDI_FAILURE);
582*0Sstevel@tonic-gate 	}
583*0Sstevel@tonic-gate 
584*0Sstevel@tonic-gate 	/* New topology tree is now valid */
585*0Sstevel@tonic-gate 	hal->topology_tree_valid = B_TRUE;
586*0Sstevel@tonic-gate 
587*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_build_exit,
588*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
589*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
590*0Sstevel@tonic-gate }
591*0Sstevel@tonic-gate 
592*0Sstevel@tonic-gate /*
593*0Sstevel@tonic-gate  * s1394_hal_stack_push()
594*0Sstevel@tonic-gate  *    checks that the stack is not full, and puts the pointer on top of the
595*0Sstevel@tonic-gate  *    HAL's stack if it isn't.  This routine is used only by the
596*0Sstevel@tonic-gate  *    h1394_self_ids() interrupt.
597*0Sstevel@tonic-gate  */
598*0Sstevel@tonic-gate static void
s1394_hal_stack_push(s1394_hal_t * hal,void * obj)599*0Sstevel@tonic-gate s1394_hal_stack_push(s1394_hal_t *hal, void *obj)
600*0Sstevel@tonic-gate {
601*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_stack_push_enter,
602*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	if (hal->hal_stack_depth < IEEE1394_MAX_NODES - 1) {
605*0Sstevel@tonic-gate 		hal->hal_stack_depth++;
606*0Sstevel@tonic-gate 		hal->hal_stack[hal->hal_stack_depth] = obj;
607*0Sstevel@tonic-gate 	} else {
608*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_hal_stack_push_error,
609*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
610*0Sstevel@tonic-gate 		    "HAL stack - Overflow");
611*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_stack_push_exit,
612*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
613*0Sstevel@tonic-gate 		return;
614*0Sstevel@tonic-gate 	}
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_stack_push_exit,
617*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
618*0Sstevel@tonic-gate }
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate /*
621*0Sstevel@tonic-gate  * s1394_hal_stack_pop()
622*0Sstevel@tonic-gate  *    checks that the stack is not empty, and pops and returns the pointer
623*0Sstevel@tonic-gate  *    from the top of the HAL's stack if it isn't.  This routine is used
624*0Sstevel@tonic-gate  *    only by the h1394_self_ids() interrupt.
625*0Sstevel@tonic-gate  */
626*0Sstevel@tonic-gate static void *
s1394_hal_stack_pop(s1394_hal_t * hal)627*0Sstevel@tonic-gate s1394_hal_stack_pop(s1394_hal_t *hal)
628*0Sstevel@tonic-gate {
629*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_stack_pop_enter,
630*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 	if (hal->hal_stack_depth > -1) {
633*0Sstevel@tonic-gate 		hal->hal_stack_depth--;
634*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_stack_pop_exit,
635*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
636*0Sstevel@tonic-gate 		return (hal->hal_stack[hal->hal_stack_depth + 1]);
637*0Sstevel@tonic-gate 
638*0Sstevel@tonic-gate 	} else {
639*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_hal_stack_pop_error,
640*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
641*0Sstevel@tonic-gate 		    "HAL stack - Underflow");
642*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_stack_pop_exit,
643*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
644*0Sstevel@tonic-gate 		return (NULL);
645*0Sstevel@tonic-gate 	}
646*0Sstevel@tonic-gate }
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate /*
649*0Sstevel@tonic-gate  * s1394_hal_queue_insert()
650*0Sstevel@tonic-gate  *    checks that the queue is not full, and puts the object in the front
651*0Sstevel@tonic-gate  *    of the HAL's queue if it isn't.  This routine is used only by the
652*0Sstevel@tonic-gate  *    h1394_self_ids() interrupt.
653*0Sstevel@tonic-gate  */
654*0Sstevel@tonic-gate static void
s1394_hal_queue_insert(s1394_hal_t * hal,void * obj)655*0Sstevel@tonic-gate s1394_hal_queue_insert(s1394_hal_t *hal, void *obj)
656*0Sstevel@tonic-gate {
657*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_queue_insert_enter,
658*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
659*0Sstevel@tonic-gate 
660*0Sstevel@tonic-gate 	if (((hal->hal_queue_front + 1) % IEEE1394_MAX_NODES) ==
661*0Sstevel@tonic-gate 	    hal->hal_queue_back) {
662*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_hal_queue_insert_error,
663*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
664*0Sstevel@tonic-gate 		    "HAL Queue - Overflow");
665*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_queue_insert_exit,
666*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
667*0Sstevel@tonic-gate 		return;
668*0Sstevel@tonic-gate 
669*0Sstevel@tonic-gate 	} else {
670*0Sstevel@tonic-gate 		hal->hal_queue[hal->hal_queue_front] = obj;
671*0Sstevel@tonic-gate 		hal->hal_queue_front = (hal->hal_queue_front + 1) %
672*0Sstevel@tonic-gate 		    IEEE1394_MAX_NODES;
673*0Sstevel@tonic-gate 	}
674*0Sstevel@tonic-gate 
675*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_queue_insert_exit,
676*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
677*0Sstevel@tonic-gate }
678*0Sstevel@tonic-gate 
679*0Sstevel@tonic-gate 
680*0Sstevel@tonic-gate /*
681*0Sstevel@tonic-gate  * s1394_hal_queue_remove()
682*0Sstevel@tonic-gate  *    checks that the queue is not empty, and pulls the object off the back
683*0Sstevel@tonic-gate  *    of the HAL's queue (and returns it) if it isn't.  This routine is used
684*0Sstevel@tonic-gate  *    only by the h1394_self_ids() interrupt.
685*0Sstevel@tonic-gate  */
686*0Sstevel@tonic-gate static void *
s1394_hal_queue_remove(s1394_hal_t * hal)687*0Sstevel@tonic-gate s1394_hal_queue_remove(s1394_hal_t *hal)
688*0Sstevel@tonic-gate {
689*0Sstevel@tonic-gate 	void	*tmp;
690*0Sstevel@tonic-gate 
691*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_queue_remove_enter,
692*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
693*0Sstevel@tonic-gate 
694*0Sstevel@tonic-gate 	if (hal->hal_queue_back == hal->hal_queue_front) {
695*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_hal_queue_remove_error,
696*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
697*0Sstevel@tonic-gate 		    "HAL Queue - Underflow");
698*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_queue_remove_exit,
699*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
700*0Sstevel@tonic-gate 		return (NULL);
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate 	} else {
703*0Sstevel@tonic-gate 		tmp = hal->hal_queue[hal->hal_queue_back];
704*0Sstevel@tonic-gate 		hal->hal_queue_back = (hal->hal_queue_back + 1) %
705*0Sstevel@tonic-gate 		    IEEE1394_MAX_NODES;
706*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_queue_remove_exit,
707*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
708*0Sstevel@tonic-gate 		return (tmp);
709*0Sstevel@tonic-gate 	}
710*0Sstevel@tonic-gate }
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 
713*0Sstevel@tonic-gate /*
714*0Sstevel@tonic-gate  * s1394_node_number_list_add()
715*0Sstevel@tonic-gate  *    checks that the node_number_list is not full and puts the node number
716*0Sstevel@tonic-gate  *    in the list.  The function is used primarily by s1394_speed_map_fill()
717*0Sstevel@tonic-gate  *    to keep track of which connections need to be set in the speed_map[].
718*0Sstevel@tonic-gate  *    This routine is used only by the h1394_self_ids() interrupt.
719*0Sstevel@tonic-gate  */
720*0Sstevel@tonic-gate static void
s1394_node_number_list_add(s1394_hal_t * hal,int node_num)721*0Sstevel@tonic-gate s1394_node_number_list_add(s1394_hal_t *hal, int node_num)
722*0Sstevel@tonic-gate {
723*0Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_node_number_list_add_enter,
724*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "", tnf_int, node_num, node_num);
725*0Sstevel@tonic-gate 
726*0Sstevel@tonic-gate 	if (hal->hal_node_number_list_size >= IEEE1394_MAX_NODES - 1) {
727*0Sstevel@tonic-gate 		TNF_PROBE_1(s1394_node_number_list_add_error,
728*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
729*0Sstevel@tonic-gate 		    "Node Number List - Overflow");
730*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_node_number_list_add_exit,
731*0Sstevel@tonic-gate 		    S1394_TNF_SL_BR_STACK, "");
732*0Sstevel@tonic-gate 		return;
733*0Sstevel@tonic-gate 	}
734*0Sstevel@tonic-gate 
735*0Sstevel@tonic-gate 	hal->hal_node_number_list[hal->hal_node_number_list_size] = node_num;
736*0Sstevel@tonic-gate 	hal->hal_node_number_list_size++;
737*0Sstevel@tonic-gate 
738*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_node_number_list_add_exit,
739*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
740*0Sstevel@tonic-gate }
741*0Sstevel@tonic-gate 
742*0Sstevel@tonic-gate /*
743*0Sstevel@tonic-gate  * s1394_topology_tree_mark_all_unvisited()
744*0Sstevel@tonic-gate  *    is used to initialize the topology_tree[] prior to tree traversals.
745*0Sstevel@tonic-gate  *    It resets the "visited" flag for each node in the tree.
746*0Sstevel@tonic-gate  */
747*0Sstevel@tonic-gate void
s1394_topology_tree_mark_all_unvisited(s1394_hal_t * hal)748*0Sstevel@tonic-gate s1394_topology_tree_mark_all_unvisited(s1394_hal_t *hal)
749*0Sstevel@tonic-gate {
750*0Sstevel@tonic-gate 	uint_t	number_of_nodes;
751*0Sstevel@tonic-gate 	int	i;
752*0Sstevel@tonic-gate 
753*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_mark_all_unvisited_enter,
754*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
757*0Sstevel@tonic-gate 
758*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
759*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++)
760*0Sstevel@tonic-gate 		CLEAR_NODE_VISITED(&hal->topology_tree[i]);
761*0Sstevel@tonic-gate 
762*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_mark_all_unvisited_exit,
763*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
764*0Sstevel@tonic-gate }
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate /*
767*0Sstevel@tonic-gate  * s1394_old_tree_mark_all_unvisited()
768*0Sstevel@tonic-gate  *    is used to initialize the old_tree[] prior to tree traversals.  It
769*0Sstevel@tonic-gate  *    resets the "visited" flag for each node in the tree.
770*0Sstevel@tonic-gate  */
771*0Sstevel@tonic-gate void
s1394_old_tree_mark_all_unvisited(s1394_hal_t * hal)772*0Sstevel@tonic-gate s1394_old_tree_mark_all_unvisited(s1394_hal_t *hal)
773*0Sstevel@tonic-gate {
774*0Sstevel@tonic-gate 	uint_t	number_of_nodes;
775*0Sstevel@tonic-gate 	int	i;
776*0Sstevel@tonic-gate 
777*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_old_tree_mark_all_unvisited_enter,
778*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
781*0Sstevel@tonic-gate 
782*0Sstevel@tonic-gate 	number_of_nodes = hal->old_number_of_nodes;
783*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++)
784*0Sstevel@tonic-gate 		CLEAR_NODE_VISITED(&hal->old_tree[i]);
785*0Sstevel@tonic-gate 
786*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_old_tree_mark_all_unvisited_exit,
787*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
788*0Sstevel@tonic-gate }
789*0Sstevel@tonic-gate 
790*0Sstevel@tonic-gate /*
791*0Sstevel@tonic-gate  * s1394_old_tree_mark_all_unmatched()
792*0Sstevel@tonic-gate  *    is used to initialize the old_tree[] prior to tree traversals.  It
793*0Sstevel@tonic-gate  *    resets the "matched" flag for each node in the tree.
794*0Sstevel@tonic-gate  */
795*0Sstevel@tonic-gate void
s1394_old_tree_mark_all_unmatched(s1394_hal_t * hal)796*0Sstevel@tonic-gate s1394_old_tree_mark_all_unmatched(s1394_hal_t *hal)
797*0Sstevel@tonic-gate {
798*0Sstevel@tonic-gate 	uint_t	number_of_nodes;
799*0Sstevel@tonic-gate 	int	i;
800*0Sstevel@tonic-gate 
801*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_old_tree_mark_all_unmatched_enter,
802*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
805*0Sstevel@tonic-gate 
806*0Sstevel@tonic-gate 	number_of_nodes = hal->old_number_of_nodes;
807*0Sstevel@tonic-gate 
808*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++)
809*0Sstevel@tonic-gate 	    CLEAR_NODE_MATCHED(&hal->old_tree[i]);
810*0Sstevel@tonic-gate 
811*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_old_tree_mark_all_unmatched_exit,
812*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
813*0Sstevel@tonic-gate }
814*0Sstevel@tonic-gate 
815*0Sstevel@tonic-gate /*
816*0Sstevel@tonic-gate  * s1394_copy_old_tree()
817*0Sstevel@tonic-gate  *    switches the pointers for old_tree[] and topology_tree[].
818*0Sstevel@tonic-gate  */
819*0Sstevel@tonic-gate void
s1394_copy_old_tree(s1394_hal_t * hal)820*0Sstevel@tonic-gate s1394_copy_old_tree(s1394_hal_t *hal)
821*0Sstevel@tonic-gate {
822*0Sstevel@tonic-gate 	s1394_node_t	*temp;
823*0Sstevel@tonic-gate 
824*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_copy_old_tree_enter,
825*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
826*0Sstevel@tonic-gate 
827*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
828*0Sstevel@tonic-gate 
829*0Sstevel@tonic-gate 	temp = hal->old_tree;
830*0Sstevel@tonic-gate 	hal->old_tree = hal->topology_tree;
831*0Sstevel@tonic-gate 	hal->topology_tree = temp;
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 	hal->old_number_of_nodes = hal->number_of_nodes;
834*0Sstevel@tonic-gate 	hal->old_node_id = hal->node_id;
835*0Sstevel@tonic-gate 	hal->old_generation_count = hal->generation_count;
836*0Sstevel@tonic-gate 
837*0Sstevel@tonic-gate 	/* Old tree is now valid and filled also */
838*0Sstevel@tonic-gate 	hal->old_tree_valid = B_TRUE;
839*0Sstevel@tonic-gate 
840*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_copy_old_tree_exit,
841*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
842*0Sstevel@tonic-gate }
843*0Sstevel@tonic-gate 
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate /*
846*0Sstevel@tonic-gate  * s1394_match_tree_nodes()
847*0Sstevel@tonic-gate  *    uses the information contained in the SelfID packets of the nodes in
848*0Sstevel@tonic-gate  *    both the old_tree[] and the topology_tree[] to determine which new
849*0Sstevel@tonic-gate  *    nodes correspond to old nodes.  Starting with the local node, we
850*0Sstevel@tonic-gate  *    compare both old and new node's ports.  Assuming that only one bus
851*0Sstevel@tonic-gate  *    reset has occurred, any node that was connected to another in the old
852*0Sstevel@tonic-gate  *    bus and is still connected to another in the new bus must be connected
853*0Sstevel@tonic-gate  *    (physically) to the same node.  Using this information, we can rebuild
854*0Sstevel@tonic-gate  *    and match the old nodes to new ones.  Any nodes which aren't matched
855*0Sstevel@tonic-gate  *    are either departing or arriving nodes and must be handled appropriately.
856*0Sstevel@tonic-gate  */
857*0Sstevel@tonic-gate void
s1394_match_tree_nodes(s1394_hal_t * hal)858*0Sstevel@tonic-gate s1394_match_tree_nodes(s1394_hal_t *hal)
859*0Sstevel@tonic-gate {
860*0Sstevel@tonic-gate 	s1394_node_t	*tmp;
861*0Sstevel@tonic-gate 	uint_t		hal_node_num;
862*0Sstevel@tonic-gate 	uint_t		hal_node_num_old;
863*0Sstevel@tonic-gate 	int		i;
864*0Sstevel@tonic-gate 	int		port_type;
865*0Sstevel@tonic-gate 
866*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_match_tree_nodes_enter,
867*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
868*0Sstevel@tonic-gate 
869*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
870*0Sstevel@tonic-gate 
871*0Sstevel@tonic-gate 	/* To ensure that the queue is empty */
872*0Sstevel@tonic-gate 	hal->hal_queue_front = hal->hal_queue_back = 0;
873*0Sstevel@tonic-gate 
874*0Sstevel@tonic-gate 	/* Set up the first matched nodes (which are our own local nodes) */
875*0Sstevel@tonic-gate 	hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
876*0Sstevel@tonic-gate 	hal_node_num_old = IEEE1394_NODE_NUM(hal->old_node_id);
877*0Sstevel@tonic-gate 	hal->topology_tree[hal_node_num].old_node =
878*0Sstevel@tonic-gate 	    &hal->old_tree[hal_node_num_old];
879*0Sstevel@tonic-gate 	hal->old_tree[hal_node_num_old].cur_node =
880*0Sstevel@tonic-gate 	    &hal->topology_tree[hal_node_num];
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate 	/* Put the node on the queue */
883*0Sstevel@tonic-gate 	s1394_hal_queue_insert(hal, &hal->topology_tree[hal_node_num]);
884*0Sstevel@tonic-gate 
885*0Sstevel@tonic-gate 	/* While the queue is not empty, remove a node */
886*0Sstevel@tonic-gate 	while (hal->hal_queue_front != hal->hal_queue_back) {
887*0Sstevel@tonic-gate 		tmp = (s1394_node_t *)s1394_hal_queue_remove(hal);
888*0Sstevel@tonic-gate 
889*0Sstevel@tonic-gate 	    /* Mark both old and new nodes as "visited" */
890*0Sstevel@tonic-gate 	    SET_NODE_VISITED(tmp);
891*0Sstevel@tonic-gate 	    SET_NODE_VISITED(tmp->old_node);
892*0Sstevel@tonic-gate 	    tmp->old_node->cur_node = tmp;
893*0Sstevel@tonic-gate 
894*0Sstevel@tonic-gate 	    /* Mark old and new nodes as "matched" */
895*0Sstevel@tonic-gate 	    SET_NODE_MATCHED(tmp);
896*0Sstevel@tonic-gate 	    SET_NODE_MATCHED(tmp->old_node);
897*0Sstevel@tonic-gate 	    s1394_copy_cfgrom(tmp, tmp->old_node);
898*0Sstevel@tonic-gate 
899*0Sstevel@tonic-gate 	    /* s1394_copy_cfgrom() clears "matched" for some cases... */
900*0Sstevel@tonic-gate 	    if ((tmp->cfgrom != NULL && CONFIG_ROM_GEN(tmp->cfgrom) <= 1) ||
901*0Sstevel@tonic-gate 		NODE_MATCHED(tmp) == B_TRUE) {
902*0Sstevel@tonic-gate 		/* Move the target list over to the new node and update */
903*0Sstevel@tonic-gate 		/* the node info. */
904*0Sstevel@tonic-gate 			s1394_target_t *t;
905*0Sstevel@tonic-gate 
906*0Sstevel@tonic-gate 			rw_enter(&hal->target_list_rwlock, RW_WRITER);
907*0Sstevel@tonic-gate 			t = tmp->target_list = tmp->old_node->target_list;
908*0Sstevel@tonic-gate 			while (t != NULL) {
909*0Sstevel@tonic-gate 				t->on_node = tmp;
910*0Sstevel@tonic-gate 				t = t->target_sibling;
911*0Sstevel@tonic-gate 			}
912*0Sstevel@tonic-gate 			rw_exit(&hal->target_list_rwlock);
913*0Sstevel@tonic-gate 		}
914*0Sstevel@tonic-gate 
915*0Sstevel@tonic-gate 		for (i = 0; i < selfid_num_ports(tmp->selfid_packet); i++) {
916*0Sstevel@tonic-gate 			port_type = selfid_port_type(tmp->selfid_packet, i);
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 			/* Is the new port connected? */
919*0Sstevel@tonic-gate 			if ((port_type == IEEE1394_SELFID_PORT_TO_CHILD) ||
920*0Sstevel@tonic-gate 			    (port_type == IEEE1394_SELFID_PORT_TO_PARENT)) {
921*0Sstevel@tonic-gate 				port_type = selfid_port_type(
922*0Sstevel@tonic-gate 				    tmp->old_node->selfid_packet, i);
923*0Sstevel@tonic-gate 
924*0Sstevel@tonic-gate 				/* Is the old port connected? */
925*0Sstevel@tonic-gate 				if ((port_type ==
926*0Sstevel@tonic-gate 					IEEE1394_SELFID_PORT_TO_CHILD) ||
927*0Sstevel@tonic-gate 				    (port_type ==
928*0Sstevel@tonic-gate 					IEEE1394_SELFID_PORT_TO_PARENT)) {
929*0Sstevel@tonic-gate 					/* Found a match, check if */
930*0Sstevel@tonic-gate 					/* we've already visited it */
931*0Sstevel@tonic-gate 					if (!NODE_VISITED(tmp->phy_port[i])) {
932*0Sstevel@tonic-gate 						tmp->phy_port[i]->old_node =
933*0Sstevel@tonic-gate 						    tmp->old_node->phy_port[i];
934*0Sstevel@tonic-gate 						s1394_hal_queue_insert(hal,
935*0Sstevel@tonic-gate 						    tmp->phy_port[i]);
936*0Sstevel@tonic-gate 					}
937*0Sstevel@tonic-gate 				}
938*0Sstevel@tonic-gate 			}
939*0Sstevel@tonic-gate 		}
940*0Sstevel@tonic-gate 	}
941*0Sstevel@tonic-gate 
942*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_match_tree_nodes_exit,
943*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
944*0Sstevel@tonic-gate }
945*0Sstevel@tonic-gate 
946*0Sstevel@tonic-gate /*
947*0Sstevel@tonic-gate  * s1394_topology_tree_calculate_diameter()
948*0Sstevel@tonic-gate  *    does a depth-first tree traversal, tracking at each branch the first
949*0Sstevel@tonic-gate  *    and second deepest paths though that branch's children.  The diameter
950*0Sstevel@tonic-gate  *    is given by the maximum of these over all branch nodes
951*0Sstevel@tonic-gate  */
952*0Sstevel@tonic-gate int
s1394_topology_tree_calculate_diameter(s1394_hal_t * hal)953*0Sstevel@tonic-gate s1394_topology_tree_calculate_diameter(s1394_hal_t *hal)
954*0Sstevel@tonic-gate {
955*0Sstevel@tonic-gate 	s1394_node_t	*current;
956*0Sstevel@tonic-gate 	uint_t		number_of_nodes;
957*0Sstevel@tonic-gate 	int		i;
958*0Sstevel@tonic-gate 	int		start;
959*0Sstevel@tonic-gate 	int		end;
960*0Sstevel@tonic-gate 	boolean_t	done;
961*0Sstevel@tonic-gate 	boolean_t	found_a_child;
962*0Sstevel@tonic-gate 	int		distance = 0;
963*0Sstevel@tonic-gate 	int		diameter = 0;
964*0Sstevel@tonic-gate 	int		local_diameter = 0;
965*0Sstevel@tonic-gate 
966*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_calculate_diameter_enter,
967*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
968*0Sstevel@tonic-gate 
969*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
970*0Sstevel@tonic-gate 
971*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
972*0Sstevel@tonic-gate 
973*0Sstevel@tonic-gate 	/* Initialize topology tree */
974*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
975*0Sstevel@tonic-gate 		hal->topology_tree[i].max_1st = 0;
976*0Sstevel@tonic-gate 		hal->topology_tree[i].max_2nd = 0;
977*0Sstevel@tonic-gate 		hal->topology_tree[i].last_port_checked = 0;
978*0Sstevel@tonic-gate 	}
979*0Sstevel@tonic-gate 
980*0Sstevel@tonic-gate 	/* Start at the root node */
981*0Sstevel@tonic-gate 	current = s1394_topology_tree_get_root_node(hal);
982*0Sstevel@tonic-gate 
983*0Sstevel@tonic-gate 	/* Flush the stack before we start */
984*0Sstevel@tonic-gate 	hal->hal_stack_depth = -1;
985*0Sstevel@tonic-gate 
986*0Sstevel@tonic-gate 	do {
987*0Sstevel@tonic-gate 		done		= B_FALSE;
988*0Sstevel@tonic-gate 		found_a_child	= B_FALSE;
989*0Sstevel@tonic-gate 		start		= current->last_port_checked;
990*0Sstevel@tonic-gate 		end		= selfid_num_ports(current->selfid_packet);
991*0Sstevel@tonic-gate 
992*0Sstevel@tonic-gate 		/* Check every previously unchecked port for children */
993*0Sstevel@tonic-gate 		for (i = start; i < end; i++) {
994*0Sstevel@tonic-gate 			current->last_port_checked++;
995*0Sstevel@tonic-gate 			/* If there is a child push it on the stack */
996*0Sstevel@tonic-gate 			if (selfid_port_type(current->selfid_packet, i) ==
997*0Sstevel@tonic-gate 			    IEEE1394_SELFID_PORT_TO_CHILD) {
998*0Sstevel@tonic-gate 				found_a_child = B_TRUE;
999*0Sstevel@tonic-gate 				s1394_hal_stack_push(hal, current);
1000*0Sstevel@tonic-gate 				current = current->phy_port[i];
1001*0Sstevel@tonic-gate 				break;
1002*0Sstevel@tonic-gate 			}
1003*0Sstevel@tonic-gate 		}
1004*0Sstevel@tonic-gate 
1005*0Sstevel@tonic-gate 		/* If we reach here and the stack is empty, we're done */
1006*0Sstevel@tonic-gate 		if (hal->hal_stack_depth == -1) {
1007*0Sstevel@tonic-gate 			done = B_TRUE;
1008*0Sstevel@tonic-gate 			continue;
1009*0Sstevel@tonic-gate 		}
1010*0Sstevel@tonic-gate 
1011*0Sstevel@tonic-gate 		/* If no children were found, we're at a leaf */
1012*0Sstevel@tonic-gate 		if (found_a_child == B_FALSE) {
1013*0Sstevel@tonic-gate 			distance = current->max_1st + 1;
1014*0Sstevel@tonic-gate 			/* Pop the child and set the appropriate fields */
1015*0Sstevel@tonic-gate 			current = s1394_hal_stack_pop(hal);
1016*0Sstevel@tonic-gate 			if (distance > current->max_1st) {
1017*0Sstevel@tonic-gate 				current->max_2nd = current->max_1st;
1018*0Sstevel@tonic-gate 				current->max_1st = (uchar_t)distance;
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate 			} else if (distance > current->max_2nd) {
1021*0Sstevel@tonic-gate 				current->max_2nd = (uchar_t)distance;
1022*0Sstevel@tonic-gate 			}
1023*0Sstevel@tonic-gate 
1024*0Sstevel@tonic-gate 			/* Update maximum distance (diameter), if necessary */
1025*0Sstevel@tonic-gate 			local_diameter = current->max_1st + current->max_2nd;
1026*0Sstevel@tonic-gate 			if (local_diameter > diameter)
1027*0Sstevel@tonic-gate 				diameter = local_diameter;
1028*0Sstevel@tonic-gate 		}
1029*0Sstevel@tonic-gate 	} while (done == B_FALSE);
1030*0Sstevel@tonic-gate 
1031*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_calculate_diameter_exit,
1032*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1033*0Sstevel@tonic-gate 	return (diameter);
1034*0Sstevel@tonic-gate }
1035*0Sstevel@tonic-gate 
1036*0Sstevel@tonic-gate /*
1037*0Sstevel@tonic-gate  * s1394_gap_count_optimize()
1038*0Sstevel@tonic-gate  *    looks in a table to find the appropriate gap_count for a given diameter.
1039*0Sstevel@tonic-gate  *    (See above - gap_count[])
1040*0Sstevel@tonic-gate  */
1041*0Sstevel@tonic-gate int
s1394_gap_count_optimize(int diameter)1042*0Sstevel@tonic-gate s1394_gap_count_optimize(int diameter)
1043*0Sstevel@tonic-gate {
1044*0Sstevel@tonic-gate 	if ((diameter >= 0) && (diameter <= MAX_HOPS)) {
1045*0Sstevel@tonic-gate 		return (gap_count[diameter]);
1046*0Sstevel@tonic-gate 	} else {
1047*0Sstevel@tonic-gate 		cmn_err(CE_NOTE, "Too may point-to-point links on the 1394"
1048*0Sstevel@tonic-gate 		    " bus - If new devices have recently been added, remove"
1049*0Sstevel@tonic-gate 		    " them.");
1050*0Sstevel@tonic-gate 		return (gap_count[MAX_HOPS]);
1051*0Sstevel@tonic-gate 	}
1052*0Sstevel@tonic-gate }
1053*0Sstevel@tonic-gate 
1054*0Sstevel@tonic-gate /*
1055*0Sstevel@tonic-gate  * s1394_get_current_gap_count()
1056*0Sstevel@tonic-gate  *    looks at all the SelfID packets to determine the current gap_count on
1057*0Sstevel@tonic-gate  *    the 1394 bus.  If the gap_counts differ from node to node, it initiates
1058*0Sstevel@tonic-gate  *    a bus reset and returns -1.
1059*0Sstevel@tonic-gate  */
1060*0Sstevel@tonic-gate int
s1394_get_current_gap_count(s1394_hal_t * hal)1061*0Sstevel@tonic-gate s1394_get_current_gap_count(s1394_hal_t *hal)
1062*0Sstevel@tonic-gate {
1063*0Sstevel@tonic-gate 	int	i;
1064*0Sstevel@tonic-gate 	int	gap_count = -1;
1065*0Sstevel@tonic-gate 
1066*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_get_current_gap_count_enter,
1067*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1068*0Sstevel@tonic-gate 
1069*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1070*0Sstevel@tonic-gate 
1071*0Sstevel@tonic-gate 	/* Grab the first gap_count in the SelfID packets */
1072*0Sstevel@tonic-gate 	gap_count = IEEE1394_SELFID_GAP_CNT(hal->selfid_ptrs[0]);
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate 	/* Compare it too all the rest */
1075*0Sstevel@tonic-gate 	for (i = 1; i < hal->number_of_nodes; i++) {
1076*0Sstevel@tonic-gate 		if (gap_count !=
1077*0Sstevel@tonic-gate 		    IEEE1394_SELFID_GAP_CNT(hal->selfid_ptrs[i])) {
1078*0Sstevel@tonic-gate 
1079*0Sstevel@tonic-gate 			/* Inconsistent gap counts */
1080*0Sstevel@tonic-gate 			TNF_PROBE_1(s1394_get_current_gap_count_error,
1081*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_ERROR, "", tnf_string, msg,
1082*0Sstevel@tonic-gate 			    "Inconsistent gap count");
1083*0Sstevel@tonic-gate 
1084*0Sstevel@tonic-gate 			if (s1394_ignore_invalid_gap_cnt == 0) {
1085*0Sstevel@tonic-gate 				/* Initiate a bus reset */
1086*0Sstevel@tonic-gate 				s1394_initiate_hal_reset(hal, CRITICAL);
1087*0Sstevel@tonic-gate 			}
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_get_current_gap_count_exit,
1090*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
1091*0Sstevel@tonic-gate 			return (-1);
1092*0Sstevel@tonic-gate 		}
1093*0Sstevel@tonic-gate 	}
1094*0Sstevel@tonic-gate 
1095*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_get_current_gap_count_exit,
1096*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1097*0Sstevel@tonic-gate 	return (gap_count);
1098*0Sstevel@tonic-gate }
1099*0Sstevel@tonic-gate 
1100*0Sstevel@tonic-gate /*
1101*0Sstevel@tonic-gate  * s1394_speed_map_fill()
1102*0Sstevel@tonic-gate  *    determines, for each pair of nodes, the maximum speed at which those
1103*0Sstevel@tonic-gate  *    nodes can communicate.  The speed of each node as well as the speed of
1104*0Sstevel@tonic-gate  *    any intermediate nodes on a given path must be accounted for, as the
1105*0Sstevel@tonic-gate  *    minimum speed on a given edge determines the maximum speed for all
1106*0Sstevel@tonic-gate  *    communications across that edge.
1107*0Sstevel@tonic-gate  *    In the method we implement below, a current minimum speed is selected.
1108*0Sstevel@tonic-gate  *    With this minimum speed in mind, we create subgraphs of the original
1109*0Sstevel@tonic-gate  *    bus which contain only edges that connect two nodes whose speeds are
1110*0Sstevel@tonic-gate  *    equal to or greater than the current minimum speed.  Then, for each of
1111*0Sstevel@tonic-gate  *    the subgraphs, we visit every node, keeping a list of the nodes we've
1112*0Sstevel@tonic-gate  *    visited.  When this list is completed, we can fill in the entries in
1113*0Sstevel@tonic-gate  *    the speed map which correspond to a pairs of these nodes.  Doing this
1114*0Sstevel@tonic-gate  *    for each subgraph and then for each speed we progressively fill in the
1115*0Sstevel@tonic-gate  *    parts of the speed map which weren't previously filled in.
1116*0Sstevel@tonic-gate  */
1117*0Sstevel@tonic-gate void
s1394_speed_map_fill(s1394_hal_t * hal)1118*0Sstevel@tonic-gate s1394_speed_map_fill(s1394_hal_t *hal)
1119*0Sstevel@tonic-gate {
1120*0Sstevel@tonic-gate 	uint_t	number_of_nodes;
1121*0Sstevel@tonic-gate 	int	i;
1122*0Sstevel@tonic-gate 	int	j;
1123*0Sstevel@tonic-gate 	int	node_num;
1124*0Sstevel@tonic-gate 
1125*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_speed_map_fill_enter,
1126*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1127*0Sstevel@tonic-gate 
1128*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1129*0Sstevel@tonic-gate 
1130*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
1131*0Sstevel@tonic-gate 	s1394_speed_map_initialize(hal);
1132*0Sstevel@tonic-gate 
1133*0Sstevel@tonic-gate 	/* Mark all speed = IEEE1394_S100 nodes in the Speed Map */
1134*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
1135*0Sstevel@tonic-gate 		if (selfid_speed(hal->topology_tree[i].selfid_packet) ==
1136*0Sstevel@tonic-gate 		    IEEE1394_S100) {
1137*0Sstevel@tonic-gate 			hal->slowest_node_speed = IEEE1394_S100;
1138*0Sstevel@tonic-gate 			node_num = IEEE1394_SELFID_PHYID(
1139*0Sstevel@tonic-gate 			    hal->topology_tree[i].selfid_packet);
1140*0Sstevel@tonic-gate 			for (j = 0; j < number_of_nodes; j++) {
1141*0Sstevel@tonic-gate 				if (j != node_num) {
1142*0Sstevel@tonic-gate 					hal->speed_map[node_num][j] =
1143*0Sstevel@tonic-gate 					    IEEE1394_S100;
1144*0Sstevel@tonic-gate 					hal->speed_map[j][node_num] =
1145*0Sstevel@tonic-gate 					    IEEE1394_S100;
1146*0Sstevel@tonic-gate 				}
1147*0Sstevel@tonic-gate 			}
1148*0Sstevel@tonic-gate 		}
1149*0Sstevel@tonic-gate 	}
1150*0Sstevel@tonic-gate 
1151*0Sstevel@tonic-gate 	s1394_speed_map_fill_speed_N(hal, IEEE1394_S200);
1152*0Sstevel@tonic-gate 	s1394_speed_map_fill_speed_N(hal, IEEE1394_S400);
1153*0Sstevel@tonic-gate 
1154*0Sstevel@tonic-gate 	/* Fill in the diagonal */
1155*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
1156*0Sstevel@tonic-gate 		hal->speed_map[i][i] =
1157*0Sstevel@tonic-gate 		    selfid_speed(hal->topology_tree[i].selfid_packet);
1158*0Sstevel@tonic-gate 	}
1159*0Sstevel@tonic-gate 
1160*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_speed_map_fill_exit,
1161*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1162*0Sstevel@tonic-gate }
1163*0Sstevel@tonic-gate 
1164*0Sstevel@tonic-gate /*
1165*0Sstevel@tonic-gate  * s1394_speed_map_fill_speed_N(),
1166*0Sstevel@tonic-gate  *    given a minimum link speed, creates subgraphs of the original bus which
1167*0Sstevel@tonic-gate  *    contain only the necessary edges (see speed_map_fill() above).  For each
1168*0Sstevel@tonic-gate  *    of the subgraphs, it visits and fills in the entries in the speed map
1169*0Sstevel@tonic-gate  *    which correspond to a pair of these nodes.
1170*0Sstevel@tonic-gate  */
1171*0Sstevel@tonic-gate static void
s1394_speed_map_fill_speed_N(s1394_hal_t * hal,int min_spd)1172*0Sstevel@tonic-gate s1394_speed_map_fill_speed_N(s1394_hal_t *hal, int min_spd)
1173*0Sstevel@tonic-gate {
1174*0Sstevel@tonic-gate 	s1394_node_t	*tmp;
1175*0Sstevel@tonic-gate 	uint_t		number_of_nodes;
1176*0Sstevel@tonic-gate 	int		i;
1177*0Sstevel@tonic-gate 	int		j;
1178*0Sstevel@tonic-gate 	int		k;
1179*0Sstevel@tonic-gate 	int		size;
1180*0Sstevel@tonic-gate 	int		ix_a, ix_b;
1181*0Sstevel@tonic-gate 
1182*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_speed_map_fill_speed_N_enter,
1183*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1184*0Sstevel@tonic-gate 
1185*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1186*0Sstevel@tonic-gate 
1187*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
1188*0Sstevel@tonic-gate 
1189*0Sstevel@tonic-gate 	/* Prepare the topology tree */
1190*0Sstevel@tonic-gate 	s1394_topology_tree_mark_all_unvisited(hal);
1191*0Sstevel@tonic-gate 
1192*0Sstevel@tonic-gate 	/* To ensure that the queue is empty */
1193*0Sstevel@tonic-gate 	hal->hal_queue_front = hal->hal_queue_back = 0;
1194*0Sstevel@tonic-gate 
1195*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
1196*0Sstevel@tonic-gate 		/* If the node's speed == min_spd and it hasn't been visited */
1197*0Sstevel@tonic-gate 		if (!NODE_VISITED(&hal->topology_tree[i]) &&
1198*0Sstevel@tonic-gate 		    (selfid_speed(hal->topology_tree[i].selfid_packet) ==
1199*0Sstevel@tonic-gate 			min_spd)) {
1200*0Sstevel@tonic-gate 
1201*0Sstevel@tonic-gate 			if (min_spd < hal->slowest_node_speed)
1202*0Sstevel@tonic-gate 				hal->slowest_node_speed = (uint8_t)min_spd;
1203*0Sstevel@tonic-gate 
1204*0Sstevel@tonic-gate 			SET_NODE_VISITED(&hal->topology_tree[i]);
1205*0Sstevel@tonic-gate 			s1394_hal_queue_insert(hal, &hal->topology_tree[i]);
1206*0Sstevel@tonic-gate 
1207*0Sstevel@tonic-gate 			while (hal->hal_queue_front != hal->hal_queue_back) {
1208*0Sstevel@tonic-gate 				tmp = (s1394_node_t *)s1394_hal_queue_remove(
1209*0Sstevel@tonic-gate 				    hal);
1210*0Sstevel@tonic-gate 				/* Add node number to the list */
1211*0Sstevel@tonic-gate 				s1394_node_number_list_add(hal,
1212*0Sstevel@tonic-gate 				    IEEE1394_SELFID_PHYID(tmp->selfid_packet));
1213*0Sstevel@tonic-gate 
1214*0Sstevel@tonic-gate 				for (j = 0; j < IEEE1394_MAX_NUM_PORTS; j++) {
1215*0Sstevel@tonic-gate 					if ((tmp->phy_port[j] != NULL) &&
1216*0Sstevel@tonic-gate 					    (!NODE_VISITED(tmp->phy_port[j]))) {
1217*0Sstevel@tonic-gate 						if (selfid_speed(
1218*0Sstevel@tonic-gate 						    tmp->phy_port[j]->
1219*0Sstevel@tonic-gate 						    selfid_packet) >= min_spd) {
1220*0Sstevel@tonic-gate 							SET_NODE_VISITED(
1221*0Sstevel@tonic-gate 							    tmp->phy_port[j]);
1222*0Sstevel@tonic-gate 							s1394_hal_queue_insert(
1223*0Sstevel@tonic-gate 							    hal,
1224*0Sstevel@tonic-gate 							    tmp->phy_port[j]);
1225*0Sstevel@tonic-gate 						}
1226*0Sstevel@tonic-gate 					}
1227*0Sstevel@tonic-gate 				}
1228*0Sstevel@tonic-gate 			}
1229*0Sstevel@tonic-gate 
1230*0Sstevel@tonic-gate 			/* For each pair, mark speed_map as min_spd */
1231*0Sstevel@tonic-gate 			size = hal->hal_node_number_list_size;
1232*0Sstevel@tonic-gate 			for (j = 0; j < size; j++) {
1233*0Sstevel@tonic-gate 				for (k = 0; k < size; k++) {
1234*0Sstevel@tonic-gate 					if (j != k) {
1235*0Sstevel@tonic-gate 						ix_a = hal->
1236*0Sstevel@tonic-gate 						    hal_node_number_list[j];
1237*0Sstevel@tonic-gate 						ix_b = hal->
1238*0Sstevel@tonic-gate 						    hal_node_number_list[k];
1239*0Sstevel@tonic-gate 						hal->speed_map[ix_a][ix_b] =
1240*0Sstevel@tonic-gate 						    (uint8_t)min_spd;
1241*0Sstevel@tonic-gate 					}
1242*0Sstevel@tonic-gate 				}
1243*0Sstevel@tonic-gate 			}
1244*0Sstevel@tonic-gate 
1245*0Sstevel@tonic-gate 			/* Flush the Node Number List */
1246*0Sstevel@tonic-gate 			hal->hal_node_number_list_size = 0;
1247*0Sstevel@tonic-gate 		}
1248*0Sstevel@tonic-gate 	}
1249*0Sstevel@tonic-gate 
1250*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_speed_map_fill_speed_N_exit,
1251*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1252*0Sstevel@tonic-gate }
1253*0Sstevel@tonic-gate 
1254*0Sstevel@tonic-gate /*
1255*0Sstevel@tonic-gate  * s1394_speed_map_initialize()
1256*0Sstevel@tonic-gate  *    fills in the speed_map with IEEE1394_S100's and SPEED_MAP_INVALID's in
1257*0Sstevel@tonic-gate  *    the appropriate places.  These will be overwritten by
1258*0Sstevel@tonic-gate  *    s1394_speed_map_fill().
1259*0Sstevel@tonic-gate  */
1260*0Sstevel@tonic-gate static void
s1394_speed_map_initialize(s1394_hal_t * hal)1261*0Sstevel@tonic-gate s1394_speed_map_initialize(s1394_hal_t *hal)
1262*0Sstevel@tonic-gate {
1263*0Sstevel@tonic-gate 	uint_t	number_of_nodes;
1264*0Sstevel@tonic-gate 	int	i, j;
1265*0Sstevel@tonic-gate 
1266*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_speed_map_initialize_enter,
1267*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1268*0Sstevel@tonic-gate 
1269*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1270*0Sstevel@tonic-gate 
1271*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
1272*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
1273*0Sstevel@tonic-gate 		for (j = 0; j < number_of_nodes; j++) {
1274*0Sstevel@tonic-gate 			if (i != j)
1275*0Sstevel@tonic-gate 				hal->speed_map[i][j] = IEEE1394_S100;
1276*0Sstevel@tonic-gate 			else
1277*0Sstevel@tonic-gate 				hal->speed_map[i][j] = SPEED_MAP_INVALID;
1278*0Sstevel@tonic-gate 		}
1279*0Sstevel@tonic-gate 	}
1280*0Sstevel@tonic-gate 
1281*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_speed_map_initialize_exit,
1282*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1283*0Sstevel@tonic-gate }
1284*0Sstevel@tonic-gate 
1285*0Sstevel@tonic-gate /*
1286*0Sstevel@tonic-gate  * s1394_speed_map_get()
1287*0Sstevel@tonic-gate  *    queries the speed_map[] for a given pair of nodes.
1288*0Sstevel@tonic-gate  */
1289*0Sstevel@tonic-gate uint8_t
s1394_speed_map_get(s1394_hal_t * hal,uint_t from_node,uint_t to_node)1290*0Sstevel@tonic-gate s1394_speed_map_get(s1394_hal_t *hal, uint_t from_node, uint_t to_node)
1291*0Sstevel@tonic-gate {
1292*0Sstevel@tonic-gate 	/* If it's not a valid node, then return slowest_node_speed */
1293*0Sstevel@tonic-gate 	if (to_node >= hal->number_of_nodes) {
1294*0Sstevel@tonic-gate 		/* Send at fastest speed everyone will see */
1295*0Sstevel@tonic-gate 		return (hal->slowest_node_speed);
1296*0Sstevel@tonic-gate 	}
1297*0Sstevel@tonic-gate 	/* else return the correct maximum speed */
1298*0Sstevel@tonic-gate 	return (hal->speed_map[from_node][to_node]);
1299*0Sstevel@tonic-gate }
1300*0Sstevel@tonic-gate 
1301*0Sstevel@tonic-gate /*
1302*0Sstevel@tonic-gate  * s1394_update_speed_map_link_speeds()
1303*0Sstevel@tonic-gate  *    takes into account information from Config ROM queries.  Any P1394A
1304*0Sstevel@tonic-gate  *    device can have a link with a different speed than its PHY.  In this
1305*0Sstevel@tonic-gate  *    case, the slower speed must be accounted for in order for communication
1306*0Sstevel@tonic-gate  *    with the remote node to work.
1307*0Sstevel@tonic-gate  */
1308*0Sstevel@tonic-gate void
s1394_update_speed_map_link_speeds(s1394_hal_t * hal)1309*0Sstevel@tonic-gate s1394_update_speed_map_link_speeds(s1394_hal_t *hal)
1310*0Sstevel@tonic-gate {
1311*0Sstevel@tonic-gate 	uint32_t bus_capabilities;
1312*0Sstevel@tonic-gate 	uint8_t	 link_speed;
1313*0Sstevel@tonic-gate 	uint_t	 number_of_nodes;
1314*0Sstevel@tonic-gate 	int	 i, j;
1315*0Sstevel@tonic-gate 
1316*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_update_speed_map_link_speeds_enter,
1317*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1318*0Sstevel@tonic-gate 
1319*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1320*0Sstevel@tonic-gate 
1321*0Sstevel@tonic-gate 	number_of_nodes = hal->number_of_nodes;
1322*0Sstevel@tonic-gate 
1323*0Sstevel@tonic-gate 	for (i = 0; i < number_of_nodes; i++) {
1324*0Sstevel@tonic-gate 
1325*0Sstevel@tonic-gate 		/* Skip invalid config ROMs */
1326*0Sstevel@tonic-gate 		if (CFGROM_VALID(&hal->topology_tree[i])) {
1327*0Sstevel@tonic-gate 
1328*0Sstevel@tonic-gate 			ASSERT(hal->topology_tree[i].cfgrom);
1329*0Sstevel@tonic-gate 
1330*0Sstevel@tonic-gate 			bus_capabilities = hal->topology_tree[i].
1331*0Sstevel@tonic-gate 			    cfgrom[IEEE1212_NODE_CAP_QUAD];
1332*0Sstevel@tonic-gate 
1333*0Sstevel@tonic-gate 			/* Skip if Bus_Info_Block generation is 0 */
1334*0Sstevel@tonic-gate 			/* because it isn't a P1394a device */
1335*0Sstevel@tonic-gate 			if ((bus_capabilities & IEEE1394_BIB_GEN_MASK) != 0) {
1336*0Sstevel@tonic-gate 				link_speed = (bus_capabilities &
1337*0Sstevel@tonic-gate 				    IEEE1394_BIB_LNK_SPD_MASK);
1338*0Sstevel@tonic-gate 
1339*0Sstevel@tonic-gate 				for (j = 0; j < number_of_nodes; j++) {
1340*0Sstevel@tonic-gate 					/* Update if link_speed is slower */
1341*0Sstevel@tonic-gate 					if (hal->speed_map[i][j] > link_speed) {
1342*0Sstevel@tonic-gate 						hal->speed_map[i][j] =
1343*0Sstevel@tonic-gate 						    link_speed;
1344*0Sstevel@tonic-gate 						hal->speed_map[j][i] =
1345*0Sstevel@tonic-gate 						    link_speed;
1346*0Sstevel@tonic-gate 					}
1347*0Sstevel@tonic-gate 
1348*0Sstevel@tonic-gate 					if (link_speed <
1349*0Sstevel@tonic-gate 					    hal->slowest_node_speed)
1350*0Sstevel@tonic-gate 						hal->slowest_node_speed =
1351*0Sstevel@tonic-gate 						    link_speed;
1352*0Sstevel@tonic-gate 				}
1353*0Sstevel@tonic-gate 			}
1354*0Sstevel@tonic-gate 		}
1355*0Sstevel@tonic-gate 	}
1356*0Sstevel@tonic-gate 
1357*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_update_speed_map_link_speeds_exit,
1358*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1359*0Sstevel@tonic-gate }
1360*0Sstevel@tonic-gate 
1361*0Sstevel@tonic-gate /*
1362*0Sstevel@tonic-gate  * s1394_get_isoch_rsrc_mgr()
1363*0Sstevel@tonic-gate  *    looks at the SelfID packets to determine the Isochronous Resource
1364*0Sstevel@tonic-gate  *    Manager's node ID.  The IRM is the highest numbered node with both
1365*0Sstevel@tonic-gate  *    the "L"-bit and the "C"-bit in its SelfID packets turned on.  If no
1366*0Sstevel@tonic-gate  *    IRM is found on the bus, then -1 is returned.
1367*0Sstevel@tonic-gate  */
1368*0Sstevel@tonic-gate int
s1394_get_isoch_rsrc_mgr(s1394_hal_t * hal)1369*0Sstevel@tonic-gate s1394_get_isoch_rsrc_mgr(s1394_hal_t *hal)
1370*0Sstevel@tonic-gate {
1371*0Sstevel@tonic-gate 	int	i;
1372*0Sstevel@tonic-gate 
1373*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_get_isoch_rsrc_mgr_enter, S1394_TNF_SL_BR_STACK,
1374*0Sstevel@tonic-gate 	    "");
1375*0Sstevel@tonic-gate 
1376*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1377*0Sstevel@tonic-gate 
1378*0Sstevel@tonic-gate 	for (i = hal->number_of_nodes - 1; i >= 0; i--) {
1379*0Sstevel@tonic-gate 		/* Highest numbered node with L=1 and C=1 */
1380*0Sstevel@tonic-gate 		if ((IEEE1394_SELFID_ISLINKON(hal->selfid_ptrs[i])) &&
1381*0Sstevel@tonic-gate 		    (IEEE1394_SELFID_ISCONTENDER(hal->selfid_ptrs[i]))) {
1382*0Sstevel@tonic-gate 
1383*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(s1394_get_isoch_rsrc_mgr_exit,
1384*0Sstevel@tonic-gate 			    S1394_TNF_SL_BR_STACK, "");
1385*0Sstevel@tonic-gate 			return (i);
1386*0Sstevel@tonic-gate 		}
1387*0Sstevel@tonic-gate 	}
1388*0Sstevel@tonic-gate 
1389*0Sstevel@tonic-gate 	/* No Isochronous Resource Manager */
1390*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_get_isoch_rsrc_mgr_exit, S1394_TNF_SL_BR_STACK,
1391*0Sstevel@tonic-gate 	    "");
1392*0Sstevel@tonic-gate 	return (-1);
1393*0Sstevel@tonic-gate }
1394*0Sstevel@tonic-gate 
1395*0Sstevel@tonic-gate /*
1396*0Sstevel@tonic-gate  * s1394_physical_arreq_setup_all()
1397*0Sstevel@tonic-gate  *    is used to enable the physical filters for the link.  If a target has
1398*0Sstevel@tonic-gate  *    registered physical space allocations, then the corresponding node's
1399*0Sstevel@tonic-gate  *    bit is set.  This is done for all targets on a HAL (usually after bus
1400*0Sstevel@tonic-gate  *    reset).
1401*0Sstevel@tonic-gate  */
1402*0Sstevel@tonic-gate void
s1394_physical_arreq_setup_all(s1394_hal_t * hal)1403*0Sstevel@tonic-gate s1394_physical_arreq_setup_all(s1394_hal_t *hal)
1404*0Sstevel@tonic-gate {
1405*0Sstevel@tonic-gate 	s1394_target_t	*curr_target;
1406*0Sstevel@tonic-gate 	uint64_t	mask = 0;
1407*0Sstevel@tonic-gate 	uint32_t	node_num;
1408*0Sstevel@tonic-gate 	uint_t		generation;
1409*0Sstevel@tonic-gate 
1410*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_physical_arreq_setup_all_enter,
1411*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1412*0Sstevel@tonic-gate 
1413*0Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1414*0Sstevel@tonic-gate 
1415*0Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
1416*0Sstevel@tonic-gate 	generation = hal->generation_count;
1417*0Sstevel@tonic-gate 	rw_enter(&hal->target_list_rwlock, RW_READER);
1418*0Sstevel@tonic-gate 
1419*0Sstevel@tonic-gate 	curr_target = hal->target_head;
1420*0Sstevel@tonic-gate 	while (curr_target != NULL) {
1421*0Sstevel@tonic-gate 		if ((curr_target->on_node != NULL) &&
1422*0Sstevel@tonic-gate 		    (curr_target->physical_arreq_enabled != 0)) {
1423*0Sstevel@tonic-gate 			node_num = curr_target->on_node->node_num;
1424*0Sstevel@tonic-gate 			mask = mask | (1 << node_num);
1425*0Sstevel@tonic-gate 		}
1426*0Sstevel@tonic-gate 		curr_target = curr_target->target_next;
1427*0Sstevel@tonic-gate 	}
1428*0Sstevel@tonic-gate 	rw_exit(&hal->target_list_rwlock);
1429*0Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
1430*0Sstevel@tonic-gate 
1431*0Sstevel@tonic-gate 	/*
1432*0Sstevel@tonic-gate 	 * Since it is cleared to 0 on bus reset, set the bits for all
1433*0Sstevel@tonic-gate 	 * nodes.  This call returns DDI_FAILURE if the generation passed
1434*0Sstevel@tonic-gate 	 * is invalid or if the HAL is shutdown.  In either case, it is
1435*0Sstevel@tonic-gate 	 * acceptable to simply ignore the result and return.
1436*0Sstevel@tonic-gate 	 */
1437*0Sstevel@tonic-gate 	(void) HAL_CALL(hal).physical_arreq_enable_set(
1438*0Sstevel@tonic-gate 	    hal->halinfo.hal_private, mask, generation);
1439*0Sstevel@tonic-gate 
1440*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_physical_arreq_setup_all_exit,
1441*0Sstevel@tonic-gate 	    S1394_TNF_SL_BR_STACK, "");
1442*0Sstevel@tonic-gate }
1443*0Sstevel@tonic-gate 
1444*0Sstevel@tonic-gate /*
1445*0Sstevel@tonic-gate  * s1394_physical_arreq_set_one()
1446*0Sstevel@tonic-gate  *    is used to enable the physical filters for the link.  If a target has
1447*0Sstevel@tonic-gate  *    registered physical space allocations, then the corresponding node's
1448*0Sstevel@tonic-gate  *    bit is set.  This is done for one target.
1449*0Sstevel@tonic-gate  */
1450*0Sstevel@tonic-gate void
s1394_physical_arreq_set_one(s1394_target_t * target)1451*0Sstevel@tonic-gate s1394_physical_arreq_set_one(s1394_target_t *target)
1452*0Sstevel@tonic-gate {
1453*0Sstevel@tonic-gate 	s1394_hal_t	*hal;
1454*0Sstevel@tonic-gate 	uint64_t	mask = 0;
1455*0Sstevel@tonic-gate 	uint32_t	node_num;
1456*0Sstevel@tonic-gate 	uint_t		generation;
1457*0Sstevel@tonic-gate 
1458*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_physical_arreq_set_one_enter,
1459*0Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
1460*0Sstevel@tonic-gate 
1461*0Sstevel@tonic-gate 	/* Find the HAL this target resides on */
1462*0Sstevel@tonic-gate 	hal = target->on_hal;
1463*0Sstevel@tonic-gate 
1464*0Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1465*0Sstevel@tonic-gate 
1466*0Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
1467*0Sstevel@tonic-gate 	rw_enter(&hal->target_list_rwlock, RW_READER);
1468*0Sstevel@tonic-gate 
1469*0Sstevel@tonic-gate 	if ((target->on_node != NULL) &&
1470*0Sstevel@tonic-gate 	    (target->physical_arreq_enabled != 0)) {
1471*0Sstevel@tonic-gate 		node_num = target->on_node->node_num;
1472*0Sstevel@tonic-gate 		mask = mask | (1 << node_num);
1473*0Sstevel@tonic-gate 
1474*0Sstevel@tonic-gate 		generation = hal->generation_count;
1475*0Sstevel@tonic-gate 
1476*0Sstevel@tonic-gate 		rw_exit(&hal->target_list_rwlock);
1477*0Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
1478*0Sstevel@tonic-gate 
1479*0Sstevel@tonic-gate 		/*
1480*0Sstevel@tonic-gate 		 * Set the bit corresponding to this node.  This call
1481*0Sstevel@tonic-gate 		 * returns DDI_FAILURE if the generation passed
1482*0Sstevel@tonic-gate 		 * is invalid or if the HAL is shutdown.  In either case,
1483*0Sstevel@tonic-gate 		 * it is acceptable to simply ignore the result and return.
1484*0Sstevel@tonic-gate 		 */
1485*0Sstevel@tonic-gate 		(void) HAL_CALL(hal).physical_arreq_enable_set(
1486*0Sstevel@tonic-gate 		    hal->halinfo.hal_private, mask, generation);
1487*0Sstevel@tonic-gate 	} else {
1488*0Sstevel@tonic-gate 		rw_exit(&hal->target_list_rwlock);
1489*0Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
1490*0Sstevel@tonic-gate 	}
1491*0Sstevel@tonic-gate 
1492*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_physical_arreq_set_one_exit,
1493*0Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
1494*0Sstevel@tonic-gate }
1495*0Sstevel@tonic-gate 
1496*0Sstevel@tonic-gate /*
1497*0Sstevel@tonic-gate  * s1394_physical_arreq_clear_one()
1498*0Sstevel@tonic-gate  *    is used to disable the physical filters for OpenHCI.  If a target frees
1499*0Sstevel@tonic-gate  *    up the last of its registered physical space, then the corresponding
1500*0Sstevel@tonic-gate  *    node's bit is cleared.  This is done for one target.
1501*0Sstevel@tonic-gate  */
1502*0Sstevel@tonic-gate void
s1394_physical_arreq_clear_one(s1394_target_t * target)1503*0Sstevel@tonic-gate s1394_physical_arreq_clear_one(s1394_target_t *target)
1504*0Sstevel@tonic-gate {
1505*0Sstevel@tonic-gate 	s1394_hal_t	*hal;
1506*0Sstevel@tonic-gate 	uint64_t	mask = 0;
1507*0Sstevel@tonic-gate 	uint32_t	node_num;
1508*0Sstevel@tonic-gate 	uint_t		generation;
1509*0Sstevel@tonic-gate 
1510*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_physical_arreq_clear_one_enter,
1511*0Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
1512*0Sstevel@tonic-gate 
1513*0Sstevel@tonic-gate 	/* Find the HAL this target resides on */
1514*0Sstevel@tonic-gate 	hal = target->on_hal;
1515*0Sstevel@tonic-gate 
1516*0Sstevel@tonic-gate 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1517*0Sstevel@tonic-gate 
1518*0Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
1519*0Sstevel@tonic-gate 	rw_enter(&hal->target_list_rwlock, RW_READER);
1520*0Sstevel@tonic-gate 
1521*0Sstevel@tonic-gate 	if ((target->on_node != NULL) &&
1522*0Sstevel@tonic-gate 	    (target->physical_arreq_enabled == 0)) {
1523*0Sstevel@tonic-gate 		node_num = target->on_node->node_num;
1524*0Sstevel@tonic-gate 		mask = mask | (1 << node_num);
1525*0Sstevel@tonic-gate 
1526*0Sstevel@tonic-gate 		generation = hal->generation_count;
1527*0Sstevel@tonic-gate 
1528*0Sstevel@tonic-gate 		rw_exit(&hal->target_list_rwlock);
1529*0Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
1530*0Sstevel@tonic-gate 
1531*0Sstevel@tonic-gate 		/*
1532*0Sstevel@tonic-gate 		 * Set the bit corresponding to this node.  This call
1533*0Sstevel@tonic-gate 		 * returns DDI_FAILURE if the generation passed
1534*0Sstevel@tonic-gate 		 * is invalid or if the HAL is shutdown.  In either case,
1535*0Sstevel@tonic-gate 		 * it is acceptable to simply ignore the result and return.
1536*0Sstevel@tonic-gate 		 */
1537*0Sstevel@tonic-gate 		(void) HAL_CALL(hal).physical_arreq_enable_clr(
1538*0Sstevel@tonic-gate 		    hal->halinfo.hal_private, mask, generation);
1539*0Sstevel@tonic-gate 	} else {
1540*0Sstevel@tonic-gate 		rw_exit(&hal->target_list_rwlock);
1541*0Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
1542*0Sstevel@tonic-gate 	}
1543*0Sstevel@tonic-gate 
1544*0Sstevel@tonic-gate 
1545*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_physical_arreq_clear_one_exit,
1546*0Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
1547*0Sstevel@tonic-gate }
1548*0Sstevel@tonic-gate 
1549*0Sstevel@tonic-gate /*
1550*0Sstevel@tonic-gate  * s1394_topology_tree_get_root_node()
1551*0Sstevel@tonic-gate  *    returns the last entry in topology_tree[] as this must always be the
1552*0Sstevel@tonic-gate  *    root node.
1553*0Sstevel@tonic-gate  */
1554*0Sstevel@tonic-gate s1394_node_t *
s1394_topology_tree_get_root_node(s1394_hal_t * hal)1555*0Sstevel@tonic-gate s1394_topology_tree_get_root_node(s1394_hal_t *hal)
1556*0Sstevel@tonic-gate {
1557*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_get_root_node_enter,
1558*0Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
1559*0Sstevel@tonic-gate 
1560*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1561*0Sstevel@tonic-gate 
1562*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_topology_tree_get_root_node_exit,
1563*0Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
1564*0Sstevel@tonic-gate 
1565*0Sstevel@tonic-gate 	return (&hal->topology_tree[hal->number_of_nodes - 1]);
1566*0Sstevel@tonic-gate }
1567