xref: /freebsd/contrib/ofed/opensm/opensm/osm_torus.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright 2009 Sandia Corporation.  Under the terms of Contract
3*d6b92ffaSHans Petter Selasky  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
4*d6b92ffaSHans Petter Selasky  * certain rights in this software.
5*d6b92ffaSHans Petter Selasky  * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
6*d6b92ffaSHans Petter Selasky  * Copyright (c) 2010-2012 Mellanox Technologies LTD. All rights reserved.
7*d6b92ffaSHans Petter Selasky  *
8*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
9*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
10*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
11*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
12*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
13*d6b92ffaSHans Petter Selasky  *
14*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
15*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
16*d6b92ffaSHans Petter Selasky  *     conditions are met:
17*d6b92ffaSHans Petter Selasky  *
18*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
19*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20*d6b92ffaSHans Petter Selasky  *        disclaimer.
21*d6b92ffaSHans Petter Selasky  *
22*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
23*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
24*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
25*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
26*d6b92ffaSHans Petter Selasky  *
27*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34*d6b92ffaSHans Petter Selasky  * SOFTWARE.
35*d6b92ffaSHans Petter Selasky  *
36*d6b92ffaSHans Petter Selasky  */
37*d6b92ffaSHans Petter Selasky 
38*d6b92ffaSHans Petter Selasky #define	_WITH_GETLINE	/* for getline() */
39*d6b92ffaSHans Petter Selasky #include <stdint.h>
40*d6b92ffaSHans Petter Selasky #include <stdbool.h>
41*d6b92ffaSHans Petter Selasky #include <stdlib.h>
42*d6b92ffaSHans Petter Selasky #include <stdio.h>
43*d6b92ffaSHans Petter Selasky #include <unistd.h>
44*d6b92ffaSHans Petter Selasky #include <errno.h>
45*d6b92ffaSHans Petter Selasky #include <string.h>
46*d6b92ffaSHans Petter Selasky 
47*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
48*d6b92ffaSHans Petter Selasky #  include <config.h>
49*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
50*d6b92ffaSHans Petter Selasky 
51*d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
52*d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_TORUS_C
53*d6b92ffaSHans Petter Selasky #include <opensm/osm_log.h>
54*d6b92ffaSHans Petter Selasky #include <opensm/osm_port.h>
55*d6b92ffaSHans Petter Selasky #include <opensm/osm_switch.h>
56*d6b92ffaSHans Petter Selasky #include <opensm/osm_node.h>
57*d6b92ffaSHans Petter Selasky #include <opensm/osm_opensm.h>
58*d6b92ffaSHans Petter Selasky 
59*d6b92ffaSHans Petter Selasky #define TORUS_MAX_DIM        3
60*d6b92ffaSHans Petter Selasky #define PORTGRP_MAX_PORTS    16
61*d6b92ffaSHans Petter Selasky #define SWITCH_MAX_PORTGRPS  (1 + 2 * TORUS_MAX_DIM)
62*d6b92ffaSHans Petter Selasky #define DEFAULT_MAX_CHANGES  32
63*d6b92ffaSHans Petter Selasky 
64*d6b92ffaSHans Petter Selasky #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
65*d6b92ffaSHans Petter Selasky 
66*d6b92ffaSHans Petter Selasky typedef ib_net64_t guid_t;
67*d6b92ffaSHans Petter Selasky 
68*d6b92ffaSHans Petter Selasky /*
69*d6b92ffaSHans Petter Selasky  * An endpoint terminates a link, and is one of three types:
70*d6b92ffaSHans Petter Selasky  *   UNKNOWN  - Uninitialized endpoint.
71*d6b92ffaSHans Petter Selasky  *   SRCSINK  - generates or consumes traffic, and thus has an associated LID;
72*d6b92ffaSHans Petter Selasky  *		  i.e. a CA or router port.
73*d6b92ffaSHans Petter Selasky  *   PASSTHRU - Has no associated LID; i.e. a switch port.
74*d6b92ffaSHans Petter Selasky  *
75*d6b92ffaSHans Petter Selasky  * If it is possible to communicate in-band with a switch, it will require
76*d6b92ffaSHans Petter Selasky  * a port with a GUID in the switch to source/sink that traffic, but there
77*d6b92ffaSHans Petter Selasky  * will be no attached link.  This code assumes there is only one such port.
78*d6b92ffaSHans Petter Selasky  *
79*d6b92ffaSHans Petter Selasky  * Here is an endpoint taxonomy:
80*d6b92ffaSHans Petter Selasky  *
81*d6b92ffaSHans Petter Selasky  *   type == SRCSINK
82*d6b92ffaSHans Petter Selasky  *   link == pointer to a valid struct link
83*d6b92ffaSHans Petter Selasky  *     ==> This endpoint is a CA or router port connected via a link to
84*d6b92ffaSHans Petter Selasky  *	     either a switch or another CA/router.  Thus:
85*d6b92ffaSHans Petter Selasky  *	   n_id ==> identifies the CA/router node GUID
86*d6b92ffaSHans Petter Selasky  *	   sw   ==> NULL
87*d6b92ffaSHans Petter Selasky  *	   port ==> identifies the port on the CA/router this endpoint uses
88*d6b92ffaSHans Petter Selasky  *	   pgrp ==> NULL
89*d6b92ffaSHans Petter Selasky  *
90*d6b92ffaSHans Petter Selasky  *   type == SRCSINK
91*d6b92ffaSHans Petter Selasky  *   link == NULL pointer
92*d6b92ffaSHans Petter Selasky  *     ==> This endpoint is the switch port used for in-band communication
93*d6b92ffaSHans Petter Selasky  *	     with the switch itself.  Thus:
94*d6b92ffaSHans Petter Selasky  *	   n_id ==> identifies the node GUID used to talk to the switch
95*d6b92ffaSHans Petter Selasky  *		      containing this endpoint
96*d6b92ffaSHans Petter Selasky  *	   sw   ==> pointer to valid struct switch containing this endpoint
97*d6b92ffaSHans Petter Selasky  *	   port ==> identifies the port on the switch this endpoint uses
98*d6b92ffaSHans Petter Selasky  *	   pgrp ==> NULL, or pointer to the valid struct port_grp holding
99*d6b92ffaSHans Petter Selasky  *		      the port in a t_switch.
100*d6b92ffaSHans Petter Selasky  *
101*d6b92ffaSHans Petter Selasky  *   type == PASSTHRU
102*d6b92ffaSHans Petter Selasky  *   link == pointer to valid struct link
103*d6b92ffaSHans Petter Selasky  *     ==> This endpoint is a switch port connected via a link to either
104*d6b92ffaSHans Petter Selasky  *	     another switch or a CA/router.  Thus:
105*d6b92ffaSHans Petter Selasky  *	   n_id ==> identifies the node GUID used to talk to the switch
106*d6b92ffaSHans Petter Selasky  *		      containing this endpoint - since each switch is assumed
107*d6b92ffaSHans Petter Selasky  *		      to have only one in-band communication port, this is a
108*d6b92ffaSHans Petter Selasky  *		      convenient unique name for the switch itself.
109*d6b92ffaSHans Petter Selasky  *	   sw   ==> pointer to valid struct switch containing this endpoint,
110*d6b92ffaSHans Petter Selasky  *		      or NULL, in the case of a fabric link that has been
111*d6b92ffaSHans Petter Selasky  *		      disconnected after being transferred to a torus link.
112*d6b92ffaSHans Petter Selasky  *	   port ==> identifies the port on the switch this endpoint uses.
113*d6b92ffaSHans Petter Selasky  *		      Note that in the special case of the coordinate direction
114*d6b92ffaSHans Petter Selasky  *		      links, the port value is -1, as those links aren't
115*d6b92ffaSHans Petter Selasky  *		      really connected to anything.
116*d6b92ffaSHans Petter Selasky  *	   pgrp ==> NULL, or pointer to the valid struct port_grp holding
117*d6b92ffaSHans Petter Selasky  *		      the port in a t_switch.
118*d6b92ffaSHans Petter Selasky  */
119*d6b92ffaSHans Petter Selasky enum endpt_type { UNKNOWN = 0, SRCSINK, PASSTHRU };
120*d6b92ffaSHans Petter Selasky struct torus;
121*d6b92ffaSHans Petter Selasky struct t_switch;
122*d6b92ffaSHans Petter Selasky struct port_grp;
123*d6b92ffaSHans Petter Selasky 
124*d6b92ffaSHans Petter Selasky struct endpoint {
125*d6b92ffaSHans Petter Selasky 	enum endpt_type type;
126*d6b92ffaSHans Petter Selasky 	int port;
127*d6b92ffaSHans Petter Selasky 	guid_t n_id;		/* IBA node GUID */
128*d6b92ffaSHans Petter Selasky 	void *sw;		/* void* can point to either switch type */
129*d6b92ffaSHans Petter Selasky 	struct link *link;
130*d6b92ffaSHans Petter Selasky 	struct port_grp *pgrp;
131*d6b92ffaSHans Petter Selasky 	void *tmp;
132*d6b92ffaSHans Petter Selasky 	/*
133*d6b92ffaSHans Petter Selasky 	 * Note: osm_port is only guaranteed to contain a valid pointer
134*d6b92ffaSHans Petter Selasky 	 * when the call stack contains torus_build_lfts() or
135*d6b92ffaSHans Petter Selasky 	 * osm_port_relink_endpoint().
136*d6b92ffaSHans Petter Selasky 	 *
137*d6b92ffaSHans Petter Selasky 	 * Otherwise, the opensm core could have deleted an osm_port object
138*d6b92ffaSHans Petter Selasky 	 * without notifying us, invalidating the pointer we hold.
139*d6b92ffaSHans Petter Selasky 	 *
140*d6b92ffaSHans Petter Selasky 	 * When presented with a pointer to an osm_port_t, it is generally
141*d6b92ffaSHans Petter Selasky 	 * safe and required to cast osm_port_t:priv to struct endpoint, and
142*d6b92ffaSHans Petter Selasky 	 * check that the endpoint's osm_port is the same as the original
143*d6b92ffaSHans Petter Selasky 	 * osm_port_t pointer.  Failure to do so means that invalidated
144*d6b92ffaSHans Petter Selasky 	 * pointers will go undetected.
145*d6b92ffaSHans Petter Selasky 	 */
146*d6b92ffaSHans Petter Selasky 	struct osm_port *osm_port;
147*d6b92ffaSHans Petter Selasky };
148*d6b92ffaSHans Petter Selasky 
149*d6b92ffaSHans Petter Selasky struct link {
150*d6b92ffaSHans Petter Selasky 	struct endpoint end[2];
151*d6b92ffaSHans Petter Selasky };
152*d6b92ffaSHans Petter Selasky 
153*d6b92ffaSHans Petter Selasky /*
154*d6b92ffaSHans Petter Selasky  * A port group is a collection of endpoints on a switch that share certain
155*d6b92ffaSHans Petter Selasky  * characteristics.  All the endpoints in a port group must have the same
156*d6b92ffaSHans Petter Selasky  * type.  Furthermore, if that type is PASSTHRU, then the connected links:
157*d6b92ffaSHans Petter Selasky  *   1) are parallel to a given coordinate direction
158*d6b92ffaSHans Petter Selasky  *   2) share the same two switches as endpoints.
159*d6b92ffaSHans Petter Selasky  *
160*d6b92ffaSHans Petter Selasky  * Torus-2QoS uses one master spanning tree for multicast, of which every
161*d6b92ffaSHans Petter Selasky  * multicast group spanning tree is a subtree.  to_stree_root is a pointer
162*d6b92ffaSHans Petter Selasky  * to the next port_grp on the path to the master spanning tree root.
163*d6b92ffaSHans Petter Selasky  * to_stree_tip is a pointer to the next port_grp on the path to a master
164*d6b92ffaSHans Petter Selasky  * spanning tree branch tip.
165*d6b92ffaSHans Petter Selasky  *
166*d6b92ffaSHans Petter Selasky  * Each t_switch can have at most one port_grp with a non-NULL to_stree_root.
167*d6b92ffaSHans Petter Selasky  * Exactly one t_switch in the fabric will have all port_grp objects with
168*d6b92ffaSHans Petter Selasky  * to_stree_root NULL; it is the master spanning tree root.
169*d6b92ffaSHans Petter Selasky  *
170*d6b92ffaSHans Petter Selasky  * A t_switch with all port_grp objects where to_stree_tip is NULL is at a
171*d6b92ffaSHans Petter Selasky  * master spanning tree branch tip.
172*d6b92ffaSHans Petter Selasky  */
173*d6b92ffaSHans Petter Selasky struct port_grp {
174*d6b92ffaSHans Petter Selasky 	enum endpt_type type;
175*d6b92ffaSHans Petter Selasky 	size_t port_cnt;	/* number of attached ports in group */
176*d6b92ffaSHans Petter Selasky 	size_t port_grp;	/* what switch port_grp we're in */
177*d6b92ffaSHans Petter Selasky 	unsigned sw_dlid_cnt;	/* switch dlids routed through this group */
178*d6b92ffaSHans Petter Selasky 	unsigned ca_dlid_cnt;	/* CA dlids routed through this group */
179*d6b92ffaSHans Petter Selasky 	struct t_switch *sw;	/* what switch we're attached to */
180*d6b92ffaSHans Petter Selasky 	struct port_grp *to_stree_root;
181*d6b92ffaSHans Petter Selasky 	struct port_grp *to_stree_tip;
182*d6b92ffaSHans Petter Selasky 	struct endpoint **port;
183*d6b92ffaSHans Petter Selasky };
184*d6b92ffaSHans Petter Selasky 
185*d6b92ffaSHans Petter Selasky /*
186*d6b92ffaSHans Petter Selasky  * A struct t_switch is used to represent a switch as placed in a torus.
187*d6b92ffaSHans Petter Selasky  *
188*d6b92ffaSHans Petter Selasky  * A t_switch used to build an N-dimensional torus will have 2N+1 port groups,
189*d6b92ffaSHans Petter Selasky  * used as follows, assuming 0 <= d < N:
190*d6b92ffaSHans Petter Selasky  *   port_grp[2d]   => links leaving in negative direction for coordinate d
191*d6b92ffaSHans Petter Selasky  *   port_grp[2d+1] => links leaving in positive direction for coordinate d
192*d6b92ffaSHans Petter Selasky  *   port_grp[2N]   => endpoints local to switch; i.e., hosts on switch
193*d6b92ffaSHans Petter Selasky  *
194*d6b92ffaSHans Petter Selasky  * struct link objects referenced by a t_switch are assumed to be oriented:
195*d6b92ffaSHans Petter Selasky  * traversing a link from link.end[0] to link.end[1] is always in the positive
196*d6b92ffaSHans Petter Selasky  * coordinate direction.
197*d6b92ffaSHans Petter Selasky  */
198*d6b92ffaSHans Petter Selasky struct t_switch {
199*d6b92ffaSHans Petter Selasky 	guid_t n_id;		/* IBA node GUID */
200*d6b92ffaSHans Petter Selasky 	int i, j, k;
201*d6b92ffaSHans Petter Selasky 	unsigned port_cnt;	/* including management port */
202*d6b92ffaSHans Petter Selasky 	struct torus *torus;
203*d6b92ffaSHans Petter Selasky 	void *tmp;
204*d6b92ffaSHans Petter Selasky 	/*
205*d6b92ffaSHans Petter Selasky 	 * Note: osm_switch is only guaranteed to contain a valid pointer
206*d6b92ffaSHans Petter Selasky 	 * when the call stack contains torus_build_lfts().
207*d6b92ffaSHans Petter Selasky 	 *
208*d6b92ffaSHans Petter Selasky 	 * Otherwise, the opensm core could have deleted an osm_switch object
209*d6b92ffaSHans Petter Selasky 	 * without notifying us, invalidating the pointer we hold.
210*d6b92ffaSHans Petter Selasky 	 *
211*d6b92ffaSHans Petter Selasky 	 * When presented with a pointer to an osm_switch_t, it is generally
212*d6b92ffaSHans Petter Selasky 	 * safe and required to cast osm_switch_t:priv to struct t_switch, and
213*d6b92ffaSHans Petter Selasky 	 * check that the switch's osm_switch is the same as the original
214*d6b92ffaSHans Petter Selasky 	 * osm_switch_t pointer.  Failure to do so means that invalidated
215*d6b92ffaSHans Petter Selasky 	 * pointers will go undetected.
216*d6b92ffaSHans Petter Selasky 	 */
217*d6b92ffaSHans Petter Selasky 	struct osm_switch *osm_switch;
218*d6b92ffaSHans Petter Selasky 
219*d6b92ffaSHans Petter Selasky 	struct port_grp ptgrp[SWITCH_MAX_PORTGRPS];
220*d6b92ffaSHans Petter Selasky 	struct endpoint **port;
221*d6b92ffaSHans Petter Selasky };
222*d6b92ffaSHans Petter Selasky 
223*d6b92ffaSHans Petter Selasky /*
224*d6b92ffaSHans Petter Selasky  * We'd like to be able to discover the torus topology in a pile of switch
225*d6b92ffaSHans Petter Selasky  * links if we can.  We'll use a struct f_switch to store raw topology for a
226*d6b92ffaSHans Petter Selasky  * fabric description, then contruct the torus topology from struct t_switch
227*d6b92ffaSHans Petter Selasky  * objects as we process the fabric and recover it.
228*d6b92ffaSHans Petter Selasky  */
229*d6b92ffaSHans Petter Selasky struct f_switch {
230*d6b92ffaSHans Petter Selasky 	guid_t n_id;		/* IBA node GUID */
231*d6b92ffaSHans Petter Selasky 	unsigned port_cnt;	/* including management port */
232*d6b92ffaSHans Petter Selasky 	void *tmp;
233*d6b92ffaSHans Petter Selasky 	/*
234*d6b92ffaSHans Petter Selasky 	 * Same rules apply here as for a struct t_switch member osm_switch.
235*d6b92ffaSHans Petter Selasky 	 */
236*d6b92ffaSHans Petter Selasky 	struct osm_switch *osm_switch;
237*d6b92ffaSHans Petter Selasky 	struct endpoint **port;
238*d6b92ffaSHans Petter Selasky };
239*d6b92ffaSHans Petter Selasky 
240*d6b92ffaSHans Petter Selasky struct fabric {
241*d6b92ffaSHans Petter Selasky 	osm_opensm_t *osm;
242*d6b92ffaSHans Petter Selasky 	unsigned ca_cnt;
243*d6b92ffaSHans Petter Selasky 	unsigned link_cnt;
244*d6b92ffaSHans Petter Selasky 	unsigned switch_cnt;
245*d6b92ffaSHans Petter Selasky 
246*d6b92ffaSHans Petter Selasky 	unsigned link_cnt_max;
247*d6b92ffaSHans Petter Selasky 	unsigned switch_cnt_max;
248*d6b92ffaSHans Petter Selasky 
249*d6b92ffaSHans Petter Selasky 	struct link **link;
250*d6b92ffaSHans Petter Selasky 	struct f_switch **sw;
251*d6b92ffaSHans Petter Selasky };
252*d6b92ffaSHans Petter Selasky 
253*d6b92ffaSHans Petter Selasky struct coord_dirs {
254*d6b92ffaSHans Petter Selasky 	/*
255*d6b92ffaSHans Petter Selasky 	 * These links define the coordinate directions for the torus.
256*d6b92ffaSHans Petter Selasky 	 * They are duplicates of links connected to switches.  Each of
257*d6b92ffaSHans Petter Selasky 	 * these links must connect to a common switch.
258*d6b92ffaSHans Petter Selasky 	 *
259*d6b92ffaSHans Petter Selasky 	 * In the event that a failed switch was specified as one of these
260*d6b92ffaSHans Petter Selasky 	 * link endpoints, our algorithm would not be able to find the
261*d6b92ffaSHans Petter Selasky 	 * torus in the fabric.  So, we'll allow multiple instances of
262*d6b92ffaSHans Petter Selasky 	 * this in the config file to allow improved resiliency.
263*d6b92ffaSHans Petter Selasky 	 */
264*d6b92ffaSHans Petter Selasky 	struct link xm_link, ym_link, zm_link;
265*d6b92ffaSHans Petter Selasky 	struct link xp_link, yp_link, zp_link;
266*d6b92ffaSHans Petter Selasky 	/*
267*d6b92ffaSHans Petter Selasky 	 * A torus dimension has coordinate values 0, 1, ..., radix - 1.
268*d6b92ffaSHans Petter Selasky 	 * The dateline, where we need to change VLs to avoid credit loops,
269*d6b92ffaSHans Petter Selasky 	 * for a torus dimension is always between coordinate values
270*d6b92ffaSHans Petter Selasky 	 * radix - 1 and 0.  The following specify the dateline location
271*d6b92ffaSHans Petter Selasky 	 * relative to the coordinate links shared switch location.
272*d6b92ffaSHans Petter Selasky 	 *
273*d6b92ffaSHans Petter Selasky 	 * E.g. if the shared switch is at 0,0,0, the following are all
274*d6b92ffaSHans Petter Selasky 	 * zero; if the shared switch is at 1,1,1, the following are all
275*d6b92ffaSHans Petter Selasky 	 * -1, etc.
276*d6b92ffaSHans Petter Selasky 	 *
277*d6b92ffaSHans Petter Selasky 	 * Since our SL/VL assignment for a path depends on the position
278*d6b92ffaSHans Petter Selasky 	 * of the path endpoints relative to the torus datelines, we need
279*d6b92ffaSHans Petter Selasky 	 * this information to keep SL/VL assignment constant in the event
280*d6b92ffaSHans Petter Selasky 	 * one of the switches used to specify coordinate directions fails.
281*d6b92ffaSHans Petter Selasky 	 */
282*d6b92ffaSHans Petter Selasky 	int x_dateline, y_dateline, z_dateline;
283*d6b92ffaSHans Petter Selasky };
284*d6b92ffaSHans Petter Selasky 
285*d6b92ffaSHans Petter Selasky struct torus {
286*d6b92ffaSHans Petter Selasky 	osm_opensm_t *osm;
287*d6b92ffaSHans Petter Selasky 	unsigned ca_cnt;
288*d6b92ffaSHans Petter Selasky 	unsigned link_cnt;
289*d6b92ffaSHans Petter Selasky 	unsigned switch_cnt;
290*d6b92ffaSHans Petter Selasky 	unsigned seed_cnt, seed_idx;
291*d6b92ffaSHans Petter Selasky 	unsigned x_sz, y_sz, z_sz;
292*d6b92ffaSHans Petter Selasky 
293*d6b92ffaSHans Petter Selasky 	unsigned port_order[IB_NODE_NUM_PORTS_MAX+1];
294*d6b92ffaSHans Petter Selasky 
295*d6b92ffaSHans Petter Selasky 	unsigned sw_pool_sz;
296*d6b92ffaSHans Petter Selasky 	unsigned link_pool_sz;
297*d6b92ffaSHans Petter Selasky 	unsigned seed_sz;
298*d6b92ffaSHans Petter Selasky 	unsigned portgrp_sz;	/* max ports for port groups in this torus */
299*d6b92ffaSHans Petter Selasky 
300*d6b92ffaSHans Petter Selasky 	struct fabric *fabric;
301*d6b92ffaSHans Petter Selasky 	struct t_switch **sw_pool;
302*d6b92ffaSHans Petter Selasky 	struct link *link_pool;
303*d6b92ffaSHans Petter Selasky 
304*d6b92ffaSHans Petter Selasky 	struct coord_dirs *seed;
305*d6b92ffaSHans Petter Selasky 	struct t_switch ****sw;
306*d6b92ffaSHans Petter Selasky 	struct t_switch *master_stree_root;
307*d6b92ffaSHans Petter Selasky 
308*d6b92ffaSHans Petter Selasky 	unsigned flags;
309*d6b92ffaSHans Petter Selasky 	unsigned max_changes;
310*d6b92ffaSHans Petter Selasky 	int debug;
311*d6b92ffaSHans Petter Selasky };
312*d6b92ffaSHans Petter Selasky 
313*d6b92ffaSHans Petter Selasky /*
314*d6b92ffaSHans Petter Selasky  * Bits to use in torus.flags
315*d6b92ffaSHans Petter Selasky  */
316*d6b92ffaSHans Petter Selasky #define X_MESH (1U << 0)
317*d6b92ffaSHans Petter Selasky #define Y_MESH (1U << 1)
318*d6b92ffaSHans Petter Selasky #define Z_MESH (1U << 2)
319*d6b92ffaSHans Petter Selasky #define MSG_DEADLOCK (1U << 29)
320*d6b92ffaSHans Petter Selasky #define NOTIFY_CHANGES (1U << 30)
321*d6b92ffaSHans Petter Selasky 
322*d6b92ffaSHans Petter Selasky #define ALL_MESH(flags) \
323*d6b92ffaSHans Petter Selasky 	((flags & (X_MESH | Y_MESH | Z_MESH)) == (X_MESH | Y_MESH | Z_MESH))
324*d6b92ffaSHans Petter Selasky 
325*d6b92ffaSHans Petter Selasky 
326*d6b92ffaSHans Petter Selasky struct torus_context {
327*d6b92ffaSHans Petter Selasky 	osm_opensm_t *osm;
328*d6b92ffaSHans Petter Selasky 	struct torus *torus;
329*d6b92ffaSHans Petter Selasky 	struct fabric fabric;
330*d6b92ffaSHans Petter Selasky };
331*d6b92ffaSHans Petter Selasky 
332*d6b92ffaSHans Petter Selasky static
teardown_fabric(struct fabric * f)333*d6b92ffaSHans Petter Selasky void teardown_fabric(struct fabric *f)
334*d6b92ffaSHans Petter Selasky {
335*d6b92ffaSHans Petter Selasky 	unsigned l, p, s;
336*d6b92ffaSHans Petter Selasky 	struct endpoint *port;
337*d6b92ffaSHans Petter Selasky 	struct f_switch *sw;
338*d6b92ffaSHans Petter Selasky 
339*d6b92ffaSHans Petter Selasky 	if (!f)
340*d6b92ffaSHans Petter Selasky 		return;
341*d6b92ffaSHans Petter Selasky 
342*d6b92ffaSHans Petter Selasky 	if (f->sw) {
343*d6b92ffaSHans Petter Selasky 		/*
344*d6b92ffaSHans Petter Selasky 		 * Need to free switches, and also find/free the endpoints
345*d6b92ffaSHans Petter Selasky 		 * we allocated for switch management ports.
346*d6b92ffaSHans Petter Selasky 		 */
347*d6b92ffaSHans Petter Selasky 		for (s = 0; s < f->switch_cnt; s++) {
348*d6b92ffaSHans Petter Selasky 			sw = f->sw[s];
349*d6b92ffaSHans Petter Selasky 			if (!sw)
350*d6b92ffaSHans Petter Selasky 				continue;
351*d6b92ffaSHans Petter Selasky 
352*d6b92ffaSHans Petter Selasky 			for (p = 0; p < sw->port_cnt; p++) {
353*d6b92ffaSHans Petter Selasky 				port = sw->port[p];
354*d6b92ffaSHans Petter Selasky 				if (port && !port->link)
355*d6b92ffaSHans Petter Selasky 					free(port);	/* management port */
356*d6b92ffaSHans Petter Selasky 			}
357*d6b92ffaSHans Petter Selasky 			free(sw);
358*d6b92ffaSHans Petter Selasky 		}
359*d6b92ffaSHans Petter Selasky 		free(f->sw);
360*d6b92ffaSHans Petter Selasky 	}
361*d6b92ffaSHans Petter Selasky 	if (f->link) {
362*d6b92ffaSHans Petter Selasky 		for (l = 0; l < f->link_cnt; l++)
363*d6b92ffaSHans Petter Selasky 			if (f->link[l])
364*d6b92ffaSHans Petter Selasky 				free(f->link[l]);
365*d6b92ffaSHans Petter Selasky 
366*d6b92ffaSHans Petter Selasky 		free(f->link);
367*d6b92ffaSHans Petter Selasky 	}
368*d6b92ffaSHans Petter Selasky 	memset(f, 0, sizeof(*f));
369*d6b92ffaSHans Petter Selasky }
370*d6b92ffaSHans Petter Selasky 
teardown_torus(struct torus * t)371*d6b92ffaSHans Petter Selasky void teardown_torus(struct torus *t)
372*d6b92ffaSHans Petter Selasky {
373*d6b92ffaSHans Petter Selasky 	unsigned p, s;
374*d6b92ffaSHans Petter Selasky 	struct endpoint *port;
375*d6b92ffaSHans Petter Selasky 	struct t_switch *sw;
376*d6b92ffaSHans Petter Selasky 
377*d6b92ffaSHans Petter Selasky 	if (!t)
378*d6b92ffaSHans Petter Selasky 		return;
379*d6b92ffaSHans Petter Selasky 
380*d6b92ffaSHans Petter Selasky 	if (t->sw_pool) {
381*d6b92ffaSHans Petter Selasky 		/*
382*d6b92ffaSHans Petter Selasky 		 * Need to free switches, and also find/free the endpoints
383*d6b92ffaSHans Petter Selasky 		 * we allocated for switch management ports.
384*d6b92ffaSHans Petter Selasky 		 */
385*d6b92ffaSHans Petter Selasky 		for (s = 0; s < t->switch_cnt; s++) {
386*d6b92ffaSHans Petter Selasky 			sw = t->sw_pool[s];
387*d6b92ffaSHans Petter Selasky 			if (!sw)
388*d6b92ffaSHans Petter Selasky 				continue;
389*d6b92ffaSHans Petter Selasky 
390*d6b92ffaSHans Petter Selasky 			for (p = 0; p < sw->port_cnt; p++) {
391*d6b92ffaSHans Petter Selasky 				port = sw->port[p];
392*d6b92ffaSHans Petter Selasky 				if (port && !port->link)
393*d6b92ffaSHans Petter Selasky 					free(port);	/* management port */
394*d6b92ffaSHans Petter Selasky 			}
395*d6b92ffaSHans Petter Selasky 			free(sw);
396*d6b92ffaSHans Petter Selasky 		}
397*d6b92ffaSHans Petter Selasky 		free(t->sw_pool);
398*d6b92ffaSHans Petter Selasky 	}
399*d6b92ffaSHans Petter Selasky 	if (t->link_pool)
400*d6b92ffaSHans Petter Selasky 		free(t->link_pool);
401*d6b92ffaSHans Petter Selasky 
402*d6b92ffaSHans Petter Selasky 	if (t->sw)
403*d6b92ffaSHans Petter Selasky 		free(t->sw);
404*d6b92ffaSHans Petter Selasky 
405*d6b92ffaSHans Petter Selasky 	if (t->seed)
406*d6b92ffaSHans Petter Selasky 		free(t->seed);
407*d6b92ffaSHans Petter Selasky 
408*d6b92ffaSHans Petter Selasky 	free(t);
409*d6b92ffaSHans Petter Selasky }
410*d6b92ffaSHans Petter Selasky 
411*d6b92ffaSHans Petter Selasky static
torus_context_create(osm_opensm_t * osm)412*d6b92ffaSHans Petter Selasky struct torus_context *torus_context_create(osm_opensm_t *osm)
413*d6b92ffaSHans Petter Selasky {
414*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx;
415*d6b92ffaSHans Petter Selasky 
416*d6b92ffaSHans Petter Selasky 	ctx = calloc(1, sizeof(*ctx));
417*d6b92ffaSHans Petter Selasky 	if (ctx)
418*d6b92ffaSHans Petter Selasky 		ctx->osm = osm;
419*d6b92ffaSHans Petter Selasky 	else
420*d6b92ffaSHans Petter Selasky 		OSM_LOG(&osm->log, OSM_LOG_ERROR,
421*d6b92ffaSHans Petter Selasky 			"ERR 4E01: calloc: %s\n", strerror(errno));
422*d6b92ffaSHans Petter Selasky 
423*d6b92ffaSHans Petter Selasky 	return ctx;
424*d6b92ffaSHans Petter Selasky }
425*d6b92ffaSHans Petter Selasky 
426*d6b92ffaSHans Petter Selasky static
torus_context_delete(void * context)427*d6b92ffaSHans Petter Selasky void torus_context_delete(void *context)
428*d6b92ffaSHans Petter Selasky {
429*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx = context;
430*d6b92ffaSHans Petter Selasky 
431*d6b92ffaSHans Petter Selasky 	teardown_fabric(&ctx->fabric);
432*d6b92ffaSHans Petter Selasky 	if (ctx->torus)
433*d6b92ffaSHans Petter Selasky 		teardown_torus(ctx->torus);
434*d6b92ffaSHans Petter Selasky 	free(ctx);
435*d6b92ffaSHans Petter Selasky }
436*d6b92ffaSHans Petter Selasky 
437*d6b92ffaSHans Petter Selasky static
grow_seed_array(struct torus * t,int new_seeds)438*d6b92ffaSHans Petter Selasky bool grow_seed_array(struct torus *t, int new_seeds)
439*d6b92ffaSHans Petter Selasky {
440*d6b92ffaSHans Petter Selasky 	unsigned cnt;
441*d6b92ffaSHans Petter Selasky 	void *ptr;
442*d6b92ffaSHans Petter Selasky 
443*d6b92ffaSHans Petter Selasky 	cnt = t->seed_cnt + new_seeds;
444*d6b92ffaSHans Petter Selasky 	if (cnt > t->seed_sz) {
445*d6b92ffaSHans Petter Selasky 		cnt += 2 + cnt / 2;
446*d6b92ffaSHans Petter Selasky 		ptr = realloc(t->seed, cnt * sizeof(*t->seed));
447*d6b92ffaSHans Petter Selasky 		if (!ptr)
448*d6b92ffaSHans Petter Selasky 			return false;
449*d6b92ffaSHans Petter Selasky 		t->seed = ptr;
450*d6b92ffaSHans Petter Selasky 		t->seed_sz = cnt;
451*d6b92ffaSHans Petter Selasky 		memset(&t->seed[t->seed_cnt], 0,
452*d6b92ffaSHans Petter Selasky 		       (cnt - t->seed_cnt) * sizeof(*t->seed));
453*d6b92ffaSHans Petter Selasky 	}
454*d6b92ffaSHans Petter Selasky 	return true;
455*d6b92ffaSHans Petter Selasky }
456*d6b92ffaSHans Petter Selasky 
457*d6b92ffaSHans Petter Selasky static
find_f_sw(struct fabric * f,guid_t sw_guid)458*d6b92ffaSHans Petter Selasky struct f_switch *find_f_sw(struct fabric *f, guid_t sw_guid)
459*d6b92ffaSHans Petter Selasky {
460*d6b92ffaSHans Petter Selasky 	unsigned s;
461*d6b92ffaSHans Petter Selasky 	struct f_switch *sw;
462*d6b92ffaSHans Petter Selasky 
463*d6b92ffaSHans Petter Selasky 	if (f->sw) {
464*d6b92ffaSHans Petter Selasky 		for (s = 0; s < f->switch_cnt; s++) {
465*d6b92ffaSHans Petter Selasky 			sw = f->sw[s];
466*d6b92ffaSHans Petter Selasky 			if (sw->n_id == sw_guid)
467*d6b92ffaSHans Petter Selasky 				return sw;
468*d6b92ffaSHans Petter Selasky 		}
469*d6b92ffaSHans Petter Selasky 	}
470*d6b92ffaSHans Petter Selasky 	return NULL;
471*d6b92ffaSHans Petter Selasky }
472*d6b92ffaSHans Petter Selasky 
473*d6b92ffaSHans Petter Selasky static
find_f_link(struct fabric * f,guid_t guid0,int port0,guid_t guid1,int port1)474*d6b92ffaSHans Petter Selasky struct link *find_f_link(struct fabric *f,
475*d6b92ffaSHans Petter Selasky 			 guid_t guid0, int port0, guid_t guid1, int port1)
476*d6b92ffaSHans Petter Selasky {
477*d6b92ffaSHans Petter Selasky 	unsigned l;
478*d6b92ffaSHans Petter Selasky 	struct link *link;
479*d6b92ffaSHans Petter Selasky 
480*d6b92ffaSHans Petter Selasky 	if (f->link) {
481*d6b92ffaSHans Petter Selasky 		for (l = 0; l < f->link_cnt; l++) {
482*d6b92ffaSHans Petter Selasky 			link = f->link[l];
483*d6b92ffaSHans Petter Selasky 			if ((link->end[0].n_id == guid0 &&
484*d6b92ffaSHans Petter Selasky 			     link->end[0].port == port0 &&
485*d6b92ffaSHans Petter Selasky 			     link->end[1].n_id == guid1 &&
486*d6b92ffaSHans Petter Selasky 			     link->end[1].port == port1) ||
487*d6b92ffaSHans Petter Selasky 			    (link->end[0].n_id == guid1 &&
488*d6b92ffaSHans Petter Selasky 			     link->end[0].port == port1 &&
489*d6b92ffaSHans Petter Selasky 			     link->end[1].n_id == guid0 &&
490*d6b92ffaSHans Petter Selasky 			     link->end[1].port == port0))
491*d6b92ffaSHans Petter Selasky 				return link;
492*d6b92ffaSHans Petter Selasky 		}
493*d6b92ffaSHans Petter Selasky 	}
494*d6b92ffaSHans Petter Selasky 	return NULL;
495*d6b92ffaSHans Petter Selasky }
496*d6b92ffaSHans Petter Selasky 
497*d6b92ffaSHans Petter Selasky static
alloc_fswitch(struct fabric * f,guid_t sw_id,unsigned port_cnt)498*d6b92ffaSHans Petter Selasky struct f_switch *alloc_fswitch(struct fabric *f,
499*d6b92ffaSHans Petter Selasky 			       guid_t sw_id, unsigned port_cnt)
500*d6b92ffaSHans Petter Selasky {
501*d6b92ffaSHans Petter Selasky 	size_t new_sw_sz;
502*d6b92ffaSHans Petter Selasky 	unsigned cnt_max;
503*d6b92ffaSHans Petter Selasky 	struct f_switch *sw = NULL;
504*d6b92ffaSHans Petter Selasky 	void *ptr;
505*d6b92ffaSHans Petter Selasky 
506*d6b92ffaSHans Petter Selasky 	if (f->switch_cnt >= f->switch_cnt_max) {
507*d6b92ffaSHans Petter Selasky 
508*d6b92ffaSHans Petter Selasky 		cnt_max = 16 + 5 * f->switch_cnt_max / 4;
509*d6b92ffaSHans Petter Selasky 		ptr = realloc(f->sw, cnt_max * sizeof(*f->sw));
510*d6b92ffaSHans Petter Selasky 		if (!ptr) {
511*d6b92ffaSHans Petter Selasky 			OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
512*d6b92ffaSHans Petter Selasky 				"ERR 4E02: realloc: %s\n", strerror(errno));
513*d6b92ffaSHans Petter Selasky 			goto out;
514*d6b92ffaSHans Petter Selasky 		}
515*d6b92ffaSHans Petter Selasky 		f->sw = ptr;
516*d6b92ffaSHans Petter Selasky 		f->switch_cnt_max = cnt_max;
517*d6b92ffaSHans Petter Selasky 		memset(&f->sw[f->switch_cnt], 0,
518*d6b92ffaSHans Petter Selasky 		       (f->switch_cnt_max - f->switch_cnt)*sizeof(*f->sw));
519*d6b92ffaSHans Petter Selasky 	}
520*d6b92ffaSHans Petter Selasky 	new_sw_sz = sizeof(*sw) + port_cnt * sizeof(*sw->port);
521*d6b92ffaSHans Petter Selasky 	sw = calloc(1, new_sw_sz);
522*d6b92ffaSHans Petter Selasky 	if (!sw) {
523*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
524*d6b92ffaSHans Petter Selasky 			"ERR 4E03: calloc: %s\n", strerror(errno));
525*d6b92ffaSHans Petter Selasky 		goto out;
526*d6b92ffaSHans Petter Selasky 	}
527*d6b92ffaSHans Petter Selasky 	sw->port = (void *)(sw + 1);
528*d6b92ffaSHans Petter Selasky 	sw->n_id = sw_id;
529*d6b92ffaSHans Petter Selasky 	sw->port_cnt = port_cnt;
530*d6b92ffaSHans Petter Selasky 	f->sw[f->switch_cnt++] = sw;
531*d6b92ffaSHans Petter Selasky out:
532*d6b92ffaSHans Petter Selasky 	return sw;
533*d6b92ffaSHans Petter Selasky }
534*d6b92ffaSHans Petter Selasky 
535*d6b92ffaSHans Petter Selasky static
alloc_flink(struct fabric * f)536*d6b92ffaSHans Petter Selasky struct link *alloc_flink(struct fabric *f)
537*d6b92ffaSHans Petter Selasky {
538*d6b92ffaSHans Petter Selasky 	unsigned cnt_max;
539*d6b92ffaSHans Petter Selasky 	struct link *l = NULL;
540*d6b92ffaSHans Petter Selasky 	void *ptr;
541*d6b92ffaSHans Petter Selasky 
542*d6b92ffaSHans Petter Selasky 	if (f->link_cnt >= f->link_cnt_max) {
543*d6b92ffaSHans Petter Selasky 
544*d6b92ffaSHans Petter Selasky 		cnt_max = 16 + 5 * f->link_cnt_max / 4;
545*d6b92ffaSHans Petter Selasky 		ptr = realloc(f->link, cnt_max * sizeof(*f->link));
546*d6b92ffaSHans Petter Selasky 		if (!ptr) {
547*d6b92ffaSHans Petter Selasky 			OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
548*d6b92ffaSHans Petter Selasky 				"ERR 4E04: realloc: %s\n", strerror(errno));
549*d6b92ffaSHans Petter Selasky 			goto out;
550*d6b92ffaSHans Petter Selasky 		}
551*d6b92ffaSHans Petter Selasky 		f->link = ptr;
552*d6b92ffaSHans Petter Selasky 		f->link_cnt_max = cnt_max;
553*d6b92ffaSHans Petter Selasky 		memset(&f->link[f->link_cnt], 0,
554*d6b92ffaSHans Petter Selasky 		       (f->link_cnt_max - f->link_cnt) * sizeof(*f->link));
555*d6b92ffaSHans Petter Selasky 	}
556*d6b92ffaSHans Petter Selasky 	l = calloc(1, sizeof(*l));
557*d6b92ffaSHans Petter Selasky 	if (!l) {
558*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
559*d6b92ffaSHans Petter Selasky 			"ERR 4E05: calloc: %s\n", strerror(errno));
560*d6b92ffaSHans Petter Selasky 		goto out;
561*d6b92ffaSHans Petter Selasky 	}
562*d6b92ffaSHans Petter Selasky 	f->link[f->link_cnt++] = l;
563*d6b92ffaSHans Petter Selasky out:
564*d6b92ffaSHans Petter Selasky 	return l;
565*d6b92ffaSHans Petter Selasky }
566*d6b92ffaSHans Petter Selasky 
567*d6b92ffaSHans Petter Selasky /*
568*d6b92ffaSHans Petter Selasky  * Caller must ensure osm_port points to a valid port which contains
569*d6b92ffaSHans Petter Selasky  * a valid osm_physp_t pointer for port 0, the switch management port.
570*d6b92ffaSHans Petter Selasky  */
571*d6b92ffaSHans Petter Selasky static
build_sw_endpoint(struct fabric * f,osm_port_t * osm_port)572*d6b92ffaSHans Petter Selasky bool build_sw_endpoint(struct fabric *f, osm_port_t *osm_port)
573*d6b92ffaSHans Petter Selasky {
574*d6b92ffaSHans Petter Selasky 	int sw_port;
575*d6b92ffaSHans Petter Selasky 	guid_t sw_guid;
576*d6b92ffaSHans Petter Selasky 	struct osm_switch *osm_sw;
577*d6b92ffaSHans Petter Selasky 	struct f_switch *sw;
578*d6b92ffaSHans Petter Selasky 	struct endpoint *ep;
579*d6b92ffaSHans Petter Selasky 	bool success = false;
580*d6b92ffaSHans Petter Selasky 
581*d6b92ffaSHans Petter Selasky 	sw_port = osm_physp_get_port_num(osm_port->p_physp);
582*d6b92ffaSHans Petter Selasky 	sw_guid = osm_node_get_node_guid(osm_port->p_node);
583*d6b92ffaSHans Petter Selasky 	osm_sw = osm_port->p_node->sw;
584*d6b92ffaSHans Petter Selasky 
585*d6b92ffaSHans Petter Selasky 	/*
586*d6b92ffaSHans Petter Selasky 	 * The switch must already exist.
587*d6b92ffaSHans Petter Selasky 	 */
588*d6b92ffaSHans Petter Selasky 	sw = find_f_sw(f, sw_guid);
589*d6b92ffaSHans Petter Selasky 	if (!sw) {
590*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
591*d6b92ffaSHans Petter Selasky 			"ERR 4E06: missing switch w/GUID 0x%04"PRIx64"\n",
592*d6b92ffaSHans Petter Selasky 			cl_ntoh64(sw_guid));
593*d6b92ffaSHans Petter Selasky 		goto out;
594*d6b92ffaSHans Petter Selasky 	}
595*d6b92ffaSHans Petter Selasky 	/*
596*d6b92ffaSHans Petter Selasky 	 * The endpoint may already exist.
597*d6b92ffaSHans Petter Selasky 	 */
598*d6b92ffaSHans Petter Selasky 	if (sw->port[sw_port]) {
599*d6b92ffaSHans Petter Selasky 		if (sw->port[sw_port]->n_id == sw_guid) {
600*d6b92ffaSHans Petter Selasky 			ep = sw->port[sw_port];
601*d6b92ffaSHans Petter Selasky 			goto success;
602*d6b92ffaSHans Petter Selasky 		} else
603*d6b92ffaSHans Petter Selasky 			OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
604*d6b92ffaSHans Petter Selasky 				"ERR 4E07: switch port %d has id "
605*d6b92ffaSHans Petter Selasky 				"0x%04"PRIx64", expected 0x%04"PRIx64"\n",
606*d6b92ffaSHans Petter Selasky 				sw_port, cl_ntoh64(sw->port[sw_port]->n_id),
607*d6b92ffaSHans Petter Selasky 				cl_ntoh64(sw_guid));
608*d6b92ffaSHans Petter Selasky 		goto out;
609*d6b92ffaSHans Petter Selasky 	}
610*d6b92ffaSHans Petter Selasky 	ep = calloc(1, sizeof(*ep));
611*d6b92ffaSHans Petter Selasky 	if (!ep) {
612*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
613*d6b92ffaSHans Petter Selasky 			"ERR 4E08: allocating endpoint: %s\n", strerror(errno));
614*d6b92ffaSHans Petter Selasky 		goto out;
615*d6b92ffaSHans Petter Selasky 	}
616*d6b92ffaSHans Petter Selasky 	ep->type = SRCSINK;
617*d6b92ffaSHans Petter Selasky 	ep->port = sw_port;
618*d6b92ffaSHans Petter Selasky 	ep->n_id = sw_guid;
619*d6b92ffaSHans Petter Selasky 	ep->link = NULL;
620*d6b92ffaSHans Petter Selasky 	ep->sw = sw;
621*d6b92ffaSHans Petter Selasky 
622*d6b92ffaSHans Petter Selasky 	sw->port[sw_port] = ep;
623*d6b92ffaSHans Petter Selasky 
624*d6b92ffaSHans Petter Selasky success:
625*d6b92ffaSHans Petter Selasky 	/*
626*d6b92ffaSHans Petter Selasky 	 * Fabric objects are temporary, so don't set osm_sw/osm_port priv
627*d6b92ffaSHans Petter Selasky 	 * pointers using them.  Wait until torus objects get constructed.
628*d6b92ffaSHans Petter Selasky 	 */
629*d6b92ffaSHans Petter Selasky 	sw->osm_switch = osm_sw;
630*d6b92ffaSHans Petter Selasky 	ep->osm_port = osm_port;
631*d6b92ffaSHans Petter Selasky 
632*d6b92ffaSHans Petter Selasky 	success = true;
633*d6b92ffaSHans Petter Selasky out:
634*d6b92ffaSHans Petter Selasky 	return success;
635*d6b92ffaSHans Petter Selasky }
636*d6b92ffaSHans Petter Selasky 
637*d6b92ffaSHans Petter Selasky static
build_ca_link(struct fabric * f,osm_port_t * osm_port_ca,guid_t sw_guid,int sw_port)638*d6b92ffaSHans Petter Selasky bool build_ca_link(struct fabric *f,
639*d6b92ffaSHans Petter Selasky 		   osm_port_t *osm_port_ca, guid_t sw_guid, int sw_port)
640*d6b92ffaSHans Petter Selasky {
641*d6b92ffaSHans Petter Selasky 	int ca_port;
642*d6b92ffaSHans Petter Selasky 	guid_t ca_guid;
643*d6b92ffaSHans Petter Selasky 	struct link *l;
644*d6b92ffaSHans Petter Selasky 	struct f_switch *sw;
645*d6b92ffaSHans Petter Selasky 	bool success = false;
646*d6b92ffaSHans Petter Selasky 
647*d6b92ffaSHans Petter Selasky 	ca_port = osm_physp_get_port_num(osm_port_ca->p_physp);
648*d6b92ffaSHans Petter Selasky 	ca_guid = osm_node_get_node_guid(osm_port_ca->p_node);
649*d6b92ffaSHans Petter Selasky 
650*d6b92ffaSHans Petter Selasky 	/*
651*d6b92ffaSHans Petter Selasky 	 * The link may already exist.
652*d6b92ffaSHans Petter Selasky 	 */
653*d6b92ffaSHans Petter Selasky 	l = find_f_link(f, sw_guid, sw_port, ca_guid, ca_port);
654*d6b92ffaSHans Petter Selasky 	if (l) {
655*d6b92ffaSHans Petter Selasky 		success = true;
656*d6b92ffaSHans Petter Selasky 		goto out;
657*d6b92ffaSHans Petter Selasky 	}
658*d6b92ffaSHans Petter Selasky 	/*
659*d6b92ffaSHans Petter Selasky 	 * The switch must already exist.
660*d6b92ffaSHans Petter Selasky 	 */
661*d6b92ffaSHans Petter Selasky 	sw = find_f_sw(f, sw_guid);
662*d6b92ffaSHans Petter Selasky 	if (!sw) {
663*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
664*d6b92ffaSHans Petter Selasky 			"ERR 4E09: missing switch w/GUID 0x%04"PRIx64"\n",
665*d6b92ffaSHans Petter Selasky 			cl_ntoh64(sw_guid));
666*d6b92ffaSHans Petter Selasky 		goto out;
667*d6b92ffaSHans Petter Selasky 	}
668*d6b92ffaSHans Petter Selasky 	l = alloc_flink(f);
669*d6b92ffaSHans Petter Selasky 	if (!l)
670*d6b92ffaSHans Petter Selasky 		goto out;
671*d6b92ffaSHans Petter Selasky 
672*d6b92ffaSHans Petter Selasky 	l->end[0].type = PASSTHRU;
673*d6b92ffaSHans Petter Selasky 	l->end[0].port = sw_port;
674*d6b92ffaSHans Petter Selasky 	l->end[0].n_id = sw_guid;
675*d6b92ffaSHans Petter Selasky 	l->end[0].sw = sw;
676*d6b92ffaSHans Petter Selasky 	l->end[0].link = l;
677*d6b92ffaSHans Petter Selasky 
678*d6b92ffaSHans Petter Selasky 	sw->port[sw_port] = &l->end[0];
679*d6b92ffaSHans Petter Selasky 
680*d6b92ffaSHans Petter Selasky 	l->end[1].type = SRCSINK;
681*d6b92ffaSHans Petter Selasky 	l->end[1].port = ca_port;
682*d6b92ffaSHans Petter Selasky 	l->end[1].n_id = ca_guid;
683*d6b92ffaSHans Petter Selasky 	l->end[1].sw = NULL;		/* Correct for a CA */
684*d6b92ffaSHans Petter Selasky 	l->end[1].link = l;
685*d6b92ffaSHans Petter Selasky 
686*d6b92ffaSHans Petter Selasky 	/*
687*d6b92ffaSHans Petter Selasky 	 * Fabric objects are temporary, so don't set osm_sw/osm_port priv
688*d6b92ffaSHans Petter Selasky 	 * pointers using them.  Wait until torus objects get constructed.
689*d6b92ffaSHans Petter Selasky 	 */
690*d6b92ffaSHans Petter Selasky 	l->end[1].osm_port = osm_port_ca;
691*d6b92ffaSHans Petter Selasky 
692*d6b92ffaSHans Petter Selasky 	++f->ca_cnt;
693*d6b92ffaSHans Petter Selasky 	success = true;
694*d6b92ffaSHans Petter Selasky out:
695*d6b92ffaSHans Petter Selasky 	return success;
696*d6b92ffaSHans Petter Selasky }
697*d6b92ffaSHans Petter Selasky 
698*d6b92ffaSHans Petter Selasky static
build_link(struct fabric * f,guid_t sw_guid0,int sw_port0,guid_t sw_guid1,int sw_port1)699*d6b92ffaSHans Petter Selasky bool build_link(struct fabric *f,
700*d6b92ffaSHans Petter Selasky 		guid_t sw_guid0, int sw_port0, guid_t sw_guid1, int sw_port1)
701*d6b92ffaSHans Petter Selasky {
702*d6b92ffaSHans Petter Selasky 	struct link *l;
703*d6b92ffaSHans Petter Selasky 	struct f_switch *sw0, *sw1;
704*d6b92ffaSHans Petter Selasky 	bool success = false;
705*d6b92ffaSHans Petter Selasky 
706*d6b92ffaSHans Petter Selasky 	/*
707*d6b92ffaSHans Petter Selasky 	 * The link may already exist.
708*d6b92ffaSHans Petter Selasky 	 */
709*d6b92ffaSHans Petter Selasky 	l = find_f_link(f, sw_guid0, sw_port0, sw_guid1, sw_port1);
710*d6b92ffaSHans Petter Selasky 	if (l) {
711*d6b92ffaSHans Petter Selasky 		success = true;
712*d6b92ffaSHans Petter Selasky 		goto out;
713*d6b92ffaSHans Petter Selasky 	}
714*d6b92ffaSHans Petter Selasky 	/*
715*d6b92ffaSHans Petter Selasky 	 * The switches must already exist.
716*d6b92ffaSHans Petter Selasky 	 */
717*d6b92ffaSHans Petter Selasky 	sw0 = find_f_sw(f, sw_guid0);
718*d6b92ffaSHans Petter Selasky 	if (!sw0) {
719*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
720*d6b92ffaSHans Petter Selasky 			"ERR 4E0A: missing switch w/GUID 0x%04"PRIx64"\n",
721*d6b92ffaSHans Petter Selasky 			cl_ntoh64(sw_guid0));
722*d6b92ffaSHans Petter Selasky 		goto out;
723*d6b92ffaSHans Petter Selasky 	}
724*d6b92ffaSHans Petter Selasky 	sw1 = find_f_sw(f, sw_guid1);
725*d6b92ffaSHans Petter Selasky 	if (!sw1) {
726*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_ERROR,
727*d6b92ffaSHans Petter Selasky 			"ERR 4E0B: missing switch w/GUID 0x%04"PRIx64"\n",
728*d6b92ffaSHans Petter Selasky 			cl_ntoh64(sw_guid1));
729*d6b92ffaSHans Petter Selasky 		goto out;
730*d6b92ffaSHans Petter Selasky 	}
731*d6b92ffaSHans Petter Selasky 	l = alloc_flink(f);
732*d6b92ffaSHans Petter Selasky 	if (!l)
733*d6b92ffaSHans Petter Selasky 		goto out;
734*d6b92ffaSHans Petter Selasky 
735*d6b92ffaSHans Petter Selasky 	l->end[0].type = PASSTHRU;
736*d6b92ffaSHans Petter Selasky 	l->end[0].port = sw_port0;
737*d6b92ffaSHans Petter Selasky 	l->end[0].n_id = sw_guid0;
738*d6b92ffaSHans Petter Selasky 	l->end[0].sw = sw0;
739*d6b92ffaSHans Petter Selasky 	l->end[0].link = l;
740*d6b92ffaSHans Petter Selasky 
741*d6b92ffaSHans Petter Selasky 	sw0->port[sw_port0] = &l->end[0];
742*d6b92ffaSHans Petter Selasky 
743*d6b92ffaSHans Petter Selasky 	l->end[1].type = PASSTHRU;
744*d6b92ffaSHans Petter Selasky 	l->end[1].port = sw_port1;
745*d6b92ffaSHans Petter Selasky 	l->end[1].n_id = sw_guid1;
746*d6b92ffaSHans Petter Selasky 	l->end[1].sw = sw1;
747*d6b92ffaSHans Petter Selasky 	l->end[1].link = l;
748*d6b92ffaSHans Petter Selasky 
749*d6b92ffaSHans Petter Selasky 	sw1->port[sw_port1] = &l->end[1];
750*d6b92ffaSHans Petter Selasky 
751*d6b92ffaSHans Petter Selasky 	success = true;
752*d6b92ffaSHans Petter Selasky out:
753*d6b92ffaSHans Petter Selasky 	return success;
754*d6b92ffaSHans Petter Selasky }
755*d6b92ffaSHans Petter Selasky 
756*d6b92ffaSHans Petter Selasky static
parse_size(unsigned * tsz,unsigned * tflags,unsigned mask,const char * parse_sep)757*d6b92ffaSHans Petter Selasky bool parse_size(unsigned *tsz, unsigned *tflags, unsigned mask,
758*d6b92ffaSHans Petter Selasky 		const char *parse_sep)
759*d6b92ffaSHans Petter Selasky {
760*d6b92ffaSHans Petter Selasky 	char *val, *nextchar;
761*d6b92ffaSHans Petter Selasky 
762*d6b92ffaSHans Petter Selasky 	val = strtok(NULL, parse_sep);
763*d6b92ffaSHans Petter Selasky 	if (!val)
764*d6b92ffaSHans Petter Selasky 		return false;
765*d6b92ffaSHans Petter Selasky 	*tsz = strtoul(val, &nextchar, 0);
766*d6b92ffaSHans Petter Selasky 	if (*tsz) {
767*d6b92ffaSHans Petter Selasky 		if (*nextchar == 't' || *nextchar == 'T')
768*d6b92ffaSHans Petter Selasky 			*tflags &= ~mask;
769*d6b92ffaSHans Petter Selasky 		else if (*nextchar == 'm' || *nextchar == 'M')
770*d6b92ffaSHans Petter Selasky 			*tflags |= mask;
771*d6b92ffaSHans Petter Selasky 		/*
772*d6b92ffaSHans Petter Selasky 		 * A torus of radix two is also a mesh of radix two
773*d6b92ffaSHans Petter Selasky 		 * with multiple links between switches in that direction.
774*d6b92ffaSHans Petter Selasky 		 *
775*d6b92ffaSHans Petter Selasky 		 * Make it so always, otherwise the failure case routing
776*d6b92ffaSHans Petter Selasky 		 * logic gets confused.
777*d6b92ffaSHans Petter Selasky 		 */
778*d6b92ffaSHans Petter Selasky 		if (*tsz == 2)
779*d6b92ffaSHans Petter Selasky 			*tflags |= mask;
780*d6b92ffaSHans Petter Selasky 	}
781*d6b92ffaSHans Petter Selasky 	return true;
782*d6b92ffaSHans Petter Selasky }
783*d6b92ffaSHans Petter Selasky 
784*d6b92ffaSHans Petter Selasky static
parse_torus(struct torus * t,const char * parse_sep)785*d6b92ffaSHans Petter Selasky bool parse_torus(struct torus *t, const char *parse_sep)
786*d6b92ffaSHans Petter Selasky {
787*d6b92ffaSHans Petter Selasky 	unsigned i, j, k, cnt;
788*d6b92ffaSHans Petter Selasky 	char *ptr;
789*d6b92ffaSHans Petter Selasky 	bool success = false;
790*d6b92ffaSHans Petter Selasky 
791*d6b92ffaSHans Petter Selasky 	/*
792*d6b92ffaSHans Petter Selasky 	 * There can be only one.  Ignore the imposters.
793*d6b92ffaSHans Petter Selasky 	 */
794*d6b92ffaSHans Petter Selasky 	if (t->sw_pool)
795*d6b92ffaSHans Petter Selasky 		goto out;
796*d6b92ffaSHans Petter Selasky 
797*d6b92ffaSHans Petter Selasky 	if (!parse_size(&t->x_sz, &t->flags, X_MESH, parse_sep))
798*d6b92ffaSHans Petter Selasky 		goto out;
799*d6b92ffaSHans Petter Selasky 
800*d6b92ffaSHans Petter Selasky 	if (!parse_size(&t->y_sz, &t->flags, Y_MESH, parse_sep))
801*d6b92ffaSHans Petter Selasky 		goto out;
802*d6b92ffaSHans Petter Selasky 
803*d6b92ffaSHans Petter Selasky 	if (!parse_size(&t->z_sz, &t->flags, Z_MESH, parse_sep))
804*d6b92ffaSHans Petter Selasky 		goto out;
805*d6b92ffaSHans Petter Selasky 
806*d6b92ffaSHans Petter Selasky 	/*
807*d6b92ffaSHans Petter Selasky 	 * Set up a linear array of switch pointers big enough to hold
808*d6b92ffaSHans Petter Selasky 	 * all expected switches.
809*d6b92ffaSHans Petter Selasky 	 */
810*d6b92ffaSHans Petter Selasky 	t->sw_pool_sz = t->x_sz * t->y_sz * t->z_sz;
811*d6b92ffaSHans Petter Selasky 	t->sw_pool = calloc(t->sw_pool_sz, sizeof(*t->sw_pool));
812*d6b92ffaSHans Petter Selasky 	if (!t->sw_pool) {
813*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
814*d6b92ffaSHans Petter Selasky 			"ERR 4E0C: Torus switch array calloc: %s\n",
815*d6b92ffaSHans Petter Selasky 			strerror(errno));
816*d6b92ffaSHans Petter Selasky 		goto out;
817*d6b92ffaSHans Petter Selasky 	}
818*d6b92ffaSHans Petter Selasky 	/*
819*d6b92ffaSHans Petter Selasky 	 * Set things up so that t->sw[i][j][k] can point to the i,j,k switch.
820*d6b92ffaSHans Petter Selasky 	 */
821*d6b92ffaSHans Petter Selasky 	cnt = t->x_sz * (1 + t->y_sz * (1 + t->z_sz));
822*d6b92ffaSHans Petter Selasky 	t->sw = malloc(cnt * sizeof(void *));
823*d6b92ffaSHans Petter Selasky 	if (!t->sw) {
824*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
825*d6b92ffaSHans Petter Selasky 			"ERR 4E0D: Torus switch array malloc: %s\n",
826*d6b92ffaSHans Petter Selasky 			strerror(errno));
827*d6b92ffaSHans Petter Selasky 		goto out;
828*d6b92ffaSHans Petter Selasky 	}
829*d6b92ffaSHans Petter Selasky 	ptr = (void *)(t->sw);
830*d6b92ffaSHans Petter Selasky 
831*d6b92ffaSHans Petter Selasky 	ptr += t->x_sz * sizeof(void *);
832*d6b92ffaSHans Petter Selasky 	for (i = 0; i < t->x_sz; i++) {
833*d6b92ffaSHans Petter Selasky 		t->sw[i] = (void *)ptr;
834*d6b92ffaSHans Petter Selasky 		ptr += t->y_sz * sizeof(void *);
835*d6b92ffaSHans Petter Selasky 	}
836*d6b92ffaSHans Petter Selasky 	for (i = 0; i < t->x_sz; i++)
837*d6b92ffaSHans Petter Selasky 		for (j = 0; j < t->y_sz; j++) {
838*d6b92ffaSHans Petter Selasky 			t->sw[i][j] = (void *)ptr;
839*d6b92ffaSHans Petter Selasky 			ptr += t->z_sz * sizeof(void *);
840*d6b92ffaSHans Petter Selasky 		}
841*d6b92ffaSHans Petter Selasky 
842*d6b92ffaSHans Petter Selasky 	for (i = 0; i < t->x_sz; i++)
843*d6b92ffaSHans Petter Selasky 		for (j = 0; j < t->y_sz; j++)
844*d6b92ffaSHans Petter Selasky 			for (k = 0; k < t->z_sz; k++)
845*d6b92ffaSHans Petter Selasky 				t->sw[i][j][k] = NULL;
846*d6b92ffaSHans Petter Selasky 
847*d6b92ffaSHans Petter Selasky 	success = true;
848*d6b92ffaSHans Petter Selasky out:
849*d6b92ffaSHans Petter Selasky 	return success;
850*d6b92ffaSHans Petter Selasky }
851*d6b92ffaSHans Petter Selasky 
852*d6b92ffaSHans Petter Selasky static
parse_unsigned(unsigned * result,const char * parse_sep)853*d6b92ffaSHans Petter Selasky bool parse_unsigned(unsigned *result, const char *parse_sep)
854*d6b92ffaSHans Petter Selasky {
855*d6b92ffaSHans Petter Selasky 	char *val, *nextchar;
856*d6b92ffaSHans Petter Selasky 
857*d6b92ffaSHans Petter Selasky 	val = strtok(NULL, parse_sep);
858*d6b92ffaSHans Petter Selasky 	if (!val)
859*d6b92ffaSHans Petter Selasky 		return false;
860*d6b92ffaSHans Petter Selasky 	*result = strtoul(val, &nextchar, 0);
861*d6b92ffaSHans Petter Selasky 	return true;
862*d6b92ffaSHans Petter Selasky }
863*d6b92ffaSHans Petter Selasky 
864*d6b92ffaSHans Petter Selasky static
parse_port_order(struct torus * t,const char * parse_sep)865*d6b92ffaSHans Petter Selasky bool parse_port_order(struct torus *t, const char *parse_sep)
866*d6b92ffaSHans Petter Selasky {
867*d6b92ffaSHans Petter Selasky 	unsigned i, j, k, n;
868*d6b92ffaSHans Petter Selasky 
869*d6b92ffaSHans Petter Selasky 	for (i = 0; i < ARRAY_SIZE(t->port_order); i++) {
870*d6b92ffaSHans Petter Selasky 		if (!parse_unsigned(&(t->port_order[i]), parse_sep))
871*d6b92ffaSHans Petter Selasky 			break;
872*d6b92ffaSHans Petter Selasky 
873*d6b92ffaSHans Petter Selasky 		for (j = 0; j < i; j++) {
874*d6b92ffaSHans Petter Selasky 			if (t->port_order[j] == t->port_order[i]) {
875*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_INFO,
876*d6b92ffaSHans Petter Selasky 					"Ignored duplicate port %u in"
877*d6b92ffaSHans Petter Selasky 					" port_order parsing\n",
878*d6b92ffaSHans Petter Selasky 					t->port_order[j]);
879*d6b92ffaSHans Petter Selasky 				i--;	/* Ignore duplicate port number */
880*d6b92ffaSHans Petter Selasky 				break;
881*d6b92ffaSHans Petter Selasky 			}
882*d6b92ffaSHans Petter Selasky 		}
883*d6b92ffaSHans Petter Selasky 	}
884*d6b92ffaSHans Petter Selasky 
885*d6b92ffaSHans Petter Selasky 	n = i;
886*d6b92ffaSHans Petter Selasky 	for (j = 0; j < ARRAY_SIZE(t->port_order); j++) {
887*d6b92ffaSHans Petter Selasky 		for (k = 0; k < i; k++)
888*d6b92ffaSHans Petter Selasky 			if (t->port_order[k] == j)
889*d6b92ffaSHans Petter Selasky 				break;
890*d6b92ffaSHans Petter Selasky 		if (k >= i)
891*d6b92ffaSHans Petter Selasky 			t->port_order[n++] = j;
892*d6b92ffaSHans Petter Selasky 	}
893*d6b92ffaSHans Petter Selasky 
894*d6b92ffaSHans Petter Selasky 	return true;
895*d6b92ffaSHans Petter Selasky }
896*d6b92ffaSHans Petter Selasky 
897*d6b92ffaSHans Petter Selasky static
parse_guid(struct torus * t,guid_t * guid,const char * parse_sep)898*d6b92ffaSHans Petter Selasky bool parse_guid(struct torus *t, guid_t *guid, const char *parse_sep)
899*d6b92ffaSHans Petter Selasky {
900*d6b92ffaSHans Petter Selasky 	char *val;
901*d6b92ffaSHans Petter Selasky 	bool success = false;
902*d6b92ffaSHans Petter Selasky 
903*d6b92ffaSHans Petter Selasky 	val = strtok(NULL, parse_sep);
904*d6b92ffaSHans Petter Selasky 	if (!val)
905*d6b92ffaSHans Petter Selasky 		goto out;
906*d6b92ffaSHans Petter Selasky 	*guid = strtoull(val, NULL, 0);
907*d6b92ffaSHans Petter Selasky 	*guid = cl_hton64(*guid);
908*d6b92ffaSHans Petter Selasky 
909*d6b92ffaSHans Petter Selasky 	success = true;
910*d6b92ffaSHans Petter Selasky out:
911*d6b92ffaSHans Petter Selasky 	return success;
912*d6b92ffaSHans Petter Selasky }
913*d6b92ffaSHans Petter Selasky 
914*d6b92ffaSHans Petter Selasky static
parse_dir_link(int c_dir,struct torus * t,const char * parse_sep)915*d6b92ffaSHans Petter Selasky bool parse_dir_link(int c_dir, struct torus *t, const char *parse_sep)
916*d6b92ffaSHans Petter Selasky {
917*d6b92ffaSHans Petter Selasky 	guid_t sw_guid0, sw_guid1;
918*d6b92ffaSHans Petter Selasky 	struct link *l;
919*d6b92ffaSHans Petter Selasky 	bool success = false;
920*d6b92ffaSHans Petter Selasky 
921*d6b92ffaSHans Petter Selasky 	if (!parse_guid(t, &sw_guid0, parse_sep))
922*d6b92ffaSHans Petter Selasky 		goto out;
923*d6b92ffaSHans Petter Selasky 
924*d6b92ffaSHans Petter Selasky 	if (!parse_guid(t, &sw_guid1, parse_sep))
925*d6b92ffaSHans Petter Selasky 		goto out;
926*d6b92ffaSHans Petter Selasky 
927*d6b92ffaSHans Petter Selasky 	if (!t) {
928*d6b92ffaSHans Petter Selasky 		success = true;
929*d6b92ffaSHans Petter Selasky 		goto out;
930*d6b92ffaSHans Petter Selasky 	}
931*d6b92ffaSHans Petter Selasky 
932*d6b92ffaSHans Petter Selasky 	switch (c_dir) {
933*d6b92ffaSHans Petter Selasky 	case -1:
934*d6b92ffaSHans Petter Selasky 		l = &t->seed[t->seed_cnt - 1].xm_link;
935*d6b92ffaSHans Petter Selasky 		break;
936*d6b92ffaSHans Petter Selasky 	case  1:
937*d6b92ffaSHans Petter Selasky 		l = &t->seed[t->seed_cnt - 1].xp_link;
938*d6b92ffaSHans Petter Selasky 		break;
939*d6b92ffaSHans Petter Selasky 	case -2:
940*d6b92ffaSHans Petter Selasky 		l = &t->seed[t->seed_cnt - 1].ym_link;
941*d6b92ffaSHans Petter Selasky 		break;
942*d6b92ffaSHans Petter Selasky 	case  2:
943*d6b92ffaSHans Petter Selasky 		l = &t->seed[t->seed_cnt - 1].yp_link;
944*d6b92ffaSHans Petter Selasky 		break;
945*d6b92ffaSHans Petter Selasky 	case -3:
946*d6b92ffaSHans Petter Selasky 		l = &t->seed[t->seed_cnt - 1].zm_link;
947*d6b92ffaSHans Petter Selasky 		break;
948*d6b92ffaSHans Petter Selasky 	case  3:
949*d6b92ffaSHans Petter Selasky 		l = &t->seed[t->seed_cnt - 1].zp_link;
950*d6b92ffaSHans Petter Selasky 		break;
951*d6b92ffaSHans Petter Selasky 	default:
952*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
953*d6b92ffaSHans Petter Selasky 			"ERR 4E0E: unknown link direction %d\n", c_dir);
954*d6b92ffaSHans Petter Selasky 		goto out;
955*d6b92ffaSHans Petter Selasky 	}
956*d6b92ffaSHans Petter Selasky 	l->end[0].type = PASSTHRU;
957*d6b92ffaSHans Petter Selasky 	l->end[0].port = -1;		/* We don't really connect. */
958*d6b92ffaSHans Petter Selasky 	l->end[0].n_id = sw_guid0;
959*d6b92ffaSHans Petter Selasky 	l->end[0].sw = NULL;		/* Fix this up later. */
960*d6b92ffaSHans Petter Selasky 	l->end[0].link = NULL;		/* Fix this up later. */
961*d6b92ffaSHans Petter Selasky 
962*d6b92ffaSHans Petter Selasky 	l->end[1].type = PASSTHRU;
963*d6b92ffaSHans Petter Selasky 	l->end[1].port = -1;		/* We don't really connect. */
964*d6b92ffaSHans Petter Selasky 	l->end[1].n_id = sw_guid1;
965*d6b92ffaSHans Petter Selasky 	l->end[1].sw = NULL;		/* Fix this up later. */
966*d6b92ffaSHans Petter Selasky 	l->end[1].link = NULL;		/* Fix this up later. */
967*d6b92ffaSHans Petter Selasky 
968*d6b92ffaSHans Petter Selasky 	success = true;
969*d6b92ffaSHans Petter Selasky out:
970*d6b92ffaSHans Petter Selasky 	return success;
971*d6b92ffaSHans Petter Selasky }
972*d6b92ffaSHans Petter Selasky 
973*d6b92ffaSHans Petter Selasky static
parse_dir_dateline(int c_dir,struct torus * t,const char * parse_sep)974*d6b92ffaSHans Petter Selasky bool parse_dir_dateline(int c_dir, struct torus *t, const char *parse_sep)
975*d6b92ffaSHans Petter Selasky {
976*d6b92ffaSHans Petter Selasky 	char *val;
977*d6b92ffaSHans Petter Selasky 	int *dl, max_dl;
978*d6b92ffaSHans Petter Selasky 	bool success = false;
979*d6b92ffaSHans Petter Selasky 
980*d6b92ffaSHans Petter Selasky 	val = strtok(NULL, parse_sep);
981*d6b92ffaSHans Petter Selasky 	if (!val)
982*d6b92ffaSHans Petter Selasky 		goto out;
983*d6b92ffaSHans Petter Selasky 
984*d6b92ffaSHans Petter Selasky 	if (!t) {
985*d6b92ffaSHans Petter Selasky 		success = true;
986*d6b92ffaSHans Petter Selasky 		goto out;
987*d6b92ffaSHans Petter Selasky 	}
988*d6b92ffaSHans Petter Selasky 
989*d6b92ffaSHans Petter Selasky 	switch (c_dir) {
990*d6b92ffaSHans Petter Selasky 	case  1:
991*d6b92ffaSHans Petter Selasky 		dl = &t->seed[t->seed_cnt - 1].x_dateline;
992*d6b92ffaSHans Petter Selasky 		max_dl = t->x_sz;
993*d6b92ffaSHans Petter Selasky 		break;
994*d6b92ffaSHans Petter Selasky 	case  2:
995*d6b92ffaSHans Petter Selasky 		dl = &t->seed[t->seed_cnt - 1].y_dateline;
996*d6b92ffaSHans Petter Selasky 		max_dl = t->y_sz;
997*d6b92ffaSHans Petter Selasky 		break;
998*d6b92ffaSHans Petter Selasky 	case  3:
999*d6b92ffaSHans Petter Selasky 		dl = &t->seed[t->seed_cnt - 1].z_dateline;
1000*d6b92ffaSHans Petter Selasky 		max_dl = t->z_sz;
1001*d6b92ffaSHans Petter Selasky 		break;
1002*d6b92ffaSHans Petter Selasky 	default:
1003*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1004*d6b92ffaSHans Petter Selasky 			"ERR 4E0F: unknown dateline direction %d\n", c_dir);
1005*d6b92ffaSHans Petter Selasky 		goto out;
1006*d6b92ffaSHans Petter Selasky 	}
1007*d6b92ffaSHans Petter Selasky 	*dl = strtol(val, NULL, 0);
1008*d6b92ffaSHans Petter Selasky 
1009*d6b92ffaSHans Petter Selasky 	if ((*dl < 0 && *dl <= -max_dl) || *dl >= max_dl)
1010*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1011*d6b92ffaSHans Petter Selasky 			"ERR 4E10: dateline value for coordinate direction %d "
1012*d6b92ffaSHans Petter Selasky 			"must be %d < dl < %d\n",
1013*d6b92ffaSHans Petter Selasky 			c_dir, -max_dl, max_dl);
1014*d6b92ffaSHans Petter Selasky 	else
1015*d6b92ffaSHans Petter Selasky 		success = true;
1016*d6b92ffaSHans Petter Selasky out:
1017*d6b92ffaSHans Petter Selasky 	return success;
1018*d6b92ffaSHans Petter Selasky }
1019*d6b92ffaSHans Petter Selasky 
1020*d6b92ffaSHans Petter Selasky static
parse_config(const char * fn,struct fabric * f,struct torus * t)1021*d6b92ffaSHans Petter Selasky bool parse_config(const char *fn, struct fabric *f, struct torus *t)
1022*d6b92ffaSHans Petter Selasky {
1023*d6b92ffaSHans Petter Selasky 	FILE *fp;
1024*d6b92ffaSHans Petter Selasky 	unsigned i;
1025*d6b92ffaSHans Petter Selasky 	char *keyword;
1026*d6b92ffaSHans Petter Selasky 	char *line_buf = NULL;
1027*d6b92ffaSHans Petter Selasky 	const char *parse_sep = " \n\t\015";
1028*d6b92ffaSHans Petter Selasky 	size_t line_buf_sz = 0;
1029*d6b92ffaSHans Petter Selasky 	size_t line_cntr = 0;
1030*d6b92ffaSHans Petter Selasky 	ssize_t llen;
1031*d6b92ffaSHans Petter Selasky 	bool kw_success, success = true;
1032*d6b92ffaSHans Petter Selasky 
1033*d6b92ffaSHans Petter Selasky 	if (!grow_seed_array(t, 2))
1034*d6b92ffaSHans Petter Selasky 		return false;
1035*d6b92ffaSHans Petter Selasky 
1036*d6b92ffaSHans Petter Selasky 	for (i = 0; i < ARRAY_SIZE(t->port_order); i++)
1037*d6b92ffaSHans Petter Selasky 		t->port_order[i] = i;
1038*d6b92ffaSHans Petter Selasky 
1039*d6b92ffaSHans Petter Selasky 	fp = fopen(fn, "r");
1040*d6b92ffaSHans Petter Selasky 	if (!fp) {
1041*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1042*d6b92ffaSHans Petter Selasky 			"ERR 4E11: Opening %s: %s\n", fn, strerror(errno));
1043*d6b92ffaSHans Petter Selasky 		return false;
1044*d6b92ffaSHans Petter Selasky 	}
1045*d6b92ffaSHans Petter Selasky 	t->flags |= NOTIFY_CHANGES;
1046*d6b92ffaSHans Petter Selasky 	t->portgrp_sz = PORTGRP_MAX_PORTS;
1047*d6b92ffaSHans Petter Selasky 	t->max_changes = DEFAULT_MAX_CHANGES;
1048*d6b92ffaSHans Petter Selasky 
1049*d6b92ffaSHans Petter Selasky next_line:
1050*d6b92ffaSHans Petter Selasky 	llen = getline(&line_buf, &line_buf_sz, fp);
1051*d6b92ffaSHans Petter Selasky 	if (llen < 0)
1052*d6b92ffaSHans Petter Selasky 		goto out;
1053*d6b92ffaSHans Petter Selasky 
1054*d6b92ffaSHans Petter Selasky 	++line_cntr;
1055*d6b92ffaSHans Petter Selasky 
1056*d6b92ffaSHans Petter Selasky 	keyword = strtok(line_buf, parse_sep);
1057*d6b92ffaSHans Petter Selasky 	if (!keyword)
1058*d6b92ffaSHans Petter Selasky 		goto next_line;
1059*d6b92ffaSHans Petter Selasky 
1060*d6b92ffaSHans Petter Selasky 	if (strcmp("torus", keyword) == 0) {
1061*d6b92ffaSHans Petter Selasky 		kw_success = parse_torus(t, parse_sep);
1062*d6b92ffaSHans Petter Selasky 	} else if (strcmp("mesh", keyword) == 0) {
1063*d6b92ffaSHans Petter Selasky 		t->flags |= X_MESH | Y_MESH | Z_MESH;
1064*d6b92ffaSHans Petter Selasky 		kw_success = parse_torus(t, parse_sep);
1065*d6b92ffaSHans Petter Selasky 	} else if (strcmp("port_order", keyword) == 0) {
1066*d6b92ffaSHans Petter Selasky 		kw_success = parse_port_order(t, parse_sep);
1067*d6b92ffaSHans Petter Selasky 	} else if (strcmp("next_seed", keyword) == 0) {
1068*d6b92ffaSHans Petter Selasky 		kw_success = grow_seed_array(t, 1);
1069*d6b92ffaSHans Petter Selasky 		t->seed_cnt++;
1070*d6b92ffaSHans Petter Selasky 	} else if (strcmp("portgroup_max_ports", keyword) == 0) {
1071*d6b92ffaSHans Petter Selasky 		kw_success = parse_unsigned(&t->portgrp_sz, parse_sep);
1072*d6b92ffaSHans Petter Selasky 	} else if (strcmp("xp_link", keyword) == 0) {
1073*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1074*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1075*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_link(1, t, parse_sep);
1076*d6b92ffaSHans Petter Selasky 	} else if (strcmp("xm_link", keyword) == 0) {
1077*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1078*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1079*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_link(-1, t, parse_sep);
1080*d6b92ffaSHans Petter Selasky 	} else if (strcmp("x_dateline", keyword) == 0) {
1081*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1082*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1083*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_dateline(1, t, parse_sep);
1084*d6b92ffaSHans Petter Selasky 	} else if (strcmp("yp_link", keyword) == 0) {
1085*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1086*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1087*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_link(2, t, parse_sep);
1088*d6b92ffaSHans Petter Selasky 	} else if (strcmp("ym_link", keyword) == 0) {
1089*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1090*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1091*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_link(-2, t, parse_sep);
1092*d6b92ffaSHans Petter Selasky 	} else if (strcmp("y_dateline", keyword) == 0) {
1093*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1094*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1095*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_dateline(2, t, parse_sep);
1096*d6b92ffaSHans Petter Selasky 	} else if (strcmp("zp_link", keyword) == 0) {
1097*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1098*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1099*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_link(3, t, parse_sep);
1100*d6b92ffaSHans Petter Selasky 	} else if (strcmp("zm_link", keyword) == 0) {
1101*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1102*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1103*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_link(-3, t, parse_sep);
1104*d6b92ffaSHans Petter Selasky 	} else if (strcmp("z_dateline", keyword) == 0) {
1105*d6b92ffaSHans Petter Selasky 		if (!t->seed_cnt)
1106*d6b92ffaSHans Petter Selasky 			t->seed_cnt++;
1107*d6b92ffaSHans Petter Selasky 		kw_success = parse_dir_dateline(3, t, parse_sep);
1108*d6b92ffaSHans Petter Selasky 	} else if (strcmp("max_changes", keyword) == 0) {
1109*d6b92ffaSHans Petter Selasky 		kw_success = parse_unsigned(&t->max_changes, parse_sep);
1110*d6b92ffaSHans Petter Selasky 	} else if (keyword[0] == '#')
1111*d6b92ffaSHans Petter Selasky 		goto next_line;
1112*d6b92ffaSHans Petter Selasky 	else {
1113*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1114*d6b92ffaSHans Petter Selasky 			"ERR 4E12: no keyword found: line %u\n",
1115*d6b92ffaSHans Petter Selasky 			(unsigned)line_cntr);
1116*d6b92ffaSHans Petter Selasky 		kw_success = false;
1117*d6b92ffaSHans Petter Selasky 	}
1118*d6b92ffaSHans Petter Selasky 	if (!kw_success) {
1119*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1120*d6b92ffaSHans Petter Selasky 			"ERR 4E13: parsing '%s': line %u\n",
1121*d6b92ffaSHans Petter Selasky 			keyword, (unsigned)line_cntr);
1122*d6b92ffaSHans Petter Selasky 	}
1123*d6b92ffaSHans Petter Selasky 	success = success && kw_success;
1124*d6b92ffaSHans Petter Selasky 	goto next_line;
1125*d6b92ffaSHans Petter Selasky 
1126*d6b92ffaSHans Petter Selasky out:
1127*d6b92ffaSHans Petter Selasky 	if (line_buf)
1128*d6b92ffaSHans Petter Selasky 		free(line_buf);
1129*d6b92ffaSHans Petter Selasky 	fclose(fp);
1130*d6b92ffaSHans Petter Selasky 	return success;
1131*d6b92ffaSHans Petter Selasky }
1132*d6b92ffaSHans Petter Selasky 
1133*d6b92ffaSHans Petter Selasky static
capture_fabric(struct fabric * fabric)1134*d6b92ffaSHans Petter Selasky bool capture_fabric(struct fabric *fabric)
1135*d6b92ffaSHans Petter Selasky {
1136*d6b92ffaSHans Petter Selasky 	osm_subn_t *subnet = &fabric->osm->subn;
1137*d6b92ffaSHans Petter Selasky 	osm_switch_t *osm_sw;
1138*d6b92ffaSHans Petter Selasky 	osm_physp_t *lphysp, *rphysp;
1139*d6b92ffaSHans Petter Selasky 	osm_port_t *lport;
1140*d6b92ffaSHans Petter Selasky 	osm_node_t *osm_node;
1141*d6b92ffaSHans Petter Selasky 	cl_map_item_t *item;
1142*d6b92ffaSHans Petter Selasky 	uint8_t ltype, rtype;
1143*d6b92ffaSHans Petter Selasky 	int p, port_cnt;
1144*d6b92ffaSHans Petter Selasky 	guid_t sw_guid;
1145*d6b92ffaSHans Petter Selasky 	bool success = true;
1146*d6b92ffaSHans Petter Selasky 
1147*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(&fabric->osm->log);
1148*d6b92ffaSHans Petter Selasky 
1149*d6b92ffaSHans Petter Selasky 	/*
1150*d6b92ffaSHans Petter Selasky 	 * On OpenSM data structures:
1151*d6b92ffaSHans Petter Selasky 	 *
1152*d6b92ffaSHans Petter Selasky 	 * Apparently, every port in a fabric has an associated osm_physp_t,
1153*d6b92ffaSHans Petter Selasky 	 * but not every port has an associated osm_port_t.  Apparently every
1154*d6b92ffaSHans Petter Selasky 	 * osm_port_t has an associated osm_physp_t.
1155*d6b92ffaSHans Petter Selasky 	 *
1156*d6b92ffaSHans Petter Selasky 	 * So, in order to find the inter-switch links we need to walk the
1157*d6b92ffaSHans Petter Selasky 	 * switch list and examine each port, via its osm_physp_t object.
1158*d6b92ffaSHans Petter Selasky 	 *
1159*d6b92ffaSHans Petter Selasky 	 * But, we need to associate our CA and switch management port
1160*d6b92ffaSHans Petter Selasky 	 * endpoints with the corresponding osm_port_t objects, in order
1161*d6b92ffaSHans Petter Selasky 	 * to simplify computation of LFT entries and perform SL lookup for
1162*d6b92ffaSHans Petter Selasky 	 * path records. Since it is apparently difficult to locate the
1163*d6b92ffaSHans Petter Selasky 	 * osm_port_t that corresponds to a given osm_physp_t, we also
1164*d6b92ffaSHans Petter Selasky 	 * need to walk the list of ports indexed by GUID to get access
1165*d6b92ffaSHans Petter Selasky 	 * to the appropriate osm_port_t objects.
1166*d6b92ffaSHans Petter Selasky 	 *
1167*d6b92ffaSHans Petter Selasky 	 * Need to allocate our switches before we do anything else.
1168*d6b92ffaSHans Petter Selasky 	 */
1169*d6b92ffaSHans Petter Selasky 	item = cl_qmap_head(&subnet->sw_guid_tbl);
1170*d6b92ffaSHans Petter Selasky 	while (item != cl_qmap_end(&subnet->sw_guid_tbl)) {
1171*d6b92ffaSHans Petter Selasky 
1172*d6b92ffaSHans Petter Selasky 		osm_sw = (osm_switch_t *)item;
1173*d6b92ffaSHans Petter Selasky 		item = cl_qmap_next(item);
1174*d6b92ffaSHans Petter Selasky 		osm_sw->priv = NULL;  /* avoid stale pointer dereferencing */
1175*d6b92ffaSHans Petter Selasky 		osm_node = osm_sw->p_node;
1176*d6b92ffaSHans Petter Selasky 
1177*d6b92ffaSHans Petter Selasky 		if (osm_node_get_type(osm_node) != IB_NODE_TYPE_SWITCH)
1178*d6b92ffaSHans Petter Selasky 			continue;
1179*d6b92ffaSHans Petter Selasky 
1180*d6b92ffaSHans Petter Selasky 		port_cnt = osm_node_get_num_physp(osm_node);
1181*d6b92ffaSHans Petter Selasky 		sw_guid = osm_node_get_node_guid(osm_node);
1182*d6b92ffaSHans Petter Selasky 
1183*d6b92ffaSHans Petter Selasky 		success = alloc_fswitch(fabric, sw_guid, port_cnt);
1184*d6b92ffaSHans Petter Selasky 		if (!success)
1185*d6b92ffaSHans Petter Selasky 			goto out;
1186*d6b92ffaSHans Petter Selasky 	}
1187*d6b92ffaSHans Petter Selasky 	/*
1188*d6b92ffaSHans Petter Selasky 	 * Now build all our endpoints.
1189*d6b92ffaSHans Petter Selasky 	 */
1190*d6b92ffaSHans Petter Selasky 	item = cl_qmap_head(&subnet->port_guid_tbl);
1191*d6b92ffaSHans Petter Selasky 	while (item != cl_qmap_end(&subnet->port_guid_tbl)) {
1192*d6b92ffaSHans Petter Selasky 
1193*d6b92ffaSHans Petter Selasky 		lport = (osm_port_t *)item;
1194*d6b92ffaSHans Petter Selasky 		item = cl_qmap_next(item);
1195*d6b92ffaSHans Petter Selasky 		lport->priv = NULL;  /* avoid stale pointer dereferencing */
1196*d6b92ffaSHans Petter Selasky 
1197*d6b92ffaSHans Petter Selasky 		lphysp = lport->p_physp;
1198*d6b92ffaSHans Petter Selasky 		if (!(lphysp && osm_physp_is_valid(lphysp)))
1199*d6b92ffaSHans Petter Selasky 			continue;
1200*d6b92ffaSHans Petter Selasky 
1201*d6b92ffaSHans Petter Selasky 		ltype = osm_node_get_type(lphysp->p_node);
1202*d6b92ffaSHans Petter Selasky 		/*
1203*d6b92ffaSHans Petter Selasky 		 * Switch management port is always port 0.
1204*d6b92ffaSHans Petter Selasky 		 */
1205*d6b92ffaSHans Petter Selasky 		if (lphysp->port_num == 0 && ltype == IB_NODE_TYPE_SWITCH) {
1206*d6b92ffaSHans Petter Selasky 			success = build_sw_endpoint(fabric, lport);
1207*d6b92ffaSHans Petter Selasky 			if (!success)
1208*d6b92ffaSHans Petter Selasky 				goto out;
1209*d6b92ffaSHans Petter Selasky 			continue;
1210*d6b92ffaSHans Petter Selasky 		}
1211*d6b92ffaSHans Petter Selasky 		rphysp = lphysp->p_remote_physp;
1212*d6b92ffaSHans Petter Selasky 		if (!(rphysp && osm_physp_is_valid(rphysp)))
1213*d6b92ffaSHans Petter Selasky 			continue;
1214*d6b92ffaSHans Petter Selasky 
1215*d6b92ffaSHans Petter Selasky 		rtype = osm_node_get_type(rphysp->p_node);
1216*d6b92ffaSHans Petter Selasky 
1217*d6b92ffaSHans Petter Selasky 		if ((ltype != IB_NODE_TYPE_CA &&
1218*d6b92ffaSHans Petter Selasky 		     ltype != IB_NODE_TYPE_ROUTER) ||
1219*d6b92ffaSHans Petter Selasky 		    rtype != IB_NODE_TYPE_SWITCH)
1220*d6b92ffaSHans Petter Selasky 			continue;
1221*d6b92ffaSHans Petter Selasky 
1222*d6b92ffaSHans Petter Selasky 		success =
1223*d6b92ffaSHans Petter Selasky 			build_ca_link(fabric, lport,
1224*d6b92ffaSHans Petter Selasky 				      osm_node_get_node_guid(rphysp->p_node),
1225*d6b92ffaSHans Petter Selasky 				      osm_physp_get_port_num(rphysp));
1226*d6b92ffaSHans Petter Selasky 		if (!success)
1227*d6b92ffaSHans Petter Selasky 			goto out;
1228*d6b92ffaSHans Petter Selasky 	}
1229*d6b92ffaSHans Petter Selasky 	/*
1230*d6b92ffaSHans Petter Selasky 	 * Lastly, build all our interswitch links.
1231*d6b92ffaSHans Petter Selasky 	 */
1232*d6b92ffaSHans Petter Selasky 	item = cl_qmap_head(&subnet->sw_guid_tbl);
1233*d6b92ffaSHans Petter Selasky 	while (item != cl_qmap_end(&subnet->sw_guid_tbl)) {
1234*d6b92ffaSHans Petter Selasky 
1235*d6b92ffaSHans Petter Selasky 		osm_sw = (osm_switch_t *)item;
1236*d6b92ffaSHans Petter Selasky 		item = cl_qmap_next(item);
1237*d6b92ffaSHans Petter Selasky 
1238*d6b92ffaSHans Petter Selasky 		port_cnt = osm_node_get_num_physp(osm_sw->p_node);
1239*d6b92ffaSHans Petter Selasky 		for (p = 0; p < port_cnt; p++) {
1240*d6b92ffaSHans Petter Selasky 
1241*d6b92ffaSHans Petter Selasky 			lphysp = osm_node_get_physp_ptr(osm_sw->p_node, p);
1242*d6b92ffaSHans Petter Selasky 			if (!(lphysp && osm_physp_is_valid(lphysp)))
1243*d6b92ffaSHans Petter Selasky 				continue;
1244*d6b92ffaSHans Petter Selasky 
1245*d6b92ffaSHans Petter Selasky 			rphysp = lphysp->p_remote_physp;
1246*d6b92ffaSHans Petter Selasky 			if (!(rphysp && osm_physp_is_valid(rphysp)))
1247*d6b92ffaSHans Petter Selasky 				continue;
1248*d6b92ffaSHans Petter Selasky 
1249*d6b92ffaSHans Petter Selasky 			if (lphysp == rphysp)
1250*d6b92ffaSHans Petter Selasky 				continue;	/* ignore loopbacks */
1251*d6b92ffaSHans Petter Selasky 
1252*d6b92ffaSHans Petter Selasky 			ltype = osm_node_get_type(lphysp->p_node);
1253*d6b92ffaSHans Petter Selasky 			rtype = osm_node_get_type(rphysp->p_node);
1254*d6b92ffaSHans Petter Selasky 
1255*d6b92ffaSHans Petter Selasky 			if (ltype != IB_NODE_TYPE_SWITCH ||
1256*d6b92ffaSHans Petter Selasky 			    rtype != IB_NODE_TYPE_SWITCH)
1257*d6b92ffaSHans Petter Selasky 				continue;
1258*d6b92ffaSHans Petter Selasky 
1259*d6b92ffaSHans Petter Selasky 			success =
1260*d6b92ffaSHans Petter Selasky 				build_link(fabric,
1261*d6b92ffaSHans Petter Selasky 					   osm_node_get_node_guid(lphysp->p_node),
1262*d6b92ffaSHans Petter Selasky 					   osm_physp_get_port_num(lphysp),
1263*d6b92ffaSHans Petter Selasky 					   osm_node_get_node_guid(rphysp->p_node),
1264*d6b92ffaSHans Petter Selasky 					   osm_physp_get_port_num(rphysp));
1265*d6b92ffaSHans Petter Selasky 			if (!success)
1266*d6b92ffaSHans Petter Selasky 				goto out;
1267*d6b92ffaSHans Petter Selasky 		}
1268*d6b92ffaSHans Petter Selasky 	}
1269*d6b92ffaSHans Petter Selasky out:
1270*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(&fabric->osm->log);
1271*d6b92ffaSHans Petter Selasky 	return success;
1272*d6b92ffaSHans Petter Selasky }
1273*d6b92ffaSHans Petter Selasky 
1274*d6b92ffaSHans Petter Selasky /*
1275*d6b92ffaSHans Petter Selasky  * diagnose_fabric() is just intended to report on fabric elements that
1276*d6b92ffaSHans Petter Selasky  * could not be placed into the torus.  We want to warn that there were
1277*d6b92ffaSHans Petter Selasky  * non-torus fabric elements, but they will be ignored for routing purposes.
1278*d6b92ffaSHans Petter Selasky  * Having them is not an error, and diagnose_fabric() thus has no return
1279*d6b92ffaSHans Petter Selasky  * value.
1280*d6b92ffaSHans Petter Selasky  */
1281*d6b92ffaSHans Petter Selasky static
diagnose_fabric(struct fabric * f)1282*d6b92ffaSHans Petter Selasky void diagnose_fabric(struct fabric *f)
1283*d6b92ffaSHans Petter Selasky {
1284*d6b92ffaSHans Petter Selasky 	struct link *l;
1285*d6b92ffaSHans Petter Selasky 	struct endpoint *ep;
1286*d6b92ffaSHans Petter Selasky 	unsigned k, p;
1287*d6b92ffaSHans Petter Selasky 
1288*d6b92ffaSHans Petter Selasky 	/*
1289*d6b92ffaSHans Petter Selasky 	 * Report on any links that didn't get transferred to the torus.
1290*d6b92ffaSHans Petter Selasky 	 */
1291*d6b92ffaSHans Petter Selasky 	for (k = 0; k < f->link_cnt; k++) {
1292*d6b92ffaSHans Petter Selasky 		l = f->link[k];
1293*d6b92ffaSHans Petter Selasky 
1294*d6b92ffaSHans Petter Selasky 		if (!(l->end[0].sw && l->end[1].sw))
1295*d6b92ffaSHans Petter Selasky 			continue;
1296*d6b92ffaSHans Petter Selasky 
1297*d6b92ffaSHans Petter Selasky 		OSM_LOG(&f->osm->log, OSM_LOG_INFO,
1298*d6b92ffaSHans Petter Selasky 			"Found non-torus fabric link:"
1299*d6b92ffaSHans Petter Selasky 			" sw GUID 0x%04"PRIx64" port %d <->"
1300*d6b92ffaSHans Petter Selasky 			" sw GUID 0x%04"PRIx64" port %d\n",
1301*d6b92ffaSHans Petter Selasky 			cl_ntoh64(l->end[0].n_id), l->end[0].port,
1302*d6b92ffaSHans Petter Selasky 			cl_ntoh64(l->end[1].n_id), l->end[1].port);
1303*d6b92ffaSHans Petter Selasky 	}
1304*d6b92ffaSHans Petter Selasky 	/*
1305*d6b92ffaSHans Petter Selasky 	 * Report on any switches with ports using endpoints that didn't
1306*d6b92ffaSHans Petter Selasky 	 * get transferred to the torus.
1307*d6b92ffaSHans Petter Selasky 	 */
1308*d6b92ffaSHans Petter Selasky 	for (k = 0; k < f->switch_cnt; k++)
1309*d6b92ffaSHans Petter Selasky 		for (p = 0; p < f->sw[k]->port_cnt; p++) {
1310*d6b92ffaSHans Petter Selasky 
1311*d6b92ffaSHans Petter Selasky 			if (!f->sw[k]->port[p])
1312*d6b92ffaSHans Petter Selasky 				continue;
1313*d6b92ffaSHans Petter Selasky 
1314*d6b92ffaSHans Petter Selasky 			ep = f->sw[k]->port[p];
1315*d6b92ffaSHans Petter Selasky 
1316*d6b92ffaSHans Petter Selasky 			/*
1317*d6b92ffaSHans Petter Selasky 			 * We already reported on inter-switch links above.
1318*d6b92ffaSHans Petter Selasky 			 */
1319*d6b92ffaSHans Petter Selasky 			if (ep->type == PASSTHRU)
1320*d6b92ffaSHans Petter Selasky 				continue;
1321*d6b92ffaSHans Petter Selasky 
1322*d6b92ffaSHans Petter Selasky 			OSM_LOG(&f->osm->log, OSM_LOG_INFO,
1323*d6b92ffaSHans Petter Selasky 				"Found non-torus fabric port:"
1324*d6b92ffaSHans Petter Selasky 				" sw GUID 0x%04"PRIx64" port %d\n",
1325*d6b92ffaSHans Petter Selasky 				cl_ntoh64(f->sw[k]->n_id), p);
1326*d6b92ffaSHans Petter Selasky 		}
1327*d6b92ffaSHans Petter Selasky }
1328*d6b92ffaSHans Petter Selasky 
1329*d6b92ffaSHans Petter Selasky static
alloc_tswitch(struct torus * t,struct f_switch * fsw)1330*d6b92ffaSHans Petter Selasky struct t_switch *alloc_tswitch(struct torus *t, struct f_switch *fsw)
1331*d6b92ffaSHans Petter Selasky {
1332*d6b92ffaSHans Petter Selasky 	unsigned g;
1333*d6b92ffaSHans Petter Selasky 	size_t new_sw_sz;
1334*d6b92ffaSHans Petter Selasky 	struct t_switch *sw = NULL;
1335*d6b92ffaSHans Petter Selasky 	void *ptr;
1336*d6b92ffaSHans Petter Selasky 
1337*d6b92ffaSHans Petter Selasky 	if (!fsw)
1338*d6b92ffaSHans Petter Selasky 		goto out;
1339*d6b92ffaSHans Petter Selasky 
1340*d6b92ffaSHans Petter Selasky 	if (t->switch_cnt >= t->sw_pool_sz) {
1341*d6b92ffaSHans Petter Selasky 		/*
1342*d6b92ffaSHans Petter Selasky 		 * This should never happen, but occasionally a particularly
1343*d6b92ffaSHans Petter Selasky 		 * pathological fabric can induce it.  So log an error.
1344*d6b92ffaSHans Petter Selasky 		 */
1345*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1346*d6b92ffaSHans Petter Selasky 			"ERR 4E14: unexpectedly requested too many switch "
1347*d6b92ffaSHans Petter Selasky 			"structures!\n");
1348*d6b92ffaSHans Petter Selasky 		goto out;
1349*d6b92ffaSHans Petter Selasky 	}
1350*d6b92ffaSHans Petter Selasky 	new_sw_sz = sizeof(*sw)
1351*d6b92ffaSHans Petter Selasky 		+ fsw->port_cnt * sizeof(*sw->port)
1352*d6b92ffaSHans Petter Selasky 		+ SWITCH_MAX_PORTGRPS * t->portgrp_sz * sizeof(*sw->ptgrp[0].port);
1353*d6b92ffaSHans Petter Selasky 	sw = calloc(1, new_sw_sz);
1354*d6b92ffaSHans Petter Selasky 	if (!sw) {
1355*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1356*d6b92ffaSHans Petter Selasky 			"ERR 4E15: calloc: %s\n", strerror(errno));
1357*d6b92ffaSHans Petter Selasky 		goto out;
1358*d6b92ffaSHans Petter Selasky 	}
1359*d6b92ffaSHans Petter Selasky 	sw->port = (void *)(sw + 1);
1360*d6b92ffaSHans Petter Selasky 	sw->n_id = fsw->n_id;
1361*d6b92ffaSHans Petter Selasky 	sw->port_cnt = fsw->port_cnt;
1362*d6b92ffaSHans Petter Selasky 	sw->torus = t;
1363*d6b92ffaSHans Petter Selasky 	sw->tmp = fsw;
1364*d6b92ffaSHans Petter Selasky 
1365*d6b92ffaSHans Petter Selasky 	ptr = &sw->port[sw->port_cnt];
1366*d6b92ffaSHans Petter Selasky 
1367*d6b92ffaSHans Petter Selasky 	for (g = 0; g < SWITCH_MAX_PORTGRPS; g++) {
1368*d6b92ffaSHans Petter Selasky 		sw->ptgrp[g].port_grp = g;
1369*d6b92ffaSHans Petter Selasky 		sw->ptgrp[g].sw = sw;
1370*d6b92ffaSHans Petter Selasky 		sw->ptgrp[g].port = ptr;
1371*d6b92ffaSHans Petter Selasky 		ptr = &sw->ptgrp[g].port[t->portgrp_sz];
1372*d6b92ffaSHans Petter Selasky 	}
1373*d6b92ffaSHans Petter Selasky 	t->sw_pool[t->switch_cnt++] = sw;
1374*d6b92ffaSHans Petter Selasky out:
1375*d6b92ffaSHans Petter Selasky 	return sw;
1376*d6b92ffaSHans Petter Selasky }
1377*d6b92ffaSHans Petter Selasky 
1378*d6b92ffaSHans Petter Selasky /*
1379*d6b92ffaSHans Petter Selasky  * install_tswitch() expects the switch coordinates i,j,k to be canonicalized
1380*d6b92ffaSHans Petter Selasky  * by caller.
1381*d6b92ffaSHans Petter Selasky  */
1382*d6b92ffaSHans Petter Selasky static
install_tswitch(struct torus * t,int i,int j,int k,struct f_switch * fsw)1383*d6b92ffaSHans Petter Selasky bool install_tswitch(struct torus *t,
1384*d6b92ffaSHans Petter Selasky 		     int i, int j, int k, struct f_switch *fsw)
1385*d6b92ffaSHans Petter Selasky {
1386*d6b92ffaSHans Petter Selasky 	struct t_switch **sw = &t->sw[i][j][k];
1387*d6b92ffaSHans Petter Selasky 
1388*d6b92ffaSHans Petter Selasky 	if (!*sw)
1389*d6b92ffaSHans Petter Selasky 		*sw = alloc_tswitch(t, fsw);
1390*d6b92ffaSHans Petter Selasky 
1391*d6b92ffaSHans Petter Selasky 	if (*sw) {
1392*d6b92ffaSHans Petter Selasky 		(*sw)->i = i;
1393*d6b92ffaSHans Petter Selasky 		(*sw)->j = j;
1394*d6b92ffaSHans Petter Selasky 		(*sw)->k = k;
1395*d6b92ffaSHans Petter Selasky 	}
1396*d6b92ffaSHans Petter Selasky 	return !!*sw;
1397*d6b92ffaSHans Petter Selasky }
1398*d6b92ffaSHans Petter Selasky 
1399*d6b92ffaSHans Petter Selasky static
alloc_tlink(struct torus * t)1400*d6b92ffaSHans Petter Selasky struct link *alloc_tlink(struct torus *t)
1401*d6b92ffaSHans Petter Selasky {
1402*d6b92ffaSHans Petter Selasky 	if (t->link_cnt >= t->link_pool_sz) {
1403*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1404*d6b92ffaSHans Petter Selasky 			"ERR 4E16: unexpectedly out of pre-allocated link "
1405*d6b92ffaSHans Petter Selasky 			"structures!\n");
1406*d6b92ffaSHans Petter Selasky 		return NULL;
1407*d6b92ffaSHans Petter Selasky 	}
1408*d6b92ffaSHans Petter Selasky 	return &t->link_pool[t->link_cnt++];
1409*d6b92ffaSHans Petter Selasky }
1410*d6b92ffaSHans Petter Selasky 
1411*d6b92ffaSHans Petter Selasky static
canonicalize(int v,int vmax)1412*d6b92ffaSHans Petter Selasky int canonicalize(int v, int vmax)
1413*d6b92ffaSHans Petter Selasky {
1414*d6b92ffaSHans Petter Selasky 	if (v >= 0 && v < vmax)
1415*d6b92ffaSHans Petter Selasky 		return v;
1416*d6b92ffaSHans Petter Selasky 
1417*d6b92ffaSHans Petter Selasky 	if (v < 0)
1418*d6b92ffaSHans Petter Selasky 		v += vmax * (1 - v/vmax);
1419*d6b92ffaSHans Petter Selasky 
1420*d6b92ffaSHans Petter Selasky 	return v % vmax;
1421*d6b92ffaSHans Petter Selasky }
1422*d6b92ffaSHans Petter Selasky 
1423*d6b92ffaSHans Petter Selasky static
set_fp_bit(bool present,int i,int j,int k)1424*d6b92ffaSHans Petter Selasky unsigned set_fp_bit(bool present, int i, int j, int k)
1425*d6b92ffaSHans Petter Selasky {
1426*d6b92ffaSHans Petter Selasky 	return (unsigned)(!present) << (i + 2 * j + 4 * k);
1427*d6b92ffaSHans Petter Selasky }
1428*d6b92ffaSHans Petter Selasky 
1429*d6b92ffaSHans Petter Selasky /*
1430*d6b92ffaSHans Petter Selasky  * Returns an 11-bit fingerprint of what switches are absent in a cube of
1431*d6b92ffaSHans Petter Selasky  * neighboring switches.  Each bit 0-7 corresponds to a corner of the cube;
1432*d6b92ffaSHans Petter Selasky  * if a bit is set the corresponding switch is absent.
1433*d6b92ffaSHans Petter Selasky  *
1434*d6b92ffaSHans Petter Selasky  * Bits 8-10 distinguish between 2D and 3D cases.  If bit 8+d is set,
1435*d6b92ffaSHans Petter Selasky  * for 0 <= d < 3;  the d dimension of the desired torus has radix greater
1436*d6b92ffaSHans Petter Selasky  * than 1. Thus, if all bits 8-10 are set, the desired torus is 3D.
1437*d6b92ffaSHans Petter Selasky  */
1438*d6b92ffaSHans Petter Selasky static
fingerprint(struct torus * t,int i,int j,int k)1439*d6b92ffaSHans Petter Selasky unsigned fingerprint(struct torus *t, int i, int j, int k)
1440*d6b92ffaSHans Petter Selasky {
1441*d6b92ffaSHans Petter Selasky 	unsigned fp;
1442*d6b92ffaSHans Petter Selasky 	int ip1, jp1, kp1;
1443*d6b92ffaSHans Petter Selasky 	int x_sz_gt1, y_sz_gt1, z_sz_gt1;
1444*d6b92ffaSHans Petter Selasky 
1445*d6b92ffaSHans Petter Selasky 	x_sz_gt1 = t->x_sz > 1;
1446*d6b92ffaSHans Petter Selasky 	y_sz_gt1 = t->y_sz > 1;
1447*d6b92ffaSHans Petter Selasky 	z_sz_gt1 = t->z_sz > 1;
1448*d6b92ffaSHans Petter Selasky 
1449*d6b92ffaSHans Petter Selasky 	ip1 = canonicalize(i + 1, t->x_sz);
1450*d6b92ffaSHans Petter Selasky 	jp1 = canonicalize(j + 1, t->y_sz);
1451*d6b92ffaSHans Petter Selasky 	kp1 = canonicalize(k + 1, t->z_sz);
1452*d6b92ffaSHans Petter Selasky 
1453*d6b92ffaSHans Petter Selasky 	fp  = set_fp_bit(t->sw[i][j][k], 0, 0, 0);
1454*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[ip1][j][k], x_sz_gt1, 0, 0);
1455*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[i][jp1][k], 0, y_sz_gt1, 0);
1456*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[ip1][jp1][k], x_sz_gt1, y_sz_gt1, 0);
1457*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[i][j][kp1], 0, 0, z_sz_gt1);
1458*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[ip1][j][kp1], x_sz_gt1, 0, z_sz_gt1);
1459*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[i][jp1][kp1], 0, y_sz_gt1, z_sz_gt1);
1460*d6b92ffaSHans Petter Selasky 	fp |= set_fp_bit(t->sw[ip1][jp1][kp1], x_sz_gt1, y_sz_gt1, z_sz_gt1);
1461*d6b92ffaSHans Petter Selasky 
1462*d6b92ffaSHans Petter Selasky 	fp |= x_sz_gt1 << 8;
1463*d6b92ffaSHans Petter Selasky 	fp |= y_sz_gt1 << 9;
1464*d6b92ffaSHans Petter Selasky 	fp |= z_sz_gt1 << 10;
1465*d6b92ffaSHans Petter Selasky 
1466*d6b92ffaSHans Petter Selasky 	return fp;
1467*d6b92ffaSHans Petter Selasky }
1468*d6b92ffaSHans Petter Selasky 
1469*d6b92ffaSHans Petter Selasky static
connect_tlink(struct port_grp * pg0,struct endpoint * f_ep0,struct port_grp * pg1,struct endpoint * f_ep1,struct torus * t)1470*d6b92ffaSHans Petter Selasky bool connect_tlink(struct port_grp *pg0, struct endpoint *f_ep0,
1471*d6b92ffaSHans Petter Selasky 		   struct port_grp *pg1, struct endpoint *f_ep1,
1472*d6b92ffaSHans Petter Selasky 		   struct torus *t)
1473*d6b92ffaSHans Petter Selasky {
1474*d6b92ffaSHans Petter Selasky 	struct link *l;
1475*d6b92ffaSHans Petter Selasky 	bool success = false;
1476*d6b92ffaSHans Petter Selasky 
1477*d6b92ffaSHans Petter Selasky 	if (pg0->port_cnt == t->portgrp_sz) {
1478*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1479*d6b92ffaSHans Petter Selasky 			"ERR 4E17: exceeded port group max "
1480*d6b92ffaSHans Petter Selasky 			"port count (%d): switch GUID 0x%04"PRIx64"\n",
1481*d6b92ffaSHans Petter Selasky 			t->portgrp_sz, cl_ntoh64(pg0->sw->n_id));
1482*d6b92ffaSHans Petter Selasky 		goto out;
1483*d6b92ffaSHans Petter Selasky 	}
1484*d6b92ffaSHans Petter Selasky 	if (pg1->port_cnt == t->portgrp_sz) {
1485*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1486*d6b92ffaSHans Petter Selasky 			"ERR 4E18: exceeded port group max "
1487*d6b92ffaSHans Petter Selasky 			"port count (%d): switch GUID 0x%04"PRIx64"\n",
1488*d6b92ffaSHans Petter Selasky 			t->portgrp_sz, cl_ntoh64(pg1->sw->n_id));
1489*d6b92ffaSHans Petter Selasky 		goto out;
1490*d6b92ffaSHans Petter Selasky 	}
1491*d6b92ffaSHans Petter Selasky 	l = alloc_tlink(t);
1492*d6b92ffaSHans Petter Selasky 	if (!l)
1493*d6b92ffaSHans Petter Selasky 		goto out;
1494*d6b92ffaSHans Petter Selasky 
1495*d6b92ffaSHans Petter Selasky 	l->end[0].type = f_ep0->type;
1496*d6b92ffaSHans Petter Selasky 	l->end[0].port = f_ep0->port;
1497*d6b92ffaSHans Petter Selasky 	l->end[0].n_id = f_ep0->n_id;
1498*d6b92ffaSHans Petter Selasky 	l->end[0].sw = pg0->sw;
1499*d6b92ffaSHans Petter Selasky 	l->end[0].link = l;
1500*d6b92ffaSHans Petter Selasky 	l->end[0].pgrp = pg0;
1501*d6b92ffaSHans Petter Selasky 	pg0->port[pg0->port_cnt++] = &l->end[0];
1502*d6b92ffaSHans Petter Selasky 	pg0->sw->port[f_ep0->port] = &l->end[0];
1503*d6b92ffaSHans Petter Selasky 
1504*d6b92ffaSHans Petter Selasky 	if (f_ep0->osm_port) {
1505*d6b92ffaSHans Petter Selasky 		l->end[0].osm_port = f_ep0->osm_port;
1506*d6b92ffaSHans Petter Selasky 		l->end[0].osm_port->priv = &l->end[0];
1507*d6b92ffaSHans Petter Selasky 		f_ep0->osm_port = NULL;
1508*d6b92ffaSHans Petter Selasky 	}
1509*d6b92ffaSHans Petter Selasky 
1510*d6b92ffaSHans Petter Selasky 	l->end[1].type = f_ep1->type;
1511*d6b92ffaSHans Petter Selasky 	l->end[1].port = f_ep1->port;
1512*d6b92ffaSHans Petter Selasky 	l->end[1].n_id = f_ep1->n_id;
1513*d6b92ffaSHans Petter Selasky 	l->end[1].sw = pg1->sw;
1514*d6b92ffaSHans Petter Selasky 	l->end[1].link = l;
1515*d6b92ffaSHans Petter Selasky 	l->end[1].pgrp = pg1;
1516*d6b92ffaSHans Petter Selasky 	pg1->port[pg1->port_cnt++] = &l->end[1];
1517*d6b92ffaSHans Petter Selasky 	pg1->sw->port[f_ep1->port] = &l->end[1];
1518*d6b92ffaSHans Petter Selasky 
1519*d6b92ffaSHans Petter Selasky 	if (f_ep1->osm_port) {
1520*d6b92ffaSHans Petter Selasky 		l->end[1].osm_port = f_ep1->osm_port;
1521*d6b92ffaSHans Petter Selasky 		l->end[1].osm_port->priv = &l->end[1];
1522*d6b92ffaSHans Petter Selasky 		f_ep1->osm_port = NULL;
1523*d6b92ffaSHans Petter Selasky 	}
1524*d6b92ffaSHans Petter Selasky 	/*
1525*d6b92ffaSHans Petter Selasky 	 * Disconnect fabric link, so that later we can see if any were
1526*d6b92ffaSHans Petter Selasky 	 * left unconnected in the torus.
1527*d6b92ffaSHans Petter Selasky 	 */
1528*d6b92ffaSHans Petter Selasky 	((struct f_switch *)f_ep0->sw)->port[f_ep0->port] = NULL;
1529*d6b92ffaSHans Petter Selasky 	f_ep0->sw = NULL;
1530*d6b92ffaSHans Petter Selasky 	f_ep0->port = -1;
1531*d6b92ffaSHans Petter Selasky 
1532*d6b92ffaSHans Petter Selasky 	((struct f_switch *)f_ep1->sw)->port[f_ep1->port] = NULL;
1533*d6b92ffaSHans Petter Selasky 	f_ep1->sw = NULL;
1534*d6b92ffaSHans Petter Selasky 	f_ep1->port = -1;
1535*d6b92ffaSHans Petter Selasky 
1536*d6b92ffaSHans Petter Selasky 	success = true;
1537*d6b92ffaSHans Petter Selasky out:
1538*d6b92ffaSHans Petter Selasky 	return success;
1539*d6b92ffaSHans Petter Selasky }
1540*d6b92ffaSHans Petter Selasky 
1541*d6b92ffaSHans Petter Selasky static
link_tswitches(struct torus * t,int cdir,struct t_switch * t_sw0,struct t_switch * t_sw1)1542*d6b92ffaSHans Petter Selasky bool link_tswitches(struct torus *t, int cdir,
1543*d6b92ffaSHans Petter Selasky 		    struct t_switch *t_sw0, struct t_switch *t_sw1)
1544*d6b92ffaSHans Petter Selasky {
1545*d6b92ffaSHans Petter Selasky 	int p;
1546*d6b92ffaSHans Petter Selasky 	struct port_grp *pg0, *pg1;
1547*d6b92ffaSHans Petter Selasky 	struct f_switch *f_sw0, *f_sw1;
1548*d6b92ffaSHans Petter Selasky 	const char *cdir_name = "unknown";
1549*d6b92ffaSHans Petter Selasky 	unsigned port_cnt;
1550*d6b92ffaSHans Petter Selasky 	int success = false;
1551*d6b92ffaSHans Petter Selasky 
1552*d6b92ffaSHans Petter Selasky 	/*
1553*d6b92ffaSHans Petter Selasky 	 * If this is a 2D torus, it is possible for this function to be
1554*d6b92ffaSHans Petter Selasky 	 * called with its two switch arguments being the same switch, in
1555*d6b92ffaSHans Petter Selasky 	 * which case there are no links to install.
1556*d6b92ffaSHans Petter Selasky 	 */
1557*d6b92ffaSHans Petter Selasky 	if (t_sw0 == t_sw1 &&
1558*d6b92ffaSHans Petter Selasky 	    ((cdir == 0 && t->x_sz == 1) ||
1559*d6b92ffaSHans Petter Selasky 	     (cdir == 1 && t->y_sz == 1) ||
1560*d6b92ffaSHans Petter Selasky 	     (cdir == 2 && t->z_sz == 1))) {
1561*d6b92ffaSHans Petter Selasky 		success = true;
1562*d6b92ffaSHans Petter Selasky 		goto out;
1563*d6b92ffaSHans Petter Selasky 	}
1564*d6b92ffaSHans Petter Selasky 	/*
1565*d6b92ffaSHans Petter Selasky 	 * Ensure that t_sw1 is in the positive cdir direction wrt. t_sw0.
1566*d6b92ffaSHans Petter Selasky 	 * ring_next_sw() relies on it.
1567*d6b92ffaSHans Petter Selasky 	 */
1568*d6b92ffaSHans Petter Selasky 	switch (cdir) {
1569*d6b92ffaSHans Petter Selasky 	case 0:
1570*d6b92ffaSHans Petter Selasky 		if (t->x_sz > 1 &&
1571*d6b92ffaSHans Petter Selasky 		    canonicalize(t_sw0->i + 1, t->x_sz) != t_sw1->i) {
1572*d6b92ffaSHans Petter Selasky 			cdir_name = "x";
1573*d6b92ffaSHans Petter Selasky 			goto cdir_error;
1574*d6b92ffaSHans Petter Selasky 		}
1575*d6b92ffaSHans Petter Selasky 		break;
1576*d6b92ffaSHans Petter Selasky 	case 1:
1577*d6b92ffaSHans Petter Selasky 		if (t->y_sz > 1 &&
1578*d6b92ffaSHans Petter Selasky 		    canonicalize(t_sw0->j + 1, t->y_sz) != t_sw1->j) {
1579*d6b92ffaSHans Petter Selasky 			cdir_name = "y";
1580*d6b92ffaSHans Petter Selasky 			goto cdir_error;
1581*d6b92ffaSHans Petter Selasky 		}
1582*d6b92ffaSHans Petter Selasky 		break;
1583*d6b92ffaSHans Petter Selasky 	case 2:
1584*d6b92ffaSHans Petter Selasky 		if (t->z_sz > 1 &&
1585*d6b92ffaSHans Petter Selasky 		    canonicalize(t_sw0->k + 1, t->z_sz) != t_sw1->k) {
1586*d6b92ffaSHans Petter Selasky 			cdir_name = "z";
1587*d6b92ffaSHans Petter Selasky 			goto cdir_error;
1588*d6b92ffaSHans Petter Selasky 		}
1589*d6b92ffaSHans Petter Selasky 		break;
1590*d6b92ffaSHans Petter Selasky 	default:
1591*d6b92ffaSHans Petter Selasky 	cdir_error:
1592*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E19: "
1593*d6b92ffaSHans Petter Selasky 			"sw 0x%04"PRIx64" (%d,%d,%d) <--> "
1594*d6b92ffaSHans Petter Selasky 			"sw 0x%04"PRIx64" (%d,%d,%d) "
1595*d6b92ffaSHans Petter Selasky 			"invalid torus %s link orientation\n",
1596*d6b92ffaSHans Petter Selasky 			cl_ntoh64(t_sw0->n_id), t_sw0->i, t_sw0->j, t_sw0->k,
1597*d6b92ffaSHans Petter Selasky 			cl_ntoh64(t_sw1->n_id), t_sw1->i, t_sw1->j, t_sw1->k,
1598*d6b92ffaSHans Petter Selasky 			cdir_name);
1599*d6b92ffaSHans Petter Selasky 		goto out;
1600*d6b92ffaSHans Petter Selasky 	}
1601*d6b92ffaSHans Petter Selasky 
1602*d6b92ffaSHans Petter Selasky 	f_sw0 = t_sw0->tmp;
1603*d6b92ffaSHans Petter Selasky 	f_sw1 = t_sw1->tmp;
1604*d6b92ffaSHans Petter Selasky 
1605*d6b92ffaSHans Petter Selasky 	if (!f_sw0 || !f_sw1) {
1606*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1607*d6b92ffaSHans Petter Selasky 			"ERR 4E1A: missing fabric switches!\n"
1608*d6b92ffaSHans Petter Selasky 			"  switch GUIDs: 0x%04"PRIx64" 0x%04"PRIx64"\n",
1609*d6b92ffaSHans Petter Selasky 			cl_ntoh64(t_sw0->n_id), cl_ntoh64(t_sw1->n_id));
1610*d6b92ffaSHans Petter Selasky 		goto out;
1611*d6b92ffaSHans Petter Selasky 	}
1612*d6b92ffaSHans Petter Selasky 	pg0 = &t_sw0->ptgrp[2*cdir + 1];
1613*d6b92ffaSHans Petter Selasky 	pg0->type = PASSTHRU;
1614*d6b92ffaSHans Petter Selasky 
1615*d6b92ffaSHans Petter Selasky 	pg1 = &t_sw1->ptgrp[2*cdir];
1616*d6b92ffaSHans Petter Selasky 	pg1->type = PASSTHRU;
1617*d6b92ffaSHans Petter Selasky 
1618*d6b92ffaSHans Petter Selasky 	port_cnt = f_sw0->port_cnt;
1619*d6b92ffaSHans Petter Selasky 	/*
1620*d6b92ffaSHans Petter Selasky 	 * Find all the links between these two switches.
1621*d6b92ffaSHans Petter Selasky 	 */
1622*d6b92ffaSHans Petter Selasky 	for (p = 0; p < port_cnt; p++) {
1623*d6b92ffaSHans Petter Selasky 		struct endpoint *f_ep0 = NULL, *f_ep1 = NULL;
1624*d6b92ffaSHans Petter Selasky 
1625*d6b92ffaSHans Petter Selasky 		if (!f_sw0->port[p] || !f_sw0->port[p]->link)
1626*d6b92ffaSHans Petter Selasky 			continue;
1627*d6b92ffaSHans Petter Selasky 
1628*d6b92ffaSHans Petter Selasky 		if (f_sw0->port[p]->link->end[0].n_id == t_sw0->n_id &&
1629*d6b92ffaSHans Petter Selasky 		    f_sw0->port[p]->link->end[1].n_id == t_sw1->n_id) {
1630*d6b92ffaSHans Petter Selasky 
1631*d6b92ffaSHans Petter Selasky 			f_ep0 = &f_sw0->port[p]->link->end[0];
1632*d6b92ffaSHans Petter Selasky 			f_ep1 = &f_sw0->port[p]->link->end[1];
1633*d6b92ffaSHans Petter Selasky 		} else if (f_sw0->port[p]->link->end[1].n_id == t_sw0->n_id &&
1634*d6b92ffaSHans Petter Selasky 			   f_sw0->port[p]->link->end[0].n_id == t_sw1->n_id) {
1635*d6b92ffaSHans Petter Selasky 
1636*d6b92ffaSHans Petter Selasky 			f_ep0 = &f_sw0->port[p]->link->end[1];
1637*d6b92ffaSHans Petter Selasky 			f_ep1 = &f_sw0->port[p]->link->end[0];
1638*d6b92ffaSHans Petter Selasky 		} else
1639*d6b92ffaSHans Petter Selasky 			continue;
1640*d6b92ffaSHans Petter Selasky 
1641*d6b92ffaSHans Petter Selasky 		if (!(f_ep0->type == PASSTHRU && f_ep1->type == PASSTHRU)) {
1642*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1643*d6b92ffaSHans Petter Selasky 				"ERR 4E1B: not interswitch "
1644*d6b92ffaSHans Petter Selasky 				"link:\n  0x%04"PRIx64"/%d <-> 0x%04"PRIx64"/%d\n",
1645*d6b92ffaSHans Petter Selasky 				cl_ntoh64(f_ep0->n_id), f_ep0->port,
1646*d6b92ffaSHans Petter Selasky 				cl_ntoh64(f_ep1->n_id), f_ep1->port);
1647*d6b92ffaSHans Petter Selasky 			goto out;
1648*d6b92ffaSHans Petter Selasky 		}
1649*d6b92ffaSHans Petter Selasky 		/*
1650*d6b92ffaSHans Petter Selasky 		 * Skip over links that already have been established in the
1651*d6b92ffaSHans Petter Selasky 		 * torus.
1652*d6b92ffaSHans Petter Selasky 		 */
1653*d6b92ffaSHans Petter Selasky 		if (!(f_ep0->sw && f_ep1->sw))
1654*d6b92ffaSHans Petter Selasky 			continue;
1655*d6b92ffaSHans Petter Selasky 
1656*d6b92ffaSHans Petter Selasky 		if (!connect_tlink(pg0, f_ep0, pg1, f_ep1, t))
1657*d6b92ffaSHans Petter Selasky 			goto out;
1658*d6b92ffaSHans Petter Selasky 	}
1659*d6b92ffaSHans Petter Selasky 	success = true;
1660*d6b92ffaSHans Petter Selasky out:
1661*d6b92ffaSHans Petter Selasky 	return success;
1662*d6b92ffaSHans Petter Selasky }
1663*d6b92ffaSHans Petter Selasky 
1664*d6b92ffaSHans Petter Selasky static
link_srcsink(struct torus * t,int i,int j,int k)1665*d6b92ffaSHans Petter Selasky bool link_srcsink(struct torus *t, int i, int j, int k)
1666*d6b92ffaSHans Petter Selasky {
1667*d6b92ffaSHans Petter Selasky 	struct endpoint *f_ep0;
1668*d6b92ffaSHans Petter Selasky 	struct endpoint *f_ep1;
1669*d6b92ffaSHans Petter Selasky 	struct t_switch *tsw;
1670*d6b92ffaSHans Petter Selasky 	struct f_switch *fsw;
1671*d6b92ffaSHans Petter Selasky 	struct port_grp *pg;
1672*d6b92ffaSHans Petter Selasky 	struct link *fl, *tl;
1673*d6b92ffaSHans Petter Selasky 	unsigned p, port_cnt;
1674*d6b92ffaSHans Petter Selasky 	bool success = false;
1675*d6b92ffaSHans Petter Selasky 
1676*d6b92ffaSHans Petter Selasky 	i = canonicalize(i, t->x_sz);
1677*d6b92ffaSHans Petter Selasky 	j = canonicalize(j, t->y_sz);
1678*d6b92ffaSHans Petter Selasky 	k = canonicalize(k, t->z_sz);
1679*d6b92ffaSHans Petter Selasky 
1680*d6b92ffaSHans Petter Selasky 	tsw = t->sw[i][j][k];
1681*d6b92ffaSHans Petter Selasky 	if (!tsw)
1682*d6b92ffaSHans Petter Selasky 		return true;
1683*d6b92ffaSHans Petter Selasky 
1684*d6b92ffaSHans Petter Selasky 	fsw = tsw->tmp;
1685*d6b92ffaSHans Petter Selasky 	/*
1686*d6b92ffaSHans Petter Selasky 	 * link_srcsink is supposed to get called once for every switch in
1687*d6b92ffaSHans Petter Selasky 	 * the fabric.  At this point every fsw we encounter must have a
1688*d6b92ffaSHans Petter Selasky 	 * non-null osm_switch.  Otherwise something has gone horribly
1689*d6b92ffaSHans Petter Selasky 	 * wrong with topology discovery; the most likely reason is that
1690*d6b92ffaSHans Petter Selasky 	 * the fabric contains a radix-4 torus dimension, but the user gave
1691*d6b92ffaSHans Petter Selasky 	 * a config that didn't say so, breaking all the checking in
1692*d6b92ffaSHans Petter Selasky 	 * safe_x_perpendicular and friends.
1693*d6b92ffaSHans Petter Selasky 	 */
1694*d6b92ffaSHans Petter Selasky 	if (!(fsw && fsw->osm_switch)) {
1695*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1696*d6b92ffaSHans Petter Selasky 			"ERR 4E1C: Invalid topology discovery. "
1697*d6b92ffaSHans Petter Selasky 			"Verify torus-2QoS.conf contents.\n");
1698*d6b92ffaSHans Petter Selasky 		return false;
1699*d6b92ffaSHans Petter Selasky 	}
1700*d6b92ffaSHans Petter Selasky 
1701*d6b92ffaSHans Petter Selasky 	pg = &tsw->ptgrp[2 * TORUS_MAX_DIM];
1702*d6b92ffaSHans Petter Selasky 	pg->type = SRCSINK;
1703*d6b92ffaSHans Petter Selasky 	tsw->osm_switch = fsw->osm_switch;
1704*d6b92ffaSHans Petter Selasky 	tsw->osm_switch->priv = tsw;
1705*d6b92ffaSHans Petter Selasky 	fsw->osm_switch = NULL;
1706*d6b92ffaSHans Petter Selasky 
1707*d6b92ffaSHans Petter Selasky 	port_cnt = fsw->port_cnt;
1708*d6b92ffaSHans Petter Selasky 	for (p = 0; p < port_cnt; p++) {
1709*d6b92ffaSHans Petter Selasky 
1710*d6b92ffaSHans Petter Selasky 		if (!fsw->port[p])
1711*d6b92ffaSHans Petter Selasky 			continue;
1712*d6b92ffaSHans Petter Selasky 
1713*d6b92ffaSHans Petter Selasky 		if (fsw->port[p]->type == SRCSINK) {
1714*d6b92ffaSHans Petter Selasky 			/*
1715*d6b92ffaSHans Petter Selasky 			 * If the endpoint is the switch port used for in-band
1716*d6b92ffaSHans Petter Selasky 			 * communication with the switch itself, move it to
1717*d6b92ffaSHans Petter Selasky 			 * the torus.
1718*d6b92ffaSHans Petter Selasky 			 */
1719*d6b92ffaSHans Petter Selasky 			if (pg->port_cnt == t->portgrp_sz) {
1720*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1721*d6b92ffaSHans Petter Selasky 					"ERR 4E1D: exceeded port group max port "
1722*d6b92ffaSHans Petter Selasky 					"count (%d): switch GUID 0x%04"PRIx64"\n",
1723*d6b92ffaSHans Petter Selasky 					t->portgrp_sz, cl_ntoh64(tsw->n_id));
1724*d6b92ffaSHans Petter Selasky 				goto out;
1725*d6b92ffaSHans Petter Selasky 			}
1726*d6b92ffaSHans Petter Selasky 			fsw->port[p]->sw = tsw;
1727*d6b92ffaSHans Petter Selasky 			fsw->port[p]->pgrp = pg;
1728*d6b92ffaSHans Petter Selasky 			tsw->port[p] = fsw->port[p];
1729*d6b92ffaSHans Petter Selasky 			tsw->port[p]->osm_port->priv = tsw->port[p];
1730*d6b92ffaSHans Petter Selasky 			pg->port[pg->port_cnt++] = fsw->port[p];
1731*d6b92ffaSHans Petter Selasky 			fsw->port[p] = NULL;
1732*d6b92ffaSHans Petter Selasky 
1733*d6b92ffaSHans Petter Selasky 		} else if (fsw->port[p]->link &&
1734*d6b92ffaSHans Petter Selasky 			   fsw->port[p]->type == PASSTHRU) {
1735*d6b92ffaSHans Petter Selasky 			/*
1736*d6b92ffaSHans Petter Selasky 			 * If the endpoint is a link to a CA, create a new link
1737*d6b92ffaSHans Petter Selasky 			 * in the torus.  Disconnect the fabric link.
1738*d6b92ffaSHans Petter Selasky 			 */
1739*d6b92ffaSHans Petter Selasky 
1740*d6b92ffaSHans Petter Selasky 			fl = fsw->port[p]->link;
1741*d6b92ffaSHans Petter Selasky 
1742*d6b92ffaSHans Petter Selasky 			if (fl->end[0].sw == fsw) {
1743*d6b92ffaSHans Petter Selasky 				f_ep0 = &fl->end[0];
1744*d6b92ffaSHans Petter Selasky 				f_ep1 = &fl->end[1];
1745*d6b92ffaSHans Petter Selasky 			} else if (fl->end[1].sw == fsw) {
1746*d6b92ffaSHans Petter Selasky 				f_ep1 = &fl->end[0];
1747*d6b92ffaSHans Petter Selasky 				f_ep0 = &fl->end[1];
1748*d6b92ffaSHans Petter Selasky 			} else
1749*d6b92ffaSHans Petter Selasky 				continue;
1750*d6b92ffaSHans Petter Selasky 
1751*d6b92ffaSHans Petter Selasky 			if (f_ep1->type != SRCSINK)
1752*d6b92ffaSHans Petter Selasky 				continue;
1753*d6b92ffaSHans Petter Selasky 
1754*d6b92ffaSHans Petter Selasky 			if (pg->port_cnt == t->portgrp_sz) {
1755*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1756*d6b92ffaSHans Petter Selasky 					"ERR 4E1E: exceeded port group max port "
1757*d6b92ffaSHans Petter Selasky 					"count (%d): switch GUID 0x%04"PRIx64"\n",
1758*d6b92ffaSHans Petter Selasky 					t->portgrp_sz, cl_ntoh64(tsw->n_id));
1759*d6b92ffaSHans Petter Selasky 				goto out;
1760*d6b92ffaSHans Petter Selasky 			}
1761*d6b92ffaSHans Petter Selasky 			/*
1762*d6b92ffaSHans Petter Selasky 			 * Switch ports connected to links don't get
1763*d6b92ffaSHans Petter Selasky 			 * associated with osm_port_t objects; see
1764*d6b92ffaSHans Petter Selasky 			 * capture_fabric().  So just check CA end.
1765*d6b92ffaSHans Petter Selasky 			 */
1766*d6b92ffaSHans Petter Selasky 			if (!f_ep1->osm_port) {
1767*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
1768*d6b92ffaSHans Petter Selasky 					"ERR 4E1F: NULL osm_port->priv port "
1769*d6b92ffaSHans Petter Selasky 					"GUID 0x%04"PRIx64"\n",
1770*d6b92ffaSHans Petter Selasky 					cl_ntoh64(f_ep1->n_id));
1771*d6b92ffaSHans Petter Selasky 				goto out;
1772*d6b92ffaSHans Petter Selasky 			}
1773*d6b92ffaSHans Petter Selasky 			tl = alloc_tlink(t);
1774*d6b92ffaSHans Petter Selasky 			if (!tl)
1775*d6b92ffaSHans Petter Selasky 				continue;
1776*d6b92ffaSHans Petter Selasky 
1777*d6b92ffaSHans Petter Selasky 			tl->end[0].type = f_ep0->type;
1778*d6b92ffaSHans Petter Selasky 			tl->end[0].port = f_ep0->port;
1779*d6b92ffaSHans Petter Selasky 			tl->end[0].n_id = f_ep0->n_id;
1780*d6b92ffaSHans Petter Selasky 			tl->end[0].sw = tsw;
1781*d6b92ffaSHans Petter Selasky 			tl->end[0].link = tl;
1782*d6b92ffaSHans Petter Selasky 			tl->end[0].pgrp = pg;
1783*d6b92ffaSHans Petter Selasky 			pg->port[pg->port_cnt++] = &tl->end[0];
1784*d6b92ffaSHans Petter Selasky 			pg->sw->port[f_ep0->port] =  &tl->end[0];
1785*d6b92ffaSHans Petter Selasky 
1786*d6b92ffaSHans Petter Selasky 			tl->end[1].type = f_ep1->type;
1787*d6b92ffaSHans Petter Selasky 			tl->end[1].port = f_ep1->port;
1788*d6b92ffaSHans Petter Selasky 			tl->end[1].n_id = f_ep1->n_id;
1789*d6b92ffaSHans Petter Selasky 			tl->end[1].sw = NULL;	/* Correct for a CA */
1790*d6b92ffaSHans Petter Selasky 			tl->end[1].link = tl;
1791*d6b92ffaSHans Petter Selasky 			tl->end[1].pgrp = NULL;	/* Correct for a CA */
1792*d6b92ffaSHans Petter Selasky 
1793*d6b92ffaSHans Petter Selasky 			tl->end[1].osm_port = f_ep1->osm_port;
1794*d6b92ffaSHans Petter Selasky 			tl->end[1].osm_port->priv = &tl->end[1];
1795*d6b92ffaSHans Petter Selasky 			f_ep1->osm_port = NULL;
1796*d6b92ffaSHans Petter Selasky 
1797*d6b92ffaSHans Petter Selasky 			t->ca_cnt++;
1798*d6b92ffaSHans Petter Selasky 			f_ep0->sw = NULL;
1799*d6b92ffaSHans Petter Selasky 			f_ep0->port = -1;
1800*d6b92ffaSHans Petter Selasky 			fsw->port[p] = NULL;
1801*d6b92ffaSHans Petter Selasky 		}
1802*d6b92ffaSHans Petter Selasky 	}
1803*d6b92ffaSHans Petter Selasky 	success = true;
1804*d6b92ffaSHans Petter Selasky out:
1805*d6b92ffaSHans Petter Selasky 	return success;
1806*d6b92ffaSHans Petter Selasky }
1807*d6b92ffaSHans Petter Selasky 
1808*d6b92ffaSHans Petter Selasky static
ffind_face_corner(struct f_switch * fsw0,struct f_switch * fsw1,struct f_switch * fsw2)1809*d6b92ffaSHans Petter Selasky struct f_switch *ffind_face_corner(struct f_switch *fsw0,
1810*d6b92ffaSHans Petter Selasky 				   struct f_switch *fsw1,
1811*d6b92ffaSHans Petter Selasky 				   struct f_switch *fsw2)
1812*d6b92ffaSHans Petter Selasky {
1813*d6b92ffaSHans Petter Selasky 	int p0, p3;
1814*d6b92ffaSHans Petter Selasky 	struct link *l;
1815*d6b92ffaSHans Petter Selasky 	struct endpoint *far_end;
1816*d6b92ffaSHans Petter Selasky 	struct f_switch *fsw, *fsw3 = NULL;
1817*d6b92ffaSHans Petter Selasky 
1818*d6b92ffaSHans Petter Selasky 	if (!(fsw0 && fsw1 && fsw2))
1819*d6b92ffaSHans Petter Selasky 		goto out;
1820*d6b92ffaSHans Petter Selasky 
1821*d6b92ffaSHans Petter Selasky 	for (p0 = 0; p0 < fsw0->port_cnt; p0++) {
1822*d6b92ffaSHans Petter Selasky 		/*
1823*d6b92ffaSHans Petter Selasky 		 * Ignore everything except switch links that haven't
1824*d6b92ffaSHans Petter Selasky 		 * been installed into the torus.
1825*d6b92ffaSHans Petter Selasky 		 */
1826*d6b92ffaSHans Petter Selasky 		if (!(fsw0->port[p0] && fsw0->port[p0]->sw &&
1827*d6b92ffaSHans Petter Selasky 		      fsw0->port[p0]->type == PASSTHRU))
1828*d6b92ffaSHans Petter Selasky 			continue;
1829*d6b92ffaSHans Petter Selasky 
1830*d6b92ffaSHans Petter Selasky 		l = fsw0->port[p0]->link;
1831*d6b92ffaSHans Petter Selasky 
1832*d6b92ffaSHans Petter Selasky 		if (l->end[0].n_id == fsw0->n_id)
1833*d6b92ffaSHans Petter Selasky 			far_end = &l->end[1];
1834*d6b92ffaSHans Petter Selasky 		else
1835*d6b92ffaSHans Petter Selasky 			far_end = &l->end[0];
1836*d6b92ffaSHans Petter Selasky 
1837*d6b92ffaSHans Petter Selasky 		/*
1838*d6b92ffaSHans Petter Selasky 		 * Ignore CAs
1839*d6b92ffaSHans Petter Selasky 		 */
1840*d6b92ffaSHans Petter Selasky 		if (!(far_end->type == PASSTHRU && far_end->sw))
1841*d6b92ffaSHans Petter Selasky 			continue;
1842*d6b92ffaSHans Petter Selasky 
1843*d6b92ffaSHans Petter Selasky 		fsw3 = far_end->sw;
1844*d6b92ffaSHans Petter Selasky 		if (fsw3->n_id == fsw1->n_id)	/* existing corner */
1845*d6b92ffaSHans Petter Selasky 			continue;
1846*d6b92ffaSHans Petter Selasky 
1847*d6b92ffaSHans Petter Selasky 		for (p3 = 0; p3 < fsw3->port_cnt; p3++) {
1848*d6b92ffaSHans Petter Selasky 			/*
1849*d6b92ffaSHans Petter Selasky 			 * Ignore everything except switch links that haven't
1850*d6b92ffaSHans Petter Selasky 			 * been installed into the torus.
1851*d6b92ffaSHans Petter Selasky 			 */
1852*d6b92ffaSHans Petter Selasky 			if (!(fsw3->port[p3] && fsw3->port[p3]->sw &&
1853*d6b92ffaSHans Petter Selasky 			      fsw3->port[p3]->type == PASSTHRU))
1854*d6b92ffaSHans Petter Selasky 				continue;
1855*d6b92ffaSHans Petter Selasky 
1856*d6b92ffaSHans Petter Selasky 			l = fsw3->port[p3]->link;
1857*d6b92ffaSHans Petter Selasky 
1858*d6b92ffaSHans Petter Selasky 			if (l->end[0].n_id == fsw3->n_id)
1859*d6b92ffaSHans Petter Selasky 				far_end = &l->end[1];
1860*d6b92ffaSHans Petter Selasky 			else
1861*d6b92ffaSHans Petter Selasky 				far_end = &l->end[0];
1862*d6b92ffaSHans Petter Selasky 
1863*d6b92ffaSHans Petter Selasky 			/*
1864*d6b92ffaSHans Petter Selasky 			 * Ignore CAs
1865*d6b92ffaSHans Petter Selasky 			 */
1866*d6b92ffaSHans Petter Selasky 			if (!(far_end->type == PASSTHRU && far_end->sw))
1867*d6b92ffaSHans Petter Selasky 				continue;
1868*d6b92ffaSHans Petter Selasky 
1869*d6b92ffaSHans Petter Selasky 			fsw = far_end->sw;
1870*d6b92ffaSHans Petter Selasky 			if (fsw->n_id == fsw2->n_id)
1871*d6b92ffaSHans Petter Selasky 				goto out;
1872*d6b92ffaSHans Petter Selasky 		}
1873*d6b92ffaSHans Petter Selasky 	}
1874*d6b92ffaSHans Petter Selasky 	fsw3 = NULL;
1875*d6b92ffaSHans Petter Selasky out:
1876*d6b92ffaSHans Petter Selasky 	return fsw3;
1877*d6b92ffaSHans Petter Selasky }
1878*d6b92ffaSHans Petter Selasky 
1879*d6b92ffaSHans Petter Selasky static
tfind_face_corner(struct t_switch * tsw0,struct t_switch * tsw1,struct t_switch * tsw2)1880*d6b92ffaSHans Petter Selasky struct f_switch *tfind_face_corner(struct t_switch *tsw0,
1881*d6b92ffaSHans Petter Selasky 				   struct t_switch *tsw1,
1882*d6b92ffaSHans Petter Selasky 				   struct t_switch *tsw2)
1883*d6b92ffaSHans Petter Selasky {
1884*d6b92ffaSHans Petter Selasky 	if (!(tsw0 && tsw1 && tsw2))
1885*d6b92ffaSHans Petter Selasky 		return NULL;
1886*d6b92ffaSHans Petter Selasky 
1887*d6b92ffaSHans Petter Selasky 	return ffind_face_corner(tsw0->tmp, tsw1->tmp, tsw2->tmp);
1888*d6b92ffaSHans Petter Selasky }
1889*d6b92ffaSHans Petter Selasky 
1890*d6b92ffaSHans Petter Selasky /*
1891*d6b92ffaSHans Petter Selasky  * This code can break on any torus with a dimension that has radix four.
1892*d6b92ffaSHans Petter Selasky  *
1893*d6b92ffaSHans Petter Selasky  * What is supposed to happen is that this code will find the
1894*d6b92ffaSHans Petter Selasky  * two faces whose shared edge is the desired perpendicular.
1895*d6b92ffaSHans Petter Selasky  *
1896*d6b92ffaSHans Petter Selasky  * What actually happens is while searching we send two connected
1897*d6b92ffaSHans Petter Selasky  * edges that are colinear in a torus dimension with radix four to
1898*d6b92ffaSHans Petter Selasky  * ffind_face_corner(), which tries to complete a face by finding a
1899*d6b92ffaSHans Petter Selasky  * 4-loop of edges.
1900*d6b92ffaSHans Petter Selasky  *
1901*d6b92ffaSHans Petter Selasky  * In the radix four torus case, it can find a 4-loop which is a ring in a
1902*d6b92ffaSHans Petter Selasky  * dimension with radix four, rather than the desired face.  It thus returns
1903*d6b92ffaSHans Petter Selasky  * true when it shouldn't, so the wrong edge is returned as the perpendicular.
1904*d6b92ffaSHans Petter Selasky  *
1905*d6b92ffaSHans Petter Selasky  * The appropriate instance of safe_N_perpendicular() (where N == x, y, z)
1906*d6b92ffaSHans Petter Selasky  * should be used to determine if it is safe to call ffind_perpendicular();
1907*d6b92ffaSHans Petter Selasky  * these functions will return false it there is a possibility of finding
1908*d6b92ffaSHans Petter Selasky  * a wrong perpendicular.
1909*d6b92ffaSHans Petter Selasky  */
ffind_3d_perpendicular(struct f_switch * fsw0,struct f_switch * fsw1,struct f_switch * fsw2,struct f_switch * fsw3)1910*d6b92ffaSHans Petter Selasky struct f_switch *ffind_3d_perpendicular(struct f_switch *fsw0,
1911*d6b92ffaSHans Petter Selasky 					struct f_switch *fsw1,
1912*d6b92ffaSHans Petter Selasky 					struct f_switch *fsw2,
1913*d6b92ffaSHans Petter Selasky 					struct f_switch *fsw3)
1914*d6b92ffaSHans Petter Selasky {
1915*d6b92ffaSHans Petter Selasky 	int p1;
1916*d6b92ffaSHans Petter Selasky 	struct link *l;
1917*d6b92ffaSHans Petter Selasky 	struct endpoint *far_end;
1918*d6b92ffaSHans Petter Selasky 	struct f_switch *fsw4 = NULL;
1919*d6b92ffaSHans Petter Selasky 
1920*d6b92ffaSHans Petter Selasky 	if (!(fsw0 && fsw1 && fsw2 && fsw3))
1921*d6b92ffaSHans Petter Selasky 		goto out;
1922*d6b92ffaSHans Petter Selasky 
1923*d6b92ffaSHans Petter Selasky 	/*
1924*d6b92ffaSHans Petter Selasky 	 * Look at all the ports on the switch, fsw1,  that is the base of
1925*d6b92ffaSHans Petter Selasky 	 * the perpendicular.
1926*d6b92ffaSHans Petter Selasky 	 */
1927*d6b92ffaSHans Petter Selasky 	for (p1 = 0; p1 < fsw1->port_cnt; p1++) {
1928*d6b92ffaSHans Petter Selasky 		/*
1929*d6b92ffaSHans Petter Selasky 		 * Ignore everything except switch links that haven't
1930*d6b92ffaSHans Petter Selasky 		 * been installed into the torus.
1931*d6b92ffaSHans Petter Selasky 		 */
1932*d6b92ffaSHans Petter Selasky 		if (!(fsw1->port[p1] && fsw1->port[p1]->sw &&
1933*d6b92ffaSHans Petter Selasky 		      fsw1->port[p1]->type == PASSTHRU))
1934*d6b92ffaSHans Petter Selasky 			continue;
1935*d6b92ffaSHans Petter Selasky 
1936*d6b92ffaSHans Petter Selasky 		l = fsw1->port[p1]->link;
1937*d6b92ffaSHans Petter Selasky 
1938*d6b92ffaSHans Petter Selasky 		if (l->end[0].n_id == fsw1->n_id)
1939*d6b92ffaSHans Petter Selasky 			far_end = &l->end[1];
1940*d6b92ffaSHans Petter Selasky 		else
1941*d6b92ffaSHans Petter Selasky 			far_end = &l->end[0];
1942*d6b92ffaSHans Petter Selasky 		/*
1943*d6b92ffaSHans Petter Selasky 		 * Ignore CAs
1944*d6b92ffaSHans Petter Selasky 		 */
1945*d6b92ffaSHans Petter Selasky 		if (!(far_end->type == PASSTHRU && far_end->sw))
1946*d6b92ffaSHans Petter Selasky 			continue;
1947*d6b92ffaSHans Petter Selasky 
1948*d6b92ffaSHans Petter Selasky 		fsw4 = far_end->sw;
1949*d6b92ffaSHans Petter Selasky 		if (fsw4->n_id == fsw3->n_id)	/* wrong perpendicular */
1950*d6b92ffaSHans Petter Selasky 			continue;
1951*d6b92ffaSHans Petter Selasky 
1952*d6b92ffaSHans Petter Selasky 		if (ffind_face_corner(fsw0, fsw1, fsw4) &&
1953*d6b92ffaSHans Petter Selasky 		    ffind_face_corner(fsw2, fsw1, fsw4))
1954*d6b92ffaSHans Petter Selasky 			goto out;
1955*d6b92ffaSHans Petter Selasky 	}
1956*d6b92ffaSHans Petter Selasky 	fsw4 = NULL;
1957*d6b92ffaSHans Petter Selasky out:
1958*d6b92ffaSHans Petter Selasky 	return fsw4;
1959*d6b92ffaSHans Petter Selasky }
ffind_2d_perpendicular(struct f_switch * fsw0,struct f_switch * fsw1,struct f_switch * fsw2)1960*d6b92ffaSHans Petter Selasky struct f_switch *ffind_2d_perpendicular(struct f_switch *fsw0,
1961*d6b92ffaSHans Petter Selasky 					struct f_switch *fsw1,
1962*d6b92ffaSHans Petter Selasky 					struct f_switch *fsw2)
1963*d6b92ffaSHans Petter Selasky {
1964*d6b92ffaSHans Petter Selasky 	int p1;
1965*d6b92ffaSHans Petter Selasky 	struct link *l;
1966*d6b92ffaSHans Petter Selasky 	struct endpoint *far_end;
1967*d6b92ffaSHans Petter Selasky 	struct f_switch *fsw3 = NULL;
1968*d6b92ffaSHans Petter Selasky 
1969*d6b92ffaSHans Petter Selasky 	if (!(fsw0 && fsw1 && fsw2))
1970*d6b92ffaSHans Petter Selasky 		goto out;
1971*d6b92ffaSHans Petter Selasky 
1972*d6b92ffaSHans Petter Selasky 	/*
1973*d6b92ffaSHans Petter Selasky 	 * Look at all the ports on the switch, fsw1,  that is the base of
1974*d6b92ffaSHans Petter Selasky 	 * the perpendicular.
1975*d6b92ffaSHans Petter Selasky 	 */
1976*d6b92ffaSHans Petter Selasky 	for (p1 = 0; p1 < fsw1->port_cnt; p1++) {
1977*d6b92ffaSHans Petter Selasky 		/*
1978*d6b92ffaSHans Petter Selasky 		 * Ignore everything except switch links that haven't
1979*d6b92ffaSHans Petter Selasky 		 * been installed into the torus.
1980*d6b92ffaSHans Petter Selasky 		 */
1981*d6b92ffaSHans Petter Selasky 		if (!(fsw1->port[p1] && fsw1->port[p1]->sw &&
1982*d6b92ffaSHans Petter Selasky 		      fsw1->port[p1]->type == PASSTHRU))
1983*d6b92ffaSHans Petter Selasky 			continue;
1984*d6b92ffaSHans Petter Selasky 
1985*d6b92ffaSHans Petter Selasky 		l = fsw1->port[p1]->link;
1986*d6b92ffaSHans Petter Selasky 
1987*d6b92ffaSHans Petter Selasky 		if (l->end[0].n_id == fsw1->n_id)
1988*d6b92ffaSHans Petter Selasky 			far_end = &l->end[1];
1989*d6b92ffaSHans Petter Selasky 		else
1990*d6b92ffaSHans Petter Selasky 			far_end = &l->end[0];
1991*d6b92ffaSHans Petter Selasky 		/*
1992*d6b92ffaSHans Petter Selasky 		 * Ignore CAs
1993*d6b92ffaSHans Petter Selasky 		 */
1994*d6b92ffaSHans Petter Selasky 		if (!(far_end->type == PASSTHRU && far_end->sw))
1995*d6b92ffaSHans Petter Selasky 			continue;
1996*d6b92ffaSHans Petter Selasky 
1997*d6b92ffaSHans Petter Selasky 		fsw3 = far_end->sw;
1998*d6b92ffaSHans Petter Selasky 		if (fsw3->n_id == fsw2->n_id)	/* wrong perpendicular */
1999*d6b92ffaSHans Petter Selasky 			continue;
2000*d6b92ffaSHans Petter Selasky 
2001*d6b92ffaSHans Petter Selasky 		if (ffind_face_corner(fsw0, fsw1, fsw3))
2002*d6b92ffaSHans Petter Selasky 			goto out;
2003*d6b92ffaSHans Petter Selasky 	}
2004*d6b92ffaSHans Petter Selasky 	fsw3 = NULL;
2005*d6b92ffaSHans Petter Selasky out:
2006*d6b92ffaSHans Petter Selasky 	return fsw3;
2007*d6b92ffaSHans Petter Selasky }
2008*d6b92ffaSHans Petter Selasky 
2009*d6b92ffaSHans Petter Selasky static
tfind_3d_perpendicular(struct t_switch * tsw0,struct t_switch * tsw1,struct t_switch * tsw2,struct t_switch * tsw3)2010*d6b92ffaSHans Petter Selasky struct f_switch *tfind_3d_perpendicular(struct t_switch *tsw0,
2011*d6b92ffaSHans Petter Selasky 					struct t_switch *tsw1,
2012*d6b92ffaSHans Petter Selasky 					struct t_switch *tsw2,
2013*d6b92ffaSHans Petter Selasky 					struct t_switch *tsw3)
2014*d6b92ffaSHans Petter Selasky {
2015*d6b92ffaSHans Petter Selasky 	if (!(tsw0 && tsw1 && tsw2 && tsw3))
2016*d6b92ffaSHans Petter Selasky 		return NULL;
2017*d6b92ffaSHans Petter Selasky 
2018*d6b92ffaSHans Petter Selasky 	return ffind_3d_perpendicular(tsw0->tmp, tsw1->tmp,
2019*d6b92ffaSHans Petter Selasky 				      tsw2->tmp, tsw3->tmp);
2020*d6b92ffaSHans Petter Selasky }
2021*d6b92ffaSHans Petter Selasky 
2022*d6b92ffaSHans Petter Selasky static
tfind_2d_perpendicular(struct t_switch * tsw0,struct t_switch * tsw1,struct t_switch * tsw2)2023*d6b92ffaSHans Petter Selasky struct f_switch *tfind_2d_perpendicular(struct t_switch *tsw0,
2024*d6b92ffaSHans Petter Selasky 					struct t_switch *tsw1,
2025*d6b92ffaSHans Petter Selasky 					struct t_switch *tsw2)
2026*d6b92ffaSHans Petter Selasky {
2027*d6b92ffaSHans Petter Selasky 	if (!(tsw0 && tsw1 && tsw2))
2028*d6b92ffaSHans Petter Selasky 		return NULL;
2029*d6b92ffaSHans Petter Selasky 
2030*d6b92ffaSHans Petter Selasky 	return ffind_2d_perpendicular(tsw0->tmp, tsw1->tmp, tsw2->tmp);
2031*d6b92ffaSHans Petter Selasky }
2032*d6b92ffaSHans Petter Selasky 
2033*d6b92ffaSHans Petter Selasky static
safe_x_ring(struct torus * t,int i,int j,int k)2034*d6b92ffaSHans Petter Selasky bool safe_x_ring(struct torus *t, int i, int j, int k)
2035*d6b92ffaSHans Petter Selasky {
2036*d6b92ffaSHans Petter Selasky 	int im1, ip1, ip2;
2037*d6b92ffaSHans Petter Selasky 	bool success = true;
2038*d6b92ffaSHans Petter Selasky 
2039*d6b92ffaSHans Petter Selasky 	/*
2040*d6b92ffaSHans Petter Selasky 	 * If this x-direction radix-4 ring has at least two links
2041*d6b92ffaSHans Petter Selasky 	 * already installed into the torus,  then this ring does not
2042*d6b92ffaSHans Petter Selasky 	 * prevent us from looking for y or z direction perpendiculars.
2043*d6b92ffaSHans Petter Selasky 	 *
2044*d6b92ffaSHans Petter Selasky 	 * It is easier to check for the appropriate switches being installed
2045*d6b92ffaSHans Petter Selasky 	 * into the torus than it is to check for the links, so force the
2046*d6b92ffaSHans Petter Selasky 	 * link installation if the appropriate switches are installed.
2047*d6b92ffaSHans Petter Selasky 	 *
2048*d6b92ffaSHans Petter Selasky 	 * Recall that canonicalize(n - 2, 4) == canonicalize(n + 2, 4).
2049*d6b92ffaSHans Petter Selasky 	 */
2050*d6b92ffaSHans Petter Selasky 	if (t->x_sz != 4 || t->flags & X_MESH)
2051*d6b92ffaSHans Petter Selasky 		goto out;
2052*d6b92ffaSHans Petter Selasky 
2053*d6b92ffaSHans Petter Selasky 	im1 = canonicalize(i - 1, t->x_sz);
2054*d6b92ffaSHans Petter Selasky 	ip1 = canonicalize(i + 1, t->x_sz);
2055*d6b92ffaSHans Petter Selasky 	ip2 = canonicalize(i + 2, t->x_sz);
2056*d6b92ffaSHans Petter Selasky 
2057*d6b92ffaSHans Petter Selasky 	if (!!t->sw[im1][j][k] +
2058*d6b92ffaSHans Petter Selasky 	    !!t->sw[ip1][j][k] + !!t->sw[ip2][j][k] < 2) {
2059*d6b92ffaSHans Petter Selasky 		success = false;
2060*d6b92ffaSHans Petter Selasky 		goto out;
2061*d6b92ffaSHans Petter Selasky 	}
2062*d6b92ffaSHans Petter Selasky 	if (t->sw[ip2][j][k] && t->sw[im1][j][k])
2063*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 0,
2064*d6b92ffaSHans Petter Selasky 					 t->sw[ip2][j][k],
2065*d6b92ffaSHans Petter Selasky 					 t->sw[im1][j][k])
2066*d6b92ffaSHans Petter Selasky 			&& success;
2067*d6b92ffaSHans Petter Selasky 
2068*d6b92ffaSHans Petter Selasky 	if (t->sw[im1][j][k] && t->sw[i][j][k])
2069*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 0,
2070*d6b92ffaSHans Petter Selasky 					 t->sw[im1][j][k],
2071*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][k])
2072*d6b92ffaSHans Petter Selasky 			&& success;
2073*d6b92ffaSHans Petter Selasky 
2074*d6b92ffaSHans Petter Selasky 	if (t->sw[i][j][k] && t->sw[ip1][j][k])
2075*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 0,
2076*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][k],
2077*d6b92ffaSHans Petter Selasky 					 t->sw[ip1][j][k])
2078*d6b92ffaSHans Petter Selasky 			&& success;
2079*d6b92ffaSHans Petter Selasky 
2080*d6b92ffaSHans Petter Selasky 	if (t->sw[ip1][j][k] && t->sw[ip2][j][k])
2081*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 0,
2082*d6b92ffaSHans Petter Selasky 					 t->sw[ip1][j][k],
2083*d6b92ffaSHans Petter Selasky 					 t->sw[ip2][j][k])
2084*d6b92ffaSHans Petter Selasky 			&& success;
2085*d6b92ffaSHans Petter Selasky out:
2086*d6b92ffaSHans Petter Selasky 	return success;
2087*d6b92ffaSHans Petter Selasky }
2088*d6b92ffaSHans Petter Selasky 
2089*d6b92ffaSHans Petter Selasky static
safe_y_ring(struct torus * t,int i,int j,int k)2090*d6b92ffaSHans Petter Selasky bool safe_y_ring(struct torus *t, int i, int j, int k)
2091*d6b92ffaSHans Petter Selasky {
2092*d6b92ffaSHans Petter Selasky 	int jm1, jp1, jp2;
2093*d6b92ffaSHans Petter Selasky 	bool success = true;
2094*d6b92ffaSHans Petter Selasky 
2095*d6b92ffaSHans Petter Selasky 	/*
2096*d6b92ffaSHans Petter Selasky 	 * If this y-direction radix-4 ring has at least two links
2097*d6b92ffaSHans Petter Selasky 	 * already installed into the torus,  then this ring does not
2098*d6b92ffaSHans Petter Selasky 	 * prevent us from looking for x or z direction perpendiculars.
2099*d6b92ffaSHans Petter Selasky 	 *
2100*d6b92ffaSHans Petter Selasky 	 * It is easier to check for the appropriate switches being installed
2101*d6b92ffaSHans Petter Selasky 	 * into the torus than it is to check for the links, so force the
2102*d6b92ffaSHans Petter Selasky 	 * link installation if the appropriate switches are installed.
2103*d6b92ffaSHans Petter Selasky 	 *
2104*d6b92ffaSHans Petter Selasky 	 * Recall that canonicalize(n - 2, 4) == canonicalize(n + 2, 4).
2105*d6b92ffaSHans Petter Selasky 	 */
2106*d6b92ffaSHans Petter Selasky 	if (t->y_sz != 4 || (t->flags & Y_MESH))
2107*d6b92ffaSHans Petter Selasky 		goto out;
2108*d6b92ffaSHans Petter Selasky 
2109*d6b92ffaSHans Petter Selasky 	jm1 = canonicalize(j - 1, t->y_sz);
2110*d6b92ffaSHans Petter Selasky 	jp1 = canonicalize(j + 1, t->y_sz);
2111*d6b92ffaSHans Petter Selasky 	jp2 = canonicalize(j + 2, t->y_sz);
2112*d6b92ffaSHans Petter Selasky 
2113*d6b92ffaSHans Petter Selasky 	if (!!t->sw[i][jm1][k] +
2114*d6b92ffaSHans Petter Selasky 	    !!t->sw[i][jp1][k] + !!t->sw[i][jp2][k] < 2) {
2115*d6b92ffaSHans Petter Selasky 		success = false;
2116*d6b92ffaSHans Petter Selasky 		goto out;
2117*d6b92ffaSHans Petter Selasky 	}
2118*d6b92ffaSHans Petter Selasky 	if (t->sw[i][jp2][k] && t->sw[i][jm1][k])
2119*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 1,
2120*d6b92ffaSHans Petter Selasky 					 t->sw[i][jp2][k],
2121*d6b92ffaSHans Petter Selasky 					 t->sw[i][jm1][k])
2122*d6b92ffaSHans Petter Selasky 			&& success;
2123*d6b92ffaSHans Petter Selasky 
2124*d6b92ffaSHans Petter Selasky 	if (t->sw[i][jm1][k] && t->sw[i][j][k])
2125*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 1,
2126*d6b92ffaSHans Petter Selasky 					 t->sw[i][jm1][k],
2127*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][k])
2128*d6b92ffaSHans Petter Selasky 			&& success;
2129*d6b92ffaSHans Petter Selasky 
2130*d6b92ffaSHans Petter Selasky 	if (t->sw[i][j][k] && t->sw[i][jp1][k])
2131*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 1,
2132*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][k],
2133*d6b92ffaSHans Petter Selasky 					 t->sw[i][jp1][k])
2134*d6b92ffaSHans Petter Selasky 			&& success;
2135*d6b92ffaSHans Petter Selasky 
2136*d6b92ffaSHans Petter Selasky 	if (t->sw[i][jp1][k] && t->sw[i][jp2][k])
2137*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 1,
2138*d6b92ffaSHans Petter Selasky 					 t->sw[i][jp1][k],
2139*d6b92ffaSHans Petter Selasky 					 t->sw[i][jp2][k])
2140*d6b92ffaSHans Petter Selasky 			&& success;
2141*d6b92ffaSHans Petter Selasky out:
2142*d6b92ffaSHans Petter Selasky 	return success;
2143*d6b92ffaSHans Petter Selasky }
2144*d6b92ffaSHans Petter Selasky 
2145*d6b92ffaSHans Petter Selasky static
safe_z_ring(struct torus * t,int i,int j,int k)2146*d6b92ffaSHans Petter Selasky bool safe_z_ring(struct torus *t, int i, int j, int k)
2147*d6b92ffaSHans Petter Selasky {
2148*d6b92ffaSHans Petter Selasky 	int km1, kp1, kp2;
2149*d6b92ffaSHans Petter Selasky 	bool success = true;
2150*d6b92ffaSHans Petter Selasky 
2151*d6b92ffaSHans Petter Selasky 	/*
2152*d6b92ffaSHans Petter Selasky 	 * If this z-direction radix-4 ring has at least two links
2153*d6b92ffaSHans Petter Selasky 	 * already installed into the torus,  then this ring does not
2154*d6b92ffaSHans Petter Selasky 	 * prevent us from looking for x or y direction perpendiculars.
2155*d6b92ffaSHans Petter Selasky 	 *
2156*d6b92ffaSHans Petter Selasky 	 * It is easier to check for the appropriate switches being installed
2157*d6b92ffaSHans Petter Selasky 	 * into the torus than it is to check for the links, so force the
2158*d6b92ffaSHans Petter Selasky 	 * link installation if the appropriate switches are installed.
2159*d6b92ffaSHans Petter Selasky 	 *
2160*d6b92ffaSHans Petter Selasky 	 * Recall that canonicalize(n - 2, 4) == canonicalize(n + 2, 4).
2161*d6b92ffaSHans Petter Selasky 	 */
2162*d6b92ffaSHans Petter Selasky 	if (t->z_sz != 4 || t->flags & Z_MESH)
2163*d6b92ffaSHans Petter Selasky 		goto out;
2164*d6b92ffaSHans Petter Selasky 
2165*d6b92ffaSHans Petter Selasky 	km1 = canonicalize(k - 1, t->z_sz);
2166*d6b92ffaSHans Petter Selasky 	kp1 = canonicalize(k + 1, t->z_sz);
2167*d6b92ffaSHans Petter Selasky 	kp2 = canonicalize(k + 2, t->z_sz);
2168*d6b92ffaSHans Petter Selasky 
2169*d6b92ffaSHans Petter Selasky 	if (!!t->sw[i][j][km1] +
2170*d6b92ffaSHans Petter Selasky 	    !!t->sw[i][j][kp1] + !!t->sw[i][j][kp2] < 2) {
2171*d6b92ffaSHans Petter Selasky 		success = false;
2172*d6b92ffaSHans Petter Selasky 		goto out;
2173*d6b92ffaSHans Petter Selasky 	}
2174*d6b92ffaSHans Petter Selasky 	if (t->sw[i][j][kp2] && t->sw[i][j][km1])
2175*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 2,
2176*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][kp2],
2177*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][km1])
2178*d6b92ffaSHans Petter Selasky 			&& success;
2179*d6b92ffaSHans Petter Selasky 
2180*d6b92ffaSHans Petter Selasky 	if (t->sw[i][j][km1] && t->sw[i][j][k])
2181*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 2,
2182*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][km1],
2183*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][k])
2184*d6b92ffaSHans Petter Selasky 			&& success;
2185*d6b92ffaSHans Petter Selasky 
2186*d6b92ffaSHans Petter Selasky 	if (t->sw[i][j][k] && t->sw[i][j][kp1])
2187*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 2,
2188*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][k],
2189*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][kp1])
2190*d6b92ffaSHans Petter Selasky 			&& success;
2191*d6b92ffaSHans Petter Selasky 
2192*d6b92ffaSHans Petter Selasky 	if (t->sw[i][j][kp1] && t->sw[i][j][kp2])
2193*d6b92ffaSHans Petter Selasky 		success = link_tswitches(t, 2,
2194*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][kp1],
2195*d6b92ffaSHans Petter Selasky 					 t->sw[i][j][kp2])
2196*d6b92ffaSHans Petter Selasky 			&& success;
2197*d6b92ffaSHans Petter Selasky out:
2198*d6b92ffaSHans Petter Selasky 	return success;
2199*d6b92ffaSHans Petter Selasky }
2200*d6b92ffaSHans Petter Selasky 
2201*d6b92ffaSHans Petter Selasky /*
2202*d6b92ffaSHans Petter Selasky  * These functions return true when it safe to call
2203*d6b92ffaSHans Petter Selasky  * tfind_3d_perpendicular()/ffind_3d_perpendicular().
2204*d6b92ffaSHans Petter Selasky  */
2205*d6b92ffaSHans Petter Selasky static
safe_x_perpendicular(struct torus * t,int i,int j,int k)2206*d6b92ffaSHans Petter Selasky bool safe_x_perpendicular(struct torus *t, int i, int j, int k)
2207*d6b92ffaSHans Petter Selasky {
2208*d6b92ffaSHans Petter Selasky 	/*
2209*d6b92ffaSHans Petter Selasky 	 * If the dimensions perpendicular to the search direction are
2210*d6b92ffaSHans Petter Selasky 	 * not radix 4 torus dimensions, it is always safe to search for
2211*d6b92ffaSHans Petter Selasky 	 * a perpendicular.
2212*d6b92ffaSHans Petter Selasky 	 *
2213*d6b92ffaSHans Petter Selasky 	 * Here we are checking for enough appropriate links having been
2214*d6b92ffaSHans Petter Selasky 	 * installed into the torus to prevent an incorrect link from being
2215*d6b92ffaSHans Petter Selasky 	 * considered as a perpendicular candidate.
2216*d6b92ffaSHans Petter Selasky 	 */
2217*d6b92ffaSHans Petter Selasky 	return safe_y_ring(t, i, j, k) && safe_z_ring(t, i, j, k);
2218*d6b92ffaSHans Petter Selasky }
2219*d6b92ffaSHans Petter Selasky 
2220*d6b92ffaSHans Petter Selasky static
safe_y_perpendicular(struct torus * t,int i,int j,int k)2221*d6b92ffaSHans Petter Selasky bool safe_y_perpendicular(struct torus *t, int i, int j, int k)
2222*d6b92ffaSHans Petter Selasky {
2223*d6b92ffaSHans Petter Selasky 	/*
2224*d6b92ffaSHans Petter Selasky 	 * If the dimensions perpendicular to the search direction are
2225*d6b92ffaSHans Petter Selasky 	 * not radix 4 torus dimensions, it is always safe to search for
2226*d6b92ffaSHans Petter Selasky 	 * a perpendicular.
2227*d6b92ffaSHans Petter Selasky 	 *
2228*d6b92ffaSHans Petter Selasky 	 * Here we are checking for enough appropriate links having been
2229*d6b92ffaSHans Petter Selasky 	 * installed into the torus to prevent an incorrect link from being
2230*d6b92ffaSHans Petter Selasky 	 * considered as a perpendicular candidate.
2231*d6b92ffaSHans Petter Selasky 	 */
2232*d6b92ffaSHans Petter Selasky 	return safe_x_ring(t, i, j, k) && safe_z_ring(t, i, j, k);
2233*d6b92ffaSHans Petter Selasky }
2234*d6b92ffaSHans Petter Selasky 
2235*d6b92ffaSHans Petter Selasky static
safe_z_perpendicular(struct torus * t,int i,int j,int k)2236*d6b92ffaSHans Petter Selasky bool safe_z_perpendicular(struct torus *t, int i, int j, int k)
2237*d6b92ffaSHans Petter Selasky {
2238*d6b92ffaSHans Petter Selasky 	/*
2239*d6b92ffaSHans Petter Selasky 	 * If the dimensions perpendicular to the search direction are
2240*d6b92ffaSHans Petter Selasky 	 * not radix 4 torus dimensions, it is always safe to search for
2241*d6b92ffaSHans Petter Selasky 	 * a perpendicular.
2242*d6b92ffaSHans Petter Selasky 	 *
2243*d6b92ffaSHans Petter Selasky 	 * Implement this by checking for enough appropriate links having
2244*d6b92ffaSHans Petter Selasky 	 * been installed into the torus to prevent an incorrect link from
2245*d6b92ffaSHans Petter Selasky 	 * being considered as a perpendicular candidate.
2246*d6b92ffaSHans Petter Selasky 	 */
2247*d6b92ffaSHans Petter Selasky 	return safe_x_ring(t, i, j, k) && safe_y_ring(t, i, j, k);
2248*d6b92ffaSHans Petter Selasky }
2249*d6b92ffaSHans Petter Selasky 
2250*d6b92ffaSHans Petter Selasky /*
2251*d6b92ffaSHans Petter Selasky  * Templates for determining 2D/3D case fingerprints. Recall that if
2252*d6b92ffaSHans Petter Selasky  * a fingerprint bit is set the corresponding switch is absent from
2253*d6b92ffaSHans Petter Selasky  * the all-switches-present template.
2254*d6b92ffaSHans Petter Selasky  *
2255*d6b92ffaSHans Petter Selasky  * I.e., for the 2D case where the x,y dimensions have a radix greater
2256*d6b92ffaSHans Petter Selasky  * than one, and the z dimension has radix 1, fingerprint bits 4-7 are
2257*d6b92ffaSHans Petter Selasky  * always zero.
2258*d6b92ffaSHans Petter Selasky  *
2259*d6b92ffaSHans Petter Selasky  * For the 2D case where the x,z dimensions have a radix greater than
2260*d6b92ffaSHans Petter Selasky  * one, and the y dimension has radix 1, fingerprint bits 2,3,6,7 are
2261*d6b92ffaSHans Petter Selasky  * always zero.
2262*d6b92ffaSHans Petter Selasky  *
2263*d6b92ffaSHans Petter Selasky  * For the 2D case where the y,z dimensions have a radix greater than
2264*d6b92ffaSHans Petter Selasky  * one, and the x dimension has radix 1, fingerprint bits 1,3,5,7 are
2265*d6b92ffaSHans Petter Selasky  * always zero.
2266*d6b92ffaSHans Petter Selasky  *
2267*d6b92ffaSHans Petter Selasky  * Recall also that bits 8-10 distinguish between 2D and 3D cases.
2268*d6b92ffaSHans Petter Selasky  * If bit 8+d is set, for 0 <= d < 3;  the d dimension of the desired
2269*d6b92ffaSHans Petter Selasky  * torus has radix greater than 1.
2270*d6b92ffaSHans Petter Selasky  */
2271*d6b92ffaSHans Petter Selasky 
2272*d6b92ffaSHans Petter Selasky /*
2273*d6b92ffaSHans Petter Selasky  * 2D case 0x300
2274*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][0  ]
2275*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][0  ]
2276*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][0  ]
2277*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][0  ]
2278*d6b92ffaSHans Petter Selasky  *                                    O . . . . . O
2279*d6b92ffaSHans Petter Selasky  * 2D case 0x500                      .           .
2280*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][0  ][k  ]          .           .
2281*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][0  ][k  ]          .           .
2282*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][0  ][k+1]          .           .
2283*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][0  ][k+1]          .           .
2284*d6b92ffaSHans Petter Selasky  *                                    @ . . . . . O
2285*d6b92ffaSHans Petter Selasky  * 2D case 0x600
2286*d6b92ffaSHans Petter Selasky  *  b0: t->sw[0  ][j  ][k  ]
2287*d6b92ffaSHans Petter Selasky  *  b2: t->sw[0  ][j+1][k  ]
2288*d6b92ffaSHans Petter Selasky  *  b4: t->sw[0  ][j  ][k+1]
2289*d6b92ffaSHans Petter Selasky  *  b6: t->sw[0  ][j+1][k+1]
2290*d6b92ffaSHans Petter Selasky  */
2291*d6b92ffaSHans Petter Selasky 
2292*d6b92ffaSHans Petter Selasky /*
2293*d6b92ffaSHans Petter Selasky  * 3D case 0x700:                           O
2294*d6b92ffaSHans Petter Selasky  *                                        . . .
2295*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .   .
2296*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
2297*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
2298*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
2299*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       . .
2300*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .   .   .   .   .
2301*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
2302*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .   .   .   .
2303*d6b92ffaSHans Petter Selasky  *                                . .       O       . .
2304*d6b92ffaSHans Petter Selasky  *                                O         .         O
2305*d6b92ffaSHans Petter Selasky  *                                  .       .       .
2306*d6b92ffaSHans Petter Selasky  *                                    .     .     .
2307*d6b92ffaSHans Petter Selasky  *                                      .   .   .
2308*d6b92ffaSHans Petter Selasky  *                                        . . .
2309*d6b92ffaSHans Petter Selasky  *                                          @
2310*d6b92ffaSHans Petter Selasky  */
2311*d6b92ffaSHans Petter Selasky 
2312*d6b92ffaSHans Petter Selasky static
log_no_crnr(struct torus * t,unsigned n,int case_i,int case_j,int case_k,int crnr_i,int crnr_j,int crnr_k)2313*d6b92ffaSHans Petter Selasky void log_no_crnr(struct torus *t, unsigned n,
2314*d6b92ffaSHans Petter Selasky 		 int case_i, int case_j, int case_k,
2315*d6b92ffaSHans Petter Selasky 		 int crnr_i, int crnr_j, int crnr_k)
2316*d6b92ffaSHans Petter Selasky {
2317*d6b92ffaSHans Petter Selasky 	if (t->debug)
2318*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Case 0x%03x "
2319*d6b92ffaSHans Petter Selasky 			"@ %d %d %d: no corner @ %d %d %d\n",
2320*d6b92ffaSHans Petter Selasky 			n, case_i, case_j, case_k, crnr_i, crnr_j, crnr_k);
2321*d6b92ffaSHans Petter Selasky }
2322*d6b92ffaSHans Petter Selasky 
2323*d6b92ffaSHans Petter Selasky static
log_no_perp(struct torus * t,unsigned n,int case_i,int case_j,int case_k,int perp_i,int perp_j,int perp_k)2324*d6b92ffaSHans Petter Selasky void log_no_perp(struct torus *t, unsigned n,
2325*d6b92ffaSHans Petter Selasky 		 int case_i, int case_j, int case_k,
2326*d6b92ffaSHans Petter Selasky 		 int perp_i, int perp_j, int perp_k)
2327*d6b92ffaSHans Petter Selasky {
2328*d6b92ffaSHans Petter Selasky 	if (t->debug)
2329*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Case 0x%03x "
2330*d6b92ffaSHans Petter Selasky 			"@ %d %d %d: no perpendicular @ %d %d %d\n",
2331*d6b92ffaSHans Petter Selasky 			n, case_i, case_j, case_k, perp_i, perp_j, perp_k);
2332*d6b92ffaSHans Petter Selasky }
2333*d6b92ffaSHans Petter Selasky 
2334*d6b92ffaSHans Petter Selasky /*
2335*d6b92ffaSHans Petter Selasky  * Handle the 2D cases with a single existing edge.
2336*d6b92ffaSHans Petter Selasky  *
2337*d6b92ffaSHans Petter Selasky  */
2338*d6b92ffaSHans Petter Selasky 
2339*d6b92ffaSHans Petter Selasky /*
2340*d6b92ffaSHans Petter Selasky  * 2D case 0x30c
2341*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][0  ]
2342*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][0  ]
2343*d6b92ffaSHans Petter Selasky  *  b2:
2344*d6b92ffaSHans Petter Selasky  *  b3:
2345*d6b92ffaSHans Petter Selasky  *                                    O           O
2346*d6b92ffaSHans Petter Selasky  * 2D case 0x530
2347*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][0  ][k  ]
2348*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][0  ][k  ]
2349*d6b92ffaSHans Petter Selasky  *  b4:
2350*d6b92ffaSHans Petter Selasky  *  b5:
2351*d6b92ffaSHans Petter Selasky  *                                    @ . . . . . O
2352*d6b92ffaSHans Petter Selasky  * 2D case 0x650
2353*d6b92ffaSHans Petter Selasky  *  b0: t->sw[0  ][j  ][k  ]
2354*d6b92ffaSHans Petter Selasky  *  b2: t->sw[0  ][j+1][k  ]
2355*d6b92ffaSHans Petter Selasky  *  b4:
2356*d6b92ffaSHans Petter Selasky  *  b6:
2357*d6b92ffaSHans Petter Selasky  */
2358*d6b92ffaSHans Petter Selasky static
handle_case_0x30c(struct torus * t,int i,int j,int k)2359*d6b92ffaSHans Petter Selasky bool handle_case_0x30c(struct torus *t, int i, int j, int k)
2360*d6b92ffaSHans Petter Selasky {
2361*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2362*d6b92ffaSHans Petter Selasky 	int jm1 = canonicalize(j - 1, t->y_sz);
2363*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2364*d6b92ffaSHans Petter Selasky 
2365*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, j, k) &&
2366*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
2367*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][j][k],
2368*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
2369*d6b92ffaSHans Petter Selasky 						   t->sw[i][jm1][k]))) {
2370*d6b92ffaSHans Petter Selasky 		return true;
2371*d6b92ffaSHans Petter Selasky 	}
2372*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x30c, i, j, k, i, j, k);
2373*d6b92ffaSHans Petter Selasky 
2374*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, ip1, j, k) &&
2375*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, k,
2376*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][k],
2377*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
2378*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jm1][k]))) {
2379*d6b92ffaSHans Petter Selasky 		return true;
2380*d6b92ffaSHans Petter Selasky 	}
2381*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x30c, i, j, k, ip1, j, k);
2382*d6b92ffaSHans Petter Selasky 	return false;
2383*d6b92ffaSHans Petter Selasky }
2384*d6b92ffaSHans Petter Selasky 
2385*d6b92ffaSHans Petter Selasky static
handle_case_0x530(struct torus * t,int i,int j,int k)2386*d6b92ffaSHans Petter Selasky bool handle_case_0x530(struct torus *t, int i, int j, int k)
2387*d6b92ffaSHans Petter Selasky {
2388*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2389*d6b92ffaSHans Petter Selasky 	int km1 = canonicalize(k - 1, t->z_sz);
2390*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2391*d6b92ffaSHans Petter Selasky 
2392*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, j, k) &&
2393*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
2394*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][j][k],
2395*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
2396*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][km1]))) {
2397*d6b92ffaSHans Petter Selasky 		return true;
2398*d6b92ffaSHans Petter Selasky 	}
2399*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x530, i, j, k, i, j, k);
2400*d6b92ffaSHans Petter Selasky 
2401*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, ip1, j, k) &&
2402*d6b92ffaSHans Petter Selasky 	      install_tswitch(t, ip1, j, kp1,
2403*d6b92ffaSHans Petter Selasky 			      tfind_2d_perpendicular(t->sw[i][j][k],
2404*d6b92ffaSHans Petter Selasky 						     t->sw[ip1][j][k],
2405*d6b92ffaSHans Petter Selasky 						     t->sw[ip1][j][km1]))) {
2406*d6b92ffaSHans Petter Selasky 		return true;
2407*d6b92ffaSHans Petter Selasky 	}
2408*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x530, i, j, k, ip1, j, k);
2409*d6b92ffaSHans Petter Selasky 	return false;
2410*d6b92ffaSHans Petter Selasky }
2411*d6b92ffaSHans Petter Selasky 
2412*d6b92ffaSHans Petter Selasky static
handle_case_0x650(struct torus * t,int i,int j,int k)2413*d6b92ffaSHans Petter Selasky bool handle_case_0x650(struct torus *t, int i, int j, int k)
2414*d6b92ffaSHans Petter Selasky {
2415*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2416*d6b92ffaSHans Petter Selasky 	int km1 = canonicalize(k - 1, t->z_sz);
2417*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2418*d6b92ffaSHans Petter Selasky 
2419*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, j, k) &&
2420*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
2421*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][jp1][k],
2422*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
2423*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][km1]))) {
2424*d6b92ffaSHans Petter Selasky 		return true;
2425*d6b92ffaSHans Petter Selasky 	}
2426*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x650, i, j, k, i, j, k);
2427*d6b92ffaSHans Petter Selasky 
2428*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, jp1, k) &&
2429*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, kp1,
2430*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][k],
2431*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
2432*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][km1]))) {
2433*d6b92ffaSHans Petter Selasky 		return true;
2434*d6b92ffaSHans Petter Selasky 	}
2435*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x650, i, j, k, i, jp1, k);
2436*d6b92ffaSHans Petter Selasky 	return false;
2437*d6b92ffaSHans Petter Selasky }
2438*d6b92ffaSHans Petter Selasky 
2439*d6b92ffaSHans Petter Selasky /*
2440*d6b92ffaSHans Petter Selasky  * 2D case 0x305
2441*d6b92ffaSHans Petter Selasky  *  b0:
2442*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][0  ]
2443*d6b92ffaSHans Petter Selasky  *  b2:
2444*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][0  ]
2445*d6b92ffaSHans Petter Selasky  *                                    O           O
2446*d6b92ffaSHans Petter Selasky  * 2D case 0x511                                  .
2447*d6b92ffaSHans Petter Selasky  *  b0:                                           .
2448*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][0  ][k  ]                      .
2449*d6b92ffaSHans Petter Selasky  *  b4:                                           .
2450*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][0  ][k+1]                      .
2451*d6b92ffaSHans Petter Selasky  *                                    @           O
2452*d6b92ffaSHans Petter Selasky  * 2D case 0x611
2453*d6b92ffaSHans Petter Selasky  *  b0:
2454*d6b92ffaSHans Petter Selasky  *  b2: t->sw[0  ][j+1][k  ]
2455*d6b92ffaSHans Petter Selasky  *  b4:
2456*d6b92ffaSHans Petter Selasky  *  b6: t->sw[0  ][j+1][k+1]
2457*d6b92ffaSHans Petter Selasky  */
2458*d6b92ffaSHans Petter Selasky static
handle_case_0x305(struct torus * t,int i,int j,int k)2459*d6b92ffaSHans Petter Selasky bool handle_case_0x305(struct torus *t, int i, int j, int k)
2460*d6b92ffaSHans Petter Selasky {
2461*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2462*d6b92ffaSHans Petter Selasky 	int ip2 = canonicalize(i + 2, t->x_sz);
2463*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2464*d6b92ffaSHans Petter Selasky 
2465*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, j, k) &&
2466*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
2467*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][jp1][k],
2468*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
2469*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][j][k]))) {
2470*d6b92ffaSHans Petter Selasky 		return true;
2471*d6b92ffaSHans Petter Selasky 	}
2472*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x305, i, j, k, ip1, j, k);
2473*d6b92ffaSHans Petter Selasky 
2474*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, jp1, k) &&
2475*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
2476*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][j][k],
2477*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
2478*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][jp1][k]))) {
2479*d6b92ffaSHans Petter Selasky 		return true;
2480*d6b92ffaSHans Petter Selasky 	}
2481*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x305, i, j, k, ip1, jp1, k);
2482*d6b92ffaSHans Petter Selasky 	return false;
2483*d6b92ffaSHans Petter Selasky }
2484*d6b92ffaSHans Petter Selasky 
2485*d6b92ffaSHans Petter Selasky static
handle_case_0x511(struct torus * t,int i,int j,int k)2486*d6b92ffaSHans Petter Selasky bool handle_case_0x511(struct torus *t, int i, int j, int k)
2487*d6b92ffaSHans Petter Selasky {
2488*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2489*d6b92ffaSHans Petter Selasky 	int ip2 = canonicalize(i + 2, t->x_sz);
2490*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2491*d6b92ffaSHans Petter Selasky 
2492*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, j, k) &&
2493*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
2494*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][j][kp1],
2495*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
2496*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][j][k]))) {
2497*d6b92ffaSHans Petter Selasky 		return true;
2498*d6b92ffaSHans Petter Selasky 	}
2499*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x511, i, j, k, ip1, j, k);
2500*d6b92ffaSHans Petter Selasky 
2501*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, j, kp1) &&
2502*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
2503*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][j][k],
2504*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
2505*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][j][kp1]))) {
2506*d6b92ffaSHans Petter Selasky 		return true;
2507*d6b92ffaSHans Petter Selasky 	}
2508*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x511, i, j, k, ip1, j, kp1);
2509*d6b92ffaSHans Petter Selasky 	return false;
2510*d6b92ffaSHans Petter Selasky }
2511*d6b92ffaSHans Petter Selasky 
2512*d6b92ffaSHans Petter Selasky static
handle_case_0x611(struct torus * t,int i,int j,int k)2513*d6b92ffaSHans Petter Selasky bool handle_case_0x611(struct torus *t, int i, int j, int k)
2514*d6b92ffaSHans Petter Selasky {
2515*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2516*d6b92ffaSHans Petter Selasky 	int jp2 = canonicalize(j + 2, t->y_sz);
2517*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2518*d6b92ffaSHans Petter Selasky 
2519*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, jp1, k) &&
2520*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
2521*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][jp1][kp1],
2522*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
2523*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp2][k]))) {
2524*d6b92ffaSHans Petter Selasky 		return true;
2525*d6b92ffaSHans Petter Selasky 	}
2526*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x611, i, j, k, i, jp1, k);
2527*d6b92ffaSHans Petter Selasky 
2528*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, jp1, kp1) &&
2529*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
2530*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][jp1][k],
2531*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
2532*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp2][kp1]))) {
2533*d6b92ffaSHans Petter Selasky 		return true;
2534*d6b92ffaSHans Petter Selasky 	}
2535*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x611, i, j, k, i, jp1, kp1);
2536*d6b92ffaSHans Petter Selasky 	return false;
2537*d6b92ffaSHans Petter Selasky }
2538*d6b92ffaSHans Petter Selasky 
2539*d6b92ffaSHans Petter Selasky /*
2540*d6b92ffaSHans Petter Selasky  * 2D case 0x303
2541*d6b92ffaSHans Petter Selasky  *  b0:
2542*d6b92ffaSHans Petter Selasky  *  b1:
2543*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][0  ]
2544*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][0  ]
2545*d6b92ffaSHans Petter Selasky  *                                    O . . . . . O
2546*d6b92ffaSHans Petter Selasky  * 2D case 0x503
2547*d6b92ffaSHans Petter Selasky  *  b0:
2548*d6b92ffaSHans Petter Selasky  *  b1:
2549*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][0  ][k+1]
2550*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][0  ][k+1]
2551*d6b92ffaSHans Petter Selasky  *                                    @           O
2552*d6b92ffaSHans Petter Selasky  * 2D case 0x605
2553*d6b92ffaSHans Petter Selasky  *  b0:
2554*d6b92ffaSHans Petter Selasky  *  b2:
2555*d6b92ffaSHans Petter Selasky  *  b4: t->sw[0  ][j  ][k+1]
2556*d6b92ffaSHans Petter Selasky  *  b6: t->sw[0  ][j+1][k+1]
2557*d6b92ffaSHans Petter Selasky  */
2558*d6b92ffaSHans Petter Selasky static
handle_case_0x303(struct torus * t,int i,int j,int k)2559*d6b92ffaSHans Petter Selasky bool handle_case_0x303(struct torus *t, int i, int j, int k)
2560*d6b92ffaSHans Petter Selasky {
2561*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2562*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2563*d6b92ffaSHans Petter Selasky 	int jp2 = canonicalize(j + 2, t->y_sz);
2564*d6b92ffaSHans Petter Selasky 
2565*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, jp1, k) &&
2566*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
2567*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][jp1][k],
2568*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
2569*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp2][k]))) {
2570*d6b92ffaSHans Petter Selasky 		return true;
2571*d6b92ffaSHans Petter Selasky 	}
2572*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x303, i, j, k, i, jp1, k);
2573*d6b92ffaSHans Petter Selasky 
2574*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, ip1, jp1, k) &&
2575*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
2576*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][jp1][k],
2577*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
2578*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp2][k]))) {
2579*d6b92ffaSHans Petter Selasky 		return true;
2580*d6b92ffaSHans Petter Selasky 	}
2581*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x303, i, j, k, ip1, jp1, k);
2582*d6b92ffaSHans Petter Selasky 	return false;
2583*d6b92ffaSHans Petter Selasky }
2584*d6b92ffaSHans Petter Selasky 
2585*d6b92ffaSHans Petter Selasky static
handle_case_0x503(struct torus * t,int i,int j,int k)2586*d6b92ffaSHans Petter Selasky bool handle_case_0x503(struct torus *t, int i, int j, int k)
2587*d6b92ffaSHans Petter Selasky {
2588*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2589*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2590*d6b92ffaSHans Petter Selasky 	int kp2 = canonicalize(k + 2, t->z_sz);
2591*d6b92ffaSHans Petter Selasky 
2592*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, j, kp1) &&
2593*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
2594*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[ip1][j][kp1],
2595*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
2596*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp2]))) {
2597*d6b92ffaSHans Petter Selasky 		return true;
2598*d6b92ffaSHans Petter Selasky 	}
2599*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x503, i, j, k, i, j, kp1);
2600*d6b92ffaSHans Petter Selasky 
2601*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, ip1, j, kp1) &&
2602*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
2603*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][kp1],
2604*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
2605*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp2]))) {
2606*d6b92ffaSHans Petter Selasky 		return true;
2607*d6b92ffaSHans Petter Selasky 	}
2608*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x503, i, j, k, ip1, j, kp1);
2609*d6b92ffaSHans Petter Selasky 	return false;
2610*d6b92ffaSHans Petter Selasky }
2611*d6b92ffaSHans Petter Selasky 
2612*d6b92ffaSHans Petter Selasky static
handle_case_0x605(struct torus * t,int i,int j,int k)2613*d6b92ffaSHans Petter Selasky bool handle_case_0x605(struct torus *t, int i, int j, int k)
2614*d6b92ffaSHans Petter Selasky {
2615*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2616*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2617*d6b92ffaSHans Petter Selasky 	int kp2 = canonicalize(k + 2, t->z_sz);
2618*d6b92ffaSHans Petter Selasky 
2619*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, j, kp1) &&
2620*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
2621*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][jp1][kp1],
2622*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
2623*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp2]))) {
2624*d6b92ffaSHans Petter Selasky 		return true;
2625*d6b92ffaSHans Petter Selasky 	}
2626*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x605, i, j, k, i, j, kp1);
2627*d6b92ffaSHans Petter Selasky 
2628*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, jp1, kp1) &&
2629*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
2630*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][kp1],
2631*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
2632*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp2]))) {
2633*d6b92ffaSHans Petter Selasky 		return true;
2634*d6b92ffaSHans Petter Selasky 	}
2635*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x605, i, j, k, i, jp1, kp1);
2636*d6b92ffaSHans Petter Selasky 	return false;
2637*d6b92ffaSHans Petter Selasky }
2638*d6b92ffaSHans Petter Selasky 
2639*d6b92ffaSHans Petter Selasky /*
2640*d6b92ffaSHans Petter Selasky  * 2D case 0x30a
2641*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][0  ]
2642*d6b92ffaSHans Petter Selasky  *  b1:
2643*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][0  ]
2644*d6b92ffaSHans Petter Selasky  *  b3:
2645*d6b92ffaSHans Petter Selasky  *                                    O           O
2646*d6b92ffaSHans Petter Selasky  * 2D case 0x522                      .
2647*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][0  ][k  ]          .
2648*d6b92ffaSHans Petter Selasky  *  b1:                               .
2649*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][0  ][k+1]          .
2650*d6b92ffaSHans Petter Selasky  *  b5:                               .
2651*d6b92ffaSHans Petter Selasky  *                                    @           O
2652*d6b92ffaSHans Petter Selasky  * 2D case 0x644
2653*d6b92ffaSHans Petter Selasky  *  b0: t->sw[0  ][j  ][k  ]
2654*d6b92ffaSHans Petter Selasky  *  b2:
2655*d6b92ffaSHans Petter Selasky  *  b4: t->sw[0  ][j  ][k+1]
2656*d6b92ffaSHans Petter Selasky  *  b6:
2657*d6b92ffaSHans Petter Selasky  */
2658*d6b92ffaSHans Petter Selasky static
handle_case_0x30a(struct torus * t,int i,int j,int k)2659*d6b92ffaSHans Petter Selasky bool handle_case_0x30a(struct torus *t, int i, int j, int k)
2660*d6b92ffaSHans Petter Selasky {
2661*d6b92ffaSHans Petter Selasky 	int im1 = canonicalize(i - 1, t->x_sz);
2662*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2663*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2664*d6b92ffaSHans Petter Selasky 
2665*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, j, k) &&
2666*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
2667*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][jp1][k],
2668*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
2669*d6b92ffaSHans Petter Selasky 						   t->sw[im1][j][k]))) {
2670*d6b92ffaSHans Petter Selasky 		return true;
2671*d6b92ffaSHans Petter Selasky 	}
2672*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x30a, i, j, k, i, j, k);
2673*d6b92ffaSHans Petter Selasky 
2674*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, jp1, k) &&
2675*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, k,
2676*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][k],
2677*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
2678*d6b92ffaSHans Petter Selasky 						   t->sw[im1][jp1][k]))) {
2679*d6b92ffaSHans Petter Selasky 		return true;
2680*d6b92ffaSHans Petter Selasky 	}
2681*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x30a, i, j, k, i, jp1, k);
2682*d6b92ffaSHans Petter Selasky 	return false;
2683*d6b92ffaSHans Petter Selasky }
2684*d6b92ffaSHans Petter Selasky 
2685*d6b92ffaSHans Petter Selasky static
handle_case_0x522(struct torus * t,int i,int j,int k)2686*d6b92ffaSHans Petter Selasky bool handle_case_0x522(struct torus *t, int i, int j, int k)
2687*d6b92ffaSHans Petter Selasky {
2688*d6b92ffaSHans Petter Selasky 	int im1 = canonicalize(i - 1, t->x_sz);
2689*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2690*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2691*d6b92ffaSHans Petter Selasky 
2692*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, j, k) &&
2693*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
2694*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][kp1],
2695*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
2696*d6b92ffaSHans Petter Selasky 						   t->sw[im1][j][k]))) {
2697*d6b92ffaSHans Petter Selasky 		return true;
2698*d6b92ffaSHans Petter Selasky 	}
2699*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x522, i, j, k, i, j, k);
2700*d6b92ffaSHans Petter Selasky 
2701*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, j, kp1) &&
2702*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, kp1,
2703*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][k],
2704*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
2705*d6b92ffaSHans Petter Selasky 						   t->sw[im1][j][kp1]))) {
2706*d6b92ffaSHans Petter Selasky 		return true;
2707*d6b92ffaSHans Petter Selasky 	}
2708*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x522, i, j, k, i, j, kp1);
2709*d6b92ffaSHans Petter Selasky 	return false;
2710*d6b92ffaSHans Petter Selasky }
2711*d6b92ffaSHans Petter Selasky 
2712*d6b92ffaSHans Petter Selasky static
handle_case_0x644(struct torus * t,int i,int j,int k)2713*d6b92ffaSHans Petter Selasky bool handle_case_0x644(struct torus *t, int i, int j, int k)
2714*d6b92ffaSHans Petter Selasky {
2715*d6b92ffaSHans Petter Selasky 	int jm1 = canonicalize(j - 1, t->y_sz);
2716*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2717*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2718*d6b92ffaSHans Petter Selasky 
2719*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, j, k) &&
2720*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
2721*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][kp1],
2722*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
2723*d6b92ffaSHans Petter Selasky 						   t->sw[i][jm1][k]))) {
2724*d6b92ffaSHans Petter Selasky 		return true;
2725*d6b92ffaSHans Petter Selasky 	}
2726*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x644, i, j, k, i, j, k);
2727*d6b92ffaSHans Petter Selasky 
2728*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, j, kp1) &&
2729*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, kp1,
2730*d6b92ffaSHans Petter Selasky 			    tfind_2d_perpendicular(t->sw[i][j][k],
2731*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
2732*d6b92ffaSHans Petter Selasky 						   t->sw[i][jm1][kp1]))) {
2733*d6b92ffaSHans Petter Selasky 		return true;
2734*d6b92ffaSHans Petter Selasky 	}
2735*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x644, i, j, k, i, j, kp1);
2736*d6b92ffaSHans Petter Selasky 	return false;
2737*d6b92ffaSHans Petter Selasky }
2738*d6b92ffaSHans Petter Selasky 
2739*d6b92ffaSHans Petter Selasky /*
2740*d6b92ffaSHans Petter Selasky  * Handle the 2D cases where two existing edges meet at a corner.
2741*d6b92ffaSHans Petter Selasky  *
2742*d6b92ffaSHans Petter Selasky  */
2743*d6b92ffaSHans Petter Selasky 
2744*d6b92ffaSHans Petter Selasky /*
2745*d6b92ffaSHans Petter Selasky  * 2D case 0x301
2746*d6b92ffaSHans Petter Selasky  *  b0:
2747*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][0  ]
2748*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][0  ]
2749*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][0  ]
2750*d6b92ffaSHans Petter Selasky  *                                    O . . . . . O
2751*d6b92ffaSHans Petter Selasky  * 2D case 0x501                                  .
2752*d6b92ffaSHans Petter Selasky  *  b0:                                           .
2753*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][0  ][k  ]                      .
2754*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][0  ][k+1]                      .
2755*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][0  ][k+1]                      .
2756*d6b92ffaSHans Petter Selasky  *                                    @           O
2757*d6b92ffaSHans Petter Selasky  * 2D case 0x601
2758*d6b92ffaSHans Petter Selasky  *  b0:
2759*d6b92ffaSHans Petter Selasky  *  b2: t->sw[0  ][j+1][k  ]
2760*d6b92ffaSHans Petter Selasky  *  b4: t->sw[0  ][j  ][k+1]
2761*d6b92ffaSHans Petter Selasky  *  b6: t->sw[0  ][j+1][k+1]
2762*d6b92ffaSHans Petter Selasky  */
2763*d6b92ffaSHans Petter Selasky static
handle_case_0x301(struct torus * t,int i,int j,int k)2764*d6b92ffaSHans Petter Selasky bool handle_case_0x301(struct torus *t, int i, int j, int k)
2765*d6b92ffaSHans Petter Selasky {
2766*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2767*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2768*d6b92ffaSHans Petter Selasky 
2769*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
2770*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
2771*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
2772*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
2773*d6b92ffaSHans Petter Selasky 		return true;
2774*d6b92ffaSHans Petter Selasky 	}
2775*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x301, i, j, k, i, j, k);
2776*d6b92ffaSHans Petter Selasky 	return false;
2777*d6b92ffaSHans Petter Selasky }
2778*d6b92ffaSHans Petter Selasky 
2779*d6b92ffaSHans Petter Selasky static
handle_case_0x501(struct torus * t,int i,int j,int k)2780*d6b92ffaSHans Petter Selasky bool handle_case_0x501(struct torus *t, int i, int j, int k)
2781*d6b92ffaSHans Petter Selasky {
2782*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2783*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2784*d6b92ffaSHans Petter Selasky 
2785*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
2786*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
2787*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
2788*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
2789*d6b92ffaSHans Petter Selasky 		return true;
2790*d6b92ffaSHans Petter Selasky 	}
2791*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x501, i, j, k, i, j, k);
2792*d6b92ffaSHans Petter Selasky 	return false;
2793*d6b92ffaSHans Petter Selasky }
2794*d6b92ffaSHans Petter Selasky 
2795*d6b92ffaSHans Petter Selasky static
handle_case_0x601(struct torus * t,int i,int j,int k)2796*d6b92ffaSHans Petter Selasky bool handle_case_0x601(struct torus *t, int i, int j, int k)
2797*d6b92ffaSHans Petter Selasky {
2798*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2799*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2800*d6b92ffaSHans Petter Selasky 
2801*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
2802*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
2803*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
2804*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
2805*d6b92ffaSHans Petter Selasky 		return true;
2806*d6b92ffaSHans Petter Selasky 	}
2807*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x601, i, j, k, i, j, k);
2808*d6b92ffaSHans Petter Selasky 	return false;
2809*d6b92ffaSHans Petter Selasky }
2810*d6b92ffaSHans Petter Selasky 
2811*d6b92ffaSHans Petter Selasky /*
2812*d6b92ffaSHans Petter Selasky  * 2D case 0x302
2813*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][0  ]
2814*d6b92ffaSHans Petter Selasky  *  b1:
2815*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][0  ]
2816*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][0  ]
2817*d6b92ffaSHans Petter Selasky  *                                    O . . . . . O
2818*d6b92ffaSHans Petter Selasky  * 2D case 0x502                      .
2819*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][0  ][k  ]          .
2820*d6b92ffaSHans Petter Selasky  *  b1:                               .
2821*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][0  ][k+1]          .
2822*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][0  ][k+1]          .
2823*d6b92ffaSHans Petter Selasky  *                                    @           O
2824*d6b92ffaSHans Petter Selasky  * 2D case 0x604
2825*d6b92ffaSHans Petter Selasky  *  b0: t->sw[0  ][j  ][k  ]
2826*d6b92ffaSHans Petter Selasky  *  b2:
2827*d6b92ffaSHans Petter Selasky  *  b4: t->sw[0  ][j  ][k+1]
2828*d6b92ffaSHans Petter Selasky  *  b6: t->sw[0  ][j+1][k+1]
2829*d6b92ffaSHans Petter Selasky  */
2830*d6b92ffaSHans Petter Selasky static
handle_case_0x302(struct torus * t,int i,int j,int k)2831*d6b92ffaSHans Petter Selasky bool handle_case_0x302(struct torus *t, int i, int j, int k)
2832*d6b92ffaSHans Petter Selasky {
2833*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2834*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2835*d6b92ffaSHans Petter Selasky 
2836*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
2837*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
2838*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
2839*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
2840*d6b92ffaSHans Petter Selasky 		return true;
2841*d6b92ffaSHans Petter Selasky 	}
2842*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x302, i, j, k, ip1, j, k);
2843*d6b92ffaSHans Petter Selasky 	return false;
2844*d6b92ffaSHans Petter Selasky }
2845*d6b92ffaSHans Petter Selasky 
2846*d6b92ffaSHans Petter Selasky static
handle_case_0x502(struct torus * t,int i,int j,int k)2847*d6b92ffaSHans Petter Selasky bool handle_case_0x502(struct torus *t, int i, int j, int k)
2848*d6b92ffaSHans Petter Selasky {
2849*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2850*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2851*d6b92ffaSHans Petter Selasky 
2852*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
2853*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
2854*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
2855*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
2856*d6b92ffaSHans Petter Selasky 		return true;
2857*d6b92ffaSHans Petter Selasky 	}
2858*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x502, i, j, k, ip1, j, k);
2859*d6b92ffaSHans Petter Selasky 	return false;
2860*d6b92ffaSHans Petter Selasky }
2861*d6b92ffaSHans Petter Selasky 
2862*d6b92ffaSHans Petter Selasky static
handle_case_0x604(struct torus * t,int i,int j,int k)2863*d6b92ffaSHans Petter Selasky bool handle_case_0x604(struct torus *t, int i, int j, int k)
2864*d6b92ffaSHans Petter Selasky {
2865*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2866*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2867*d6b92ffaSHans Petter Selasky 
2868*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
2869*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
2870*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
2871*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
2872*d6b92ffaSHans Petter Selasky 		return true;
2873*d6b92ffaSHans Petter Selasky 	}
2874*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x604, i, j, k, i, jp1, k);
2875*d6b92ffaSHans Petter Selasky 	return false;
2876*d6b92ffaSHans Petter Selasky }
2877*d6b92ffaSHans Petter Selasky 
2878*d6b92ffaSHans Petter Selasky 
2879*d6b92ffaSHans Petter Selasky /*
2880*d6b92ffaSHans Petter Selasky  * 2D case 0x308
2881*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][0  ]
2882*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][0  ]
2883*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][0  ]
2884*d6b92ffaSHans Petter Selasky  *  b3:
2885*d6b92ffaSHans Petter Selasky  *                                    O           O
2886*d6b92ffaSHans Petter Selasky  * 2D case 0x520                      .
2887*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][0  ][k  ]          .
2888*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][0  ][k  ]          .
2889*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][0  ][k+1]          .
2890*d6b92ffaSHans Petter Selasky  *  b5:                               .
2891*d6b92ffaSHans Petter Selasky  *                                    @ . . . . . O
2892*d6b92ffaSHans Petter Selasky  * 2D case 0x640
2893*d6b92ffaSHans Petter Selasky  *  b0: t->sw[0  ][j  ][k  ]
2894*d6b92ffaSHans Petter Selasky  *  b2: t->sw[0  ][j+1][k  ]
2895*d6b92ffaSHans Petter Selasky  *  b4: t->sw[0  ][j  ][k+1]
2896*d6b92ffaSHans Petter Selasky  *  b6:
2897*d6b92ffaSHans Petter Selasky  */
2898*d6b92ffaSHans Petter Selasky static
handle_case_0x308(struct torus * t,int i,int j,int k)2899*d6b92ffaSHans Petter Selasky bool handle_case_0x308(struct torus *t, int i, int j, int k)
2900*d6b92ffaSHans Petter Selasky {
2901*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2902*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2903*d6b92ffaSHans Petter Selasky 
2904*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
2905*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
2906*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
2907*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
2908*d6b92ffaSHans Petter Selasky 		return true;
2909*d6b92ffaSHans Petter Selasky 	}
2910*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x308, i, j, k, ip1, jp1, k);
2911*d6b92ffaSHans Petter Selasky 	return false;
2912*d6b92ffaSHans Petter Selasky }
2913*d6b92ffaSHans Petter Selasky 
2914*d6b92ffaSHans Petter Selasky static
handle_case_0x520(struct torus * t,int i,int j,int k)2915*d6b92ffaSHans Petter Selasky bool handle_case_0x520(struct torus *t, int i, int j, int k)
2916*d6b92ffaSHans Petter Selasky {
2917*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2918*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2919*d6b92ffaSHans Petter Selasky 
2920*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
2921*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
2922*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
2923*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
2924*d6b92ffaSHans Petter Selasky 		return true;
2925*d6b92ffaSHans Petter Selasky 	}
2926*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x520, i, j, k, ip1, j, kp1);
2927*d6b92ffaSHans Petter Selasky 	return false;
2928*d6b92ffaSHans Petter Selasky }
2929*d6b92ffaSHans Petter Selasky 
2930*d6b92ffaSHans Petter Selasky static
handle_case_0x640(struct torus * t,int i,int j,int k)2931*d6b92ffaSHans Petter Selasky bool handle_case_0x640(struct torus *t, int i, int j, int k)
2932*d6b92ffaSHans Petter Selasky {
2933*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2934*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2935*d6b92ffaSHans Petter Selasky 
2936*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
2937*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
2938*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
2939*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
2940*d6b92ffaSHans Petter Selasky 		return true;
2941*d6b92ffaSHans Petter Selasky 	}
2942*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x640, i, j, k, i, jp1, kp1);
2943*d6b92ffaSHans Petter Selasky 	return false;
2944*d6b92ffaSHans Petter Selasky }
2945*d6b92ffaSHans Petter Selasky 
2946*d6b92ffaSHans Petter Selasky /*
2947*d6b92ffaSHans Petter Selasky  * 2D case 0x304
2948*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][0  ]
2949*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][0  ]
2950*d6b92ffaSHans Petter Selasky  *  b2:
2951*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][0  ]
2952*d6b92ffaSHans Petter Selasky  *                                    O           O
2953*d6b92ffaSHans Petter Selasky  * 2D case 0x510                                  .
2954*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][0  ][k  ]                      .
2955*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][0  ][k  ]                      .
2956*d6b92ffaSHans Petter Selasky  *  b4:                                           .
2957*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][0  ][k+1]                      .
2958*d6b92ffaSHans Petter Selasky  *                                    @ . . . . . O
2959*d6b92ffaSHans Petter Selasky  * 2D case 0x610
2960*d6b92ffaSHans Petter Selasky  *  b0: t->sw[0  ][j  ][k  ]
2961*d6b92ffaSHans Petter Selasky  *  b2: t->sw[0  ][j+1][k  ]
2962*d6b92ffaSHans Petter Selasky  *  b4:
2963*d6b92ffaSHans Petter Selasky  *  b6: t->sw[0  ][j+1][k+1]
2964*d6b92ffaSHans Petter Selasky  */
2965*d6b92ffaSHans Petter Selasky static
handle_case_0x304(struct torus * t,int i,int j,int k)2966*d6b92ffaSHans Petter Selasky bool handle_case_0x304(struct torus *t, int i, int j, int k)
2967*d6b92ffaSHans Petter Selasky {
2968*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2969*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
2970*d6b92ffaSHans Petter Selasky 
2971*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
2972*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
2973*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
2974*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
2975*d6b92ffaSHans Petter Selasky 		return true;
2976*d6b92ffaSHans Petter Selasky 	}
2977*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x304, i, j, k, i, jp1, k);
2978*d6b92ffaSHans Petter Selasky 	return false;
2979*d6b92ffaSHans Petter Selasky }
2980*d6b92ffaSHans Petter Selasky 
2981*d6b92ffaSHans Petter Selasky static
handle_case_0x510(struct torus * t,int i,int j,int k)2982*d6b92ffaSHans Petter Selasky bool handle_case_0x510(struct torus *t, int i, int j, int k)
2983*d6b92ffaSHans Petter Selasky {
2984*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
2985*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
2986*d6b92ffaSHans Petter Selasky 
2987*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
2988*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
2989*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
2990*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
2991*d6b92ffaSHans Petter Selasky 		return true;
2992*d6b92ffaSHans Petter Selasky 	}
2993*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x510, i, j, k, i, j, kp1);
2994*d6b92ffaSHans Petter Selasky 	return false;
2995*d6b92ffaSHans Petter Selasky }
2996*d6b92ffaSHans Petter Selasky 
2997*d6b92ffaSHans Petter Selasky static
handle_case_0x610(struct torus * t,int i,int j,int k)2998*d6b92ffaSHans Petter Selasky bool handle_case_0x610(struct torus *t, int i, int j, int k)
2999*d6b92ffaSHans Petter Selasky {
3000*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3001*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3002*d6b92ffaSHans Petter Selasky 
3003*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
3004*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
3005*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
3006*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
3007*d6b92ffaSHans Petter Selasky 		return true;
3008*d6b92ffaSHans Petter Selasky 	}
3009*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x610, i, j, k, i, j, kp1);
3010*d6b92ffaSHans Petter Selasky 	return false;
3011*d6b92ffaSHans Petter Selasky }
3012*d6b92ffaSHans Petter Selasky 
3013*d6b92ffaSHans Petter Selasky /*
3014*d6b92ffaSHans Petter Selasky  * Handle the 3D cases where two existing edges meet at a corner.
3015*d6b92ffaSHans Petter Selasky  *
3016*d6b92ffaSHans Petter Selasky  */
3017*d6b92ffaSHans Petter Selasky 
3018*d6b92ffaSHans Petter Selasky /*
3019*d6b92ffaSHans Petter Selasky  * 3D case 0x71f:                           O
3020*d6b92ffaSHans Petter Selasky  *                                        .   .
3021*d6b92ffaSHans Petter Selasky  *  b0:                                 .       .
3022*d6b92ffaSHans Petter Selasky  *  b1:                               .           .
3023*d6b92ffaSHans Petter Selasky  *  b2:                             .               .
3024*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3025*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3026*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]
3027*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]
3028*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]
3029*d6b92ffaSHans Petter Selasky  *                                          O
3030*d6b92ffaSHans Petter Selasky  *                                O                   O
3031*d6b92ffaSHans Petter Selasky  *
3032*d6b92ffaSHans Petter Selasky  *
3033*d6b92ffaSHans Petter Selasky  *
3034*d6b92ffaSHans Petter Selasky  *
3035*d6b92ffaSHans Petter Selasky  *                                          @
3036*d6b92ffaSHans Petter Selasky  */
3037*d6b92ffaSHans Petter Selasky static
handle_case_0x71f(struct torus * t,int i,int j,int k)3038*d6b92ffaSHans Petter Selasky bool handle_case_0x71f(struct torus *t, int i, int j, int k)
3039*d6b92ffaSHans Petter Selasky {
3040*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3041*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3042*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3043*d6b92ffaSHans Petter Selasky 	int kp2 = canonicalize(k + 2, t->z_sz);
3044*d6b92ffaSHans Petter Selasky 
3045*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, ip1, jp1, kp1) &&
3046*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, k,
3047*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][kp1],
3048*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3049*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3050*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp2]))) {
3051*d6b92ffaSHans Petter Selasky 		return true;
3052*d6b92ffaSHans Petter Selasky 	}
3053*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x71f, i, j, k, ip1, jp1, kp1);
3054*d6b92ffaSHans Petter Selasky 	return false;
3055*d6b92ffaSHans Petter Selasky }
3056*d6b92ffaSHans Petter Selasky 
3057*d6b92ffaSHans Petter Selasky /*
3058*d6b92ffaSHans Petter Selasky  * 3D case 0x72f:                           O
3059*d6b92ffaSHans Petter Selasky  *                                        .
3060*d6b92ffaSHans Petter Selasky  *  b0:                                 .
3061*d6b92ffaSHans Petter Selasky  *  b1:                               .
3062*d6b92ffaSHans Petter Selasky  *  b2:                             .
3063*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3064*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O
3065*d6b92ffaSHans Petter Selasky  *  b5:                               .
3066*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .
3067*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .
3068*d6b92ffaSHans Petter Selasky  *                                          O
3069*d6b92ffaSHans Petter Selasky  *                                O                   O
3070*d6b92ffaSHans Petter Selasky  *
3071*d6b92ffaSHans Petter Selasky  *
3072*d6b92ffaSHans Petter Selasky  *
3073*d6b92ffaSHans Petter Selasky  *
3074*d6b92ffaSHans Petter Selasky  *                                          @
3075*d6b92ffaSHans Petter Selasky  */
3076*d6b92ffaSHans Petter Selasky static
handle_case_0x72f(struct torus * t,int i,int j,int k)3077*d6b92ffaSHans Petter Selasky bool handle_case_0x72f(struct torus *t, int i, int j, int k)
3078*d6b92ffaSHans Petter Selasky {
3079*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3080*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3081*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3082*d6b92ffaSHans Petter Selasky 	int kp2 = canonicalize(k + 2, t->z_sz);
3083*d6b92ffaSHans Petter Selasky 
3084*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, jp1, kp1) &&
3085*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
3086*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][kp1],
3087*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3088*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3089*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp2]))) {
3090*d6b92ffaSHans Petter Selasky 		return true;
3091*d6b92ffaSHans Petter Selasky 	}
3092*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x72f, i, j, k, i, jp1, kp1);
3093*d6b92ffaSHans Petter Selasky 	return false;
3094*d6b92ffaSHans Petter Selasky }
3095*d6b92ffaSHans Petter Selasky 
3096*d6b92ffaSHans Petter Selasky /*
3097*d6b92ffaSHans Petter Selasky  * 3D case 0x737:                           O
3098*d6b92ffaSHans Petter Selasky  *                                        . .
3099*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .
3100*d6b92ffaSHans Petter Selasky  *  b1:                               .     .
3101*d6b92ffaSHans Petter Selasky  *  b2:                             .       .
3102*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
3103*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3104*d6b92ffaSHans Petter Selasky  *  b5:
3105*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]
3106*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]
3107*d6b92ffaSHans Petter Selasky  *                                          O
3108*d6b92ffaSHans Petter Selasky  *                                O                   O
3109*d6b92ffaSHans Petter Selasky  *
3110*d6b92ffaSHans Petter Selasky  *
3111*d6b92ffaSHans Petter Selasky  *
3112*d6b92ffaSHans Petter Selasky  *
3113*d6b92ffaSHans Petter Selasky  *                                          @
3114*d6b92ffaSHans Petter Selasky  */
3115*d6b92ffaSHans Petter Selasky static
handle_case_0x737(struct torus * t,int i,int j,int k)3116*d6b92ffaSHans Petter Selasky bool handle_case_0x737(struct torus *t, int i, int j, int k)
3117*d6b92ffaSHans Petter Selasky {
3118*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3119*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3120*d6b92ffaSHans Petter Selasky 	int jp2 = canonicalize(j + 2, t->y_sz);
3121*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3122*d6b92ffaSHans Petter Selasky 
3123*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, ip1, jp1, kp1) &&
3124*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, kp1,
3125*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][jp1][kp1],
3126*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3127*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3128*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp2][kp1]))) {
3129*d6b92ffaSHans Petter Selasky 		return true;
3130*d6b92ffaSHans Petter Selasky 	}
3131*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x737, i, j, k, ip1, jp1, kp1);
3132*d6b92ffaSHans Petter Selasky 	return false;
3133*d6b92ffaSHans Petter Selasky }
3134*d6b92ffaSHans Petter Selasky 
3135*d6b92ffaSHans Petter Selasky /*
3136*d6b92ffaSHans Petter Selasky  * 3D case 0x73b:                           O
3137*d6b92ffaSHans Petter Selasky  *                                        .
3138*d6b92ffaSHans Petter Selasky  *  b0:                                 .
3139*d6b92ffaSHans Petter Selasky  *  b1:                               .
3140*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .
3141*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3142*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
3143*d6b92ffaSHans Petter Selasky  *  b5:                           .
3144*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .
3145*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .
3146*d6b92ffaSHans Petter Selasky  *                                .         O
3147*d6b92ffaSHans Petter Selasky  *                                O                   O
3148*d6b92ffaSHans Petter Selasky  *
3149*d6b92ffaSHans Petter Selasky  *
3150*d6b92ffaSHans Petter Selasky  *
3151*d6b92ffaSHans Petter Selasky  *
3152*d6b92ffaSHans Petter Selasky  *                                          @
3153*d6b92ffaSHans Petter Selasky  */
3154*d6b92ffaSHans Petter Selasky static
handle_case_0x73b(struct torus * t,int i,int j,int k)3155*d6b92ffaSHans Petter Selasky bool handle_case_0x73b(struct torus *t, int i, int j, int k)
3156*d6b92ffaSHans Petter Selasky {
3157*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3158*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3159*d6b92ffaSHans Petter Selasky 	int jp2 = canonicalize(j + 2, t->y_sz);
3160*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3161*d6b92ffaSHans Petter Selasky 
3162*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, jp1, kp1) &&
3163*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
3164*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][jp1][k],
3165*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3166*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3167*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp2][kp1]))) {
3168*d6b92ffaSHans Petter Selasky 		return true;
3169*d6b92ffaSHans Petter Selasky 	}
3170*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x73b, i, j, k, i, jp1, kp1);
3171*d6b92ffaSHans Petter Selasky 	return false;
3172*d6b92ffaSHans Petter Selasky }
3173*d6b92ffaSHans Petter Selasky 
3174*d6b92ffaSHans Petter Selasky /*
3175*d6b92ffaSHans Petter Selasky  * 3D case 0x74f:                           O
3176*d6b92ffaSHans Petter Selasky  *                                            .
3177*d6b92ffaSHans Petter Selasky  *  b0:                                         .
3178*d6b92ffaSHans Petter Selasky  *  b1:                                           .
3179*d6b92ffaSHans Petter Selasky  *  b2:                                             .
3180*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3181*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       .
3182*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .
3183*d6b92ffaSHans Petter Selasky  *  b6:                                         .
3184*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                  .
3185*d6b92ffaSHans Petter Selasky  *                                          O
3186*d6b92ffaSHans Petter Selasky  *                                O                   O
3187*d6b92ffaSHans Petter Selasky  *
3188*d6b92ffaSHans Petter Selasky  *
3189*d6b92ffaSHans Petter Selasky  *
3190*d6b92ffaSHans Petter Selasky  *
3191*d6b92ffaSHans Petter Selasky  *                                          @
3192*d6b92ffaSHans Petter Selasky  */
3193*d6b92ffaSHans Petter Selasky static
handle_case_0x74f(struct torus * t,int i,int j,int k)3194*d6b92ffaSHans Petter Selasky bool handle_case_0x74f(struct torus *t, int i, int j, int k)
3195*d6b92ffaSHans Petter Selasky {
3196*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3197*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3198*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3199*d6b92ffaSHans Petter Selasky 	int kp2 = canonicalize(k + 2, t->z_sz);
3200*d6b92ffaSHans Petter Selasky 
3201*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, ip1, j, kp1) &&
3202*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
3203*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][kp1],
3204*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
3205*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3206*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp2]))) {
3207*d6b92ffaSHans Petter Selasky 		return true;
3208*d6b92ffaSHans Petter Selasky 	}
3209*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x74f, i, j, k, ip1, j, kp1);
3210*d6b92ffaSHans Petter Selasky 	return false;
3211*d6b92ffaSHans Petter Selasky }
3212*d6b92ffaSHans Petter Selasky 
3213*d6b92ffaSHans Petter Selasky /*
3214*d6b92ffaSHans Petter Selasky  * 3D case 0x757:                           O
3215*d6b92ffaSHans Petter Selasky  *                                          . .
3216*d6b92ffaSHans Petter Selasky  *  b0:                                     .   .
3217*d6b92ffaSHans Petter Selasky  *  b1:                                     .     .
3218*d6b92ffaSHans Petter Selasky  *  b2:                                     .       .
3219*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
3220*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3221*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]
3222*d6b92ffaSHans Petter Selasky  *  b6:
3223*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]
3224*d6b92ffaSHans Petter Selasky  *                                          O
3225*d6b92ffaSHans Petter Selasky  *                                O                   O
3226*d6b92ffaSHans Petter Selasky  *
3227*d6b92ffaSHans Petter Selasky  *
3228*d6b92ffaSHans Petter Selasky  *
3229*d6b92ffaSHans Petter Selasky  *
3230*d6b92ffaSHans Petter Selasky  *                                          @
3231*d6b92ffaSHans Petter Selasky  */
3232*d6b92ffaSHans Petter Selasky static
handle_case_0x757(struct torus * t,int i,int j,int k)3233*d6b92ffaSHans Petter Selasky bool handle_case_0x757(struct torus *t, int i, int j, int k)
3234*d6b92ffaSHans Petter Selasky {
3235*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3236*d6b92ffaSHans Petter Selasky 	int ip2 = canonicalize(i + 2, t->x_sz);
3237*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3238*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3239*d6b92ffaSHans Petter Selasky 
3240*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, jp1, kp1) &&
3241*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, kp1,
3242*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][kp1],
3243*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3244*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3245*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][jp1][kp1]))) {
3246*d6b92ffaSHans Petter Selasky 		return true;
3247*d6b92ffaSHans Petter Selasky 	}
3248*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x757, i, j, k, ip1, jp1, kp1);
3249*d6b92ffaSHans Petter Selasky 	return false;
3250*d6b92ffaSHans Petter Selasky }
3251*d6b92ffaSHans Petter Selasky 
3252*d6b92ffaSHans Petter Selasky /*
3253*d6b92ffaSHans Petter Selasky  * 3D case 0x75d:                           O
3254*d6b92ffaSHans Petter Selasky  *                                            .
3255*d6b92ffaSHans Petter Selasky  *  b0:                                         .
3256*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                      .
3257*d6b92ffaSHans Petter Selasky  *  b2:                                             .
3258*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3259*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
3260*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                          .
3261*d6b92ffaSHans Petter Selasky  *  b6:                                               .
3262*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                          .
3263*d6b92ffaSHans Petter Selasky  *                                          O         .
3264*d6b92ffaSHans Petter Selasky  *                                O                   O
3265*d6b92ffaSHans Petter Selasky  *
3266*d6b92ffaSHans Petter Selasky  *
3267*d6b92ffaSHans Petter Selasky  *
3268*d6b92ffaSHans Petter Selasky  *
3269*d6b92ffaSHans Petter Selasky  *                                          @
3270*d6b92ffaSHans Petter Selasky  */
3271*d6b92ffaSHans Petter Selasky static
handle_case_0x75d(struct torus * t,int i,int j,int k)3272*d6b92ffaSHans Petter Selasky bool handle_case_0x75d(struct torus *t, int i, int j, int k)
3273*d6b92ffaSHans Petter Selasky {
3274*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3275*d6b92ffaSHans Petter Selasky 	int ip2 = canonicalize(i + 2, t->x_sz);
3276*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3277*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3278*d6b92ffaSHans Petter Selasky 
3279*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, j, kp1) &&
3280*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
3281*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][k],
3282*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
3283*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3284*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][j][kp1]))) {
3285*d6b92ffaSHans Petter Selasky 		return true;
3286*d6b92ffaSHans Petter Selasky 	}
3287*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x75d, i, j, k, ip1, j, kp1);
3288*d6b92ffaSHans Petter Selasky 	return false;
3289*d6b92ffaSHans Petter Selasky }
3290*d6b92ffaSHans Petter Selasky 
3291*d6b92ffaSHans Petter Selasky /*
3292*d6b92ffaSHans Petter Selasky  * 3D case 0x773:                           O
3293*d6b92ffaSHans Petter Selasky  *                                          .
3294*d6b92ffaSHans Petter Selasky  *  b0:                                     .
3295*d6b92ffaSHans Petter Selasky  *  b1:                                     .
3296*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]                .
3297*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
3298*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3299*d6b92ffaSHans Petter Selasky  *  b5:                                   .
3300*d6b92ffaSHans Petter Selasky  *  b6:                                 .
3301*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]          .
3302*d6b92ffaSHans Petter Selasky  *                                  .       O
3303*d6b92ffaSHans Petter Selasky  *                                O                   O
3304*d6b92ffaSHans Petter Selasky  *
3305*d6b92ffaSHans Petter Selasky  *
3306*d6b92ffaSHans Petter Selasky  *
3307*d6b92ffaSHans Petter Selasky  *
3308*d6b92ffaSHans Petter Selasky  *                                          @
3309*d6b92ffaSHans Petter Selasky  */
3310*d6b92ffaSHans Petter Selasky static
handle_case_0x773(struct torus * t,int i,int j,int k)3311*d6b92ffaSHans Petter Selasky bool handle_case_0x773(struct torus *t, int i, int j, int k)
3312*d6b92ffaSHans Petter Selasky {
3313*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3314*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3315*d6b92ffaSHans Petter Selasky 	int jp2 = canonicalize(j + 2, t->y_sz);
3316*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3317*d6b92ffaSHans Petter Selasky 
3318*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, ip1, jp1, k) &&
3319*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
3320*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][jp1][k],
3321*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3322*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3323*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp2][k]))) {
3324*d6b92ffaSHans Petter Selasky 		return true;
3325*d6b92ffaSHans Petter Selasky 	}
3326*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x773, i, j, k, ip1, jp1, k);
3327*d6b92ffaSHans Petter Selasky 	return false;
3328*d6b92ffaSHans Petter Selasky }
3329*d6b92ffaSHans Petter Selasky 
3330*d6b92ffaSHans Petter Selasky /*
3331*d6b92ffaSHans Petter Selasky  * 3D case 0x775:                           O
3332*d6b92ffaSHans Petter Selasky  *                                          .
3333*d6b92ffaSHans Petter Selasky  *  b0:                                     .
3334*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .
3335*d6b92ffaSHans Petter Selasky  *  b2:                                     .
3336*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
3337*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3338*d6b92ffaSHans Petter Selasky  *  b5:                                       .
3339*d6b92ffaSHans Petter Selasky  *  b6:                                         .
3340*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                      .
3341*d6b92ffaSHans Petter Selasky  *                                          O       .
3342*d6b92ffaSHans Petter Selasky  *                                O                   O
3343*d6b92ffaSHans Petter Selasky  *
3344*d6b92ffaSHans Petter Selasky  *
3345*d6b92ffaSHans Petter Selasky  *
3346*d6b92ffaSHans Petter Selasky  *
3347*d6b92ffaSHans Petter Selasky  *                                          @
3348*d6b92ffaSHans Petter Selasky  */
3349*d6b92ffaSHans Petter Selasky static
handle_case_0x775(struct torus * t,int i,int j,int k)3350*d6b92ffaSHans Petter Selasky bool handle_case_0x775(struct torus *t, int i, int j, int k)
3351*d6b92ffaSHans Petter Selasky {
3352*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3353*d6b92ffaSHans Petter Selasky 	int ip2 = canonicalize(i + 2, t->x_sz);
3354*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3355*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3356*d6b92ffaSHans Petter Selasky 
3357*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, jp1, k) &&
3358*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
3359*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][k],
3360*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3361*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][kp1],
3362*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][jp1][k]))) {
3363*d6b92ffaSHans Petter Selasky 		return true;
3364*d6b92ffaSHans Petter Selasky 	}
3365*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x775, i, j, k, ip1, jp1, k);
3366*d6b92ffaSHans Petter Selasky 	return false;
3367*d6b92ffaSHans Petter Selasky }
3368*d6b92ffaSHans Petter Selasky 
3369*d6b92ffaSHans Petter Selasky /*
3370*d6b92ffaSHans Petter Selasky  * 3D case 0x78f:                           O
3371*d6b92ffaSHans Petter Selasky  *
3372*d6b92ffaSHans Petter Selasky  *  b0:
3373*d6b92ffaSHans Petter Selasky  *  b1:
3374*d6b92ffaSHans Petter Selasky  *  b2:
3375*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3376*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       .
3377*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .
3378*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .
3379*d6b92ffaSHans Petter Selasky  *  b7:                                   .   .
3380*d6b92ffaSHans Petter Selasky  *                                          O
3381*d6b92ffaSHans Petter Selasky  *                                O                   O
3382*d6b92ffaSHans Petter Selasky  *
3383*d6b92ffaSHans Petter Selasky  *
3384*d6b92ffaSHans Petter Selasky  *
3385*d6b92ffaSHans Petter Selasky  *
3386*d6b92ffaSHans Petter Selasky  *                                          @
3387*d6b92ffaSHans Petter Selasky  */
3388*d6b92ffaSHans Petter Selasky static
handle_case_0x78f(struct torus * t,int i,int j,int k)3389*d6b92ffaSHans Petter Selasky bool handle_case_0x78f(struct torus *t, int i, int j, int k)
3390*d6b92ffaSHans Petter Selasky {
3391*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3392*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3393*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3394*d6b92ffaSHans Petter Selasky 	int kp2 = canonicalize(k + 2, t->z_sz);
3395*d6b92ffaSHans Petter Selasky 
3396*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, j, kp1) &&
3397*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
3398*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][kp1],
3399*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
3400*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3401*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp2]))) {
3402*d6b92ffaSHans Petter Selasky 		return true;
3403*d6b92ffaSHans Petter Selasky 	}
3404*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x78f, i, j, k, i, j, kp1);
3405*d6b92ffaSHans Petter Selasky 	return false;
3406*d6b92ffaSHans Petter Selasky }
3407*d6b92ffaSHans Petter Selasky 
3408*d6b92ffaSHans Petter Selasky /*
3409*d6b92ffaSHans Petter Selasky  * 3D case 0x7ab:                           O
3410*d6b92ffaSHans Petter Selasky  *
3411*d6b92ffaSHans Petter Selasky  *  b0:
3412*d6b92ffaSHans Petter Selasky  *  b1:
3413*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3414*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3415*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
3416*d6b92ffaSHans Petter Selasky  *  b5:                           .   .
3417*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
3418*d6b92ffaSHans Petter Selasky  *  b7:                           .       .
3419*d6b92ffaSHans Petter Selasky  *                                .         O
3420*d6b92ffaSHans Petter Selasky  *                                O                   O
3421*d6b92ffaSHans Petter Selasky  *
3422*d6b92ffaSHans Petter Selasky  *
3423*d6b92ffaSHans Petter Selasky  *
3424*d6b92ffaSHans Petter Selasky  *
3425*d6b92ffaSHans Petter Selasky  *                                          @
3426*d6b92ffaSHans Petter Selasky  */
3427*d6b92ffaSHans Petter Selasky static
handle_case_0x7ab(struct torus * t,int i,int j,int k)3428*d6b92ffaSHans Petter Selasky bool handle_case_0x7ab(struct torus *t, int i, int j, int k)
3429*d6b92ffaSHans Petter Selasky {
3430*d6b92ffaSHans Petter Selasky 	int im1 = canonicalize(i - 1, t->x_sz);
3431*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3432*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3433*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3434*d6b92ffaSHans Petter Selasky 
3435*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, jp1, kp1) &&
3436*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, kp1,
3437*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][kp1],
3438*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3439*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3440*d6b92ffaSHans Petter Selasky 						   t->sw[im1][jp1][kp1]))) {
3441*d6b92ffaSHans Petter Selasky 		return true;
3442*d6b92ffaSHans Petter Selasky 	}
3443*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7ab, i, j, k, i, jp1, kp1);
3444*d6b92ffaSHans Petter Selasky 	return false;
3445*d6b92ffaSHans Petter Selasky }
3446*d6b92ffaSHans Petter Selasky 
3447*d6b92ffaSHans Petter Selasky /*
3448*d6b92ffaSHans Petter Selasky  * 3D case 0x7ae:                           O
3449*d6b92ffaSHans Petter Selasky  *
3450*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3451*d6b92ffaSHans Petter Selasky  *  b1:
3452*d6b92ffaSHans Petter Selasky  *  b2:
3453*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3454*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O
3455*d6b92ffaSHans Petter Selasky  *  b5:                               .
3456*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .
3457*d6b92ffaSHans Petter Selasky  *  b7:                                   .
3458*d6b92ffaSHans Petter Selasky  *                                          O
3459*d6b92ffaSHans Petter Selasky  *                                O         .         O
3460*d6b92ffaSHans Petter Selasky  *                                          .
3461*d6b92ffaSHans Petter Selasky  *                                          .
3462*d6b92ffaSHans Petter Selasky  *                                          .
3463*d6b92ffaSHans Petter Selasky  *                                          .
3464*d6b92ffaSHans Petter Selasky  *                                          @
3465*d6b92ffaSHans Petter Selasky  */
3466*d6b92ffaSHans Petter Selasky static
handle_case_0x7ae(struct torus * t,int i,int j,int k)3467*d6b92ffaSHans Petter Selasky bool handle_case_0x7ae(struct torus *t, int i, int j, int k)
3468*d6b92ffaSHans Petter Selasky {
3469*d6b92ffaSHans Petter Selasky 	int im1 = canonicalize(i - 1, t->x_sz);
3470*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3471*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3472*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3473*d6b92ffaSHans Petter Selasky 
3474*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, j, kp1) &&
3475*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, kp1,
3476*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][k],
3477*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
3478*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3479*d6b92ffaSHans Petter Selasky 						   t->sw[im1][j][kp1]))) {
3480*d6b92ffaSHans Petter Selasky 		return true;
3481*d6b92ffaSHans Petter Selasky 	}
3482*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7ae, i, j, k, i, j, kp1);
3483*d6b92ffaSHans Petter Selasky 	return false;
3484*d6b92ffaSHans Petter Selasky }
3485*d6b92ffaSHans Petter Selasky 
3486*d6b92ffaSHans Petter Selasky /*
3487*d6b92ffaSHans Petter Selasky  * 3D case 0x7b3:                           O
3488*d6b92ffaSHans Petter Selasky  *
3489*d6b92ffaSHans Petter Selasky  *  b0:
3490*d6b92ffaSHans Petter Selasky  *  b1:
3491*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3492*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
3493*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
3494*d6b92ffaSHans Petter Selasky  *  b5:                           .       .
3495*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
3496*d6b92ffaSHans Petter Selasky  *  b7:                           .   .
3497*d6b92ffaSHans Petter Selasky  *                                . .       O
3498*d6b92ffaSHans Petter Selasky  *                                O                   O
3499*d6b92ffaSHans Petter Selasky  *
3500*d6b92ffaSHans Petter Selasky  *
3501*d6b92ffaSHans Petter Selasky  *
3502*d6b92ffaSHans Petter Selasky  *
3503*d6b92ffaSHans Petter Selasky  *                                          @
3504*d6b92ffaSHans Petter Selasky  */
3505*d6b92ffaSHans Petter Selasky static
handle_case_0x7b3(struct torus * t,int i,int j,int k)3506*d6b92ffaSHans Petter Selasky bool handle_case_0x7b3(struct torus *t, int i, int j, int k)
3507*d6b92ffaSHans Petter Selasky {
3508*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3509*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3510*d6b92ffaSHans Petter Selasky 	int jp2 = canonicalize(j + 2, t->y_sz);
3511*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3512*d6b92ffaSHans Petter Selasky 
3513*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, jp1, k) &&
3514*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
3515*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][jp1][kp1],
3516*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3517*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3518*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp2][k]))) {
3519*d6b92ffaSHans Petter Selasky 		return true;
3520*d6b92ffaSHans Petter Selasky 	}
3521*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7b3, i, j, k, i, jp1, k);
3522*d6b92ffaSHans Petter Selasky 	return false;
3523*d6b92ffaSHans Petter Selasky }
3524*d6b92ffaSHans Petter Selasky 
3525*d6b92ffaSHans Petter Selasky /*
3526*d6b92ffaSHans Petter Selasky  * 3D case 0x7ba:                           O
3527*d6b92ffaSHans Petter Selasky  *
3528*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3529*d6b92ffaSHans Petter Selasky  *  b1:
3530*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3531*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3532*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
3533*d6b92ffaSHans Petter Selasky  *  b5:                           .
3534*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .
3535*d6b92ffaSHans Petter Selasky  *  b7:                           .
3536*d6b92ffaSHans Petter Selasky  *                                .         O
3537*d6b92ffaSHans Petter Selasky  *                                O                   O
3538*d6b92ffaSHans Petter Selasky  *                                  .
3539*d6b92ffaSHans Petter Selasky  *                                    .
3540*d6b92ffaSHans Petter Selasky  *                                      .
3541*d6b92ffaSHans Petter Selasky  *                                        .
3542*d6b92ffaSHans Petter Selasky  *                                          @
3543*d6b92ffaSHans Petter Selasky  */
3544*d6b92ffaSHans Petter Selasky static
handle_case_0x7ba(struct torus * t,int i,int j,int k)3545*d6b92ffaSHans Petter Selasky bool handle_case_0x7ba(struct torus *t, int i, int j, int k)
3546*d6b92ffaSHans Petter Selasky {
3547*d6b92ffaSHans Petter Selasky 	int im1 = canonicalize(i - 1, t->x_sz);
3548*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3549*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3550*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3551*d6b92ffaSHans Petter Selasky 
3552*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, jp1, k) &&
3553*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, k,
3554*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][k],
3555*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3556*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][kp1],
3557*d6b92ffaSHans Petter Selasky 						   t->sw[im1][jp1][k]))) {
3558*d6b92ffaSHans Petter Selasky 		return true;
3559*d6b92ffaSHans Petter Selasky 	}
3560*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7ba, i, j, k, i, jp1, k);
3561*d6b92ffaSHans Petter Selasky 	return false;
3562*d6b92ffaSHans Petter Selasky }
3563*d6b92ffaSHans Petter Selasky 
3564*d6b92ffaSHans Petter Selasky /*
3565*d6b92ffaSHans Petter Selasky  * 3D case 0x7cd:                           O
3566*d6b92ffaSHans Petter Selasky  *
3567*d6b92ffaSHans Petter Selasky  *  b0:
3568*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3569*d6b92ffaSHans Petter Selasky  *  b2:
3570*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3571*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
3572*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .   .
3573*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
3574*d6b92ffaSHans Petter Selasky  *  b7:                                       .       .
3575*d6b92ffaSHans Petter Selasky  *                                          O         .
3576*d6b92ffaSHans Petter Selasky  *                                O                   O
3577*d6b92ffaSHans Petter Selasky  *
3578*d6b92ffaSHans Petter Selasky  *
3579*d6b92ffaSHans Petter Selasky  *
3580*d6b92ffaSHans Petter Selasky  *
3581*d6b92ffaSHans Petter Selasky  *                                          @
3582*d6b92ffaSHans Petter Selasky  */
3583*d6b92ffaSHans Petter Selasky static
handle_case_0x7cd(struct torus * t,int i,int j,int k)3584*d6b92ffaSHans Petter Selasky bool handle_case_0x7cd(struct torus *t, int i, int j, int k)
3585*d6b92ffaSHans Petter Selasky {
3586*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3587*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3588*d6b92ffaSHans Petter Selasky 	int jm1 = canonicalize(j - 1, t->y_sz);
3589*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3590*d6b92ffaSHans Petter Selasky 
3591*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, ip1, j, kp1) &&
3592*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, kp1,
3593*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][kp1],
3594*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
3595*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
3596*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jm1][kp1]))) {
3597*d6b92ffaSHans Petter Selasky 		return true;
3598*d6b92ffaSHans Petter Selasky 	}
3599*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7cd, i, j, k, ip1, j, kp1);
3600*d6b92ffaSHans Petter Selasky 	return false;
3601*d6b92ffaSHans Petter Selasky }
3602*d6b92ffaSHans Petter Selasky 
3603*d6b92ffaSHans Petter Selasky /*
3604*d6b92ffaSHans Petter Selasky  * 3D case 0x7ce:                           O
3605*d6b92ffaSHans Petter Selasky  *
3606*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3607*d6b92ffaSHans Petter Selasky  *  b1:
3608*d6b92ffaSHans Petter Selasky  *  b2:
3609*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3610*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       .
3611*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .
3612*d6b92ffaSHans Petter Selasky  *  b6:                                         .
3613*d6b92ffaSHans Petter Selasky  *  b7:                                       .
3614*d6b92ffaSHans Petter Selasky  *                                          O
3615*d6b92ffaSHans Petter Selasky  *                                O         .         O
3616*d6b92ffaSHans Petter Selasky  *                                          .
3617*d6b92ffaSHans Petter Selasky  *                                          .
3618*d6b92ffaSHans Petter Selasky  *                                          .
3619*d6b92ffaSHans Petter Selasky  *                                          .
3620*d6b92ffaSHans Petter Selasky  *                                          @
3621*d6b92ffaSHans Petter Selasky  */
3622*d6b92ffaSHans Petter Selasky static
handle_case_0x7ce(struct torus * t,int i,int j,int k)3623*d6b92ffaSHans Petter Selasky bool handle_case_0x7ce(struct torus *t, int i, int j, int k)
3624*d6b92ffaSHans Petter Selasky {
3625*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3626*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3627*d6b92ffaSHans Petter Selasky 	int jm1 = canonicalize(j - 1, t->y_sz);
3628*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3629*d6b92ffaSHans Petter Selasky 
3630*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, j, kp1) &&
3631*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, kp1,
3632*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][k],
3633*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][kp1],
3634*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
3635*d6b92ffaSHans Petter Selasky 						   t->sw[i][jm1][kp1]))) {
3636*d6b92ffaSHans Petter Selasky 		return true;
3637*d6b92ffaSHans Petter Selasky 	}
3638*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7ce, i, j, k, i, j, kp1);
3639*d6b92ffaSHans Petter Selasky 	return false;
3640*d6b92ffaSHans Petter Selasky }
3641*d6b92ffaSHans Petter Selasky 
3642*d6b92ffaSHans Petter Selasky /*
3643*d6b92ffaSHans Petter Selasky  * 3D case 0x7d5:                           O
3644*d6b92ffaSHans Petter Selasky  *
3645*d6b92ffaSHans Petter Selasky  *  b0:
3646*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3647*d6b92ffaSHans Petter Selasky  *  b2:
3648*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
3649*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
3650*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .       .
3651*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
3652*d6b92ffaSHans Petter Selasky  *  b7:                                           .   .
3653*d6b92ffaSHans Petter Selasky  *                                          O       . .
3654*d6b92ffaSHans Petter Selasky  *                                O                   O
3655*d6b92ffaSHans Petter Selasky  *
3656*d6b92ffaSHans Petter Selasky  *
3657*d6b92ffaSHans Petter Selasky  *
3658*d6b92ffaSHans Petter Selasky  *
3659*d6b92ffaSHans Petter Selasky  *                                          @
3660*d6b92ffaSHans Petter Selasky  */
3661*d6b92ffaSHans Petter Selasky static
handle_case_0x7d5(struct torus * t,int i,int j,int k)3662*d6b92ffaSHans Petter Selasky bool handle_case_0x7d5(struct torus *t, int i, int j, int k)
3663*d6b92ffaSHans Petter Selasky {
3664*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3665*d6b92ffaSHans Petter Selasky 	int ip2 = canonicalize(i + 2, t->x_sz);
3666*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3667*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3668*d6b92ffaSHans Petter Selasky 
3669*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, ip1, j, k) &&
3670*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, k,
3671*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][kp1],
3672*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
3673*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3674*d6b92ffaSHans Petter Selasky 						   t->sw[ip2][j][k]))) {
3675*d6b92ffaSHans Petter Selasky 		return true;
3676*d6b92ffaSHans Petter Selasky 	}
3677*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7d5, i, j, k, ip1, j, k);
3678*d6b92ffaSHans Petter Selasky 	return false;
3679*d6b92ffaSHans Petter Selasky }
3680*d6b92ffaSHans Petter Selasky 
3681*d6b92ffaSHans Petter Selasky /*
3682*d6b92ffaSHans Petter Selasky  * 3D case 0x7dc:                           O
3683*d6b92ffaSHans Petter Selasky  *
3684*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3685*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3686*d6b92ffaSHans Petter Selasky  *  b2:
3687*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3688*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
3689*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                          .
3690*d6b92ffaSHans Petter Selasky  *  b6:                                               .
3691*d6b92ffaSHans Petter Selasky  *  b7:                                               .
3692*d6b92ffaSHans Petter Selasky  *                                          O         .
3693*d6b92ffaSHans Petter Selasky  *                                O                   O
3694*d6b92ffaSHans Petter Selasky  *                                                  .
3695*d6b92ffaSHans Petter Selasky  *                                                .
3696*d6b92ffaSHans Petter Selasky  *                                              .
3697*d6b92ffaSHans Petter Selasky  *                                            .
3698*d6b92ffaSHans Petter Selasky  *                                          @
3699*d6b92ffaSHans Petter Selasky  */
3700*d6b92ffaSHans Petter Selasky static
handle_case_0x7dc(struct torus * t,int i,int j,int k)3701*d6b92ffaSHans Petter Selasky bool handle_case_0x7dc(struct torus *t, int i, int j, int k)
3702*d6b92ffaSHans Petter Selasky {
3703*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3704*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3705*d6b92ffaSHans Petter Selasky 	int jm1 = canonicalize(j - 1, t->y_sz);
3706*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3707*d6b92ffaSHans Petter Selasky 
3708*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, ip1, j, k) &&
3709*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, k,
3710*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][k],
3711*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
3712*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][kp1],
3713*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jm1][k]))) {
3714*d6b92ffaSHans Petter Selasky 		return true;
3715*d6b92ffaSHans Petter Selasky 	}
3716*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7dc, i, j, k, ip1, j, k);
3717*d6b92ffaSHans Petter Selasky 	return false;
3718*d6b92ffaSHans Petter Selasky }
3719*d6b92ffaSHans Petter Selasky 
3720*d6b92ffaSHans Petter Selasky /*
3721*d6b92ffaSHans Petter Selasky  * 3D case 0x7ea:                           O
3722*d6b92ffaSHans Petter Selasky  *
3723*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3724*d6b92ffaSHans Petter Selasky  *  b1:
3725*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3726*d6b92ffaSHans Petter Selasky  *  b3:                            O                   O
3727*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                 O
3728*d6b92ffaSHans Petter Selasky  *  b5:
3729*d6b92ffaSHans Petter Selasky  *  b6:
3730*d6b92ffaSHans Petter Selasky  *  b7:
3731*d6b92ffaSHans Petter Selasky  *                                          O
3732*d6b92ffaSHans Petter Selasky  *                                O         .         O
3733*d6b92ffaSHans Petter Selasky  *                                  .       .
3734*d6b92ffaSHans Petter Selasky  *                                    .     .
3735*d6b92ffaSHans Petter Selasky  *                                      .   .
3736*d6b92ffaSHans Petter Selasky  *                                        . .
3737*d6b92ffaSHans Petter Selasky  *                                          @
3738*d6b92ffaSHans Petter Selasky  */
3739*d6b92ffaSHans Petter Selasky static
handle_case_0x7ea(struct torus * t,int i,int j,int k)3740*d6b92ffaSHans Petter Selasky bool handle_case_0x7ea(struct torus *t, int i, int j, int k)
3741*d6b92ffaSHans Petter Selasky {
3742*d6b92ffaSHans Petter Selasky 	int im1 = canonicalize(i - 1, t->x_sz);
3743*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3744*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3745*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3746*d6b92ffaSHans Petter Selasky 
3747*d6b92ffaSHans Petter Selasky 	if (safe_x_perpendicular(t, i, j, k) &&
3748*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, k,
3749*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][kp1],
3750*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
3751*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3752*d6b92ffaSHans Petter Selasky 						   t->sw[im1][j][k]))) {
3753*d6b92ffaSHans Petter Selasky 		return true;
3754*d6b92ffaSHans Petter Selasky 	}
3755*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7ea, i, j, k, i, j, k);
3756*d6b92ffaSHans Petter Selasky 	return false;
3757*d6b92ffaSHans Petter Selasky }
3758*d6b92ffaSHans Petter Selasky 
3759*d6b92ffaSHans Petter Selasky /*
3760*d6b92ffaSHans Petter Selasky  * 3D case 0x7ec:                           O
3761*d6b92ffaSHans Petter Selasky  *
3762*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3763*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3764*d6b92ffaSHans Petter Selasky  *  b2:
3765*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3766*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O
3767*d6b92ffaSHans Petter Selasky  *  b5:
3768*d6b92ffaSHans Petter Selasky  *  b6:
3769*d6b92ffaSHans Petter Selasky  *  b7:
3770*d6b92ffaSHans Petter Selasky  *                                          O
3771*d6b92ffaSHans Petter Selasky  *                                O         .         O
3772*d6b92ffaSHans Petter Selasky  *                                          .       .
3773*d6b92ffaSHans Petter Selasky  *                                          .     .
3774*d6b92ffaSHans Petter Selasky  *                                          .   .
3775*d6b92ffaSHans Petter Selasky  *                                          . .
3776*d6b92ffaSHans Petter Selasky  *                                          @
3777*d6b92ffaSHans Petter Selasky  */
3778*d6b92ffaSHans Petter Selasky static
handle_case_0x7ec(struct torus * t,int i,int j,int k)3779*d6b92ffaSHans Petter Selasky bool handle_case_0x7ec(struct torus *t, int i, int j, int k)
3780*d6b92ffaSHans Petter Selasky {
3781*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3782*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3783*d6b92ffaSHans Petter Selasky 	int jm1 = canonicalize(j - 1, t->y_sz);
3784*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3785*d6b92ffaSHans Petter Selasky 
3786*d6b92ffaSHans Petter Selasky 	if (safe_y_perpendicular(t, i, j, k) &&
3787*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, k,
3788*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][kp1],
3789*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
3790*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
3791*d6b92ffaSHans Petter Selasky 						   t->sw[i][jm1][k]))) {
3792*d6b92ffaSHans Petter Selasky 		return true;
3793*d6b92ffaSHans Petter Selasky 	}
3794*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7ec, i, j, k, i, j, k);
3795*d6b92ffaSHans Petter Selasky 	return false;
3796*d6b92ffaSHans Petter Selasky }
3797*d6b92ffaSHans Petter Selasky 
3798*d6b92ffaSHans Petter Selasky /*
3799*d6b92ffaSHans Petter Selasky  * 3D case 0x7f1:                           O
3800*d6b92ffaSHans Petter Selasky  *
3801*d6b92ffaSHans Petter Selasky  *  b0:
3802*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3803*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3804*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
3805*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3806*d6b92ffaSHans Petter Selasky  *  b5:                                   .   .
3807*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .
3808*d6b92ffaSHans Petter Selasky  *  b7:                               .           .
3809*d6b92ffaSHans Petter Selasky  *                                  .       O       .
3810*d6b92ffaSHans Petter Selasky  *                                O                   O
3811*d6b92ffaSHans Petter Selasky  *
3812*d6b92ffaSHans Petter Selasky  *
3813*d6b92ffaSHans Petter Selasky  *
3814*d6b92ffaSHans Petter Selasky  *
3815*d6b92ffaSHans Petter Selasky  *                                          @
3816*d6b92ffaSHans Petter Selasky  */
3817*d6b92ffaSHans Petter Selasky static
handle_case_0x7f1(struct torus * t,int i,int j,int k)3818*d6b92ffaSHans Petter Selasky bool handle_case_0x7f1(struct torus *t, int i, int j, int k)
3819*d6b92ffaSHans Petter Selasky {
3820*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3821*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3822*d6b92ffaSHans Petter Selasky 	int km1 = canonicalize(k - 1, t->z_sz);
3823*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3824*d6b92ffaSHans Petter Selasky 
3825*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, ip1, jp1, k) &&
3826*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, jp1, kp1,
3827*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][k],
3828*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3829*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3830*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][km1]))) {
3831*d6b92ffaSHans Petter Selasky 		return true;
3832*d6b92ffaSHans Petter Selasky 	}
3833*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7f1, i, j, k, ip1, jp1, k);
3834*d6b92ffaSHans Petter Selasky 	return false;
3835*d6b92ffaSHans Petter Selasky }
3836*d6b92ffaSHans Petter Selasky 
3837*d6b92ffaSHans Petter Selasky /*
3838*d6b92ffaSHans Petter Selasky  * 3D case 0x7f2:                           O
3839*d6b92ffaSHans Petter Selasky  *
3840*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3841*d6b92ffaSHans Petter Selasky  *  b1:
3842*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3843*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
3844*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3845*d6b92ffaSHans Petter Selasky  *  b5:                                   .
3846*d6b92ffaSHans Petter Selasky  *  b6:                                 .
3847*d6b92ffaSHans Petter Selasky  *  b7:                               .
3848*d6b92ffaSHans Petter Selasky  *                                  .       O
3849*d6b92ffaSHans Petter Selasky  *                                O                   O
3850*d6b92ffaSHans Petter Selasky  *                                  .
3851*d6b92ffaSHans Petter Selasky  *                                    .
3852*d6b92ffaSHans Petter Selasky  *                                      .
3853*d6b92ffaSHans Petter Selasky  *                                        .
3854*d6b92ffaSHans Petter Selasky  *                                          @
3855*d6b92ffaSHans Petter Selasky  */
3856*d6b92ffaSHans Petter Selasky static
handle_case_0x7f2(struct torus * t,int i,int j,int k)3857*d6b92ffaSHans Petter Selasky bool handle_case_0x7f2(struct torus *t, int i, int j, int k)
3858*d6b92ffaSHans Petter Selasky {
3859*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3860*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3861*d6b92ffaSHans Petter Selasky 	int km1 = canonicalize(k - 1, t->z_sz);
3862*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3863*d6b92ffaSHans Petter Selasky 
3864*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, jp1, k) &&
3865*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, jp1, kp1,
3866*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][k],
3867*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3868*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3869*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][km1]))) {
3870*d6b92ffaSHans Petter Selasky 		return true;
3871*d6b92ffaSHans Petter Selasky 	}
3872*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7f2, i, j, k, i, jp1, k);
3873*d6b92ffaSHans Petter Selasky 	return false;
3874*d6b92ffaSHans Petter Selasky }
3875*d6b92ffaSHans Petter Selasky 
3876*d6b92ffaSHans Petter Selasky /*
3877*d6b92ffaSHans Petter Selasky  * 3D case 0x7f4:                           O
3878*d6b92ffaSHans Petter Selasky  *
3879*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3880*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3881*d6b92ffaSHans Petter Selasky  *  b2:
3882*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
3883*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3884*d6b92ffaSHans Petter Selasky  *  b5:                                       .
3885*d6b92ffaSHans Petter Selasky  *  b6:                                         .
3886*d6b92ffaSHans Petter Selasky  *  b7:                                           .
3887*d6b92ffaSHans Petter Selasky  *                                          O       .
3888*d6b92ffaSHans Petter Selasky  *                                O                   O
3889*d6b92ffaSHans Petter Selasky  *                                                  .
3890*d6b92ffaSHans Petter Selasky  *                                                .
3891*d6b92ffaSHans Petter Selasky  *                                              .
3892*d6b92ffaSHans Petter Selasky  *                                            .
3893*d6b92ffaSHans Petter Selasky  *                                          @
3894*d6b92ffaSHans Petter Selasky  */
3895*d6b92ffaSHans Petter Selasky static
handle_case_0x7f4(struct torus * t,int i,int j,int k)3896*d6b92ffaSHans Petter Selasky bool handle_case_0x7f4(struct torus *t, int i, int j, int k)
3897*d6b92ffaSHans Petter Selasky {
3898*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3899*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3900*d6b92ffaSHans Petter Selasky 	int km1 = canonicalize(k - 1, t->z_sz);
3901*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3902*d6b92ffaSHans Petter Selasky 
3903*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, ip1, j, k) &&
3904*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, ip1, j, kp1,
3905*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[i][j][k],
3906*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][k],
3907*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][jp1][k],
3908*d6b92ffaSHans Petter Selasky 						   t->sw[ip1][j][km1]))) {
3909*d6b92ffaSHans Petter Selasky 		return true;
3910*d6b92ffaSHans Petter Selasky 	}
3911*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7f4, i, j, k, ip1, j, k);
3912*d6b92ffaSHans Petter Selasky 	return false;
3913*d6b92ffaSHans Petter Selasky }
3914*d6b92ffaSHans Petter Selasky 
3915*d6b92ffaSHans Petter Selasky /*
3916*d6b92ffaSHans Petter Selasky  * 3D case 0x7f8:                           O
3917*d6b92ffaSHans Petter Selasky  *
3918*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
3919*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
3920*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
3921*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
3922*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3923*d6b92ffaSHans Petter Selasky  *  b5:
3924*d6b92ffaSHans Petter Selasky  *  b6:
3925*d6b92ffaSHans Petter Selasky  *  b7:
3926*d6b92ffaSHans Petter Selasky  *                                          O
3927*d6b92ffaSHans Petter Selasky  *                                O                   O
3928*d6b92ffaSHans Petter Selasky  *                                  .               .
3929*d6b92ffaSHans Petter Selasky  *                                    .           .
3930*d6b92ffaSHans Petter Selasky  *                                      .       .
3931*d6b92ffaSHans Petter Selasky  *                                        .   .
3932*d6b92ffaSHans Petter Selasky  *                                          @
3933*d6b92ffaSHans Petter Selasky  */
3934*d6b92ffaSHans Petter Selasky static
handle_case_0x7f8(struct torus * t,int i,int j,int k)3935*d6b92ffaSHans Petter Selasky bool handle_case_0x7f8(struct torus *t, int i, int j, int k)
3936*d6b92ffaSHans Petter Selasky {
3937*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3938*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3939*d6b92ffaSHans Petter Selasky 	int km1 = canonicalize(k - 1, t->z_sz);
3940*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3941*d6b92ffaSHans Petter Selasky 
3942*d6b92ffaSHans Petter Selasky 	if (safe_z_perpendicular(t, i, j, k) &&
3943*d6b92ffaSHans Petter Selasky 	    install_tswitch(t, i, j, kp1,
3944*d6b92ffaSHans Petter Selasky 			    tfind_3d_perpendicular(t->sw[ip1][j][k],
3945*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][k],
3946*d6b92ffaSHans Petter Selasky 						   t->sw[i][jp1][k],
3947*d6b92ffaSHans Petter Selasky 						   t->sw[i][j][km1]))) {
3948*d6b92ffaSHans Petter Selasky 		return true;
3949*d6b92ffaSHans Petter Selasky 	}
3950*d6b92ffaSHans Petter Selasky 	log_no_perp(t, 0x7f8, i, j, k, i, j, k);
3951*d6b92ffaSHans Petter Selasky 	return false;
3952*d6b92ffaSHans Petter Selasky }
3953*d6b92ffaSHans Petter Selasky 
3954*d6b92ffaSHans Petter Selasky /*
3955*d6b92ffaSHans Petter Selasky  * Handle the cases where three existing edges meet at a corner.
3956*d6b92ffaSHans Petter Selasky  */
3957*d6b92ffaSHans Petter Selasky 
3958*d6b92ffaSHans Petter Selasky /*
3959*d6b92ffaSHans Petter Selasky  * 3D case 0x717:                           O
3960*d6b92ffaSHans Petter Selasky  *                                        . . .
3961*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
3962*d6b92ffaSHans Petter Selasky  *  b1:                               .     .     .
3963*d6b92ffaSHans Petter Selasky  *  b2:                             .       .       .
3964*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
3965*d6b92ffaSHans Petter Selasky  *  b4:                                     O
3966*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]
3967*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]
3968*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]
3969*d6b92ffaSHans Petter Selasky  *                                          O
3970*d6b92ffaSHans Petter Selasky  *                                O                   O
3971*d6b92ffaSHans Petter Selasky  *
3972*d6b92ffaSHans Petter Selasky  *
3973*d6b92ffaSHans Petter Selasky  *
3974*d6b92ffaSHans Petter Selasky  *
3975*d6b92ffaSHans Petter Selasky  *                                          @
3976*d6b92ffaSHans Petter Selasky  */
3977*d6b92ffaSHans Petter Selasky static
handle_case_0x717(struct torus * t,int i,int j,int k)3978*d6b92ffaSHans Petter Selasky bool handle_case_0x717(struct torus *t, int i, int j, int k)
3979*d6b92ffaSHans Petter Selasky {
3980*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
3981*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
3982*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
3983*d6b92ffaSHans Petter Selasky 
3984*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
3985*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
3986*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
3987*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
3988*d6b92ffaSHans Petter Selasky 		return true;
3989*d6b92ffaSHans Petter Selasky 	}
3990*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x717, i, j, k, i, j, kp1);
3991*d6b92ffaSHans Petter Selasky 
3992*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
3993*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
3994*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
3995*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
3996*d6b92ffaSHans Petter Selasky 		return true;
3997*d6b92ffaSHans Petter Selasky 	}
3998*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x717, i, j, k, ip1, j, k);
3999*d6b92ffaSHans Petter Selasky 
4000*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
4001*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
4002*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4003*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4004*d6b92ffaSHans Petter Selasky 		return true;
4005*d6b92ffaSHans Petter Selasky 	}
4006*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x717, i, j, k, i, jp1, k);
4007*d6b92ffaSHans Petter Selasky 	return false;
4008*d6b92ffaSHans Petter Selasky }
4009*d6b92ffaSHans Petter Selasky 
4010*d6b92ffaSHans Petter Selasky /*
4011*d6b92ffaSHans Petter Selasky  * 3D case 0x72b:                           O
4012*d6b92ffaSHans Petter Selasky  *                                        .
4013*d6b92ffaSHans Petter Selasky  *  b0:                                 .
4014*d6b92ffaSHans Petter Selasky  *  b1:                               .
4015*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .
4016*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4017*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
4018*d6b92ffaSHans Petter Selasky  *  b5:                           .   .
4019*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4020*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .       .
4021*d6b92ffaSHans Petter Selasky  *                                .         O
4022*d6b92ffaSHans Petter Selasky  *                                O                   O
4023*d6b92ffaSHans Petter Selasky  *
4024*d6b92ffaSHans Petter Selasky  *
4025*d6b92ffaSHans Petter Selasky  *
4026*d6b92ffaSHans Petter Selasky  *
4027*d6b92ffaSHans Petter Selasky  *                                          @
4028*d6b92ffaSHans Petter Selasky  */
4029*d6b92ffaSHans Petter Selasky static
handle_case_0x72b(struct torus * t,int i,int j,int k)4030*d6b92ffaSHans Petter Selasky bool handle_case_0x72b(struct torus *t, int i, int j, int k)
4031*d6b92ffaSHans Petter Selasky {
4032*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4033*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4034*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4035*d6b92ffaSHans Petter Selasky 
4036*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
4037*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
4038*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4039*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4040*d6b92ffaSHans Petter Selasky 		return true;
4041*d6b92ffaSHans Petter Selasky 	}
4042*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x72b, i, j, k, ip1, j, kp1);
4043*d6b92ffaSHans Petter Selasky 
4044*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4045*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4046*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4047*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4048*d6b92ffaSHans Petter Selasky 		return true;
4049*d6b92ffaSHans Petter Selasky 	}
4050*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x72b, i, j, k, i, j, k);
4051*d6b92ffaSHans Petter Selasky 
4052*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
4053*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4054*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4055*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4056*d6b92ffaSHans Petter Selasky 		return true;
4057*d6b92ffaSHans Petter Selasky 	}
4058*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x72b, i, j, k, ip1, jp1, k);
4059*d6b92ffaSHans Petter Selasky 	return false;
4060*d6b92ffaSHans Petter Selasky }
4061*d6b92ffaSHans Petter Selasky 
4062*d6b92ffaSHans Petter Selasky /*
4063*d6b92ffaSHans Petter Selasky  * 3D case 0x74d:                           O
4064*d6b92ffaSHans Petter Selasky  *                                            .
4065*d6b92ffaSHans Petter Selasky  *  b0:                                         .
4066*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                      .
4067*d6b92ffaSHans Petter Selasky  *  b2:                                             .
4068*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4069*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
4070*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .   .
4071*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
4072*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                  .       .
4073*d6b92ffaSHans Petter Selasky  *                                          O         .
4074*d6b92ffaSHans Petter Selasky  *                                O                   O
4075*d6b92ffaSHans Petter Selasky  *
4076*d6b92ffaSHans Petter Selasky  *
4077*d6b92ffaSHans Petter Selasky  *
4078*d6b92ffaSHans Petter Selasky  *
4079*d6b92ffaSHans Petter Selasky  *                                          @
4080*d6b92ffaSHans Petter Selasky  */
4081*d6b92ffaSHans Petter Selasky static
handle_case_0x74d(struct torus * t,int i,int j,int k)4082*d6b92ffaSHans Petter Selasky bool handle_case_0x74d(struct torus *t, int i, int j, int k)
4083*d6b92ffaSHans Petter Selasky {
4084*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4085*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4086*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4087*d6b92ffaSHans Petter Selasky 
4088*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
4089*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
4090*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
4091*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4092*d6b92ffaSHans Petter Selasky 		return true;
4093*d6b92ffaSHans Petter Selasky 	}
4094*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x74d, i, j, k, i, jp1, kp1);
4095*d6b92ffaSHans Petter Selasky 
4096*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4097*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4098*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
4099*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4100*d6b92ffaSHans Petter Selasky 		return true;
4101*d6b92ffaSHans Petter Selasky 	}
4102*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x74d, i, j, k, i, j, k);
4103*d6b92ffaSHans Petter Selasky 
4104*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
4105*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4106*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
4107*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4108*d6b92ffaSHans Petter Selasky 		return true;
4109*d6b92ffaSHans Petter Selasky 	}
4110*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x74d, i, j, k, ip1, jp1, k);
4111*d6b92ffaSHans Petter Selasky 	return false;
4112*d6b92ffaSHans Petter Selasky }
4113*d6b92ffaSHans Petter Selasky 
4114*d6b92ffaSHans Petter Selasky /*
4115*d6b92ffaSHans Petter Selasky  * 3D case 0x771:                           O
4116*d6b92ffaSHans Petter Selasky  *                                          .
4117*d6b92ffaSHans Petter Selasky  *  b0:                                     .
4118*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .
4119*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]                .
4120*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4121*d6b92ffaSHans Petter Selasky  *  b4:                                     O
4122*d6b92ffaSHans Petter Selasky  *  b5:                                   .   .
4123*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .
4124*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]          .           .
4125*d6b92ffaSHans Petter Selasky  *                                  .       O       .
4126*d6b92ffaSHans Petter Selasky  *                                O                   O
4127*d6b92ffaSHans Petter Selasky  *
4128*d6b92ffaSHans Petter Selasky  *
4129*d6b92ffaSHans Petter Selasky  *
4130*d6b92ffaSHans Petter Selasky  *
4131*d6b92ffaSHans Petter Selasky  *                                          @
4132*d6b92ffaSHans Petter Selasky  */
4133*d6b92ffaSHans Petter Selasky static
handle_case_0x771(struct torus * t,int i,int j,int k)4134*d6b92ffaSHans Petter Selasky bool handle_case_0x771(struct torus *t, int i, int j, int k)
4135*d6b92ffaSHans Petter Selasky {
4136*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4137*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4138*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4139*d6b92ffaSHans Petter Selasky 
4140*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4141*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4142*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
4143*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
4144*d6b92ffaSHans Petter Selasky 		return true;
4145*d6b92ffaSHans Petter Selasky 	}
4146*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x771, i, j, k, i, j, k);
4147*d6b92ffaSHans Petter Selasky 
4148*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
4149*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][kp1],
4150*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
4151*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
4152*d6b92ffaSHans Petter Selasky 		return true;
4153*d6b92ffaSHans Petter Selasky 	}
4154*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x771, i, j, k, ip1, j, kp1);
4155*d6b92ffaSHans Petter Selasky 
4156*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
4157*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][kp1],
4158*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
4159*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
4160*d6b92ffaSHans Petter Selasky 		return true;
4161*d6b92ffaSHans Petter Selasky 	}
4162*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x771, i, j, k, i, jp1, kp1);
4163*d6b92ffaSHans Petter Selasky 	return false;
4164*d6b92ffaSHans Petter Selasky }
4165*d6b92ffaSHans Petter Selasky 
4166*d6b92ffaSHans Petter Selasky /*
4167*d6b92ffaSHans Petter Selasky  * 3D case 0x78e:                           O
4168*d6b92ffaSHans Petter Selasky  *
4169*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4170*d6b92ffaSHans Petter Selasky  *  b1:
4171*d6b92ffaSHans Petter Selasky  *  b2:
4172*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4173*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       .
4174*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .
4175*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .
4176*d6b92ffaSHans Petter Selasky  *  b7:                                   .   .
4177*d6b92ffaSHans Petter Selasky  *                                          O
4178*d6b92ffaSHans Petter Selasky  *                                O         .         O
4179*d6b92ffaSHans Petter Selasky  *                                          .
4180*d6b92ffaSHans Petter Selasky  *                                          .
4181*d6b92ffaSHans Petter Selasky  *                                          .
4182*d6b92ffaSHans Petter Selasky  *                                          .
4183*d6b92ffaSHans Petter Selasky  *                                          @
4184*d6b92ffaSHans Petter Selasky  */
4185*d6b92ffaSHans Petter Selasky static
handle_case_0x78e(struct torus * t,int i,int j,int k)4186*d6b92ffaSHans Petter Selasky bool handle_case_0x78e(struct torus *t, int i, int j, int k)
4187*d6b92ffaSHans Petter Selasky {
4188*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4189*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4190*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4191*d6b92ffaSHans Petter Selasky 
4192*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
4193*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
4194*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
4195*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4196*d6b92ffaSHans Petter Selasky 		return true;
4197*d6b92ffaSHans Petter Selasky 	}
4198*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78e, i, j, k, ip1, jp1, kp1);
4199*d6b92ffaSHans Petter Selasky 
4200*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
4201*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
4202*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
4203*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
4204*d6b92ffaSHans Petter Selasky 		return true;
4205*d6b92ffaSHans Petter Selasky 	}
4206*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78e, i, j, k, ip1, j, k);
4207*d6b92ffaSHans Petter Selasky 
4208*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
4209*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
4210*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
4211*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4212*d6b92ffaSHans Petter Selasky 		return true;
4213*d6b92ffaSHans Petter Selasky 	}
4214*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78e, i, j, k, i, jp1, k);
4215*d6b92ffaSHans Petter Selasky 	return false;
4216*d6b92ffaSHans Petter Selasky }
4217*d6b92ffaSHans Petter Selasky 
4218*d6b92ffaSHans Petter Selasky /*
4219*d6b92ffaSHans Petter Selasky  * 3D case 0x7b2:                           O
4220*d6b92ffaSHans Petter Selasky  *
4221*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4222*d6b92ffaSHans Petter Selasky  *  b1:
4223*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
4224*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
4225*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
4226*d6b92ffaSHans Petter Selasky  *  b5:                           .       .
4227*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4228*d6b92ffaSHans Petter Selasky  *  b7:                           .   .
4229*d6b92ffaSHans Petter Selasky  *                                . .       O
4230*d6b92ffaSHans Petter Selasky  *                                O                   O
4231*d6b92ffaSHans Petter Selasky  *                                  .
4232*d6b92ffaSHans Petter Selasky  *                                    .
4233*d6b92ffaSHans Petter Selasky  *                                      .
4234*d6b92ffaSHans Petter Selasky  *                                        .
4235*d6b92ffaSHans Petter Selasky  *                                          @
4236*d6b92ffaSHans Petter Selasky  */
4237*d6b92ffaSHans Petter Selasky static
handle_case_0x7b2(struct torus * t,int i,int j,int k)4238*d6b92ffaSHans Petter Selasky bool handle_case_0x7b2(struct torus *t, int i, int j, int k)
4239*d6b92ffaSHans Petter Selasky {
4240*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4241*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4242*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4243*d6b92ffaSHans Petter Selasky 
4244*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
4245*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
4246*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
4247*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
4248*d6b92ffaSHans Petter Selasky 		return true;
4249*d6b92ffaSHans Petter Selasky 	}
4250*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7b2, i, j, k, ip1, j, k);
4251*d6b92ffaSHans Petter Selasky 
4252*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
4253*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
4254*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
4255*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
4256*d6b92ffaSHans Petter Selasky 		return true;
4257*d6b92ffaSHans Petter Selasky 	}
4258*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7b2, i, j, k, ip1, jp1, kp1);
4259*d6b92ffaSHans Petter Selasky 
4260*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
4261*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
4262*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
4263*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k]))) {
4264*d6b92ffaSHans Petter Selasky 		return true;
4265*d6b92ffaSHans Petter Selasky 	}
4266*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7b2, i, j, k, i, j, kp1);
4267*d6b92ffaSHans Petter Selasky 	return false;
4268*d6b92ffaSHans Petter Selasky }
4269*d6b92ffaSHans Petter Selasky 
4270*d6b92ffaSHans Petter Selasky /*
4271*d6b92ffaSHans Petter Selasky  * 3D case 0x7d4:                           O
4272*d6b92ffaSHans Petter Selasky  *
4273*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4274*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
4275*d6b92ffaSHans Petter Selasky  *  b2:
4276*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
4277*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
4278*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .       .
4279*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
4280*d6b92ffaSHans Petter Selasky  *  b7:                                           .   .
4281*d6b92ffaSHans Petter Selasky  *                                          O       . .
4282*d6b92ffaSHans Petter Selasky  *                                O                   O
4283*d6b92ffaSHans Petter Selasky  *                                                  .
4284*d6b92ffaSHans Petter Selasky  *                                                .
4285*d6b92ffaSHans Petter Selasky  *                                              .
4286*d6b92ffaSHans Petter Selasky  *                                            .
4287*d6b92ffaSHans Petter Selasky  *                                          @
4288*d6b92ffaSHans Petter Selasky  */
4289*d6b92ffaSHans Petter Selasky static
handle_case_0x7d4(struct torus * t,int i,int j,int k)4290*d6b92ffaSHans Petter Selasky bool handle_case_0x7d4(struct torus *t, int i, int j, int k)
4291*d6b92ffaSHans Petter Selasky {
4292*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4293*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4294*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4295*d6b92ffaSHans Petter Selasky 
4296*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
4297*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
4298*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
4299*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
4300*d6b92ffaSHans Petter Selasky 		return true;
4301*d6b92ffaSHans Petter Selasky 	}
4302*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7d4, i, j, k, i, jp1, k);
4303*d6b92ffaSHans Petter Selasky 
4304*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
4305*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
4306*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
4307*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k]))) {
4308*d6b92ffaSHans Petter Selasky 		return true;
4309*d6b92ffaSHans Petter Selasky 	}
4310*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7d4, i, j, k, i, j, kp1);
4311*d6b92ffaSHans Petter Selasky 
4312*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
4313*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
4314*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
4315*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
4316*d6b92ffaSHans Petter Selasky 		return true;
4317*d6b92ffaSHans Petter Selasky 	}
4318*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7d4, i, j, k, ip1, jp1, kp1);
4319*d6b92ffaSHans Petter Selasky 	return false;
4320*d6b92ffaSHans Petter Selasky }
4321*d6b92ffaSHans Petter Selasky 
4322*d6b92ffaSHans Petter Selasky /*
4323*d6b92ffaSHans Petter Selasky  * 3D case 0x7e8:                           O
4324*d6b92ffaSHans Petter Selasky  *
4325*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4326*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
4327*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
4328*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4329*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O
4330*d6b92ffaSHans Petter Selasky  *  b5:
4331*d6b92ffaSHans Petter Selasky  *  b6:
4332*d6b92ffaSHans Petter Selasky  *  b7:
4333*d6b92ffaSHans Petter Selasky  *                                          O
4334*d6b92ffaSHans Petter Selasky  *                                O         .         O
4335*d6b92ffaSHans Petter Selasky  *                                  .       .       .
4336*d6b92ffaSHans Petter Selasky  *                                    .     .     .
4337*d6b92ffaSHans Petter Selasky  *                                      .   .   .
4338*d6b92ffaSHans Petter Selasky  *                                        . . .
4339*d6b92ffaSHans Petter Selasky  *                                          @
4340*d6b92ffaSHans Petter Selasky  */
4341*d6b92ffaSHans Petter Selasky static
handle_case_0x7e8(struct torus * t,int i,int j,int k)4342*d6b92ffaSHans Petter Selasky bool handle_case_0x7e8(struct torus *t, int i, int j, int k)
4343*d6b92ffaSHans Petter Selasky {
4344*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4345*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4346*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4347*d6b92ffaSHans Petter Selasky 
4348*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
4349*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4350*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
4351*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
4352*d6b92ffaSHans Petter Selasky 		return true;
4353*d6b92ffaSHans Petter Selasky 	}
4354*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7e8, i, j, k, ip1, jp1, k);
4355*d6b92ffaSHans Petter Selasky 
4356*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
4357*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4358*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
4359*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4360*d6b92ffaSHans Petter Selasky 		return true;
4361*d6b92ffaSHans Petter Selasky 	}
4362*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7e8, i, j, k, ip1, j, kp1);
4363*d6b92ffaSHans Petter Selasky 
4364*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
4365*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4366*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
4367*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4368*d6b92ffaSHans Petter Selasky 		return true;
4369*d6b92ffaSHans Petter Selasky 	}
4370*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7e8, i, j, k, i, jp1, kp1);
4371*d6b92ffaSHans Petter Selasky 	return false;
4372*d6b92ffaSHans Petter Selasky }
4373*d6b92ffaSHans Petter Selasky 
4374*d6b92ffaSHans Petter Selasky /*
4375*d6b92ffaSHans Petter Selasky  * Handle the cases where four corners on a single face are missing.
4376*d6b92ffaSHans Petter Selasky  */
4377*d6b92ffaSHans Petter Selasky 
4378*d6b92ffaSHans Petter Selasky /*
4379*d6b92ffaSHans Petter Selasky  * 3D case 0x70f:                           O
4380*d6b92ffaSHans Petter Selasky  *                                        .   .
4381*d6b92ffaSHans Petter Selasky  *  b0:                                 .       .
4382*d6b92ffaSHans Petter Selasky  *  b1:                               .           .
4383*d6b92ffaSHans Petter Selasky  *  b2:                             .               .
4384*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4385*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       .
4386*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .
4387*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .
4388*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .
4389*d6b92ffaSHans Petter Selasky  *                                          O
4390*d6b92ffaSHans Petter Selasky  *                                O                   O
4391*d6b92ffaSHans Petter Selasky  *
4392*d6b92ffaSHans Petter Selasky  *
4393*d6b92ffaSHans Petter Selasky  *
4394*d6b92ffaSHans Petter Selasky  *
4395*d6b92ffaSHans Petter Selasky  *                                          @
4396*d6b92ffaSHans Petter Selasky  */
4397*d6b92ffaSHans Petter Selasky static
handle_case_0x70f(struct torus * t,int i,int j,int k)4398*d6b92ffaSHans Petter Selasky bool handle_case_0x70f(struct torus *t, int i, int j, int k)
4399*d6b92ffaSHans Petter Selasky {
4400*d6b92ffaSHans Petter Selasky 	if (handle_case_0x71f(t, i, j, k))
4401*d6b92ffaSHans Petter Selasky 		return true;
4402*d6b92ffaSHans Petter Selasky 
4403*d6b92ffaSHans Petter Selasky 	if (handle_case_0x72f(t, i, j, k))
4404*d6b92ffaSHans Petter Selasky 		return true;
4405*d6b92ffaSHans Petter Selasky 
4406*d6b92ffaSHans Petter Selasky 	if (handle_case_0x74f(t, i, j, k))
4407*d6b92ffaSHans Petter Selasky 		return true;
4408*d6b92ffaSHans Petter Selasky 
4409*d6b92ffaSHans Petter Selasky 	return handle_case_0x78f(t, i, j, k);
4410*d6b92ffaSHans Petter Selasky }
4411*d6b92ffaSHans Petter Selasky 
4412*d6b92ffaSHans Petter Selasky /*
4413*d6b92ffaSHans Petter Selasky  * 3D case 0x733:                           O
4414*d6b92ffaSHans Petter Selasky  *                                        . .
4415*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .
4416*d6b92ffaSHans Petter Selasky  *  b1:                               .     .
4417*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
4418*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4419*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
4420*d6b92ffaSHans Petter Selasky  *  b5:                           .       .
4421*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4422*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .
4423*d6b92ffaSHans Petter Selasky  *                                . .       O
4424*d6b92ffaSHans Petter Selasky  *                                O                   O
4425*d6b92ffaSHans Petter Selasky  *
4426*d6b92ffaSHans Petter Selasky  *
4427*d6b92ffaSHans Petter Selasky  *
4428*d6b92ffaSHans Petter Selasky  *
4429*d6b92ffaSHans Petter Selasky  *                                          @
4430*d6b92ffaSHans Petter Selasky  */
4431*d6b92ffaSHans Petter Selasky static
handle_case_0x733(struct torus * t,int i,int j,int k)4432*d6b92ffaSHans Petter Selasky bool handle_case_0x733(struct torus *t, int i, int j, int k)
4433*d6b92ffaSHans Petter Selasky {
4434*d6b92ffaSHans Petter Selasky 	if (handle_case_0x737(t, i, j, k))
4435*d6b92ffaSHans Petter Selasky 		return true;
4436*d6b92ffaSHans Petter Selasky 
4437*d6b92ffaSHans Petter Selasky 	if (handle_case_0x73b(t, i, j, k))
4438*d6b92ffaSHans Petter Selasky 		return true;
4439*d6b92ffaSHans Petter Selasky 
4440*d6b92ffaSHans Petter Selasky 	if (handle_case_0x773(t, i, j, k))
4441*d6b92ffaSHans Petter Selasky 		return true;
4442*d6b92ffaSHans Petter Selasky 
4443*d6b92ffaSHans Petter Selasky 	return handle_case_0x7b3(t, i, j, k);
4444*d6b92ffaSHans Petter Selasky }
4445*d6b92ffaSHans Petter Selasky 
4446*d6b92ffaSHans Petter Selasky /*
4447*d6b92ffaSHans Petter Selasky  * 3D case 0x755:                           O
4448*d6b92ffaSHans Petter Selasky  *                                          . .
4449*d6b92ffaSHans Petter Selasky  *  b0:                                     .   .
4450*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
4451*d6b92ffaSHans Petter Selasky  *  b2:                                     .       .
4452*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4453*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
4454*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .       .
4455*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
4456*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                      .   .
4457*d6b92ffaSHans Petter Selasky  *                                          O       . .
4458*d6b92ffaSHans Petter Selasky  *                                O                   O
4459*d6b92ffaSHans Petter Selasky  *
4460*d6b92ffaSHans Petter Selasky  *
4461*d6b92ffaSHans Petter Selasky  *
4462*d6b92ffaSHans Petter Selasky  *
4463*d6b92ffaSHans Petter Selasky  *                                          @
4464*d6b92ffaSHans Petter Selasky  */
4465*d6b92ffaSHans Petter Selasky static
handle_case_0x755(struct torus * t,int i,int j,int k)4466*d6b92ffaSHans Petter Selasky bool handle_case_0x755(struct torus *t, int i, int j, int k)
4467*d6b92ffaSHans Petter Selasky {
4468*d6b92ffaSHans Petter Selasky 	if (handle_case_0x757(t, i, j, k))
4469*d6b92ffaSHans Petter Selasky 		return true;
4470*d6b92ffaSHans Petter Selasky 
4471*d6b92ffaSHans Petter Selasky 	if (handle_case_0x75d(t, i, j, k))
4472*d6b92ffaSHans Petter Selasky 		return true;
4473*d6b92ffaSHans Petter Selasky 
4474*d6b92ffaSHans Petter Selasky 	if (handle_case_0x775(t, i, j, k))
4475*d6b92ffaSHans Petter Selasky 		return true;
4476*d6b92ffaSHans Petter Selasky 
4477*d6b92ffaSHans Petter Selasky 	return handle_case_0x7d5(t, i, j, k);
4478*d6b92ffaSHans Petter Selasky }
4479*d6b92ffaSHans Petter Selasky 
4480*d6b92ffaSHans Petter Selasky /*
4481*d6b92ffaSHans Petter Selasky  * 3D case 0x7aa:                           O
4482*d6b92ffaSHans Petter Selasky  *
4483*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4484*d6b92ffaSHans Petter Selasky  *  b1:
4485*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
4486*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4487*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
4488*d6b92ffaSHans Petter Selasky  *  b5:                           .   .
4489*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4490*d6b92ffaSHans Petter Selasky  *  b7:                           .       .
4491*d6b92ffaSHans Petter Selasky  *                                .         O
4492*d6b92ffaSHans Petter Selasky  *                                O         .         O
4493*d6b92ffaSHans Petter Selasky  *                                  .       .
4494*d6b92ffaSHans Petter Selasky  *                                    .     .
4495*d6b92ffaSHans Petter Selasky  *                                      .   .
4496*d6b92ffaSHans Petter Selasky  *                                        . .
4497*d6b92ffaSHans Petter Selasky  *                                          @
4498*d6b92ffaSHans Petter Selasky  */
4499*d6b92ffaSHans Petter Selasky static
handle_case_0x7aa(struct torus * t,int i,int j,int k)4500*d6b92ffaSHans Petter Selasky bool handle_case_0x7aa(struct torus *t, int i, int j, int k)
4501*d6b92ffaSHans Petter Selasky {
4502*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7ab(t, i, j, k))
4503*d6b92ffaSHans Petter Selasky 		return true;
4504*d6b92ffaSHans Petter Selasky 
4505*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7ae(t, i, j, k))
4506*d6b92ffaSHans Petter Selasky 		return true;
4507*d6b92ffaSHans Petter Selasky 
4508*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7ba(t, i, j, k))
4509*d6b92ffaSHans Petter Selasky 		return true;
4510*d6b92ffaSHans Petter Selasky 
4511*d6b92ffaSHans Petter Selasky 	return handle_case_0x7ea(t, i, j, k);
4512*d6b92ffaSHans Petter Selasky }
4513*d6b92ffaSHans Petter Selasky 
4514*d6b92ffaSHans Petter Selasky /*
4515*d6b92ffaSHans Petter Selasky  * 3D case 0x7cc:                           O
4516*d6b92ffaSHans Petter Selasky  *
4517*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4518*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
4519*d6b92ffaSHans Petter Selasky  *  b2:
4520*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4521*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
4522*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .   .
4523*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
4524*d6b92ffaSHans Petter Selasky  *  b7:                                       .       .
4525*d6b92ffaSHans Petter Selasky  *                                          O         .
4526*d6b92ffaSHans Petter Selasky  *                                O         .         O
4527*d6b92ffaSHans Petter Selasky  *                                          .       .
4528*d6b92ffaSHans Petter Selasky  *                                          .     .
4529*d6b92ffaSHans Petter Selasky  *                                          .   .
4530*d6b92ffaSHans Petter Selasky  *                                          . .
4531*d6b92ffaSHans Petter Selasky  *                                          @
4532*d6b92ffaSHans Petter Selasky  */
4533*d6b92ffaSHans Petter Selasky static
handle_case_0x7cc(struct torus * t,int i,int j,int k)4534*d6b92ffaSHans Petter Selasky bool handle_case_0x7cc(struct torus *t, int i, int j, int k)
4535*d6b92ffaSHans Petter Selasky {
4536*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7cd(t, i, j, k))
4537*d6b92ffaSHans Petter Selasky 		return true;
4538*d6b92ffaSHans Petter Selasky 
4539*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7ce(t, i, j, k))
4540*d6b92ffaSHans Petter Selasky 		return true;
4541*d6b92ffaSHans Petter Selasky 
4542*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7dc(t, i, j, k))
4543*d6b92ffaSHans Petter Selasky 		return true;
4544*d6b92ffaSHans Petter Selasky 
4545*d6b92ffaSHans Petter Selasky 	return handle_case_0x7ec(t, i, j, k);
4546*d6b92ffaSHans Petter Selasky }
4547*d6b92ffaSHans Petter Selasky 
4548*d6b92ffaSHans Petter Selasky /*
4549*d6b92ffaSHans Petter Selasky  * 3D case 0x7f0:                           O
4550*d6b92ffaSHans Petter Selasky  *
4551*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
4552*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
4553*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
4554*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
4555*d6b92ffaSHans Petter Selasky  *  b4:                                     O
4556*d6b92ffaSHans Petter Selasky  *  b5:                                   .   .
4557*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .
4558*d6b92ffaSHans Petter Selasky  *  b7:                               .           .
4559*d6b92ffaSHans Petter Selasky  *                                  .       O       .
4560*d6b92ffaSHans Petter Selasky  *                                O                   O
4561*d6b92ffaSHans Petter Selasky  *                                  .               .
4562*d6b92ffaSHans Petter Selasky  *                                    .           .
4563*d6b92ffaSHans Petter Selasky  *                                      .       .
4564*d6b92ffaSHans Petter Selasky  *                                        .   .
4565*d6b92ffaSHans Petter Selasky  *                                          @
4566*d6b92ffaSHans Petter Selasky  */
4567*d6b92ffaSHans Petter Selasky static
handle_case_0x7f0(struct torus * t,int i,int j,int k)4568*d6b92ffaSHans Petter Selasky bool handle_case_0x7f0(struct torus *t, int i, int j, int k)
4569*d6b92ffaSHans Petter Selasky {
4570*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7f1(t, i, j, k))
4571*d6b92ffaSHans Petter Selasky 		return true;
4572*d6b92ffaSHans Petter Selasky 
4573*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7f2(t, i, j, k))
4574*d6b92ffaSHans Petter Selasky 		return true;
4575*d6b92ffaSHans Petter Selasky 
4576*d6b92ffaSHans Petter Selasky 	if (handle_case_0x7f4(t, i, j, k))
4577*d6b92ffaSHans Petter Selasky 		return true;
4578*d6b92ffaSHans Petter Selasky 
4579*d6b92ffaSHans Petter Selasky 	return handle_case_0x7f8(t, i, j, k);
4580*d6b92ffaSHans Petter Selasky }
4581*d6b92ffaSHans Petter Selasky 
4582*d6b92ffaSHans Petter Selasky /*
4583*d6b92ffaSHans Petter Selasky  * Handle the cases where three corners on a single face are missing.
4584*d6b92ffaSHans Petter Selasky  */
4585*d6b92ffaSHans Petter Selasky 
4586*d6b92ffaSHans Petter Selasky 
4587*d6b92ffaSHans Petter Selasky /*
4588*d6b92ffaSHans Petter Selasky  * 3D case 0x707:                           O
4589*d6b92ffaSHans Petter Selasky  *                                        . . .
4590*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
4591*d6b92ffaSHans Petter Selasky  *  b1:                               .     .     .
4592*d6b92ffaSHans Petter Selasky  *  b2:                             .       .       .
4593*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4594*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       .
4595*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .
4596*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .
4597*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .
4598*d6b92ffaSHans Petter Selasky  *                                          O
4599*d6b92ffaSHans Petter Selasky  *                                O                   O
4600*d6b92ffaSHans Petter Selasky  *
4601*d6b92ffaSHans Petter Selasky  *
4602*d6b92ffaSHans Petter Selasky  *
4603*d6b92ffaSHans Petter Selasky  *
4604*d6b92ffaSHans Petter Selasky  *                                          @
4605*d6b92ffaSHans Petter Selasky  */
4606*d6b92ffaSHans Petter Selasky static
handle_case_0x707(struct torus * t,int i,int j,int k)4607*d6b92ffaSHans Petter Selasky bool handle_case_0x707(struct torus *t, int i, int j, int k)
4608*d6b92ffaSHans Petter Selasky {
4609*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4610*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4611*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4612*d6b92ffaSHans Petter Selasky 
4613*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
4614*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
4615*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4616*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
4617*d6b92ffaSHans Petter Selasky 		return true;
4618*d6b92ffaSHans Petter Selasky 	}
4619*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x707, i, j, k, ip1, j, k);
4620*d6b92ffaSHans Petter Selasky 
4621*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
4622*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
4623*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4624*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4625*d6b92ffaSHans Petter Selasky 		return true;
4626*d6b92ffaSHans Petter Selasky 	}
4627*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x707, i, j, k, i, jp1, k);
4628*d6b92ffaSHans Petter Selasky 	return false;
4629*d6b92ffaSHans Petter Selasky }
4630*d6b92ffaSHans Petter Selasky 
4631*d6b92ffaSHans Petter Selasky /*
4632*d6b92ffaSHans Petter Selasky  * 3D case 0x70b:                           O
4633*d6b92ffaSHans Petter Selasky  *                                        .   .
4634*d6b92ffaSHans Petter Selasky  *  b0:                                 .       .
4635*d6b92ffaSHans Petter Selasky  *  b1:                               .           .
4636*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .               .
4637*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4638*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       .
4639*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .           .
4640*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
4641*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .       .   .
4642*d6b92ffaSHans Petter Selasky  *                                .         O
4643*d6b92ffaSHans Petter Selasky  *                                O                   O
4644*d6b92ffaSHans Petter Selasky  *
4645*d6b92ffaSHans Petter Selasky  *
4646*d6b92ffaSHans Petter Selasky  *
4647*d6b92ffaSHans Petter Selasky  *
4648*d6b92ffaSHans Petter Selasky  *                                          @
4649*d6b92ffaSHans Petter Selasky  */
4650*d6b92ffaSHans Petter Selasky static
handle_case_0x70b(struct torus * t,int i,int j,int k)4651*d6b92ffaSHans Petter Selasky bool handle_case_0x70b(struct torus *t, int i, int j, int k)
4652*d6b92ffaSHans Petter Selasky {
4653*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4654*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4655*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4656*d6b92ffaSHans Petter Selasky 
4657*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4658*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4659*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4660*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4661*d6b92ffaSHans Petter Selasky 		return true;
4662*d6b92ffaSHans Petter Selasky 	}
4663*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70b, i, j, k, i, j, k);
4664*d6b92ffaSHans Petter Selasky 
4665*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
4666*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4667*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4668*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4669*d6b92ffaSHans Petter Selasky 		return true;
4670*d6b92ffaSHans Petter Selasky 	}
4671*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70b, i, j, k, ip1, jp1, k);
4672*d6b92ffaSHans Petter Selasky 	return false;
4673*d6b92ffaSHans Petter Selasky }
4674*d6b92ffaSHans Petter Selasky 
4675*d6b92ffaSHans Petter Selasky /*
4676*d6b92ffaSHans Petter Selasky  * 3D case 0x70d:                           O
4677*d6b92ffaSHans Petter Selasky  *                                        .   .
4678*d6b92ffaSHans Petter Selasky  *  b0:                                 .       .
4679*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .           .
4680*d6b92ffaSHans Petter Selasky  *  b2:                             .               .
4681*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4682*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       . .
4683*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .   .
4684*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .     .
4685*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .       .
4686*d6b92ffaSHans Petter Selasky  *                                          O         .
4687*d6b92ffaSHans Petter Selasky  *                                O                   O
4688*d6b92ffaSHans Petter Selasky  *
4689*d6b92ffaSHans Petter Selasky  *
4690*d6b92ffaSHans Petter Selasky  *
4691*d6b92ffaSHans Petter Selasky  *
4692*d6b92ffaSHans Petter Selasky  *                                          @
4693*d6b92ffaSHans Petter Selasky  */
4694*d6b92ffaSHans Petter Selasky static
handle_case_0x70d(struct torus * t,int i,int j,int k)4695*d6b92ffaSHans Petter Selasky bool handle_case_0x70d(struct torus *t, int i, int j, int k)
4696*d6b92ffaSHans Petter Selasky {
4697*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4698*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4699*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4700*d6b92ffaSHans Petter Selasky 
4701*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4702*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4703*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
4704*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4705*d6b92ffaSHans Petter Selasky 		return true;
4706*d6b92ffaSHans Petter Selasky 	}
4707*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70d, i, j, k, i, j, k);
4708*d6b92ffaSHans Petter Selasky 
4709*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
4710*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4711*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
4712*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4713*d6b92ffaSHans Petter Selasky 		return true;
4714*d6b92ffaSHans Petter Selasky 	}
4715*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70d, i, j, k, ip1, jp1, k);
4716*d6b92ffaSHans Petter Selasky 	return false;
4717*d6b92ffaSHans Petter Selasky }
4718*d6b92ffaSHans Petter Selasky 
4719*d6b92ffaSHans Petter Selasky /*
4720*d6b92ffaSHans Petter Selasky  * 3D case 0x70e:                           O
4721*d6b92ffaSHans Petter Selasky  *                                        .   .
4722*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .       .
4723*d6b92ffaSHans Petter Selasky  *  b1:                               .           .
4724*d6b92ffaSHans Petter Selasky  *  b2:                             .               .
4725*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4726*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       .
4727*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .
4728*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .
4729*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .
4730*d6b92ffaSHans Petter Selasky  *                                          O
4731*d6b92ffaSHans Petter Selasky  *                                O         .         O
4732*d6b92ffaSHans Petter Selasky  *                                          .
4733*d6b92ffaSHans Petter Selasky  *                                          .
4734*d6b92ffaSHans Petter Selasky  *                                          .
4735*d6b92ffaSHans Petter Selasky  *                                          .
4736*d6b92ffaSHans Petter Selasky  *                                          @
4737*d6b92ffaSHans Petter Selasky  */
4738*d6b92ffaSHans Petter Selasky static
handle_case_0x70e(struct torus * t,int i,int j,int k)4739*d6b92ffaSHans Petter Selasky bool handle_case_0x70e(struct torus *t, int i, int j, int k)
4740*d6b92ffaSHans Petter Selasky {
4741*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4742*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4743*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4744*d6b92ffaSHans Petter Selasky 
4745*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
4746*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
4747*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
4748*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
4749*d6b92ffaSHans Petter Selasky 		return true;
4750*d6b92ffaSHans Petter Selasky 	}
4751*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70e, i, j, k, ip1, j, k);
4752*d6b92ffaSHans Petter Selasky 
4753*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
4754*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
4755*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
4756*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4757*d6b92ffaSHans Petter Selasky 		return true;
4758*d6b92ffaSHans Petter Selasky 	}
4759*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70e, i, j, k, i, jp1, k);
4760*d6b92ffaSHans Petter Selasky 	return false;
4761*d6b92ffaSHans Petter Selasky }
4762*d6b92ffaSHans Petter Selasky 
4763*d6b92ffaSHans Petter Selasky /*
4764*d6b92ffaSHans Petter Selasky  * 3D case 0x713:                           O
4765*d6b92ffaSHans Petter Selasky  *                                        . . .
4766*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
4767*d6b92ffaSHans Petter Selasky  *  b1:                               .     .     .
4768*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
4769*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4770*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
4771*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .       .
4772*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4773*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .
4774*d6b92ffaSHans Petter Selasky  *                                . .       O
4775*d6b92ffaSHans Petter Selasky  *                                O                   O
4776*d6b92ffaSHans Petter Selasky  *
4777*d6b92ffaSHans Petter Selasky  *
4778*d6b92ffaSHans Petter Selasky  *
4779*d6b92ffaSHans Petter Selasky  *
4780*d6b92ffaSHans Petter Selasky  *                                          @
4781*d6b92ffaSHans Petter Selasky  */
4782*d6b92ffaSHans Petter Selasky static
handle_case_0x713(struct torus * t,int i,int j,int k)4783*d6b92ffaSHans Petter Selasky bool handle_case_0x713(struct torus *t, int i, int j, int k)
4784*d6b92ffaSHans Petter Selasky {
4785*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4786*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4787*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4788*d6b92ffaSHans Petter Selasky 
4789*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
4790*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
4791*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4792*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
4793*d6b92ffaSHans Petter Selasky 		return true;
4794*d6b92ffaSHans Petter Selasky 	}
4795*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x713, i, j, k, ip1, j, k);
4796*d6b92ffaSHans Petter Selasky 
4797*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
4798*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
4799*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4800*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4801*d6b92ffaSHans Petter Selasky 		return true;
4802*d6b92ffaSHans Petter Selasky 	}
4803*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x713, i, j, k, i, j, kp1);
4804*d6b92ffaSHans Petter Selasky 	return false;
4805*d6b92ffaSHans Petter Selasky }
4806*d6b92ffaSHans Petter Selasky 
4807*d6b92ffaSHans Petter Selasky /*
4808*d6b92ffaSHans Petter Selasky  * 3D case 0x715:                           O
4809*d6b92ffaSHans Petter Selasky  *                                        . . .
4810*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
4811*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
4812*d6b92ffaSHans Petter Selasky  *  b2:                             .       .       .
4813*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4814*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
4815*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .       .
4816*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]                    .     .
4817*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                      .   .
4818*d6b92ffaSHans Petter Selasky  *                                          O       . .
4819*d6b92ffaSHans Petter Selasky  *                                O                   O
4820*d6b92ffaSHans Petter Selasky  *
4821*d6b92ffaSHans Petter Selasky  *
4822*d6b92ffaSHans Petter Selasky  *
4823*d6b92ffaSHans Petter Selasky  *
4824*d6b92ffaSHans Petter Selasky  *                                          @
4825*d6b92ffaSHans Petter Selasky  */
4826*d6b92ffaSHans Petter Selasky static
handle_case_0x715(struct torus * t,int i,int j,int k)4827*d6b92ffaSHans Petter Selasky bool handle_case_0x715(struct torus *t, int i, int j, int k)
4828*d6b92ffaSHans Petter Selasky {
4829*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4830*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4831*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4832*d6b92ffaSHans Petter Selasky 
4833*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
4834*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
4835*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4836*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4837*d6b92ffaSHans Petter Selasky 		return true;
4838*d6b92ffaSHans Petter Selasky 	}
4839*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x715, i, j, k, i, jp1, k);
4840*d6b92ffaSHans Petter Selasky 
4841*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
4842*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
4843*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
4844*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
4845*d6b92ffaSHans Petter Selasky 		return true;
4846*d6b92ffaSHans Petter Selasky 	}
4847*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x715, i, j, k, i, j, kp1);
4848*d6b92ffaSHans Petter Selasky 	return false;
4849*d6b92ffaSHans Petter Selasky }
4850*d6b92ffaSHans Petter Selasky 
4851*d6b92ffaSHans Petter Selasky /*
4852*d6b92ffaSHans Petter Selasky  * 3D case 0x723:                           O
4853*d6b92ffaSHans Petter Selasky  *                                        . .
4854*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .
4855*d6b92ffaSHans Petter Selasky  *  b1:                               .     .
4856*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
4857*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4858*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
4859*d6b92ffaSHans Petter Selasky  *  b5:                           .   .   .
4860*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4861*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .
4862*d6b92ffaSHans Petter Selasky  *                                . .       O
4863*d6b92ffaSHans Petter Selasky  *                                O                   O
4864*d6b92ffaSHans Petter Selasky  *
4865*d6b92ffaSHans Petter Selasky  *
4866*d6b92ffaSHans Petter Selasky  *
4867*d6b92ffaSHans Petter Selasky  *
4868*d6b92ffaSHans Petter Selasky  *                                          @
4869*d6b92ffaSHans Petter Selasky  */
4870*d6b92ffaSHans Petter Selasky static
handle_case_0x723(struct torus * t,int i,int j,int k)4871*d6b92ffaSHans Petter Selasky bool handle_case_0x723(struct torus *t, int i, int j, int k)
4872*d6b92ffaSHans Petter Selasky {
4873*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4874*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4875*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4876*d6b92ffaSHans Petter Selasky 
4877*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4878*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4879*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4880*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
4881*d6b92ffaSHans Petter Selasky 		return true;
4882*d6b92ffaSHans Petter Selasky 	}
4883*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x723, i, j, k, i, j, k);
4884*d6b92ffaSHans Petter Selasky 
4885*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
4886*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
4887*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4888*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4889*d6b92ffaSHans Petter Selasky 		return true;
4890*d6b92ffaSHans Petter Selasky 	}
4891*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x723, i, j, k, ip1, j, kp1);
4892*d6b92ffaSHans Petter Selasky 	return false;
4893*d6b92ffaSHans Petter Selasky }
4894*d6b92ffaSHans Petter Selasky 
4895*d6b92ffaSHans Petter Selasky /*
4896*d6b92ffaSHans Petter Selasky  * 3D case 0x72a:                           O
4897*d6b92ffaSHans Petter Selasky  *                                        .
4898*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .
4899*d6b92ffaSHans Petter Selasky  *  b1:                               .
4900*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .
4901*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
4902*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
4903*d6b92ffaSHans Petter Selasky  *  b5:                           .   .
4904*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4905*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .       .
4906*d6b92ffaSHans Petter Selasky  *                                .         O
4907*d6b92ffaSHans Petter Selasky  *                                O         .         O
4908*d6b92ffaSHans Petter Selasky  *                                  .       .
4909*d6b92ffaSHans Petter Selasky  *                                    .     .
4910*d6b92ffaSHans Petter Selasky  *                                      .   .
4911*d6b92ffaSHans Petter Selasky  *                                        . .
4912*d6b92ffaSHans Petter Selasky  *                                          @
4913*d6b92ffaSHans Petter Selasky  */
4914*d6b92ffaSHans Petter Selasky static
handle_case_0x72a(struct torus * t,int i,int j,int k)4915*d6b92ffaSHans Petter Selasky bool handle_case_0x72a(struct torus *t, int i, int j, int k)
4916*d6b92ffaSHans Petter Selasky {
4917*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4918*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4919*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4920*d6b92ffaSHans Petter Selasky 
4921*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
4922*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
4923*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4924*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4925*d6b92ffaSHans Petter Selasky 		return true;
4926*d6b92ffaSHans Petter Selasky 	}
4927*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x72a, i, j, k, ip1, jp1, k);
4928*d6b92ffaSHans Petter Selasky 
4929*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
4930*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
4931*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
4932*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4933*d6b92ffaSHans Petter Selasky 		return true;
4934*d6b92ffaSHans Petter Selasky 	}
4935*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x72a, i, j, k, ip1, j, kp1);
4936*d6b92ffaSHans Petter Selasky 	return false;
4937*d6b92ffaSHans Petter Selasky }
4938*d6b92ffaSHans Petter Selasky 
4939*d6b92ffaSHans Petter Selasky /*
4940*d6b92ffaSHans Petter Selasky  * 3D case 0x731:                           O
4941*d6b92ffaSHans Petter Selasky  *                                        . .
4942*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .
4943*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .
4944*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
4945*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4946*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
4947*d6b92ffaSHans Petter Selasky  *  b5:                           .       .   .
4948*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
4949*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .           .
4950*d6b92ffaSHans Petter Selasky  *                                . .       O       .
4951*d6b92ffaSHans Petter Selasky  *                                O                   O
4952*d6b92ffaSHans Petter Selasky  *
4953*d6b92ffaSHans Petter Selasky  *
4954*d6b92ffaSHans Petter Selasky  *
4955*d6b92ffaSHans Petter Selasky  *
4956*d6b92ffaSHans Petter Selasky  *                                          @
4957*d6b92ffaSHans Petter Selasky  */
4958*d6b92ffaSHans Petter Selasky static
handle_case_0x731(struct torus * t,int i,int j,int k)4959*d6b92ffaSHans Petter Selasky bool handle_case_0x731(struct torus *t, int i, int j, int k)
4960*d6b92ffaSHans Petter Selasky {
4961*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
4962*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
4963*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
4964*d6b92ffaSHans Petter Selasky 
4965*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
4966*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4967*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
4968*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
4969*d6b92ffaSHans Petter Selasky 		return true;
4970*d6b92ffaSHans Petter Selasky 	}
4971*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x731, i, j, k, i, j, k);
4972*d6b92ffaSHans Petter Selasky 
4973*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
4974*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
4975*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
4976*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
4977*d6b92ffaSHans Petter Selasky 		return true;
4978*d6b92ffaSHans Petter Selasky 	}
4979*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x731, i, j, k, ip1, j, kp1);
4980*d6b92ffaSHans Petter Selasky 	return false;
4981*d6b92ffaSHans Petter Selasky }
4982*d6b92ffaSHans Petter Selasky 
4983*d6b92ffaSHans Petter Selasky /*
4984*d6b92ffaSHans Petter Selasky  * 3D case 0x732:                           O
4985*d6b92ffaSHans Petter Selasky  *                                        . .
4986*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .
4987*d6b92ffaSHans Petter Selasky  *  b1:                               .     .
4988*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
4989*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
4990*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
4991*d6b92ffaSHans Petter Selasky  *  b5:                           .       .
4992*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
4993*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .
4994*d6b92ffaSHans Petter Selasky  *                                . .       O
4995*d6b92ffaSHans Petter Selasky  *                                O                   O
4996*d6b92ffaSHans Petter Selasky  *                                  .
4997*d6b92ffaSHans Petter Selasky  *                                    .
4998*d6b92ffaSHans Petter Selasky  *                                      .
4999*d6b92ffaSHans Petter Selasky  *                                        .
5000*d6b92ffaSHans Petter Selasky  *                                          @
5001*d6b92ffaSHans Petter Selasky  */
5002*d6b92ffaSHans Petter Selasky static
handle_case_0x732(struct torus * t,int i,int j,int k)5003*d6b92ffaSHans Petter Selasky bool handle_case_0x732(struct torus *t, int i, int j, int k)
5004*d6b92ffaSHans Petter Selasky {
5005*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5006*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5007*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5008*d6b92ffaSHans Petter Selasky 
5009*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
5010*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5011*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5012*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5013*d6b92ffaSHans Petter Selasky 		return true;
5014*d6b92ffaSHans Petter Selasky 	}
5015*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x732, i, j, k, ip1, j, k);
5016*d6b92ffaSHans Petter Selasky 
5017*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
5018*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5019*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5020*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5021*d6b92ffaSHans Petter Selasky 		return true;
5022*d6b92ffaSHans Petter Selasky 	}
5023*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x732, i, j, k, i, j, kp1);
5024*d6b92ffaSHans Petter Selasky 	return false;
5025*d6b92ffaSHans Petter Selasky }
5026*d6b92ffaSHans Petter Selasky 
5027*d6b92ffaSHans Petter Selasky /*
5028*d6b92ffaSHans Petter Selasky  * 3D case 0x745:                           O
5029*d6b92ffaSHans Petter Selasky  *                                          . .
5030*d6b92ffaSHans Petter Selasky  *  b0:                                     .   .
5031*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
5032*d6b92ffaSHans Petter Selasky  *  b2:                                     .       .
5033*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5034*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
5035*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .   .   .
5036*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
5037*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                  .   .   .
5038*d6b92ffaSHans Petter Selasky  *                                          O       . .
5039*d6b92ffaSHans Petter Selasky  *                                O                   O
5040*d6b92ffaSHans Petter Selasky  *
5041*d6b92ffaSHans Petter Selasky  *
5042*d6b92ffaSHans Petter Selasky  *
5043*d6b92ffaSHans Petter Selasky  *
5044*d6b92ffaSHans Petter Selasky  *                                          @
5045*d6b92ffaSHans Petter Selasky  */
5046*d6b92ffaSHans Petter Selasky static
handle_case_0x745(struct torus * t,int i,int j,int k)5047*d6b92ffaSHans Petter Selasky bool handle_case_0x745(struct torus *t, int i, int j, int k)
5048*d6b92ffaSHans Petter Selasky {
5049*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5050*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5051*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5052*d6b92ffaSHans Petter Selasky 
5053*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
5054*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5055*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5056*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
5057*d6b92ffaSHans Petter Selasky 		return true;
5058*d6b92ffaSHans Petter Selasky 	}
5059*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x745, i, j, k, i, j, k);
5060*d6b92ffaSHans Petter Selasky 
5061*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5062*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5063*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5064*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5065*d6b92ffaSHans Petter Selasky 		return true;
5066*d6b92ffaSHans Petter Selasky 	}
5067*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x745, i, j, k, i, jp1, kp1);
5068*d6b92ffaSHans Petter Selasky 	return false;
5069*d6b92ffaSHans Petter Selasky }
5070*d6b92ffaSHans Petter Selasky 
5071*d6b92ffaSHans Petter Selasky /*
5072*d6b92ffaSHans Petter Selasky  * 3D case 0x74c:                           O
5073*d6b92ffaSHans Petter Selasky  *                                            .
5074*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]                    .
5075*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                      .
5076*d6b92ffaSHans Petter Selasky  *  b2:                                             .
5077*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5078*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
5079*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .   .
5080*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
5081*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                  .       .
5082*d6b92ffaSHans Petter Selasky  *                                          O         .
5083*d6b92ffaSHans Petter Selasky  *                                O         .         O
5084*d6b92ffaSHans Petter Selasky  *                                          .       .
5085*d6b92ffaSHans Petter Selasky  *                                          .     .
5086*d6b92ffaSHans Petter Selasky  *                                          .   .
5087*d6b92ffaSHans Petter Selasky  *                                          . .
5088*d6b92ffaSHans Petter Selasky  *                                          @
5089*d6b92ffaSHans Petter Selasky  */
5090*d6b92ffaSHans Petter Selasky static
handle_case_0x74c(struct torus * t,int i,int j,int k)5091*d6b92ffaSHans Petter Selasky bool handle_case_0x74c(struct torus *t, int i, int j, int k)
5092*d6b92ffaSHans Petter Selasky {
5093*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5094*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5095*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5096*d6b92ffaSHans Petter Selasky 
5097*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
5098*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5099*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5100*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5101*d6b92ffaSHans Petter Selasky 		return true;
5102*d6b92ffaSHans Petter Selasky 	}
5103*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x74c, i, j, k, ip1, jp1, k);
5104*d6b92ffaSHans Petter Selasky 
5105*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5106*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5107*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5108*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5109*d6b92ffaSHans Petter Selasky 		return true;
5110*d6b92ffaSHans Petter Selasky 	}
5111*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x74c, i, j, k, i, jp1, kp1);
5112*d6b92ffaSHans Petter Selasky 	return false;
5113*d6b92ffaSHans Petter Selasky }
5114*d6b92ffaSHans Petter Selasky 
5115*d6b92ffaSHans Petter Selasky /*
5116*d6b92ffaSHans Petter Selasky  * 3D case 0x751:                           O
5117*d6b92ffaSHans Petter Selasky  *                                          . .
5118*d6b92ffaSHans Petter Selasky  *  b0:                                     .   .
5119*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
5120*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]                .       .
5121*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5122*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
5123*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]              .   .       .
5124*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .     .
5125*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]          .           .   .
5126*d6b92ffaSHans Petter Selasky  *                                  .       O       . .
5127*d6b92ffaSHans Petter Selasky  *                                O                   O
5128*d6b92ffaSHans Petter Selasky  *
5129*d6b92ffaSHans Petter Selasky  *
5130*d6b92ffaSHans Petter Selasky  *
5131*d6b92ffaSHans Petter Selasky  *
5132*d6b92ffaSHans Petter Selasky  *                                          @
5133*d6b92ffaSHans Petter Selasky  */
5134*d6b92ffaSHans Petter Selasky static
handle_case_0x751(struct torus * t,int i,int j,int k)5135*d6b92ffaSHans Petter Selasky bool handle_case_0x751(struct torus *t, int i, int j, int k)
5136*d6b92ffaSHans Petter Selasky {
5137*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5138*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5139*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5140*d6b92ffaSHans Petter Selasky 
5141*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
5142*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5143*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
5144*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
5145*d6b92ffaSHans Petter Selasky 		return true;
5146*d6b92ffaSHans Petter Selasky 	}
5147*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x751, i, j, k, i, j, k);
5148*d6b92ffaSHans Petter Selasky 
5149*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5150*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
5151*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
5152*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5153*d6b92ffaSHans Petter Selasky 		return true;
5154*d6b92ffaSHans Petter Selasky 	}
5155*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x751, i, j, k, i, jp1, kp1);
5156*d6b92ffaSHans Petter Selasky 	return false;
5157*d6b92ffaSHans Petter Selasky }
5158*d6b92ffaSHans Petter Selasky 
5159*d6b92ffaSHans Petter Selasky /*
5160*d6b92ffaSHans Petter Selasky  * 3D case 0x754:                           O
5161*d6b92ffaSHans Petter Selasky  *                                          . .
5162*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]                .   .
5163*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
5164*d6b92ffaSHans Petter Selasky  *  b2:                                     .       .
5165*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5166*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
5167*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .       .
5168*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
5169*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                      .   .
5170*d6b92ffaSHans Petter Selasky  *                                          O       . .
5171*d6b92ffaSHans Petter Selasky  *                                O                   O
5172*d6b92ffaSHans Petter Selasky  *                                                  .
5173*d6b92ffaSHans Petter Selasky  *                                                .
5174*d6b92ffaSHans Petter Selasky  *                                              .
5175*d6b92ffaSHans Petter Selasky  *                                            .
5176*d6b92ffaSHans Petter Selasky  *                                          @
5177*d6b92ffaSHans Petter Selasky  */
5178*d6b92ffaSHans Petter Selasky static
handle_case_0x754(struct torus * t,int i,int j,int k)5179*d6b92ffaSHans Petter Selasky bool handle_case_0x754(struct torus *t, int i, int j, int k)
5180*d6b92ffaSHans Petter Selasky {
5181*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5182*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5183*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5184*d6b92ffaSHans Petter Selasky 
5185*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
5186*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5187*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5188*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5189*d6b92ffaSHans Petter Selasky 		return true;
5190*d6b92ffaSHans Petter Selasky 	}
5191*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x754, i, j, k, i, jp1, k);
5192*d6b92ffaSHans Petter Selasky 
5193*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
5194*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5195*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5196*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
5197*d6b92ffaSHans Petter Selasky 		return true;
5198*d6b92ffaSHans Petter Selasky 	}
5199*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x754, i, j, k, i, j, kp1);
5200*d6b92ffaSHans Petter Selasky 	return false;
5201*d6b92ffaSHans Petter Selasky }
5202*d6b92ffaSHans Petter Selasky 
5203*d6b92ffaSHans Petter Selasky /*
5204*d6b92ffaSHans Petter Selasky  * 3D case 0x770:                           O
5205*d6b92ffaSHans Petter Selasky  *                                          .
5206*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]                .
5207*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .
5208*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]                .
5209*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5210*d6b92ffaSHans Petter Selasky  *  b4:                                     O
5211*d6b92ffaSHans Petter Selasky  *  b5:                                   .   .
5212*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .
5213*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]          .           .
5214*d6b92ffaSHans Petter Selasky  *                                  .       O       .
5215*d6b92ffaSHans Petter Selasky  *                                O                   O
5216*d6b92ffaSHans Petter Selasky  *                                  .               .
5217*d6b92ffaSHans Petter Selasky  *                                    .           .
5218*d6b92ffaSHans Petter Selasky  *                                      .       .
5219*d6b92ffaSHans Petter Selasky  *                                        .   .
5220*d6b92ffaSHans Petter Selasky  *                                          @
5221*d6b92ffaSHans Petter Selasky  */
5222*d6b92ffaSHans Petter Selasky static
handle_case_0x770(struct torus * t,int i,int j,int k)5223*d6b92ffaSHans Petter Selasky bool handle_case_0x770(struct torus *t, int i, int j, int k)
5224*d6b92ffaSHans Petter Selasky {
5225*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5226*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5227*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5228*d6b92ffaSHans Petter Selasky 
5229*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
5230*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5231*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
5232*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5233*d6b92ffaSHans Petter Selasky 		return true;
5234*d6b92ffaSHans Petter Selasky 	}
5235*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x770, i, j, k, ip1, j, kp1);
5236*d6b92ffaSHans Petter Selasky 
5237*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5238*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
5239*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
5240*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5241*d6b92ffaSHans Petter Selasky 		return true;
5242*d6b92ffaSHans Petter Selasky 	}
5243*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x770, i, j, k, i, jp1, kp1);
5244*d6b92ffaSHans Petter Selasky 	return false;
5245*d6b92ffaSHans Petter Selasky }
5246*d6b92ffaSHans Petter Selasky 
5247*d6b92ffaSHans Petter Selasky /*
5248*d6b92ffaSHans Petter Selasky  * 3D case 0x78a:                           O
5249*d6b92ffaSHans Petter Selasky  *
5250*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5251*d6b92ffaSHans Petter Selasky  *  b1:
5252*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5253*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5254*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       .
5255*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .           .
5256*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
5257*d6b92ffaSHans Petter Selasky  *  b7:                           .       .   .
5258*d6b92ffaSHans Petter Selasky  *                                .         O
5259*d6b92ffaSHans Petter Selasky  *                                O         .         O
5260*d6b92ffaSHans Petter Selasky  *                                  .       .
5261*d6b92ffaSHans Petter Selasky  *                                    .     .
5262*d6b92ffaSHans Petter Selasky  *                                      .   .
5263*d6b92ffaSHans Petter Selasky  *                                        . .
5264*d6b92ffaSHans Petter Selasky  *                                          @
5265*d6b92ffaSHans Petter Selasky  */
5266*d6b92ffaSHans Petter Selasky static
handle_case_0x78a(struct torus * t,int i,int j,int k)5267*d6b92ffaSHans Petter Selasky bool handle_case_0x78a(struct torus *t, int i, int j, int k)
5268*d6b92ffaSHans Petter Selasky {
5269*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5270*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5271*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5272*d6b92ffaSHans Petter Selasky 
5273*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
5274*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5275*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
5276*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
5277*d6b92ffaSHans Petter Selasky 		return true;
5278*d6b92ffaSHans Petter Selasky 	}
5279*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78a, i, j, k, ip1, j, k);
5280*d6b92ffaSHans Petter Selasky 
5281*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
5282*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
5283*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
5284*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5285*d6b92ffaSHans Petter Selasky 		return true;
5286*d6b92ffaSHans Petter Selasky 	}
5287*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78a, i, j, k, ip1, jp1, kp1);
5288*d6b92ffaSHans Petter Selasky 	return false;
5289*d6b92ffaSHans Petter Selasky }
5290*d6b92ffaSHans Petter Selasky 
5291*d6b92ffaSHans Petter Selasky /*
5292*d6b92ffaSHans Petter Selasky  * 3D case 0x78c:                           O
5293*d6b92ffaSHans Petter Selasky  *
5294*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5295*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
5296*d6b92ffaSHans Petter Selasky  *  b2:
5297*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5298*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       . .
5299*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .   .
5300*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .     .
5301*d6b92ffaSHans Petter Selasky  *  b7:                                   .   .       .
5302*d6b92ffaSHans Petter Selasky  *                                          O         .
5303*d6b92ffaSHans Petter Selasky  *                                O         .         O
5304*d6b92ffaSHans Petter Selasky  *                                          .       .
5305*d6b92ffaSHans Petter Selasky  *                                          .     .
5306*d6b92ffaSHans Petter Selasky  *                                          .   .
5307*d6b92ffaSHans Petter Selasky  *                                          . .
5308*d6b92ffaSHans Petter Selasky  *                                          @
5309*d6b92ffaSHans Petter Selasky  */
5310*d6b92ffaSHans Petter Selasky static
handle_case_0x78c(struct torus * t,int i,int j,int k)5311*d6b92ffaSHans Petter Selasky bool handle_case_0x78c(struct torus *t, int i, int j, int k)
5312*d6b92ffaSHans Petter Selasky {
5313*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5314*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5315*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5316*d6b92ffaSHans Petter Selasky 
5317*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
5318*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5319*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
5320*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5321*d6b92ffaSHans Petter Selasky 		return true;
5322*d6b92ffaSHans Petter Selasky 	}
5323*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78c, i, j, k, i, jp1, k);
5324*d6b92ffaSHans Petter Selasky 
5325*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
5326*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
5327*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
5328*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5329*d6b92ffaSHans Petter Selasky 		return true;
5330*d6b92ffaSHans Petter Selasky 	}
5331*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x78c, i, j, k, ip1, jp1, kp1);
5332*d6b92ffaSHans Petter Selasky 	return false;
5333*d6b92ffaSHans Petter Selasky }
5334*d6b92ffaSHans Petter Selasky 
5335*d6b92ffaSHans Petter Selasky /*
5336*d6b92ffaSHans Petter Selasky  * 3D case 0x7a2:                           O
5337*d6b92ffaSHans Petter Selasky  *
5338*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5339*d6b92ffaSHans Petter Selasky  *  b1:
5340*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5341*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
5342*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
5343*d6b92ffaSHans Petter Selasky  *  b5:                           .   .   .
5344*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
5345*d6b92ffaSHans Petter Selasky  *  b7:                           .   .   .
5346*d6b92ffaSHans Petter Selasky  *                                . .       O
5347*d6b92ffaSHans Petter Selasky  *                                O         .         O
5348*d6b92ffaSHans Petter Selasky  *                                  .       .
5349*d6b92ffaSHans Petter Selasky  *                                    .     .
5350*d6b92ffaSHans Petter Selasky  *                                      .   .
5351*d6b92ffaSHans Petter Selasky  *                                        . .
5352*d6b92ffaSHans Petter Selasky  *                                          @
5353*d6b92ffaSHans Petter Selasky  */
5354*d6b92ffaSHans Petter Selasky static
handle_case_0x7a2(struct torus * t,int i,int j,int k)5355*d6b92ffaSHans Petter Selasky bool handle_case_0x7a2(struct torus *t, int i, int j, int k)
5356*d6b92ffaSHans Petter Selasky {
5357*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5358*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5359*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5360*d6b92ffaSHans Petter Selasky 
5361*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
5362*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5363*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5364*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5365*d6b92ffaSHans Petter Selasky 		return true;
5366*d6b92ffaSHans Petter Selasky 	}
5367*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7a2, i, j, k, ip1, j, k);
5368*d6b92ffaSHans Petter Selasky 
5369*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
5370*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
5371*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5372*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5373*d6b92ffaSHans Petter Selasky 		return true;
5374*d6b92ffaSHans Petter Selasky 	}
5375*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7a2, i, j, k, ip1, jp1, kp1);
5376*d6b92ffaSHans Petter Selasky 	return false;
5377*d6b92ffaSHans Petter Selasky }
5378*d6b92ffaSHans Petter Selasky 
5379*d6b92ffaSHans Petter Selasky /*
5380*d6b92ffaSHans Petter Selasky  * 3D case 0x7a8:                           O
5381*d6b92ffaSHans Petter Selasky  *
5382*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5383*d6b92ffaSHans Petter Selasky  *  b1: t->sw[ip1][j  ][k  ]
5384*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5385*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5386*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
5387*d6b92ffaSHans Petter Selasky  *  b5:                           .   .
5388*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
5389*d6b92ffaSHans Petter Selasky  *  b7:                           .       .
5390*d6b92ffaSHans Petter Selasky  *                                .         O
5391*d6b92ffaSHans Petter Selasky  *                                O         .         O
5392*d6b92ffaSHans Petter Selasky  *                                  .       .       .
5393*d6b92ffaSHans Petter Selasky  *                                    .     .     .
5394*d6b92ffaSHans Petter Selasky  *                                      .   .   .
5395*d6b92ffaSHans Petter Selasky  *                                        . . .
5396*d6b92ffaSHans Petter Selasky  *                                          @
5397*d6b92ffaSHans Petter Selasky  */
5398*d6b92ffaSHans Petter Selasky static
handle_case_0x7a8(struct torus * t,int i,int j,int k)5399*d6b92ffaSHans Petter Selasky bool handle_case_0x7a8(struct torus *t, int i, int j, int k)
5400*d6b92ffaSHans Petter Selasky {
5401*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5402*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5403*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5404*d6b92ffaSHans Petter Selasky 
5405*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
5406*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5407*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
5408*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
5409*d6b92ffaSHans Petter Selasky 		return true;
5410*d6b92ffaSHans Petter Selasky 	}
5411*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7a8, i, j, k, ip1, jp1, k);
5412*d6b92ffaSHans Petter Selasky 
5413*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
5414*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5415*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
5416*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
5417*d6b92ffaSHans Petter Selasky 		return true;
5418*d6b92ffaSHans Petter Selasky 	}
5419*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7a8, i, j, k, ip1, j, kp1);
5420*d6b92ffaSHans Petter Selasky 	return false;
5421*d6b92ffaSHans Petter Selasky }
5422*d6b92ffaSHans Petter Selasky 
5423*d6b92ffaSHans Petter Selasky /*
5424*d6b92ffaSHans Petter Selasky  * 3D case 0x7b0:                           O
5425*d6b92ffaSHans Petter Selasky  *
5426*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5427*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
5428*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5429*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
5430*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
5431*d6b92ffaSHans Petter Selasky  *  b5:                           .       .   .
5432*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
5433*d6b92ffaSHans Petter Selasky  *  b7:                           .   .           .
5434*d6b92ffaSHans Petter Selasky  *                                . .       O       .
5435*d6b92ffaSHans Petter Selasky  *                                O                   O
5436*d6b92ffaSHans Petter Selasky  *                                  .               .
5437*d6b92ffaSHans Petter Selasky  *                                    .           .
5438*d6b92ffaSHans Petter Selasky  *                                      .       .
5439*d6b92ffaSHans Petter Selasky  *                                        .   .
5440*d6b92ffaSHans Petter Selasky  *                                          @
5441*d6b92ffaSHans Petter Selasky  */
5442*d6b92ffaSHans Petter Selasky static
handle_case_0x7b0(struct torus * t,int i,int j,int k)5443*d6b92ffaSHans Petter Selasky bool handle_case_0x7b0(struct torus *t, int i, int j, int k)
5444*d6b92ffaSHans Petter Selasky {
5445*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5446*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5447*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5448*d6b92ffaSHans Petter Selasky 
5449*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
5450*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5451*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5452*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5453*d6b92ffaSHans Petter Selasky 		return true;
5454*d6b92ffaSHans Petter Selasky 	}
5455*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7b0, i, j, k, i, j, kp1);
5456*d6b92ffaSHans Petter Selasky 
5457*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
5458*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
5459*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5460*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5461*d6b92ffaSHans Petter Selasky 		return true;
5462*d6b92ffaSHans Petter Selasky 	}
5463*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7b0, i, j, k, ip1, jp1, kp1);
5464*d6b92ffaSHans Petter Selasky 	return false;
5465*d6b92ffaSHans Petter Selasky }
5466*d6b92ffaSHans Petter Selasky 
5467*d6b92ffaSHans Petter Selasky /*
5468*d6b92ffaSHans Petter Selasky  * 3D case 0x7c4:                           O
5469*d6b92ffaSHans Petter Selasky  *
5470*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5471*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
5472*d6b92ffaSHans Petter Selasky  *  b2:
5473*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
5474*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
5475*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .   .   .
5476*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
5477*d6b92ffaSHans Petter Selasky  *  b7:                                       .   .   .
5478*d6b92ffaSHans Petter Selasky  *                                          O       . .
5479*d6b92ffaSHans Petter Selasky  *                                O         .         O
5480*d6b92ffaSHans Petter Selasky  *                                          .       .
5481*d6b92ffaSHans Petter Selasky  *                                          .     .
5482*d6b92ffaSHans Petter Selasky  *                                          .   .
5483*d6b92ffaSHans Petter Selasky  *                                          . .
5484*d6b92ffaSHans Petter Selasky  *                                          @
5485*d6b92ffaSHans Petter Selasky  */
5486*d6b92ffaSHans Petter Selasky static
handle_case_0x7c4(struct torus * t,int i,int j,int k)5487*d6b92ffaSHans Petter Selasky bool handle_case_0x7c4(struct torus *t, int i, int j, int k)
5488*d6b92ffaSHans Petter Selasky {
5489*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5490*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5491*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5492*d6b92ffaSHans Petter Selasky 
5493*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
5494*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5495*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5496*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5497*d6b92ffaSHans Petter Selasky 		return true;
5498*d6b92ffaSHans Petter Selasky 	}
5499*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7c4, i, j, k, i, jp1, k);
5500*d6b92ffaSHans Petter Selasky 
5501*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
5502*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
5503*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5504*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5505*d6b92ffaSHans Petter Selasky 		return true;
5506*d6b92ffaSHans Petter Selasky 	}
5507*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7c4, i, j, k, ip1, jp1, kp1);
5508*d6b92ffaSHans Petter Selasky 	return false;
5509*d6b92ffaSHans Petter Selasky }
5510*d6b92ffaSHans Petter Selasky 
5511*d6b92ffaSHans Petter Selasky /*
5512*d6b92ffaSHans Petter Selasky  * 3D case 0x7c8:                           O
5513*d6b92ffaSHans Petter Selasky  *
5514*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5515*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
5516*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5517*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5518*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
5519*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                      .   .
5520*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
5521*d6b92ffaSHans Petter Selasky  *  b7:                                       .       .
5522*d6b92ffaSHans Petter Selasky  *                                          O         .
5523*d6b92ffaSHans Petter Selasky  *                                O         .         O
5524*d6b92ffaSHans Petter Selasky  *                                  .       .       .
5525*d6b92ffaSHans Petter Selasky  *                                    .     .     .
5526*d6b92ffaSHans Petter Selasky  *                                      .   .   .
5527*d6b92ffaSHans Petter Selasky  *                                        . . .
5528*d6b92ffaSHans Petter Selasky  *                                          @
5529*d6b92ffaSHans Petter Selasky  */
5530*d6b92ffaSHans Petter Selasky static
handle_case_0x7c8(struct torus * t,int i,int j,int k)5531*d6b92ffaSHans Petter Selasky bool handle_case_0x7c8(struct torus *t, int i, int j, int k)
5532*d6b92ffaSHans Petter Selasky {
5533*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5534*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5535*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5536*d6b92ffaSHans Petter Selasky 
5537*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
5538*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5539*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
5540*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
5541*d6b92ffaSHans Petter Selasky 		return true;
5542*d6b92ffaSHans Petter Selasky 	}
5543*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7c8, i, j, k, ip1, jp1, k);
5544*d6b92ffaSHans Petter Selasky 
5545*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5546*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5547*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
5548*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
5549*d6b92ffaSHans Petter Selasky 		return true;
5550*d6b92ffaSHans Petter Selasky 	}
5551*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7c8, i, j, k, i, jp1, kp1);
5552*d6b92ffaSHans Petter Selasky 	return false;
5553*d6b92ffaSHans Petter Selasky }
5554*d6b92ffaSHans Petter Selasky 
5555*d6b92ffaSHans Petter Selasky /*
5556*d6b92ffaSHans Petter Selasky  * 3D case 0x7d0:                           O
5557*d6b92ffaSHans Petter Selasky  *
5558*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5559*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
5560*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5561*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
5562*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
5563*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]              .   .       .
5564*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .     .
5565*d6b92ffaSHans Petter Selasky  *  b7:                               .           .   .
5566*d6b92ffaSHans Petter Selasky  *                                  .       O       . .
5567*d6b92ffaSHans Petter Selasky  *                                O                   O
5568*d6b92ffaSHans Petter Selasky  *                                  .               .
5569*d6b92ffaSHans Petter Selasky  *                                    .           .
5570*d6b92ffaSHans Petter Selasky  *                                      .       .
5571*d6b92ffaSHans Petter Selasky  *                                        .   .
5572*d6b92ffaSHans Petter Selasky  *                                          @
5573*d6b92ffaSHans Petter Selasky  */
5574*d6b92ffaSHans Petter Selasky static
handle_case_0x7d0(struct torus * t,int i,int j,int k)5575*d6b92ffaSHans Petter Selasky bool handle_case_0x7d0(struct torus *t, int i, int j, int k)
5576*d6b92ffaSHans Petter Selasky {
5577*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5578*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5579*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5580*d6b92ffaSHans Petter Selasky 
5581*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
5582*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5583*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5584*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
5585*d6b92ffaSHans Petter Selasky 		return true;
5586*d6b92ffaSHans Petter Selasky 	}
5587*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7d0, i, j, k, i, j, kp1);
5588*d6b92ffaSHans Petter Selasky 
5589*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
5590*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
5591*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5592*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5593*d6b92ffaSHans Petter Selasky 		return true;
5594*d6b92ffaSHans Petter Selasky 	}
5595*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7d0, i, j, k, ip1, jp1, kp1);
5596*d6b92ffaSHans Petter Selasky 	return false;
5597*d6b92ffaSHans Petter Selasky }
5598*d6b92ffaSHans Petter Selasky 
5599*d6b92ffaSHans Petter Selasky /*
5600*d6b92ffaSHans Petter Selasky  * 3D case 0x7e0:                           O
5601*d6b92ffaSHans Petter Selasky  *
5602*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
5603*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
5604*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
5605*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
5606*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O
5607*d6b92ffaSHans Petter Selasky  *  b5:                                   .   .
5608*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .
5609*d6b92ffaSHans Petter Selasky  *  b7:                               .           .
5610*d6b92ffaSHans Petter Selasky  *                                  .       O       .
5611*d6b92ffaSHans Petter Selasky  *                                O         .         O
5612*d6b92ffaSHans Petter Selasky  *                                  .       .       .
5613*d6b92ffaSHans Petter Selasky  *                                    .     .     .
5614*d6b92ffaSHans Petter Selasky  *                                      .   .   .
5615*d6b92ffaSHans Petter Selasky  *                                        . . .
5616*d6b92ffaSHans Petter Selasky  *                                          @
5617*d6b92ffaSHans Petter Selasky  */
5618*d6b92ffaSHans Petter Selasky static
handle_case_0x7e0(struct torus * t,int i,int j,int k)5619*d6b92ffaSHans Petter Selasky bool handle_case_0x7e0(struct torus *t, int i, int j, int k)
5620*d6b92ffaSHans Petter Selasky {
5621*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5622*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5623*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5624*d6b92ffaSHans Petter Selasky 
5625*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
5626*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5627*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
5628*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
5629*d6b92ffaSHans Petter Selasky 		return true;
5630*d6b92ffaSHans Petter Selasky 	}
5631*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7e0, i, j, k, ip1, j, kp1);
5632*d6b92ffaSHans Petter Selasky 
5633*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5634*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5635*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
5636*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
5637*d6b92ffaSHans Petter Selasky 		return true;
5638*d6b92ffaSHans Petter Selasky 	}
5639*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7e0, i, j, k, i, jp1, kp1);
5640*d6b92ffaSHans Petter Selasky 	return false;
5641*d6b92ffaSHans Petter Selasky }
5642*d6b92ffaSHans Petter Selasky 
5643*d6b92ffaSHans Petter Selasky /*
5644*d6b92ffaSHans Petter Selasky  * Handle the cases where two corners on a single edge are missing.
5645*d6b92ffaSHans Petter Selasky  */
5646*d6b92ffaSHans Petter Selasky 
5647*d6b92ffaSHans Petter Selasky /*
5648*d6b92ffaSHans Petter Selasky  * 3D case 0x703:                           O
5649*d6b92ffaSHans Petter Selasky  *                                        . . .
5650*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
5651*d6b92ffaSHans Petter Selasky  *  b1:                               .     .     .
5652*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
5653*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5654*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       .
5655*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .   .       .
5656*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
5657*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .   .
5658*d6b92ffaSHans Petter Selasky  *                                . .       O
5659*d6b92ffaSHans Petter Selasky  *                                O                   O
5660*d6b92ffaSHans Petter Selasky  *
5661*d6b92ffaSHans Petter Selasky  *
5662*d6b92ffaSHans Petter Selasky  *
5663*d6b92ffaSHans Petter Selasky  *
5664*d6b92ffaSHans Petter Selasky  *                                          @
5665*d6b92ffaSHans Petter Selasky  */
5666*d6b92ffaSHans Petter Selasky static
handle_case_0x703(struct torus * t,int i,int j,int k)5667*d6b92ffaSHans Petter Selasky bool handle_case_0x703(struct torus *t, int i, int j, int k)
5668*d6b92ffaSHans Petter Selasky {
5669*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5670*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5671*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5672*d6b92ffaSHans Petter Selasky 
5673*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
5674*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
5675*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
5676*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
5677*d6b92ffaSHans Petter Selasky 		return true;
5678*d6b92ffaSHans Petter Selasky 	}
5679*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x703, i, j, k, i, j, k);
5680*d6b92ffaSHans Petter Selasky 
5681*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
5682*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
5683*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
5684*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
5685*d6b92ffaSHans Petter Selasky 		return true;
5686*d6b92ffaSHans Petter Selasky 	}
5687*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x703, i, j, k, ip1, j, k);
5688*d6b92ffaSHans Petter Selasky 	return false;
5689*d6b92ffaSHans Petter Selasky }
5690*d6b92ffaSHans Petter Selasky 
5691*d6b92ffaSHans Petter Selasky /*
5692*d6b92ffaSHans Petter Selasky  * 3D case 0x705:                           O
5693*d6b92ffaSHans Petter Selasky  *                                        . . .
5694*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
5695*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
5696*d6b92ffaSHans Petter Selasky  *  b2:                             .       .       .
5697*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5698*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       . .
5699*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .       .   .   .
5700*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .     .
5701*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .   .   .
5702*d6b92ffaSHans Petter Selasky  *                                          O       . .
5703*d6b92ffaSHans Petter Selasky  *                                O                   O
5704*d6b92ffaSHans Petter Selasky  *
5705*d6b92ffaSHans Petter Selasky  *
5706*d6b92ffaSHans Petter Selasky  *
5707*d6b92ffaSHans Petter Selasky  *
5708*d6b92ffaSHans Petter Selasky  *                                          @
5709*d6b92ffaSHans Petter Selasky  */
5710*d6b92ffaSHans Petter Selasky static
handle_case_0x705(struct torus * t,int i,int j,int k)5711*d6b92ffaSHans Petter Selasky bool handle_case_0x705(struct torus *t, int i, int j, int k)
5712*d6b92ffaSHans Petter Selasky {
5713*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5714*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5715*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5716*d6b92ffaSHans Petter Selasky 
5717*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
5718*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5719*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5720*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
5721*d6b92ffaSHans Petter Selasky 		return true;
5722*d6b92ffaSHans Petter Selasky 	}
5723*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x705, i, j, k, i, j, k);
5724*d6b92ffaSHans Petter Selasky 
5725*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
5726*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][jp1][k],
5727*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
5728*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5729*d6b92ffaSHans Petter Selasky 		return true;
5730*d6b92ffaSHans Petter Selasky 	}
5731*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x705, i, j, k, i, jp1, k);
5732*d6b92ffaSHans Petter Selasky 	return false;
5733*d6b92ffaSHans Petter Selasky }
5734*d6b92ffaSHans Petter Selasky 
5735*d6b92ffaSHans Petter Selasky /*
5736*d6b92ffaSHans Petter Selasky  * 3D case 0x70a:                           O
5737*d6b92ffaSHans Petter Selasky  *                                        . . .
5738*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .       .
5739*d6b92ffaSHans Petter Selasky  *  b1:                               .           .
5740*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .               .
5741*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5742*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       .
5743*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .           .
5744*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
5745*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .       .   .
5746*d6b92ffaSHans Petter Selasky  *                                .         O
5747*d6b92ffaSHans Petter Selasky  *                                O         .         O
5748*d6b92ffaSHans Petter Selasky  *                                  .       .
5749*d6b92ffaSHans Petter Selasky  *                                    .     .
5750*d6b92ffaSHans Petter Selasky  *                                      .   .
5751*d6b92ffaSHans Petter Selasky  *                                        . .
5752*d6b92ffaSHans Petter Selasky  *                                          @
5753*d6b92ffaSHans Petter Selasky  */
5754*d6b92ffaSHans Petter Selasky static
handle_case_0x70a(struct torus * t,int i,int j,int k)5755*d6b92ffaSHans Petter Selasky bool handle_case_0x70a(struct torus *t, int i, int j, int k)
5756*d6b92ffaSHans Petter Selasky {
5757*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5758*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5759*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5760*d6b92ffaSHans Petter Selasky 
5761*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
5762*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5763*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
5764*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
5765*d6b92ffaSHans Petter Selasky 		return true;
5766*d6b92ffaSHans Petter Selasky 	}
5767*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70a, i, j, k, ip1, j, k);
5768*d6b92ffaSHans Petter Selasky 
5769*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
5770*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
5771*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
5772*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5773*d6b92ffaSHans Petter Selasky 		return true;
5774*d6b92ffaSHans Petter Selasky 	}
5775*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70a, i, j, k, ip1, jp1, k);
5776*d6b92ffaSHans Petter Selasky 	return false;
5777*d6b92ffaSHans Petter Selasky }
5778*d6b92ffaSHans Petter Selasky 
5779*d6b92ffaSHans Petter Selasky /*
5780*d6b92ffaSHans Petter Selasky  * 3D case 0x70c:                           O
5781*d6b92ffaSHans Petter Selasky  *                                        .   .
5782*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .       .
5783*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .           .
5784*d6b92ffaSHans Petter Selasky  *  b2:                             .               .
5785*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
5786*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       . .
5787*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .           .   .
5788*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .     .
5789*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .       .
5790*d6b92ffaSHans Petter Selasky  *                                          O         .
5791*d6b92ffaSHans Petter Selasky  *                                O         .         O
5792*d6b92ffaSHans Petter Selasky  *                                          .       .
5793*d6b92ffaSHans Petter Selasky  *                                          .     .
5794*d6b92ffaSHans Petter Selasky  *                                          .   .
5795*d6b92ffaSHans Petter Selasky  *                                          . .
5796*d6b92ffaSHans Petter Selasky  *                                          @
5797*d6b92ffaSHans Petter Selasky  */
5798*d6b92ffaSHans Petter Selasky static
handle_case_0x70c(struct torus * t,int i,int j,int k)5799*d6b92ffaSHans Petter Selasky bool handle_case_0x70c(struct torus *t, int i, int j, int k)
5800*d6b92ffaSHans Petter Selasky {
5801*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5802*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5803*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5804*d6b92ffaSHans Petter Selasky 
5805*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
5806*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5807*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
5808*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5809*d6b92ffaSHans Petter Selasky 		return true;
5810*d6b92ffaSHans Petter Selasky 	}
5811*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70c, i, j, k, i, jp1, k);
5812*d6b92ffaSHans Petter Selasky 
5813*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
5814*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5815*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5816*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5817*d6b92ffaSHans Petter Selasky 		return true;
5818*d6b92ffaSHans Petter Selasky 	}
5819*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x70c, i, j, k, ip1, jp1, k);
5820*d6b92ffaSHans Petter Selasky 	return false;
5821*d6b92ffaSHans Petter Selasky }
5822*d6b92ffaSHans Petter Selasky 
5823*d6b92ffaSHans Petter Selasky /*
5824*d6b92ffaSHans Petter Selasky  * 3D case 0x711:                           O
5825*d6b92ffaSHans Petter Selasky  *                                        . . .
5826*d6b92ffaSHans Petter Selasky  *  b0:                                 .   .   .
5827*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
5828*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
5829*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5830*d6b92ffaSHans Petter Selasky  *  b4:                           .         O         .
5831*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .       .   .       .
5832*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
5833*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .           .   .
5834*d6b92ffaSHans Petter Selasky  *                                . .       O       . .
5835*d6b92ffaSHans Petter Selasky  *                                O                   O
5836*d6b92ffaSHans Petter Selasky  *
5837*d6b92ffaSHans Petter Selasky  *
5838*d6b92ffaSHans Petter Selasky  *
5839*d6b92ffaSHans Petter Selasky  *
5840*d6b92ffaSHans Petter Selasky  *                                          @
5841*d6b92ffaSHans Petter Selasky  */
5842*d6b92ffaSHans Petter Selasky static
handle_case_0x711(struct torus * t,int i,int j,int k)5843*d6b92ffaSHans Petter Selasky bool handle_case_0x711(struct torus *t, int i, int j, int k)
5844*d6b92ffaSHans Petter Selasky {
5845*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5846*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5847*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5848*d6b92ffaSHans Petter Selasky 
5849*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
5850*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5851*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
5852*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
5853*d6b92ffaSHans Petter Selasky 		return true;
5854*d6b92ffaSHans Petter Selasky 	}
5855*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x711, i, j, k, i, j, k);
5856*d6b92ffaSHans Petter Selasky 
5857*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
5858*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
5859*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1],
5860*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5861*d6b92ffaSHans Petter Selasky 		return true;
5862*d6b92ffaSHans Petter Selasky 	}
5863*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x711, i, j, k, i, j, kp1);
5864*d6b92ffaSHans Petter Selasky 	return false;
5865*d6b92ffaSHans Petter Selasky }
5866*d6b92ffaSHans Petter Selasky 
5867*d6b92ffaSHans Petter Selasky /*
5868*d6b92ffaSHans Petter Selasky  * 3D case 0x722:                           O
5869*d6b92ffaSHans Petter Selasky  *                                        . .
5870*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .
5871*d6b92ffaSHans Petter Selasky  *  b1:                               .     .
5872*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
5873*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5874*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
5875*d6b92ffaSHans Petter Selasky  *  b5:                           .   .   .
5876*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .
5877*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .
5878*d6b92ffaSHans Petter Selasky  *                                . .       O
5879*d6b92ffaSHans Petter Selasky  *                                O         .         O
5880*d6b92ffaSHans Petter Selasky  *                                  .       .
5881*d6b92ffaSHans Petter Selasky  *                                    .     .
5882*d6b92ffaSHans Petter Selasky  *                                      .   .
5883*d6b92ffaSHans Petter Selasky  *                                        . .
5884*d6b92ffaSHans Petter Selasky  *                                          @
5885*d6b92ffaSHans Petter Selasky  */
5886*d6b92ffaSHans Petter Selasky static
handle_case_0x722(struct torus * t,int i,int j,int k)5887*d6b92ffaSHans Petter Selasky bool handle_case_0x722(struct torus *t, int i, int j, int k)
5888*d6b92ffaSHans Petter Selasky {
5889*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5890*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5891*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5892*d6b92ffaSHans Petter Selasky 
5893*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
5894*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5895*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5896*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5897*d6b92ffaSHans Petter Selasky 		return true;
5898*d6b92ffaSHans Petter Selasky 	}
5899*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x722, i, j, k, ip1, j, k);
5900*d6b92ffaSHans Petter Selasky 
5901*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
5902*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5903*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1],
5904*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5905*d6b92ffaSHans Petter Selasky 		return true;
5906*d6b92ffaSHans Petter Selasky 	}
5907*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x722, i, j, k, ip1, j, kp1);
5908*d6b92ffaSHans Petter Selasky 	return false;
5909*d6b92ffaSHans Petter Selasky }
5910*d6b92ffaSHans Petter Selasky 
5911*d6b92ffaSHans Petter Selasky /*
5912*d6b92ffaSHans Petter Selasky  * 3D case 0x730:                           O
5913*d6b92ffaSHans Petter Selasky  *                                        . .
5914*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .
5915*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .
5916*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
5917*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5918*d6b92ffaSHans Petter Selasky  *  b4:                           .         O
5919*d6b92ffaSHans Petter Selasky  *  b5:                           .       .   .
5920*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
5921*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .           .
5922*d6b92ffaSHans Petter Selasky  *                                . .       O       .
5923*d6b92ffaSHans Petter Selasky  *                                O                   O
5924*d6b92ffaSHans Petter Selasky  *                                  .               .
5925*d6b92ffaSHans Petter Selasky  *                                    .           .
5926*d6b92ffaSHans Petter Selasky  *                                      .       .
5927*d6b92ffaSHans Petter Selasky  *                                        .   .
5928*d6b92ffaSHans Petter Selasky  *                                          @
5929*d6b92ffaSHans Petter Selasky  */
5930*d6b92ffaSHans Petter Selasky static
handle_case_0x730(struct torus * t,int i,int j,int k)5931*d6b92ffaSHans Petter Selasky bool handle_case_0x730(struct torus *t, int i, int j, int k)
5932*d6b92ffaSHans Petter Selasky {
5933*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5934*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5935*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5936*d6b92ffaSHans Petter Selasky 
5937*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
5938*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5939*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
5940*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
5941*d6b92ffaSHans Petter Selasky 		return true;
5942*d6b92ffaSHans Petter Selasky 	}
5943*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x730, i, j, k, i, j, kp1);
5944*d6b92ffaSHans Petter Selasky 
5945*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
5946*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
5947*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
5948*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5949*d6b92ffaSHans Petter Selasky 		return true;
5950*d6b92ffaSHans Petter Selasky 	}
5951*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x730, i, j, k, ip1, j, kp1);
5952*d6b92ffaSHans Petter Selasky 	return false;
5953*d6b92ffaSHans Petter Selasky }
5954*d6b92ffaSHans Petter Selasky 
5955*d6b92ffaSHans Petter Selasky /*
5956*d6b92ffaSHans Petter Selasky  * 3D case 0x744:                           O
5957*d6b92ffaSHans Petter Selasky  *                                          . .
5958*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]                .   .
5959*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
5960*d6b92ffaSHans Petter Selasky  *  b2:                                     .       .
5961*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
5962*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
5963*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]                  .   .   .
5964*d6b92ffaSHans Petter Selasky  *  b6:                                         .     .
5965*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]                  .   .   .
5966*d6b92ffaSHans Petter Selasky  *                                          O       . .
5967*d6b92ffaSHans Petter Selasky  *                                O         .         O
5968*d6b92ffaSHans Petter Selasky  *                                          .       .
5969*d6b92ffaSHans Petter Selasky  *                                          .     .
5970*d6b92ffaSHans Petter Selasky  *                                          .   .
5971*d6b92ffaSHans Petter Selasky  *                                          . .
5972*d6b92ffaSHans Petter Selasky  *                                          @
5973*d6b92ffaSHans Petter Selasky  */
5974*d6b92ffaSHans Petter Selasky static
handle_case_0x744(struct torus * t,int i,int j,int k)5975*d6b92ffaSHans Petter Selasky bool handle_case_0x744(struct torus *t, int i, int j, int k)
5976*d6b92ffaSHans Petter Selasky {
5977*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
5978*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
5979*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
5980*d6b92ffaSHans Petter Selasky 
5981*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
5982*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
5983*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
5984*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
5985*d6b92ffaSHans Petter Selasky 		return true;
5986*d6b92ffaSHans Petter Selasky 	}
5987*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x744, i, j, k, i, jp1, k);
5988*d6b92ffaSHans Petter Selasky 
5989*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
5990*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
5991*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1],
5992*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
5993*d6b92ffaSHans Petter Selasky 		return true;
5994*d6b92ffaSHans Petter Selasky 	}
5995*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x744, i, j, k, i, jp1, kp1);
5996*d6b92ffaSHans Petter Selasky 	return false;
5997*d6b92ffaSHans Petter Selasky }
5998*d6b92ffaSHans Petter Selasky 
5999*d6b92ffaSHans Petter Selasky /*
6000*d6b92ffaSHans Petter Selasky  * 3D case 0x750:                           O
6001*d6b92ffaSHans Petter Selasky  *                                          . .
6002*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]                .   .
6003*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
6004*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]                .       .
6005*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6006*d6b92ffaSHans Petter Selasky  *  b4:                                     O         .
6007*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]              .   .       .
6008*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .     .
6009*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]          .           .   .
6010*d6b92ffaSHans Petter Selasky  *                                  .       O       . .
6011*d6b92ffaSHans Petter Selasky  *                                O                   O
6012*d6b92ffaSHans Petter Selasky  *                                  .               .
6013*d6b92ffaSHans Petter Selasky  *                                    .           .
6014*d6b92ffaSHans Petter Selasky  *                                      .       .
6015*d6b92ffaSHans Petter Selasky  *                                        .   .
6016*d6b92ffaSHans Petter Selasky  *                                          @
6017*d6b92ffaSHans Petter Selasky  */
6018*d6b92ffaSHans Petter Selasky static
handle_case_0x750(struct torus * t,int i,int j,int k)6019*d6b92ffaSHans Petter Selasky bool handle_case_0x750(struct torus *t, int i, int j, int k)
6020*d6b92ffaSHans Petter Selasky {
6021*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6022*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6023*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6024*d6b92ffaSHans Petter Selasky 
6025*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
6026*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
6027*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
6028*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
6029*d6b92ffaSHans Petter Selasky 		return true;
6030*d6b92ffaSHans Petter Selasky 	}
6031*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x750, i, j, k, i, j, kp1);
6032*d6b92ffaSHans Petter Selasky 
6033*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
6034*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
6035*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
6036*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][kp1]))) {
6037*d6b92ffaSHans Petter Selasky 		return true;
6038*d6b92ffaSHans Petter Selasky 	}
6039*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x750, i, j, k, i, jp1, kp1);
6040*d6b92ffaSHans Petter Selasky 	return false;
6041*d6b92ffaSHans Petter Selasky }
6042*d6b92ffaSHans Petter Selasky 
6043*d6b92ffaSHans Petter Selasky /*
6044*d6b92ffaSHans Petter Selasky  * 3D case 0x788:                           O
6045*d6b92ffaSHans Petter Selasky  *
6046*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
6047*d6b92ffaSHans Petter Selasky  *  b1: t->sw[ip1][j  ][k  ]
6048*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
6049*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
6050*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       . .
6051*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .           .   .
6052*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
6053*d6b92ffaSHans Petter Selasky  *  b7:                           .       .   .       .
6054*d6b92ffaSHans Petter Selasky  *                                .         O         .
6055*d6b92ffaSHans Petter Selasky  *                                O         .         O
6056*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6057*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6058*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6059*d6b92ffaSHans Petter Selasky  *                                        . . .
6060*d6b92ffaSHans Petter Selasky  *                                          @
6061*d6b92ffaSHans Petter Selasky  */
6062*d6b92ffaSHans Petter Selasky static
handle_case_0x788(struct torus * t,int i,int j,int k)6063*d6b92ffaSHans Petter Selasky bool handle_case_0x788(struct torus *t, int i, int j, int k)
6064*d6b92ffaSHans Petter Selasky {
6065*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6066*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6067*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6068*d6b92ffaSHans Petter Selasky 
6069*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
6070*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
6071*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
6072*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
6073*d6b92ffaSHans Petter Selasky 		return true;
6074*d6b92ffaSHans Petter Selasky 	}
6075*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x788, i, j, k, ip1, jp1, k);
6076*d6b92ffaSHans Petter Selasky 
6077*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
6078*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
6079*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
6080*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
6081*d6b92ffaSHans Petter Selasky 		return true;
6082*d6b92ffaSHans Petter Selasky 	}
6083*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x788, i, j, k, ip1, jp1, kp1);
6084*d6b92ffaSHans Petter Selasky 	return false;
6085*d6b92ffaSHans Petter Selasky }
6086*d6b92ffaSHans Petter Selasky 
6087*d6b92ffaSHans Petter Selasky /*
6088*d6b92ffaSHans Petter Selasky  * 3D case 0x7a0:                           O
6089*d6b92ffaSHans Petter Selasky  *
6090*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
6091*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
6092*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
6093*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
6094*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
6095*d6b92ffaSHans Petter Selasky  *  b5:                           .   .   .   .
6096*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
6097*d6b92ffaSHans Petter Selasky  *  b7:                           .   .   .       .
6098*d6b92ffaSHans Petter Selasky  *                                . .       O       .
6099*d6b92ffaSHans Petter Selasky  *                                O         .         O
6100*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6101*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6102*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6103*d6b92ffaSHans Petter Selasky  *                                        . . .
6104*d6b92ffaSHans Petter Selasky  *                                          @
6105*d6b92ffaSHans Petter Selasky  */
6106*d6b92ffaSHans Petter Selasky static
handle_case_0x7a0(struct torus * t,int i,int j,int k)6107*d6b92ffaSHans Petter Selasky bool handle_case_0x7a0(struct torus *t, int i, int j, int k)
6108*d6b92ffaSHans Petter Selasky {
6109*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6110*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6111*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6112*d6b92ffaSHans Petter Selasky 
6113*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
6114*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
6115*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
6116*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
6117*d6b92ffaSHans Petter Selasky 		return true;
6118*d6b92ffaSHans Petter Selasky 	}
6119*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7a0, i, j, k, ip1, j, kp1);
6120*d6b92ffaSHans Petter Selasky 
6121*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
6122*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
6123*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k],
6124*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
6125*d6b92ffaSHans Petter Selasky 		return true;
6126*d6b92ffaSHans Petter Selasky 	}
6127*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7a0, i, j, k, ip1, jp1, kp1);
6128*d6b92ffaSHans Petter Selasky 	return false;
6129*d6b92ffaSHans Petter Selasky }
6130*d6b92ffaSHans Petter Selasky 
6131*d6b92ffaSHans Petter Selasky /*
6132*d6b92ffaSHans Petter Selasky  * 3D case 0x7c0:                           O
6133*d6b92ffaSHans Petter Selasky  *
6134*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
6135*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
6136*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
6137*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
6138*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
6139*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]              .   .   .   .
6140*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .     .
6141*d6b92ffaSHans Petter Selasky  *  b7:                               .       .   .   .
6142*d6b92ffaSHans Petter Selasky  *                                  .       O       . .
6143*d6b92ffaSHans Petter Selasky  *                                O         .         O
6144*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6145*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6146*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6147*d6b92ffaSHans Petter Selasky  *                                        . . .
6148*d6b92ffaSHans Petter Selasky  *                                          @
6149*d6b92ffaSHans Petter Selasky  */
6150*d6b92ffaSHans Petter Selasky static
handle_case_0x7c0(struct torus * t,int i,int j,int k)6151*d6b92ffaSHans Petter Selasky bool handle_case_0x7c0(struct torus *t, int i, int j, int k)
6152*d6b92ffaSHans Petter Selasky {
6153*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6154*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6155*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6156*d6b92ffaSHans Petter Selasky 
6157*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
6158*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][kp1],
6159*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
6160*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][k]))) {
6161*d6b92ffaSHans Petter Selasky 		return true;
6162*d6b92ffaSHans Petter Selasky 	}
6163*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7c0, i, j, k, i, jp1, kp1);
6164*d6b92ffaSHans Petter Selasky 
6165*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
6166*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][kp1],
6167*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
6168*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k]))) {
6169*d6b92ffaSHans Petter Selasky 		return true;
6170*d6b92ffaSHans Petter Selasky 	}
6171*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x7c0, i, j, k, ip1, jp1, kp1);
6172*d6b92ffaSHans Petter Selasky 	return false;
6173*d6b92ffaSHans Petter Selasky }
6174*d6b92ffaSHans Petter Selasky 
6175*d6b92ffaSHans Petter Selasky /*
6176*d6b92ffaSHans Petter Selasky  * Handle the cases where a single corner is missing.
6177*d6b92ffaSHans Petter Selasky  */
6178*d6b92ffaSHans Petter Selasky 
6179*d6b92ffaSHans Petter Selasky /*
6180*d6b92ffaSHans Petter Selasky  * 3D case 0x701:                           O
6181*d6b92ffaSHans Petter Selasky  *                                        . . .
6182*d6b92ffaSHans Petter Selasky  *  b0:                                     .   .   .
6183*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
6184*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
6185*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6186*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       . .
6187*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .   .   .   .   .
6188*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
6189*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .   .   .   .
6190*d6b92ffaSHans Petter Selasky  *                                . .       O       . .
6191*d6b92ffaSHans Petter Selasky  *                                O                   O
6192*d6b92ffaSHans Petter Selasky  *
6193*d6b92ffaSHans Petter Selasky  *
6194*d6b92ffaSHans Petter Selasky  *
6195*d6b92ffaSHans Petter Selasky  *
6196*d6b92ffaSHans Petter Selasky  *                                          @
6197*d6b92ffaSHans Petter Selasky  */
6198*d6b92ffaSHans Petter Selasky static
handle_case_0x701(struct torus * t,int i,int j,int k)6199*d6b92ffaSHans Petter Selasky bool handle_case_0x701(struct torus *t, int i, int j, int k)
6200*d6b92ffaSHans Petter Selasky {
6201*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6202*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6203*d6b92ffaSHans Petter Selasky 
6204*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, k,
6205*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
6206*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][jp1][k],
6207*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
6208*d6b92ffaSHans Petter Selasky 		return true;
6209*d6b92ffaSHans Petter Selasky 	}
6210*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x701, i, j, k, i, j, k);
6211*d6b92ffaSHans Petter Selasky 	return false;
6212*d6b92ffaSHans Petter Selasky }
6213*d6b92ffaSHans Petter Selasky 
6214*d6b92ffaSHans Petter Selasky /*
6215*d6b92ffaSHans Petter Selasky  * 3D case 0x702:                           O
6216*d6b92ffaSHans Petter Selasky  *                                        . . .
6217*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .   .
6218*d6b92ffaSHans Petter Selasky  *  b1:                               .     .     .
6219*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
6220*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6221*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       .
6222*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .   .       .
6223*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
6224*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .   .
6225*d6b92ffaSHans Petter Selasky  *                                . .       O
6226*d6b92ffaSHans Petter Selasky  *                                O         .         O
6227*d6b92ffaSHans Petter Selasky  *                                  .       .
6228*d6b92ffaSHans Petter Selasky  *                                    .     .
6229*d6b92ffaSHans Petter Selasky  *                                      .   .
6230*d6b92ffaSHans Petter Selasky  *                                        . .
6231*d6b92ffaSHans Petter Selasky  *                                          @
6232*d6b92ffaSHans Petter Selasky  */
6233*d6b92ffaSHans Petter Selasky static
handle_case_0x702(struct torus * t,int i,int j,int k)6234*d6b92ffaSHans Petter Selasky bool handle_case_0x702(struct torus *t, int i, int j, int k)
6235*d6b92ffaSHans Petter Selasky {
6236*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6237*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6238*d6b92ffaSHans Petter Selasky 
6239*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, k,
6240*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
6241*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
6242*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
6243*d6b92ffaSHans Petter Selasky 		return true;
6244*d6b92ffaSHans Petter Selasky 	}
6245*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x702, i, j, k, ip1, j, k);
6246*d6b92ffaSHans Petter Selasky 	return false;
6247*d6b92ffaSHans Petter Selasky }
6248*d6b92ffaSHans Petter Selasky 
6249*d6b92ffaSHans Petter Selasky /*
6250*d6b92ffaSHans Petter Selasky  * 3D case 0x704:                           O
6251*d6b92ffaSHans Petter Selasky  *                                        . . .
6252*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .   .
6253*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
6254*d6b92ffaSHans Petter Selasky  *  b2:                             .       .       .
6255*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6256*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]        .       O       . .
6257*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]          .       .   .   .
6258*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]            .       .     .
6259*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]              .   .   .   .
6260*d6b92ffaSHans Petter Selasky  *                                          O       . .
6261*d6b92ffaSHans Petter Selasky  *                                O         .         O
6262*d6b92ffaSHans Petter Selasky  *                                          .       .
6263*d6b92ffaSHans Petter Selasky  *                                          .     .
6264*d6b92ffaSHans Petter Selasky  *                                          .   .
6265*d6b92ffaSHans Petter Selasky  *                                          . .
6266*d6b92ffaSHans Petter Selasky  *                                          @
6267*d6b92ffaSHans Petter Selasky  */
6268*d6b92ffaSHans Petter Selasky static
handle_case_0x704(struct torus * t,int i,int j,int k)6269*d6b92ffaSHans Petter Selasky bool handle_case_0x704(struct torus *t, int i, int j, int k)
6270*d6b92ffaSHans Petter Selasky {
6271*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6272*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6273*d6b92ffaSHans Petter Selasky 
6274*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, k,
6275*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
6276*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
6277*d6b92ffaSHans Petter Selasky 					      t->sw[i][jp1][kp1]))) {
6278*d6b92ffaSHans Petter Selasky 		return true;
6279*d6b92ffaSHans Petter Selasky 	}
6280*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x704, i, j, k, i, jp1, k);
6281*d6b92ffaSHans Petter Selasky 	return false;
6282*d6b92ffaSHans Petter Selasky }
6283*d6b92ffaSHans Petter Selasky 
6284*d6b92ffaSHans Petter Selasky /*
6285*d6b92ffaSHans Petter Selasky  * 3D case 0x708:                           O
6286*d6b92ffaSHans Petter Selasky  *                                        .   .
6287*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .       .
6288*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .           .
6289*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .               .
6290*d6b92ffaSHans Petter Selasky  *  b3:                           O                   O
6291*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       . .
6292*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .           .   .
6293*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
6294*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .       .   .       .
6295*d6b92ffaSHans Petter Selasky  *                                .         O         .
6296*d6b92ffaSHans Petter Selasky  *                                O         .         O
6297*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6298*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6299*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6300*d6b92ffaSHans Petter Selasky  *                                        . . .
6301*d6b92ffaSHans Petter Selasky  *                                          @
6302*d6b92ffaSHans Petter Selasky  */
6303*d6b92ffaSHans Petter Selasky static
handle_case_0x708(struct torus * t,int i,int j,int k)6304*d6b92ffaSHans Petter Selasky bool handle_case_0x708(struct torus *t, int i, int j, int k)
6305*d6b92ffaSHans Petter Selasky {
6306*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6307*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6308*d6b92ffaSHans Petter Selasky 
6309*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, k,
6310*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
6311*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
6312*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k]))) {
6313*d6b92ffaSHans Petter Selasky 		return true;
6314*d6b92ffaSHans Petter Selasky 	}
6315*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x708, i, j, k, ip1, jp1, k);
6316*d6b92ffaSHans Petter Selasky 	return false;
6317*d6b92ffaSHans Petter Selasky }
6318*d6b92ffaSHans Petter Selasky 
6319*d6b92ffaSHans Petter Selasky /*
6320*d6b92ffaSHans Petter Selasky  * 3D case 0x710:                           O
6321*d6b92ffaSHans Petter Selasky  *                                        . . .
6322*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .   .
6323*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .     .
6324*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .       .
6325*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6326*d6b92ffaSHans Petter Selasky  *  b4:                           .         O         .
6327*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .       .   .       .
6328*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
6329*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .           .   .
6330*d6b92ffaSHans Petter Selasky  *                                . .       O       . .
6331*d6b92ffaSHans Petter Selasky  *                                O                   O
6332*d6b92ffaSHans Petter Selasky  *                                  .               .
6333*d6b92ffaSHans Petter Selasky  *                                    .           .
6334*d6b92ffaSHans Petter Selasky  *                                      .       .
6335*d6b92ffaSHans Petter Selasky  *                                        .   .
6336*d6b92ffaSHans Petter Selasky  *                                          @
6337*d6b92ffaSHans Petter Selasky  */
6338*d6b92ffaSHans Petter Selasky static
handle_case_0x710(struct torus * t,int i,int j,int k)6339*d6b92ffaSHans Petter Selasky bool handle_case_0x710(struct torus *t, int i, int j, int k)
6340*d6b92ffaSHans Petter Selasky {
6341*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6342*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6343*d6b92ffaSHans Petter Selasky 
6344*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, j, kp1,
6345*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][j][k],
6346*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][k],
6347*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
6348*d6b92ffaSHans Petter Selasky 		return true;
6349*d6b92ffaSHans Petter Selasky 	}
6350*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x710, i, j, k, i, j, kp1);
6351*d6b92ffaSHans Petter Selasky 	return false;
6352*d6b92ffaSHans Petter Selasky }
6353*d6b92ffaSHans Petter Selasky 
6354*d6b92ffaSHans Petter Selasky /*
6355*d6b92ffaSHans Petter Selasky  * 3D case 0x720:                           O
6356*d6b92ffaSHans Petter Selasky  *                                        . .
6357*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]            .   .
6358*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]          .     .
6359*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]        .       .
6360*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6361*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O
6362*d6b92ffaSHans Petter Selasky  *  b5:                           .   .   .   .
6363*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .
6364*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]      .   .   .       .
6365*d6b92ffaSHans Petter Selasky  *                                . .       O       .
6366*d6b92ffaSHans Petter Selasky  *                                O         .         O
6367*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6368*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6369*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6370*d6b92ffaSHans Petter Selasky  *                                        . . .
6371*d6b92ffaSHans Petter Selasky  *                                          @
6372*d6b92ffaSHans Petter Selasky  */
6373*d6b92ffaSHans Petter Selasky static
handle_case_0x720(struct torus * t,int i,int j,int k)6374*d6b92ffaSHans Petter Selasky bool handle_case_0x720(struct torus *t, int i, int j, int k)
6375*d6b92ffaSHans Petter Selasky {
6376*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6377*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6378*d6b92ffaSHans Petter Selasky 
6379*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, j, kp1,
6380*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[ip1][j][k],
6381*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
6382*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
6383*d6b92ffaSHans Petter Selasky 		return true;
6384*d6b92ffaSHans Petter Selasky 	}
6385*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x720, i, j, k, ip1, j, kp1);
6386*d6b92ffaSHans Petter Selasky 	return false;
6387*d6b92ffaSHans Petter Selasky }
6388*d6b92ffaSHans Petter Selasky 
6389*d6b92ffaSHans Petter Selasky /*
6390*d6b92ffaSHans Petter Selasky  * 3D case 0x740:                           O
6391*d6b92ffaSHans Petter Selasky  *                                          . .
6392*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]                .   .
6393*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]                .     .
6394*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]                .       .
6395*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O         .         O
6396*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]                O       . .
6397*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]              .   .   .   .
6398*d6b92ffaSHans Petter Selasky  *  b6:                                 .       .     .
6399*d6b92ffaSHans Petter Selasky  *  b7: t->sw[i+1][j+1][k+1]          .       .   .   .
6400*d6b92ffaSHans Petter Selasky  *                                  .       O       . .
6401*d6b92ffaSHans Petter Selasky  *                                O         .         O
6402*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6403*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6404*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6405*d6b92ffaSHans Petter Selasky  *                                        . . .
6406*d6b92ffaSHans Petter Selasky  *                                          @
6407*d6b92ffaSHans Petter Selasky  */
6408*d6b92ffaSHans Petter Selasky static
handle_case_0x740(struct torus * t,int i,int j,int k)6409*d6b92ffaSHans Petter Selasky bool handle_case_0x740(struct torus *t, int i, int j, int k)
6410*d6b92ffaSHans Petter Selasky {
6411*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6412*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6413*d6b92ffaSHans Petter Selasky 
6414*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, i, jp1, kp1,
6415*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][k],
6416*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][k],
6417*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1]))) {
6418*d6b92ffaSHans Petter Selasky 		return true;
6419*d6b92ffaSHans Petter Selasky 	}
6420*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x740, i, j, k, i, jp1, kp1);
6421*d6b92ffaSHans Petter Selasky 	return false;
6422*d6b92ffaSHans Petter Selasky }
6423*d6b92ffaSHans Petter Selasky 
6424*d6b92ffaSHans Petter Selasky /*
6425*d6b92ffaSHans Petter Selasky  * 3D case 0x780:                           O
6426*d6b92ffaSHans Petter Selasky  *
6427*d6b92ffaSHans Petter Selasky  *  b0: t->sw[i  ][j  ][k  ]
6428*d6b92ffaSHans Petter Selasky  *  b1: t->sw[i+1][j  ][k  ]
6429*d6b92ffaSHans Petter Selasky  *  b2: t->sw[i  ][j+1][k  ]
6430*d6b92ffaSHans Petter Selasky  *  b3: t->sw[i+1][j+1][k  ]      O                   O
6431*d6b92ffaSHans Petter Selasky  *  b4: t->sw[i  ][j  ][k+1]      . .       O       . .
6432*d6b92ffaSHans Petter Selasky  *  b5: t->sw[i+1][j  ][k+1]      .   .   .   .   .   .
6433*d6b92ffaSHans Petter Selasky  *  b6: t->sw[i  ][j+1][k+1]      .     .       .     .
6434*d6b92ffaSHans Petter Selasky  *  b7:                           .   .   .   .   .   .
6435*d6b92ffaSHans Petter Selasky  *                                . .       O       . .
6436*d6b92ffaSHans Petter Selasky  *                                O         .         O
6437*d6b92ffaSHans Petter Selasky  *                                  .       .       .
6438*d6b92ffaSHans Petter Selasky  *                                    .     .     .
6439*d6b92ffaSHans Petter Selasky  *                                      .   .   .
6440*d6b92ffaSHans Petter Selasky  *                                        . . .
6441*d6b92ffaSHans Petter Selasky  *                                          @
6442*d6b92ffaSHans Petter Selasky  */
6443*d6b92ffaSHans Petter Selasky static
handle_case_0x780(struct torus * t,int i,int j,int k)6444*d6b92ffaSHans Petter Selasky bool handle_case_0x780(struct torus *t, int i, int j, int k)
6445*d6b92ffaSHans Petter Selasky {
6446*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6447*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6448*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6449*d6b92ffaSHans Petter Selasky 
6450*d6b92ffaSHans Petter Selasky 	if (install_tswitch(t, ip1, jp1, kp1,
6451*d6b92ffaSHans Petter Selasky 			    tfind_face_corner(t->sw[i][jp1][kp1],
6452*d6b92ffaSHans Petter Selasky 					      t->sw[i][j][kp1],
6453*d6b92ffaSHans Petter Selasky 					      t->sw[ip1][j][kp1]))) {
6454*d6b92ffaSHans Petter Selasky 		return true;
6455*d6b92ffaSHans Petter Selasky 	}
6456*d6b92ffaSHans Petter Selasky 	log_no_crnr(t, 0x780, i, j, k, ip1, jp1, kp1);
6457*d6b92ffaSHans Petter Selasky 	return false;
6458*d6b92ffaSHans Petter Selasky }
6459*d6b92ffaSHans Petter Selasky 
6460*d6b92ffaSHans Petter Selasky /*
6461*d6b92ffaSHans Petter Selasky  * Make sure links between all known torus/mesh switches are installed.
6462*d6b92ffaSHans Petter Selasky  *
6463*d6b92ffaSHans Petter Selasky  * We don't have to worry about links that wrap on a mesh coordinate, as
6464*d6b92ffaSHans Petter Selasky  * there shouldn't be any; if there are it indicates an input error.
6465*d6b92ffaSHans Petter Selasky  */
6466*d6b92ffaSHans Petter Selasky static
check_tlinks(struct torus * t,int i,int j,int k)6467*d6b92ffaSHans Petter Selasky void check_tlinks(struct torus *t, int i, int j, int k)
6468*d6b92ffaSHans Petter Selasky {
6469*d6b92ffaSHans Petter Selasky 	struct t_switch ****sw = t->sw;
6470*d6b92ffaSHans Petter Selasky 	int ip1 = canonicalize(i + 1, t->x_sz);
6471*d6b92ffaSHans Petter Selasky 	int jp1 = canonicalize(j + 1, t->y_sz);
6472*d6b92ffaSHans Petter Selasky 	int kp1 = canonicalize(k + 1, t->z_sz);
6473*d6b92ffaSHans Petter Selasky 
6474*d6b92ffaSHans Petter Selasky 	/*
6475*d6b92ffaSHans Petter Selasky 	 * Don't waste time/code checking return status of link_tswitches()
6476*d6b92ffaSHans Petter Selasky 	 * here.  It is unlikely to fail, and the result of any failure here
6477*d6b92ffaSHans Petter Selasky 	 * will be caught elsewhere anyway.
6478*d6b92ffaSHans Petter Selasky 	 */
6479*d6b92ffaSHans Petter Selasky 	if (sw[i][j][k] && sw[ip1][j][k])
6480*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 0, sw[i][j][k], sw[ip1][j][k]);
6481*d6b92ffaSHans Petter Selasky 
6482*d6b92ffaSHans Petter Selasky 	if (sw[i][jp1][k] && sw[ip1][jp1][k])
6483*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 0, sw[i][jp1][k], sw[ip1][jp1][k]);
6484*d6b92ffaSHans Petter Selasky 
6485*d6b92ffaSHans Petter Selasky 	if (sw[i][j][kp1] && sw[ip1][j][kp1])
6486*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 0, sw[i][j][kp1], sw[ip1][j][kp1]);
6487*d6b92ffaSHans Petter Selasky 
6488*d6b92ffaSHans Petter Selasky 	if (sw[i][jp1][kp1] && sw[ip1][jp1][kp1])
6489*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 0, sw[i][jp1][kp1], sw[ip1][jp1][kp1]);
6490*d6b92ffaSHans Petter Selasky 
6491*d6b92ffaSHans Petter Selasky 
6492*d6b92ffaSHans Petter Selasky 	if (sw[i][j][k] && sw[i][jp1][k])
6493*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 1, sw[i][j][k], sw[i][jp1][k]);
6494*d6b92ffaSHans Petter Selasky 
6495*d6b92ffaSHans Petter Selasky 	if (sw[ip1][j][k] && sw[ip1][jp1][k])
6496*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 1, sw[ip1][j][k], sw[ip1][jp1][k]);
6497*d6b92ffaSHans Petter Selasky 
6498*d6b92ffaSHans Petter Selasky 	if (sw[i][j][kp1] && sw[i][jp1][kp1])
6499*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 1, sw[i][j][kp1], sw[i][jp1][kp1]);
6500*d6b92ffaSHans Petter Selasky 
6501*d6b92ffaSHans Petter Selasky 	if (sw[ip1][j][kp1] && sw[ip1][jp1][kp1])
6502*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 1, sw[ip1][j][kp1], sw[ip1][jp1][kp1]);
6503*d6b92ffaSHans Petter Selasky 
6504*d6b92ffaSHans Petter Selasky 
6505*d6b92ffaSHans Petter Selasky 	if (sw[i][j][k] && sw[i][j][kp1])
6506*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 2, sw[i][j][k], sw[i][j][kp1]);
6507*d6b92ffaSHans Petter Selasky 
6508*d6b92ffaSHans Petter Selasky 	if (sw[ip1][j][k] && sw[ip1][j][kp1])
6509*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 2, sw[ip1][j][k], sw[ip1][j][kp1]);
6510*d6b92ffaSHans Petter Selasky 
6511*d6b92ffaSHans Petter Selasky 	if (sw[i][jp1][k] && sw[i][jp1][kp1])
6512*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 2, sw[i][jp1][k], sw[i][jp1][kp1]);
6513*d6b92ffaSHans Petter Selasky 
6514*d6b92ffaSHans Petter Selasky 	if (sw[ip1][jp1][k] && sw[ip1][jp1][kp1])
6515*d6b92ffaSHans Petter Selasky 		link_tswitches(t, 2, sw[ip1][jp1][k], sw[ip1][jp1][kp1]);
6516*d6b92ffaSHans Petter Selasky }
6517*d6b92ffaSHans Petter Selasky 
6518*d6b92ffaSHans Petter Selasky static
locate_sw(struct torus * t,int i,int j,int k)6519*d6b92ffaSHans Petter Selasky void locate_sw(struct torus *t, int i, int j, int k)
6520*d6b92ffaSHans Petter Selasky {
6521*d6b92ffaSHans Petter Selasky 	unsigned fp;
6522*d6b92ffaSHans Petter Selasky 	bool success;
6523*d6b92ffaSHans Petter Selasky 
6524*d6b92ffaSHans Petter Selasky 	i = canonicalize(i, t->x_sz);
6525*d6b92ffaSHans Petter Selasky 	j = canonicalize(j, t->y_sz);
6526*d6b92ffaSHans Petter Selasky 	k = canonicalize(k, t->z_sz);
6527*d6b92ffaSHans Petter Selasky 
6528*d6b92ffaSHans Petter Selasky 	/*
6529*d6b92ffaSHans Petter Selasky 	 * By definition, if a coordinate direction is meshed, we don't
6530*d6b92ffaSHans Petter Selasky 	 * allow it to wrap to zero.
6531*d6b92ffaSHans Petter Selasky 	 */
6532*d6b92ffaSHans Petter Selasky 	if (t->flags & X_MESH) {
6533*d6b92ffaSHans Petter Selasky 		int ip1 = canonicalize(i + 1, t->x_sz);
6534*d6b92ffaSHans Petter Selasky 		if (ip1 < i)
6535*d6b92ffaSHans Petter Selasky 			goto out;
6536*d6b92ffaSHans Petter Selasky 	}
6537*d6b92ffaSHans Petter Selasky 	if (t->flags & Y_MESH) {
6538*d6b92ffaSHans Petter Selasky 		int jp1 = canonicalize(j + 1, t->y_sz);
6539*d6b92ffaSHans Petter Selasky 		if (jp1 < j)
6540*d6b92ffaSHans Petter Selasky 			goto out;
6541*d6b92ffaSHans Petter Selasky 	}
6542*d6b92ffaSHans Petter Selasky 	if (t->flags & Z_MESH) {
6543*d6b92ffaSHans Petter Selasky 		int kp1 = canonicalize(k + 1, t->z_sz);
6544*d6b92ffaSHans Petter Selasky 		if (kp1 < k)
6545*d6b92ffaSHans Petter Selasky 			goto out;
6546*d6b92ffaSHans Petter Selasky 	}
6547*d6b92ffaSHans Petter Selasky 	/*
6548*d6b92ffaSHans Petter Selasky 	 * There are various reasons that the links are not installed between
6549*d6b92ffaSHans Petter Selasky 	 * known torus switches.  These include cases where the search for
6550*d6b92ffaSHans Petter Selasky 	 * new switches only partially succeeds due to missing switches, and
6551*d6b92ffaSHans Petter Selasky 	 * cases where we haven't processed this position yet, but processing
6552*d6b92ffaSHans Petter Selasky 	 * of multiple independent neighbor positions has installed switches
6553*d6b92ffaSHans Petter Selasky 	 * into corners of our case.
6554*d6b92ffaSHans Petter Selasky 	 *
6555*d6b92ffaSHans Petter Selasky 	 * In any event, the topology assumptions made in handling the
6556*d6b92ffaSHans Petter Selasky 	 * fingerprint for this position require that all links be installed
6557*d6b92ffaSHans Petter Selasky 	 * between installed switches for this position.
6558*d6b92ffaSHans Petter Selasky 	 */
6559*d6b92ffaSHans Petter Selasky again:
6560*d6b92ffaSHans Petter Selasky 	check_tlinks(t, i, j, k);
6561*d6b92ffaSHans Petter Selasky 	fp = fingerprint(t, i, j, k);
6562*d6b92ffaSHans Petter Selasky 
6563*d6b92ffaSHans Petter Selasky 	switch (fp) {
6564*d6b92ffaSHans Petter Selasky 	/*
6565*d6b92ffaSHans Petter Selasky 	 * When all switches are present, we are done.  Otherwise, one of
6566*d6b92ffaSHans Petter Selasky 	 * the cases below will be unsuccessful, and we'll be done also.
6567*d6b92ffaSHans Petter Selasky 	 *
6568*d6b92ffaSHans Petter Selasky 	 * Note that check_tlinks() above will ensure all links that are
6569*d6b92ffaSHans Petter Selasky 	 * present are connected, in the event that all our switches are
6570*d6b92ffaSHans Petter Selasky 	 * present due to successful case handling in the surrounding
6571*d6b92ffaSHans Petter Selasky 	 * torus/mesh.
6572*d6b92ffaSHans Petter Selasky 	 */
6573*d6b92ffaSHans Petter Selasky 	case 0x300:
6574*d6b92ffaSHans Petter Selasky 	case 0x500:
6575*d6b92ffaSHans Petter Selasky 	case 0x600:
6576*d6b92ffaSHans Petter Selasky 	case 0x700:
6577*d6b92ffaSHans Petter Selasky 		goto out;
6578*d6b92ffaSHans Petter Selasky 	/*
6579*d6b92ffaSHans Petter Selasky 	 * Ignore the 2D cases where there isn't enough information to uniquely
6580*d6b92ffaSHans Petter Selasky 	 * locate/place a switch into the cube.
6581*d6b92ffaSHans Petter Selasky 	 */
6582*d6b92ffaSHans Petter Selasky 	case 0x30f: 	/* 0 corners available */
6583*d6b92ffaSHans Petter Selasky 	case 0x533: 	/* 0 corners available */
6584*d6b92ffaSHans Petter Selasky 	case 0x655: 	/* 0 corners available */
6585*d6b92ffaSHans Petter Selasky 	case 0x30e:	/* 1 corner available */
6586*d6b92ffaSHans Petter Selasky 	case 0x532:	/* 1 corner available */
6587*d6b92ffaSHans Petter Selasky 	case 0x654:	/* 1 corner available */
6588*d6b92ffaSHans Petter Selasky 	case 0x30d:	/* 1 corner available */
6589*d6b92ffaSHans Petter Selasky 	case 0x531:	/* 1 corner available */
6590*d6b92ffaSHans Petter Selasky 	case 0x651:	/* 1 corner available */
6591*d6b92ffaSHans Petter Selasky 	case 0x30b:	/* 1 corner available */
6592*d6b92ffaSHans Petter Selasky 	case 0x523:	/* 1 corner available */
6593*d6b92ffaSHans Petter Selasky 	case 0x645:	/* 1 corner available */
6594*d6b92ffaSHans Petter Selasky 	case 0x307:	/* 1 corner available */
6595*d6b92ffaSHans Petter Selasky 	case 0x513:	/* 1 corner available */
6596*d6b92ffaSHans Petter Selasky 	case 0x615:	/* 1 corner available */
6597*d6b92ffaSHans Petter Selasky 		goto out;
6598*d6b92ffaSHans Petter Selasky 	/*
6599*d6b92ffaSHans Petter Selasky 	 * Handle the 2D cases with a single existing edge.
6600*d6b92ffaSHans Petter Selasky 	 *
6601*d6b92ffaSHans Petter Selasky 	 */
6602*d6b92ffaSHans Petter Selasky 	case 0x30c:
6603*d6b92ffaSHans Petter Selasky 		success = handle_case_0x30c(t, i, j, k);
6604*d6b92ffaSHans Petter Selasky 		break;
6605*d6b92ffaSHans Petter Selasky 	case 0x303:
6606*d6b92ffaSHans Petter Selasky 		success = handle_case_0x303(t, i, j, k);
6607*d6b92ffaSHans Petter Selasky 		break;
6608*d6b92ffaSHans Petter Selasky 	case 0x305:
6609*d6b92ffaSHans Petter Selasky 		success = handle_case_0x305(t, i, j, k);
6610*d6b92ffaSHans Petter Selasky 		break;
6611*d6b92ffaSHans Petter Selasky 	case 0x30a:
6612*d6b92ffaSHans Petter Selasky 		success = handle_case_0x30a(t, i, j, k);
6613*d6b92ffaSHans Petter Selasky 		break;
6614*d6b92ffaSHans Petter Selasky 	case 0x503:
6615*d6b92ffaSHans Petter Selasky 		success = handle_case_0x503(t, i, j, k);
6616*d6b92ffaSHans Petter Selasky 		break;
6617*d6b92ffaSHans Petter Selasky 	case 0x511:
6618*d6b92ffaSHans Petter Selasky 		success = handle_case_0x511(t, i, j, k);
6619*d6b92ffaSHans Petter Selasky 		break;
6620*d6b92ffaSHans Petter Selasky 	case 0x522:
6621*d6b92ffaSHans Petter Selasky 		success = handle_case_0x522(t, i, j, k);
6622*d6b92ffaSHans Petter Selasky 		break;
6623*d6b92ffaSHans Petter Selasky 	case 0x530:
6624*d6b92ffaSHans Petter Selasky 		success = handle_case_0x530(t, i, j, k);
6625*d6b92ffaSHans Petter Selasky 		break;
6626*d6b92ffaSHans Petter Selasky 	case 0x605:
6627*d6b92ffaSHans Petter Selasky 		success = handle_case_0x605(t, i, j, k);
6628*d6b92ffaSHans Petter Selasky 		break;
6629*d6b92ffaSHans Petter Selasky 	case 0x611:
6630*d6b92ffaSHans Petter Selasky 		success = handle_case_0x611(t, i, j, k);
6631*d6b92ffaSHans Petter Selasky 		break;
6632*d6b92ffaSHans Petter Selasky 	case 0x644:
6633*d6b92ffaSHans Petter Selasky 		success = handle_case_0x644(t, i, j, k);
6634*d6b92ffaSHans Petter Selasky 		break;
6635*d6b92ffaSHans Petter Selasky 	case 0x650:
6636*d6b92ffaSHans Petter Selasky 		success = handle_case_0x650(t, i, j, k);
6637*d6b92ffaSHans Petter Selasky 		break;
6638*d6b92ffaSHans Petter Selasky 	/*
6639*d6b92ffaSHans Petter Selasky 	 * Handle the 2D cases where two existing edges meet at a corner.
6640*d6b92ffaSHans Petter Selasky 	 */
6641*d6b92ffaSHans Petter Selasky 	case 0x301:
6642*d6b92ffaSHans Petter Selasky 		success = handle_case_0x301(t, i, j, k);
6643*d6b92ffaSHans Petter Selasky 		break;
6644*d6b92ffaSHans Petter Selasky 	case 0x302:
6645*d6b92ffaSHans Petter Selasky 		success = handle_case_0x302(t, i, j, k);
6646*d6b92ffaSHans Petter Selasky 		break;
6647*d6b92ffaSHans Petter Selasky 	case 0x304:
6648*d6b92ffaSHans Petter Selasky 		success = handle_case_0x304(t, i, j, k);
6649*d6b92ffaSHans Petter Selasky 		break;
6650*d6b92ffaSHans Petter Selasky 	case 0x308:
6651*d6b92ffaSHans Petter Selasky 		success = handle_case_0x308(t, i, j, k);
6652*d6b92ffaSHans Petter Selasky 		break;
6653*d6b92ffaSHans Petter Selasky 	case 0x501:
6654*d6b92ffaSHans Petter Selasky 		success = handle_case_0x501(t, i, j, k);
6655*d6b92ffaSHans Petter Selasky 		break;
6656*d6b92ffaSHans Petter Selasky 	case 0x502:
6657*d6b92ffaSHans Petter Selasky 		success = handle_case_0x502(t, i, j, k);
6658*d6b92ffaSHans Petter Selasky 		break;
6659*d6b92ffaSHans Petter Selasky 	case 0x520:
6660*d6b92ffaSHans Petter Selasky 		success = handle_case_0x520(t, i, j, k);
6661*d6b92ffaSHans Petter Selasky 		break;
6662*d6b92ffaSHans Petter Selasky 	case 0x510:
6663*d6b92ffaSHans Petter Selasky 		success = handle_case_0x510(t, i, j, k);
6664*d6b92ffaSHans Petter Selasky 		break;
6665*d6b92ffaSHans Petter Selasky 	case 0x601:
6666*d6b92ffaSHans Petter Selasky 		success = handle_case_0x601(t, i, j, k);
6667*d6b92ffaSHans Petter Selasky 		break;
6668*d6b92ffaSHans Petter Selasky 	case 0x604:
6669*d6b92ffaSHans Petter Selasky 		success = handle_case_0x604(t, i, j, k);
6670*d6b92ffaSHans Petter Selasky 		break;
6671*d6b92ffaSHans Petter Selasky 	case 0x610:
6672*d6b92ffaSHans Petter Selasky 		success = handle_case_0x610(t, i, j, k);
6673*d6b92ffaSHans Petter Selasky 		break;
6674*d6b92ffaSHans Petter Selasky 	case 0x640:
6675*d6b92ffaSHans Petter Selasky 		success = handle_case_0x640(t, i, j, k);
6676*d6b92ffaSHans Petter Selasky 		break;
6677*d6b92ffaSHans Petter Selasky 	/*
6678*d6b92ffaSHans Petter Selasky 	 * Ignore the 3D cases where there isn't enough information to uniquely
6679*d6b92ffaSHans Petter Selasky 	 * locate/place a switch into the cube.
6680*d6b92ffaSHans Petter Selasky 	 */
6681*d6b92ffaSHans Petter Selasky 	case 0x7ff:	/* 0 corners available */
6682*d6b92ffaSHans Petter Selasky 	case 0x7fe:	/* 1 corner available */
6683*d6b92ffaSHans Petter Selasky 	case 0x7fd:	/* 1 corner available */
6684*d6b92ffaSHans Petter Selasky 	case 0x7fb:	/* 1 corner available */
6685*d6b92ffaSHans Petter Selasky 	case 0x7f7:	/* 1 corner available */
6686*d6b92ffaSHans Petter Selasky 	case 0x7ef:	/* 1 corner available */
6687*d6b92ffaSHans Petter Selasky 	case 0x7df:	/* 1 corner available */
6688*d6b92ffaSHans Petter Selasky 	case 0x7bf:	/* 1 corner available */
6689*d6b92ffaSHans Petter Selasky 	case 0x77f:	/* 1 corner available */
6690*d6b92ffaSHans Petter Selasky 	case 0x7fc:	/* 2 adj corners available */
6691*d6b92ffaSHans Petter Selasky 	case 0x7fa:	/* 2 adj corners available */
6692*d6b92ffaSHans Petter Selasky 	case 0x7f5:	/* 2 adj corners available */
6693*d6b92ffaSHans Petter Selasky 	case 0x7f3:	/* 2 adj corners available */
6694*d6b92ffaSHans Petter Selasky 	case 0x7cf:	/* 2 adj corners available */
6695*d6b92ffaSHans Petter Selasky 	case 0x7af:	/* 2 adj corners available */
6696*d6b92ffaSHans Petter Selasky 	case 0x75f:	/* 2 adj corners available */
6697*d6b92ffaSHans Petter Selasky 	case 0x73f:	/* 2 adj corners available */
6698*d6b92ffaSHans Petter Selasky 	case 0x7ee:	/* 2 adj corners available */
6699*d6b92ffaSHans Petter Selasky 	case 0x7dd:	/* 2 adj corners available */
6700*d6b92ffaSHans Petter Selasky 	case 0x7bb:	/* 2 adj corners available */
6701*d6b92ffaSHans Petter Selasky 	case 0x777:	/* 2 adj corners available */
6702*d6b92ffaSHans Petter Selasky 		goto out;
6703*d6b92ffaSHans Petter Selasky 	/*
6704*d6b92ffaSHans Petter Selasky 	 * Handle the 3D cases where two existing edges meet at a corner.
6705*d6b92ffaSHans Petter Selasky 	 *
6706*d6b92ffaSHans Petter Selasky 	 */
6707*d6b92ffaSHans Petter Selasky 	case 0x71f:
6708*d6b92ffaSHans Petter Selasky 		success = handle_case_0x71f(t, i, j, k);
6709*d6b92ffaSHans Petter Selasky 		break;
6710*d6b92ffaSHans Petter Selasky 	case 0x72f:
6711*d6b92ffaSHans Petter Selasky 		success = handle_case_0x72f(t, i, j, k);
6712*d6b92ffaSHans Petter Selasky 		break;
6713*d6b92ffaSHans Petter Selasky 	case 0x737:
6714*d6b92ffaSHans Petter Selasky 		success = handle_case_0x737(t, i, j, k);
6715*d6b92ffaSHans Petter Selasky 		break;
6716*d6b92ffaSHans Petter Selasky 	case 0x73b:
6717*d6b92ffaSHans Petter Selasky 		success = handle_case_0x73b(t, i, j, k);
6718*d6b92ffaSHans Petter Selasky 		break;
6719*d6b92ffaSHans Petter Selasky 	case 0x74f:
6720*d6b92ffaSHans Petter Selasky 		success = handle_case_0x74f(t, i, j, k);
6721*d6b92ffaSHans Petter Selasky 		break;
6722*d6b92ffaSHans Petter Selasky 	case 0x757:
6723*d6b92ffaSHans Petter Selasky 		success = handle_case_0x757(t, i, j, k);
6724*d6b92ffaSHans Petter Selasky 		break;
6725*d6b92ffaSHans Petter Selasky 	case 0x75d:
6726*d6b92ffaSHans Petter Selasky 		success = handle_case_0x75d(t, i, j, k);
6727*d6b92ffaSHans Petter Selasky 		break;
6728*d6b92ffaSHans Petter Selasky 	case 0x773:
6729*d6b92ffaSHans Petter Selasky 		success = handle_case_0x773(t, i, j, k);
6730*d6b92ffaSHans Petter Selasky 		break;
6731*d6b92ffaSHans Petter Selasky 	case 0x775:
6732*d6b92ffaSHans Petter Selasky 		success = handle_case_0x775(t, i, j, k);
6733*d6b92ffaSHans Petter Selasky 		break;
6734*d6b92ffaSHans Petter Selasky 	case 0x78f:
6735*d6b92ffaSHans Petter Selasky 		success = handle_case_0x78f(t, i, j, k);
6736*d6b92ffaSHans Petter Selasky 		break;
6737*d6b92ffaSHans Petter Selasky 	case 0x7ab:
6738*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7ab(t, i, j, k);
6739*d6b92ffaSHans Petter Selasky 		break;
6740*d6b92ffaSHans Petter Selasky 	case 0x7ae:
6741*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7ae(t, i, j, k);
6742*d6b92ffaSHans Petter Selasky 		break;
6743*d6b92ffaSHans Petter Selasky 	case 0x7b3:
6744*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7b3(t, i, j, k);
6745*d6b92ffaSHans Petter Selasky 		break;
6746*d6b92ffaSHans Petter Selasky 	case 0x7ba:
6747*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7ba(t, i, j, k);
6748*d6b92ffaSHans Petter Selasky 		break;
6749*d6b92ffaSHans Petter Selasky 	case 0x7cd:
6750*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7cd(t, i, j, k);
6751*d6b92ffaSHans Petter Selasky 		break;
6752*d6b92ffaSHans Petter Selasky 	case 0x7ce:
6753*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7ce(t, i, j, k);
6754*d6b92ffaSHans Petter Selasky 		break;
6755*d6b92ffaSHans Petter Selasky 	case 0x7d5:
6756*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7d5(t, i, j, k);
6757*d6b92ffaSHans Petter Selasky 		break;
6758*d6b92ffaSHans Petter Selasky 	case 0x7dc:
6759*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7dc(t, i, j, k);
6760*d6b92ffaSHans Petter Selasky 		break;
6761*d6b92ffaSHans Petter Selasky 	case 0x7ea:
6762*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7ea(t, i, j, k);
6763*d6b92ffaSHans Petter Selasky 		break;
6764*d6b92ffaSHans Petter Selasky 	case 0x7ec:
6765*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7ec(t, i, j, k);
6766*d6b92ffaSHans Petter Selasky 		break;
6767*d6b92ffaSHans Petter Selasky 	case 0x7f1:
6768*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7f1(t, i, j, k);
6769*d6b92ffaSHans Petter Selasky 		break;
6770*d6b92ffaSHans Petter Selasky 	case 0x7f2:
6771*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7f2(t, i, j, k);
6772*d6b92ffaSHans Petter Selasky 		break;
6773*d6b92ffaSHans Petter Selasky 	case 0x7f4:
6774*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7f4(t, i, j, k);
6775*d6b92ffaSHans Petter Selasky 		break;
6776*d6b92ffaSHans Petter Selasky 	case 0x7f8:
6777*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7f8(t, i, j, k);
6778*d6b92ffaSHans Petter Selasky 		break;
6779*d6b92ffaSHans Petter Selasky 	/*
6780*d6b92ffaSHans Petter Selasky 	 * Handle the cases where three existing edges meet at a corner.
6781*d6b92ffaSHans Petter Selasky 	 *
6782*d6b92ffaSHans Petter Selasky 	 */
6783*d6b92ffaSHans Petter Selasky 	case 0x717:
6784*d6b92ffaSHans Petter Selasky 		success = handle_case_0x717(t, i, j, k);
6785*d6b92ffaSHans Petter Selasky 		break;
6786*d6b92ffaSHans Petter Selasky 	case 0x72b:
6787*d6b92ffaSHans Petter Selasky 		success = handle_case_0x72b(t, i, j, k);
6788*d6b92ffaSHans Petter Selasky 		break;
6789*d6b92ffaSHans Petter Selasky 	case 0x74d:
6790*d6b92ffaSHans Petter Selasky 		success = handle_case_0x74d(t, i, j, k);
6791*d6b92ffaSHans Petter Selasky 		break;
6792*d6b92ffaSHans Petter Selasky 	case 0x771:
6793*d6b92ffaSHans Petter Selasky 		success = handle_case_0x771(t, i, j, k);
6794*d6b92ffaSHans Petter Selasky 		break;
6795*d6b92ffaSHans Petter Selasky 	case 0x78e:
6796*d6b92ffaSHans Petter Selasky 		success = handle_case_0x78e(t, i, j, k);
6797*d6b92ffaSHans Petter Selasky 		break;
6798*d6b92ffaSHans Petter Selasky 	case 0x7b2:
6799*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7b2(t, i, j, k);
6800*d6b92ffaSHans Petter Selasky 		break;
6801*d6b92ffaSHans Petter Selasky 	case 0x7d4:
6802*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7d4(t, i, j, k);
6803*d6b92ffaSHans Petter Selasky 		break;
6804*d6b92ffaSHans Petter Selasky 	case 0x7e8:
6805*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7e8(t, i, j, k);
6806*d6b92ffaSHans Petter Selasky 		break;
6807*d6b92ffaSHans Petter Selasky 	/*
6808*d6b92ffaSHans Petter Selasky 	 * Handle the cases where four corners on a single face are missing.
6809*d6b92ffaSHans Petter Selasky 	 */
6810*d6b92ffaSHans Petter Selasky 	case 0x70f:
6811*d6b92ffaSHans Petter Selasky 		success = handle_case_0x70f(t, i, j, k);
6812*d6b92ffaSHans Petter Selasky 		break;
6813*d6b92ffaSHans Petter Selasky 	case 0x733:
6814*d6b92ffaSHans Petter Selasky 		success = handle_case_0x733(t, i, j, k);
6815*d6b92ffaSHans Petter Selasky 		break;
6816*d6b92ffaSHans Petter Selasky 	case 0x755:
6817*d6b92ffaSHans Petter Selasky 		success = handle_case_0x755(t, i, j, k);
6818*d6b92ffaSHans Petter Selasky 		break;
6819*d6b92ffaSHans Petter Selasky 	case 0x7aa:
6820*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7aa(t, i, j, k);
6821*d6b92ffaSHans Petter Selasky 		break;
6822*d6b92ffaSHans Petter Selasky 	case 0x7cc:
6823*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7cc(t, i, j, k);
6824*d6b92ffaSHans Petter Selasky 		break;
6825*d6b92ffaSHans Petter Selasky 	case 0x7f0:
6826*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7f0(t, i, j, k);
6827*d6b92ffaSHans Petter Selasky 		break;
6828*d6b92ffaSHans Petter Selasky 	/*
6829*d6b92ffaSHans Petter Selasky 	 * Handle the cases where three corners on a single face are missing.
6830*d6b92ffaSHans Petter Selasky 	 */
6831*d6b92ffaSHans Petter Selasky 	case 0x707:
6832*d6b92ffaSHans Petter Selasky 		success = handle_case_0x707(t, i, j, k);
6833*d6b92ffaSHans Petter Selasky 		break;
6834*d6b92ffaSHans Petter Selasky 	case 0x70b:
6835*d6b92ffaSHans Petter Selasky 		success = handle_case_0x70b(t, i, j, k);
6836*d6b92ffaSHans Petter Selasky 		break;
6837*d6b92ffaSHans Petter Selasky 	case 0x70d:
6838*d6b92ffaSHans Petter Selasky 		success = handle_case_0x70d(t, i, j, k);
6839*d6b92ffaSHans Petter Selasky 		break;
6840*d6b92ffaSHans Petter Selasky 	case 0x70e:
6841*d6b92ffaSHans Petter Selasky 		success = handle_case_0x70e(t, i, j, k);
6842*d6b92ffaSHans Petter Selasky 		break;
6843*d6b92ffaSHans Petter Selasky 	case 0x713:
6844*d6b92ffaSHans Petter Selasky 		success = handle_case_0x713(t, i, j, k);
6845*d6b92ffaSHans Petter Selasky 		break;
6846*d6b92ffaSHans Petter Selasky 	case 0x715:
6847*d6b92ffaSHans Petter Selasky 		success = handle_case_0x715(t, i, j, k);
6848*d6b92ffaSHans Petter Selasky 		break;
6849*d6b92ffaSHans Petter Selasky 	case 0x723:
6850*d6b92ffaSHans Petter Selasky 		success = handle_case_0x723(t, i, j, k);
6851*d6b92ffaSHans Petter Selasky 		break;
6852*d6b92ffaSHans Petter Selasky 	case 0x72a:
6853*d6b92ffaSHans Petter Selasky 		success = handle_case_0x72a(t, i, j, k);
6854*d6b92ffaSHans Petter Selasky 		break;
6855*d6b92ffaSHans Petter Selasky 	case 0x731:
6856*d6b92ffaSHans Petter Selasky 		success = handle_case_0x731(t, i, j, k);
6857*d6b92ffaSHans Petter Selasky 		break;
6858*d6b92ffaSHans Petter Selasky 	case 0x732:
6859*d6b92ffaSHans Petter Selasky 		success = handle_case_0x732(t, i, j, k);
6860*d6b92ffaSHans Petter Selasky 		break;
6861*d6b92ffaSHans Petter Selasky 	case 0x745:
6862*d6b92ffaSHans Petter Selasky 		success = handle_case_0x745(t, i, j, k);
6863*d6b92ffaSHans Petter Selasky 		break;
6864*d6b92ffaSHans Petter Selasky 	case 0x74c:
6865*d6b92ffaSHans Petter Selasky 		success = handle_case_0x74c(t, i, j, k);
6866*d6b92ffaSHans Petter Selasky 		break;
6867*d6b92ffaSHans Petter Selasky 	case 0x751:
6868*d6b92ffaSHans Petter Selasky 		success = handle_case_0x751(t, i, j, k);
6869*d6b92ffaSHans Petter Selasky 		break;
6870*d6b92ffaSHans Petter Selasky 	case 0x754:
6871*d6b92ffaSHans Petter Selasky 		success = handle_case_0x754(t, i, j, k);
6872*d6b92ffaSHans Petter Selasky 		break;
6873*d6b92ffaSHans Petter Selasky 	case 0x770:
6874*d6b92ffaSHans Petter Selasky 		success = handle_case_0x770(t, i, j, k);
6875*d6b92ffaSHans Petter Selasky 		break;
6876*d6b92ffaSHans Petter Selasky 	case 0x78a:
6877*d6b92ffaSHans Petter Selasky 		success = handle_case_0x78a(t, i, j, k);
6878*d6b92ffaSHans Petter Selasky 		break;
6879*d6b92ffaSHans Petter Selasky 	case 0x78c:
6880*d6b92ffaSHans Petter Selasky 		success = handle_case_0x78c(t, i, j, k);
6881*d6b92ffaSHans Petter Selasky 		break;
6882*d6b92ffaSHans Petter Selasky 	case 0x7a2:
6883*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7a2(t, i, j, k);
6884*d6b92ffaSHans Petter Selasky 		break;
6885*d6b92ffaSHans Petter Selasky 	case 0x7a8:
6886*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7a8(t, i, j, k);
6887*d6b92ffaSHans Petter Selasky 		break;
6888*d6b92ffaSHans Petter Selasky 	case 0x7b0:
6889*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7b0(t, i, j, k);
6890*d6b92ffaSHans Petter Selasky 		break;
6891*d6b92ffaSHans Petter Selasky 	case 0x7c4:
6892*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7c4(t, i, j, k);
6893*d6b92ffaSHans Petter Selasky 		break;
6894*d6b92ffaSHans Petter Selasky 	case 0x7c8:
6895*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7c8(t, i, j, k);
6896*d6b92ffaSHans Petter Selasky 		break;
6897*d6b92ffaSHans Petter Selasky 	case 0x7d0:
6898*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7d0(t, i, j, k);
6899*d6b92ffaSHans Petter Selasky 		break;
6900*d6b92ffaSHans Petter Selasky 	case 0x7e0:
6901*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7e0(t, i, j, k);
6902*d6b92ffaSHans Petter Selasky 		break;
6903*d6b92ffaSHans Petter Selasky 	/*
6904*d6b92ffaSHans Petter Selasky 	 * Handle the cases where two corners on a single edge are missing.
6905*d6b92ffaSHans Petter Selasky 	 */
6906*d6b92ffaSHans Petter Selasky 	case 0x703:
6907*d6b92ffaSHans Petter Selasky 		success = handle_case_0x703(t, i, j, k);
6908*d6b92ffaSHans Petter Selasky 		break;
6909*d6b92ffaSHans Petter Selasky 	case 0x705:
6910*d6b92ffaSHans Petter Selasky 		success = handle_case_0x705(t, i, j, k);
6911*d6b92ffaSHans Petter Selasky 		break;
6912*d6b92ffaSHans Petter Selasky 	case 0x70a:
6913*d6b92ffaSHans Petter Selasky 		success = handle_case_0x70a(t, i, j, k);
6914*d6b92ffaSHans Petter Selasky 		break;
6915*d6b92ffaSHans Petter Selasky 	case 0x70c:
6916*d6b92ffaSHans Petter Selasky 		success = handle_case_0x70c(t, i, j, k);
6917*d6b92ffaSHans Petter Selasky 		break;
6918*d6b92ffaSHans Petter Selasky 	case 0x711:
6919*d6b92ffaSHans Petter Selasky 		success = handle_case_0x711(t, i, j, k);
6920*d6b92ffaSHans Petter Selasky 		break;
6921*d6b92ffaSHans Petter Selasky 	case 0x722:
6922*d6b92ffaSHans Petter Selasky 		success = handle_case_0x722(t, i, j, k);
6923*d6b92ffaSHans Petter Selasky 		break;
6924*d6b92ffaSHans Petter Selasky 	case 0x730:
6925*d6b92ffaSHans Petter Selasky 		success = handle_case_0x730(t, i, j, k);
6926*d6b92ffaSHans Petter Selasky 		break;
6927*d6b92ffaSHans Petter Selasky 	case 0x744:
6928*d6b92ffaSHans Petter Selasky 		success = handle_case_0x744(t, i, j, k);
6929*d6b92ffaSHans Petter Selasky 		break;
6930*d6b92ffaSHans Petter Selasky 	case 0x750:
6931*d6b92ffaSHans Petter Selasky 		success = handle_case_0x750(t, i, j, k);
6932*d6b92ffaSHans Petter Selasky 		break;
6933*d6b92ffaSHans Petter Selasky 	case 0x788:
6934*d6b92ffaSHans Petter Selasky 		success = handle_case_0x788(t, i, j, k);
6935*d6b92ffaSHans Petter Selasky 		break;
6936*d6b92ffaSHans Petter Selasky 	case 0x7a0:
6937*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7a0(t, i, j, k);
6938*d6b92ffaSHans Petter Selasky 		break;
6939*d6b92ffaSHans Petter Selasky 	case 0x7c0:
6940*d6b92ffaSHans Petter Selasky 		success = handle_case_0x7c0(t, i, j, k);
6941*d6b92ffaSHans Petter Selasky 		break;
6942*d6b92ffaSHans Petter Selasky 	/*
6943*d6b92ffaSHans Petter Selasky 	 * Handle the cases where a single corner is missing.
6944*d6b92ffaSHans Petter Selasky 	 */
6945*d6b92ffaSHans Petter Selasky 	case 0x701:
6946*d6b92ffaSHans Petter Selasky 		success = handle_case_0x701(t, i, j, k);
6947*d6b92ffaSHans Petter Selasky 		break;
6948*d6b92ffaSHans Petter Selasky 	case 0x702:
6949*d6b92ffaSHans Petter Selasky 		success = handle_case_0x702(t, i, j, k);
6950*d6b92ffaSHans Petter Selasky 		break;
6951*d6b92ffaSHans Petter Selasky 	case 0x704:
6952*d6b92ffaSHans Petter Selasky 		success = handle_case_0x704(t, i, j, k);
6953*d6b92ffaSHans Petter Selasky 		break;
6954*d6b92ffaSHans Petter Selasky 	case 0x708:
6955*d6b92ffaSHans Petter Selasky 		success = handle_case_0x708(t, i, j, k);
6956*d6b92ffaSHans Petter Selasky 		break;
6957*d6b92ffaSHans Petter Selasky 	case 0x710:
6958*d6b92ffaSHans Petter Selasky 		success = handle_case_0x710(t, i, j, k);
6959*d6b92ffaSHans Petter Selasky 		break;
6960*d6b92ffaSHans Petter Selasky 	case 0x720:
6961*d6b92ffaSHans Petter Selasky 		success = handle_case_0x720(t, i, j, k);
6962*d6b92ffaSHans Petter Selasky 		break;
6963*d6b92ffaSHans Petter Selasky 	case 0x740:
6964*d6b92ffaSHans Petter Selasky 		success = handle_case_0x740(t, i, j, k);
6965*d6b92ffaSHans Petter Selasky 		break;
6966*d6b92ffaSHans Petter Selasky 	case 0x780:
6967*d6b92ffaSHans Petter Selasky 		success = handle_case_0x780(t, i, j, k);
6968*d6b92ffaSHans Petter Selasky 		break;
6969*d6b92ffaSHans Petter Selasky 
6970*d6b92ffaSHans Petter Selasky 	default:
6971*d6b92ffaSHans Petter Selasky 		/*
6972*d6b92ffaSHans Petter Selasky 		 * There's lots of unhandled cases still, but it's not clear
6973*d6b92ffaSHans Petter Selasky 		 * we care.  Let debugging show us what they are so we can
6974*d6b92ffaSHans Petter Selasky 		 * learn if we care.
6975*d6b92ffaSHans Petter Selasky 		 */
6976*d6b92ffaSHans Petter Selasky 		if (t->debug)
6977*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
6978*d6b92ffaSHans Petter Selasky 				"Unhandled fingerprint 0x%03x @ %d %d %d\n",
6979*d6b92ffaSHans Petter Selasky 				fp, i, j, k);
6980*d6b92ffaSHans Petter Selasky 		goto out;
6981*d6b92ffaSHans Petter Selasky 	}
6982*d6b92ffaSHans Petter Selasky 	/*
6983*d6b92ffaSHans Petter Selasky 	 * If we successfully handled a case, we may be able to make more
6984*d6b92ffaSHans Petter Selasky 	 * progress at this position, so try again.  Otherwise, even though
6985*d6b92ffaSHans Petter Selasky 	 * we didn't successfully handle a case, we may have installed a
6986*d6b92ffaSHans Petter Selasky 	 * switch into the torus/mesh, so try to install links as well.
6987*d6b92ffaSHans Petter Selasky 	 * Then we'll have another go at the next position.
6988*d6b92ffaSHans Petter Selasky 	 */
6989*d6b92ffaSHans Petter Selasky 	if (success) {
6990*d6b92ffaSHans Petter Selasky 		if (t->debug)
6991*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
6992*d6b92ffaSHans Petter Selasky 				"Success on fingerprint 0x%03x @ %d %d %d\n",
6993*d6b92ffaSHans Petter Selasky 				fp, i, j, k);
6994*d6b92ffaSHans Petter Selasky 		goto again;
6995*d6b92ffaSHans Petter Selasky 	} else {
6996*d6b92ffaSHans Petter Selasky 		check_tlinks(t, i, j, k);
6997*d6b92ffaSHans Petter Selasky 		if (t->debug)
6998*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
6999*d6b92ffaSHans Petter Selasky 				"Failed on fingerprint 0x%03x @ %d %d %d\n",
7000*d6b92ffaSHans Petter Selasky 				fp, i, j, k);
7001*d6b92ffaSHans Petter Selasky 	}
7002*d6b92ffaSHans Petter Selasky out:
7003*d6b92ffaSHans Petter Selasky 	return;
7004*d6b92ffaSHans Petter Selasky }
7005*d6b92ffaSHans Petter Selasky 
7006*d6b92ffaSHans Petter Selasky #define LINK_ERR_STR " direction link required for topology seed configuration since radix == 4! See torus-2QoS.conf(5).\n"
7007*d6b92ffaSHans Petter Selasky #define LINK_ERR2_STR " direction link required for topology seed configuration! See torus-2QoS.conf(5).\n"
7008*d6b92ffaSHans Petter Selasky #define SEED_ERR_STR " direction links for topology seed do not share a common switch! See torus-2QoS.conf(5).\n"
7009*d6b92ffaSHans Petter Selasky 
7010*d6b92ffaSHans Petter Selasky static
verify_setup(struct torus * t,struct fabric * f)7011*d6b92ffaSHans Petter Selasky bool verify_setup(struct torus *t, struct fabric *f)
7012*d6b92ffaSHans Petter Selasky {
7013*d6b92ffaSHans Petter Selasky 	struct coord_dirs *o;
7014*d6b92ffaSHans Petter Selasky 	struct f_switch *sw;
7015*d6b92ffaSHans Petter Selasky 	unsigned p, s, n = 0;
7016*d6b92ffaSHans Petter Selasky 	bool success = false;
7017*d6b92ffaSHans Petter Selasky 	bool all_sw_present, need_seed = true;
7018*d6b92ffaSHans Petter Selasky 
7019*d6b92ffaSHans Petter Selasky 	if (!(t->x_sz && t->y_sz && t->z_sz)) {
7020*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7021*d6b92ffaSHans Petter Selasky 			"ERR 4E20: missing required torus size specification!\n");
7022*d6b92ffaSHans Petter Selasky 		goto out;
7023*d6b92ffaSHans Petter Selasky 	}
7024*d6b92ffaSHans Petter Selasky 	if (t->osm->subn.min_sw_data_vls < 2) {
7025*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7026*d6b92ffaSHans Petter Selasky 			"ERR 4E48: Too few data VLs to support torus routing "
7027*d6b92ffaSHans Petter Selasky 			"without credit loops (have switchport %d need 2)\n",
7028*d6b92ffaSHans Petter Selasky 			(int)t->osm->subn.min_sw_data_vls);
7029*d6b92ffaSHans Petter Selasky 		goto out;
7030*d6b92ffaSHans Petter Selasky 	}
7031*d6b92ffaSHans Petter Selasky 	if (t->osm->subn.min_sw_data_vls < 4)
7032*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7033*d6b92ffaSHans Petter Selasky 			"Warning: Too few data VLs to support torus routing "
7034*d6b92ffaSHans Petter Selasky 			"with a failed switch without credit loops "
7035*d6b92ffaSHans Petter Selasky 			"(have switchport %d need 4)\n",
7036*d6b92ffaSHans Petter Selasky 			(int)t->osm->subn.min_sw_data_vls);
7037*d6b92ffaSHans Petter Selasky 	if (t->osm->subn.min_sw_data_vls < 8)
7038*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7039*d6b92ffaSHans Petter Selasky 			"Warning: Too few data VLs to support torus routing "
7040*d6b92ffaSHans Petter Selasky 			"with two QoS levels (have switchport %d need 8)\n",
7041*d6b92ffaSHans Petter Selasky 			(int)t->osm->subn.min_sw_data_vls);
7042*d6b92ffaSHans Petter Selasky 	if (t->osm->subn.min_data_vls < 2)
7043*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7044*d6b92ffaSHans Petter Selasky 			"Warning: Too few data VLs to support torus routing "
7045*d6b92ffaSHans Petter Selasky 			"with two QoS levels (have endport %d need 2)\n",
7046*d6b92ffaSHans Petter Selasky 			(int)t->osm->subn.min_data_vls);
7047*d6b92ffaSHans Petter Selasky 	/*
7048*d6b92ffaSHans Petter Selasky 	 * Be sure all the switches in the torus support the port
7049*d6b92ffaSHans Petter Selasky 	 * ordering that might have been configured.
7050*d6b92ffaSHans Petter Selasky 	 */
7051*d6b92ffaSHans Petter Selasky 	for (s = 0; s < f->switch_cnt; s++) {
7052*d6b92ffaSHans Petter Selasky 		sw = f->sw[s];
7053*d6b92ffaSHans Petter Selasky 		for (p = 0; p < sw->port_cnt; p++) {
7054*d6b92ffaSHans Petter Selasky 			if (t->port_order[p] >= sw->port_cnt) {
7055*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7056*d6b92ffaSHans Petter Selasky 					"ERR 4E21: port_order configured using "
7057*d6b92ffaSHans Petter Selasky 					"port %u, but only %u ports in "
7058*d6b92ffaSHans Petter Selasky 					"switch w/ GUID 0x%04"PRIx64"\n",
7059*d6b92ffaSHans Petter Selasky 					t->port_order[p], sw->port_cnt - 1,
7060*d6b92ffaSHans Petter Selasky 					cl_ntoh64(sw->n_id));
7061*d6b92ffaSHans Petter Selasky 				goto out;
7062*d6b92ffaSHans Petter Selasky 			}
7063*d6b92ffaSHans Petter Selasky 		}
7064*d6b92ffaSHans Petter Selasky 	}
7065*d6b92ffaSHans Petter Selasky 	/*
7066*d6b92ffaSHans Petter Selasky 	 * Unfortunately, there is a problem with non-unique topology for any
7067*d6b92ffaSHans Petter Selasky 	 * torus dimension which has radix four.  This problem requires extra
7068*d6b92ffaSHans Petter Selasky 	 * input, in the form of specifying both the positive and negative
7069*d6b92ffaSHans Petter Selasky 	 * coordinate directions from a common switch, for any torus dimension
7070*d6b92ffaSHans Petter Selasky 	 * with radix four (see also build_torus()).
7071*d6b92ffaSHans Petter Selasky 	 *
7072*d6b92ffaSHans Petter Selasky 	 * Do the checking required to ensure that the required information
7073*d6b92ffaSHans Petter Selasky 	 * is present, but more than the needed information is not required.
7074*d6b92ffaSHans Petter Selasky 	 *
7075*d6b92ffaSHans Petter Selasky 	 * So, verify that we learned the coordinate directions correctly for
7076*d6b92ffaSHans Petter Selasky 	 * the fabric.  The coordinate direction links get an invalid port
7077*d6b92ffaSHans Petter Selasky 	 * set on their ends when parsed.
7078*d6b92ffaSHans Petter Selasky 	 */
7079*d6b92ffaSHans Petter Selasky again:
7080*d6b92ffaSHans Petter Selasky 	all_sw_present = true;
7081*d6b92ffaSHans Petter Selasky 	o = &t->seed[n];
7082*d6b92ffaSHans Petter Selasky 
7083*d6b92ffaSHans Petter Selasky 	if (t->x_sz == 4 && !(t->flags & X_MESH)) {
7084*d6b92ffaSHans Petter Selasky 		if (o->xp_link.end[0].port >= 0) {
7085*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7086*d6b92ffaSHans Petter Selasky 				"ERR 4E22: Positive x" LINK_ERR_STR);
7087*d6b92ffaSHans Petter Selasky 			goto out;
7088*d6b92ffaSHans Petter Selasky 		}
7089*d6b92ffaSHans Petter Selasky 		if (o->xm_link.end[0].port >= 0) {
7090*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7091*d6b92ffaSHans Petter Selasky 				"ERR 4E23: Negative x" LINK_ERR_STR);
7092*d6b92ffaSHans Petter Selasky 			goto out;
7093*d6b92ffaSHans Petter Selasky 		}
7094*d6b92ffaSHans Petter Selasky 		if (o->xp_link.end[0].n_id != o->xm_link.end[0].n_id) {
7095*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7096*d6b92ffaSHans Petter Selasky 				"ERR 4E24: Positive/negative x" SEED_ERR_STR);
7097*d6b92ffaSHans Petter Selasky 			goto out;
7098*d6b92ffaSHans Petter Selasky 		}
7099*d6b92ffaSHans Petter Selasky 	}
7100*d6b92ffaSHans Petter Selasky 	if (t->y_sz == 4 && !(t->flags & Y_MESH)) {
7101*d6b92ffaSHans Petter Selasky 		if (o->yp_link.end[0].port >= 0) {
7102*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7103*d6b92ffaSHans Petter Selasky 				"ERR 4E25: Positive y" LINK_ERR_STR);
7104*d6b92ffaSHans Petter Selasky 			goto out;
7105*d6b92ffaSHans Petter Selasky 		}
7106*d6b92ffaSHans Petter Selasky 		if (o->ym_link.end[0].port >= 0) {
7107*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7108*d6b92ffaSHans Petter Selasky 				"ERR 4E26: Negative y" LINK_ERR_STR);
7109*d6b92ffaSHans Petter Selasky 			goto out;
7110*d6b92ffaSHans Petter Selasky 		}
7111*d6b92ffaSHans Petter Selasky 		if (o->yp_link.end[0].n_id != o->ym_link.end[0].n_id) {
7112*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7113*d6b92ffaSHans Petter Selasky 				"ERR 4E27: Positive/negative y" SEED_ERR_STR);
7114*d6b92ffaSHans Petter Selasky 			goto out;
7115*d6b92ffaSHans Petter Selasky 		}
7116*d6b92ffaSHans Petter Selasky 	}
7117*d6b92ffaSHans Petter Selasky 	if (t->z_sz == 4 && !(t->flags & Z_MESH)) {
7118*d6b92ffaSHans Petter Selasky 		if (o->zp_link.end[0].port >= 0) {
7119*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7120*d6b92ffaSHans Petter Selasky 				"ERR 4E28: Positive z" LINK_ERR_STR);
7121*d6b92ffaSHans Petter Selasky 			goto out;
7122*d6b92ffaSHans Petter Selasky 		}
7123*d6b92ffaSHans Petter Selasky 		if (o->zm_link.end[0].port >= 0) {
7124*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7125*d6b92ffaSHans Petter Selasky 				"ERR 4E29: Negative z" LINK_ERR_STR);
7126*d6b92ffaSHans Petter Selasky 			goto out;
7127*d6b92ffaSHans Petter Selasky 		}
7128*d6b92ffaSHans Petter Selasky 		if (o->zp_link.end[0].n_id != o->zm_link.end[0].n_id) {
7129*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7130*d6b92ffaSHans Petter Selasky 				"ERR 4E2A: Positive/negative z" SEED_ERR_STR);
7131*d6b92ffaSHans Petter Selasky 			goto out;
7132*d6b92ffaSHans Petter Selasky 		}
7133*d6b92ffaSHans Petter Selasky 	}
7134*d6b92ffaSHans Petter Selasky 	if (t->x_sz > 1) {
7135*d6b92ffaSHans Petter Selasky 		if (o->xp_link.end[0].port >= 0 &&
7136*d6b92ffaSHans Petter Selasky 		    o->xm_link.end[0].port >= 0) {
7137*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7138*d6b92ffaSHans Petter Selasky 				"ERR 4E2B: Positive or negative x" LINK_ERR2_STR);
7139*d6b92ffaSHans Petter Selasky 			goto out;
7140*d6b92ffaSHans Petter Selasky 		}
7141*d6b92ffaSHans Petter Selasky 		if (o->xp_link.end[0].port < 0 &&
7142*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->xp_link.end[0].n_id))
7143*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7144*d6b92ffaSHans Petter Selasky 
7145*d6b92ffaSHans Petter Selasky 		if (o->xp_link.end[1].port < 0 &&
7146*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->xp_link.end[1].n_id))
7147*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7148*d6b92ffaSHans Petter Selasky 
7149*d6b92ffaSHans Petter Selasky 		if (o->xm_link.end[0].port < 0 &&
7150*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->xm_link.end[0].n_id))
7151*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7152*d6b92ffaSHans Petter Selasky 
7153*d6b92ffaSHans Petter Selasky 		if (o->xm_link.end[1].port < 0 &&
7154*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->xm_link.end[1].n_id))
7155*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7156*d6b92ffaSHans Petter Selasky 	}
7157*d6b92ffaSHans Petter Selasky 	if (t->z_sz > 1) {
7158*d6b92ffaSHans Petter Selasky 		if (o->zp_link.end[0].port >= 0 &&
7159*d6b92ffaSHans Petter Selasky 		    o->zm_link.end[0].port >= 0) {
7160*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7161*d6b92ffaSHans Petter Selasky 				"ERR 4E2C: Positive or negative z" LINK_ERR2_STR);
7162*d6b92ffaSHans Petter Selasky 			goto out;
7163*d6b92ffaSHans Petter Selasky 		}
7164*d6b92ffaSHans Petter Selasky 		if ((o->xp_link.end[0].port < 0 &&
7165*d6b92ffaSHans Petter Selasky 		     o->zp_link.end[0].port < 0 &&
7166*d6b92ffaSHans Petter Selasky 		     o->zp_link.end[0].n_id != o->xp_link.end[0].n_id) ||
7167*d6b92ffaSHans Petter Selasky 
7168*d6b92ffaSHans Petter Selasky 		    (o->xp_link.end[0].port < 0 &&
7169*d6b92ffaSHans Petter Selasky 		     o->zm_link.end[0].port < 0 &&
7170*d6b92ffaSHans Petter Selasky 		     o->zm_link.end[0].n_id != o->xp_link.end[0].n_id) ||
7171*d6b92ffaSHans Petter Selasky 
7172*d6b92ffaSHans Petter Selasky 		    (o->xm_link.end[0].port < 0 &&
7173*d6b92ffaSHans Petter Selasky 		     o->zp_link.end[0].port < 0 &&
7174*d6b92ffaSHans Petter Selasky 		     o->zp_link.end[0].n_id != o->xm_link.end[0].n_id) ||
7175*d6b92ffaSHans Petter Selasky 
7176*d6b92ffaSHans Petter Selasky 		    (o->xm_link.end[0].port < 0 &&
7177*d6b92ffaSHans Petter Selasky 		     o->zm_link.end[0].port < 0 &&
7178*d6b92ffaSHans Petter Selasky 		     o->zm_link.end[0].n_id != o->xm_link.end[0].n_id)) {
7179*d6b92ffaSHans Petter Selasky 
7180*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7181*d6b92ffaSHans Petter Selasky 				"ERR 4E2D: x and z" SEED_ERR_STR);
7182*d6b92ffaSHans Petter Selasky 			goto out;
7183*d6b92ffaSHans Petter Selasky 		}
7184*d6b92ffaSHans Petter Selasky 		if (o->zp_link.end[0].port < 0 &&
7185*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->zp_link.end[0].n_id))
7186*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7187*d6b92ffaSHans Petter Selasky 
7188*d6b92ffaSHans Petter Selasky 		if (o->zp_link.end[1].port < 0 &&
7189*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->zp_link.end[1].n_id))
7190*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7191*d6b92ffaSHans Petter Selasky 
7192*d6b92ffaSHans Petter Selasky 		if (o->zm_link.end[0].port < 0 &&
7193*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->zm_link.end[0].n_id))
7194*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7195*d6b92ffaSHans Petter Selasky 
7196*d6b92ffaSHans Petter Selasky 		if (o->zm_link.end[1].port < 0 &&
7197*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->zm_link.end[1].n_id))
7198*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7199*d6b92ffaSHans Petter Selasky 	}
7200*d6b92ffaSHans Petter Selasky 	if (t->y_sz > 1) {
7201*d6b92ffaSHans Petter Selasky 		if (o->yp_link.end[0].port >= 0 &&
7202*d6b92ffaSHans Petter Selasky 		    o->ym_link.end[0].port >= 0) {
7203*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7204*d6b92ffaSHans Petter Selasky 				"ERR 4E2E: Positive or negative y" LINK_ERR2_STR);
7205*d6b92ffaSHans Petter Selasky 			goto out;
7206*d6b92ffaSHans Petter Selasky 		}
7207*d6b92ffaSHans Petter Selasky 		if ((o->xp_link.end[0].port < 0 &&
7208*d6b92ffaSHans Petter Selasky 		     o->yp_link.end[0].port < 0 &&
7209*d6b92ffaSHans Petter Selasky 		     o->yp_link.end[0].n_id != o->xp_link.end[0].n_id) ||
7210*d6b92ffaSHans Petter Selasky 
7211*d6b92ffaSHans Petter Selasky 		    (o->xp_link.end[0].port < 0 &&
7212*d6b92ffaSHans Petter Selasky 		     o->ym_link.end[0].port < 0 &&
7213*d6b92ffaSHans Petter Selasky 		     o->ym_link.end[0].n_id != o->xp_link.end[0].n_id) ||
7214*d6b92ffaSHans Petter Selasky 
7215*d6b92ffaSHans Petter Selasky 		    (o->xm_link.end[0].port < 0 &&
7216*d6b92ffaSHans Petter Selasky 		     o->yp_link.end[0].port < 0 &&
7217*d6b92ffaSHans Petter Selasky 		     o->yp_link.end[0].n_id != o->xm_link.end[0].n_id) ||
7218*d6b92ffaSHans Petter Selasky 
7219*d6b92ffaSHans Petter Selasky 		    (o->xm_link.end[0].port < 0 &&
7220*d6b92ffaSHans Petter Selasky 		     o->ym_link.end[0].port < 0 &&
7221*d6b92ffaSHans Petter Selasky 		     o->ym_link.end[0].n_id != o->xm_link.end[0].n_id)) {
7222*d6b92ffaSHans Petter Selasky 
7223*d6b92ffaSHans Petter Selasky 			OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7224*d6b92ffaSHans Petter Selasky 				"ERR 4E2F: x and y" SEED_ERR_STR);
7225*d6b92ffaSHans Petter Selasky 			goto out;
7226*d6b92ffaSHans Petter Selasky 		}
7227*d6b92ffaSHans Petter Selasky 		if (o->yp_link.end[0].port < 0 &&
7228*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->yp_link.end[0].n_id))
7229*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7230*d6b92ffaSHans Petter Selasky 
7231*d6b92ffaSHans Petter Selasky 		if (o->yp_link.end[1].port < 0 &&
7232*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->yp_link.end[1].n_id))
7233*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7234*d6b92ffaSHans Petter Selasky 
7235*d6b92ffaSHans Petter Selasky 		if (o->ym_link.end[0].port < 0 &&
7236*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->ym_link.end[0].n_id))
7237*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7238*d6b92ffaSHans Petter Selasky 
7239*d6b92ffaSHans Petter Selasky 		if (o->ym_link.end[1].port < 0 &&
7240*d6b92ffaSHans Petter Selasky 		    !find_f_sw(f, o->ym_link.end[1].n_id))
7241*d6b92ffaSHans Petter Selasky 			all_sw_present = false;
7242*d6b92ffaSHans Petter Selasky 	}
7243*d6b92ffaSHans Petter Selasky 	if (all_sw_present && need_seed) {
7244*d6b92ffaSHans Petter Selasky 		t->seed_idx = n;
7245*d6b92ffaSHans Petter Selasky 		need_seed = false;
7246*d6b92ffaSHans Petter Selasky 	}
7247*d6b92ffaSHans Petter Selasky 	if (++n < t->seed_cnt)
7248*d6b92ffaSHans Petter Selasky 		goto again;
7249*d6b92ffaSHans Petter Selasky 
7250*d6b92ffaSHans Petter Selasky 	if (need_seed)
7251*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7252*d6b92ffaSHans Petter Selasky 			"ERR 4E30: Every configured torus seed has at "
7253*d6b92ffaSHans Petter Selasky 			"least one switch missing in fabric! See "
7254*d6b92ffaSHans Petter Selasky 			"torus-2QoS.conf(5) and TORUS TOPOLOGY DISCOVERY "
7255*d6b92ffaSHans Petter Selasky 			"in torus-2QoS(8)\n");
7256*d6b92ffaSHans Petter Selasky 	else
7257*d6b92ffaSHans Petter Selasky 		success = true;
7258*d6b92ffaSHans Petter Selasky out:
7259*d6b92ffaSHans Petter Selasky 	return success;
7260*d6b92ffaSHans Petter Selasky }
7261*d6b92ffaSHans Petter Selasky 
7262*d6b92ffaSHans Petter Selasky static
build_torus(struct fabric * f,struct torus * t)7263*d6b92ffaSHans Petter Selasky bool build_torus(struct fabric *f, struct torus *t)
7264*d6b92ffaSHans Petter Selasky {
7265*d6b92ffaSHans Petter Selasky 	int i, j, k;
7266*d6b92ffaSHans Petter Selasky 	int im1, jm1, km1;
7267*d6b92ffaSHans Petter Selasky 	int ip1, jp1, kp1;
7268*d6b92ffaSHans Petter Selasky 	unsigned nlink;
7269*d6b92ffaSHans Petter Selasky 	struct coord_dirs *o;
7270*d6b92ffaSHans Petter Selasky 	struct f_switch *fsw0, *fsw1;
7271*d6b92ffaSHans Petter Selasky 	struct t_switch ****sw = t->sw;
7272*d6b92ffaSHans Petter Selasky 	bool success = true;
7273*d6b92ffaSHans Petter Selasky 
7274*d6b92ffaSHans Petter Selasky 	t->link_pool_sz = f->link_cnt;
7275*d6b92ffaSHans Petter Selasky 	t->link_pool = calloc(1, t->link_pool_sz * sizeof(*t->link_pool));
7276*d6b92ffaSHans Petter Selasky 	if (!t->link_pool) {
7277*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7278*d6b92ffaSHans Petter Selasky 			"ERR 4E31: Allocating torus link pool: %s\n",
7279*d6b92ffaSHans Petter Selasky 			strerror(errno));
7280*d6b92ffaSHans Petter Selasky 		goto out;
7281*d6b92ffaSHans Petter Selasky 	}
7282*d6b92ffaSHans Petter Selasky 	t->fabric = f;
7283*d6b92ffaSHans Petter Selasky 
7284*d6b92ffaSHans Petter Selasky 	/*
7285*d6b92ffaSHans Petter Selasky 	 * Get things started by locating the up to seven switches that
7286*d6b92ffaSHans Petter Selasky 	 * define the torus "seed", coordinate directions, and datelines.
7287*d6b92ffaSHans Petter Selasky 	 */
7288*d6b92ffaSHans Petter Selasky 	o = &t->seed[t->seed_idx];
7289*d6b92ffaSHans Petter Selasky 
7290*d6b92ffaSHans Petter Selasky 	i = canonicalize(-o->x_dateline, t->x_sz);
7291*d6b92ffaSHans Petter Selasky 	j = canonicalize(-o->y_dateline, t->y_sz);
7292*d6b92ffaSHans Petter Selasky 	k = canonicalize(-o->z_dateline, t->z_sz);
7293*d6b92ffaSHans Petter Selasky 
7294*d6b92ffaSHans Petter Selasky 	if (o->xp_link.end[0].port < 0) {
7295*d6b92ffaSHans Petter Selasky 		ip1 = canonicalize(1 - o->x_dateline, t->x_sz);
7296*d6b92ffaSHans Petter Selasky 		fsw0 = find_f_sw(f, o->xp_link.end[0].n_id);
7297*d6b92ffaSHans Petter Selasky 		fsw1 = find_f_sw(f, o->xp_link.end[1].n_id);
7298*d6b92ffaSHans Petter Selasky 		success =
7299*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, k, fsw0) &&
7300*d6b92ffaSHans Petter Selasky 			install_tswitch(t, ip1, j, k, fsw1) && success;
7301*d6b92ffaSHans Petter Selasky 	}
7302*d6b92ffaSHans Petter Selasky 	if (o->xm_link.end[0].port < 0) {
7303*d6b92ffaSHans Petter Selasky 		im1 = canonicalize(-1 - o->x_dateline, t->x_sz);
7304*d6b92ffaSHans Petter Selasky 		fsw0 = find_f_sw(f, o->xm_link.end[0].n_id);
7305*d6b92ffaSHans Petter Selasky 		fsw1 = find_f_sw(f, o->xm_link.end[1].n_id);
7306*d6b92ffaSHans Petter Selasky 		success =
7307*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, k, fsw0) &&
7308*d6b92ffaSHans Petter Selasky 			install_tswitch(t, im1, j, k, fsw1) && success;
7309*d6b92ffaSHans Petter Selasky 	}
7310*d6b92ffaSHans Petter Selasky 	if (o->yp_link.end[0].port < 0) {
7311*d6b92ffaSHans Petter Selasky 		jp1 = canonicalize(1 - o->y_dateline, t->y_sz);
7312*d6b92ffaSHans Petter Selasky 		fsw0 = find_f_sw(f, o->yp_link.end[0].n_id);
7313*d6b92ffaSHans Petter Selasky 		fsw1 = find_f_sw(f, o->yp_link.end[1].n_id);
7314*d6b92ffaSHans Petter Selasky 		success =
7315*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, k, fsw0) &&
7316*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, jp1, k, fsw1) && success;
7317*d6b92ffaSHans Petter Selasky 	}
7318*d6b92ffaSHans Petter Selasky 	if (o->ym_link.end[0].port < 0) {
7319*d6b92ffaSHans Petter Selasky 		jm1 = canonicalize(-1 - o->y_dateline, t->y_sz);
7320*d6b92ffaSHans Petter Selasky 		fsw0 = find_f_sw(f, o->ym_link.end[0].n_id);
7321*d6b92ffaSHans Petter Selasky 		fsw1 = find_f_sw(f, o->ym_link.end[1].n_id);
7322*d6b92ffaSHans Petter Selasky 		success =
7323*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, k, fsw0) &&
7324*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, jm1, k, fsw1) && success;
7325*d6b92ffaSHans Petter Selasky 	}
7326*d6b92ffaSHans Petter Selasky 	if (o->zp_link.end[0].port < 0) {
7327*d6b92ffaSHans Petter Selasky 		kp1 = canonicalize(1 - o->z_dateline, t->z_sz);
7328*d6b92ffaSHans Petter Selasky 		fsw0 = find_f_sw(f, o->zp_link.end[0].n_id);
7329*d6b92ffaSHans Petter Selasky 		fsw1 = find_f_sw(f, o->zp_link.end[1].n_id);
7330*d6b92ffaSHans Petter Selasky 		success =
7331*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, k, fsw0) &&
7332*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, kp1, fsw1) && success;
7333*d6b92ffaSHans Petter Selasky 	}
7334*d6b92ffaSHans Petter Selasky 	if (o->zm_link.end[0].port < 0) {
7335*d6b92ffaSHans Petter Selasky 		km1 = canonicalize(-1 - o->z_dateline, t->z_sz);
7336*d6b92ffaSHans Petter Selasky 		fsw0 = find_f_sw(f, o->zm_link.end[0].n_id);
7337*d6b92ffaSHans Petter Selasky 		fsw1 = find_f_sw(f, o->zm_link.end[1].n_id);
7338*d6b92ffaSHans Petter Selasky 		success =
7339*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, k, fsw0) &&
7340*d6b92ffaSHans Petter Selasky 			install_tswitch(t, i, j, km1, fsw1) && success;
7341*d6b92ffaSHans Petter Selasky 	}
7342*d6b92ffaSHans Petter Selasky 	if (!success)
7343*d6b92ffaSHans Petter Selasky 		goto out;
7344*d6b92ffaSHans Petter Selasky 
7345*d6b92ffaSHans Petter Selasky 	if (!t->seed_idx)
7346*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7347*d6b92ffaSHans Petter Selasky 			"Using torus seed configured as default "
7348*d6b92ffaSHans Petter Selasky 			"(seed sw %d,%d,%d GUID 0x%04"PRIx64").\n",
7349*d6b92ffaSHans Petter Selasky 			i, j, k, cl_ntoh64(sw[i][j][k]->n_id));
7350*d6b92ffaSHans Petter Selasky 	else
7351*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7352*d6b92ffaSHans Petter Selasky 			"Using torus seed configured as backup #%u "
7353*d6b92ffaSHans Petter Selasky 			"(seed sw %d,%d,%d GUID 0x%04"PRIx64").\n",
7354*d6b92ffaSHans Petter Selasky 			t->seed_idx, i, j, k, cl_ntoh64(sw[i][j][k]->n_id));
7355*d6b92ffaSHans Petter Selasky 
7356*d6b92ffaSHans Petter Selasky 	/*
7357*d6b92ffaSHans Petter Selasky 	 * Search the fabric and construct the expected torus topology.
7358*d6b92ffaSHans Petter Selasky 	 *
7359*d6b92ffaSHans Petter Selasky 	 * The algorithm is to consider the "cube" formed by eight switch
7360*d6b92ffaSHans Petter Selasky 	 * locations bounded by the corners i, j, k and i+1, j+1, k+1.
7361*d6b92ffaSHans Petter Selasky 	 * For each such cube look at the topology of the switches already
7362*d6b92ffaSHans Petter Selasky 	 * placed in the torus, and deduce which new switches can be placed
7363*d6b92ffaSHans Petter Selasky 	 * into their proper locations in the torus.  Examine each cube
7364*d6b92ffaSHans Petter Selasky 	 * multiple times, until the number of links moved into the torus
7365*d6b92ffaSHans Petter Selasky 	 * topology does not change.
7366*d6b92ffaSHans Petter Selasky 	 */
7367*d6b92ffaSHans Petter Selasky again:
7368*d6b92ffaSHans Petter Selasky 	nlink = t->link_cnt;
7369*d6b92ffaSHans Petter Selasky 
7370*d6b92ffaSHans Petter Selasky 	for (k = 0; k < (int)t->z_sz; k++)
7371*d6b92ffaSHans Petter Selasky 		for (j = 0; j < (int)t->y_sz; j++)
7372*d6b92ffaSHans Petter Selasky 			for (i = 0; i < (int)t->x_sz; i++)
7373*d6b92ffaSHans Petter Selasky 				locate_sw(t, i, j, k);
7374*d6b92ffaSHans Petter Selasky 
7375*d6b92ffaSHans Petter Selasky 	if (t->link_cnt != nlink)
7376*d6b92ffaSHans Petter Selasky 		goto again;
7377*d6b92ffaSHans Petter Selasky 
7378*d6b92ffaSHans Petter Selasky 	/*
7379*d6b92ffaSHans Petter Selasky 	 * Move all other endpoints into torus/mesh.
7380*d6b92ffaSHans Petter Selasky 	 */
7381*d6b92ffaSHans Petter Selasky 	for (k = 0; k < (int)t->z_sz; k++)
7382*d6b92ffaSHans Petter Selasky 		for (j = 0; j < (int)t->y_sz; j++)
7383*d6b92ffaSHans Petter Selasky 			for (i = 0; i < (int)t->x_sz; i++)
7384*d6b92ffaSHans Petter Selasky 				if (!link_srcsink(t, i, j, k)) {
7385*d6b92ffaSHans Petter Selasky 					success = false;
7386*d6b92ffaSHans Petter Selasky 					goto out;
7387*d6b92ffaSHans Petter Selasky 				}
7388*d6b92ffaSHans Petter Selasky out:
7389*d6b92ffaSHans Petter Selasky 	return success;
7390*d6b92ffaSHans Petter Selasky }
7391*d6b92ffaSHans Petter Selasky 
7392*d6b92ffaSHans Petter Selasky /*
7393*d6b92ffaSHans Petter Selasky  * Returns a count of differences between old and new switches.
7394*d6b92ffaSHans Petter Selasky  */
7395*d6b92ffaSHans Petter Selasky static
tsw_changes(struct t_switch * nsw,struct t_switch * osw)7396*d6b92ffaSHans Petter Selasky unsigned tsw_changes(struct t_switch *nsw, struct t_switch *osw)
7397*d6b92ffaSHans Petter Selasky {
7398*d6b92ffaSHans Petter Selasky 	unsigned p, cnt = 0, port_cnt;
7399*d6b92ffaSHans Petter Selasky 	struct endpoint *npt, *opt;
7400*d6b92ffaSHans Petter Selasky 	struct endpoint *rnpt, *ropt;
7401*d6b92ffaSHans Petter Selasky 
7402*d6b92ffaSHans Petter Selasky 	if (nsw && !osw) {
7403*d6b92ffaSHans Petter Selasky 		cnt++;
7404*d6b92ffaSHans Petter Selasky 		OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO,
7405*d6b92ffaSHans Petter Selasky 			"New torus switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7406*d6b92ffaSHans Petter Selasky 			nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id));
7407*d6b92ffaSHans Petter Selasky 		goto out;
7408*d6b92ffaSHans Petter Selasky 	}
7409*d6b92ffaSHans Petter Selasky 	if (osw && !nsw) {
7410*d6b92ffaSHans Petter Selasky 		cnt++;
7411*d6b92ffaSHans Petter Selasky 		OSM_LOG(&osw->torus->osm->log, OSM_LOG_INFO,
7412*d6b92ffaSHans Petter Selasky 			"Lost torus switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7413*d6b92ffaSHans Petter Selasky 			osw->i, osw->j, osw->k, cl_ntoh64(osw->n_id));
7414*d6b92ffaSHans Petter Selasky 		goto out;
7415*d6b92ffaSHans Petter Selasky 	}
7416*d6b92ffaSHans Petter Selasky 	if (!(nsw && osw))
7417*d6b92ffaSHans Petter Selasky 		goto out;
7418*d6b92ffaSHans Petter Selasky 
7419*d6b92ffaSHans Petter Selasky 	if (nsw->n_id != osw->n_id) {
7420*d6b92ffaSHans Petter Selasky 		cnt++;
7421*d6b92ffaSHans Petter Selasky 		OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO,
7422*d6b92ffaSHans Petter Selasky 			"Torus switch %d,%d,%d GUID "
7423*d6b92ffaSHans Petter Selasky 			"was 0x%04"PRIx64", now 0x%04"PRIx64"\n",
7424*d6b92ffaSHans Petter Selasky 			nsw->i, nsw->j, nsw->k,
7425*d6b92ffaSHans Petter Selasky 			cl_ntoh64(osw->n_id), cl_ntoh64(nsw->n_id));
7426*d6b92ffaSHans Petter Selasky 	}
7427*d6b92ffaSHans Petter Selasky 
7428*d6b92ffaSHans Petter Selasky 	if (nsw->port_cnt != osw->port_cnt) {
7429*d6b92ffaSHans Petter Selasky 		cnt++;
7430*d6b92ffaSHans Petter Selasky 		OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO,
7431*d6b92ffaSHans Petter Selasky 			"Torus switch %d,%d,%d GUID 0x%04"PRIx64" "
7432*d6b92ffaSHans Petter Selasky 			"had %d ports, now has %d\n",
7433*d6b92ffaSHans Petter Selasky 			nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id),
7434*d6b92ffaSHans Petter Selasky 			osw->port_cnt, nsw->port_cnt);
7435*d6b92ffaSHans Petter Selasky 	}
7436*d6b92ffaSHans Petter Selasky 	port_cnt = nsw->port_cnt;
7437*d6b92ffaSHans Petter Selasky 	if (port_cnt > osw->port_cnt)
7438*d6b92ffaSHans Petter Selasky 		port_cnt = osw->port_cnt;
7439*d6b92ffaSHans Petter Selasky 
7440*d6b92ffaSHans Petter Selasky 	for (p = 0; p < port_cnt; p++) {
7441*d6b92ffaSHans Petter Selasky 		npt = nsw->port[p];
7442*d6b92ffaSHans Petter Selasky 		opt = osw->port[p];
7443*d6b92ffaSHans Petter Selasky 
7444*d6b92ffaSHans Petter Selasky 		if (npt && npt->link) {
7445*d6b92ffaSHans Petter Selasky 			if (&npt->link->end[0] == npt)
7446*d6b92ffaSHans Petter Selasky 				rnpt = &npt->link->end[1];
7447*d6b92ffaSHans Petter Selasky 			else
7448*d6b92ffaSHans Petter Selasky 				rnpt = &npt->link->end[0];
7449*d6b92ffaSHans Petter Selasky 		} else
7450*d6b92ffaSHans Petter Selasky 			rnpt = NULL;
7451*d6b92ffaSHans Petter Selasky 
7452*d6b92ffaSHans Petter Selasky 		if (opt && opt->link) {
7453*d6b92ffaSHans Petter Selasky 			if (&opt->link->end[0] == opt)
7454*d6b92ffaSHans Petter Selasky 				ropt = &opt->link->end[1];
7455*d6b92ffaSHans Petter Selasky 			else
7456*d6b92ffaSHans Petter Selasky 				ropt = &opt->link->end[0];
7457*d6b92ffaSHans Petter Selasky 		} else
7458*d6b92ffaSHans Petter Selasky 			ropt = NULL;
7459*d6b92ffaSHans Petter Selasky 
7460*d6b92ffaSHans Petter Selasky 		if (rnpt && !ropt) {
7461*d6b92ffaSHans Petter Selasky 			++cnt;
7462*d6b92ffaSHans Petter Selasky 			OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO,
7463*d6b92ffaSHans Petter Selasky 				"Torus switch %d,%d,%d GUID 0x%04"PRIx64"[%d] "
7464*d6b92ffaSHans Petter Selasky 				"remote now %s GUID 0x%04"PRIx64"[%d], "
7465*d6b92ffaSHans Petter Selasky 				"was missing\n",
7466*d6b92ffaSHans Petter Selasky 				nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id),
7467*d6b92ffaSHans Petter Selasky 				p, rnpt->type == PASSTHRU ? "sw" : "node",
7468*d6b92ffaSHans Petter Selasky 				cl_ntoh64(rnpt->n_id), rnpt->port);
7469*d6b92ffaSHans Petter Selasky 			continue;
7470*d6b92ffaSHans Petter Selasky 		}
7471*d6b92ffaSHans Petter Selasky 		if (ropt && !rnpt) {
7472*d6b92ffaSHans Petter Selasky 			++cnt;
7473*d6b92ffaSHans Petter Selasky 			OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO,
7474*d6b92ffaSHans Petter Selasky 				"Torus switch %d,%d,%d GUID 0x%04"PRIx64"[%d] "
7475*d6b92ffaSHans Petter Selasky 				"remote now missing, "
7476*d6b92ffaSHans Petter Selasky 				"was %s GUID 0x%04"PRIx64"[%d]\n",
7477*d6b92ffaSHans Petter Selasky 				osw->i, osw->j, osw->k, cl_ntoh64(nsw->n_id),
7478*d6b92ffaSHans Petter Selasky 				p, ropt->type == PASSTHRU ? "sw" : "node",
7479*d6b92ffaSHans Petter Selasky 				cl_ntoh64(ropt->n_id), ropt->port);
7480*d6b92ffaSHans Petter Selasky 			continue;
7481*d6b92ffaSHans Petter Selasky 		}
7482*d6b92ffaSHans Petter Selasky 		if (!(rnpt && ropt))
7483*d6b92ffaSHans Petter Selasky 			continue;
7484*d6b92ffaSHans Petter Selasky 
7485*d6b92ffaSHans Petter Selasky 		if (rnpt->n_id != ropt->n_id) {
7486*d6b92ffaSHans Petter Selasky 			++cnt;
7487*d6b92ffaSHans Petter Selasky 			OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO,
7488*d6b92ffaSHans Petter Selasky 				"Torus switch %d,%d,%d GUID 0x%04"PRIx64"[%d] "
7489*d6b92ffaSHans Petter Selasky 				"remote now %s GUID 0x%04"PRIx64"[%d], "
7490*d6b92ffaSHans Petter Selasky 				"was %s GUID 0x%04"PRIx64"[%d]\n",
7491*d6b92ffaSHans Petter Selasky 				nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id),
7492*d6b92ffaSHans Petter Selasky 				p, rnpt->type == PASSTHRU ? "sw" : "node",
7493*d6b92ffaSHans Petter Selasky 				cl_ntoh64(rnpt->n_id), rnpt->port,
7494*d6b92ffaSHans Petter Selasky 				ropt->type == PASSTHRU ? "sw" : "node",
7495*d6b92ffaSHans Petter Selasky 				cl_ntoh64(ropt->n_id), ropt->port);
7496*d6b92ffaSHans Petter Selasky 			continue;
7497*d6b92ffaSHans Petter Selasky 		}
7498*d6b92ffaSHans Petter Selasky 	}
7499*d6b92ffaSHans Petter Selasky out:
7500*d6b92ffaSHans Petter Selasky 	return cnt;
7501*d6b92ffaSHans Petter Selasky }
7502*d6b92ffaSHans Petter Selasky 
7503*d6b92ffaSHans Petter Selasky static
dump_torus(struct torus * t)7504*d6b92ffaSHans Petter Selasky void dump_torus(struct torus *t)
7505*d6b92ffaSHans Petter Selasky {
7506*d6b92ffaSHans Petter Selasky 	unsigned i, j, k;
7507*d6b92ffaSHans Petter Selasky 	unsigned x_sz = t->x_sz;
7508*d6b92ffaSHans Petter Selasky 	unsigned y_sz = t->y_sz;
7509*d6b92ffaSHans Petter Selasky 	unsigned z_sz = t->z_sz;
7510*d6b92ffaSHans Petter Selasky 	char path[1024];
7511*d6b92ffaSHans Petter Selasky 	FILE *file;
7512*d6b92ffaSHans Petter Selasky 
7513*d6b92ffaSHans Petter Selasky 	snprintf(path, sizeof(path), "%s/%s", t->osm->subn.opt.dump_files_dir,
7514*d6b92ffaSHans Petter Selasky 		 "opensm-torus.dump");
7515*d6b92ffaSHans Petter Selasky 	file = fopen(path, "w");
7516*d6b92ffaSHans Petter Selasky 	if (!file) {
7517*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7518*d6b92ffaSHans Petter Selasky 			"ERR 4E47: cannot create file \'%s\'\n", path);
7519*d6b92ffaSHans Petter Selasky 		return;
7520*d6b92ffaSHans Petter Selasky 	}
7521*d6b92ffaSHans Petter Selasky 
7522*d6b92ffaSHans Petter Selasky 	for (k = 0; k < z_sz; k++)
7523*d6b92ffaSHans Petter Selasky 		for (j = 0; j < y_sz; j++)
7524*d6b92ffaSHans Petter Selasky 			for (i = 0; i < x_sz; i++)
7525*d6b92ffaSHans Petter Selasky 				if (t->sw[i][j][k])
7526*d6b92ffaSHans Petter Selasky 					fprintf(file, "switch %u,%u,%u GUID 0x%04"
7527*d6b92ffaSHans Petter Selasky 						PRIx64 " (%s)\n",
7528*d6b92ffaSHans Petter Selasky 						i, j, k,
7529*d6b92ffaSHans Petter Selasky 						cl_ntoh64(t->sw[i][j][k]->n_id),
7530*d6b92ffaSHans Petter Selasky 						t->sw[i][j][k]->osm_switch->p_node->print_desc);
7531*d6b92ffaSHans Petter Selasky 	fclose(file);
7532*d6b92ffaSHans Petter Selasky }
7533*d6b92ffaSHans Petter Selasky 
7534*d6b92ffaSHans Petter Selasky static
report_torus_changes(struct torus * nt,struct torus * ot)7535*d6b92ffaSHans Petter Selasky void report_torus_changes(struct torus *nt, struct torus *ot)
7536*d6b92ffaSHans Petter Selasky {
7537*d6b92ffaSHans Petter Selasky 	unsigned cnt = 0;
7538*d6b92ffaSHans Petter Selasky 	unsigned i, j, k;
7539*d6b92ffaSHans Petter Selasky 	unsigned x_sz = nt->x_sz;
7540*d6b92ffaSHans Petter Selasky 	unsigned y_sz = nt->y_sz;
7541*d6b92ffaSHans Petter Selasky 	unsigned z_sz = nt->z_sz;
7542*d6b92ffaSHans Petter Selasky 	unsigned max_changes = nt->max_changes;
7543*d6b92ffaSHans Petter Selasky 
7544*d6b92ffaSHans Petter Selasky 	if (OSM_LOG_IS_ACTIVE_V2(&nt->osm->log, OSM_LOG_ROUTING))
7545*d6b92ffaSHans Petter Selasky 		dump_torus(nt);
7546*d6b92ffaSHans Petter Selasky 
7547*d6b92ffaSHans Petter Selasky 	if (!ot)
7548*d6b92ffaSHans Petter Selasky 		return;
7549*d6b92ffaSHans Petter Selasky 
7550*d6b92ffaSHans Petter Selasky 	if (x_sz != ot->x_sz) {
7551*d6b92ffaSHans Petter Selasky 		cnt++;
7552*d6b92ffaSHans Petter Selasky 		OSM_LOG(&nt->osm->log, OSM_LOG_INFO,
7553*d6b92ffaSHans Petter Selasky 			"Torus x radix was %d now %d\n",
7554*d6b92ffaSHans Petter Selasky 			ot->x_sz, nt->x_sz);
7555*d6b92ffaSHans Petter Selasky 		if (x_sz > ot->x_sz)
7556*d6b92ffaSHans Petter Selasky 			x_sz = ot->x_sz;
7557*d6b92ffaSHans Petter Selasky 	}
7558*d6b92ffaSHans Petter Selasky 	if (y_sz != ot->y_sz) {
7559*d6b92ffaSHans Petter Selasky 		cnt++;
7560*d6b92ffaSHans Petter Selasky 		OSM_LOG(&nt->osm->log, OSM_LOG_INFO,
7561*d6b92ffaSHans Petter Selasky 			"Torus y radix was %d now %d\n",
7562*d6b92ffaSHans Petter Selasky 			ot->y_sz, nt->y_sz);
7563*d6b92ffaSHans Petter Selasky 		if (y_sz > ot->y_sz)
7564*d6b92ffaSHans Petter Selasky 			y_sz = ot->y_sz;
7565*d6b92ffaSHans Petter Selasky 	}
7566*d6b92ffaSHans Petter Selasky 	if (z_sz != ot->z_sz) {
7567*d6b92ffaSHans Petter Selasky 		cnt++;
7568*d6b92ffaSHans Petter Selasky 		OSM_LOG(&nt->osm->log, OSM_LOG_INFO,
7569*d6b92ffaSHans Petter Selasky 			"Torus z radix was %d now %d\n",
7570*d6b92ffaSHans Petter Selasky 			ot->z_sz, nt->z_sz);
7571*d6b92ffaSHans Petter Selasky 		if (z_sz > ot->z_sz)
7572*d6b92ffaSHans Petter Selasky 			z_sz = ot->z_sz;
7573*d6b92ffaSHans Petter Selasky 	}
7574*d6b92ffaSHans Petter Selasky 
7575*d6b92ffaSHans Petter Selasky 	for (k = 0; k < z_sz; k++)
7576*d6b92ffaSHans Petter Selasky 		for (j = 0; j < y_sz; j++)
7577*d6b92ffaSHans Petter Selasky 			for (i = 0; i < x_sz; i++) {
7578*d6b92ffaSHans Petter Selasky 				cnt += tsw_changes(nt->sw[i][j][k],
7579*d6b92ffaSHans Petter Selasky 						   ot->sw[i][j][k]);
7580*d6b92ffaSHans Petter Selasky 				/*
7581*d6b92ffaSHans Petter Selasky 				 * Booting a big fabric will cause lots of
7582*d6b92ffaSHans Petter Selasky 				 * changes as hosts come up, so don't spew.
7583*d6b92ffaSHans Petter Selasky 				 * We want to log changes to learn more about
7584*d6b92ffaSHans Petter Selasky 				 * bouncing links, etc, so they can be fixed.
7585*d6b92ffaSHans Petter Selasky 				 */
7586*d6b92ffaSHans Petter Selasky 				if (cnt > max_changes) {
7587*d6b92ffaSHans Petter Selasky 					OSM_LOG(&nt->osm->log, OSM_LOG_INFO,
7588*d6b92ffaSHans Petter Selasky 						"Too many torus changes; "
7589*d6b92ffaSHans Petter Selasky 						"stopping reporting early\n");
7590*d6b92ffaSHans Petter Selasky 					return;
7591*d6b92ffaSHans Petter Selasky 				}
7592*d6b92ffaSHans Petter Selasky 			}
7593*d6b92ffaSHans Petter Selasky }
7594*d6b92ffaSHans Petter Selasky 
7595*d6b92ffaSHans Petter Selasky static
rpt_torus_missing(struct torus * t,int i,int j,int k,struct t_switch * sw,int * missing_z)7596*d6b92ffaSHans Petter Selasky void rpt_torus_missing(struct torus *t, int i, int j, int k,
7597*d6b92ffaSHans Petter Selasky 		       struct t_switch *sw, int *missing_z)
7598*d6b92ffaSHans Petter Selasky {
7599*d6b92ffaSHans Petter Selasky 	uint64_t guid_ho;
7600*d6b92ffaSHans Petter Selasky 
7601*d6b92ffaSHans Petter Selasky 	if (!sw) {
7602*d6b92ffaSHans Petter Selasky 		/*
7603*d6b92ffaSHans Petter Selasky 		 * We can have multiple missing switches without deadlock
7604*d6b92ffaSHans Petter Selasky 		 * if and only if they are adajacent in the Z direction.
7605*d6b92ffaSHans Petter Selasky 		 */
7606*d6b92ffaSHans Petter Selasky 		if ((t->switch_cnt + 1) < t->sw_pool_sz) {
7607*d6b92ffaSHans Petter Selasky 			if (t->sw[i][j][canonicalize(k - 1, t->z_sz)] &&
7608*d6b92ffaSHans Petter Selasky 			    t->sw[i][j][canonicalize(k + 1, t->z_sz)])
7609*d6b92ffaSHans Petter Selasky 				t->flags |= MSG_DEADLOCK;
7610*d6b92ffaSHans Petter Selasky 		}
7611*d6b92ffaSHans Petter Selasky 		/*
7612*d6b92ffaSHans Petter Selasky 		 * There can be only one such Z-column of missing switches.
7613*d6b92ffaSHans Petter Selasky 		 */
7614*d6b92ffaSHans Petter Selasky 		if (*missing_z < 0)
7615*d6b92ffaSHans Petter Selasky 			*missing_z = i + j * t->x_sz;
7616*d6b92ffaSHans Petter Selasky 		else if (*missing_z != i + j * t->x_sz)
7617*d6b92ffaSHans Petter Selasky 			t->flags |= MSG_DEADLOCK;
7618*d6b92ffaSHans Petter Selasky 
7619*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7620*d6b92ffaSHans Petter Selasky 			"Missing torus switch at %d,%d,%d\n", i, j, k);
7621*d6b92ffaSHans Petter Selasky 		return;
7622*d6b92ffaSHans Petter Selasky 	}
7623*d6b92ffaSHans Petter Selasky 	guid_ho = cl_ntoh64(sw->n_id);
7624*d6b92ffaSHans Petter Selasky 
7625*d6b92ffaSHans Petter Selasky 	if (!(sw->ptgrp[0].port_cnt || (t->x_sz == 1) ||
7626*d6b92ffaSHans Petter Selasky 	      ((t->flags & X_MESH) && i == 0)))
7627*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7628*d6b92ffaSHans Petter Selasky 			"Missing torus -x link on "
7629*d6b92ffaSHans Petter Selasky 			"switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7630*d6b92ffaSHans Petter Selasky 			i, j, k, guid_ho);
7631*d6b92ffaSHans Petter Selasky 	if (!(sw->ptgrp[1].port_cnt || (t->x_sz == 1) ||
7632*d6b92ffaSHans Petter Selasky 	      ((t->flags & X_MESH) && (i + 1) == t->x_sz)))
7633*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7634*d6b92ffaSHans Petter Selasky 			"Missing torus +x link on "
7635*d6b92ffaSHans Petter Selasky 			"switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7636*d6b92ffaSHans Petter Selasky 			i, j, k, guid_ho);
7637*d6b92ffaSHans Petter Selasky 	if (!(sw->ptgrp[2].port_cnt || (t->y_sz == 1) ||
7638*d6b92ffaSHans Petter Selasky 	      ((t->flags & Y_MESH) && j == 0)))
7639*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7640*d6b92ffaSHans Petter Selasky 			"Missing torus -y link on "
7641*d6b92ffaSHans Petter Selasky 			"switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7642*d6b92ffaSHans Petter Selasky 			i, j, k, guid_ho);
7643*d6b92ffaSHans Petter Selasky 	if (!(sw->ptgrp[3].port_cnt || (t->y_sz == 1) ||
7644*d6b92ffaSHans Petter Selasky 	      ((t->flags & Y_MESH) && (j + 1) == t->y_sz)))
7645*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7646*d6b92ffaSHans Petter Selasky 			"Missing torus +y link on "
7647*d6b92ffaSHans Petter Selasky 			"switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7648*d6b92ffaSHans Petter Selasky 			i, j, k, guid_ho);
7649*d6b92ffaSHans Petter Selasky 	if (!(sw->ptgrp[4].port_cnt || (t->z_sz == 1) ||
7650*d6b92ffaSHans Petter Selasky 	      ((t->flags & Z_MESH) && k == 0)))
7651*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7652*d6b92ffaSHans Petter Selasky 			"Missing torus -z link on "
7653*d6b92ffaSHans Petter Selasky 			"switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7654*d6b92ffaSHans Petter Selasky 			i, j, k, guid_ho);
7655*d6b92ffaSHans Petter Selasky 	if (!(sw->ptgrp[5].port_cnt || (t->z_sz == 1) ||
7656*d6b92ffaSHans Petter Selasky 	      ((t->flags & Z_MESH) && (k + 1) == t->z_sz)))
7657*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7658*d6b92ffaSHans Petter Selasky 			"Missing torus +z link on "
7659*d6b92ffaSHans Petter Selasky 			"switch %d,%d,%d GUID 0x%04"PRIx64"\n",
7660*d6b92ffaSHans Petter Selasky 			i, j, k, guid_ho);
7661*d6b92ffaSHans Petter Selasky }
7662*d6b92ffaSHans Petter Selasky 
7663*d6b92ffaSHans Petter Selasky /*
7664*d6b92ffaSHans Petter Selasky  * Returns true if the torus can be successfully routed, false otherwise.
7665*d6b92ffaSHans Petter Selasky  */
7666*d6b92ffaSHans Petter Selasky static
routable_torus(struct torus * t,struct fabric * f)7667*d6b92ffaSHans Petter Selasky bool routable_torus(struct torus *t, struct fabric *f)
7668*d6b92ffaSHans Petter Selasky {
7669*d6b92ffaSHans Petter Selasky 	int i, j, k, tmp = -1;
7670*d6b92ffaSHans Petter Selasky 	unsigned b2g_cnt, g2b_cnt;
7671*d6b92ffaSHans Petter Selasky 	bool success = true;
7672*d6b92ffaSHans Petter Selasky 
7673*d6b92ffaSHans Petter Selasky 	t->flags &= ~MSG_DEADLOCK;
7674*d6b92ffaSHans Petter Selasky 
7675*d6b92ffaSHans Petter Selasky 	if (t->link_cnt != f->link_cnt || t->switch_cnt != f->switch_cnt)
7676*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_INFO,
7677*d6b92ffaSHans Petter Selasky 			"Warning: Could not construct torus using all "
7678*d6b92ffaSHans Petter Selasky 			"known fabric switches and/or links.\n");
7679*d6b92ffaSHans Petter Selasky 
7680*d6b92ffaSHans Petter Selasky 	for (k = 0; k < (int)t->z_sz; k++)
7681*d6b92ffaSHans Petter Selasky 		for (j = 0; j < (int)t->y_sz; j++)
7682*d6b92ffaSHans Petter Selasky 			for (i = 0; i < (int)t->x_sz; i++)
7683*d6b92ffaSHans Petter Selasky 				rpt_torus_missing(t, i, j, k,
7684*d6b92ffaSHans Petter Selasky 						  t->sw[i][j][k], &tmp);
7685*d6b92ffaSHans Petter Selasky 	/*
7686*d6b92ffaSHans Petter Selasky 	 * Check for multiple failures that create disjoint regions on a ring.
7687*d6b92ffaSHans Petter Selasky 	 */
7688*d6b92ffaSHans Petter Selasky 	for (k = 0; k < (int)t->z_sz; k++)
7689*d6b92ffaSHans Petter Selasky 		for (j = 0; j < (int)t->y_sz; j++) {
7690*d6b92ffaSHans Petter Selasky 			b2g_cnt = 0;
7691*d6b92ffaSHans Petter Selasky 			g2b_cnt = 0;
7692*d6b92ffaSHans Petter Selasky 			for (i = 0; i < (int)t->x_sz; i++) {
7693*d6b92ffaSHans Petter Selasky 
7694*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k])
7695*d6b92ffaSHans Petter Selasky 					continue;
7696*d6b92ffaSHans Petter Selasky 
7697*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k]->ptgrp[0].port_cnt)
7698*d6b92ffaSHans Petter Selasky 					b2g_cnt++;
7699*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k]->ptgrp[1].port_cnt)
7700*d6b92ffaSHans Petter Selasky 					g2b_cnt++;
7701*d6b92ffaSHans Petter Selasky 			}
7702*d6b92ffaSHans Petter Selasky 			if (b2g_cnt != g2b_cnt) {
7703*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7704*d6b92ffaSHans Petter Selasky 					"ERR 4E32: strange failures in "
7705*d6b92ffaSHans Petter Selasky 					"x ring at y=%d  z=%d"
7706*d6b92ffaSHans Petter Selasky 					" b2g_cnt %u g2b_cnt %u\n",
7707*d6b92ffaSHans Petter Selasky 					j, k, b2g_cnt, g2b_cnt);
7708*d6b92ffaSHans Petter Selasky 				success = false;
7709*d6b92ffaSHans Petter Selasky 			}
7710*d6b92ffaSHans Petter Selasky 			if (b2g_cnt > 1) {
7711*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7712*d6b92ffaSHans Petter Selasky 					"ERR 4E33: disjoint failures in "
7713*d6b92ffaSHans Petter Selasky 					"x ring at y=%d  z=%d\n", j, k);
7714*d6b92ffaSHans Petter Selasky 				success = false;
7715*d6b92ffaSHans Petter Selasky 			}
7716*d6b92ffaSHans Petter Selasky 		}
7717*d6b92ffaSHans Petter Selasky 
7718*d6b92ffaSHans Petter Selasky 	for (i = 0; i < (int)t->x_sz; i++)
7719*d6b92ffaSHans Petter Selasky 		for (k = 0; k < (int)t->z_sz; k++) {
7720*d6b92ffaSHans Petter Selasky 			b2g_cnt = 0;
7721*d6b92ffaSHans Petter Selasky 			g2b_cnt = 0;
7722*d6b92ffaSHans Petter Selasky 			for (j = 0; j < (int)t->y_sz; j++) {
7723*d6b92ffaSHans Petter Selasky 
7724*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k])
7725*d6b92ffaSHans Petter Selasky 					continue;
7726*d6b92ffaSHans Petter Selasky 
7727*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k]->ptgrp[2].port_cnt)
7728*d6b92ffaSHans Petter Selasky 					b2g_cnt++;
7729*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k]->ptgrp[3].port_cnt)
7730*d6b92ffaSHans Petter Selasky 					g2b_cnt++;
7731*d6b92ffaSHans Petter Selasky 			}
7732*d6b92ffaSHans Petter Selasky 			if (b2g_cnt != g2b_cnt) {
7733*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7734*d6b92ffaSHans Petter Selasky 					"ERR 4E34: strange failures in "
7735*d6b92ffaSHans Petter Selasky 					"y ring at x=%d  z=%d"
7736*d6b92ffaSHans Petter Selasky 					" b2g_cnt %u g2b_cnt %u\n",
7737*d6b92ffaSHans Petter Selasky 					i, k, b2g_cnt, g2b_cnt);
7738*d6b92ffaSHans Petter Selasky 				success = false;
7739*d6b92ffaSHans Petter Selasky 			}
7740*d6b92ffaSHans Petter Selasky 			if (b2g_cnt > 1) {
7741*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7742*d6b92ffaSHans Petter Selasky 					"ERR 4E35: disjoint failures in "
7743*d6b92ffaSHans Petter Selasky 					"y ring at x=%d  z=%d\n", i, k);
7744*d6b92ffaSHans Petter Selasky 				success = false;
7745*d6b92ffaSHans Petter Selasky 			}
7746*d6b92ffaSHans Petter Selasky 		}
7747*d6b92ffaSHans Petter Selasky 
7748*d6b92ffaSHans Petter Selasky 	for (j = 0; j < (int)t->y_sz; j++)
7749*d6b92ffaSHans Petter Selasky 		for (i = 0; i < (int)t->x_sz; i++) {
7750*d6b92ffaSHans Petter Selasky 			b2g_cnt = 0;
7751*d6b92ffaSHans Petter Selasky 			g2b_cnt = 0;
7752*d6b92ffaSHans Petter Selasky 			for (k = 0; k < (int)t->z_sz; k++) {
7753*d6b92ffaSHans Petter Selasky 
7754*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k])
7755*d6b92ffaSHans Petter Selasky 					continue;
7756*d6b92ffaSHans Petter Selasky 
7757*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k]->ptgrp[4].port_cnt)
7758*d6b92ffaSHans Petter Selasky 					b2g_cnt++;
7759*d6b92ffaSHans Petter Selasky 				if (!t->sw[i][j][k]->ptgrp[5].port_cnt)
7760*d6b92ffaSHans Petter Selasky 					g2b_cnt++;
7761*d6b92ffaSHans Petter Selasky 			}
7762*d6b92ffaSHans Petter Selasky 			if (b2g_cnt != g2b_cnt) {
7763*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7764*d6b92ffaSHans Petter Selasky 					"ERR 4E36: strange failures in "
7765*d6b92ffaSHans Petter Selasky 					"z ring at x=%d  y=%d"
7766*d6b92ffaSHans Petter Selasky 					" b2g_cnt %u g2b_cnt %u\n",
7767*d6b92ffaSHans Petter Selasky 					i, j, b2g_cnt, g2b_cnt);
7768*d6b92ffaSHans Petter Selasky 				success = false;
7769*d6b92ffaSHans Petter Selasky 			}
7770*d6b92ffaSHans Petter Selasky 			if (b2g_cnt > 1) {
7771*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7772*d6b92ffaSHans Petter Selasky 					"ERR 4E37: disjoint failures in "
7773*d6b92ffaSHans Petter Selasky 					"z ring at x=%d  y=%d\n", i, j);
7774*d6b92ffaSHans Petter Selasky 				success = false;
7775*d6b92ffaSHans Petter Selasky 			}
7776*d6b92ffaSHans Petter Selasky 		}
7777*d6b92ffaSHans Petter Selasky 
7778*d6b92ffaSHans Petter Selasky 	if (t->flags & MSG_DEADLOCK) {
7779*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
7780*d6b92ffaSHans Petter Selasky 			"ERR 4E38: missing switch topology "
7781*d6b92ffaSHans Petter Selasky 			"==> message deadlock!\n");
7782*d6b92ffaSHans Petter Selasky 		success = false;
7783*d6b92ffaSHans Petter Selasky 	}
7784*d6b92ffaSHans Petter Selasky 	return success;
7785*d6b92ffaSHans Petter Selasky }
7786*d6b92ffaSHans Petter Selasky 
7787*d6b92ffaSHans Petter Selasky /*
7788*d6b92ffaSHans Petter Selasky  * Use this function to re-establish the pointers between a torus endpoint
7789*d6b92ffaSHans Petter Selasky  * and an opensm osm_port_t.
7790*d6b92ffaSHans Petter Selasky  *
7791*d6b92ffaSHans Petter Selasky  * Typically this is only needed when "opensm --ucast-cache" is used, and
7792*d6b92ffaSHans Petter Selasky  * a CA link bounces.  When the CA port goes away, the osm_port_t object
7793*d6b92ffaSHans Petter Selasky  * is destroyed, invalidating the endpoint osm_port_t pointer.  When the
7794*d6b92ffaSHans Petter Selasky  * link comes back, a new osm_port_t object is created with a NULL priv
7795*d6b92ffaSHans Petter Selasky  * member.  Thus, when osm_get_torus_sl() is called it is missing the data
7796*d6b92ffaSHans Petter Selasky  * needed to do its work.  Use this function to fix things up.
7797*d6b92ffaSHans Petter Selasky  */
7798*d6b92ffaSHans Petter Selasky static
osm_port_relink_endpoint(const osm_port_t * osm_port)7799*d6b92ffaSHans Petter Selasky struct endpoint *osm_port_relink_endpoint(const osm_port_t *osm_port)
7800*d6b92ffaSHans Petter Selasky {
7801*d6b92ffaSHans Petter Selasky 	guid_t node_guid;
7802*d6b92ffaSHans Petter Selasky 	uint8_t port_num, r_port_num;
7803*d6b92ffaSHans Petter Selasky 	struct t_switch *sw;
7804*d6b92ffaSHans Petter Selasky 	struct endpoint *ep = NULL;
7805*d6b92ffaSHans Petter Selasky 	osm_switch_t *osm_sw;
7806*d6b92ffaSHans Petter Selasky 	osm_physp_t *osm_physp;
7807*d6b92ffaSHans Petter Selasky 	osm_node_t *osm_node, *r_osm_node;
7808*d6b92ffaSHans Petter Selasky 
7809*d6b92ffaSHans Petter Selasky 	/*
7810*d6b92ffaSHans Petter Selasky 	 * We need to find the torus endpoint that has the same GUID as
7811*d6b92ffaSHans Petter Selasky 	 * the osm_port.  Rather than search the entire set of endpoints,
7812*d6b92ffaSHans Petter Selasky 	 * we'll try to follow pointers.
7813*d6b92ffaSHans Petter Selasky 	 */
7814*d6b92ffaSHans Petter Selasky 	osm_physp = osm_port->p_physp;
7815*d6b92ffaSHans Petter Selasky 	osm_node = osm_port->p_node;
7816*d6b92ffaSHans Petter Selasky 	port_num = osm_physp_get_port_num(osm_physp);
7817*d6b92ffaSHans Petter Selasky 	node_guid = osm_node_get_node_guid(osm_node);
7818*d6b92ffaSHans Petter Selasky 	/*
7819*d6b92ffaSHans Petter Selasky 	 * Switch management port?
7820*d6b92ffaSHans Petter Selasky 	 */
7821*d6b92ffaSHans Petter Selasky 	if (port_num == 0 &&
7822*d6b92ffaSHans Petter Selasky 	    osm_node_get_type(osm_node) == IB_NODE_TYPE_SWITCH) {
7823*d6b92ffaSHans Petter Selasky 
7824*d6b92ffaSHans Petter Selasky 		osm_sw = osm_node->sw;
7825*d6b92ffaSHans Petter Selasky 		if (osm_sw && osm_sw->priv) {
7826*d6b92ffaSHans Petter Selasky 			sw = osm_sw->priv;
7827*d6b92ffaSHans Petter Selasky 			if (sw->osm_switch == osm_sw &&
7828*d6b92ffaSHans Petter Selasky 			    sw->port[0]->n_id == node_guid) {
7829*d6b92ffaSHans Petter Selasky 
7830*d6b92ffaSHans Petter Selasky 				ep = sw->port[0];
7831*d6b92ffaSHans Petter Selasky 				goto relink_priv;
7832*d6b92ffaSHans Petter Selasky 			}
7833*d6b92ffaSHans Petter Selasky 		}
7834*d6b92ffaSHans Petter Selasky 	}
7835*d6b92ffaSHans Petter Selasky 	/*
7836*d6b92ffaSHans Petter Selasky 	 * CA port?  Try other end of link.  This should also catch a
7837*d6b92ffaSHans Petter Selasky 	 * router port if it is connected to a switch.
7838*d6b92ffaSHans Petter Selasky 	 */
7839*d6b92ffaSHans Petter Selasky 	r_osm_node = osm_node_get_remote_node(osm_node, port_num, &r_port_num);
7840*d6b92ffaSHans Petter Selasky 	if (!r_osm_node)
7841*d6b92ffaSHans Petter Selasky 		goto out;
7842*d6b92ffaSHans Petter Selasky 
7843*d6b92ffaSHans Petter Selasky 	osm_sw = r_osm_node->sw;
7844*d6b92ffaSHans Petter Selasky 	if (!osm_sw)
7845*d6b92ffaSHans Petter Selasky 		goto out;
7846*d6b92ffaSHans Petter Selasky 
7847*d6b92ffaSHans Petter Selasky 	sw = osm_sw->priv;
7848*d6b92ffaSHans Petter Selasky 	if (!(sw && sw->osm_switch == osm_sw))
7849*d6b92ffaSHans Petter Selasky 		goto out;
7850*d6b92ffaSHans Petter Selasky 
7851*d6b92ffaSHans Petter Selasky 	ep = sw->port[r_port_num];
7852*d6b92ffaSHans Petter Selasky 	if (!(ep && ep->link))
7853*d6b92ffaSHans Petter Selasky 		goto out;
7854*d6b92ffaSHans Petter Selasky 
7855*d6b92ffaSHans Petter Selasky 	if (ep->link->end[0].n_id == node_guid) {
7856*d6b92ffaSHans Petter Selasky 		ep = &ep->link->end[0];
7857*d6b92ffaSHans Petter Selasky 		goto relink_priv;
7858*d6b92ffaSHans Petter Selasky 	}
7859*d6b92ffaSHans Petter Selasky 	if (ep->link->end[1].n_id == node_guid) {
7860*d6b92ffaSHans Petter Selasky 		ep = &ep->link->end[1];
7861*d6b92ffaSHans Petter Selasky 		goto relink_priv;
7862*d6b92ffaSHans Petter Selasky 	}
7863*d6b92ffaSHans Petter Selasky 	ep = NULL;
7864*d6b92ffaSHans Petter Selasky 	goto out;
7865*d6b92ffaSHans Petter Selasky 
7866*d6b92ffaSHans Petter Selasky relink_priv:
7867*d6b92ffaSHans Petter Selasky 	/* FIXME:
7868*d6b92ffaSHans Petter Selasky 	 * Unfortunately, we need to cast away const to rebuild the links
7869*d6b92ffaSHans Petter Selasky 	 * between the torus endpoint and the osm_port_t.
7870*d6b92ffaSHans Petter Selasky 	 *
7871*d6b92ffaSHans Petter Selasky 	 * What is really needed is to check whether pr_rcv_get_path_parms()
7872*d6b92ffaSHans Petter Selasky 	 * needs its port objects to be const.  If so, why, and whether
7873*d6b92ffaSHans Petter Selasky 	 * anything can be done about it.
7874*d6b92ffaSHans Petter Selasky 	 */
7875*d6b92ffaSHans Petter Selasky 	((osm_port_t *)osm_port)->priv = ep;
7876*d6b92ffaSHans Petter Selasky 	ep->osm_port = (osm_port_t *)osm_port;
7877*d6b92ffaSHans Petter Selasky out:
7878*d6b92ffaSHans Petter Selasky 	return ep;
7879*d6b92ffaSHans Petter Selasky }
7880*d6b92ffaSHans Petter Selasky 
7881*d6b92ffaSHans Petter Selasky /*
7882*d6b92ffaSHans Petter Selasky  * Computing LFT entries and path SL values:
7883*d6b92ffaSHans Petter Selasky  *
7884*d6b92ffaSHans Petter Selasky  * For a pristine torus, we compute LFT entries using XYZ DOR, and select
7885*d6b92ffaSHans Petter Selasky  * which direction to route on a ring (i.e., the 1-D torus for the coordinate
7886*d6b92ffaSHans Petter Selasky  * in question) based on shortest path.  We compute the SL to use for the
7887*d6b92ffaSHans Petter Selasky  * path based on whether we crossed a dateline (where a ring coordinate
7888*d6b92ffaSHans Petter Selasky  * wraps to zero) for each coordinate.
7889*d6b92ffaSHans Petter Selasky  *
7890*d6b92ffaSHans Petter Selasky  * When there is a link/switch failure, we want to compute LFT entries
7891*d6b92ffaSHans Petter Selasky  * to route around the failure, without changing the path SL.  I.e., we
7892*d6b92ffaSHans Petter Selasky  * want the SL to reach a given destination from a given source to be
7893*d6b92ffaSHans Petter Selasky  * independent of the presence or number of failed components in the fabric.
7894*d6b92ffaSHans Petter Selasky  *
7895*d6b92ffaSHans Petter Selasky  * In order to make this feasible, we will assume that no ring is broken
7896*d6b92ffaSHans Petter Selasky  * into disjoint pieces by multiple failures
7897*d6b92ffaSHans Petter Selasky  *
7898*d6b92ffaSHans Petter Selasky  * We handle failure by attempting to take the long way around any ring
7899*d6b92ffaSHans Petter Selasky  * with connectivity interrupted by failed components, unless the path
7900*d6b92ffaSHans Petter Selasky  * requires a turn on a failed switch.
7901*d6b92ffaSHans Petter Selasky  *
7902*d6b92ffaSHans Petter Selasky  * For paths that require a turn on a failed switch, we head towards the
7903*d6b92ffaSHans Petter Selasky  * failed switch, then turn when progress is blocked by a failure, using a
7904*d6b92ffaSHans Petter Selasky  * turn allowed under XYZ DOR.  However, such a path will also require a turn
7905*d6b92ffaSHans Petter Selasky  * that is not a legal XYZ DOR turn, so we construct the SL2VL mapping tables
7906*d6b92ffaSHans Petter Selasky  * such that XYZ DOR turns use one set of VLs and ZYX DOR turns use a
7907*d6b92ffaSHans Petter Selasky  * separate set of VLs.
7908*d6b92ffaSHans Petter Selasky  *
7909*d6b92ffaSHans Petter Selasky  * Under these rules the algorithm guarantees credit-loop-free routing for a
7910*d6b92ffaSHans Petter Selasky  * single failed switch, without any change in path SL values.  We can also
7911*d6b92ffaSHans Petter Selasky  * guarantee credit-loop-free routing for failures of multiple switches, if
7912*d6b92ffaSHans Petter Selasky  * they are adjacent in the last DOR direction.  Since we use XYZ-DOR,
7913*d6b92ffaSHans Petter Selasky  * that means failed switches at i,j,k and i,j,k+1 will not cause credit
7914*d6b92ffaSHans Petter Selasky  * loops.
7915*d6b92ffaSHans Petter Selasky  *
7916*d6b92ffaSHans Petter Selasky  * These failure routing rules are intended to prevent paths that cross any
7917*d6b92ffaSHans Petter Selasky  * coordinate dateline twice (over and back), so we don't need to worry about
7918*d6b92ffaSHans Petter Selasky  * any ambiguity over which SL to use for such a case.  Also, we cannot have
7919*d6b92ffaSHans Petter Selasky  * a ring deadlock when a ring is broken by failure and we route the long
7920*d6b92ffaSHans Petter Selasky  * way around, so we don't need to worry about the impact of such routing
7921*d6b92ffaSHans Petter Selasky  * on SL choice.
7922*d6b92ffaSHans Petter Selasky  */
7923*d6b92ffaSHans Petter Selasky 
7924*d6b92ffaSHans Petter Selasky /*
7925*d6b92ffaSHans Petter Selasky  * Functions to set our SL bit encoding for routing/QoS info.  Combine the
7926*d6b92ffaSHans Petter Selasky  * resuts of these functions with bitwise or to get final SL.
7927*d6b92ffaSHans Petter Selasky  *
7928*d6b92ffaSHans Petter Selasky  * SL bits 0-2 encode whether we "looped" in a given direction
7929*d6b92ffaSHans Petter Selasky  * on the torus on the path from source to destination.
7930*d6b92ffaSHans Petter Selasky  *
7931*d6b92ffaSHans Petter Selasky  * SL bit 3 encodes the QoS level.  We only support two QoS levels.
7932*d6b92ffaSHans Petter Selasky  *
7933*d6b92ffaSHans Petter Selasky  * Below we assume TORUS_MAX_DIM == 3 and 0 <= coord_dir < TORUS_MAX_DIM.
7934*d6b92ffaSHans Petter Selasky  */
7935*d6b92ffaSHans Petter Selasky static inline
sl_set_use_loop_vl(bool use_loop_vl,unsigned coord_dir)7936*d6b92ffaSHans Petter Selasky unsigned sl_set_use_loop_vl(bool use_loop_vl, unsigned coord_dir)
7937*d6b92ffaSHans Petter Selasky {
7938*d6b92ffaSHans Petter Selasky 	return (coord_dir < TORUS_MAX_DIM)
7939*d6b92ffaSHans Petter Selasky 		? ((unsigned)use_loop_vl << coord_dir) : 0;
7940*d6b92ffaSHans Petter Selasky }
7941*d6b92ffaSHans Petter Selasky 
7942*d6b92ffaSHans Petter Selasky static inline
sl_set_qos(unsigned qos)7943*d6b92ffaSHans Petter Selasky unsigned sl_set_qos(unsigned qos)
7944*d6b92ffaSHans Petter Selasky {
7945*d6b92ffaSHans Petter Selasky 	return (unsigned)(!!qos) << TORUS_MAX_DIM;
7946*d6b92ffaSHans Petter Selasky }
7947*d6b92ffaSHans Petter Selasky 
7948*d6b92ffaSHans Petter Selasky /*
7949*d6b92ffaSHans Petter Selasky  * Functions to crack our SL bit encoding for routing/QoS info.
7950*d6b92ffaSHans Petter Selasky  */
7951*d6b92ffaSHans Petter Selasky static inline
sl_get_use_loop_vl(unsigned sl,unsigned coord_dir)7952*d6b92ffaSHans Petter Selasky bool sl_get_use_loop_vl(unsigned sl, unsigned coord_dir)
7953*d6b92ffaSHans Petter Selasky {
7954*d6b92ffaSHans Petter Selasky 	return (coord_dir < TORUS_MAX_DIM)
7955*d6b92ffaSHans Petter Selasky 		? (sl >> coord_dir) & 0x1 : false;
7956*d6b92ffaSHans Petter Selasky }
7957*d6b92ffaSHans Petter Selasky 
7958*d6b92ffaSHans Petter Selasky static inline
sl_get_qos(unsigned sl)7959*d6b92ffaSHans Petter Selasky unsigned sl_get_qos(unsigned sl)
7960*d6b92ffaSHans Petter Selasky {
7961*d6b92ffaSHans Petter Selasky 	return (sl >> TORUS_MAX_DIM) & 0x1;
7962*d6b92ffaSHans Petter Selasky }
7963*d6b92ffaSHans Petter Selasky 
7964*d6b92ffaSHans Petter Selasky /*
7965*d6b92ffaSHans Petter Selasky  * Functions to encode routing/QoS info into VL bits.  Combine the resuts of
7966*d6b92ffaSHans Petter Selasky  * these functions with bitwise or to get final VL.
7967*d6b92ffaSHans Petter Selasky  *
7968*d6b92ffaSHans Petter Selasky  * For interswitch links:
7969*d6b92ffaSHans Petter Selasky  * VL bit 0 encodes whether we need to leave on the "loop" VL.
7970*d6b92ffaSHans Petter Selasky  *
7971*d6b92ffaSHans Petter Selasky  * VL bit 1 encodes whether turn is XYZ DOR or ZYX DOR. A 3d mesh/torus
7972*d6b92ffaSHans Petter Selasky  * has 6 turn types: x-y, y-z, x-z, y-x, z-y, z-x.  The first three are
7973*d6b92ffaSHans Petter Selasky  * legal XYZ DOR turns, and the second three are legal ZYX DOR turns.
7974*d6b92ffaSHans Petter Selasky  * Straight-through (x-x, y-y, z-z) paths are legal in both DOR variants,
7975*d6b92ffaSHans Petter Selasky  * so we'll assign them to XYZ DOR VLs.
7976*d6b92ffaSHans Petter Selasky  *
7977*d6b92ffaSHans Petter Selasky  * Note that delivery to switch-local ports (i.e. those that source/sink
7978*d6b92ffaSHans Petter Selasky  * traffic, rather than forwarding it) cannot cause a deadlock, so that
7979*d6b92ffaSHans Petter Selasky  * can also use either XYZ or ZYX DOR.
7980*d6b92ffaSHans Petter Selasky  *
7981*d6b92ffaSHans Petter Selasky  * VL bit 2 encodes QoS level.
7982*d6b92ffaSHans Petter Selasky  *
7983*d6b92ffaSHans Petter Selasky  * For end port links:
7984*d6b92ffaSHans Petter Selasky  * VL bit 0 encodes QoS level.
7985*d6b92ffaSHans Petter Selasky  *
7986*d6b92ffaSHans Petter Selasky  * Note that if VL bit encodings are changed here, the available fabric VL
7987*d6b92ffaSHans Petter Selasky  * verification in verify_setup() needs to be updated as well.
7988*d6b92ffaSHans Petter Selasky  */
7989*d6b92ffaSHans Petter Selasky static inline
vl_set_loop_vl(bool use_loop_vl)7990*d6b92ffaSHans Petter Selasky unsigned vl_set_loop_vl(bool use_loop_vl)
7991*d6b92ffaSHans Petter Selasky {
7992*d6b92ffaSHans Petter Selasky 	return use_loop_vl;
7993*d6b92ffaSHans Petter Selasky }
7994*d6b92ffaSHans Petter Selasky 
7995*d6b92ffaSHans Petter Selasky static inline
vl_set_qos_vl(unsigned qos)7996*d6b92ffaSHans Petter Selasky unsigned vl_set_qos_vl(unsigned qos)
7997*d6b92ffaSHans Petter Selasky {
7998*d6b92ffaSHans Petter Selasky 	return (qos & 0x1) << 2;
7999*d6b92ffaSHans Petter Selasky }
8000*d6b92ffaSHans Petter Selasky 
8001*d6b92ffaSHans Petter Selasky static inline
vl_set_ca_qos_vl(unsigned qos)8002*d6b92ffaSHans Petter Selasky unsigned vl_set_ca_qos_vl(unsigned qos)
8003*d6b92ffaSHans Petter Selasky {
8004*d6b92ffaSHans Petter Selasky 	return qos & 0x1;
8005*d6b92ffaSHans Petter Selasky }
8006*d6b92ffaSHans Petter Selasky 
8007*d6b92ffaSHans Petter Selasky static inline
vl_set_turn_vl(unsigned in_coord_dir,unsigned out_coord_dir)8008*d6b92ffaSHans Petter Selasky unsigned vl_set_turn_vl(unsigned in_coord_dir, unsigned out_coord_dir)
8009*d6b92ffaSHans Petter Selasky {
8010*d6b92ffaSHans Petter Selasky 	unsigned vl = 0;
8011*d6b92ffaSHans Petter Selasky 
8012*d6b92ffaSHans Petter Selasky 	if (in_coord_dir != TORUS_MAX_DIM &&
8013*d6b92ffaSHans Petter Selasky 	    out_coord_dir != TORUS_MAX_DIM)
8014*d6b92ffaSHans Petter Selasky 		vl = (in_coord_dir > out_coord_dir)
8015*d6b92ffaSHans Petter Selasky 			? 0x1 << 1 : 0;
8016*d6b92ffaSHans Petter Selasky 
8017*d6b92ffaSHans Petter Selasky 	return vl;
8018*d6b92ffaSHans Petter Selasky }
8019*d6b92ffaSHans Petter Selasky 
8020*d6b92ffaSHans Petter Selasky static
sl2vl_entry(struct torus * t,struct t_switch * sw,int input_pt,int output_pt,unsigned sl)8021*d6b92ffaSHans Petter Selasky unsigned sl2vl_entry(struct torus *t, struct t_switch *sw,
8022*d6b92ffaSHans Petter Selasky 		     int input_pt, int output_pt, unsigned sl)
8023*d6b92ffaSHans Petter Selasky {
8024*d6b92ffaSHans Petter Selasky 	unsigned id, od, vl, data_vls;
8025*d6b92ffaSHans Petter Selasky 
8026*d6b92ffaSHans Petter Selasky 	if (sw && sw->port[input_pt])
8027*d6b92ffaSHans Petter Selasky 		id = sw->port[input_pt]->pgrp->port_grp / 2;
8028*d6b92ffaSHans Petter Selasky 	else
8029*d6b92ffaSHans Petter Selasky 		id = TORUS_MAX_DIM;
8030*d6b92ffaSHans Petter Selasky 
8031*d6b92ffaSHans Petter Selasky 	if (sw && sw->port[output_pt])
8032*d6b92ffaSHans Petter Selasky 		od = sw->port[output_pt]->pgrp->port_grp / 2;
8033*d6b92ffaSHans Petter Selasky 	else
8034*d6b92ffaSHans Petter Selasky 		od = TORUS_MAX_DIM;
8035*d6b92ffaSHans Petter Selasky 
8036*d6b92ffaSHans Petter Selasky 	if (sw)
8037*d6b92ffaSHans Petter Selasky 		data_vls = t->osm->subn.min_sw_data_vls;
8038*d6b92ffaSHans Petter Selasky 	else
8039*d6b92ffaSHans Petter Selasky 		data_vls = t->osm->subn.min_data_vls;
8040*d6b92ffaSHans Petter Selasky 
8041*d6b92ffaSHans Petter Selasky 	vl = 0;
8042*d6b92ffaSHans Petter Selasky 	if (sw && od != TORUS_MAX_DIM) {
8043*d6b92ffaSHans Petter Selasky 		if (data_vls >= 2)
8044*d6b92ffaSHans Petter Selasky 			vl |= vl_set_loop_vl(sl_get_use_loop_vl(sl, od));
8045*d6b92ffaSHans Petter Selasky 		if (data_vls >= 4)
8046*d6b92ffaSHans Petter Selasky 			vl |= vl_set_turn_vl(id, od);
8047*d6b92ffaSHans Petter Selasky 		if (data_vls >= 8)
8048*d6b92ffaSHans Petter Selasky 			vl |= vl_set_qos_vl(sl_get_qos(sl));
8049*d6b92ffaSHans Petter Selasky 	} else {
8050*d6b92ffaSHans Petter Selasky 		if (data_vls >= 2)
8051*d6b92ffaSHans Petter Selasky 			vl |= vl_set_ca_qos_vl(sl_get_qos(sl));
8052*d6b92ffaSHans Petter Selasky 	}
8053*d6b92ffaSHans Petter Selasky 	return vl;
8054*d6b92ffaSHans Petter Selasky }
8055*d6b92ffaSHans Petter Selasky 
8056*d6b92ffaSHans Petter Selasky static
torus_update_osm_sl2vl(void * context,osm_physp_t * osm_phys_port,uint8_t iport_num,uint8_t oport_num,ib_slvl_table_t * osm_oport_sl2vl)8057*d6b92ffaSHans Petter Selasky void torus_update_osm_sl2vl(void *context, osm_physp_t *osm_phys_port,
8058*d6b92ffaSHans Petter Selasky 			    uint8_t iport_num, uint8_t oport_num,
8059*d6b92ffaSHans Petter Selasky 			    ib_slvl_table_t *osm_oport_sl2vl)
8060*d6b92ffaSHans Petter Selasky {
8061*d6b92ffaSHans Petter Selasky 	osm_node_t *node = osm_physp_get_node_ptr(osm_phys_port);
8062*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx = context;
8063*d6b92ffaSHans Petter Selasky 	struct t_switch *sw = NULL;
8064*d6b92ffaSHans Petter Selasky 	int sl, vl;
8065*d6b92ffaSHans Petter Selasky 
8066*d6b92ffaSHans Petter Selasky 	if (node->sw) {
8067*d6b92ffaSHans Petter Selasky 		sw = node->sw->priv;
8068*d6b92ffaSHans Petter Selasky 		if (sw && sw->osm_switch != node->sw) {
8069*d6b92ffaSHans Petter Selasky 			osm_log_t *log = &ctx->osm->log;
8070*d6b92ffaSHans Petter Selasky 			guid_t guid;
8071*d6b92ffaSHans Petter Selasky 
8072*d6b92ffaSHans Petter Selasky 			guid = osm_node_get_node_guid(node);
8073*d6b92ffaSHans Petter Selasky 			OSM_LOG(log, OSM_LOG_INFO,
8074*d6b92ffaSHans Petter Selasky 				"Note: osm_switch (GUID 0x%04"PRIx64") "
8075*d6b92ffaSHans Petter Selasky 				"not in torus fabric description\n",
8076*d6b92ffaSHans Petter Selasky 				cl_ntoh64(guid));
8077*d6b92ffaSHans Petter Selasky 			return;
8078*d6b92ffaSHans Petter Selasky 		}
8079*d6b92ffaSHans Petter Selasky 	}
8080*d6b92ffaSHans Petter Selasky 	for (sl = 0; sl < 16; sl++) {
8081*d6b92ffaSHans Petter Selasky 		vl = sl2vl_entry(ctx->torus, sw, iport_num, oport_num, sl);
8082*d6b92ffaSHans Petter Selasky 		ib_slvl_table_set(osm_oport_sl2vl, sl, vl);
8083*d6b92ffaSHans Petter Selasky 	}
8084*d6b92ffaSHans Petter Selasky }
8085*d6b92ffaSHans Petter Selasky 
8086*d6b92ffaSHans Petter Selasky static
torus_update_osm_vlarb(void * context,osm_physp_t * osm_phys_port,uint8_t port_num,ib_vl_arb_table_t * block,unsigned block_length,unsigned block_num)8087*d6b92ffaSHans Petter Selasky void torus_update_osm_vlarb(void *context, osm_physp_t *osm_phys_port,
8088*d6b92ffaSHans Petter Selasky 			    uint8_t port_num, ib_vl_arb_table_t *block,
8089*d6b92ffaSHans Petter Selasky 			    unsigned block_length, unsigned block_num)
8090*d6b92ffaSHans Petter Selasky {
8091*d6b92ffaSHans Petter Selasky 	osm_node_t *node = osm_physp_get_node_ptr(osm_phys_port);
8092*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx = context;
8093*d6b92ffaSHans Petter Selasky 	struct t_switch *sw = NULL;
8094*d6b92ffaSHans Petter Selasky 	unsigned i, next;
8095*d6b92ffaSHans Petter Selasky 
8096*d6b92ffaSHans Petter Selasky 	if (node->sw) {
8097*d6b92ffaSHans Petter Selasky 		sw = node->sw->priv;
8098*d6b92ffaSHans Petter Selasky 		if (sw && sw->osm_switch != node->sw) {
8099*d6b92ffaSHans Petter Selasky 			osm_log_t *log = &ctx->osm->log;
8100*d6b92ffaSHans Petter Selasky 			guid_t guid;
8101*d6b92ffaSHans Petter Selasky 
8102*d6b92ffaSHans Petter Selasky 			guid = osm_node_get_node_guid(node);
8103*d6b92ffaSHans Petter Selasky 			OSM_LOG(log, OSM_LOG_INFO,
8104*d6b92ffaSHans Petter Selasky 				"Note: osm_switch (GUID 0x%04"PRIx64") "
8105*d6b92ffaSHans Petter Selasky 				"not in torus fabric description\n",
8106*d6b92ffaSHans Petter Selasky 				cl_ntoh64(guid));
8107*d6b92ffaSHans Petter Selasky 			return;
8108*d6b92ffaSHans Petter Selasky 		}
8109*d6b92ffaSHans Petter Selasky 	}
8110*d6b92ffaSHans Petter Selasky 
8111*d6b92ffaSHans Petter Selasky 	/*
8112*d6b92ffaSHans Petter Selasky 	 * If osm_phys_port is a switch port that connects to a CA, then
8113*d6b92ffaSHans Petter Selasky 	 * we're using at most VL 0 (for QoS level 0) and VL 1 (for QoS
8114*d6b92ffaSHans Petter Selasky 	 * level 1).  We've been passed the VLarb values for a switch
8115*d6b92ffaSHans Petter Selasky 	 * external port, so we need to fix them up to avoid unexpected
8116*d6b92ffaSHans Petter Selasky 	 * results depending on how the switch handles VLarb values for
8117*d6b92ffaSHans Petter Selasky 	 * unprogrammed VLs.
8118*d6b92ffaSHans Petter Selasky 	 *
8119*d6b92ffaSHans Petter Selasky 	 * For inter-switch links torus-2QoS uses VLs 0-3 to implement
8120*d6b92ffaSHans Petter Selasky 	 * QoS level 0, and VLs 4-7 to implement QoS level 1.
8121*d6b92ffaSHans Petter Selasky 	 *
8122*d6b92ffaSHans Petter Selasky 	 * So, leave VL 0 alone, remap VL 4 to VL 1, zero out the rest,
8123*d6b92ffaSHans Petter Selasky 	 * and compress out the zero entries to the end.
8124*d6b92ffaSHans Petter Selasky 	 */
8125*d6b92ffaSHans Petter Selasky 	if (!sw || !port_num || !sw->port[port_num] ||
8126*d6b92ffaSHans Petter Selasky 	    sw->port[port_num]->pgrp->port_grp != 2 * TORUS_MAX_DIM)
8127*d6b92ffaSHans Petter Selasky 		return;
8128*d6b92ffaSHans Petter Selasky 
8129*d6b92ffaSHans Petter Selasky 	next = 0;
8130*d6b92ffaSHans Petter Selasky 	for (i = 0; i < block_length; i++) {
8131*d6b92ffaSHans Petter Selasky 		switch (block->vl_entry[i].vl) {
8132*d6b92ffaSHans Petter Selasky 		case 4:
8133*d6b92ffaSHans Petter Selasky 			block->vl_entry[i].vl = 1;
8134*d6b92ffaSHans Petter Selasky 			/* fall through */
8135*d6b92ffaSHans Petter Selasky 		case 0:
8136*d6b92ffaSHans Petter Selasky 			block->vl_entry[next].vl = block->vl_entry[i].vl;
8137*d6b92ffaSHans Petter Selasky 			block->vl_entry[next].weight = block->vl_entry[i].weight;
8138*d6b92ffaSHans Petter Selasky 			next++;
8139*d6b92ffaSHans Petter Selasky 			/*
8140*d6b92ffaSHans Petter Selasky 			 * If we didn't update vl_entry[i] in place,
8141*d6b92ffaSHans Petter Selasky 			 * fall through to zero it out.
8142*d6b92ffaSHans Petter Selasky 			 */
8143*d6b92ffaSHans Petter Selasky 			if (next > i)
8144*d6b92ffaSHans Petter Selasky 				break;
8145*d6b92ffaSHans Petter Selasky 		default:
8146*d6b92ffaSHans Petter Selasky 			block->vl_entry[i].vl = 0;
8147*d6b92ffaSHans Petter Selasky 			block->vl_entry[i].weight = 0;
8148*d6b92ffaSHans Petter Selasky 			break;
8149*d6b92ffaSHans Petter Selasky 		}
8150*d6b92ffaSHans Petter Selasky 	}
8151*d6b92ffaSHans Petter Selasky }
8152*d6b92ffaSHans Petter Selasky 
8153*d6b92ffaSHans Petter Selasky /*
8154*d6b92ffaSHans Petter Selasky  * Computes the path lengths *vl0_len and *vl1_len to get from src
8155*d6b92ffaSHans Petter Selasky  * to dst on a ring with count switches.
8156*d6b92ffaSHans Petter Selasky  *
8157*d6b92ffaSHans Petter Selasky  * *vl0_len is the path length for a direct path; it corresponds to a path
8158*d6b92ffaSHans Petter Selasky  * that should be assigned to use VL0 in a switch.  *vl1_len is the path
8159*d6b92ffaSHans Petter Selasky  * length for a path that wraps aroung the ring, i.e. where the ring index
8160*d6b92ffaSHans Petter Selasky  * goes from count to zero or from zero to count.  It corresponds to the path
8161*d6b92ffaSHans Petter Selasky  * that should be assigned to use VL1 in a switch.
8162*d6b92ffaSHans Petter Selasky  */
8163*d6b92ffaSHans Petter Selasky static
get_pathlen(unsigned src,unsigned dst,unsigned count,unsigned * vl0_len,unsigned * vl1_len)8164*d6b92ffaSHans Petter Selasky void get_pathlen(unsigned src, unsigned dst, unsigned count,
8165*d6b92ffaSHans Petter Selasky 		 unsigned *vl0_len, unsigned *vl1_len)
8166*d6b92ffaSHans Petter Selasky {
8167*d6b92ffaSHans Petter Selasky 	unsigned s, l;		/* assume s < l */
8168*d6b92ffaSHans Petter Selasky 
8169*d6b92ffaSHans Petter Selasky 	if (dst > src) {
8170*d6b92ffaSHans Petter Selasky 		s = src;
8171*d6b92ffaSHans Petter Selasky 		l = dst;
8172*d6b92ffaSHans Petter Selasky 	} else {
8173*d6b92ffaSHans Petter Selasky 		s = dst;
8174*d6b92ffaSHans Petter Selasky 		l = src;
8175*d6b92ffaSHans Petter Selasky 	}
8176*d6b92ffaSHans Petter Selasky 	*vl0_len = l - s;
8177*d6b92ffaSHans Petter Selasky 	*vl1_len = s + count - l;
8178*d6b92ffaSHans Petter Selasky }
8179*d6b92ffaSHans Petter Selasky 
8180*d6b92ffaSHans Petter Selasky /*
8181*d6b92ffaSHans Petter Selasky  * Returns a positive number if we should take the "positive" ring direction
8182*d6b92ffaSHans Petter Selasky  * to reach dst from src, a negative number if we should take the "negative"
8183*d6b92ffaSHans Petter Selasky  * ring direction, and 0 if src and dst are the same.  The choice is strictly
8184*d6b92ffaSHans Petter Selasky  * based on which path is shorter.
8185*d6b92ffaSHans Petter Selasky  */
8186*d6b92ffaSHans Petter Selasky static
ring_dir_idx(unsigned src,unsigned dst,unsigned count)8187*d6b92ffaSHans Petter Selasky int ring_dir_idx(unsigned src, unsigned dst, unsigned count)
8188*d6b92ffaSHans Petter Selasky {
8189*d6b92ffaSHans Petter Selasky 	int r;
8190*d6b92ffaSHans Petter Selasky 	unsigned vl0_len, vl1_len;
8191*d6b92ffaSHans Petter Selasky 
8192*d6b92ffaSHans Petter Selasky 	if (dst == src)
8193*d6b92ffaSHans Petter Selasky 		return 0;
8194*d6b92ffaSHans Petter Selasky 
8195*d6b92ffaSHans Petter Selasky 	get_pathlen(src, dst, count, &vl0_len, &vl1_len);
8196*d6b92ffaSHans Petter Selasky 
8197*d6b92ffaSHans Petter Selasky 	if (dst > src)
8198*d6b92ffaSHans Petter Selasky 		r = vl0_len <= vl1_len ? 1 : -1;
8199*d6b92ffaSHans Petter Selasky 	else
8200*d6b92ffaSHans Petter Selasky 		r = vl0_len <= vl1_len ? -1 : 1;
8201*d6b92ffaSHans Petter Selasky 
8202*d6b92ffaSHans Petter Selasky 	return r;
8203*d6b92ffaSHans Petter Selasky }
8204*d6b92ffaSHans Petter Selasky 
8205*d6b92ffaSHans Petter Selasky /*
8206*d6b92ffaSHans Petter Selasky  * Returns true if the VL1 path should be used to reach src from dst on a
8207*d6b92ffaSHans Petter Selasky  * ring, based on which path is shorter.
8208*d6b92ffaSHans Petter Selasky  */
8209*d6b92ffaSHans Petter Selasky static
use_vl1(unsigned src,unsigned dst,unsigned count)8210*d6b92ffaSHans Petter Selasky bool use_vl1(unsigned src, unsigned dst, unsigned count)
8211*d6b92ffaSHans Petter Selasky {
8212*d6b92ffaSHans Petter Selasky 	unsigned vl0_len, vl1_len;
8213*d6b92ffaSHans Petter Selasky 
8214*d6b92ffaSHans Petter Selasky 	get_pathlen(src, dst, count, &vl0_len, &vl1_len);
8215*d6b92ffaSHans Petter Selasky 
8216*d6b92ffaSHans Petter Selasky 	return vl0_len <= vl1_len ? false : true;
8217*d6b92ffaSHans Petter Selasky }
8218*d6b92ffaSHans Petter Selasky 
8219*d6b92ffaSHans Petter Selasky /*
8220*d6b92ffaSHans Petter Selasky  * Returns the next switch in the ring of switches along coordinate direction
8221*d6b92ffaSHans Petter Selasky  * cdir, in the positive ring direction if rdir is positive, and in the
8222*d6b92ffaSHans Petter Selasky  * negative ring direction if rdir is negative.
8223*d6b92ffaSHans Petter Selasky  *
8224*d6b92ffaSHans Petter Selasky  * Returns NULL if rdir is zero, or there is no next switch.
8225*d6b92ffaSHans Petter Selasky  */
8226*d6b92ffaSHans Petter Selasky static
ring_next_sw(struct t_switch * sw,unsigned cdir,int rdir)8227*d6b92ffaSHans Petter Selasky struct t_switch *ring_next_sw(struct t_switch *sw, unsigned cdir, int rdir)
8228*d6b92ffaSHans Petter Selasky {
8229*d6b92ffaSHans Petter Selasky 	unsigned pt_grp, far_end = 0;
8230*d6b92ffaSHans Petter Selasky 
8231*d6b92ffaSHans Petter Selasky 	if (!rdir)
8232*d6b92ffaSHans Petter Selasky 		return NULL;
8233*d6b92ffaSHans Petter Selasky 	/*
8234*d6b92ffaSHans Petter Selasky 	 * Recall that links are installed into the torus so that their 1 end
8235*d6b92ffaSHans Petter Selasky 	 * is in the "positive" coordinate direction relative to their 0 end
8236*d6b92ffaSHans Petter Selasky 	 * (see link_tswitches() and connect_tlink()).  Recall also that for
8237*d6b92ffaSHans Petter Selasky 	 * interswitch links, all links in a given switch port group have the
8238*d6b92ffaSHans Petter Selasky 	 * same endpoints, so we just need to look at the first link.
8239*d6b92ffaSHans Petter Selasky 	 */
8240*d6b92ffaSHans Petter Selasky 	pt_grp = 2 * cdir;
8241*d6b92ffaSHans Petter Selasky 	if (rdir > 0) {
8242*d6b92ffaSHans Petter Selasky 		pt_grp++;
8243*d6b92ffaSHans Petter Selasky 		far_end = 1;
8244*d6b92ffaSHans Petter Selasky 	}
8245*d6b92ffaSHans Petter Selasky 
8246*d6b92ffaSHans Petter Selasky 	if (!sw->ptgrp[pt_grp].port_cnt)
8247*d6b92ffaSHans Petter Selasky 		return NULL;
8248*d6b92ffaSHans Petter Selasky 
8249*d6b92ffaSHans Petter Selasky 	return sw->ptgrp[pt_grp].port[0]->link->end[far_end].sw;
8250*d6b92ffaSHans Petter Selasky }
8251*d6b92ffaSHans Petter Selasky 
8252*d6b92ffaSHans Petter Selasky /*
8253*d6b92ffaSHans Petter Selasky  * Returns a positive number if we should take the "positive" ring direction
8254*d6b92ffaSHans Petter Selasky  * to reach dsw from ssw, a negative number if we should take the "negative"
8255*d6b92ffaSHans Petter Selasky  * ring direction, and 0 if src and dst are the same, or if dsw is not
8256*d6b92ffaSHans Petter Selasky  * reachable from ssw because the path is interrupted by failure.
8257*d6b92ffaSHans Petter Selasky  */
8258*d6b92ffaSHans Petter Selasky static
ring_dir_path(struct torus * t,unsigned cdir,struct t_switch * ssw,struct t_switch * dsw)8259*d6b92ffaSHans Petter Selasky int ring_dir_path(struct torus *t, unsigned cdir,
8260*d6b92ffaSHans Petter Selasky 		  struct t_switch *ssw, struct t_switch *dsw)
8261*d6b92ffaSHans Petter Selasky {
8262*d6b92ffaSHans Petter Selasky 	int d = 0;
8263*d6b92ffaSHans Petter Selasky 	struct t_switch *sw;
8264*d6b92ffaSHans Petter Selasky 
8265*d6b92ffaSHans Petter Selasky 	switch (cdir) {
8266*d6b92ffaSHans Petter Selasky 	case 0:
8267*d6b92ffaSHans Petter Selasky 		d = ring_dir_idx(ssw->i, dsw->i, t->x_sz);
8268*d6b92ffaSHans Petter Selasky 		break;
8269*d6b92ffaSHans Petter Selasky 	case 1:
8270*d6b92ffaSHans Petter Selasky 		d = ring_dir_idx(ssw->j, dsw->j, t->y_sz);
8271*d6b92ffaSHans Petter Selasky 		break;
8272*d6b92ffaSHans Petter Selasky 	case 2:
8273*d6b92ffaSHans Petter Selasky 		d = ring_dir_idx(ssw->k, dsw->k, t->z_sz);
8274*d6b92ffaSHans Petter Selasky 		break;
8275*d6b92ffaSHans Petter Selasky 	default:
8276*d6b92ffaSHans Petter Selasky 		break;
8277*d6b92ffaSHans Petter Selasky 	}
8278*d6b92ffaSHans Petter Selasky 	if (!d)
8279*d6b92ffaSHans Petter Selasky 		goto out;
8280*d6b92ffaSHans Petter Selasky 
8281*d6b92ffaSHans Petter Selasky 	sw = ssw;
8282*d6b92ffaSHans Petter Selasky 	while (sw) {
8283*d6b92ffaSHans Petter Selasky 		sw = ring_next_sw(sw, cdir, d);
8284*d6b92ffaSHans Petter Selasky 		if (sw == dsw)
8285*d6b92ffaSHans Petter Selasky 			goto out;
8286*d6b92ffaSHans Petter Selasky 	}
8287*d6b92ffaSHans Petter Selasky 	d *= -1;
8288*d6b92ffaSHans Petter Selasky 	sw = ssw;
8289*d6b92ffaSHans Petter Selasky 	while (sw) {
8290*d6b92ffaSHans Petter Selasky 		sw = ring_next_sw(sw, cdir, d);
8291*d6b92ffaSHans Petter Selasky 		if (sw == dsw)
8292*d6b92ffaSHans Petter Selasky 			goto out;
8293*d6b92ffaSHans Petter Selasky 	}
8294*d6b92ffaSHans Petter Selasky 	d = 0;
8295*d6b92ffaSHans Petter Selasky out:
8296*d6b92ffaSHans Petter Selasky 	return d;
8297*d6b92ffaSHans Petter Selasky }
8298*d6b92ffaSHans Petter Selasky 
8299*d6b92ffaSHans Petter Selasky /*
8300*d6b92ffaSHans Petter Selasky  * Returns true, and sets *pt_grp to the port group index to use for the
8301*d6b92ffaSHans Petter Selasky  * next hop, if it is possible to make progress from ssw to dsw along the
8302*d6b92ffaSHans Petter Selasky  * coordinate direction cdir, taking into account whether there are
8303*d6b92ffaSHans Petter Selasky  * interruptions in the path.
8304*d6b92ffaSHans Petter Selasky  *
8305*d6b92ffaSHans Petter Selasky  * This next hop result can be used without worrying about ring deadlocks -
8306*d6b92ffaSHans Petter Selasky  * if we don't choose the shortest path it is because there is a failure in
8307*d6b92ffaSHans Petter Selasky  * the ring, which removes the possibilility of a ring deadlock on that ring.
8308*d6b92ffaSHans Petter Selasky  */
8309*d6b92ffaSHans Petter Selasky static
next_hop_path(struct torus * t,unsigned cdir,struct t_switch * ssw,struct t_switch * dsw,unsigned * pt_grp)8310*d6b92ffaSHans Petter Selasky bool next_hop_path(struct torus *t, unsigned cdir,
8311*d6b92ffaSHans Petter Selasky 		   struct t_switch *ssw, struct t_switch *dsw,
8312*d6b92ffaSHans Petter Selasky 		   unsigned *pt_grp)
8313*d6b92ffaSHans Petter Selasky {
8314*d6b92ffaSHans Petter Selasky 	struct t_switch *tsw = NULL;
8315*d6b92ffaSHans Petter Selasky 	bool success = false;
8316*d6b92ffaSHans Petter Selasky 	int d;
8317*d6b92ffaSHans Petter Selasky 
8318*d6b92ffaSHans Petter Selasky 	/*
8319*d6b92ffaSHans Petter Selasky 	 * If the path from ssw to dsw turns, this is the switch where the
8320*d6b92ffaSHans Petter Selasky 	 * turn happens.
8321*d6b92ffaSHans Petter Selasky 	 */
8322*d6b92ffaSHans Petter Selasky 	switch (cdir) {
8323*d6b92ffaSHans Petter Selasky 	case 0:
8324*d6b92ffaSHans Petter Selasky 		tsw = t->sw[dsw->i][ssw->j][ssw->k];
8325*d6b92ffaSHans Petter Selasky 		break;
8326*d6b92ffaSHans Petter Selasky 	case 1:
8327*d6b92ffaSHans Petter Selasky 		tsw = t->sw[ssw->i][dsw->j][ssw->k];
8328*d6b92ffaSHans Petter Selasky 		break;
8329*d6b92ffaSHans Petter Selasky 	case 2:
8330*d6b92ffaSHans Petter Selasky 		tsw = t->sw[ssw->i][ssw->j][dsw->k];
8331*d6b92ffaSHans Petter Selasky 		break;
8332*d6b92ffaSHans Petter Selasky 	default:
8333*d6b92ffaSHans Petter Selasky 		goto out;
8334*d6b92ffaSHans Petter Selasky 	}
8335*d6b92ffaSHans Petter Selasky 	if (tsw) {
8336*d6b92ffaSHans Petter Selasky 		d = ring_dir_path(t, cdir, ssw, tsw);
8337*d6b92ffaSHans Petter Selasky 		cdir *= 2;
8338*d6b92ffaSHans Petter Selasky 		if (d > 0)
8339*d6b92ffaSHans Petter Selasky 			*pt_grp = cdir + 1;
8340*d6b92ffaSHans Petter Selasky 		else if (d < 0)
8341*d6b92ffaSHans Petter Selasky 			*pt_grp = cdir;
8342*d6b92ffaSHans Petter Selasky 		else
8343*d6b92ffaSHans Petter Selasky 			goto out;
8344*d6b92ffaSHans Petter Selasky 		success = true;
8345*d6b92ffaSHans Petter Selasky 	}
8346*d6b92ffaSHans Petter Selasky out:
8347*d6b92ffaSHans Petter Selasky 	return success;
8348*d6b92ffaSHans Petter Selasky }
8349*d6b92ffaSHans Petter Selasky 
8350*d6b92ffaSHans Petter Selasky /*
8351*d6b92ffaSHans Petter Selasky  * Returns true, and sets *pt_grp to the port group index to use for the
8352*d6b92ffaSHans Petter Selasky  * next hop, if it is possible to make progress from ssw to dsw along the
8353*d6b92ffaSHans Petter Selasky  * coordinate direction cdir.  This decision is made strictly on a
8354*d6b92ffaSHans Petter Selasky  * shortest-path basis without regard for path availability.
8355*d6b92ffaSHans Petter Selasky  */
8356*d6b92ffaSHans Petter Selasky static
next_hop_idx(struct torus * t,unsigned cdir,struct t_switch * ssw,struct t_switch * dsw,unsigned * pt_grp)8357*d6b92ffaSHans Petter Selasky bool next_hop_idx(struct torus *t, unsigned cdir,
8358*d6b92ffaSHans Petter Selasky 		  struct t_switch *ssw, struct t_switch *dsw,
8359*d6b92ffaSHans Petter Selasky 		  unsigned *pt_grp)
8360*d6b92ffaSHans Petter Selasky {
8361*d6b92ffaSHans Petter Selasky 	int d;
8362*d6b92ffaSHans Petter Selasky 	unsigned g;
8363*d6b92ffaSHans Petter Selasky 	bool success = false;
8364*d6b92ffaSHans Petter Selasky 
8365*d6b92ffaSHans Petter Selasky 	switch (cdir) {
8366*d6b92ffaSHans Petter Selasky 	case 0:
8367*d6b92ffaSHans Petter Selasky 		d = ring_dir_idx(ssw->i, dsw->i, t->x_sz);
8368*d6b92ffaSHans Petter Selasky 		break;
8369*d6b92ffaSHans Petter Selasky 	case 1:
8370*d6b92ffaSHans Petter Selasky 		d = ring_dir_idx(ssw->j, dsw->j, t->y_sz);
8371*d6b92ffaSHans Petter Selasky 		break;
8372*d6b92ffaSHans Petter Selasky 	case 2:
8373*d6b92ffaSHans Petter Selasky 		d = ring_dir_idx(ssw->k, dsw->k, t->z_sz);
8374*d6b92ffaSHans Petter Selasky 		break;
8375*d6b92ffaSHans Petter Selasky 	default:
8376*d6b92ffaSHans Petter Selasky 		goto out;
8377*d6b92ffaSHans Petter Selasky 	}
8378*d6b92ffaSHans Petter Selasky 
8379*d6b92ffaSHans Petter Selasky 	cdir *= 2;
8380*d6b92ffaSHans Petter Selasky 	if (d > 0)
8381*d6b92ffaSHans Petter Selasky 		g = cdir + 1;
8382*d6b92ffaSHans Petter Selasky 	else if (d < 0)
8383*d6b92ffaSHans Petter Selasky 		g = cdir;
8384*d6b92ffaSHans Petter Selasky 	else
8385*d6b92ffaSHans Petter Selasky 		goto out;
8386*d6b92ffaSHans Petter Selasky 
8387*d6b92ffaSHans Petter Selasky 	if (!ssw->ptgrp[g].port_cnt)
8388*d6b92ffaSHans Petter Selasky 		goto out;
8389*d6b92ffaSHans Petter Selasky 
8390*d6b92ffaSHans Petter Selasky 	*pt_grp = g;
8391*d6b92ffaSHans Petter Selasky 	success = true;
8392*d6b92ffaSHans Petter Selasky out:
8393*d6b92ffaSHans Petter Selasky 	return success;
8394*d6b92ffaSHans Petter Selasky }
8395*d6b92ffaSHans Petter Selasky 
8396*d6b92ffaSHans Petter Selasky static
warn_on_routing(const char * msg,struct t_switch * sw,struct t_switch * dsw)8397*d6b92ffaSHans Petter Selasky void warn_on_routing(const char *msg,
8398*d6b92ffaSHans Petter Selasky 		     struct t_switch *sw, struct t_switch *dsw)
8399*d6b92ffaSHans Petter Selasky {
8400*d6b92ffaSHans Petter Selasky 	OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR,
8401*d6b92ffaSHans Petter Selasky 		"%s from sw 0x%04"PRIx64" (%d,%d,%d) "
8402*d6b92ffaSHans Petter Selasky 		"to sw 0x%04"PRIx64" (%d,%d,%d)\n",
8403*d6b92ffaSHans Petter Selasky 		msg, cl_ntoh64(sw->n_id), sw->i, sw->j, sw->k,
8404*d6b92ffaSHans Petter Selasky 		cl_ntoh64(dsw->n_id), dsw->i, dsw->j, dsw->k);
8405*d6b92ffaSHans Petter Selasky }
8406*d6b92ffaSHans Petter Selasky 
8407*d6b92ffaSHans Petter Selasky static
next_hop_x(struct torus * t,struct t_switch * ssw,struct t_switch * dsw,unsigned * pt_grp)8408*d6b92ffaSHans Petter Selasky bool next_hop_x(struct torus *t,
8409*d6b92ffaSHans Petter Selasky 		struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp)
8410*d6b92ffaSHans Petter Selasky {
8411*d6b92ffaSHans Petter Selasky 	if (t->sw[dsw->i][ssw->j][ssw->k])
8412*d6b92ffaSHans Petter Selasky 		/*
8413*d6b92ffaSHans Petter Selasky 		 * The next turning switch on this path is available,
8414*d6b92ffaSHans Petter Selasky 		 * so head towards it by the shortest available path.
8415*d6b92ffaSHans Petter Selasky 		 */
8416*d6b92ffaSHans Petter Selasky 		return next_hop_path(t, 0, ssw, dsw, pt_grp);
8417*d6b92ffaSHans Petter Selasky 	else
8418*d6b92ffaSHans Petter Selasky 		/*
8419*d6b92ffaSHans Petter Selasky 		 * The next turning switch on this path is not
8420*d6b92ffaSHans Petter Selasky 		 * available, so head towards it in the shortest
8421*d6b92ffaSHans Petter Selasky 		 * path direction.
8422*d6b92ffaSHans Petter Selasky 		 */
8423*d6b92ffaSHans Petter Selasky 		return next_hop_idx(t, 0, ssw, dsw, pt_grp);
8424*d6b92ffaSHans Petter Selasky }
8425*d6b92ffaSHans Petter Selasky 
8426*d6b92ffaSHans Petter Selasky static
next_hop_y(struct torus * t,struct t_switch * ssw,struct t_switch * dsw,unsigned * pt_grp)8427*d6b92ffaSHans Petter Selasky bool next_hop_y(struct torus *t,
8428*d6b92ffaSHans Petter Selasky 		struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp)
8429*d6b92ffaSHans Petter Selasky {
8430*d6b92ffaSHans Petter Selasky 	if (t->sw[ssw->i][dsw->j][ssw->k])
8431*d6b92ffaSHans Petter Selasky 		/*
8432*d6b92ffaSHans Petter Selasky 		 * The next turning switch on this path is available,
8433*d6b92ffaSHans Petter Selasky 		 * so head towards it by the shortest available path.
8434*d6b92ffaSHans Petter Selasky 		 */
8435*d6b92ffaSHans Petter Selasky 		return next_hop_path(t, 1, ssw, dsw, pt_grp);
8436*d6b92ffaSHans Petter Selasky 	else
8437*d6b92ffaSHans Petter Selasky 		/*
8438*d6b92ffaSHans Petter Selasky 		 * The next turning switch on this path is not
8439*d6b92ffaSHans Petter Selasky 		 * available, so head towards it in the shortest
8440*d6b92ffaSHans Petter Selasky 		 * path direction.
8441*d6b92ffaSHans Petter Selasky 		 */
8442*d6b92ffaSHans Petter Selasky 		return next_hop_idx(t, 1, ssw, dsw, pt_grp);
8443*d6b92ffaSHans Petter Selasky }
8444*d6b92ffaSHans Petter Selasky 
8445*d6b92ffaSHans Petter Selasky static
next_hop_z(struct torus * t,struct t_switch * ssw,struct t_switch * dsw,unsigned * pt_grp)8446*d6b92ffaSHans Petter Selasky bool next_hop_z(struct torus *t,
8447*d6b92ffaSHans Petter Selasky 		struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp)
8448*d6b92ffaSHans Petter Selasky {
8449*d6b92ffaSHans Petter Selasky 	return next_hop_path(t, 2, ssw, dsw, pt_grp);
8450*d6b92ffaSHans Petter Selasky }
8451*d6b92ffaSHans Petter Selasky 
8452*d6b92ffaSHans Petter Selasky /*
8453*d6b92ffaSHans Petter Selasky  * Returns the port number on *sw to use to reach *dsw, or -1 if unable to
8454*d6b92ffaSHans Petter Selasky  * route.
8455*d6b92ffaSHans Petter Selasky  */
8456*d6b92ffaSHans Petter Selasky static
lft_port(struct torus * t,struct t_switch * sw,struct t_switch * dsw,bool update_port_cnt,bool ca)8457*d6b92ffaSHans Petter Selasky int lft_port(struct torus *t,
8458*d6b92ffaSHans Petter Selasky 	     struct t_switch *sw, struct t_switch *dsw,
8459*d6b92ffaSHans Petter Selasky 	     bool update_port_cnt, bool ca)
8460*d6b92ffaSHans Petter Selasky {
8461*d6b92ffaSHans Petter Selasky 	unsigned g, p;
8462*d6b92ffaSHans Petter Selasky 	struct port_grp *pg;
8463*d6b92ffaSHans Petter Selasky 
8464*d6b92ffaSHans Petter Selasky 	/*
8465*d6b92ffaSHans Petter Selasky 	 * The IBA does not provide a way to preserve path history for
8466*d6b92ffaSHans Petter Selasky 	 * routing decisions and VL assignment, and the only mechanism to
8467*d6b92ffaSHans Petter Selasky 	 * provide global fabric knowledge to the routing engine is via
8468*d6b92ffaSHans Petter Selasky 	 * the four SL bits.  This severely constrains the ability to deal
8469*d6b92ffaSHans Petter Selasky 	 * with missing/dead switches.
8470*d6b92ffaSHans Petter Selasky 	 *
8471*d6b92ffaSHans Petter Selasky 	 * Also, if routing a torus with XYZ-DOR, the only way to route
8472*d6b92ffaSHans Petter Selasky 	 * around a missing/dead switch is to introduce a turn that is
8473*d6b92ffaSHans Petter Selasky 	 * illegal under XYZ-DOR.
8474*d6b92ffaSHans Petter Selasky 	 *
8475*d6b92ffaSHans Petter Selasky 	 * But here's what we can do:
8476*d6b92ffaSHans Petter Selasky 	 *
8477*d6b92ffaSHans Petter Selasky 	 * We have a VL bit we use to flag illegal turns, thus putting the
8478*d6b92ffaSHans Petter Selasky 	 * hop directly after an illegal turn on a separate set of VLs.
8479*d6b92ffaSHans Petter Selasky 	 * Unfortunately, since there is no path history,  the _second_
8480*d6b92ffaSHans Petter Selasky 	 * and subsequent hops after an illegal turn use the standard
8481*d6b92ffaSHans Petter Selasky 	 * XYZ-DOR VL set.  This is enough to introduce credit loops in
8482*d6b92ffaSHans Petter Selasky 	 * many cases.
8483*d6b92ffaSHans Petter Selasky 	 *
8484*d6b92ffaSHans Petter Selasky 	 * To minimize the number of cases such illegal turns can introduce
8485*d6b92ffaSHans Petter Selasky 	 * credit loops, we try to introduce the illegal turn as late in a
8486*d6b92ffaSHans Petter Selasky 	 * path as possible.
8487*d6b92ffaSHans Petter Selasky 	 *
8488*d6b92ffaSHans Petter Selasky 	 * Define a turning switch as a switch where a path turns from one
8489*d6b92ffaSHans Petter Selasky 	 * coordinate direction onto another.  If a turning switch in a path
8490*d6b92ffaSHans Petter Selasky 	 * is missing, construct the LFT entries so that the path progresses
8491*d6b92ffaSHans Petter Selasky 	 * as far as possible on the shortest path to the turning switch.
8492*d6b92ffaSHans Petter Selasky 	 * When progress is not possible, turn onto the next coordinate
8493*d6b92ffaSHans Petter Selasky 	 * direction.
8494*d6b92ffaSHans Petter Selasky 	 *
8495*d6b92ffaSHans Petter Selasky 	 * The next turn after that will be an illegal turn, after which
8496*d6b92ffaSHans Petter Selasky 	 * point the path will continue to use a standard XYZ-DOR path.
8497*d6b92ffaSHans Petter Selasky 	 */
8498*d6b92ffaSHans Petter Selasky 	if (dsw->i != sw->i) {
8499*d6b92ffaSHans Petter Selasky 
8500*d6b92ffaSHans Petter Selasky 		if (next_hop_x(t, sw, dsw, &g))
8501*d6b92ffaSHans Petter Selasky 			goto done;
8502*d6b92ffaSHans Petter Selasky 		/*
8503*d6b92ffaSHans Petter Selasky 		 * This path has made as much progress in this direction as
8504*d6b92ffaSHans Petter Selasky 		 * is possible, so turn it now.
8505*d6b92ffaSHans Petter Selasky 		 */
8506*d6b92ffaSHans Petter Selasky 		if (dsw->j != sw->j && next_hop_y(t, sw, dsw, &g))
8507*d6b92ffaSHans Petter Selasky 			goto done;
8508*d6b92ffaSHans Petter Selasky 
8509*d6b92ffaSHans Petter Selasky 		if (dsw->k != sw->k && next_hop_z(t, sw, dsw, &g))
8510*d6b92ffaSHans Petter Selasky 			goto done;
8511*d6b92ffaSHans Petter Selasky 
8512*d6b92ffaSHans Petter Selasky 		warn_on_routing("Error: unable to route", sw, dsw);
8513*d6b92ffaSHans Petter Selasky 		goto no_route;
8514*d6b92ffaSHans Petter Selasky 	} else if (dsw->j != sw->j) {
8515*d6b92ffaSHans Petter Selasky 
8516*d6b92ffaSHans Petter Selasky 		if (next_hop_y(t, sw, dsw, &g))
8517*d6b92ffaSHans Petter Selasky 			goto done;
8518*d6b92ffaSHans Petter Selasky 
8519*d6b92ffaSHans Petter Selasky 		if (dsw->k != sw->k && next_hop_z(t, sw, dsw, &g))
8520*d6b92ffaSHans Petter Selasky 			goto done;
8521*d6b92ffaSHans Petter Selasky 
8522*d6b92ffaSHans Petter Selasky 		warn_on_routing("Error: unable to route", sw, dsw);
8523*d6b92ffaSHans Petter Selasky 		goto no_route;
8524*d6b92ffaSHans Petter Selasky 	} else {
8525*d6b92ffaSHans Petter Selasky 		if (dsw->k == sw->k)
8526*d6b92ffaSHans Petter Selasky 			warn_on_routing("Warning: bad routing", sw, dsw);
8527*d6b92ffaSHans Petter Selasky 
8528*d6b92ffaSHans Petter Selasky 		if (next_hop_z(t, sw, dsw, &g))
8529*d6b92ffaSHans Petter Selasky 			goto done;
8530*d6b92ffaSHans Petter Selasky 
8531*d6b92ffaSHans Petter Selasky 		warn_on_routing("Error: unable to route", sw, dsw);
8532*d6b92ffaSHans Petter Selasky 		goto no_route;
8533*d6b92ffaSHans Petter Selasky 	}
8534*d6b92ffaSHans Petter Selasky done:
8535*d6b92ffaSHans Petter Selasky 	pg = &sw->ptgrp[g];
8536*d6b92ffaSHans Petter Selasky 	if (!pg->port_cnt)
8537*d6b92ffaSHans Petter Selasky 		goto no_route;
8538*d6b92ffaSHans Petter Selasky 
8539*d6b92ffaSHans Petter Selasky 	if (update_port_cnt) {
8540*d6b92ffaSHans Petter Selasky 		if (ca)
8541*d6b92ffaSHans Petter Selasky 			p = pg->ca_dlid_cnt++ % pg->port_cnt;
8542*d6b92ffaSHans Petter Selasky 		else
8543*d6b92ffaSHans Petter Selasky 			p = pg->sw_dlid_cnt++ % pg->port_cnt;
8544*d6b92ffaSHans Petter Selasky 	} else {
8545*d6b92ffaSHans Petter Selasky 		/*
8546*d6b92ffaSHans Petter Selasky 		 * If we're not updating port counts, then we're just running
8547*d6b92ffaSHans Petter Selasky 		 * routes for SL path checking, and it doesn't matter which
8548*d6b92ffaSHans Petter Selasky 		 * of several parallel links we use.  Use the first one.
8549*d6b92ffaSHans Petter Selasky 		 */
8550*d6b92ffaSHans Petter Selasky 		p = 0;
8551*d6b92ffaSHans Petter Selasky 	}
8552*d6b92ffaSHans Petter Selasky 	p = pg->port[p]->port;
8553*d6b92ffaSHans Petter Selasky 
8554*d6b92ffaSHans Petter Selasky 	return p;
8555*d6b92ffaSHans Petter Selasky 
8556*d6b92ffaSHans Petter Selasky no_route:
8557*d6b92ffaSHans Petter Selasky 	/*
8558*d6b92ffaSHans Petter Selasky 	 * We can't get there from here.
8559*d6b92ffaSHans Petter Selasky 	 */
8560*d6b92ffaSHans Petter Selasky 	OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
8561*d6b92ffaSHans Petter Selasky 		"ERR 4E39: routing on sw 0x%04"PRIx64": sending "
8562*d6b92ffaSHans Petter Selasky 		"traffic for dest sw 0x%04"PRIx64" to port %u\n",
8563*d6b92ffaSHans Petter Selasky 		cl_ntoh64(sw->n_id), cl_ntoh64(dsw->n_id), OSM_NO_PATH);
8564*d6b92ffaSHans Petter Selasky 	return -1;
8565*d6b92ffaSHans Petter Selasky }
8566*d6b92ffaSHans Petter Selasky 
8567*d6b92ffaSHans Petter Selasky static
get_lid(struct port_grp * pg,unsigned p,uint16_t * dlid_base,uint8_t * dlid_lmc,bool * ca)8568*d6b92ffaSHans Petter Selasky bool get_lid(struct port_grp *pg, unsigned p,
8569*d6b92ffaSHans Petter Selasky 	     uint16_t *dlid_base, uint8_t *dlid_lmc, bool *ca)
8570*d6b92ffaSHans Petter Selasky {
8571*d6b92ffaSHans Petter Selasky 	struct endpoint *ep;
8572*d6b92ffaSHans Petter Selasky 	osm_port_t *osm_port;
8573*d6b92ffaSHans Petter Selasky 
8574*d6b92ffaSHans Petter Selasky 	if (p >= pg->port_cnt) {
8575*d6b92ffaSHans Petter Selasky 		OSM_LOG(&pg->sw->torus->osm->log, OSM_LOG_ERROR,
8576*d6b92ffaSHans Petter Selasky 			"ERR 4E3A: Port group index %u too large: sw "
8577*d6b92ffaSHans Petter Selasky 			"0x%04"PRIx64" pt_grp %u pt_grp_cnt %u\n",
8578*d6b92ffaSHans Petter Selasky 			p, cl_ntoh64(pg->sw->n_id),
8579*d6b92ffaSHans Petter Selasky 			(unsigned)pg->port_grp, (unsigned)pg->port_cnt);
8580*d6b92ffaSHans Petter Selasky 		return false;
8581*d6b92ffaSHans Petter Selasky 	}
8582*d6b92ffaSHans Petter Selasky 	if (pg->port[p]->type == SRCSINK) {
8583*d6b92ffaSHans Petter Selasky 		ep = pg->port[p];
8584*d6b92ffaSHans Petter Selasky 		if (ca)
8585*d6b92ffaSHans Petter Selasky 			*ca = false;
8586*d6b92ffaSHans Petter Selasky 	} else if (pg->port[p]->type == PASSTHRU &&
8587*d6b92ffaSHans Petter Selasky 		   pg->port[p]->link->end[1].type == SRCSINK) {
8588*d6b92ffaSHans Petter Selasky 		/*
8589*d6b92ffaSHans Petter Selasky 		 * If this port is connected via a link to a CA, then we
8590*d6b92ffaSHans Petter Selasky 		 * know link->end[0] is the switch end and link->end[1] is
8591*d6b92ffaSHans Petter Selasky 		 * the CA end; see build_ca_link() and link_srcsink().
8592*d6b92ffaSHans Petter Selasky 		 */
8593*d6b92ffaSHans Petter Selasky 		ep = &pg->port[p]->link->end[1];
8594*d6b92ffaSHans Petter Selasky 		if (ca)
8595*d6b92ffaSHans Petter Selasky 			*ca = true;
8596*d6b92ffaSHans Petter Selasky 	} else {
8597*d6b92ffaSHans Petter Selasky 		OSM_LOG(&pg->sw->torus->osm->log, OSM_LOG_ERROR,
8598*d6b92ffaSHans Petter Selasky 			"ERR 4E3B: Switch 0x%04"PRIx64" port %d improperly connected\n",
8599*d6b92ffaSHans Petter Selasky 			cl_ntoh64(pg->sw->n_id), pg->port[p]->port);
8600*d6b92ffaSHans Petter Selasky 		return false;
8601*d6b92ffaSHans Petter Selasky 	}
8602*d6b92ffaSHans Petter Selasky 	osm_port = ep->osm_port;
8603*d6b92ffaSHans Petter Selasky 	if (!(osm_port && osm_port->priv == ep)) {
8604*d6b92ffaSHans Petter Selasky 		OSM_LOG(&pg->sw->torus->osm->log, OSM_LOG_ERROR,
8605*d6b92ffaSHans Petter Selasky 			"ERR 4E3C: ep->osm_port->priv != ep "
8606*d6b92ffaSHans Petter Selasky 			"for sw 0x%04"PRIx64" port %d\n",
8607*d6b92ffaSHans Petter Selasky 			cl_ntoh64(((struct t_switch *)(ep->sw))->n_id), ep->port);
8608*d6b92ffaSHans Petter Selasky 		return false;
8609*d6b92ffaSHans Petter Selasky 	}
8610*d6b92ffaSHans Petter Selasky 	*dlid_base = cl_ntoh16(osm_physp_get_base_lid(osm_port->p_physp));
8611*d6b92ffaSHans Petter Selasky 	*dlid_lmc = osm_physp_get_lmc(osm_port->p_physp);
8612*d6b92ffaSHans Petter Selasky 
8613*d6b92ffaSHans Petter Selasky 	return true;
8614*d6b92ffaSHans Petter Selasky }
8615*d6b92ffaSHans Petter Selasky 
8616*d6b92ffaSHans Petter Selasky static
torus_lft(struct torus * t,struct t_switch * sw)8617*d6b92ffaSHans Petter Selasky bool torus_lft(struct torus *t, struct t_switch *sw)
8618*d6b92ffaSHans Petter Selasky {
8619*d6b92ffaSHans Petter Selasky 	bool success = true;
8620*d6b92ffaSHans Petter Selasky 	int dp;
8621*d6b92ffaSHans Petter Selasky 	unsigned p, s;
8622*d6b92ffaSHans Petter Selasky 	uint16_t l, dlid_base;
8623*d6b92ffaSHans Petter Selasky 	uint8_t dlid_lmc;
8624*d6b92ffaSHans Petter Selasky 	bool ca;
8625*d6b92ffaSHans Petter Selasky 	struct port_grp *pgrp;
8626*d6b92ffaSHans Petter Selasky 	struct t_switch *dsw;
8627*d6b92ffaSHans Petter Selasky 	osm_switch_t *osm_sw;
8628*d6b92ffaSHans Petter Selasky 	uint8_t order[IB_NODE_NUM_PORTS_MAX+1];
8629*d6b92ffaSHans Petter Selasky 
8630*d6b92ffaSHans Petter Selasky 	if (!(sw->osm_switch && sw->osm_switch->priv == sw)) {
8631*d6b92ffaSHans Petter Selasky 		OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
8632*d6b92ffaSHans Petter Selasky 			"ERR 4E3D: sw->osm_switch->priv != sw "
8633*d6b92ffaSHans Petter Selasky 			"for sw 0x%04"PRIx64"\n", cl_ntoh64(sw->n_id));
8634*d6b92ffaSHans Petter Selasky 		return false;
8635*d6b92ffaSHans Petter Selasky 	}
8636*d6b92ffaSHans Petter Selasky 	osm_sw = sw->osm_switch;
8637*d6b92ffaSHans Petter Selasky 	memset(osm_sw->new_lft, OSM_NO_PATH, osm_sw->lft_size);
8638*d6b92ffaSHans Petter Selasky 
8639*d6b92ffaSHans Petter Selasky 	for (s = 0; s < t->switch_cnt; s++) {
8640*d6b92ffaSHans Petter Selasky 
8641*d6b92ffaSHans Petter Selasky 		dsw = t->sw_pool[s];
8642*d6b92ffaSHans Petter Selasky 		pgrp = &dsw->ptgrp[2 * TORUS_MAX_DIM];
8643*d6b92ffaSHans Petter Selasky 
8644*d6b92ffaSHans Petter Selasky 		memset(order, IB_INVALID_PORT_NUM, sizeof(order));
8645*d6b92ffaSHans Petter Selasky 		for (p = 0; p < pgrp->port_cnt; p++)
8646*d6b92ffaSHans Petter Selasky 			order[pgrp->port[p]->port] = p;
8647*d6b92ffaSHans Petter Selasky 
8648*d6b92ffaSHans Petter Selasky 		for (p = 0; p < ARRAY_SIZE(order); p++) {
8649*d6b92ffaSHans Petter Selasky 
8650*d6b92ffaSHans Petter Selasky 			uint8_t px = order[t->port_order[p]];
8651*d6b92ffaSHans Petter Selasky 
8652*d6b92ffaSHans Petter Selasky 			if (px == IB_INVALID_PORT_NUM)
8653*d6b92ffaSHans Petter Selasky 				continue;
8654*d6b92ffaSHans Petter Selasky 
8655*d6b92ffaSHans Petter Selasky 			if (!get_lid(pgrp, px, &dlid_base, &dlid_lmc, &ca))
8656*d6b92ffaSHans Petter Selasky 				return false;
8657*d6b92ffaSHans Petter Selasky 
8658*d6b92ffaSHans Petter Selasky 			if (sw->n_id == dsw->n_id)
8659*d6b92ffaSHans Petter Selasky 				dp = pgrp->port[px]->port;
8660*d6b92ffaSHans Petter Selasky 			else
8661*d6b92ffaSHans Petter Selasky 				dp = lft_port(t, sw, dsw, true, ca);
8662*d6b92ffaSHans Petter Selasky 			/*
8663*d6b92ffaSHans Petter Selasky 			 * LMC > 0 doesn't really make sense for torus-2QoS.
8664*d6b92ffaSHans Petter Selasky 			 * So, just make sure traffic gets delivered if
8665*d6b92ffaSHans Petter Selasky 			 * non-zero LMC is used.
8666*d6b92ffaSHans Petter Selasky 			 */
8667*d6b92ffaSHans Petter Selasky 			if (dp >= 0)
8668*d6b92ffaSHans Petter Selasky 				for (l = 0; l < (1U << dlid_lmc); l++)
8669*d6b92ffaSHans Petter Selasky 					osm_sw->new_lft[dlid_base + l] = dp;
8670*d6b92ffaSHans Petter Selasky 			else
8671*d6b92ffaSHans Petter Selasky 				success = false;
8672*d6b92ffaSHans Petter Selasky 		}
8673*d6b92ffaSHans Petter Selasky 	}
8674*d6b92ffaSHans Petter Selasky 	return success;
8675*d6b92ffaSHans Petter Selasky }
8676*d6b92ffaSHans Petter Selasky 
8677*d6b92ffaSHans Petter Selasky static
mcast_stree_branch(struct t_switch * sw,osm_switch_t * osm_sw,osm_mgrp_box_t * mgb,unsigned depth,unsigned * port_cnt,unsigned * max_depth)8678*d6b92ffaSHans Petter Selasky osm_mtree_node_t *mcast_stree_branch(struct t_switch *sw, osm_switch_t *osm_sw,
8679*d6b92ffaSHans Petter Selasky 				     osm_mgrp_box_t *mgb, unsigned depth,
8680*d6b92ffaSHans Petter Selasky 				     unsigned *port_cnt, unsigned *max_depth)
8681*d6b92ffaSHans Petter Selasky {
8682*d6b92ffaSHans Petter Selasky 	osm_mtree_node_t *mtn = NULL;
8683*d6b92ffaSHans Petter Selasky 	osm_mcast_tbl_t *mcast_tbl, *ds_mcast_tbl;
8684*d6b92ffaSHans Petter Selasky 	osm_node_t *ds_node;
8685*d6b92ffaSHans Petter Selasky 	struct t_switch *ds_sw;
8686*d6b92ffaSHans Petter Selasky 	struct port_grp *ptgrp;
8687*d6b92ffaSHans Petter Selasky 	struct link *link;
8688*d6b92ffaSHans Petter Selasky 	struct endpoint *port;
8689*d6b92ffaSHans Petter Selasky 	unsigned g, p;
8690*d6b92ffaSHans Petter Selasky 	unsigned mcast_fwd_ports = 0, mcast_end_ports = 0;
8691*d6b92ffaSHans Petter Selasky 
8692*d6b92ffaSHans Petter Selasky 	depth++;
8693*d6b92ffaSHans Petter Selasky 
8694*d6b92ffaSHans Petter Selasky 	if (osm_sw->priv != sw) {
8695*d6b92ffaSHans Petter Selasky 		OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR,
8696*d6b92ffaSHans Petter Selasky 			"ERR 4E3E: osm_sw (GUID 0x%04"PRIx64") "
8697*d6b92ffaSHans Petter Selasky 			"not in torus fabric description\n",
8698*d6b92ffaSHans Petter Selasky 			cl_ntoh64(osm_node_get_node_guid(osm_sw->p_node)));
8699*d6b92ffaSHans Petter Selasky 		goto out;
8700*d6b92ffaSHans Petter Selasky 	}
8701*d6b92ffaSHans Petter Selasky 	if (!osm_switch_supports_mcast(osm_sw)) {
8702*d6b92ffaSHans Petter Selasky 		OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR,
8703*d6b92ffaSHans Petter Selasky 			"ERR 4E3F: osm_sw (GUID 0x%04"PRIx64") "
8704*d6b92ffaSHans Petter Selasky 			"does not support multicast\n",
8705*d6b92ffaSHans Petter Selasky 			cl_ntoh64(osm_node_get_node_guid(osm_sw->p_node)));
8706*d6b92ffaSHans Petter Selasky 		goto out;
8707*d6b92ffaSHans Petter Selasky 	}
8708*d6b92ffaSHans Petter Selasky 	mtn = osm_mtree_node_new(osm_sw);
8709*d6b92ffaSHans Petter Selasky 	if (!mtn) {
8710*d6b92ffaSHans Petter Selasky 		OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR,
8711*d6b92ffaSHans Petter Selasky 			"ERR 4E46: Insufficient memory to build multicast tree\n");
8712*d6b92ffaSHans Petter Selasky 		goto out;
8713*d6b92ffaSHans Petter Selasky 	}
8714*d6b92ffaSHans Petter Selasky 	mcast_tbl = osm_switch_get_mcast_tbl_ptr(osm_sw);
8715*d6b92ffaSHans Petter Selasky 	/*
8716*d6b92ffaSHans Petter Selasky 	 * Recurse to downstream switches, i.e. those closer to master
8717*d6b92ffaSHans Petter Selasky 	 * spanning tree branch tips.
8718*d6b92ffaSHans Petter Selasky 	 *
8719*d6b92ffaSHans Petter Selasky 	 * Note that if there are multiple ports in this port group, i.e.,
8720*d6b92ffaSHans Petter Selasky 	 * multiple parallel links, we can pick any one of them to use for
8721*d6b92ffaSHans Petter Selasky 	 * any individual MLID without causing loops.  Pick one based on MLID
8722*d6b92ffaSHans Petter Selasky 	 * for now, until someone turns up evidence we need to be smarter.
8723*d6b92ffaSHans Petter Selasky 	 *
8724*d6b92ffaSHans Petter Selasky 	 * Also, it might be we got called in a window between a switch getting
8725*d6b92ffaSHans Petter Selasky 	 * removed from the fabric, and torus-2QoS getting to rebuild its
8726*d6b92ffaSHans Petter Selasky 	 * fabric representation.  If that were to happen, our next hop
8727*d6b92ffaSHans Petter Selasky 	 * osm_switch pointer might be stale.  Look it up via opensm's fabric
8728*d6b92ffaSHans Petter Selasky 	 * description to be sure it's not.
8729*d6b92ffaSHans Petter Selasky 	 */
8730*d6b92ffaSHans Petter Selasky 	for (g = 0; g < 2 * TORUS_MAX_DIM; g++) {
8731*d6b92ffaSHans Petter Selasky 		ptgrp = &sw->ptgrp[g];
8732*d6b92ffaSHans Petter Selasky 		if (!ptgrp->to_stree_tip)
8733*d6b92ffaSHans Petter Selasky 			continue;
8734*d6b92ffaSHans Petter Selasky 
8735*d6b92ffaSHans Petter Selasky 		p = mgb->mlid % ptgrp->port_cnt;/* port # in port group */
8736*d6b92ffaSHans Petter Selasky 		p = ptgrp->port[p]->port;	/* now port # in switch */
8737*d6b92ffaSHans Petter Selasky 
8738*d6b92ffaSHans Petter Selasky 		ds_node = osm_node_get_remote_node(osm_sw->p_node, p, NULL);
8739*d6b92ffaSHans Petter Selasky 		ds_sw = ptgrp->to_stree_tip->sw;
8740*d6b92ffaSHans Petter Selasky 
8741*d6b92ffaSHans Petter Selasky 		if (!(ds_node && ds_node->sw &&
8742*d6b92ffaSHans Petter Selasky 		      ds_sw->osm_switch == ds_node->sw)) {
8743*d6b92ffaSHans Petter Selasky 			OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR,
8744*d6b92ffaSHans Petter Selasky 				"ERR 4E40: stale pointer to osm_sw "
8745*d6b92ffaSHans Petter Selasky 				"(GUID 0x%04"PRIx64")\n", cl_ntoh64(ds_sw->n_id));
8746*d6b92ffaSHans Petter Selasky 			continue;
8747*d6b92ffaSHans Petter Selasky 		}
8748*d6b92ffaSHans Petter Selasky 		mtn->child_array[p] =
8749*d6b92ffaSHans Petter Selasky 			mcast_stree_branch(ds_sw, ds_node->sw, mgb,
8750*d6b92ffaSHans Petter Selasky 					   depth, port_cnt, max_depth);
8751*d6b92ffaSHans Petter Selasky 		if (!mtn->child_array[p])
8752*d6b92ffaSHans Petter Selasky 			continue;
8753*d6b92ffaSHans Petter Selasky 
8754*d6b92ffaSHans Petter Selasky 		osm_mcast_tbl_set(mcast_tbl, mgb->mlid, p);
8755*d6b92ffaSHans Petter Selasky 		mcast_fwd_ports++;
8756*d6b92ffaSHans Petter Selasky 		/*
8757*d6b92ffaSHans Petter Selasky 		 * Since we forward traffic for this multicast group on this
8758*d6b92ffaSHans Petter Selasky 		 * port, cause the switch on the other end of the link
8759*d6b92ffaSHans Petter Selasky 		 * to forward traffic back to us.  Do it now since have at
8760*d6b92ffaSHans Petter Selasky 		 * hand the link used; otherwise it'll be hard to figure out
8761*d6b92ffaSHans Petter Selasky 		 * later, and if we get it wrong we get a MC routing loop.
8762*d6b92ffaSHans Petter Selasky 		 */
8763*d6b92ffaSHans Petter Selasky 		link = sw->port[p]->link;
8764*d6b92ffaSHans Petter Selasky 		ds_mcast_tbl = osm_switch_get_mcast_tbl_ptr(ds_node->sw);
8765*d6b92ffaSHans Petter Selasky 
8766*d6b92ffaSHans Petter Selasky 		if (&link->end[0] == sw->port[p])
8767*d6b92ffaSHans Petter Selasky 			osm_mcast_tbl_set(ds_mcast_tbl, mgb->mlid,
8768*d6b92ffaSHans Petter Selasky 					  link->end[1].port);
8769*d6b92ffaSHans Petter Selasky 		else
8770*d6b92ffaSHans Petter Selasky 			osm_mcast_tbl_set(ds_mcast_tbl, mgb->mlid,
8771*d6b92ffaSHans Petter Selasky 					  link->end[0].port);
8772*d6b92ffaSHans Petter Selasky 	}
8773*d6b92ffaSHans Petter Selasky 	/*
8774*d6b92ffaSHans Petter Selasky 	 * Add any host ports marked as in mcast group into spanning tree.
8775*d6b92ffaSHans Petter Selasky 	 */
8776*d6b92ffaSHans Petter Selasky 	ptgrp = &sw->ptgrp[2 * TORUS_MAX_DIM];
8777*d6b92ffaSHans Petter Selasky 	for (p = 0; p < ptgrp->port_cnt; p++) {
8778*d6b92ffaSHans Petter Selasky 		port = ptgrp->port[p];
8779*d6b92ffaSHans Petter Selasky 		if (port->tmp) {
8780*d6b92ffaSHans Petter Selasky 			port->tmp = NULL;
8781*d6b92ffaSHans Petter Selasky 			mtn->child_array[port->port] = OSM_MTREE_LEAF;
8782*d6b92ffaSHans Petter Selasky 			osm_mcast_tbl_set(mcast_tbl, mgb->mlid, port->port);
8783*d6b92ffaSHans Petter Selasky 			mcast_end_ports++;
8784*d6b92ffaSHans Petter Selasky 		}
8785*d6b92ffaSHans Petter Selasky 	}
8786*d6b92ffaSHans Petter Selasky 	if (!(mcast_end_ports || mcast_fwd_ports)) {
8787*d6b92ffaSHans Petter Selasky 		osm_mtree_destroy(mtn);
8788*d6b92ffaSHans Petter Selasky 		mtn = NULL;
8789*d6b92ffaSHans Petter Selasky 	} else if (depth > *max_depth)
8790*d6b92ffaSHans Petter Selasky 		*max_depth = depth;
8791*d6b92ffaSHans Petter Selasky 
8792*d6b92ffaSHans Petter Selasky 	*port_cnt += mcast_end_ports;
8793*d6b92ffaSHans Petter Selasky out:
8794*d6b92ffaSHans Petter Selasky 	return mtn;
8795*d6b92ffaSHans Petter Selasky }
8796*d6b92ffaSHans Petter Selasky 
8797*d6b92ffaSHans Petter Selasky static
next_mgrp_box_port(osm_mgrp_box_t * mgb,cl_list_item_t ** list_iterator,cl_map_item_t ** map_iterator)8798*d6b92ffaSHans Petter Selasky osm_port_t *next_mgrp_box_port(osm_mgrp_box_t *mgb,
8799*d6b92ffaSHans Petter Selasky 			       cl_list_item_t **list_iterator,
8800*d6b92ffaSHans Petter Selasky 			       cl_map_item_t **map_iterator)
8801*d6b92ffaSHans Petter Selasky {
8802*d6b92ffaSHans Petter Selasky 	osm_mgrp_t *mgrp;
8803*d6b92ffaSHans Petter Selasky 	osm_mcm_port_t *mcm_port;
8804*d6b92ffaSHans Petter Selasky 	osm_port_t *osm_port = NULL;
8805*d6b92ffaSHans Petter Selasky 	cl_map_item_t *m_item = *map_iterator;
8806*d6b92ffaSHans Petter Selasky 	cl_list_item_t *l_item = *list_iterator;
8807*d6b92ffaSHans Petter Selasky 
8808*d6b92ffaSHans Petter Selasky next_mgrp:
8809*d6b92ffaSHans Petter Selasky 	if (!l_item)
8810*d6b92ffaSHans Petter Selasky 		l_item = cl_qlist_head(&mgb->mgrp_list);
8811*d6b92ffaSHans Petter Selasky 	if (l_item == cl_qlist_end(&mgb->mgrp_list)) {
8812*d6b92ffaSHans Petter Selasky 		l_item = NULL;
8813*d6b92ffaSHans Petter Selasky 		goto out;
8814*d6b92ffaSHans Petter Selasky 	}
8815*d6b92ffaSHans Petter Selasky 	mgrp = cl_item_obj(l_item, mgrp, list_item);
8816*d6b92ffaSHans Petter Selasky 
8817*d6b92ffaSHans Petter Selasky 	if (!m_item)
8818*d6b92ffaSHans Petter Selasky 		m_item = cl_qmap_head(&mgrp->mcm_port_tbl);
8819*d6b92ffaSHans Petter Selasky 	if (m_item == cl_qmap_end(&mgrp->mcm_port_tbl)) {
8820*d6b92ffaSHans Petter Selasky 		m_item = NULL;
8821*d6b92ffaSHans Petter Selasky 		l_item = cl_qlist_next(l_item);
8822*d6b92ffaSHans Petter Selasky 		goto next_mgrp;
8823*d6b92ffaSHans Petter Selasky 	}
8824*d6b92ffaSHans Petter Selasky 	mcm_port = cl_item_obj(m_item, mcm_port, map_item);
8825*d6b92ffaSHans Petter Selasky 	m_item = cl_qmap_next(m_item);
8826*d6b92ffaSHans Petter Selasky 	osm_port = mcm_port->port;
8827*d6b92ffaSHans Petter Selasky out:
8828*d6b92ffaSHans Petter Selasky 	*list_iterator = l_item;
8829*d6b92ffaSHans Petter Selasky 	*map_iterator = m_item;
8830*d6b92ffaSHans Petter Selasky 	return osm_port;
8831*d6b92ffaSHans Petter Selasky }
8832*d6b92ffaSHans Petter Selasky 
8833*d6b92ffaSHans Petter Selasky static
torus_mcast_stree(void * context,osm_mgrp_box_t * mgb)8834*d6b92ffaSHans Petter Selasky ib_api_status_t torus_mcast_stree(void *context, osm_mgrp_box_t *mgb)
8835*d6b92ffaSHans Petter Selasky {
8836*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx = context;
8837*d6b92ffaSHans Petter Selasky 	struct torus *t = ctx->torus;
8838*d6b92ffaSHans Petter Selasky 	cl_map_item_t *m_item = NULL;
8839*d6b92ffaSHans Petter Selasky 	cl_list_item_t *l_item = NULL;
8840*d6b92ffaSHans Petter Selasky 	osm_port_t *osm_port;
8841*d6b92ffaSHans Petter Selasky 	osm_switch_t *osm_sw;
8842*d6b92ffaSHans Petter Selasky 	struct endpoint *port;
8843*d6b92ffaSHans Petter Selasky 	unsigned port_cnt = 0, max_depth = 0;
8844*d6b92ffaSHans Petter Selasky 
8845*d6b92ffaSHans Petter Selasky 	osm_purge_mtree(&ctx->osm->sm, mgb);
8846*d6b92ffaSHans Petter Selasky 
8847*d6b92ffaSHans Petter Selasky 	/*
8848*d6b92ffaSHans Petter Selasky 	 * Build a spanning tree for a multicast group by first marking
8849*d6b92ffaSHans Petter Selasky 	 * the torus endpoints that are participating in the group.
8850*d6b92ffaSHans Petter Selasky 	 * Then do a depth-first search of the torus master spanning
8851*d6b92ffaSHans Petter Selasky 	 * tree to build up the spanning tree specific to this group.
8852*d6b92ffaSHans Petter Selasky 	 *
8853*d6b92ffaSHans Petter Selasky 	 * Since the torus master spanning tree is constructed specifically
8854*d6b92ffaSHans Petter Selasky 	 * to guarantee that multicast will not deadlock against unicast
8855*d6b92ffaSHans Petter Selasky 	 * when they share VLs, we can be sure that any multicast group
8856*d6b92ffaSHans Petter Selasky 	 * spanning tree constructed this way has the same property.
8857*d6b92ffaSHans Petter Selasky 	 */
8858*d6b92ffaSHans Petter Selasky 	while ((osm_port = next_mgrp_box_port(mgb, &l_item, &m_item))) {
8859*d6b92ffaSHans Petter Selasky 		port = osm_port->priv;
8860*d6b92ffaSHans Petter Selasky 		if (!(port && port->osm_port == osm_port)) {
8861*d6b92ffaSHans Petter Selasky 			port = osm_port_relink_endpoint(osm_port);
8862*d6b92ffaSHans Petter Selasky 			if (!port) {
8863*d6b92ffaSHans Petter Selasky 				guid_t id;
8864*d6b92ffaSHans Petter Selasky 				id = osm_node_get_node_guid(osm_port->p_node);
8865*d6b92ffaSHans Petter Selasky 				OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR,
8866*d6b92ffaSHans Petter Selasky 					"ERR 4E41: osm_port (GUID 0x%04"PRIx64") "
8867*d6b92ffaSHans Petter Selasky 					"not in torus fabric description\n",
8868*d6b92ffaSHans Petter Selasky 					cl_ntoh64(id));
8869*d6b92ffaSHans Petter Selasky 				continue;
8870*d6b92ffaSHans Petter Selasky 			}
8871*d6b92ffaSHans Petter Selasky 		}
8872*d6b92ffaSHans Petter Selasky 		/*
8873*d6b92ffaSHans Petter Selasky 		 * If this is a CA port, mark the switch port at the
8874*d6b92ffaSHans Petter Selasky 		 * other end of this port's link.
8875*d6b92ffaSHans Petter Selasky 		 *
8876*d6b92ffaSHans Petter Selasky 		 * By definition, a CA port is connected to end[1] of a link,
8877*d6b92ffaSHans Petter Selasky 		 * and the switch port is end[0].  See build_ca_link() and
8878*d6b92ffaSHans Petter Selasky 		 * link_srcsink().
8879*d6b92ffaSHans Petter Selasky 		 */
8880*d6b92ffaSHans Petter Selasky 		if (port->link)
8881*d6b92ffaSHans Petter Selasky 			port = &port->link->end[0];
8882*d6b92ffaSHans Petter Selasky 		port->tmp = osm_port;
8883*d6b92ffaSHans Petter Selasky 	}
8884*d6b92ffaSHans Petter Selasky 	/*
8885*d6b92ffaSHans Petter Selasky 	 * It might be we got called in a window between a switch getting
8886*d6b92ffaSHans Petter Selasky 	 * removed from the fabric, and torus-2QoS getting to rebuild its
8887*d6b92ffaSHans Petter Selasky 	 * fabric representation.  If that were to happen, our
8888*d6b92ffaSHans Petter Selasky 	 * master_stree_root->osm_switch pointer might be stale.  Look up
8889*d6b92ffaSHans Petter Selasky 	 * the osm_switch by GUID to be sure it's not.
8890*d6b92ffaSHans Petter Selasky 	 *
8891*d6b92ffaSHans Petter Selasky 	 * Also, call into mcast_stree_branch with depth = -1, because
8892*d6b92ffaSHans Petter Selasky 	 * depth at root switch needs to be 0.
8893*d6b92ffaSHans Petter Selasky 	 */
8894*d6b92ffaSHans Petter Selasky 	osm_sw = (osm_switch_t *)cl_qmap_get(&ctx->osm->subn.sw_guid_tbl,
8895*d6b92ffaSHans Petter Selasky 					     t->master_stree_root->n_id);
8896*d6b92ffaSHans Petter Selasky 	if (!(osm_sw && t->master_stree_root->osm_switch == osm_sw)) {
8897*d6b92ffaSHans Petter Selasky 		OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR,
8898*d6b92ffaSHans Petter Selasky 			"ERR 4E42: stale pointer to osm_sw (GUID 0x%04"PRIx64")\n",
8899*d6b92ffaSHans Petter Selasky 			cl_ntoh64(t->master_stree_root->n_id));
8900*d6b92ffaSHans Petter Selasky 		return IB_ERROR;
8901*d6b92ffaSHans Petter Selasky 	}
8902*d6b92ffaSHans Petter Selasky 	mgb->root = mcast_stree_branch(t->master_stree_root, osm_sw,
8903*d6b92ffaSHans Petter Selasky 				       mgb, -1, &port_cnt, &max_depth);
8904*d6b92ffaSHans Petter Selasky 
8905*d6b92ffaSHans Petter Selasky 	OSM_LOG(&ctx->osm->log, OSM_LOG_VERBOSE,
8906*d6b92ffaSHans Petter Selasky 		"Configured MLID 0x%X for %u ports, max tree depth = %u\n",
8907*d6b92ffaSHans Petter Selasky 		mgb->mlid, port_cnt, max_depth);
8908*d6b92ffaSHans Petter Selasky 
8909*d6b92ffaSHans Petter Selasky 	return IB_SUCCESS;
8910*d6b92ffaSHans Petter Selasky }
8911*d6b92ffaSHans Petter Selasky 
8912*d6b92ffaSHans Petter Selasky static
good_xy_ring(struct torus * t,const int x,const int y,const int z)8913*d6b92ffaSHans Petter Selasky bool good_xy_ring(struct torus *t, const int x, const int y, const int z)
8914*d6b92ffaSHans Petter Selasky {
8915*d6b92ffaSHans Petter Selasky 	struct t_switch ****sw = t->sw;
8916*d6b92ffaSHans Petter Selasky 	bool good_ring = true;
8917*d6b92ffaSHans Petter Selasky 	int x_tst, y_tst;
8918*d6b92ffaSHans Petter Selasky 
8919*d6b92ffaSHans Petter Selasky 	for (x_tst = 0; x_tst < t->x_sz && good_ring; x_tst++)
8920*d6b92ffaSHans Petter Selasky 		good_ring = sw[x_tst][y][z];
8921*d6b92ffaSHans Petter Selasky 
8922*d6b92ffaSHans Petter Selasky 	for (y_tst = 0; y_tst < t->y_sz && good_ring; y_tst++)
8923*d6b92ffaSHans Petter Selasky 		good_ring = sw[x][y_tst][z];
8924*d6b92ffaSHans Petter Selasky 
8925*d6b92ffaSHans Petter Selasky 	return good_ring;
8926*d6b92ffaSHans Petter Selasky }
8927*d6b92ffaSHans Petter Selasky 
8928*d6b92ffaSHans Petter Selasky static
find_plane_mid(struct torus * t,const int z)8929*d6b92ffaSHans Petter Selasky struct t_switch *find_plane_mid(struct torus *t, const int z)
8930*d6b92ffaSHans Petter Selasky {
8931*d6b92ffaSHans Petter Selasky 	int x, dx, xm = t->x_sz / 2;
8932*d6b92ffaSHans Petter Selasky 	int y, dy, ym = t->y_sz / 2;
8933*d6b92ffaSHans Petter Selasky 	struct t_switch ****sw = t->sw;
8934*d6b92ffaSHans Petter Selasky 
8935*d6b92ffaSHans Petter Selasky 	if (good_xy_ring(t, xm, ym, z))
8936*d6b92ffaSHans Petter Selasky 		return sw[xm][ym][z];
8937*d6b92ffaSHans Petter Selasky 
8938*d6b92ffaSHans Petter Selasky 	for (dx = 1, dy = 1; dx <= xm && dy <= ym; dx++, dy++) {
8939*d6b92ffaSHans Petter Selasky 
8940*d6b92ffaSHans Petter Selasky 		x = canonicalize(xm - dx, t->x_sz);
8941*d6b92ffaSHans Petter Selasky 		y = canonicalize(ym - dy, t->y_sz);
8942*d6b92ffaSHans Petter Selasky 		if (good_xy_ring(t, x, y, z))
8943*d6b92ffaSHans Petter Selasky 			return sw[x][y][z];
8944*d6b92ffaSHans Petter Selasky 
8945*d6b92ffaSHans Petter Selasky 		x = canonicalize(xm + dx, t->x_sz);
8946*d6b92ffaSHans Petter Selasky 		y = canonicalize(ym + dy, t->y_sz);
8947*d6b92ffaSHans Petter Selasky 		if (good_xy_ring(t, x, y, z))
8948*d6b92ffaSHans Petter Selasky 			return sw[x][y][z];
8949*d6b92ffaSHans Petter Selasky 	}
8950*d6b92ffaSHans Petter Selasky 	return NULL;
8951*d6b92ffaSHans Petter Selasky }
8952*d6b92ffaSHans Petter Selasky 
8953*d6b92ffaSHans Petter Selasky static
find_stree_root(struct torus * t)8954*d6b92ffaSHans Petter Selasky struct t_switch *find_stree_root(struct torus *t)
8955*d6b92ffaSHans Petter Selasky {
8956*d6b92ffaSHans Petter Selasky 	int x, y, z, dz, zm = t->z_sz / 2;
8957*d6b92ffaSHans Petter Selasky 	struct t_switch ****sw = t->sw;
8958*d6b92ffaSHans Petter Selasky 	struct t_switch *root;
8959*d6b92ffaSHans Petter Selasky 	bool good_plane;
8960*d6b92ffaSHans Petter Selasky 
8961*d6b92ffaSHans Petter Selasky 	/*
8962*d6b92ffaSHans Petter Selasky 	 * Look for a switch near the "center" (wrt. the datelines) of the
8963*d6b92ffaSHans Petter Selasky 	 * torus, as that will be the most optimum spanning tree root.  Use
8964*d6b92ffaSHans Petter Selasky 	 * a search that is not exhaustive, on the theory that this routing
8965*d6b92ffaSHans Petter Selasky 	 * engine isn't useful anyway if too many switches are missing.
8966*d6b92ffaSHans Petter Selasky 	 *
8967*d6b92ffaSHans Petter Selasky 	 * Also, want to pick an x-y plane with no missing switches, so that
8968*d6b92ffaSHans Petter Selasky 	 * the master spanning tree construction algorithm doesn't have to
8969*d6b92ffaSHans Petter Selasky 	 * deal with needing a turn on a missing switch.
8970*d6b92ffaSHans Petter Selasky 	 */
8971*d6b92ffaSHans Petter Selasky 	for (dz = 0; dz <= zm; dz++) {
8972*d6b92ffaSHans Petter Selasky 
8973*d6b92ffaSHans Petter Selasky 		z = canonicalize(zm - dz, t->z_sz);
8974*d6b92ffaSHans Petter Selasky 		good_plane = true;
8975*d6b92ffaSHans Petter Selasky 		for (y = 0; y < t->y_sz && good_plane; y++)
8976*d6b92ffaSHans Petter Selasky 			for (x = 0; x < t->x_sz && good_plane; x++)
8977*d6b92ffaSHans Petter Selasky 				good_plane = sw[x][y][z];
8978*d6b92ffaSHans Petter Selasky 
8979*d6b92ffaSHans Petter Selasky 		if (good_plane) {
8980*d6b92ffaSHans Petter Selasky 			root = find_plane_mid(t, z);
8981*d6b92ffaSHans Petter Selasky 			if (root)
8982*d6b92ffaSHans Petter Selasky 				goto out;
8983*d6b92ffaSHans Petter Selasky 		}
8984*d6b92ffaSHans Petter Selasky 		if (!dz)
8985*d6b92ffaSHans Petter Selasky 			continue;
8986*d6b92ffaSHans Petter Selasky 
8987*d6b92ffaSHans Petter Selasky 		z = canonicalize(zm + dz, t->z_sz);
8988*d6b92ffaSHans Petter Selasky 		good_plane = true;
8989*d6b92ffaSHans Petter Selasky 		for (y = 0; y < t->y_sz && good_plane; y++)
8990*d6b92ffaSHans Petter Selasky 			for (x = 0; x < t->x_sz && good_plane; x++)
8991*d6b92ffaSHans Petter Selasky 				good_plane = sw[x][y][z];
8992*d6b92ffaSHans Petter Selasky 
8993*d6b92ffaSHans Petter Selasky 		if (good_plane) {
8994*d6b92ffaSHans Petter Selasky 			root = find_plane_mid(t, z);
8995*d6b92ffaSHans Petter Selasky 			if (root)
8996*d6b92ffaSHans Petter Selasky 				goto out;
8997*d6b92ffaSHans Petter Selasky 		}
8998*d6b92ffaSHans Petter Selasky 	}
8999*d6b92ffaSHans Petter Selasky 	/*
9000*d6b92ffaSHans Petter Selasky 	 * Note that torus-2QoS can route a torus that is missing an entire
9001*d6b92ffaSHans Petter Selasky 	 * column (switches with x,y constant, for all z values) without
9002*d6b92ffaSHans Petter Selasky 	 * deadlocks.
9003*d6b92ffaSHans Petter Selasky 	 *
9004*d6b92ffaSHans Petter Selasky 	 * if we've reached this point, we must have a column of missing
9005*d6b92ffaSHans Petter Selasky 	 * switches, as routable_torus() would have returned false for
9006*d6b92ffaSHans Petter Selasky 	 * any other configuration of missing switches that made it through
9007*d6b92ffaSHans Petter Selasky 	 * the above.
9008*d6b92ffaSHans Petter Selasky 	 *
9009*d6b92ffaSHans Petter Selasky 	 * So any switch in the mid-z plane will do as the root.
9010*d6b92ffaSHans Petter Selasky 	 */
9011*d6b92ffaSHans Petter Selasky 	root = find_plane_mid(t, zm);
9012*d6b92ffaSHans Petter Selasky out:
9013*d6b92ffaSHans Petter Selasky 	return root;
9014*d6b92ffaSHans Petter Selasky }
9015*d6b92ffaSHans Petter Selasky 
9016*d6b92ffaSHans Petter Selasky static
sw_in_master_stree(struct t_switch * sw)9017*d6b92ffaSHans Petter Selasky bool sw_in_master_stree(struct t_switch *sw)
9018*d6b92ffaSHans Petter Selasky {
9019*d6b92ffaSHans Petter Selasky 	int g;
9020*d6b92ffaSHans Petter Selasky 	bool connected;
9021*d6b92ffaSHans Petter Selasky 
9022*d6b92ffaSHans Petter Selasky 	connected = sw == sw->torus->master_stree_root;
9023*d6b92ffaSHans Petter Selasky 	for (g = 0; g < 2 * TORUS_MAX_DIM; g++)
9024*d6b92ffaSHans Petter Selasky 		connected = connected || sw->ptgrp[g].to_stree_root;
9025*d6b92ffaSHans Petter Selasky 
9026*d6b92ffaSHans Petter Selasky 	return connected;
9027*d6b92ffaSHans Petter Selasky }
9028*d6b92ffaSHans Petter Selasky 
9029*d6b92ffaSHans Petter Selasky static
grow_master_stree_branch(struct t_switch * root,struct t_switch * tip,unsigned to_root_pg,unsigned to_tip_pg)9030*d6b92ffaSHans Petter Selasky void grow_master_stree_branch(struct t_switch *root, struct t_switch *tip,
9031*d6b92ffaSHans Petter Selasky 			      unsigned to_root_pg, unsigned to_tip_pg)
9032*d6b92ffaSHans Petter Selasky {
9033*d6b92ffaSHans Petter Selasky 	root->ptgrp[to_tip_pg].to_stree_tip = &tip->ptgrp[to_root_pg];
9034*d6b92ffaSHans Petter Selasky 	tip->ptgrp[to_root_pg].to_stree_root = &root->ptgrp[to_tip_pg];
9035*d6b92ffaSHans Petter Selasky }
9036*d6b92ffaSHans Petter Selasky 
9037*d6b92ffaSHans Petter Selasky static
build_master_stree_branch(struct t_switch * branch_root,int cdir)9038*d6b92ffaSHans Petter Selasky void build_master_stree_branch(struct t_switch *branch_root, int cdir)
9039*d6b92ffaSHans Petter Selasky {
9040*d6b92ffaSHans Petter Selasky 	struct t_switch *sw, *n_sw, *p_sw;
9041*d6b92ffaSHans Petter Selasky 	unsigned l, idx, cnt, pg, ng;
9042*d6b92ffaSHans Petter Selasky 
9043*d6b92ffaSHans Petter Selasky 	switch (cdir) {
9044*d6b92ffaSHans Petter Selasky 	case 0:
9045*d6b92ffaSHans Petter Selasky 		idx = branch_root->i;
9046*d6b92ffaSHans Petter Selasky 		cnt = branch_root->torus->x_sz;
9047*d6b92ffaSHans Petter Selasky 		break;
9048*d6b92ffaSHans Petter Selasky 	case 1:
9049*d6b92ffaSHans Petter Selasky 		idx = branch_root->j;
9050*d6b92ffaSHans Petter Selasky 		cnt = branch_root->torus->y_sz;
9051*d6b92ffaSHans Petter Selasky 		break;
9052*d6b92ffaSHans Petter Selasky 	case 2:
9053*d6b92ffaSHans Petter Selasky 		idx = branch_root->k;
9054*d6b92ffaSHans Petter Selasky 		cnt = branch_root->torus->z_sz;
9055*d6b92ffaSHans Petter Selasky 		break;
9056*d6b92ffaSHans Petter Selasky 	default:
9057*d6b92ffaSHans Petter Selasky 		goto out;
9058*d6b92ffaSHans Petter Selasky 	}
9059*d6b92ffaSHans Petter Selasky 	/*
9060*d6b92ffaSHans Petter Selasky 	 * This algorithm intends that a spanning tree branch never crosses
9061*d6b92ffaSHans Petter Selasky 	 * a dateline unless the 1-D ring for which we're building the branch
9062*d6b92ffaSHans Petter Selasky 	 * is interrupted by failure.  We need that guarantee to prevent
9063*d6b92ffaSHans Petter Selasky 	 * multicast/unicast credit loops.
9064*d6b92ffaSHans Petter Selasky 	 */
9065*d6b92ffaSHans Petter Selasky 	n_sw = branch_root;		/* tip of negative cdir branch */
9066*d6b92ffaSHans Petter Selasky 	ng = 2 * cdir;			/* negative cdir port group index */
9067*d6b92ffaSHans Petter Selasky 	p_sw = branch_root;		/* tip of positive cdir branch */
9068*d6b92ffaSHans Petter Selasky 	pg = 2 * cdir + 1;		/* positive cdir port group index */
9069*d6b92ffaSHans Petter Selasky 
9070*d6b92ffaSHans Petter Selasky 	for (l = idx; n_sw && l >= 1; l--) {
9071*d6b92ffaSHans Petter Selasky 		sw = ring_next_sw(n_sw, cdir, -1);
9072*d6b92ffaSHans Petter Selasky 		if (sw && !sw_in_master_stree(sw)) {
9073*d6b92ffaSHans Petter Selasky 			grow_master_stree_branch(n_sw, sw, pg, ng);
9074*d6b92ffaSHans Petter Selasky 			n_sw = sw;
9075*d6b92ffaSHans Petter Selasky 		} else
9076*d6b92ffaSHans Petter Selasky 			n_sw = NULL;
9077*d6b92ffaSHans Petter Selasky 	}
9078*d6b92ffaSHans Petter Selasky 	for (l = idx; p_sw && l < (cnt - 1); l++) {
9079*d6b92ffaSHans Petter Selasky 		sw = ring_next_sw(p_sw, cdir, 1);
9080*d6b92ffaSHans Petter Selasky 		if (sw && !sw_in_master_stree(sw)) {
9081*d6b92ffaSHans Petter Selasky 			grow_master_stree_branch(p_sw, sw, ng, pg);
9082*d6b92ffaSHans Petter Selasky 			p_sw = sw;
9083*d6b92ffaSHans Petter Selasky 		} else
9084*d6b92ffaSHans Petter Selasky 			p_sw = NULL;
9085*d6b92ffaSHans Petter Selasky 	}
9086*d6b92ffaSHans Petter Selasky 	if (n_sw && p_sw)
9087*d6b92ffaSHans Petter Selasky 		goto out;
9088*d6b92ffaSHans Petter Selasky 	/*
9089*d6b92ffaSHans Petter Selasky 	 * At least one branch couldn't grow to the dateline for this ring.
9090*d6b92ffaSHans Petter Selasky 	 * That means it is acceptable to grow the branch by crossing the
9091*d6b92ffaSHans Petter Selasky 	 * dateline.
9092*d6b92ffaSHans Petter Selasky 	 */
9093*d6b92ffaSHans Petter Selasky 	for (l = 0; l < cnt; l++) {
9094*d6b92ffaSHans Petter Selasky 		if (n_sw) {
9095*d6b92ffaSHans Petter Selasky 			sw = ring_next_sw(n_sw, cdir, -1);
9096*d6b92ffaSHans Petter Selasky 			if (sw && !sw_in_master_stree(sw)) {
9097*d6b92ffaSHans Petter Selasky 				grow_master_stree_branch(n_sw, sw, pg, ng);
9098*d6b92ffaSHans Petter Selasky 				n_sw = sw;
9099*d6b92ffaSHans Petter Selasky 			} else
9100*d6b92ffaSHans Petter Selasky 				n_sw = NULL;
9101*d6b92ffaSHans Petter Selasky 		}
9102*d6b92ffaSHans Petter Selasky 		if (p_sw) {
9103*d6b92ffaSHans Petter Selasky 			sw = ring_next_sw(p_sw, cdir, 1);
9104*d6b92ffaSHans Petter Selasky 			if (sw && !sw_in_master_stree(sw)) {
9105*d6b92ffaSHans Petter Selasky 				grow_master_stree_branch(p_sw, sw, ng, pg);
9106*d6b92ffaSHans Petter Selasky 				p_sw = sw;
9107*d6b92ffaSHans Petter Selasky 			} else
9108*d6b92ffaSHans Petter Selasky 				p_sw = NULL;
9109*d6b92ffaSHans Petter Selasky 		}
9110*d6b92ffaSHans Petter Selasky 		if (!(n_sw || p_sw))
9111*d6b92ffaSHans Petter Selasky 			break;
9112*d6b92ffaSHans Petter Selasky 	}
9113*d6b92ffaSHans Petter Selasky out:
9114*d6b92ffaSHans Petter Selasky 	return;
9115*d6b92ffaSHans Petter Selasky }
9116*d6b92ffaSHans Petter Selasky 
9117*d6b92ffaSHans Petter Selasky static
torus_master_stree(struct torus * t)9118*d6b92ffaSHans Petter Selasky bool torus_master_stree(struct torus *t)
9119*d6b92ffaSHans Petter Selasky {
9120*d6b92ffaSHans Petter Selasky 	int i, j, k;
9121*d6b92ffaSHans Petter Selasky 	bool success = false;
9122*d6b92ffaSHans Petter Selasky 	struct t_switch *stree_root = find_stree_root(t);
9123*d6b92ffaSHans Petter Selasky 
9124*d6b92ffaSHans Petter Selasky 	if (stree_root)
9125*d6b92ffaSHans Petter Selasky 		build_master_stree_branch(stree_root, 0);
9126*d6b92ffaSHans Petter Selasky 	else
9127*d6b92ffaSHans Petter Selasky 		goto out;
9128*d6b92ffaSHans Petter Selasky 
9129*d6b92ffaSHans Petter Selasky 	k = stree_root->k;
9130*d6b92ffaSHans Petter Selasky 	for (i = 0; i < t->x_sz; i++) {
9131*d6b92ffaSHans Petter Selasky 		j = stree_root->j;
9132*d6b92ffaSHans Petter Selasky 		if (t->sw[i][j][k])
9133*d6b92ffaSHans Petter Selasky 			build_master_stree_branch(t->sw[i][j][k], 1);
9134*d6b92ffaSHans Petter Selasky 
9135*d6b92ffaSHans Petter Selasky 		for (j = 0; j < t->y_sz; j++)
9136*d6b92ffaSHans Petter Selasky 			if (t->sw[i][j][k])
9137*d6b92ffaSHans Petter Selasky 				build_master_stree_branch(t->sw[i][j][k], 2);
9138*d6b92ffaSHans Petter Selasky 	}
9139*d6b92ffaSHans Petter Selasky 	t->master_stree_root = stree_root;
9140*d6b92ffaSHans Petter Selasky 	/*
9141*d6b92ffaSHans Petter Selasky 	 * At this point we should have a master spanning tree that contains
9142*d6b92ffaSHans Petter Selasky 	 * every present switch, for all fabrics that torus-2QoS can route
9143*d6b92ffaSHans Petter Selasky 	 * without deadlocks.  Make sure this is the case; otherwise warn
9144*d6b92ffaSHans Petter Selasky 	 * and return failure so we get bug reports.
9145*d6b92ffaSHans Petter Selasky 	 */
9146*d6b92ffaSHans Petter Selasky 	success = true;
9147*d6b92ffaSHans Petter Selasky 	for (i = 0; i < t->x_sz; i++)
9148*d6b92ffaSHans Petter Selasky 		for (j = 0; j < t->y_sz; j++)
9149*d6b92ffaSHans Petter Selasky 			for (k = 0; k < t->z_sz; k++) {
9150*d6b92ffaSHans Petter Selasky 				struct t_switch *sw = t->sw[i][j][k];
9151*d6b92ffaSHans Petter Selasky 				if (!sw || sw_in_master_stree(sw))
9152*d6b92ffaSHans Petter Selasky 					continue;
9153*d6b92ffaSHans Petter Selasky 
9154*d6b92ffaSHans Petter Selasky 				success = false;
9155*d6b92ffaSHans Petter Selasky 				OSM_LOG(&t->osm->log, OSM_LOG_ERROR,
9156*d6b92ffaSHans Petter Selasky 					"ERR 4E43: sw 0x%04"PRIx64" (%d,%d,%d) not in "
9157*d6b92ffaSHans Petter Selasky 					"torus multicast master spanning tree\n",
9158*d6b92ffaSHans Petter Selasky 					cl_ntoh64(sw->n_id), i, j, k);
9159*d6b92ffaSHans Petter Selasky 			}
9160*d6b92ffaSHans Petter Selasky out:
9161*d6b92ffaSHans Petter Selasky 	return success;
9162*d6b92ffaSHans Petter Selasky }
9163*d6b92ffaSHans Petter Selasky 
route_torus(struct torus * t)9164*d6b92ffaSHans Petter Selasky int route_torus(struct torus *t)
9165*d6b92ffaSHans Petter Selasky {
9166*d6b92ffaSHans Petter Selasky 	int s;
9167*d6b92ffaSHans Petter Selasky 	bool success = true;
9168*d6b92ffaSHans Petter Selasky 
9169*d6b92ffaSHans Petter Selasky 	for (s = 0; s < (int)t->switch_cnt; s++)
9170*d6b92ffaSHans Petter Selasky 		success = torus_lft(t, t->sw_pool[s]) && success;
9171*d6b92ffaSHans Petter Selasky 
9172*d6b92ffaSHans Petter Selasky 	success = success && torus_master_stree(t);
9173*d6b92ffaSHans Petter Selasky 
9174*d6b92ffaSHans Petter Selasky 	return success ? 0 : -1;
9175*d6b92ffaSHans Petter Selasky }
9176*d6b92ffaSHans Petter Selasky 
torus_path_sl(void * context,uint8_t path_sl_hint,const ib_net16_t slid,const ib_net16_t dlid)9177*d6b92ffaSHans Petter Selasky uint8_t torus_path_sl(void *context, uint8_t path_sl_hint,
9178*d6b92ffaSHans Petter Selasky 		      const ib_net16_t slid, const ib_net16_t dlid)
9179*d6b92ffaSHans Petter Selasky {
9180*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx = context;
9181*d6b92ffaSHans Petter Selasky 	osm_opensm_t *p_osm = ctx->osm;
9182*d6b92ffaSHans Petter Selasky 	osm_log_t *log = &p_osm->log;
9183*d6b92ffaSHans Petter Selasky 	osm_port_t *osm_sport, *osm_dport;
9184*d6b92ffaSHans Petter Selasky 	struct endpoint *sport, *dport;
9185*d6b92ffaSHans Petter Selasky 	struct t_switch *ssw, *dsw;
9186*d6b92ffaSHans Petter Selasky 	struct torus *t;
9187*d6b92ffaSHans Petter Selasky 	guid_t guid;
9188*d6b92ffaSHans Petter Selasky 	unsigned sl = 0;
9189*d6b92ffaSHans Petter Selasky 
9190*d6b92ffaSHans Petter Selasky 	osm_sport = osm_get_port_by_lid(&p_osm->subn, slid);
9191*d6b92ffaSHans Petter Selasky 	if (!osm_sport)
9192*d6b92ffaSHans Petter Selasky 		goto out;
9193*d6b92ffaSHans Petter Selasky 
9194*d6b92ffaSHans Petter Selasky 	osm_dport = osm_get_port_by_lid(&p_osm->subn, dlid);
9195*d6b92ffaSHans Petter Selasky 	if (!osm_dport)
9196*d6b92ffaSHans Petter Selasky 		goto out;
9197*d6b92ffaSHans Petter Selasky 
9198*d6b92ffaSHans Petter Selasky 	sport = osm_sport->priv;
9199*d6b92ffaSHans Petter Selasky 	if (!(sport && sport->osm_port == osm_sport)) {
9200*d6b92ffaSHans Petter Selasky 		sport = osm_port_relink_endpoint(osm_sport);
9201*d6b92ffaSHans Petter Selasky 		if (!sport) {
9202*d6b92ffaSHans Petter Selasky 			guid = osm_node_get_node_guid(osm_sport->p_node);
9203*d6b92ffaSHans Petter Selasky 			OSM_LOG(log, OSM_LOG_INFO,
9204*d6b92ffaSHans Petter Selasky 				"Note: osm_sport (GUID 0x%04"PRIx64") "
9205*d6b92ffaSHans Petter Selasky 				"not in torus fabric description\n",
9206*d6b92ffaSHans Petter Selasky 				cl_ntoh64(guid));
9207*d6b92ffaSHans Petter Selasky 			goto out;
9208*d6b92ffaSHans Petter Selasky 		}
9209*d6b92ffaSHans Petter Selasky 	}
9210*d6b92ffaSHans Petter Selasky 	dport = osm_dport->priv;
9211*d6b92ffaSHans Petter Selasky 	if (!(dport && dport->osm_port == osm_dport)) {
9212*d6b92ffaSHans Petter Selasky 		dport = osm_port_relink_endpoint(osm_dport);
9213*d6b92ffaSHans Petter Selasky 		if (!dport) {
9214*d6b92ffaSHans Petter Selasky 			guid = osm_node_get_node_guid(osm_dport->p_node);
9215*d6b92ffaSHans Petter Selasky 			OSM_LOG(log, OSM_LOG_INFO,
9216*d6b92ffaSHans Petter Selasky 				"Note: osm_dport (GUID 0x%04"PRIx64") "
9217*d6b92ffaSHans Petter Selasky 				"not in torus fabric description\n",
9218*d6b92ffaSHans Petter Selasky 				cl_ntoh64(guid));
9219*d6b92ffaSHans Petter Selasky 			goto out;
9220*d6b92ffaSHans Petter Selasky 		}
9221*d6b92ffaSHans Petter Selasky 	}
9222*d6b92ffaSHans Petter Selasky 	/*
9223*d6b92ffaSHans Petter Selasky 	 * We're only supposed to be called for CA ports, and maybe
9224*d6b92ffaSHans Petter Selasky 	 * switch management ports.
9225*d6b92ffaSHans Petter Selasky 	 */
9226*d6b92ffaSHans Petter Selasky 	if (sport->type != SRCSINK) {
9227*d6b92ffaSHans Petter Selasky 		guid = osm_node_get_node_guid(osm_sport->p_node);
9228*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9229*d6b92ffaSHans Petter Selasky 			"Error: osm_sport (GUID 0x%04"PRIx64") "
9230*d6b92ffaSHans Petter Selasky 			"not a data src/sink port\n", cl_ntoh64(guid));
9231*d6b92ffaSHans Petter Selasky 		goto out;
9232*d6b92ffaSHans Petter Selasky 	}
9233*d6b92ffaSHans Petter Selasky 	if (dport->type != SRCSINK) {
9234*d6b92ffaSHans Petter Selasky 		guid = osm_node_get_node_guid(osm_dport->p_node);
9235*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9236*d6b92ffaSHans Petter Selasky 			"Error: osm_dport (GUID 0x%04"PRIx64") "
9237*d6b92ffaSHans Petter Selasky 			"not a data src/sink port\n", cl_ntoh64(guid));
9238*d6b92ffaSHans Petter Selasky 		goto out;
9239*d6b92ffaSHans Petter Selasky 	}
9240*d6b92ffaSHans Petter Selasky 	/*
9241*d6b92ffaSHans Petter Selasky 	 * By definition, a CA port is connected to end[1] of a link, and
9242*d6b92ffaSHans Petter Selasky 	 * the switch port is end[0].  See build_ca_link() and link_srcsink().
9243*d6b92ffaSHans Petter Selasky 	 */
9244*d6b92ffaSHans Petter Selasky 	if (sport->link) {
9245*d6b92ffaSHans Petter Selasky 		ssw = sport->link->end[0].sw;
9246*d6b92ffaSHans Petter Selasky 	} else {
9247*d6b92ffaSHans Petter Selasky 		ssw = sport->sw;
9248*d6b92ffaSHans Petter Selasky 	}
9249*d6b92ffaSHans Petter Selasky 	if (dport->link)
9250*d6b92ffaSHans Petter Selasky 		dsw = dport->link->end[0].sw;
9251*d6b92ffaSHans Petter Selasky 	else
9252*d6b92ffaSHans Petter Selasky 		dsw = dport->sw;
9253*d6b92ffaSHans Petter Selasky 
9254*d6b92ffaSHans Petter Selasky 	t = ssw->torus;
9255*d6b92ffaSHans Petter Selasky 
9256*d6b92ffaSHans Petter Selasky 	sl  = sl_set_use_loop_vl(use_vl1(ssw->i, dsw->i, t->x_sz), 0);
9257*d6b92ffaSHans Petter Selasky 	sl |= sl_set_use_loop_vl(use_vl1(ssw->j, dsw->j, t->y_sz), 1);
9258*d6b92ffaSHans Petter Selasky 	sl |= sl_set_use_loop_vl(use_vl1(ssw->k, dsw->k, t->z_sz), 2);
9259*d6b92ffaSHans Petter Selasky 	sl |= sl_set_qos(sl_get_qos(path_sl_hint));
9260*d6b92ffaSHans Petter Selasky out:
9261*d6b92ffaSHans Petter Selasky 	return sl;
9262*d6b92ffaSHans Petter Selasky }
9263*d6b92ffaSHans Petter Selasky 
9264*d6b92ffaSHans Petter Selasky static
sum_vlarb_weights(const char * vlarb_str,unsigned total_weight[IB_MAX_NUM_VLS])9265*d6b92ffaSHans Petter Selasky void sum_vlarb_weights(const char *vlarb_str,
9266*d6b92ffaSHans Petter Selasky 		       unsigned total_weight[IB_MAX_NUM_VLS])
9267*d6b92ffaSHans Petter Selasky {
9268*d6b92ffaSHans Petter Selasky 	unsigned i = 0, v, vl = 0;
9269*d6b92ffaSHans Petter Selasky 	char *end;
9270*d6b92ffaSHans Petter Selasky 
9271*d6b92ffaSHans Petter Selasky 	while (*vlarb_str && i++ < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
9272*d6b92ffaSHans Petter Selasky 		v = strtoul(vlarb_str, &end, 0);
9273*d6b92ffaSHans Petter Selasky 		if (*end)
9274*d6b92ffaSHans Petter Selasky 			end++;
9275*d6b92ffaSHans Petter Selasky 		vlarb_str = end;
9276*d6b92ffaSHans Petter Selasky 		if (i & 0x1)
9277*d6b92ffaSHans Petter Selasky 			vl = v & 0xf;
9278*d6b92ffaSHans Petter Selasky 		else
9279*d6b92ffaSHans Petter Selasky 			total_weight[vl] += v & 0xff;
9280*d6b92ffaSHans Petter Selasky 	}
9281*d6b92ffaSHans Petter Selasky }
9282*d6b92ffaSHans Petter Selasky 
9283*d6b92ffaSHans Petter Selasky static
uniform_vlarb_weight_value(unsigned * weight,unsigned count)9284*d6b92ffaSHans Petter Selasky int uniform_vlarb_weight_value(unsigned *weight, unsigned count)
9285*d6b92ffaSHans Petter Selasky {
9286*d6b92ffaSHans Petter Selasky 	int i, v = weight[0];
9287*d6b92ffaSHans Petter Selasky 
9288*d6b92ffaSHans Petter Selasky 	for (i = 1; i < count; i++) {
9289*d6b92ffaSHans Petter Selasky 		if (v != weight[i])
9290*d6b92ffaSHans Petter Selasky 			return -1;
9291*d6b92ffaSHans Petter Selasky 	}
9292*d6b92ffaSHans Petter Selasky 	return v;
9293*d6b92ffaSHans Petter Selasky }
9294*d6b92ffaSHans Petter Selasky 
9295*d6b92ffaSHans Petter Selasky static
check_vlarb_config(const char * vlarb_str,bool is_default,const char * str,const char * pri,osm_log_t * log)9296*d6b92ffaSHans Petter Selasky void check_vlarb_config(const char *vlarb_str, bool is_default,
9297*d6b92ffaSHans Petter Selasky 			const char *str, const char *pri, osm_log_t *log)
9298*d6b92ffaSHans Petter Selasky {
9299*d6b92ffaSHans Petter Selasky 	unsigned total_weight[IB_MAX_NUM_VLS] = {0,};
9300*d6b92ffaSHans Petter Selasky 
9301*d6b92ffaSHans Petter Selasky 	sum_vlarb_weights(vlarb_str, total_weight);
9302*d6b92ffaSHans Petter Selasky 	if (!(uniform_vlarb_weight_value(&total_weight[0], 4) >= 0 &&
9303*d6b92ffaSHans Petter Selasky 	      uniform_vlarb_weight_value(&total_weight[4], 4) >= 0))
9304*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9305*d6b92ffaSHans Petter Selasky 			"Warning: torus-2QoS requires same VLarb weights for "
9306*d6b92ffaSHans Petter Selasky 			"VLs 0-3; also for VLs 4-7: not true for %s "
9307*d6b92ffaSHans Petter Selasky 			"%s_vlarb_%s\n",
9308*d6b92ffaSHans Petter Selasky 			(is_default ? "default" : "configured"), str, pri);
9309*d6b92ffaSHans Petter Selasky }
9310*d6b92ffaSHans Petter Selasky 
9311*d6b92ffaSHans Petter Selasky /*
9312*d6b92ffaSHans Petter Selasky  * Use this to check the qos_config for switch external ports.
9313*d6b92ffaSHans Petter Selasky  */
9314*d6b92ffaSHans Petter Selasky static
check_qos_swe_config(osm_qos_options_t * opt,osm_qos_options_t * def,osm_log_t * log)9315*d6b92ffaSHans Petter Selasky void check_qos_swe_config(osm_qos_options_t *opt,
9316*d6b92ffaSHans Petter Selasky 			  osm_qos_options_t *def, osm_log_t *log)
9317*d6b92ffaSHans Petter Selasky {
9318*d6b92ffaSHans Petter Selasky 	const char *vlarb_str, *tstr;
9319*d6b92ffaSHans Petter Selasky 	bool is_default;
9320*d6b92ffaSHans Petter Selasky 	unsigned max_vls;
9321*d6b92ffaSHans Petter Selasky 
9322*d6b92ffaSHans Petter Selasky 	max_vls = def->max_vls;
9323*d6b92ffaSHans Petter Selasky 	if (opt->max_vls > 0)
9324*d6b92ffaSHans Petter Selasky 		max_vls = opt->max_vls;
9325*d6b92ffaSHans Petter Selasky 
9326*d6b92ffaSHans Petter Selasky 	if (max_vls > 0 && max_vls < 8)
9327*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9328*d6b92ffaSHans Petter Selasky 			"Warning: full torus-2QoS functionality not available "
9329*d6b92ffaSHans Petter Selasky 			"for configured %s_max_vls = %d\n",
9330*d6b92ffaSHans Petter Selasky 			(opt->max_vls > 0 ? "qos_swe" : "qos"), opt->max_vls);
9331*d6b92ffaSHans Petter Selasky 
9332*d6b92ffaSHans Petter Selasky 	vlarb_str = opt->vlarb_high;
9333*d6b92ffaSHans Petter Selasky 	is_default = false;
9334*d6b92ffaSHans Petter Selasky 	tstr = "qos_swe";
9335*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9336*d6b92ffaSHans Petter Selasky 		vlarb_str = def->vlarb_high;
9337*d6b92ffaSHans Petter Selasky 		tstr = "qos";
9338*d6b92ffaSHans Petter Selasky 	}
9339*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9340*d6b92ffaSHans Petter Selasky 		vlarb_str = OSM_DEFAULT_QOS_VLARB_HIGH;
9341*d6b92ffaSHans Petter Selasky 		is_default = true;
9342*d6b92ffaSHans Petter Selasky 	}
9343*d6b92ffaSHans Petter Selasky 	check_vlarb_config(vlarb_str, is_default, tstr, "high", log);
9344*d6b92ffaSHans Petter Selasky 
9345*d6b92ffaSHans Petter Selasky 	vlarb_str = opt->vlarb_low;
9346*d6b92ffaSHans Petter Selasky 	is_default = false;
9347*d6b92ffaSHans Petter Selasky 	tstr = "qos_swe";
9348*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9349*d6b92ffaSHans Petter Selasky 		vlarb_str = def->vlarb_low;
9350*d6b92ffaSHans Petter Selasky 		tstr = "qos";
9351*d6b92ffaSHans Petter Selasky 	}
9352*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9353*d6b92ffaSHans Petter Selasky 		vlarb_str = OSM_DEFAULT_QOS_VLARB_LOW;
9354*d6b92ffaSHans Petter Selasky 		is_default = true;
9355*d6b92ffaSHans Petter Selasky 	}
9356*d6b92ffaSHans Petter Selasky 	check_vlarb_config(vlarb_str, is_default, tstr, "low", log);
9357*d6b92ffaSHans Petter Selasky 
9358*d6b92ffaSHans Petter Selasky 	if (opt->sl2vl)
9359*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9360*d6b92ffaSHans Petter Selasky 			"Warning: torus-2QoS must override configured "
9361*d6b92ffaSHans Petter Selasky 			"qos_swe_sl2vl to generate deadlock-free routes\n");
9362*d6b92ffaSHans Petter Selasky }
9363*d6b92ffaSHans Petter Selasky 
9364*d6b92ffaSHans Petter Selasky static
check_ep_vlarb_config(const char * vlarb_str,bool is_default,bool is_specific,const char * str,const char * pri,osm_log_t * log)9365*d6b92ffaSHans Petter Selasky void check_ep_vlarb_config(const char *vlarb_str,
9366*d6b92ffaSHans Petter Selasky 			   bool is_default, bool is_specific,
9367*d6b92ffaSHans Petter Selasky 			   const char *str, const char *pri, osm_log_t *log)
9368*d6b92ffaSHans Petter Selasky {
9369*d6b92ffaSHans Petter Selasky 	unsigned i, total_weight[IB_MAX_NUM_VLS] = {0,};
9370*d6b92ffaSHans Petter Selasky 	int val = 0;
9371*d6b92ffaSHans Petter Selasky 
9372*d6b92ffaSHans Petter Selasky 	sum_vlarb_weights(vlarb_str, total_weight);
9373*d6b92ffaSHans Petter Selasky 	for (i = 2; i < 8; i++) {
9374*d6b92ffaSHans Petter Selasky 		val += total_weight[i];
9375*d6b92ffaSHans Petter Selasky 	}
9376*d6b92ffaSHans Petter Selasky 	if (!val)
9377*d6b92ffaSHans Petter Selasky 		return;
9378*d6b92ffaSHans Petter Selasky 
9379*d6b92ffaSHans Petter Selasky 	if (is_specific)
9380*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9381*d6b92ffaSHans Petter Selasky 			"Warning: torus-2QoS recommends 0 VLarb weights"
9382*d6b92ffaSHans Petter Selasky 			" for VLs 2-7 on endpoint links; not true for "
9383*d6b92ffaSHans Petter Selasky 			" configured %s_vlarb_%s\n", str, pri);
9384*d6b92ffaSHans Petter Selasky 	else
9385*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9386*d6b92ffaSHans Petter Selasky 			"Warning: torus-2QoS recommends 0 VLarb weights "
9387*d6b92ffaSHans Petter Selasky 			"for VLs 2-7 on endpoint links; not true for %s "
9388*d6b92ffaSHans Petter Selasky 			"qos_vlarb_%s values used for %s_vlarb_%s\n",
9389*d6b92ffaSHans Petter Selasky 			(is_default ? "default" : "configured"), pri, str, pri);
9390*d6b92ffaSHans Petter Selasky }
9391*d6b92ffaSHans Petter Selasky 
9392*d6b92ffaSHans Petter Selasky /*
9393*d6b92ffaSHans Petter Selasky  * Use this to check the qos_config for endports
9394*d6b92ffaSHans Petter Selasky  */
9395*d6b92ffaSHans Petter Selasky static
check_qos_ep_config(osm_qos_options_t * opt,osm_qos_options_t * def,const char * str,osm_log_t * log)9396*d6b92ffaSHans Petter Selasky void check_qos_ep_config(osm_qos_options_t *opt, osm_qos_options_t *def,
9397*d6b92ffaSHans Petter Selasky 			 const char *str, osm_log_t *log)
9398*d6b92ffaSHans Petter Selasky {
9399*d6b92ffaSHans Petter Selasky 	const char *vlarb_str;
9400*d6b92ffaSHans Petter Selasky 	bool is_default, is_specific;
9401*d6b92ffaSHans Petter Selasky 	unsigned max_vls;
9402*d6b92ffaSHans Petter Selasky 
9403*d6b92ffaSHans Petter Selasky 	max_vls = def->max_vls;
9404*d6b92ffaSHans Petter Selasky 	if (opt->max_vls > 0)
9405*d6b92ffaSHans Petter Selasky 		max_vls = opt->max_vls;
9406*d6b92ffaSHans Petter Selasky 
9407*d6b92ffaSHans Petter Selasky 	if (max_vls > 0 && max_vls < 2)
9408*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9409*d6b92ffaSHans Petter Selasky 			"Warning: full torus-2QoS functionality not available "
9410*d6b92ffaSHans Petter Selasky 			"for configured %s_max_vls = %d\n",
9411*d6b92ffaSHans Petter Selasky 			(opt->max_vls > 0 ? str : "qos"), opt->max_vls);
9412*d6b92ffaSHans Petter Selasky 
9413*d6b92ffaSHans Petter Selasky 	vlarb_str = opt->vlarb_high;
9414*d6b92ffaSHans Petter Selasky 	is_default = false;
9415*d6b92ffaSHans Petter Selasky 	is_specific = true;
9416*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9417*d6b92ffaSHans Petter Selasky 		vlarb_str = def->vlarb_high;
9418*d6b92ffaSHans Petter Selasky 		is_specific = false;
9419*d6b92ffaSHans Petter Selasky 	}
9420*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9421*d6b92ffaSHans Petter Selasky 		vlarb_str = OSM_DEFAULT_QOS_VLARB_HIGH;
9422*d6b92ffaSHans Petter Selasky 		is_default = true;
9423*d6b92ffaSHans Petter Selasky 	}
9424*d6b92ffaSHans Petter Selasky 	check_ep_vlarb_config(vlarb_str, is_default, is_specific,
9425*d6b92ffaSHans Petter Selasky 			      str, "high", log);
9426*d6b92ffaSHans Petter Selasky 
9427*d6b92ffaSHans Petter Selasky 	vlarb_str = opt->vlarb_low;
9428*d6b92ffaSHans Petter Selasky 	is_default = false;
9429*d6b92ffaSHans Petter Selasky 	is_specific = true;
9430*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9431*d6b92ffaSHans Petter Selasky 		vlarb_str = def->vlarb_low;
9432*d6b92ffaSHans Petter Selasky 		is_specific = false;
9433*d6b92ffaSHans Petter Selasky 	}
9434*d6b92ffaSHans Petter Selasky 	if (!vlarb_str) {
9435*d6b92ffaSHans Petter Selasky 		vlarb_str = OSM_DEFAULT_QOS_VLARB_LOW;
9436*d6b92ffaSHans Petter Selasky 		is_default = true;
9437*d6b92ffaSHans Petter Selasky 	}
9438*d6b92ffaSHans Petter Selasky 	check_ep_vlarb_config(vlarb_str, is_default, is_specific,
9439*d6b92ffaSHans Petter Selasky 			      str, "low", log);
9440*d6b92ffaSHans Petter Selasky 
9441*d6b92ffaSHans Petter Selasky 	if (opt->sl2vl)
9442*d6b92ffaSHans Petter Selasky 		OSM_LOG(log, OSM_LOG_INFO,
9443*d6b92ffaSHans Petter Selasky 			"Warning: torus-2QoS must override configured "
9444*d6b92ffaSHans Petter Selasky 			"%s_sl2vl to generate deadlock-free routes\n", str);
9445*d6b92ffaSHans Petter Selasky }
9446*d6b92ffaSHans Petter Selasky 
9447*d6b92ffaSHans Petter Selasky static
torus_build_lfts(void * context)9448*d6b92ffaSHans Petter Selasky int torus_build_lfts(void *context)
9449*d6b92ffaSHans Petter Selasky {
9450*d6b92ffaSHans Petter Selasky 	int status = -1;
9451*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx = context;
9452*d6b92ffaSHans Petter Selasky 	struct fabric *fabric;
9453*d6b92ffaSHans Petter Selasky 	struct torus *torus;
9454*d6b92ffaSHans Petter Selasky 
9455*d6b92ffaSHans Petter Selasky 	if (!ctx->osm->subn.opt.qos) {
9456*d6b92ffaSHans Petter Selasky 		OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR,
9457*d6b92ffaSHans Petter Selasky 			"ERR 4E44: Routing engine list contains torus-2QoS. "
9458*d6b92ffaSHans Petter Selasky 			"Enable QoS for correct operation "
9459*d6b92ffaSHans Petter Selasky 			"(-Q or 'qos TRUE' in opensm.conf).\n");
9460*d6b92ffaSHans Petter Selasky 		return status;
9461*d6b92ffaSHans Petter Selasky 	}
9462*d6b92ffaSHans Petter Selasky 
9463*d6b92ffaSHans Petter Selasky 	fabric = &ctx->fabric;
9464*d6b92ffaSHans Petter Selasky 	teardown_fabric(fabric);
9465*d6b92ffaSHans Petter Selasky 
9466*d6b92ffaSHans Petter Selasky 	torus = calloc(1, sizeof(*torus));
9467*d6b92ffaSHans Petter Selasky 	if (!torus) {
9468*d6b92ffaSHans Petter Selasky 		OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR,
9469*d6b92ffaSHans Petter Selasky 			"ERR 4E45: allocating torus: %s\n", strerror(errno));
9470*d6b92ffaSHans Petter Selasky 		goto out;
9471*d6b92ffaSHans Petter Selasky 	}
9472*d6b92ffaSHans Petter Selasky 	torus->osm = ctx->osm;
9473*d6b92ffaSHans Petter Selasky 	fabric->osm = ctx->osm;
9474*d6b92ffaSHans Petter Selasky 
9475*d6b92ffaSHans Petter Selasky 	if (!parse_config(ctx->osm->subn.opt.torus_conf_file,
9476*d6b92ffaSHans Petter Selasky 			  fabric, torus))
9477*d6b92ffaSHans Petter Selasky 		goto out;
9478*d6b92ffaSHans Petter Selasky 
9479*d6b92ffaSHans Petter Selasky 	if (!capture_fabric(fabric))
9480*d6b92ffaSHans Petter Selasky 		goto out;
9481*d6b92ffaSHans Petter Selasky 
9482*d6b92ffaSHans Petter Selasky 	OSM_LOG(&torus->osm->log, OSM_LOG_INFO,
9483*d6b92ffaSHans Petter Selasky 		"Found fabric w/ %d links, %d switches, %d CA ports, "
9484*d6b92ffaSHans Petter Selasky 		"minimum data VLs: endport %d, switchport %d\n",
9485*d6b92ffaSHans Petter Selasky 		(int)fabric->link_cnt, (int)fabric->switch_cnt,
9486*d6b92ffaSHans Petter Selasky 		(int)fabric->ca_cnt, (int)ctx->osm->subn.min_data_vls,
9487*d6b92ffaSHans Petter Selasky 		(int)ctx->osm->subn.min_sw_data_vls);
9488*d6b92ffaSHans Petter Selasky 
9489*d6b92ffaSHans Petter Selasky 	if (!verify_setup(torus, fabric))
9490*d6b92ffaSHans Petter Selasky 		goto out;
9491*d6b92ffaSHans Petter Selasky 
9492*d6b92ffaSHans Petter Selasky 	OSM_LOG(&torus->osm->log, OSM_LOG_INFO,
9493*d6b92ffaSHans Petter Selasky 		"Looking for %d x %d x %d %s\n",
9494*d6b92ffaSHans Petter Selasky 		(int)torus->x_sz, (int)torus->y_sz, (int)torus->z_sz,
9495*d6b92ffaSHans Petter Selasky 		(ALL_MESH(torus->flags) ? "mesh" : "torus"));
9496*d6b92ffaSHans Petter Selasky 
9497*d6b92ffaSHans Petter Selasky 	if (!build_torus(fabric, torus)) {
9498*d6b92ffaSHans Petter Selasky 		OSM_LOG(&torus->osm->log, OSM_LOG_ERROR, "ERR 4E57: "
9499*d6b92ffaSHans Petter Selasky 			"build_torus finished with errors\n");
9500*d6b92ffaSHans Petter Selasky 		goto out;
9501*d6b92ffaSHans Petter Selasky 	}
9502*d6b92ffaSHans Petter Selasky 
9503*d6b92ffaSHans Petter Selasky 	OSM_LOG(&torus->osm->log, OSM_LOG_INFO,
9504*d6b92ffaSHans Petter Selasky 		"Built %d x %d x %d %s w/ %d links, %d switches, %d CA ports\n",
9505*d6b92ffaSHans Petter Selasky 		(int)torus->x_sz, (int)torus->y_sz, (int)torus->z_sz,
9506*d6b92ffaSHans Petter Selasky 		(ALL_MESH(torus->flags) ? "mesh" : "torus"),
9507*d6b92ffaSHans Petter Selasky 		(int)torus->link_cnt, (int)torus->switch_cnt,
9508*d6b92ffaSHans Petter Selasky 		(int)torus->ca_cnt);
9509*d6b92ffaSHans Petter Selasky 
9510*d6b92ffaSHans Petter Selasky 	diagnose_fabric(fabric);
9511*d6b92ffaSHans Petter Selasky 	/*
9512*d6b92ffaSHans Petter Selasky 	 * Since we found some sort of torus fabric, report on any topology
9513*d6b92ffaSHans Petter Selasky 	 * changes vs. the last torus we found.
9514*d6b92ffaSHans Petter Selasky 	 */
9515*d6b92ffaSHans Petter Selasky 	if (torus->flags & NOTIFY_CHANGES)
9516*d6b92ffaSHans Petter Selasky 		report_torus_changes(torus, ctx->torus);
9517*d6b92ffaSHans Petter Selasky 
9518*d6b92ffaSHans Petter Selasky 	if (routable_torus(torus, fabric))
9519*d6b92ffaSHans Petter Selasky 		status = route_torus(torus);
9520*d6b92ffaSHans Petter Selasky 
9521*d6b92ffaSHans Petter Selasky out:
9522*d6b92ffaSHans Petter Selasky 	if (status) {		/* bad torus!! */
9523*d6b92ffaSHans Petter Selasky 		if (torus)
9524*d6b92ffaSHans Petter Selasky 			teardown_torus(torus);
9525*d6b92ffaSHans Petter Selasky 	} else {
9526*d6b92ffaSHans Petter Selasky 		osm_subn_opt_t *opt = &torus->osm->subn.opt;
9527*d6b92ffaSHans Petter Selasky 		osm_log_t *log = &torus->osm->log;
9528*d6b92ffaSHans Petter Selasky 
9529*d6b92ffaSHans Petter Selasky 		if (ctx->torus)
9530*d6b92ffaSHans Petter Selasky 			teardown_torus(ctx->torus);
9531*d6b92ffaSHans Petter Selasky 		ctx->torus = torus;
9532*d6b92ffaSHans Petter Selasky 
9533*d6b92ffaSHans Petter Selasky 		check_qos_swe_config(&opt->qos_swe_options, &opt->qos_options,
9534*d6b92ffaSHans Petter Selasky 				     log);
9535*d6b92ffaSHans Petter Selasky 
9536*d6b92ffaSHans Petter Selasky 		check_qos_ep_config(&opt->qos_ca_options,
9537*d6b92ffaSHans Petter Selasky 				    &opt->qos_options, "qos_ca", log);
9538*d6b92ffaSHans Petter Selasky 		check_qos_ep_config(&opt->qos_sw0_options,
9539*d6b92ffaSHans Petter Selasky 				    &opt->qos_options, "qos_sw0", log);
9540*d6b92ffaSHans Petter Selasky 		check_qos_ep_config(&opt->qos_rtr_options,
9541*d6b92ffaSHans Petter Selasky 				    &opt->qos_options, "qos_rtr", log);
9542*d6b92ffaSHans Petter Selasky 	}
9543*d6b92ffaSHans Petter Selasky 	teardown_fabric(fabric);
9544*d6b92ffaSHans Petter Selasky 	return status;
9545*d6b92ffaSHans Petter Selasky }
9546*d6b92ffaSHans Petter Selasky 
osm_ucast_torus2QoS_setup(struct osm_routing_engine * r,osm_opensm_t * osm)9547*d6b92ffaSHans Petter Selasky int osm_ucast_torus2QoS_setup(struct osm_routing_engine *r,
9548*d6b92ffaSHans Petter Selasky 			      osm_opensm_t *osm)
9549*d6b92ffaSHans Petter Selasky {
9550*d6b92ffaSHans Petter Selasky 	struct torus_context *ctx;
9551*d6b92ffaSHans Petter Selasky 
9552*d6b92ffaSHans Petter Selasky 	ctx = torus_context_create(osm);
9553*d6b92ffaSHans Petter Selasky 	if (!ctx)
9554*d6b92ffaSHans Petter Selasky 		return -1;
9555*d6b92ffaSHans Petter Selasky 
9556*d6b92ffaSHans Petter Selasky 	r->context = ctx;
9557*d6b92ffaSHans Petter Selasky 	r->ucast_build_fwd_tables = torus_build_lfts;
9558*d6b92ffaSHans Petter Selasky 	r->build_lid_matrices = ucast_dummy_build_lid_matrices;
9559*d6b92ffaSHans Petter Selasky 	r->update_sl2vl = torus_update_osm_sl2vl;
9560*d6b92ffaSHans Petter Selasky 	r->update_vlarb = torus_update_osm_vlarb;
9561*d6b92ffaSHans Petter Selasky 	r->path_sl = torus_path_sl;
9562*d6b92ffaSHans Petter Selasky 	r->mcast_build_stree = torus_mcast_stree;
9563*d6b92ffaSHans Petter Selasky 	r->destroy = torus_context_delete;
9564*d6b92ffaSHans Petter Selasky 	return 0;
9565*d6b92ffaSHans Petter Selasky }
9566