2N/A#!/usr/bin/perl -w
2N/A#
2N/A# CDDL HEADER START
2N/A#
2N/A# The contents of this file are subject to the terms of the
2N/A# Common Development and Distribution License (the "License").
2N/A# You may not use this file except in compliance with the License.
2N/A#
2N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A# or http://www.opensolaris.org/os/licensing.
2N/A# See the License for the specific language governing permissions
2N/A# and limitations under the License.
2N/A#
2N/A# When distributing Covered Code, include this CDDL HEADER in each
2N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A# If applicable, add the following below this CDDL HEADER, with the
2N/A# fields enclosed by brackets "[]" replaced with your own identifying
2N/A# information: Portions Copyright [yyyy] [name of copyright owner]
2N/A#
2N/A# CDDL HEADER END
2N/A#
2N/A#
2N/A# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A#
2N/A
2N/A#
2N/A# The fan topologies can be quite complicated, but are ultimately regular. This
2N/A# perl file uses some simplified internal structures to generate an .xml file
2N/A# without the maintenance overhead.
2N/A#
2N/A
2N/Ause Getopt::Std;
2N/Ause strict;
2N/A
2N/A#
2N/A# Master table of platforms.
2N/A#
2N/Amy @platforms = (
2N/A #
2N/A # Galaxy 1/2 platforms.
2N/A #
2N/A # These systems have 2 fan-connector boards. Each fan-connector board has 3
2N/A # fan modules. Each fan module is an individual FRU. The fan-connector
2N/A # boards are also FRUs.
2N/A #
2N/A {
2N/A set => "Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|" .
2N/A "Sun-Fire-X4100-M2|Sun-Fire-X4200-M2",
2N/A topology => [
2N/A {
2N/A label => "FT %d",
2N/A count => 2,
2N/A fru => "self"
2N/A }, {
2N/A fac_enum => 1,
2N/A provider => "fac_prov_ipmi",
2N/A count => 3,
2N/A label => "FT %d FM %d",
2N/A entity_ref => "ft%d.fm%d.led",
2N/A entity_ref_nparams => 2,
2N/A fm_service_indctr => "ft%d.fm%d.led",
2N/A fru => "self"
2N/A }
2N/A ]
2N/A },
2N/A
2N/A #
2N/A # Thumper platforms
2N/A #
2N/A # These systems have 5 fan modules, with each fan module containing 2 fans.
2N/A # The FRUs for the individual fans are the containing fan module.
2N/A #
2N/A {
2N/A set => "Sun-Fire-X4500|Sun-Fire-X4540",
2N/A topology => [
2N/A {
2N/A fac_enum => 0,
2N/A provider => "fac_prov_ipmi",
2N/A label => "FT %d",
2N/A count => 5,
2N/A fru => "self",
2N/A entity_ref => "FT%d/PRSNT,ft%d.prsnt",
2N/A entity_ref_nparams => 1,
2N/A fm_service_indctr => "FT%d/SVC,ft%d.service.led",
2N/A fm_ok2rm_indctr => "FT%d/OK,ft%d.ok2rm.led",
2N/A }, {
2N/A fac_enum => 1,
2N/A provider => "fac_prov_ipmi",
2N/A count => 2,
2N/A entity_ref => "FT%d/FAN%d/TACH,ft%d.f%d.speed",
2N/A entity_ref_nparams => 2,
2N/A fru => "parent"
2N/A }
2N/A ]
2N/A },
2N/A
2N/A #
2N/A # Fan Module/Fan topology for all G1N/G2N platforms.
2N/A #
2N/A # There are two fan boards, which are FRU's. Each fan board has
2N/A # 3 fan modules for a total of 6 fan modules, with each fan module
2N/A # containing 2 fans. The FRU's for the individual fans are the
2N/A # containing fan module.
2N/A #
2N/A # Unfortunately, the IPMI topology on these systems is rather broken, and
2N/A # all the SDRs that should be separate entities in fact refer to the same
2N/A # entity IDs. So we have to use the alternative 'entity_present' option
2N/A # using a single SDR record.
2N/A #
2N/A {
2N/A set => "Sun-Fire-X4240|Sun-Fire-X4440",
2N/A topology => [
2N/A {
2N/A count => 2,
2N/A label => "FANBD%d",
2N/A fru => "self"
2N/A }, {
2N/A label => "FANBD%d FM%d",
2N/A count => 3,
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_present => "FB%d/FM%d/PRSNT,fb%d.fm%d.prsnt",
2N/A fm_service_indctr=> "FB%d/FM%d/SERVICE,fb%d.fm%d.led",
2N/A entity_ref_nparams => 2
2N/A }, {
2N/A fac_enum => 1,
2N/A count => 2,
2N/A fru => "parent",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB%d/FM%d/F%d/TACH,fb%d.fm%d.f%d.speed",
2N/A entity_present => "FB%d/FM%d/PRSNT,fb%d.fm%d.prsnt",
2N/A entity_ref_nparams => 3
2N/A }
2N/A
2N/A ]
2N/A },
2N/A
2N/A #
2N/A # Fan Module/Fan topology for the Sun Fire X4600/X4600 M2 platforms.
2N/A #
2N/A # These systems have 4 fan assemblies with a single fan per assembly.
2N/A # Each fan assembly is a FRU. The fan assemblies have a service LED
2N/A # but no other indicators.
2N/A #
2N/A {
2N/A set => "Sun-Fire-X4600|Sun-Fire-X4600-M2",
2N/A topology => [
2N/A {
2N/A fac_enum => 1,
2N/A provider => "fac_prov_ipmi",
2N/A count => 4,
2N/A label => "FT %d",
2N/A fru => "self",
2N/A entity_ref => "ft%d.fm0.prsnt",
2N/A entity_ref_nparams => 1,
2N/A fm_service_indctr => "ft%d.fm0.led"
2N/A }
2N/A ]
2N/A },
2N/A
2N/A #
2N/A # Fan Module/Fan topology for Sun Fire X4140.
2N/A #
2N/A # There are two fan boards, which are FRU's. The first fanboard has 4
2N/A # fanmodules (which are also FRU's). The second fan board has 3 fan
2N/A # modules. Each fanmodule contains two fans.
2N/A #
2N/A {
2N/A set => "Sun-Fire-X4140",
2N/A topology => [
2N/A {
2N/A count => 2,
2N/A label => "FANBD%d",
2N/A fru => "self",
2N/A }, {
2N/A fac_enum => 1,
2N/A provider => "fac_prov_ipmi",
2N/A label => "FANBD%d FM%d",
2N/A count => 4,
2N/A fru => "self",
2N/A fm_service_indctr=> "FB%d/FM%d/SERVICE,fb%d.fm%d.led",
2N/A entity_ref_nparams => 2,
2N/A entity_ref => "fb%d.fm%d.prsnt"
2N/A }, {
2N/A fac_enum => 1,
2N/A provider => "fac_prov_ipmi",
2N/A count => 2,
2N/A fru => "parent",
2N/A entity_ref => "FB%d/FM%d/F%d/TACH,fb%d.fm%d.f%d.speed",
2N/A entity_ref_nparams => 3
2N/A }
2N/A
2N/A ]
2N/A },
2N/A #
2N/A # Fan Module/Fan topology for the Sun Fire X4150.
2N/A #
2N/A # There are two fan boards, which are FRU's. The first fanboard has 4
2N/A # fanmodules (which are also FRU's). The second fan board has 3 fan
2N/A # modules. Each fanmodule contains two fans.
2N/A #
2N/A {
2N/A set => "SUN-FIRE-X4150",
2N/A topology => [
2N/A {
2N/A count => 2,
2N/A label => "FANBD%d",
2N/A fru => "self",
2N/A entity_present => "FB%d/PRSRNT"
2N/A }, {
2N/A label => "FANBD%d FM%d",
2N/A count => 4,
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB%d/FM%d/PRSNT",
2N/A fm_service_indctr=> "",
2N/A entity_ref_nparams => 2
2N/A }, {
2N/A fac_enum => 1,
2N/A count => 2,
2N/A fru => "parent",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB%d/FM%d/F%d/TACH",
2N/A entity_ref_nparams => 3
2N/A }
2N/A
2N/A ]
2N/A },
2N/A #
2N/A # Fan Module/Fan topology for Duradi 2U.
2N/A #
2N/A # There are two fan boards, which are FRU's. Both fanboards have 3
2N/A # fanmodules (which are also FRU's). Each fanmodule contains two fans.
2N/A #
2N/A {
2N/A set => "SUN-FIRE-X4250|SUN-FIRE-X4450",
2N/A topology => [
2N/A {
2N/A count => 2,
2N/A label => "FANBD%d",
2N/A fru => "self",
2N/A entity_present => "FB%d/PRSRNT"
2N/A }, {
2N/A label => "FANBD%d FM%d",
2N/A count => 3,
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB%d/FM%d/PRSNT",
2N/A fm_service_indctr=> "",
2N/A entity_ref_nparams => 2
2N/A }, {
2N/A fac_enum => 1,
2N/A count => 2,
2N/A fru => "parent",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB%d/FM%d/F%d/TACH",
2N/A entity_ref_nparams => 3
2N/A }
2N/A
2N/A ]
2N/A },
2N/A #
2N/A # Fan Module/Fan topology for Callisto.
2N/A #
2N/A # There is one fan board, which is a FRU. Connected to the fanboard are
2N/A # 6 fanmodules (which are also FRU's). Each fanmodule contains one fan.
2N/A #
2N/A {
2N/A set => "SUN-FIRE-X4470-SERVER",
2N/A topology => [
2N/A {
2N/A count => 1,
2N/A label => "FANBD",
2N/A fru => "self",
2N/A }, {
2N/A fac_enum => 1,
2N/A label => "FAN%d",
2N/A count => 6,
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_present => "FB/FAN%d/PRSNT",
2N/A entity_ref => "FB/FAN%d/TACH",
2N/A fm_service_indctr => "FB/FAN%d/SERVICE",
2N/A entity_ref_nparams => 1
2N/A }
2N/A ]
2N/A },
2N/A #
2N/A # Fan Module/Fan topology for Callisto+
2N/A #
2N/A # There is one fan board, which is a FRU. Connected to the fanboard are
2N/A # 6 fanmodules (which are also FRU's). Each fanmodule contains one fan.
2N/A #
2N/A {
2N/A set => "SUN-FIRE-X4470-M2-SERVER",
2N/A topology => [
2N/A {
2N/A count => 1,
2N/A label => "FANBD",
2N/A fru => "self",
2N/A }, {
2N/A fac_enum => 1,
2N/A label => "FAN%d",
2N/A count => 6,
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_present => "FB/FAN%d/PRSNT",
2N/A entity_ref => "FB/FAN%d/TACH",
2N/A fm_service_indctr => "FB/FAN%d/SERVICE",
2N/A entity_ref_nparams => 1
2N/A }
2N/A ]
2N/A },
2N/A #
2N/A # Fan Module/Fan topology for Lynx+/Hyde.
2N/A #
2N/A # There is one fan board, which is a FRU. Connected to the fanboard are
2N/A # 6 fanmodules (which are also FRU's). Each fanmodule contains two fans.
2N/A #
2N/A {
2N/A set => "SUN-FIRE-X4270-M2-SERVER",
2N/A topology => [
2N/A {
2N/A count => 1,
2N/A label => "FANBD",
2N/A fru => "self",
2N/A entity_present => "FB/PRSNT"
2N/A }, {
2N/A label => "FM%d",
2N/A count => 6,
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB/FM%d/PRSNT",
2N/A fm_service_indctr=> "FB/FM%d/SERVICE",
2N/A entity_ref_nparams => 1
2N/A }, {
2N/A fac_enum => 1,
2N/A count => 2,
2N/A fru => "parent",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB/FM%d/F%d/TACH",
2N/A entity_ref_nparams => 2
2N/A }
2N/A ]
2N/A },
2N/A #
2N/A # Fan board/Fan Module/Fan topology for Lynx+/Thelma.
2N/A #
2N/A # There is one fan board, which is a FRU. Connected to the fanboard are
2N/A # 4 fanmodules (which are also FRU's). Each fanmodule contains four fans.
2N/A #
2N/A {
2N/A set => "SUN-FIRE-X4170-M2-SERVER",
2N/A topology => [
2N/A {
2N/A count => 1,
2N/A label => "FANBD",
2N/A fru => "self",
2N/A entity_present => "FB/PRSNT"
2N/A }, {
2N/A count => 4,
2N/A label => "FM%d",
2N/A fru => "self",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB/FM%d/PRSNT",
2N/A fm_service_indctr=> "FB/FM%d/SERVICE",
2N/A entity_ref_nparams => 1
2N/A }, {
2N/A fac_enum => 1,
2N/A count => 4,
2N/A fru => "parent",
2N/A provider => "fac_prov_ipmi",
2N/A entity_ref => "FB/FM%d/F%d/TACH",
2N/A entity_ref_nparams => 2
2N/A }
2N/A ]
2N/A }
2N/A);
2N/A
2N/A#
2N/A# Process an entry in the topology list. We are passed the indentation level,
2N/A# the current topology array, the set list, and any pushed indices. This is
2N/A# called recursively.
2N/A#
2N/Asub process_topology
2N/A{
2N/A my ($indent, $toporef, $set, @indices) = @_;
2N/A my @topo = @$toporef;
2N/A my $level = shift @topo;
2N/A my $type = $#topo == -1 ? "fan" : "fanmodule";
2N/A
2N/A printf("%*s<range name='%s' min='%d' max='%d'>\n",
2N/A $indent, "", $type, 0, $level->{count} - 1);
2N/A $indent += 2;
2N/A
2N/A for (my $i = 0; $i < $level->{count}; $i++) {
2N/A #
2N/A # Special case code for the 1U version of Durado and Duradi,
2N/A # both of which have an assymetric fan topology
2N/A #
2N/A last if ((($set eq "SUN-FIRE-X4150") || ($set eq "Sun-Fire-X4140"))
2N/A && ($type eq "fanmodule") && ($#indices == 0)
2N/A && ($indices[0] == 1) && ($i == 3));
2N/A
2N/A if ($set eq "SUN-FIRE-X4470-SERVER" ||
2N/A $set eq "SUN-FIRE-X4470-M2-SERVER" ||
2N/A $set eq "SUN-FIRE-X4270-M2-SERVER" ||
2N/A $set eq "SUN-FIRE-X4170-M2-SERVER") {
2N/A if (defined($level->{entity_ref_nparams}) &&
2N/A $#indices + 1 == $level->{entity_ref_nparams}) {
2N/A pop @indices;
2N/A }
2N/A }
2N/A push @indices, $i;
2N/A printf("%*s<node instance='%d'>\n", $indent, "", $i);
2N/A
2N/A $indent += 2;
2N/A
2N/A # Facility enumerator
2N/A if ($level->{fac_enum}) {
2N/A printf("%*s<fac-enum provider='",
2N/A $indent, "");
2N/A printf($level->{provider});
2N/A printf("' />\n");
2N/A }
2N/A
2N/A # Facility nodes for service and ok2rm LED's
2N/A if ($level->{fm_service_indctr}) {
2N/A printf("%*s<facility name='service' type='indicator' ".
2N/A "provider='fac_prov_ipmi' >\n", $indent+2, "");
2N/A printf("%*s<propgroup name='facility' version='1' ".
2N/A "name-stability='Private' data-stability='Private' >\n",
2N/A $indent+4, "");
2N/A printf("%*s<propval name='type' type='uint32' ".
2N/A "value='0' />\n", $indent+6, "");
2N/A printf("%*s<propmethod name='ipmi_entity' version='0' ".
2N/A "propname='entity_ref' proptype='string_array' >\n",
2N/A $indent+6, "");
2N/A
2N/A printf("%*s<argval name='format' type='string_array'>\n",
2N/A $indent+8, "");
2N/A my @refs = split(/\,/, $level->{fm_service_indctr});
2N/A foreach my $ref (@refs) {
2N/A printf("%*s<argitem value='", $indent+10, "");
2N/A printf($ref, @indices);
2N/A printf("' />\n");
2N/A }
2N/A
2N/A printf("%*s</argval>\n", $indent+8, "");
2N/A printf("%*s<argval name='offset' type='uint32' ".
2N/A "value='0' />\n", $indent+8, "");
2N/A printf("%*s<argval name='nparams' type='uint32' ".
2N/A "value='%d' />\n", $indent+8, "",
2N/A $level->{entity_ref_nparams});
2N/A printf("%*s</propmethod>\n", $indent+6, "");
2N/A printf("%*s<propmethod name='ipmi_indicator_mode' ".
2N/A "version='0' propname='mode' proptype='uint32' ".
2N/A "mutable='1' >\n", $indent+6, "");
2N/A printf("%*s</propmethod>\n", $indent+6, "");
2N/A printf("%*s</propgroup>\n", $indent+4, "");
2N/A printf("%*s</facility>\n", $indent+2, "");
2N/A }
2N/A if ($level->{fm_ok2rm_indctr}) {
2N/A printf("%*s<facility name='ok2rm' type='indicator' ".
2N/A "provider='fac_prov_ipmi' >\n", $indent+2, "");
2N/A printf("%*s<propgroup name='facility' version='1' ".
2N/A "name-stability='Private' data-stability='Private' >\n",
2N/A $indent+4, "");
2N/A printf("%*s<propval name='type' type='uint32' ".
2N/A "value='2' />\n", $indent+6, "");
2N/A printf("%*s<propmethod name='ipmi_entity' version='0' ".
2N/A "propname='entity_ref' proptype='string_array' >\n",
2N/A $indent+6, "");
2N/A
2N/A printf("%*s<argval name='format' type='string_array'>\n",
2N/A $indent+8, "");
2N/A my @refs = split(/\,/, $level->{fm_ok2rm_indctr});
2N/A foreach my $ref (@refs) {
2N/A printf("%*s<argitem value='", $indent+10, "");
2N/A printf($ref, @indices);
2N/A printf("' />\n");
2N/A }
2N/A printf("%*s</argval>\n", $indent+8, "");
2N/A printf("%*s<argval name='offset' type='uint32' ".
2N/A "value='0' />\n", $indent+8, "");
2N/A printf("%*s<argval name='nparams' type='uint32' ".
2N/A "value='%d' />\n", $indent+8, "",
2N/A $level->{entity_ref_nparams});
2N/A printf("%*s</propmethod>\n", $indent+6, "");
2N/A printf("%*s<propmethod name='ipmi_indicator_mode' ".
2N/A "version='0' propname='mode' proptype='uint32' mutable='1' >\n",
2N/A $indent+6, "");
2N/A printf("%*s</propmethod>\n", $indent+6, "");
2N/A printf("%*s</propgroup>\n", $indent+4, "");
2N/A printf("%*s</facility>\n", $indent+2, "");
2N/A }
2N/A
2N/A # Protocol properties (label, fmri)
2N/A printf("%*s<propgroup name='protocol' version='1' " .
2N/A "name-stability='Private' data-stability='Private'>\n",
2N/A $indent, "");
2N/A
2N/A $indent += 2;
2N/A
2N/A if ($level->{label}) {
2N/A printf("%*s<propval name='label' type='string' " .
2N/A "value='", $indent, "");
2N/A printf($level->{label}, @indices);
2N/A printf("' />\n");
2N/A }
2N/A
2N/A printf("%*s<propmethod name='ipmi_fru_fmri' " .
2N/A "version='0' propname='FRU' proptype='fmri'>\n",
2N/A $indent, "");
2N/A printf("%*s<argval name='entity' type='string' " .
2N/A "value='%s' />\n", $indent + 2, "", $level->{fru});
2N/A printf("%*s</propmethod>\n", $indent, "");
2N/A
2N/A $indent -= 2;
2N/A
2N/A printf("%*s</propgroup>\n", $indent, "");
2N/A
2N/A #
2N/A # Entity references (if any)
2N/A #
2N/A if ($level->{entity_ref}) {
2N/A my $val = $level->{entity_ref};
2N/A printf("%*s<propgroup name='ipmi' version='1' " .
2N/A "name-stability='Private' " .
2N/A "data-stability='Private' >\n", $indent, "");
2N/A
2N/A printf("%*s<propval name='entity_ref' ".
2N/A "type='string_array'>\n", $indent + 2, "");
2N/A my @refs = split(/\,/, $val);
2N/A foreach my $ref (@refs) {
2N/A printf("%*s<propitem value='", $indent+4, "");
2N/A printf($ref, @indices);
2N/A printf("' />\n");
2N/A }
2N/A printf("%*s</propval>\n", $indent+2, "");
2N/A printf("%*s</propgroup>\n", $indent, "");
2N/A }
2N/A if ($level->{entity_present}) {
2N/A my $val = $level->{entity_present};
2N/A printf("%*s<propgroup name='ipmi' version='1' " .
2N/A "name-stability='Private' " .
2N/A "data-stability='Private' >\n", $indent, "");
2N/A
2N/A printf("%*s<propval name='entity_present' " .
2N/A "type='string_array'>\n", $indent + 2, "");
2N/A my @refs = split(/\,/, $val);
2N/A foreach my $ref (@refs) {
2N/A printf("%*s<propitem value='", $indent+4, "");
2N/A printf($ref, @indices);
2N/A printf("' />\n");
2N/A }
2N/A printf("%*s</propval>\n", $indent+4, "");
2N/A printf("%*s</propgroup>\n", $indent, "");
2N/A }
2N/A
2N/A #
2N/A # Post-process IPMI enumerator method
2N/A #
2N/A printf("%*s<enum-method name='ipmi' version='1' ".
2N/A "/>\n", $indent, "");
2N/A
2N/A #
2N/A # Children (if any)
2N/A #
2N/A if ($#topo != -1) {
2N/A printf("%*s<dependents grouping='children'>\n",
2N/A $indent, "");
2N/A process_topology($indent + 2, \@topo, $set, @indices);
2N/A printf("%*s</dependents>\n", $indent, "");
2N/A }
2N/A
2N/A $indent -= 2;
2N/A
2N/A printf("%*s</node>\n", $indent, "");
2N/A pop @indices;
2N/A }
2N/A
2N/A $indent -= 2;
2N/A printf("%*s</range>\n", $indent, "");
2N/A}
2N/A
2N/A#
2N/A# Process a single platform file.
2N/A#
2N/Asub process_platform
2N/A{
2N/A my ($desc) = @_;
2N/A my $indent = 2;
2N/A
2N/A printf("%*s<set type='product' setlist='%s'>\n", $indent, "",
2N/A $desc->{set});
2N/A
2N/A process_topology($indent + 2, $desc->{topology}, $desc->{set});
2N/A
2N/A printf("%*s</set>\n", $indent, "");
2N/A}
2N/A
2N/Aprint "<topology name='fan' scheme='hc'>\n";
2N/A
2N/Amy $desc;
2N/Aforeach $desc (@platforms) {
2N/A process_platform($desc);
2N/A}
2N/A
2N/Aprint "</topology>\n";