xref: /illumos-gate/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen (revision 47842382d52f28aa3173aa6b511781c322ccb6a2)
1#!/usr/bin/perl -w
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27#
28# The fan topologies can be quite complicated, but are ultimately regular.  This
29# perl file uses some simplified internal structures to generate an .xml file
30# without the maintenance overhead.
31#
32
33use Getopt::Std;
34use strict;
35
36#
37# Master table of platforms.
38#
39my @platforms = (
40    #
41    # Galaxy 1/2 platforms.
42    #
43    # These systems have 2 fan-connector boards.  Each fan-connector board has 3
44    # fan modules.  Each fan module is an individual FRU.  The fan-connector
45    # boards are also FRUs.
46    #
47    {
48	set => "Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|" .
49	    "Sun-Fire-X4100-M2|Sun-Fire-X4200-M2",
50	topology => [
51	    {
52		label => "FT %d",
53		count => 2,
54		fru => "self"
55	    }, {
56	        fac_enum => 1,
57		provider => "fac_prov_ipmi",
58		count => 3,
59		label => "FT %d FM %d",
60		entity_ref => "ft%d.fm%d.led",
61		entity_ref_nparams => 2,
62		fm_service_indctr => "ft%d.fm%d.led",
63		fru => "self"
64	    }
65	]
66    },
67
68    #
69    # Thumper platforms
70    #
71    # These systems have 5 fan modules, with each fan module containing 2 fans.
72    # The FRUs for the individual fans are the containing fan module.
73    #
74    {
75	set => "Sun-Fire-X4500|Sun-Fire-X4540",
76	topology => [
77	    {
78	        fac_enum => 0,
79		provider => "fac_prov_ipmi",
80		label => "FT %d",
81		count => 5,
82		fru => "self",
83		entity_ref => "ft%d.prsnt",
84		entity_ref_nparams => 1,
85		fm_service_indctr => "ft%d.service.led",
86		fm_ok2rm_indctr => "ft%d.ok2rm.led",
87	    }, {
88	        fac_enum => 1,
89		provider => "fac_prov_ipmi",
90		count => 2,
91		entity_ref => "ft%d.f%d.speed",
92		entity_ref_nparams => 2,
93		fru => "parent"
94	    }
95	]
96    },
97
98    #
99    # Fan Module/Fan topology for all G1N/G2N platforms.
100    #
101    # There are two fan boards, which are FRU's.  Each fan board has
102    # 3 fan modules for a total of 6 fan modules, with each fan module
103    # containing 2 fans.  The FRU's for the individual fans are the
104    # containing fan module.
105    #
106    # Unfortunately, the IPMI topology on these systems is rather broken, and
107    # all the SDRs that should be separate entities in fact refer to the same
108    # entity IDs.  So we have to use the alternative 'entity_present' option
109    # using a single SDR record.
110    #
111    {
112	set => "Sun-Fire-X4240|Sun-Fire-X4440",
113	topology => [
114	    {
115		count => 2,
116		label => "FANBD%d",
117		fru => "self"
118	    }, {
119		label => "FANBD%d FM%d",
120		count => 3,
121		fru => "self",
122		provider => "fac_prov_ipmi",
123		entity_present => "fb%d.fm%d.prsnt",
124		fm_service_indctr=> "fb%d.fm%d.led",
125		entity_ref_nparams => 2
126	    }, {
127		fac_enum => 1,
128		count => 2,
129		fru => "parent",
130		provider => "fac_prov_ipmi",
131		entity_ref => "fb%d.fm%d.f%d.speed",
132		entity_present => "fb%d.fm%d.prsnt",
133		entity_ref_nparams => 3
134	    }
135
136	]
137    },
138
139    #
140    # Fan Module/Fan topology for G4F platforms.
141    #
142    # These systems have 4 fan assemblies with a single fan per assembly.
143    # Each fan assembly is a FRU.  The fan assemblies have a service LED
144    # but no other indicators.
145    #
146    {
147	set => "Sun-Fire-X4600|Sun-Fire-X4600-M2",
148	topology => [
149	    {
150	        fac_enum => 1,
151		provider => "fac_prov_ipmi",
152		count => 4,
153		label => "FT %d",
154		fru => "self",
155		entity_ref => "ft%d.fm0.prsnt",
156		entity_ref_nparams => 1,
157		fm_service_indctr => "ft%d.fm0.led"
158	    }
159	]
160    },
161
162    #
163    # Fan Module/Fan topology for Duradi 1U.
164    #
165    # There are two fan boards, which are FRU's.  The first fanboard has 4
166    # fanmodules (which are also FRU's).  The second fan board has 3 fan
167    # modules.  Each fanmodule contains two fans.
168    #
169    {
170	set => "SUN-FIRE-X4150",
171	topology => [
172	    {
173		count => 2,
174		label => "FANBD%d",
175		fru => "self",
176		entity_present => "FB%d/PRSRNT"
177	    }, {
178		label => "FANBD%d FM%d",
179		count => 4,
180		fru => "self",
181		provider => "fac_prov_ipmi",
182		entity_ref => "FB%d/FM%d/PRSNT",
183		fm_service_indctr=> "",
184		entity_ref_nparams => 2
185	    }, {
186		fac_enum => 1,
187		count => 2,
188		fru => "parent",
189		provider => "fac_prov_ipmi",
190		entity_ref => "FB%d/FM%d/F%d/TACH",
191		entity_ref_nparams => 3
192	    }
193
194	]
195    },
196    #
197    # Fan Module/Fan topology for Duradi 2U.
198    #
199    # There are two fan boards, which are FRU's.  Both fanboards have 3
200    # fanmodules (which are also FRU's). Each fanmodule contains two fans.
201    #
202    {
203	set => "SUN-FIRE-X4250",
204	topology => [
205	    {
206		count => 2,
207		label => "FANBD%d",
208		fru => "self",
209		entity_present => "FB%d/PRSRNT"
210	    }, {
211		label => "FANBD%d FM%d",
212		count => 3,
213		fru => "self",
214		provider => "fac_prov_ipmi",
215		entity_ref => "FB%d/FM%d/PRSNT",
216		fm_service_indctr=> "",
217		entity_ref_nparams => 2
218	    }, {
219		fac_enum => 1,
220		count => 2,
221		fru => "parent",
222		provider => "fac_prov_ipmi",
223		entity_ref => "FB%d/FM%d/F%d/TACH",
224		entity_ref_nparams => 3
225	    }
226
227	]
228    }
229);
230
231#
232# Process an entry in the topology list.  We are passed the indentation level,
233# the current topology array, the set list, and any pushed indices.  This is
234# called recursively.
235#
236sub process_topology
237{
238	my ($indent, $toporef, $set, @indices) = @_;
239	my @topo = @$toporef;
240	my $level = shift @topo;
241	my $type = $#topo == -1 ? "fan" : "fanmodule";
242
243	printf("%*s<range name='%s' min='%d' max='%d'>\n",
244	    $indent, "", $type, 0, $level->{count} - 1);
245	$indent += 2;
246
247	for (my $i = 0; $i < $level->{count}; $i++) {
248		#
249		# Special case code for Duradi 1U, which has an assymetric fan
250		# topology
251		#
252		last if (($set eq "SUN-FIRE-X4150") && ($type eq "fanmodule") &&
253		    ($#indices == 0) && ($indices[0] == 1) && ($i == 3));
254
255		push @indices, $i;
256
257		printf("%*s<node instance='%d'>\n", $indent, "", $i);
258
259		$indent += 2;
260
261		# Facility enumerator
262		if ($level->{fac_enum}) {
263			printf("%*s<fac-enum provider='",
264			    $indent, "");
265			printf($level->{provider});
266			printf("' />\n");
267		}
268
269		# Facility nodes for service and ok2rm LED's
270		if ($level->{fm_service_indctr}) {
271			printf("%*s<facility name='service' type='indicator' ".
272			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
273			printf("%*s<propgroup name='facility' version='1' ".
274			    "name-stability='Private' data-stability='Private' >\n",
275			    $indent+4, "");
276			printf("%*s<propval name='type' type='uint32' ".
277			    "value='1' />\n", $indent+6, "");
278			printf("%*s<propmethod name='ipmi_entity' version='0' ".
279			    "propname='entity_ref' proptype='string' >\n",
280			    $indent+6, "");
281			printf("%*s<argval name='format' type='string' ".
282			    "value='%s' />\n", $indent+8, "",
283			    $level->{fm_service_indctr});
284			printf("%*s<argval name='offset' type='uint32' ".
285			    "value='0' />\n", $indent+8, "");
286			printf("%*s<argval name='nparams' type='uint32' ".
287			    "value='%d' />\n", $indent+8, "",
288			    $level->{entity_ref_nparams});
289			printf("%*s</propmethod>\n", $indent+6, "");
290			printf("%*s<propmethod name='ipmi_indicator_mode' ".
291			    "version='0' propname='mode' proptype='uint32' ".
292			    "mutable='1' >\n", $indent+6, "");
293			printf("%*s</propmethod>\n", $indent+6, "");
294			printf("%*s</propgroup>\n", $indent+4, "");
295			printf("%*s</facility>\n", $indent+2, "");
296		}
297		if ($level->{fm_ok2rm_indctr}) {
298			printf("%*s<facility name='ok2rm' type='indicator' ".
299			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
300			printf("%*s<propgroup name='facility' version='1' ".
301			    "name-stability='Private' data-stability='Private' >\n",
302			    $indent+4, "");
303			printf("%*s<propval name='type' type='uint32' ".
304			    "value='2' />\n", $indent+6, "");
305			printf("%*s<propmethod name='ipmi_entity' version='0' ".
306			    "propname='entity_ref' proptype='string' >\n",
307			    $indent+6, "");
308			printf("%*s<argval name='format' type='string' ".
309			    "value='%s' />\n", $indent+8, "",
310			    $level->{fm_ok2rm_indctr});
311			printf("%*s<argval name='offset' type='uint32' ".
312			    "value='0' />\n", $indent+8, "");
313			printf("%*s<argval name='nparams' type='uint32' ".
314			    "value='%d' />\n", $indent+8, "",
315			    $level->{entity_ref_nparams});
316			printf("%*s</propmethod>\n", $indent+6, "");
317			printf("%*s<propmethod name='ipmi_indicator_mode' ".
318			    "version='0' propname='mode' proptype='uint32' mutable='1' >\n",
319			    $indent+6, "");
320			printf("%*s</propmethod>\n", $indent+6, "");
321			printf("%*s</propgroup>\n", $indent+4, "");
322			printf("%*s</facility>\n", $indent+2, "");
323		}
324
325		# Protocol properties (label, fmri)
326		printf("%*s<propgroup name='protocol' version='1' " .
327		    "name-stability='Private' data-stability='Private'>\n",
328		    $indent, "");
329
330		$indent += 2;
331
332		if ($level->{label}) {
333			printf("%*s<propval name='label' type='string' " .
334			    "value='", $indent, "");
335			printf($level->{label}, @indices);
336			printf("' />\n");
337		}
338
339		printf("%*s<propmethod name='ipmi_fru_fmri' " .
340		    "version='0' propname='FRU' proptype='fmri'>\n",
341		    $indent, "");
342		printf("%*s<argval name='entity' type='string' " .
343		    "value='%s' />\n", $indent + 2, "", $level->{fru});
344		printf("%*s</propmethod>\n", $indent, "");
345
346		$indent -= 2;
347
348		printf("%*s</propgroup>\n", $indent, "");
349
350		#
351		# Entity references (if any)
352		#
353		if ($level->{entity_ref}) {
354			my $val = $level->{entity_ref};
355			printf("%*s<propgroup name='ipmi' version='1' " .
356			    "name-stability='Private' " .
357			    "data-stability='Private' >\n", $indent, "");
358			printf("%*s<propval name='entity_ref' " .
359			    "type='string' value='", $indent + 2, "");
360			printf($val, @indices);
361			printf("' />\n");
362			printf("%*s</propgroup>\n", $indent, "");
363		}
364		if ($level->{entity_present}) {
365			my $val = $level->{entity_present};
366			printf("%*s<propgroup name='ipmi' version='1' " .
367			    "name-stability='Private' " .
368			    "data-stability='Private' >\n", $indent, "");
369			printf("%*s<propval name='entity_present' " .
370			    "type='string' value='", $indent + 2, "");
371			printf($val, @indices);
372			printf("' />\n");
373			printf("%*s</propgroup>\n", $indent, "");
374		}
375
376		#
377		# Post-process IPMI enumerator method
378		#
379		printf("%*s<enum-method name='ipmi' version='1' ".
380		    "/>\n", $indent, "");
381
382		#
383		# Children (if any)
384		#
385		if ($#topo != -1) {
386			printf("%*s<dependents grouping='children'>\n",
387			    $indent, "");
388			process_topology($indent + 2, \@topo, $set, @indices);
389			printf("%*s</dependents>\n", $indent, "");
390		}
391
392		$indent -= 2;
393
394		printf("%*s</node>\n", $indent, "");
395		pop @indices;
396	}
397
398	$indent -= 2;
399	printf("%*s</range>\n", $indent, "");
400}
401
402#
403# Process a single platform file.
404#
405sub process_platform
406{
407	my ($desc) = @_;
408	my $indent = 2;
409
410	printf("%*s<set type='product' setlist='%s'>\n", $indent, "",
411	    $desc->{set});
412
413	process_topology($indent + 2, $desc->{topology}, $desc->{set});
414
415	printf("%*s</set>\n", $indent, "");
416}
417
418print "<topology name='fan' scheme='hc'>\n";
419
420my $desc;
421foreach $desc (@platforms) {
422	process_platform($desc);
423}
424
425print "</topology>\n";
426