xref: /illumos-gate/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen (revision d656abb5804319b33c85955a73ee450ef7ff9739)
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 Durado 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-X4140",
171	topology => [
172	    {
173		count => 2,
174		label => "FANBD%d",
175		fru => "self",
176	    }, {
177		fac_enum => 1,
178		provider => "fac_prov_ipmi",
179		label => "FANBD%d FM%d",
180		count => 4,
181		fru => "self",
182		fm_service_indctr=> "fb%d.fm%d.led",
183		entity_ref_nparams => 2
184	    }, {
185		fac_enum => 1,
186		provider => "fac_prov_ipmi",
187		count => 2,
188		fru => "parent",
189		entity_ref => "fb%d.fm%d.f%d.speed",
190		entity_ref_nparams => 3
191	    }
192
193	]
194    },
195    #
196    # Fan Module/Fan topology for Duradi 1U.
197    #
198    # There are two fan boards, which are FRU's.  The first fanboard has 4
199    # fanmodules (which are also FRU's).  The second fan board has 3 fan
200    # modules.  Each fanmodule contains two fans.
201    #
202    {
203	set => "SUN-FIRE-X4150",
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 => 4,
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    # Fan Module/Fan topology for Duradi 2U.
231    #
232    # There are two fan boards, which are FRU's.  Both fanboards have 3
233    # fanmodules (which are also FRU's). Each fanmodule contains two fans.
234    #
235    {
236	set => "SUN-FIRE-X4250",
237	topology => [
238	    {
239		count => 2,
240		label => "FANBD%d",
241		fru => "self",
242		entity_present => "FB%d/PRSRNT"
243	    }, {
244		label => "FANBD%d FM%d",
245		count => 3,
246		fru => "self",
247		provider => "fac_prov_ipmi",
248		entity_ref => "FB%d/FM%d/PRSNT",
249		fm_service_indctr=> "",
250		entity_ref_nparams => 2
251	    }, {
252		fac_enum => 1,
253		count => 2,
254		fru => "parent",
255		provider => "fac_prov_ipmi",
256		entity_ref => "FB%d/FM%d/F%d/TACH",
257		entity_ref_nparams => 3
258	    }
259
260	]
261    }
262);
263
264#
265# Process an entry in the topology list.  We are passed the indentation level,
266# the current topology array, the set list, and any pushed indices.  This is
267# called recursively.
268#
269sub process_topology
270{
271	my ($indent, $toporef, $set, @indices) = @_;
272	my @topo = @$toporef;
273	my $level = shift @topo;
274	my $type = $#topo == -1 ? "fan" : "fanmodule";
275
276	printf("%*s<range name='%s' min='%d' max='%d'>\n",
277	    $indent, "", $type, 0, $level->{count} - 1);
278	$indent += 2;
279
280	for (my $i = 0; $i < $level->{count}; $i++) {
281		#
282		# Special case code for the 1U version of Durado and Duradi,
283		# both of which have an assymetric fan topology
284		#
285		last if ((($set eq "SUN-FIRE-X4150") || ($set eq "Sun-Fire-X4140"))
286		    && ($type eq "fanmodule") && ($#indices == 0)
287		    && ($indices[0] == 1) && ($i == 3));
288
289		push @indices, $i;
290
291		printf("%*s<node instance='%d'>\n", $indent, "", $i);
292
293		$indent += 2;
294
295		# Facility enumerator
296		if ($level->{fac_enum}) {
297			printf("%*s<fac-enum provider='",
298			    $indent, "");
299			printf($level->{provider});
300			printf("' />\n");
301		}
302
303		# Facility nodes for service and ok2rm LED's
304		if ($level->{fm_service_indctr}) {
305			printf("%*s<facility name='service' type='indicator' ".
306			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
307			printf("%*s<propgroup name='facility' version='1' ".
308			    "name-stability='Private' data-stability='Private' >\n",
309			    $indent+4, "");
310			printf("%*s<propval name='type' type='uint32' ".
311			    "value='0' />\n", $indent+6, "");
312			printf("%*s<propmethod name='ipmi_entity' version='0' ".
313			    "propname='entity_ref' proptype='string' >\n",
314			    $indent+6, "");
315			printf("%*s<argval name='format' type='string' ".
316			    "value='%s' />\n", $indent+8, "",
317			    $level->{fm_service_indctr});
318			printf("%*s<argval name='offset' type='uint32' ".
319			    "value='0' />\n", $indent+8, "");
320			printf("%*s<argval name='nparams' type='uint32' ".
321			    "value='%d' />\n", $indent+8, "",
322			    $level->{entity_ref_nparams});
323			printf("%*s</propmethod>\n", $indent+6, "");
324			printf("%*s<propmethod name='ipmi_indicator_mode' ".
325			    "version='0' propname='mode' proptype='uint32' ".
326			    "mutable='1' >\n", $indent+6, "");
327			printf("%*s</propmethod>\n", $indent+6, "");
328			printf("%*s</propgroup>\n", $indent+4, "");
329			printf("%*s</facility>\n", $indent+2, "");
330		}
331		if ($level->{fm_ok2rm_indctr}) {
332			printf("%*s<facility name='ok2rm' type='indicator' ".
333			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
334			printf("%*s<propgroup name='facility' version='1' ".
335			    "name-stability='Private' data-stability='Private' >\n",
336			    $indent+4, "");
337			printf("%*s<propval name='type' type='uint32' ".
338			    "value='2' />\n", $indent+6, "");
339			printf("%*s<propmethod name='ipmi_entity' version='0' ".
340			    "propname='entity_ref' proptype='string' >\n",
341			    $indent+6, "");
342			printf("%*s<argval name='format' type='string' ".
343			    "value='%s' />\n", $indent+8, "",
344			    $level->{fm_ok2rm_indctr});
345			printf("%*s<argval name='offset' type='uint32' ".
346			    "value='0' />\n", $indent+8, "");
347			printf("%*s<argval name='nparams' type='uint32' ".
348			    "value='%d' />\n", $indent+8, "",
349			    $level->{entity_ref_nparams});
350			printf("%*s</propmethod>\n", $indent+6, "");
351			printf("%*s<propmethod name='ipmi_indicator_mode' ".
352			    "version='0' propname='mode' proptype='uint32' mutable='1' >\n",
353			    $indent+6, "");
354			printf("%*s</propmethod>\n", $indent+6, "");
355			printf("%*s</propgroup>\n", $indent+4, "");
356			printf("%*s</facility>\n", $indent+2, "");
357		}
358
359		# Protocol properties (label, fmri)
360		printf("%*s<propgroup name='protocol' version='1' " .
361		    "name-stability='Private' data-stability='Private'>\n",
362		    $indent, "");
363
364		$indent += 2;
365
366		if ($level->{label}) {
367			printf("%*s<propval name='label' type='string' " .
368			    "value='", $indent, "");
369			printf($level->{label}, @indices);
370			printf("' />\n");
371		}
372
373		printf("%*s<propmethod name='ipmi_fru_fmri' " .
374		    "version='0' propname='FRU' proptype='fmri'>\n",
375		    $indent, "");
376		printf("%*s<argval name='entity' type='string' " .
377		    "value='%s' />\n", $indent + 2, "", $level->{fru});
378		printf("%*s</propmethod>\n", $indent, "");
379
380		$indent -= 2;
381
382		printf("%*s</propgroup>\n", $indent, "");
383
384		#
385		# Entity references (if any)
386		#
387		if ($level->{entity_ref}) {
388			my $val = $level->{entity_ref};
389			printf("%*s<propgroup name='ipmi' version='1' " .
390			    "name-stability='Private' " .
391			    "data-stability='Private' >\n", $indent, "");
392			printf("%*s<propval name='entity_ref' " .
393			    "type='string' value='", $indent + 2, "");
394			printf($val, @indices);
395			printf("' />\n");
396			printf("%*s</propgroup>\n", $indent, "");
397		}
398		if ($level->{entity_present}) {
399			my $val = $level->{entity_present};
400			printf("%*s<propgroup name='ipmi' version='1' " .
401			    "name-stability='Private' " .
402			    "data-stability='Private' >\n", $indent, "");
403			printf("%*s<propval name='entity_present' " .
404			    "type='string' value='", $indent + 2, "");
405			printf($val, @indices);
406			printf("' />\n");
407			printf("%*s</propgroup>\n", $indent, "");
408		}
409
410		#
411		# Post-process IPMI enumerator method
412		#
413		printf("%*s<enum-method name='ipmi' version='1' ".
414		    "/>\n", $indent, "");
415
416		#
417		# Children (if any)
418		#
419		if ($#topo != -1) {
420			printf("%*s<dependents grouping='children'>\n",
421			    $indent, "");
422			process_topology($indent + 2, \@topo, $set, @indices);
423			printf("%*s</dependents>\n", $indent, "");
424		}
425
426		$indent -= 2;
427
428		printf("%*s</node>\n", $indent, "");
429		pop @indices;
430	}
431
432	$indent -= 2;
433	printf("%*s</range>\n", $indent, "");
434}
435
436#
437# Process a single platform file.
438#
439sub process_platform
440{
441	my ($desc) = @_;
442	my $indent = 2;
443
444	printf("%*s<set type='product' setlist='%s'>\n", $indent, "",
445	    $desc->{set});
446
447	process_topology($indent + 2, $desc->{topology}, $desc->{set});
448
449	printf("%*s</set>\n", $indent, "");
450}
451
452print "<topology name='fan' scheme='hc'>\n";
453
454my $desc;
455foreach $desc (@platforms) {
456	process_platform($desc);
457}
458
459print "</topology>\n";
460