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