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, Version 1.0 only 7# (the "License"). You may not use this file except in compliance 8# with the License. 9# 10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11# or http://www.opensolaris.org/os/licensing. 12# See the License for the specific language governing permissions 13# and limitations under the License. 14# 15# When distributing Covered Code, include this CDDL HEADER in each 16# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17# If applicable, add the following below this CDDL HEADER, with the 18# fields enclosed by brackets "[]" replaced with your own identifying 19# information: Portions Copyright [yyyy] [name of copyright owner] 20# 21# CDDL HEADER END 22# 23 24# 25# Copyright 2006 Sun Microsystems, Inc. All rights reserved. 26# Use is subject to license terms. 27# 28# ident "%Z%%M% %I% %E% SMI" 29# 30 31use strict; 32use File::Basename; 33 34my $PROGNAME = basename($0); 35 36my ($funcunit, $error); 37my @funcunits = (); 38 39my $state = "initial"; 40 41sub usage() { 42 print STDERR "Usage: $PROGNAME inputfile\n"; 43 exit(2); 44} 45 46sub bail() { 47 print STDERR "$PROGNAME: ", join(" ", @_), "\n"; 48 exit(1); 49} 50 51sub parsebail() { 52 print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n"; 53 exit(1); 54} 55 56sub print_header() { 57 print "#include \"ao_mca_disp.h\"\n\n"; 58} 59 60sub print_footer() { 61 print "const ao_error_disp_t *ao_error_disp[] = {\n"; 62 63 foreach my $name (@funcunits) { 64 print "\t$name,\n"; 65 } 66 67 print "};\n"; 68} 69 70sub funcunit_begin() { 71 my $arrnm = "ao_error_disp_" . $_[0]; 72 print "static const ao_error_disp_t " . $arrnm . "[] = {\n"; 73 74 @funcunits = (@funcunits, $arrnm); 75} 76 77sub funcunit_end() { 78 print "\tNULL\n};\n\n"; 79} 80 81sub error_begin() { 82 my ($ereport_name) = @_; 83 84 $ereport_name =~ tr/[a-z]./[A-Z]_/; 85 my $flags_name = $ereport_name; 86 $flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/; 87 88 print "\tFM_$ereport_name,\n\tFM_$flags_name,\n"; 89} 90 91sub error_end() { 92 print "\t},\n\n"; 93} 94 95sub print_bits() { 96 my $name = $_[0]; 97 my @bits = @_[1..$#_]; 98 99 if (@bits == 0) { 100 print "\t0,"; 101 } elsif (@bits == 1) { 102 print "\t$bits[0],"; 103 } else { 104 print "\t( ", join(" | ", @bits), " ),"; 105 } 106 107 print " /* $name */\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 $val = $_[0]; 276 277 if ($val eq "") { 278 print "\t0, /* panic_when */\n"; 279 } else { 280 $val =~ tr/[a-z]/[A-Z]/; 281 print "\tAO_AED_PANIC_$val,\n"; 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