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