Home | History | Annotate | Download | only in i86pc
      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 
     33 use Getopt::Std;
     34 use strict;
     35 
     36 #
     37 # Master table of platforms.
     38 #
     39 my @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,ft%d.prsnt",
     84 		entity_ref_nparams => 1,
     85 		fm_service_indctr => "FT%d/SVC,ft%d.service.led",
     86 		fm_ok2rm_indctr => "FT%d/OK,ft%d.ok2rm.led",
     87 	    }, {
     88 	        fac_enum => 1,
     89 		provider => "fac_prov_ipmi",
     90 		count => 2,
     91 		entity_ref => "FT%d/FAN%d/TACH,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,fb%d.fm%d.prsnt",
    124 		fm_service_indctr=> "FB%d/FM%d/SERVICE,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/TACH,fb%d.fm%d.f%d.speed",
    132 		entity_present => "FB%d/FM%d/PRSNT,fb%d.fm%d.prsnt",
    133 		entity_ref_nparams => 3
    134 	    }
    135 
    136 	]
    137     },
    138 
    139     #
    140     # Fan Module/Fan topology for the Sun Fire X4600/X4600 M2 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 Sun Fire X4140.
    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/SERVICE,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/TACH,fb%d.fm%d.f%d.speed",
    190 		entity_ref_nparams => 3
    191 	    }
    192 
    193 	]
    194     },
    195     #
    196     # Fan Module/Fan topology for the Sun Fire X4150.
    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|SUN-FIRE-X4450",
    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 #
    269 sub 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_array' >\n",
    314 			    $indent+6, "");
    315 
    316 			printf("%*s<argval name='format' type='string_array'>\n",
    317 			    $indent+8, "");
    318 			my @refs = split(/\,/, $level->{fm_service_indctr});
    319 			foreach my $ref (@refs) {
    320 				printf("%*s<argitem value='", $indent+10, "");
    321 				printf($ref, @indices);
    322 				printf("' />\n");
    323 			}
    324 			
    325 			printf("%*s</argval>\n", $indent+8, "");
    326 			printf("%*s<argval name='offset' type='uint32' ".
    327 			    "value='0' />\n", $indent+8, "");
    328 			printf("%*s<argval name='nparams' type='uint32' ".
    329 			    "value='%d' />\n", $indent+8, "",
    330 			    $level->{entity_ref_nparams});
    331 			printf("%*s</propmethod>\n", $indent+6, "");
    332 			printf("%*s<propmethod name='ipmi_indicator_mode' ".
    333 			    "version='0' propname='mode' proptype='uint32' ".
    334 			    "mutable='1' >\n", $indent+6, "");
    335 			printf("%*s</propmethod>\n", $indent+6, "");
    336 			printf("%*s</propgroup>\n", $indent+4, "");
    337 			printf("%*s</facility>\n", $indent+2, "");
    338 		}
    339 		if ($level->{fm_ok2rm_indctr}) {
    340 			printf("%*s<facility name='ok2rm' type='indicator' ".
    341 			    "provider='fac_prov_ipmi' >\n", $indent+2, "");
    342 			printf("%*s<propgroup name='facility' version='1' ".
    343 			    "name-stability='Private' data-stability='Private' >\n",
    344 			    $indent+4, "");
    345 			printf("%*s<propval name='type' type='uint32' ".
    346 			    "value='2' />\n", $indent+6, "");
    347 			printf("%*s<propmethod name='ipmi_entity' version='0' ".
    348 			    "propname='entity_ref' proptype='string_array' >\n",
    349 			    $indent+6, "");
    350 
    351 			printf("%*s<argval name='format' type='string_array'>\n",
    352 			    $indent+8, "");
    353 			my @refs = split(/\,/, $level->{fm_ok2rm_indctr});
    354 			foreach my $ref (@refs) {
    355 				printf("%*s<argitem value='", $indent+10, "");
    356 				printf($ref, @indices);
    357 				printf("' />\n");
    358 			}
    359 			printf("%*s</argval>\n", $indent+8, "");
    360 			printf("%*s<argval name='offset' type='uint32' ".
    361 			    "value='0' />\n", $indent+8, "");
    362 			printf("%*s<argval name='nparams' type='uint32' ".
    363 			    "value='%d' />\n", $indent+8, "",
    364 			    $level->{entity_ref_nparams});
    365 			printf("%*s</propmethod>\n", $indent+6, "");
    366 			printf("%*s<propmethod name='ipmi_indicator_mode' ".
    367 			    "version='0' propname='mode' proptype='uint32' mutable='1' >\n",
    368 			    $indent+6, "");
    369 			printf("%*s</propmethod>\n", $indent+6, "");
    370 			printf("%*s</propgroup>\n", $indent+4, "");
    371 			printf("%*s</facility>\n", $indent+2, "");
    372 		}
    373 
    374 		# Protocol properties (label, fmri)
    375 		printf("%*s<propgroup name='protocol' version='1' " .
    376 		    "name-stability='Private' data-stability='Private'>\n",
    377 		    $indent, "");
    378 
    379 		$indent += 2;
    380 
    381 		if ($level->{label}) {
    382 			printf("%*s<propval name='label' type='string' " .
    383 			    "value='", $indent, "");
    384 			printf($level->{label}, @indices);
    385 			printf("' />\n");
    386 		}
    387 
    388 		printf("%*s<propmethod name='ipmi_fru_fmri' " .
    389 		    "version='0' propname='FRU' proptype='fmri'>\n",
    390 		    $indent, "");
    391 		printf("%*s<argval name='entity' type='string' " .
    392 		    "value='%s' />\n", $indent + 2, "", $level->{fru});
    393 		printf("%*s</propmethod>\n", $indent, "");
    394 
    395 		$indent -= 2;
    396 
    397 		printf("%*s</propgroup>\n", $indent, "");
    398 
    399 		#
    400 		# Entity references (if any)
    401 		#
    402 		if ($level->{entity_ref}) {
    403 			my $val = $level->{entity_ref};
    404 			printf("%*s<propgroup name='ipmi' version='1' " .
    405 			    "name-stability='Private' " .
    406 			    "data-stability='Private' >\n", $indent, "");
    407 
    408 			printf("%*s<propval name='entity_ref' ".
    409 			    "type='string_array'>\n", $indent + 2, "");
    410 			my @refs = split(/\,/, $val);
    411 			foreach my $ref (@refs) {
    412 				printf("%*s<propitem value='", $indent+4, "");
    413 				printf($ref, @indices);
    414 				printf("' />\n");
    415 			}
    416 			printf("%*s</propval>\n", $indent+2, "");
    417 			printf("%*s</propgroup>\n", $indent, "");
    418 		}
    419 		if ($level->{entity_present}) {
    420 			my $val = $level->{entity_present};
    421 			printf("%*s<propgroup name='ipmi' version='1' " .
    422 			    "name-stability='Private' " .
    423 			    "data-stability='Private' >\n", $indent, "");
    424 
    425 			printf("%*s<propval name='entity_present' " .
    426 			    "type='string_array'>\n", $indent + 2, "");
    427 			my @refs = split(/\,/, $val);
    428 			foreach my $ref (@refs) {
    429 				printf("%*s<propitem value='", $indent+4, "");
    430 				printf($ref, @indices);
    431 				printf("' />\n");
    432 			}
    433 			printf("%*s</propval>\n", $indent+4, "");
    434 			printf("%*s</propgroup>\n", $indent, "");
    435 		}
    436 
    437 		#
    438 		# Post-process IPMI enumerator method
    439 		#
    440 		printf("%*s<enum-method name='ipmi' version='1' ".
    441 		    "/>\n", $indent, "");
    442 
    443 		#
    444 		# Children (if any)
    445 		#
    446 		if ($#topo != -1) {
    447 			printf("%*s<dependents grouping='children'>\n",
    448 			    $indent, "");
    449 			process_topology($indent + 2, \@topo, $set, @indices);
    450 			printf("%*s</dependents>\n", $indent, "");
    451 		}
    452 
    453 		$indent -= 2;
    454 
    455 		printf("%*s</node>\n", $indent, "");
    456 		pop @indices;
    457 	}
    458 
    459 	$indent -= 2;
    460 	printf("%*s</range>\n", $indent, "");
    461 }
    462 
    463 #
    464 # Process a single platform file.
    465 #
    466 sub process_platform
    467 {
    468 	my ($desc) = @_;
    469 	my $indent = 2;
    470 
    471 	printf("%*s<set type='product' setlist='%s'>\n", $indent, "",
    472 	    $desc->{set});
    473 
    474 	process_topology($indent + 2, $desc->{topology}, $desc->{set});
    475 
    476 	printf("%*s</set>\n", $indent, "");
    477 }
    478 
    479 print "<topology name='fan' scheme='hc'>\n";
    480 
    481 my $desc;
    482 foreach $desc (@platforms) {
    483 	process_platform($desc);
    484 }
    485 
    486 print "</topology>\n";
    487