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