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 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 fac_enum => 1, 120 provider => "fac_prov_ipmi", 121 label => "FANBD%d FM%d", 122 count => 3, 123 fru => "self", 124 entity_present => "fb%d.fm%d.prsnt", 125 entity_ref => "fb%d.fm%d.prsnt", 126 entity_ref_nparams => 2, 127 fm_service_indctr=> "fb%d.fm%d.led", 128 }, { 129 count => 2, 130 fru => "parent" 131 } 132 133 ] 134 }, 135 136 # 137 # Fan Module/Fan topology for G4F platforms. 138 # 139 # These systems have 4 fan assemblies with a single fan per assembly. 140 # Each fan assembly is a FRU. The fan assemblies have a service LED 141 # but no other indicators. 142 # 143 { 144 set => "Sun-Fire-X4600-M2", 145 topology => [ 146 { 147 fac_enum => 1, 148 provider => "fac_prov_ipmi", 149 count => 4, 150 label => "FT %d", 151 fru => "self", 152 entity_ref => "ft%d.fm0.prsnt", 153 entity_ref_nparams => 1, 154 fm_service_indctr => "ft%d.fm0.led" 155 } 156 ] 157 } 158); 159 160# 161# Process an entry in the topology list. We are passed the indentation level, 162# the current topology array, and any pushed indices. This is called 163# recursively. 164# 165sub process_topology 166{ 167 my ($indent, $toporef, @indices) = @_; 168 my @topo = @$toporef; 169 my $level = shift @topo; 170 my $type = $#topo == -1 ? "fan" : "fanmodule"; 171 172 printf("%*s<range name='%s' min='%d' max='%d'>\n", 173 $indent, "", $type, 0, $level->{count} - 1); 174 $indent += 2; 175 176 for (my $i = 0; $i < $level->{count}; $i++) { 177 push @indices, $i; 178 179 printf("%*s<node instance='%d'>\n", $indent, "", $i); 180 181 $indent += 2; 182 183 # Facility enumerator 184 if ($level->{fac_enum}) { 185 printf("%*s<fac-enum provider='", 186 $indent, ""); 187 printf($level->{provider}, @indices); 188 printf("' />\n"); 189 } 190 191 # Facility nodes for service and ok2rm LED's 192 if ($level->{fm_service_indctr}) { 193 printf("%*s<facility name='service' type='indicator' ". 194 "provider='fac_prov_ipmi' >\n", $indent+2, ""); 195 printf("%*s<propgroup name='facility' version='1' ". 196 "name-stability='Private' data-stability='Private' >\n", 197 $indent+4, ""); 198 printf("%*s<propval name='type' type='uint32' ". 199 "value='1' />\n", $indent+6, ""); 200 printf("%*s<propmethod name='ipmi_entity' version='0' ". 201 "propname='entity_ref' proptype='string' >\n", 202 $indent+6, ""); 203 printf("%*s<argval name='format' type='string' ". 204 "value='%s' />\n", $indent+8, "", 205 $level->{fm_service_indctr}); 206 printf("%*s<argval name='offset' type='uint32' ". 207 "value='0' />\n", $indent+8, ""); 208 printf("%*s<argval name='nparams' type='uint32' ". 209 "value='%d' />\n", $indent+8, "", 210 $level->{entity_ref_nparams}); 211 printf("%*s</propmethod>\n", $indent+6, ""); 212 printf("%*s<propmethod name='ipmi_indicator_mode' ". 213 "version='0' propname='mode' proptype='uint32' ". 214 "mutable='1' >\n", $indent+6, ""); 215 printf("%*s</propmethod>\n", $indent+6, ""); 216 printf("%*s</propgroup>\n", $indent+4, ""); 217 printf("%*s</facility>\n", $indent+2, ""); 218 } 219 if ($level->{fm_ok2rm_indctr}) { 220 printf("%*s<facility name='ok2rm' type='indicator' ". 221 "provider='fac_prov_ipmi' >\n", $indent+2, ""); 222 printf("%*s<propgroup name='facility' version='1' ". 223 "name-stability='Private' data-stability='Private' >\n", 224 $indent+4, ""); 225 printf("%*s<propval name='type' type='uint32' ". 226 "value='2' />\n", $indent+6, ""); 227 printf("%*s<propmethod name='ipmi_entity' version='0' ". 228 "propname='entity_ref' proptype='string' >\n", 229 $indent+6, ""); 230 printf("%*s<argval name='format' type='string' ". 231 "value='%s' />\n", $indent+8, "", 232 $level->{fm_ok2rm_indctr}); 233 printf("%*s<argval name='offset' type='uint32' ". 234 "value='0' />\n", $indent+8, ""); 235 printf("%*s<argval name='nparams' type='uint32' ". 236 "value='%d' />\n", $indent+8, "", 237 $level->{entity_ref_nparams}); 238 printf("%*s</propmethod>\n", $indent+6, ""); 239 printf("%*s<propmethod name='ipmi_indicator_mode' ". 240 "version='0' propname='mode' proptype='uint32' mutable='1' >\n", 241 $indent+6, ""); 242 printf("%*s</propmethod>\n", $indent+6, ""); 243 printf("%*s</propgroup>\n", $indent+4, ""); 244 printf("%*s</facility>\n", $indent+2, ""); 245 } 246 247 # Protocol properties (label, fmri) 248 printf("%*s<propgroup name='protocol' version='1' " . 249 "name-stability='Private' data-stability='Private'>\n", 250 $indent, ""); 251 252 $indent += 2; 253 254 if ($level->{label}) { 255 printf("%*s<propval name='label' type='string' " . 256 "value='", $indent, ""); 257 printf($level->{label}, @indices); 258 printf("' />\n"); 259 } 260 261 printf("%*s<propmethod name='ipmi_fru_fmri' " . 262 "version='0' propname='FRU' proptype='fmri'>\n", 263 $indent, ""); 264 printf("%*s<argval name='entity' type='string' " . 265 "value='%s' />\n", $indent + 2, "", $level->{fru}); 266 printf("%*s</propmethod>\n", $indent, ""); 267 268 $indent -= 2; 269 270 printf("%*s</propgroup>\n", $indent, ""); 271 272 # 273 # Entity references (if any) 274 # 275 if ($level->{entity_ref} || $level->{entity_present}) { 276 my $name = $level->{entity_ref} ? "entity_ref" : 277 "entity_present"; 278 my $val = $level->{$name}; 279 printf("%*s<propgroup name='ipmi' version='1' " . 280 "name-stability='Private' " . 281 "data-stability='Private' >\n", $indent, ""); 282 printf("%*s<propval name='%s' " . 283 "type='string' value='", $indent + 2, "", $name); 284 printf($val, @indices); 285 printf("' />\n"); 286 printf("%*s</propgroup>\n", $indent, ""); 287 } 288 289 # 290 # Post-process IPMI enumerator method 291 # 292 printf("%*s<enum-method name='ipmi' version='1' ". 293 "/>\n", $indent, ""); 294 295 # 296 # Children (if any) 297 # 298 if ($#topo != -1) { 299 printf("%*s<dependents grouping='children'>\n", 300 $indent, ""); 301 process_topology($indent + 2, \@topo, @indices); 302 printf("%*s</dependents>\n", $indent, ""); 303 } 304 305 $indent -= 2; 306 307 printf("%*s</node>\n", $indent, ""); 308 pop @indices; 309 } 310 311 $indent -= 2; 312 printf("%*s</range>\n", $indent, ""); 313} 314 315# 316# Process a single platform file. 317# 318sub process_platform 319{ 320 my ($desc) = @_; 321 my $indent = 2; 322 323 printf("%*s<set type='product' setlist='%s'>\n", $indent, "", 324 $desc->{set}); 325 326 process_topology($indent + 2, $desc->{topology}); 327 328 printf("%*s</set>\n", $indent, ""); 329} 330 331print "<topology name='fan' scheme='hc'>\n"; 332 333my $desc; 334foreach $desc (@platforms) { 335 process_platform($desc); 336} 337 338print "</topology>\n"; 339