xref: /titanic_50/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen (revision ff3124eff995e6cd8ebd8c6543648e0670920034)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26#ident	"%Z%%M%	%I%	%E% SMI"
27
28#
29# The fan topologies can be quite complicated, but are ultimately regular.  This
30# perl file uses some simplified internal structures to generate an .xml file
31# without the maintenance overhead.
32#
33
34use Getopt::Std;
35use strict;
36
37#
38# Master table of platforms.
39#
40my @platforms = (
41    #
42    # Galaxy 1/2 platforms.
43    #
44    # These systems have 2 fan-connector boards.  Each fan-connector board has 3
45    # fan modules.  Each fan module is an individual FRU.  The fan-connector
46    # boards are also FRUs.
47    #
48    {
49	set => "Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|" .
50	    "Sun-Fire-X4100-M2|Sun-Fire-X4200-M2",
51	topology => [
52	    {
53		label => "FT %d",
54		count => 2,
55		fru => "self"
56	    }, {
57	        fac_enum => 1,
58		provider => "fac_prov_ipmi",
59		count => 3,
60		label => "FT %d FM %d",
61		entity_ref => "ft%d.fm%d.led",
62		entity_ref_nparams => 2,
63		fm_service_indctr => "ft%d.fm%d.led",
64		fru => "self"
65	    }
66	]
67    },
68
69    #
70    # Thumper platforms
71    #
72    # These systems have 5 fan modules, with each fan module containing 2 fans.
73    # The FRUs for the individual fans are the containing fan module.
74    #
75    {
76	set => "Sun-Fire-X4500|Sun-Fire-X4540",
77	topology => [
78	    {
79	        fac_enum => 0,
80		provider => "fac_prov_ipmi",
81		label => "FT %d",
82		count => 5,
83		fru => "self",
84		entity_ref => "ft%d.prsnt",
85		entity_ref_nparams => 1,
86		fm_service_indctr => "ft%d.service.led",
87		fm_ok2rm_indctr => "ft%d.ok2rm.led",
88	    }, {
89	        fac_enum => 1,
90		provider => "fac_prov_ipmi",
91		count => 2,
92		entity_ref => "ft%d.f%d.speed",
93		entity_ref_nparams => 2,
94		fru => "parent"
95	    }
96	]
97    },
98
99    #
100    # Fan Module/Fan topology for all G1N/G2N platforms.
101    #
102    # There are two fan boards, which are FRU's.  Each fan board has
103    # 3 fan modules for a total of 6 fan modules, with each fan module
104    # containing 2 fans.  The FRU's for the individual fans are the
105    # containing fan module.
106    #
107    # Unfortunately, the IPMI topology on these systems is rather broken, and
108    # all the SDRs that should be separate entities in fact refer to the same
109    # entity IDs.  So we have to use the alternative 'entity_present' option
110    # using a single SDR record.
111    #
112    {
113	set => "Sun-Fire-X4240|Sun-Fire-X4440",
114	topology => [
115	    {
116		count => 2,
117		label => "FANBD%d",
118		fru => "self"
119	    }, {
120		fac_enum => 1,
121		provider => "fac_prov_ipmi",
122		label => "FANBD%d FM%d",
123		count => 3,
124		fru => "self",
125		entity_present => "fb%d.fm%d.prsnt",
126		entity_ref => "fb%d.fm%d.prsnt",
127		entity_ref_nparams => 2,
128		fm_service_indctr_ => "fb%d.fm%d.led",
129	    }, {
130		count => 2,
131		fru => "parent"
132	    }
133
134	]
135    },
136
137    #
138    # Fan Module/Fan topology for G4F platforms.
139    #
140    # These systems have 4 fan assemblies with a single fan per assembly.
141    # Each fan assembly is a FRU.  The fan assemblies have a service LED
142    # but no other indicators.
143    #
144    {
145	set => "Sun-Fire-X4600-M2",
146	topology => [
147	    {
148	        fac_enum => 1,
149		provider => "fac_prov_ipmi",
150		count => 4,
151		label => "FT %d",
152		fru => "self",
153		entity_ref => "ft%d.fm0.prsnt",
154		entity_ref_nparams => 1,
155		fm_service_indctr => "ft%d.fm0.led"
156	    }
157	]
158    }
159);
160
161sub usage
162{
163	print STDERR "Usage: xml-gen -p <platform> -i <input_xml_file> -o <output_xml_file>\n";
164}
165
166#
167# Process an entry in the topology list.  We are passed the indentation level,
168# the current topology array, and any pushed indices.  This is called
169# recursively.
170#
171sub process_topology
172{
173	my ($indent, $toporef, @indices) = @_;
174	my @topo = @$toporef;
175	my $level = shift @topo;
176	my $type = $#topo == -1 ? "fan" : "fanmodule";
177
178	printf(OFILE "%*s<range name='%s' min='%d' max='%d'>\n",
179	    $indent, "", $type, 0, $level->{count} - 1);
180	$indent += 2;
181
182	for (my $i = 0; $i < $level->{count}; $i++) {
183		push @indices, $i;
184
185		printf(OFILE "%*s<node instance='%d'>\n", $indent, "", $i);
186
187		$indent += 2;
188
189		# Facility enumerator
190		if ($level->{fac_enum}) {
191			printf(OFILE "%*s<fac-enum provider='",
192			    $indent, "");
193			printf(OFILE $level->{provider}, @indices);
194			printf(OFILE "' />\n");
195		}
196
197		# Facility nodes for service and ok2rm LED's
198		if ($level->{fm_service_indctr}) {
199			printf(OFILE "%*s<facility name='service' type='indicator' ".
200			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
201			printf(OFILE "%*s<propgroup name='facility' version='1' ".
202			    "name-stability='Private' data-stability='Private' >\n",
203			    $indent+4, "");
204			printf(OFILE "%*s<propval name='type' type='uint32' ".
205			    "value='1' />\n", $indent+6, "");
206			printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ".
207			    "propname='entity_ref' proptype='string' >\n",
208			    $indent+6, "");
209			printf(OFILE "%*s<argval name='format' type='string' ".
210			    "value='%s' />\n", $indent+8, "",
211			    $level->{fm_service_indctr});
212			printf(OFILE "%*s<argval name='offset' type='uint32' ".
213			    "value='0' />\n", $indent+8, "");
214			printf(OFILE "%*s<argval name='nparams' type='uint32' ".
215			    "value='%d' />\n", $indent+8, "",
216			    $level->{entity_ref_nparams});
217			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
218			printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ".
219			    "version='0' propname='mode' proptype='uint32' ".
220			    "mutable='1' >\n", $indent+6, "");
221			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
222			printf(OFILE "%*s</propgroup>\n", $indent+4, "");
223			printf(OFILE "%*s</facility>\n", $indent+2, "");
224		}
225		if ($level->{fm_ok2rm_indctr}) {
226			printf(OFILE "%*s<facility name='ok2rm' type='indicator' ".
227			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
228			printf(OFILE "%*s<propgroup name='facility' version='1' ".
229			    "name-stability='Private' data-stability='Private' >\n",
230			    $indent+4, "");
231			printf(OFILE "%*s<propval name='type' type='uint32' ".
232			    "value='2' />\n", $indent+6, "");
233			printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ".
234			    "propname='entity_ref' proptype='string' >\n",
235			    $indent+6, "");
236			printf(OFILE "%*s<argval name='format' type='string' ".
237			    "value='%s' />\n", $indent+8, "",
238			    $level->{fm_ok2rm_indctr});
239			printf(OFILE "%*s<argval name='offset' type='uint32' ".
240			    "value='0' />\n", $indent+8, "");
241			printf(OFILE "%*s<argval name='nparams' type='uint32' ".
242			    "value='%d' />\n", $indent+8, "",
243			    $level->{entity_ref_nparams});
244			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
245			printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ".
246			    "version='0' propname='mode' proptype='uint32' mutable='1' >\n",
247			    $indent+6, "");
248			printf(OFILE "%*s</propmethod>\n", $indent+6, "");
249			printf(OFILE "%*s</propgroup>\n", $indent+4, "");
250			printf(OFILE "%*s</facility>\n", $indent+2, "");
251		}
252		# Protocol properties (label, fmri)
253		printf(OFILE "%*s<propgroup name='protocol' version='1' " .
254		    "name-stability='Private' data-stability='Private'>\n",
255		    $indent, "");
256
257		$indent += 2;
258
259		if ($level->{label}) {
260			printf(OFILE "%*s<propval name='label' type='string' " .
261			    "value='", $indent, "");
262			printf(OFILE $level->{label}, @indices);
263			printf(OFILE "' />\n");
264		}
265
266		printf(OFILE "%*s<propmethod name='ipmi_fru_fmri' " .
267		    "version='0' propname='FRU' proptype='fmri'>\n",
268		    $indent, "");
269		printf(OFILE "%*s<argval name='entity' type='string' " .
270		    "value='%s' />\n", $indent + 2, "", $level->{fru});
271		printf(OFILE "%*s</propmethod>\n", $indent, "");
272
273		$indent -= 2;
274
275		printf(OFILE "%*s</propgroup>\n", $indent, "");
276
277		#
278		# Entity references (if any)
279		#
280		if ($level->{entity_ref} || $level->{entity_present}) {
281			my $name = $level->{entity_ref} ? "entity_ref" :
282			    "entity_present";
283			my $val = $level->{$name};
284			printf(OFILE "%*s<propgroup name='ipmi' version='1' " .
285			    "name-stability='Private' " .
286			    "data-stability='Private' >\n", $indent, "");
287			printf(OFILE "%*s<propval name='%s' " .
288			    "type='string' value='", $indent + 2, "", $name);
289			printf(OFILE $val, @indices);
290			printf(OFILE "' />\n");
291			printf(OFILE "%*s</propgroup>\n", $indent, "");
292		}
293
294		#
295		# Post-process IPMI enumerator method
296		#
297		if ($level->{provider}) {
298			printf(OFILE "%*s<enum-method name='ipmi' version='1' ".
299			    "/>\n", $indent, "");
300		}
301
302		#
303		# Children (if any)
304		#
305		if ($#topo != -1) {
306			printf(OFILE "%*s<dependents grouping='children'>\n",
307			    $indent, "");
308			process_topology($indent + 2, \@topo, @indices);
309			printf(OFILE "%*s</dependents>\n", $indent, "");
310		}
311
312		$indent -= 2;
313
314		printf(OFILE "%*s</node>\n", $indent, "");
315		pop @indices;
316	}
317
318	$indent -= 2;
319	printf(OFILE "%*s</range>\n", $indent, "");
320}
321
322#
323# Process a single platform file.
324#
325sub process_platform
326{
327	my ($desc) = @_;
328	my $indent = 2;
329
330	printf(OFILE "%*s<set type='product' setlist='%s'>\n", $indent, "",
331	    $desc->{set});
332
333	process_topology($indent + 2, $desc->{topology});
334
335	printf(OFILE "%*s</set>\n", $indent, "");
336}
337
338my %options;
339getopts("p:i:o:h", \%options);
340if ($options{'h'}) {
341	usage();
342	exit (1);
343}
344
345my $platform = $options{'p'};
346my $input_file = $options{'i'};
347my $output_file = $options{'o'};
348
349if (!$platform || !$input_file || !$output_file) {
350	usage();
351	exit (1);
352}
353
354open(IFILE, "< $input_file") || die("$input_file cannot be opened.");
355open(OFILE, "> $output_file") || die("$output_file cannot be opened.");
356
357#
358# Open the file and read in the header until we reach the <topology> node.
359#
360while (<IFILE>) {
361	last if /<topology/;
362	print OFILE;
363}
364
365#
366# Construct the framework.
367#
368print OFILE "<topology name='fan' scheme='hc'>\n";
369
370my $desc;
371foreach $desc (@platforms) {
372	my $set = $desc->{set};
373	process_platform($desc);
374}
375
376print OFILE "</topology>\n";
377