Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / 1394 / s1394_bus_reset.c
blobcde8ce0e5448be26d33139a38582b66cee8bf263
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * s1394_bus_reset.c
31 * 1394 Services Layer Bus Reset Routines
32 * These routines handle all of the tasks relating to 1394 bus resets
35 #include <sys/conf.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/types.h>
39 #include <sys/kmem.h>
40 #include <sys/tnf_probe.h>
42 #include <sys/1394/t1394.h>
43 #include <sys/1394/s1394.h>
44 #include <sys/1394/h1394.h>
45 #include <sys/1394/ieee1394.h>
46 #include <sys/1394/ieee1212.h>
48 static uint8_t selfid_speed(s1394_selfid_pkt_t *s);
50 static int selfid_num_ports(s1394_selfid_pkt_t *s);
52 static int selfid_port_type(s1394_selfid_pkt_t *s, int port);
54 static void s1394_hal_stack_push(s1394_hal_t *hal, void *o);
56 static void *s1394_hal_stack_pop(s1394_hal_t *hal);
58 static void s1394_hal_queue_insert(s1394_hal_t *hal, void *o);
60 static void *s1394_hal_queue_remove(s1394_hal_t *hal);
62 static void s1394_node_number_list_add(s1394_hal_t *hal, int node_num);
64 static void s1394_speed_map_fill_speed_N(s1394_hal_t *hal, int min_spd);
66 static void s1394_speed_map_initialize(s1394_hal_t *hal);
68 int s1394_ignore_invalid_gap_cnt = 0; /* patch for invalid gap_cnts */
71 * Gap_count look-up table (See IEEE P1394a Table C-2) - Draft 3.0
72 * (modified from original table IEEE 1394-1995 8.4.6.2)
74 static int gap_count[MAX_HOPS + 1] = {
75 0, 5, 7, 8, 10, 13, 16, 18, 21,
76 24, 26, 29, 32, 35, 37, 40, 43,
77 46, 48, 51, 54, 57, 59, 62
81 * s1394_parse_selfid_buffer()
82 * takes the SelfID data buffer and parses it, testing whether each packet
83 * is valid (has a correct inverse packet) and setting the pointers in
84 * selfid_ptrs[] to the appropriate offsets within the buffer.
86 int
87 s1394_parse_selfid_buffer(s1394_hal_t *hal, void *selfid_buf_addr,
88 uint32_t selfid_size)
90 s1394_selfid_pkt_t *s;
91 uint32_t *data;
92 uint_t i = 0;
93 uint_t j = 0;
94 boolean_t error = B_FALSE;
95 int valid_pkt_id;
97 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
99 data = (uint32_t *)selfid_buf_addr;
101 if (selfid_size == 0) {
102 /* Initiate a bus reset */
103 s1394_initiate_hal_reset(hal, CRITICAL);
105 /* Set error status */
106 error = B_TRUE;
108 /* Release HAL lock and return */
109 goto parse_buffer_done;
112 /* Convert bytes to quadlets */
113 selfid_size = selfid_size >> 2;
115 while (j < selfid_size) {
116 valid_pkt_id = ((data[j] & IEEE1394_SELFID_PCKT_ID_MASK) >>
117 IEEE1394_SELFID_PCKT_ID_SHIFT);
119 s = (s1394_selfid_pkt_t *)(&data[j]);
121 /* Test if packet has valid inverse quadlet */
122 if (IEEE1394_SELFID_ISVALID(s) &&
123 (valid_pkt_id == IEEE1394_SELFID_PCKT_ID_VALID)) {
125 hal->selfid_ptrs[i] = s;
127 /* While this packet contains multiple quadlets */
128 j += 2;
130 while (IEEE1394_SELFID_ISMORE(s)) {
131 valid_pkt_id =
132 ((data[j] & IEEE1394_SELFID_PCKT_ID_MASK) >>
133 IEEE1394_SELFID_PCKT_ID_SHIFT);
135 s = (s1394_selfid_pkt_t *)(&data[j]);
137 /* Test if packet has valid inverse quadlet */
138 if (IEEE1394_SELFID_ISVALID(s) &&
139 (valid_pkt_id ==
140 IEEE1394_SELFID_PCKT_ID_VALID)) {
141 j += 2;
142 } else {
143 /* Initiate a bus reset */
144 s1394_initiate_hal_reset(hal, CRITICAL);
146 /* Set error status */
147 error = B_TRUE;
149 /* Release HAL lock and return */
150 goto parse_buffer_done;
153 i++;
154 } else {
155 /* Initiate a bus reset */
156 s1394_initiate_hal_reset(hal, CRITICAL);
158 /* Set error status */
159 error = B_TRUE;
161 /* Release HAL lock and return */
162 goto parse_buffer_done;
166 hal->number_of_nodes = i;
168 parse_buffer_done:
169 if (error == B_TRUE)
170 return (DDI_FAILURE);
171 else
172 return (DDI_SUCCESS);
176 * s1394_sort_selfids()
177 * takes the selfid_ptrs[] in the HAL struct and sorts them by node number,
178 * using a heapsort.
180 void
181 s1394_sort_selfids(s1394_hal_t *hal)
183 s1394_selfid_pkt_t *current;
184 uint_t number_of_nodes;
185 int i;
186 int j;
188 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
190 number_of_nodes = hal->number_of_nodes;
192 /* We start at one because the root has no parent to check */
193 for (i = 1; i < number_of_nodes; i++) {
194 current = hal->selfid_ptrs[i];
195 j = i;
196 while ((j > 0) && (IEEE1394_SELFID_PHYID(current) >
197 IEEE1394_SELFID_PHYID(hal->selfid_ptrs[j / 2]))) {
198 hal->selfid_ptrs[j] = hal->selfid_ptrs[j / 2];
199 hal->selfid_ptrs[j / 2] = current;
200 j = j / 2;
204 for (i = number_of_nodes - 1; i > 0; i--) {
205 current = hal->selfid_ptrs[i];
206 hal->selfid_ptrs[i] = hal->selfid_ptrs[0];
207 hal->selfid_ptrs[0] = current;
208 j = 0;
209 while (2 * j + 1 < i) {
210 if (2 * j + 2 >= i) {
211 if (IEEE1394_SELFID_PHYID(current) <
212 IEEE1394_SELFID_PHYID(
213 hal->selfid_ptrs[2 * j + 1])) {
214 hal->selfid_ptrs[j] =
215 hal->selfid_ptrs[2 * j + 1];
216 hal->selfid_ptrs[2 * j + 1] = current;
217 j = 2 * j + 1;
219 break;
222 if (IEEE1394_SELFID_PHYID(hal->selfid_ptrs[2 * j + 1]) >
223 IEEE1394_SELFID_PHYID(
224 hal->selfid_ptrs[2 * j + 2])) {
225 if (IEEE1394_SELFID_PHYID(current) <
226 IEEE1394_SELFID_PHYID(
227 hal->selfid_ptrs[2 * j + 1])) {
228 hal->selfid_ptrs[j] =
229 hal->selfid_ptrs[2 * j + 1];
230 hal->selfid_ptrs[2 * j + 1] = current;
231 j = 2 * j + 1;
232 } else {
233 break;
235 } else {
236 if (IEEE1394_SELFID_PHYID(current) <
237 IEEE1394_SELFID_PHYID(
238 hal->selfid_ptrs[2 * j + 2])) {
239 hal->selfid_ptrs[j] =
240 hal->selfid_ptrs[2 * j + 2];
241 hal->selfid_ptrs[2 * j + 2] = current;
242 j = 2 * j + 2;
243 } else {
244 break;
252 * selfid_speed()
253 * examines the "sp" bits for a given packet (see IEEE 1394-1995 4.3.4.1)
254 * and returns the node's speed capabilities.
256 static uint8_t
257 selfid_speed(s1394_selfid_pkt_t *s)
259 uint32_t sp;
261 sp = ((s->spkt_data & IEEE1394_SELFID_SP_MASK) >>
262 IEEE1394_SELFID_SP_SHIFT);
264 switch (sp) {
265 case IEEE1394_S100:
266 case IEEE1394_S200:
267 case IEEE1394_S400:
268 return (sp);
271 * To verify higher speeds we should look at PHY register #3
272 * on this node. This will need to be done to support P1394b
274 default:
275 return (IEEE1394_S400);
280 * selfid_num_ports()
281 * determines whether a packet is multi-part or single, and from this it
282 * calculates the number of ports which have been specified.
283 * (See IEEE 1394-1995 4.3.4.1)
285 static int
286 selfid_num_ports(s1394_selfid_pkt_t *s)
288 int p = 3;
290 while (IEEE1394_SELFID_ISMORE(s)) {
291 p += 8;
292 s++;
295 /* Threshold the number of ports at the P1394A defined maximum */
296 /* (see P1394A Draft 3.0 - Section 8.5.1) */
297 if (p > IEEE1394_MAX_NUM_PORTS)
298 p = IEEE1394_MAX_NUM_PORTS;
300 return (p);
304 * selfid_port_type()
305 * determines what type of node the specified port connects to.
306 * (See IEEE 1394-1995 4.3.4.1)
308 static int
309 selfid_port_type(s1394_selfid_pkt_t *s, int port)
311 int block;
312 int offset = IEEE1394_SELFID_PORT_OFFSET_FIRST;
314 if (port > 2) {
315 /* Calculate which quadlet and bits for this port */
316 port -= 3;
317 block = (port >> 3) + 1;
318 port = port % 8;
319 /* Move to the correct quadlet */
320 s += block;
321 offset = IEEE1394_SELFID_PORT_OFFSET_OTHERS;
324 /* Shift by appropriate number of bits and mask */
325 return ((s->spkt_data >> (offset - 2 * port)) & 0x00000003);
329 * s1394_init_topology_tree()
330 * frees any config rom's allocated in the topology tree before zapping it.
331 * If it gets a bus reset before the tree is marked processed, there will
332 * be memory allocated for cfgrom's being read. If there is no tree copy,
333 * topology would still be topology tree from the previous generation and
334 * if we bzero'd the tree, we will have a memory leak. To avoid this leak,
335 * walk through the tree and free any config roms in nodes that are NOT
336 * matched. (For matched nodes, we ensure that nodes in old and topology
337 * tree point to the same area of memory.)
339 void
340 s1394_init_topology_tree(s1394_hal_t *hal, boolean_t copied,
341 ushort_t number_of_nodes)
343 s1394_node_t *node;
344 uint32_t *config_rom;
345 uint_t tree_size;
346 int i;
348 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
351 * if copied is false, we want to free any cfgrom memory that is
352 * not referenced to in both topology and old trees. However, we
353 * don't use hal->number_of_nodes as the number of nodes to look at.
354 * The reason being we could be seeing the bus reset before the
355 * state is appropriate for a tree copy (which need
356 * toplogy_tree_processed to be true) and some nodes might have
357 * departed in this generation and hal->number_of_nodes reflects
358 * the number of nodes in this generation. Use number_of_nodes that
359 * gets passed into this routine as the actual number of nodes to
360 * look at.
362 if (copied == B_FALSE) {
363 /* Free any cfgrom alloced and zap the node */
364 for (i = 0; i < number_of_nodes; i++) {
365 node = &hal->topology_tree[i];
366 config_rom = node->cfgrom;
367 if (config_rom != NULL) {
368 if (CFGROM_NEW_ALLOC(node) == B_TRUE) {
369 kmem_free((void *)config_rom,
370 IEEE1394_CONFIG_ROM_SZ);
376 tree_size = hal->number_of_nodes * sizeof (s1394_node_t);
377 bzero((void *)hal->topology_tree, tree_size);
381 * s1394_topology_tree_build()
382 * takes the selfid_ptrs[] and builds the topology_tree[] by examining
383 * the node numbers (the order in which the nodes responded to SelfID).
384 * It sets the port pointers, leaf label, parent port, and
385 * s1394_selfid_packet_t pointer in each node.
388 s1394_topology_tree_build(s1394_hal_t *hal)
390 s1394_node_t *tmp;
391 uint32_t number_of_nodes;
392 boolean_t push_to_orphan_stack = B_FALSE;
393 boolean_t found_parent = B_FALSE;
394 boolean_t found_connection = B_FALSE;
395 int i;
396 int j;
398 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
400 number_of_nodes = hal->number_of_nodes;
402 /* Flush the Stack */
403 hal->hal_stack_depth = -1;
405 /* For each node on the bus initialize its topology_tree entry */
406 for (i = 0; i < number_of_nodes; i++) {
407 /* Make sure that node numbers are correct */
408 if (i != IEEE1394_SELFID_PHYID(hal->selfid_ptrs[i])) {
409 /* Initiate a bus reset */
410 s1394_initiate_hal_reset(hal, CRITICAL);
412 return (DDI_FAILURE);
415 hal->topology_tree[i].selfid_packet = hal->selfid_ptrs[i];
416 hal->topology_tree[i].parent_port = (char)NO_PARENT;
417 hal->topology_tree[i].is_a_leaf = 1;
418 hal->topology_tree[i].node_num = (uchar_t)i;
421 for (i = 0; i < number_of_nodes; i++) {
422 /* Current node has no parent yet */
423 found_parent = B_FALSE;
425 /* Current node has no connections yet */
426 found_connection = B_FALSE;
428 /* Initialize all ports on this node */
429 for (j = 0; j < IEEE1394_MAX_NUM_PORTS; j++)
430 hal->topology_tree[i].phy_port[j] = NULL;
432 /* For each port on the node - highest to lowest */
433 for (j = selfid_num_ports(hal->selfid_ptrs[i]) - 1;
434 j >= 0; j--) {
435 if (selfid_port_type(hal->selfid_ptrs[i], j) ==
436 IEEE1394_SELFID_PORT_TO_PARENT) {
438 found_connection = B_TRUE;
439 if (found_parent == B_FALSE) {
440 push_to_orphan_stack = B_TRUE;
441 hal->topology_tree[i].parent_port =
442 (char)j;
443 found_parent = B_TRUE;
445 } else {
446 /* Initiate a bus reset */
447 s1394_initiate_hal_reset(hal, CRITICAL);
449 return (DDI_FAILURE);
451 } else if (selfid_port_type(hal->selfid_ptrs[i], j) ==
452 IEEE1394_SELFID_PORT_TO_CHILD) {
454 found_connection = B_TRUE;
455 tmp = (s1394_node_t *)s1394_hal_stack_pop(hal);
456 if (tmp == NULL) {
457 /* Initiate a bus reset */
458 s1394_initiate_hal_reset(hal, CRITICAL);
460 return (DDI_FAILURE);
463 hal->topology_tree[i].phy_port[j] = tmp;
464 hal->topology_tree[i].is_a_leaf = 0;
465 tmp->phy_port[tmp->parent_port] =
466 &hal->topology_tree[i];
470 /* If current node has no parents or children - Invalid */
471 if ((found_connection == B_FALSE) && (number_of_nodes > 1)) {
472 /* Initiate a bus reset */
473 s1394_initiate_hal_reset(hal, CRITICAL);
475 return (DDI_FAILURE);
478 /* Push it on the "Orphan" stack if it has no parent yet */
479 if (push_to_orphan_stack == B_TRUE) {
480 push_to_orphan_stack = B_FALSE;
481 s1394_hal_stack_push(hal, &hal->topology_tree[i]);
485 /* If the stack is not empty, then something has gone seriously wrong */
486 if (hal->hal_stack_depth != -1) {
487 /* Initiate a bus reset */
488 s1394_initiate_hal_reset(hal, CRITICAL);
490 return (DDI_FAILURE);
493 /* New topology tree is now valid */
494 hal->topology_tree_valid = B_TRUE;
496 return (DDI_SUCCESS);
500 * s1394_hal_stack_push()
501 * checks that the stack is not full, and puts the pointer on top of the
502 * HAL's stack if it isn't. This routine is used only by the
503 * h1394_self_ids() interrupt.
505 static void
506 s1394_hal_stack_push(s1394_hal_t *hal, void *obj)
508 if (hal->hal_stack_depth < IEEE1394_MAX_NODES - 1) {
509 hal->hal_stack_depth++;
510 hal->hal_stack[hal->hal_stack_depth] = obj;
515 * s1394_hal_stack_pop()
516 * checks that the stack is not empty, and pops and returns the pointer
517 * from the top of the HAL's stack if it isn't. This routine is used
518 * only by the h1394_self_ids() interrupt.
520 static void *
521 s1394_hal_stack_pop(s1394_hal_t *hal)
523 if (hal->hal_stack_depth > -1) {
524 hal->hal_stack_depth--;
525 return (hal->hal_stack[hal->hal_stack_depth + 1]);
526 } else {
527 return (NULL);
532 * s1394_hal_queue_insert()
533 * checks that the queue is not full, and puts the object in the front
534 * of the HAL's queue if it isn't. This routine is used only by the
535 * h1394_self_ids() interrupt.
537 static void
538 s1394_hal_queue_insert(s1394_hal_t *hal, void *obj)
540 if (((hal->hal_queue_front + 1) % IEEE1394_MAX_NODES) ==
541 hal->hal_queue_back) {
542 return;
544 } else {
545 hal->hal_queue[hal->hal_queue_front] = obj;
546 hal->hal_queue_front = (hal->hal_queue_front + 1) %
547 IEEE1394_MAX_NODES;
553 * s1394_hal_queue_remove()
554 * checks that the queue is not empty, and pulls the object off the back
555 * of the HAL's queue (and returns it) if it isn't. This routine is used
556 * only by the h1394_self_ids() interrupt.
558 static void *
559 s1394_hal_queue_remove(s1394_hal_t *hal)
561 void *tmp;
563 if (hal->hal_queue_back == hal->hal_queue_front) {
564 return (NULL);
566 } else {
567 tmp = hal->hal_queue[hal->hal_queue_back];
568 hal->hal_queue_back = (hal->hal_queue_back + 1) %
569 IEEE1394_MAX_NODES;
570 return (tmp);
576 * s1394_node_number_list_add()
577 * checks that the node_number_list is not full and puts the node number
578 * in the list. The function is used primarily by s1394_speed_map_fill()
579 * to keep track of which connections need to be set in the speed_map[].
580 * This routine is used only by the h1394_self_ids() interrupt.
582 static void
583 s1394_node_number_list_add(s1394_hal_t *hal, int node_num)
585 if (hal->hal_node_number_list_size >= IEEE1394_MAX_NODES - 1) {
586 return;
589 hal->hal_node_number_list[hal->hal_node_number_list_size] = node_num;
590 hal->hal_node_number_list_size++;
594 * s1394_topology_tree_mark_all_unvisited()
595 * is used to initialize the topology_tree[] prior to tree traversals.
596 * It resets the "visited" flag for each node in the tree.
598 void
599 s1394_topology_tree_mark_all_unvisited(s1394_hal_t *hal)
601 uint_t number_of_nodes;
602 int i;
604 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
606 number_of_nodes = hal->number_of_nodes;
607 for (i = 0; i < number_of_nodes; i++)
608 CLEAR_NODE_VISITED(&hal->topology_tree[i]);
612 * s1394_old_tree_mark_all_unvisited()
613 * is used to initialize the old_tree[] prior to tree traversals. It
614 * resets the "visited" flag for each node in the tree.
616 void
617 s1394_old_tree_mark_all_unvisited(s1394_hal_t *hal)
619 uint_t number_of_nodes;
620 int i;
622 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
624 number_of_nodes = hal->old_number_of_nodes;
625 for (i = 0; i < number_of_nodes; i++)
626 CLEAR_NODE_VISITED(&hal->old_tree[i]);
630 * s1394_old_tree_mark_all_unmatched()
631 * is used to initialize the old_tree[] prior to tree traversals. It
632 * resets the "matched" flag for each node in the tree.
634 void
635 s1394_old_tree_mark_all_unmatched(s1394_hal_t *hal)
637 uint_t number_of_nodes;
638 int i;
640 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
642 number_of_nodes = hal->old_number_of_nodes;
644 for (i = 0; i < number_of_nodes; i++)
645 CLEAR_NODE_MATCHED(&hal->old_tree[i]);
649 * s1394_copy_old_tree()
650 * switches the pointers for old_tree[] and topology_tree[].
652 void
653 s1394_copy_old_tree(s1394_hal_t *hal)
655 s1394_node_t *temp;
657 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
659 temp = hal->old_tree;
660 hal->old_tree = hal->topology_tree;
661 hal->topology_tree = temp;
663 hal->old_number_of_nodes = hal->number_of_nodes;
664 hal->old_node_id = hal->node_id;
665 hal->old_generation_count = hal->generation_count;
667 /* Old tree is now valid and filled also */
668 hal->old_tree_valid = B_TRUE;
673 * s1394_match_tree_nodes()
674 * uses the information contained in the SelfID packets of the nodes in
675 * both the old_tree[] and the topology_tree[] to determine which new
676 * nodes correspond to old nodes. Starting with the local node, we
677 * compare both old and new node's ports. Assuming that only one bus
678 * reset has occurred, any node that was connected to another in the old
679 * bus and is still connected to another in the new bus must be connected
680 * (physically) to the same node. Using this information, we can rebuild
681 * and match the old nodes to new ones. Any nodes which aren't matched
682 * are either departing or arriving nodes and must be handled appropriately.
684 void
685 s1394_match_tree_nodes(s1394_hal_t *hal)
687 s1394_node_t *tmp;
688 uint_t hal_node_num;
689 uint_t hal_node_num_old;
690 int i;
691 int port_type;
693 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
695 /* To ensure that the queue is empty */
696 hal->hal_queue_front = hal->hal_queue_back = 0;
698 /* Set up the first matched nodes (which are our own local nodes) */
699 hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
700 hal_node_num_old = IEEE1394_NODE_NUM(hal->old_node_id);
701 hal->topology_tree[hal_node_num].old_node =
702 &hal->old_tree[hal_node_num_old];
703 hal->old_tree[hal_node_num_old].cur_node =
704 &hal->topology_tree[hal_node_num];
706 /* Put the node on the queue */
707 s1394_hal_queue_insert(hal, &hal->topology_tree[hal_node_num]);
709 /* While the queue is not empty, remove a node */
710 while (hal->hal_queue_front != hal->hal_queue_back) {
711 tmp = (s1394_node_t *)s1394_hal_queue_remove(hal);
713 /* Mark both old and new nodes as "visited" */
714 SET_NODE_VISITED(tmp);
715 SET_NODE_VISITED(tmp->old_node);
716 tmp->old_node->cur_node = tmp;
718 /* Mark old and new nodes as "matched" */
719 SET_NODE_MATCHED(tmp);
720 SET_NODE_MATCHED(tmp->old_node);
721 s1394_copy_cfgrom(tmp, tmp->old_node);
723 /* s1394_copy_cfgrom() clears "matched" for some cases... */
724 if ((tmp->cfgrom != NULL && CONFIG_ROM_GEN(tmp->cfgrom) <= 1) ||
725 NODE_MATCHED(tmp) == B_TRUE) {
726 /* Move the target list over to the new node and update */
727 /* the node info. */
728 s1394_target_t *t;
730 rw_enter(&hal->target_list_rwlock, RW_WRITER);
731 t = tmp->target_list = tmp->old_node->target_list;
732 while (t != NULL) {
733 t->on_node = tmp;
734 t = t->target_sibling;
736 rw_exit(&hal->target_list_rwlock);
739 for (i = 0; i < selfid_num_ports(tmp->selfid_packet); i++) {
740 port_type = selfid_port_type(tmp->selfid_packet, i);
742 /* Is the new port connected? */
743 if ((port_type == IEEE1394_SELFID_PORT_TO_CHILD) ||
744 (port_type == IEEE1394_SELFID_PORT_TO_PARENT)) {
745 port_type = selfid_port_type(
746 tmp->old_node->selfid_packet, i);
748 /* Is the old port connected? */
749 if ((port_type ==
750 IEEE1394_SELFID_PORT_TO_CHILD) ||
751 (port_type ==
752 IEEE1394_SELFID_PORT_TO_PARENT)) {
753 /* Found a match, check if */
754 /* we've already visited it */
755 if (!NODE_VISITED(tmp->phy_port[i])) {
756 tmp->phy_port[i]->old_node =
757 tmp->old_node->phy_port[i];
758 s1394_hal_queue_insert(hal,
759 tmp->phy_port[i]);
768 * s1394_topology_tree_calculate_diameter()
769 * does a depth-first tree traversal, tracking at each branch the first
770 * and second deepest paths though that branch's children. The diameter
771 * is given by the maximum of these over all branch nodes
774 s1394_topology_tree_calculate_diameter(s1394_hal_t *hal)
776 s1394_node_t *current;
777 uint_t number_of_nodes;
778 int i;
779 int start;
780 int end;
781 boolean_t done;
782 boolean_t found_a_child;
783 int distance = 0;
784 int diameter = 0;
785 int local_diameter = 0;
787 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
789 number_of_nodes = hal->number_of_nodes;
791 /* Initialize topology tree */
792 for (i = 0; i < number_of_nodes; i++) {
793 hal->topology_tree[i].max_1st = 0;
794 hal->topology_tree[i].max_2nd = 0;
795 hal->topology_tree[i].last_port_checked = 0;
798 /* Start at the root node */
799 current = s1394_topology_tree_get_root_node(hal);
801 /* Flush the stack before we start */
802 hal->hal_stack_depth = -1;
804 do {
805 done = B_FALSE;
806 found_a_child = B_FALSE;
807 start = current->last_port_checked;
808 end = selfid_num_ports(current->selfid_packet);
810 /* Check every previously unchecked port for children */
811 for (i = start; i < end; i++) {
812 current->last_port_checked++;
813 /* If there is a child push it on the stack */
814 if (selfid_port_type(current->selfid_packet, i) ==
815 IEEE1394_SELFID_PORT_TO_CHILD) {
816 found_a_child = B_TRUE;
817 s1394_hal_stack_push(hal, current);
818 current = current->phy_port[i];
819 break;
823 /* If we reach here and the stack is empty, we're done */
824 if (hal->hal_stack_depth == -1) {
825 done = B_TRUE;
826 continue;
829 /* If no children were found, we're at a leaf */
830 if (found_a_child == B_FALSE) {
831 distance = current->max_1st + 1;
832 /* Pop the child and set the appropriate fields */
833 current = s1394_hal_stack_pop(hal);
834 if (distance > current->max_1st) {
835 current->max_2nd = current->max_1st;
836 current->max_1st = (uchar_t)distance;
838 } else if (distance > current->max_2nd) {
839 current->max_2nd = (uchar_t)distance;
842 /* Update maximum distance (diameter), if necessary */
843 local_diameter = current->max_1st + current->max_2nd;
844 if (local_diameter > diameter)
845 diameter = local_diameter;
847 } while (done == B_FALSE);
849 return (diameter);
853 * s1394_gap_count_optimize()
854 * looks in a table to find the appropriate gap_count for a given diameter.
855 * (See above - gap_count[])
858 s1394_gap_count_optimize(int diameter)
860 if ((diameter >= 0) && (diameter <= MAX_HOPS)) {
861 return (gap_count[diameter]);
862 } else {
863 cmn_err(CE_NOTE, "Too may point-to-point links on the 1394"
864 " bus - If new devices have recently been added, remove"
865 " them.");
866 return (gap_count[MAX_HOPS]);
871 * s1394_get_current_gap_count()
872 * looks at all the SelfID packets to determine the current gap_count on
873 * the 1394 bus. If the gap_counts differ from node to node, it initiates
874 * a bus reset and returns -1.
877 s1394_get_current_gap_count(s1394_hal_t *hal)
879 int i;
880 int gap_count = -1;
882 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
884 /* Grab the first gap_count in the SelfID packets */
885 gap_count = IEEE1394_SELFID_GAP_CNT(hal->selfid_ptrs[0]);
887 /* Compare it too all the rest */
888 for (i = 1; i < hal->number_of_nodes; i++) {
889 if (gap_count !=
890 IEEE1394_SELFID_GAP_CNT(hal->selfid_ptrs[i])) {
892 if (s1394_ignore_invalid_gap_cnt == 0) {
893 /* Initiate a bus reset */
894 s1394_initiate_hal_reset(hal, CRITICAL);
897 return (-1);
901 return (gap_count);
905 * s1394_speed_map_fill()
906 * determines, for each pair of nodes, the maximum speed at which those
907 * nodes can communicate. The speed of each node as well as the speed of
908 * any intermediate nodes on a given path must be accounted for, as the
909 * minimum speed on a given edge determines the maximum speed for all
910 * communications across that edge.
911 * In the method we implement below, a current minimum speed is selected.
912 * With this minimum speed in mind, we create subgraphs of the original
913 * bus which contain only edges that connect two nodes whose speeds are
914 * equal to or greater than the current minimum speed. Then, for each of
915 * the subgraphs, we visit every node, keeping a list of the nodes we've
916 * visited. When this list is completed, we can fill in the entries in
917 * the speed map which correspond to a pairs of these nodes. Doing this
918 * for each subgraph and then for each speed we progressively fill in the
919 * parts of the speed map which weren't previously filled in.
921 void
922 s1394_speed_map_fill(s1394_hal_t *hal)
924 uint_t number_of_nodes;
925 int i;
926 int j;
927 int node_num;
929 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
931 number_of_nodes = hal->number_of_nodes;
932 s1394_speed_map_initialize(hal);
934 /* Mark all speed = IEEE1394_S100 nodes in the Speed Map */
935 for (i = 0; i < number_of_nodes; i++) {
936 if (selfid_speed(hal->topology_tree[i].selfid_packet) ==
937 IEEE1394_S100) {
938 hal->slowest_node_speed = IEEE1394_S100;
939 node_num = IEEE1394_SELFID_PHYID(
940 hal->topology_tree[i].selfid_packet);
941 for (j = 0; j < number_of_nodes; j++) {
942 if (j != node_num) {
943 hal->speed_map[node_num][j] =
944 IEEE1394_S100;
945 hal->speed_map[j][node_num] =
946 IEEE1394_S100;
952 s1394_speed_map_fill_speed_N(hal, IEEE1394_S200);
953 s1394_speed_map_fill_speed_N(hal, IEEE1394_S400);
955 /* Fill in the diagonal */
956 for (i = 0; i < number_of_nodes; i++) {
957 hal->speed_map[i][i] =
958 selfid_speed(hal->topology_tree[i].selfid_packet);
963 * s1394_speed_map_fill_speed_N(),
964 * given a minimum link speed, creates subgraphs of the original bus which
965 * contain only the necessary edges (see speed_map_fill() above). For each
966 * of the subgraphs, it visits and fills in the entries in the speed map
967 * which correspond to a pair of these nodes.
969 static void
970 s1394_speed_map_fill_speed_N(s1394_hal_t *hal, int min_spd)
972 s1394_node_t *tmp;
973 uint_t number_of_nodes;
974 int i;
975 int j;
976 int k;
977 int size;
978 int ix_a, ix_b;
980 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
982 number_of_nodes = hal->number_of_nodes;
984 /* Prepare the topology tree */
985 s1394_topology_tree_mark_all_unvisited(hal);
987 /* To ensure that the queue is empty */
988 hal->hal_queue_front = hal->hal_queue_back = 0;
990 for (i = 0; i < number_of_nodes; i++) {
991 /* If the node's speed == min_spd and it hasn't been visited */
992 if (!NODE_VISITED(&hal->topology_tree[i]) &&
993 (selfid_speed(hal->topology_tree[i].selfid_packet) ==
994 min_spd)) {
996 if (min_spd < hal->slowest_node_speed)
997 hal->slowest_node_speed = (uint8_t)min_spd;
999 SET_NODE_VISITED(&hal->topology_tree[i]);
1000 s1394_hal_queue_insert(hal, &hal->topology_tree[i]);
1002 while (hal->hal_queue_front != hal->hal_queue_back) {
1003 tmp = (s1394_node_t *)s1394_hal_queue_remove(
1004 hal);
1005 /* Add node number to the list */
1006 s1394_node_number_list_add(hal,
1007 IEEE1394_SELFID_PHYID(tmp->selfid_packet));
1009 for (j = 0; j < IEEE1394_MAX_NUM_PORTS; j++) {
1010 if ((tmp->phy_port[j] != NULL) &&
1011 (!NODE_VISITED(tmp->phy_port[j]))) {
1012 if (selfid_speed(
1013 tmp->phy_port[j]->
1014 selfid_packet) >= min_spd) {
1015 SET_NODE_VISITED(
1016 tmp->phy_port[j]);
1017 s1394_hal_queue_insert(
1018 hal,
1019 tmp->phy_port[j]);
1025 /* For each pair, mark speed_map as min_spd */
1026 size = hal->hal_node_number_list_size;
1027 for (j = 0; j < size; j++) {
1028 for (k = 0; k < size; k++) {
1029 if (j != k) {
1030 ix_a = hal->
1031 hal_node_number_list[j];
1032 ix_b = hal->
1033 hal_node_number_list[k];
1034 hal->speed_map[ix_a][ix_b] =
1035 (uint8_t)min_spd;
1040 /* Flush the Node Number List */
1041 hal->hal_node_number_list_size = 0;
1047 * s1394_speed_map_initialize()
1048 * fills in the speed_map with IEEE1394_S100's and SPEED_MAP_INVALID's in
1049 * the appropriate places. These will be overwritten by
1050 * s1394_speed_map_fill().
1052 static void
1053 s1394_speed_map_initialize(s1394_hal_t *hal)
1055 uint_t number_of_nodes;
1056 int i, j;
1058 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1060 number_of_nodes = hal->number_of_nodes;
1061 for (i = 0; i < number_of_nodes; i++) {
1062 for (j = 0; j < number_of_nodes; j++) {
1063 if (i != j)
1064 hal->speed_map[i][j] = IEEE1394_S100;
1065 else
1066 hal->speed_map[i][j] = SPEED_MAP_INVALID;
1072 * s1394_speed_map_get()
1073 * queries the speed_map[] for a given pair of nodes.
1075 uint8_t
1076 s1394_speed_map_get(s1394_hal_t *hal, uint_t from_node, uint_t to_node)
1078 /* If it's not a valid node, then return slowest_node_speed */
1079 if (to_node >= hal->number_of_nodes) {
1080 /* Send at fastest speed everyone will see */
1081 return (hal->slowest_node_speed);
1083 /* else return the correct maximum speed */
1084 return (hal->speed_map[from_node][to_node]);
1088 * s1394_update_speed_map_link_speeds()
1089 * takes into account information from Config ROM queries. Any P1394A
1090 * device can have a link with a different speed than its PHY. In this
1091 * case, the slower speed must be accounted for in order for communication
1092 * with the remote node to work.
1094 void
1095 s1394_update_speed_map_link_speeds(s1394_hal_t *hal)
1097 uint32_t bus_capabilities;
1098 uint8_t link_speed;
1099 uint_t number_of_nodes;
1100 int i, j;
1102 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1104 number_of_nodes = hal->number_of_nodes;
1106 for (i = 0; i < number_of_nodes; i++) {
1108 /* Skip invalid config ROMs */
1109 if (CFGROM_VALID(&hal->topology_tree[i])) {
1111 ASSERT(hal->topology_tree[i].cfgrom);
1113 bus_capabilities = hal->topology_tree[i].
1114 cfgrom[IEEE1212_NODE_CAP_QUAD];
1116 /* Skip if Bus_Info_Block generation is 0 */
1117 /* because it isn't a P1394a device */
1118 if ((bus_capabilities & IEEE1394_BIB_GEN_MASK) != 0) {
1119 link_speed = (bus_capabilities &
1120 IEEE1394_BIB_LNK_SPD_MASK);
1122 for (j = 0; j < number_of_nodes; j++) {
1123 /* Update if link_speed is slower */
1124 if (hal->speed_map[i][j] > link_speed) {
1125 hal->speed_map[i][j] =
1126 link_speed;
1127 hal->speed_map[j][i] =
1128 link_speed;
1131 if (link_speed <
1132 hal->slowest_node_speed)
1133 hal->slowest_node_speed =
1134 link_speed;
1142 * s1394_get_isoch_rsrc_mgr()
1143 * looks at the SelfID packets to determine the Isochronous Resource
1144 * Manager's node ID. The IRM is the highest numbered node with both
1145 * the "L"-bit and the "C"-bit in its SelfID packets turned on. If no
1146 * IRM is found on the bus, then -1 is returned.
1149 s1394_get_isoch_rsrc_mgr(s1394_hal_t *hal)
1151 int i;
1153 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1155 for (i = hal->number_of_nodes - 1; i >= 0; i--) {
1156 /* Highest numbered node with L=1 and C=1 */
1157 if ((IEEE1394_SELFID_ISLINKON(hal->selfid_ptrs[i])) &&
1158 (IEEE1394_SELFID_ISCONTENDER(hal->selfid_ptrs[i]))) {
1160 return (i);
1164 /* No Isochronous Resource Manager */
1165 return (-1);
1169 * s1394_physical_arreq_setup_all()
1170 * is used to enable the physical filters for the link. If a target has
1171 * registered physical space allocations, then the corresponding node's
1172 * bit is set. This is done for all targets on a HAL (usually after bus
1173 * reset).
1175 void
1176 s1394_physical_arreq_setup_all(s1394_hal_t *hal)
1178 s1394_target_t *curr_target;
1179 uint64_t mask = 0;
1180 uint32_t node_num;
1181 uint_t generation;
1183 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1185 mutex_enter(&hal->topology_tree_mutex);
1186 generation = hal->generation_count;
1187 rw_enter(&hal->target_list_rwlock, RW_READER);
1189 curr_target = hal->target_head;
1190 while (curr_target != NULL) {
1191 if ((curr_target->on_node != NULL) &&
1192 (curr_target->physical_arreq_enabled != 0)) {
1193 node_num = curr_target->on_node->node_num;
1194 mask = mask | (1 << node_num);
1196 curr_target = curr_target->target_next;
1198 rw_exit(&hal->target_list_rwlock);
1199 mutex_exit(&hal->topology_tree_mutex);
1202 * Since it is cleared to 0 on bus reset, set the bits for all
1203 * nodes. This call returns DDI_FAILURE if the generation passed
1204 * is invalid or if the HAL is shutdown. In either case, it is
1205 * acceptable to simply ignore the result and return.
1207 (void) HAL_CALL(hal).physical_arreq_enable_set(
1208 hal->halinfo.hal_private, mask, generation);
1212 * s1394_physical_arreq_set_one()
1213 * is used to enable the physical filters for the link. If a target has
1214 * registered physical space allocations, then the corresponding node's
1215 * bit is set. This is done for one target.
1217 void
1218 s1394_physical_arreq_set_one(s1394_target_t *target)
1220 s1394_hal_t *hal;
1221 uint64_t mask = 0;
1222 uint32_t node_num;
1223 uint_t generation;
1225 /* Find the HAL this target resides on */
1226 hal = target->on_hal;
1228 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1230 mutex_enter(&hal->topology_tree_mutex);
1231 rw_enter(&hal->target_list_rwlock, RW_READER);
1233 if ((target->on_node != NULL) &&
1234 (target->physical_arreq_enabled != 0)) {
1235 node_num = target->on_node->node_num;
1236 mask = mask | (1 << node_num);
1238 generation = hal->generation_count;
1240 rw_exit(&hal->target_list_rwlock);
1241 mutex_exit(&hal->topology_tree_mutex);
1244 * Set the bit corresponding to this node. This call
1245 * returns DDI_FAILURE if the generation passed
1246 * is invalid or if the HAL is shutdown. In either case,
1247 * it is acceptable to simply ignore the result and return.
1249 (void) HAL_CALL(hal).physical_arreq_enable_set(
1250 hal->halinfo.hal_private, mask, generation);
1251 } else {
1252 rw_exit(&hal->target_list_rwlock);
1253 mutex_exit(&hal->topology_tree_mutex);
1258 * s1394_physical_arreq_clear_one()
1259 * is used to disable the physical filters for OpenHCI. If a target frees
1260 * up the last of its registered physical space, then the corresponding
1261 * node's bit is cleared. This is done for one target.
1263 void
1264 s1394_physical_arreq_clear_one(s1394_target_t *target)
1266 s1394_hal_t *hal;
1267 uint64_t mask = 0;
1268 uint32_t node_num;
1269 uint_t generation;
1271 /* Find the HAL this target resides on */
1272 hal = target->on_hal;
1274 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1276 mutex_enter(&hal->topology_tree_mutex);
1277 rw_enter(&hal->target_list_rwlock, RW_READER);
1279 if ((target->on_node != NULL) &&
1280 (target->physical_arreq_enabled == 0)) {
1281 node_num = target->on_node->node_num;
1282 mask = mask | (1 << node_num);
1284 generation = hal->generation_count;
1286 rw_exit(&hal->target_list_rwlock);
1287 mutex_exit(&hal->topology_tree_mutex);
1290 * Set the bit corresponding to this node. This call
1291 * returns DDI_FAILURE if the generation passed
1292 * is invalid or if the HAL is shutdown. In either case,
1293 * it is acceptable to simply ignore the result and return.
1295 (void) HAL_CALL(hal).physical_arreq_enable_clr(
1296 hal->halinfo.hal_private, mask, generation);
1297 } else {
1298 rw_exit(&hal->target_list_rwlock);
1299 mutex_exit(&hal->topology_tree_mutex);
1304 * s1394_topology_tree_get_root_node()
1305 * returns the last entry in topology_tree[] as this must always be the
1306 * root node.
1308 s1394_node_t *
1309 s1394_topology_tree_get_root_node(s1394_hal_t *hal)
1311 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1313 return (&hal->topology_tree[hal->number_of_nodes - 1]);