1#!/bin/perl 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# 24# Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27# ident "%Z%%M% %I% %E% SMI" 28# 29 30use strict; 31use File::Basename; 32 33my $PROGNAME = basename($0); 34 35my ($funcunit, $error); 36my @funcunits = (); 37 38my $state = "initial"; 39 40sub usage() { 41 print STDERR "Usage: $PROGNAME inputfile\n"; 42 exit(2); 43} 44 45sub bail() { 46 print STDERR "$PROGNAME: ", join(" ", @_), "\n"; 47 exit(1); 48} 49 50sub parsebail() { 51 print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n"; 52 exit(1); 53} 54 55sub print_header() { 56 print "#include \"ao_mca_disp.h\"\n\n"; 57} 58 59sub print_footer() { 60 print "const ao_error_disp_t *ao_error_disp[] = {\n"; 61 62 foreach my $name (@funcunits) { 63 print "\t$name,\n"; 64 } 65 66 print "};\n"; 67} 68 69sub funcunit_begin() { 70 my $arrnm = "ao_error_disp_" . $_[0]; 71 print "static const ao_error_disp_t " . $arrnm . "[] = {\n"; 72 73 @funcunits = (@funcunits, $arrnm); 74} 75 76sub funcunit_end() { 77 print "\tNULL\n};\n\n"; 78} 79 80sub error_begin() { 81 my ($ereport_name) = @_; 82 83 $ereport_name =~ tr/[a-z]./[A-Z]_/; 84 my $flags_name = $ereport_name; 85 $flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/; 86 87 print "\tFM_$ereport_name,\n\tFM_$flags_name,\n"; 88} 89 90sub error_end() { 91 print "\t},\n\n"; 92} 93 94sub print_bits() { 95 my $name = $_[0]; 96 my @bits = @_[1..$#_]; 97 98 if (@bits == 0) { 99 print "\t0,"; 100 } elsif (@bits == 1) { 101 print "\t$bits[0],"; 102 } else { 103 print "\t( ", join(" | ", @bits), " ),"; 104 } 105 106 print " /* $name */" if (defined $name); 107 print "\n"; 108} 109 110sub field_burst() { 111 my ($field, $valuesref, $name, $prefix) = @_; 112 113 if ($field eq "-") { 114 return (); 115 } 116 117 map { 118 if (!defined ${$valuesref}{$_}) { 119 &parsebail("unknown $name value `$_'"); 120 } 121 $_ = ${$valuesref}{$_}; 122 tr/[a-z]/[A-Z]/; 123 $prefix . "_" . $_; 124 } split(/\//, $field); 125} 126 127sub bin2dec() { 128 my $bin = $_[0]; 129 my $dec = 0; 130 131 foreach my $bit (split(//, $bin)) { 132 $dec = $dec * 2 + ($bit eq "1" ? 1 : 0); 133 } 134 135 $dec; 136} 137 138sub state_funcunit() { 139 my $val = $_[0]; 140 141 if (defined $::funcunit) { 142 &funcunit_end(); 143 } 144 145 $::funcunit = $val; 146 undef $::error; 147 &funcunit_begin($::funcunit); 148} 149 150sub state_desc() { 151 my $desc = $_[0]; 152 153 print "\t/* $desc */\n\t{\n"; 154} 155 156sub state_error() { 157 $::error = $_[0]; 158 &error_begin($::error); 159} 160 161sub state_mask_on() { 162 @::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 163} 164 165sub state_mask_off() { 166 my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 167 168 &print_bits("mask", @::mask_on, @mask_off); 169 &print_bits("mask_res", @::mask_on); 170} 171 172sub state_code() { 173 my ($ext, $type, $pp, $t, $r4, $ii, $ll, $tt) = split(/\s+/, $_[0]); 174 175 my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 ); 176 my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 ); 177 178 my %r4_values = ( 179 gen => 'gen', 180 rd => 'rd', 181 wr => 'wr', 182 drd => 'drd', 183 dwr => 'dwr', 184 ird => 'ird', 185 pf => 'prefetch', 186 ev => 'evict', 187 snp => 'snoop', 188 '-' => '-'); 189 190 my %pp_values = ( 191 src => 'src', 192 rsp => 'rsp', 193 obs => 'obs', 194 gen => 'gen', 195 '-' => '-' ); 196 197 my %t_values = ( 0 => 1, 1 => 1, '-' => 1 ); 198 199 my %ii_values = ( 200 mem => 'mem', 201 io => 'io', 202 gen => 'gen', 203 '-' => '-' ); 204 205 if (!defined $tt_values{$tt}) { 206 &parsebail("unknown tt value `$tt'"); 207 } 208 209 if (!defined $ll_values{$ll}) { 210 &parsebail("unknown ll value `$ll'"); 211 } 212 213 my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT"); 214 215 my @pp = ($pp eq '-') ? () : 216 &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT"); 217 218 if (!defined $t_values{$t}) { 219 &parsebail("unknown t value `$t'"); 220 } 221 222 my @ii = ($ii eq '-') ? () : 223 &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT"); 224 225 map { 226 tr/[a-z]/[A-Z]/; 227 } ($ii, $ll, $tt); 228 229 if ($type eq "bus") { 230 if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" || 231 $ll eq "-" || 232 $tt ne "-") { 233 &parsebail("invalid members for bus code type"); 234 } 235 236 print "\tAMD_ERRCODE_MKBUS(" . 237 "0, " . # pp 238 "AMD_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " . 239 "0, " . # r4 240 "0, " . # ii 241 "AMD_ERRCODE_LL_$ll),\n"; 242 243 } elsif ($type eq "mem") { 244 if ($r4 eq "-" || $tt eq "-" || $ll eq "-" || 245 $pp ne "-" || $t ne "-" || $ii ne "-") { 246 &parsebail("invalid members for mem code type"); 247 } 248 249 print "\tAMD_ERRCODE_MKMEM(" . 250 "0, " . # r4 251 "AMD_ERRCODE_TT_$tt, " . 252 "AMD_ERRCODE_LL_$ll),\n"; 253 254 } elsif ($type eq "tlb") { 255 if ($tt eq "-" || $ll eq "-" || 256 $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") { 257 &parsebail("invalid members for tlb code type"); 258 } 259 260 print "\tAMD_ERRCODE_MKTLB(" . 261 "AMD_ERRCODE_TT_$tt, " . 262 "AMD_ERRCODE_LL_$ll),\n"; 263 } else { 264 &parsebail("unknown code type `$type'"); 265 } 266 267 print "\t" . &bin2dec($ext) . ", /* ext code $ext */\n"; 268 269 &print_bits("pp_bits", @pp); 270 &print_bits("ii_bits", @ii); 271 &print_bits("r4_bits", @r4); 272} 273 274sub state_panic() { 275 my @vals = split(/,\s*/, $_[0]); 276 277 if ($#vals < 0) { 278 print "\t0, /* panic_when */\n"; 279 } else { 280 @vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals; 281 &print_bits("panic_when", @vals); 282 } 283} 284 285sub state_flags() { 286 my @flags = split(/,\s*/, $_[0]); 287 288 @flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags; 289 290 &print_bits("flags", @flags); 291} 292 293my %stateparse = ( 294 funcunit => [ \&state_funcunit, "desc" ], 295 desc => [ \&state_desc, "error" ], 296 error => [ \&state_error, "mask on" ], 297 'mask on' => [ \&state_mask_on, "mask off" ], 298 'mask off' => [ \&state_mask_off, "code" ], 299 code => [ \&state_code, "panic" ], 300 panic => [ \&state_panic, "flags" ], 301 flags => [ \&state_flags, "initial" ] 302); 303 304usage unless (@ARGV == 1); 305 306my $infile = $ARGV[0]; 307open(INFILE, "<$infile") || &bail("failed to open $infile: $!"); 308 309&print_header(); 310 311while (<INFILE>) { 312 chop; 313 314 /^#/ && next; 315 /^$/ && next; 316 317 if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) { 318 &parsebail("failed to parse"); 319 } 320 321 my ($keyword, $val) = ($1, $2); 322 323 if ($state eq "initial") { 324 if ($keyword eq "funcunit") { 325 $state = "funcunit"; 326 } elsif ($keyword eq "desc") { 327 $state = "desc"; 328 } else { 329 &parsebail("unexpected keyword $keyword between " . 330 "errors"); 331 } 332 333 } elsif ($state eq "desc") { 334 if ($keyword eq "funcunit") { 335 $state = "funcunit"; 336 } 337 } 338 339 if ($keyword ne $state) { 340 &parsebail("keyword `$keyword' invalid here; expected `$state'"); 341 } 342 343 if (!defined $stateparse{$state}) { 344 &parsebail("attempt to transition to invalid state `$state'"); 345 } 346 347 my ($handler, $next) = @{$stateparse{$state}}; 348 349 &{$handler}($val); 350 351 $state = $next; 352 353 if ($state eq "initial") { 354 &error_end(); 355 } 356} 357 358close(INFILE); 359 360if ($state ne "initial" && $state ne "desc") { 361 &bail("input file ended prematurely"); 362} 363 364if (defined $::funcunit) { 365 &funcunit_end(); 366} else { 367 &bail("no functional units defined"); 368} 369 370&print_footer; 371