11414Scindi#!/bin/perl 21414Scindi# 31414Scindi# CDDL HEADER START 41414Scindi# 51414Scindi# The contents of this file are subject to the terms of the 61538Sgavinm# Common Development and Distribution License (the "License"). 71538Sgavinm# You may not use this file except in compliance with the License. 81414Scindi# 91414Scindi# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 101414Scindi# or http://www.opensolaris.org/os/licensing. 111414Scindi# See the License for the specific language governing permissions 121414Scindi# and limitations under the License. 131414Scindi# 141414Scindi# When distributing Covered Code, include this CDDL HEADER in each 151414Scindi# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 161414Scindi# If applicable, add the following below this CDDL HEADER, with the 171414Scindi# fields enclosed by brackets "[]" replaced with your own identifying 181414Scindi# information: Portions Copyright [yyyy] [name of copyright owner] 191414Scindi# 201414Scindi# CDDL HEADER END 211414Scindi# 221414Scindi 231414Scindi# 24*5254Sgavinm# Copyright 2007 Sun Microsystems, Inc. All rights reserved. 251414Scindi# Use is subject to license terms. 261414Scindi# 271414Scindi# ident "%Z%%M% %I% %E% SMI" 281414Scindi# 291414Scindi 301414Scindiuse strict; 311414Scindiuse File::Basename; 321414Scindi 331414Scindimy $PROGNAME = basename($0); 341414Scindi 351414Scindimy ($funcunit, $error); 361414Scindimy @funcunits = (); 373164Sgavinmmy @errorrefs = (); 383164Sgavinm 393164Sgavinmmy $codelinesin = 0; # number of input 'code' lines for an ereport type 403164Sgavinmmy $codeoutlen = 0; # number of output lines from sub state_code 411414Scindi 421414Scindimy $state = "initial"; 431414Scindi 441414Scindisub usage() { 451414Scindi print STDERR "Usage: $PROGNAME inputfile\n"; 461414Scindi exit(2); 471414Scindi} 481414Scindi 491414Scindisub bail() { 501414Scindi print STDERR "$PROGNAME: ", join(" ", @_), "\n"; 511414Scindi exit(1); 521414Scindi} 531414Scindi 541414Scindisub parsebail() { 551414Scindi print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n"; 561414Scindi exit(1); 571414Scindi} 581414Scindi 593164Sgavinmsub error_alloc() { 603164Sgavinm my @a = (); 613164Sgavinm 623164Sgavinm push(@::errorrefs, \@a); 633164Sgavinm return (\@a); 643164Sgavinm} 653164Sgavinm 663164Sgavinmsub error_dup() { 673164Sgavinm my ($drop) = @_; 683164Sgavinm my $newref = &error_alloc(); 693164Sgavinm 703164Sgavinm my $zeroref = $::errorrefs[0]; 713164Sgavinm 723164Sgavinm my $n = $#$zeroref - $drop; 733164Sgavinm 743164Sgavinm @$newref = @$zeroref[0 .. $n]; 753164Sgavinm} 763164Sgavinm 773164Sgavinmsub code_lines() { 783164Sgavinm return ($::codelinesin++); 793164Sgavinm} 803164Sgavinm 813164Sgavinmsub error_init() { 823164Sgavinm &error_alloc(); 833164Sgavinm $::codelinesin = 0; 843164Sgavinm} 853164Sgavinm 863164Sgavinmsub error_reset() { 873164Sgavinm @::errorrefs = (); 883164Sgavinm $::codelinesin = 0; 893164Sgavinm $::codeoutlen = 0; 903164Sgavinm} 913164Sgavinm 923164Sgavinmsub errout() { 933164Sgavinm my ($line) = @_; 943164Sgavinm 953164Sgavinm foreach my $ref (@::errorrefs) { 963164Sgavinm push(@$ref, $line); 973164Sgavinm } 983164Sgavinm} 993164Sgavinm 1003164Sgavinmsub errout_N() { 1013164Sgavinm my ($instance, $line) = @_; 1023164Sgavinm my $ref = @::errorrefs[$instance]; 1033164Sgavinm push(@$ref, $line); 1043164Sgavinm return 1; 1053164Sgavinm} 1063164Sgavinm 1073164Sgavinmsub print_errout() { 1083164Sgavinm foreach my $ref (@::errorrefs) { 1093164Sgavinm print @$ref; 1103164Sgavinm } 1113164Sgavinm} 1123164Sgavinm 1131414Scindisub print_header() { 114*5254Sgavinm print "#include <sys/mca_x86.h>\n"; 1151414Scindi print "#include \"ao_mca_disp.h\"\n\n"; 1161414Scindi} 1171414Scindi 1181414Scindisub print_footer() { 1193164Sgavinm print 'const ao_error_disp_t *ao_error_disp[] = {' . "\n"; 1201414Scindi 1211414Scindi foreach my $name (@funcunits) { 1221414Scindi print "\t$name,\n"; 1231414Scindi } 1241414Scindi 1251414Scindi print "};\n"; 1261414Scindi} 1271414Scindi 1281414Scindisub funcunit_begin() { 1291414Scindi my $arrnm = "ao_error_disp_" . $_[0]; 1301414Scindi print "static const ao_error_disp_t " . $arrnm . "[] = {\n"; 1311414Scindi 1321414Scindi @funcunits = (@funcunits, $arrnm); 1331414Scindi} 1341414Scindi 1351414Scindisub funcunit_end() { 1363164Sgavinm print "\t{ NULL }\n};\n\n"; 1371414Scindi} 1381414Scindi 1391414Scindisub error_begin() { 1401414Scindi my ($ereport_name) = @_; 1411414Scindi 1421414Scindi $ereport_name =~ tr/[a-z]./[A-Z]_/; 1431414Scindi my $flags_name = $ereport_name; 1441414Scindi $flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/; 1451414Scindi 1463164Sgavinm &errout("\tFM_$ereport_name,\n\tFM_$flags_name,\n"); 1471414Scindi} 1481414Scindi 1491414Scindisub error_end() { 1503164Sgavinm &errout("\t},\n\n"); 1513164Sgavinm 1523164Sgavinm &print_errout(); 1533164Sgavinm 1543164Sgavinm &error_reset(); 1551414Scindi} 1561414Scindi 1571414Scindisub print_bits() { 1581414Scindi my $name = $_[0]; 1591414Scindi my @bits = @_[1..$#_]; 1603164Sgavinm my $out = ""; 1611414Scindi 1621414Scindi if (@bits == 0) { 1633164Sgavinm $out = "\t0,"; 1641414Scindi } elsif (@bits == 1) { 1653164Sgavinm $out = "\t$bits[0],"; 1661414Scindi } else { 1673164Sgavinm $out = "\t( " . join(" | ", @bits) . " ),"; 1681414Scindi } 1691414Scindi 1703164Sgavinm $out .= " /* $name */" if (defined $name); 1713164Sgavinm $out .= "\n"; 1723164Sgavinm 1733164Sgavinm return ($out); 1741414Scindi} 1751414Scindi 1761414Scindisub field_burst() { 1771414Scindi my ($field, $valuesref, $name, $prefix) = @_; 1781414Scindi 1791414Scindi if ($field eq "-") { 1801414Scindi return (); 1811414Scindi } 1821414Scindi 1831414Scindi map { 1841414Scindi if (!defined ${$valuesref}{$_}) { 1851414Scindi &parsebail("unknown $name value `$_'"); 1861414Scindi } 1871414Scindi $_ = ${$valuesref}{$_}; 1881414Scindi tr/[a-z]/[A-Z]/; 1891414Scindi $prefix . "_" . $_; 1901414Scindi } split(/\//, $field); 1911414Scindi} 1921414Scindi 1931414Scindisub bin2dec() { 1941414Scindi my $bin = $_[0]; 1951414Scindi my $dec = 0; 1961414Scindi 1971414Scindi foreach my $bit (split(//, $bin)) { 1981414Scindi $dec = $dec * 2 + ($bit eq "1" ? 1 : 0); 1991414Scindi } 2001414Scindi 2011414Scindi $dec; 2021414Scindi} 2031414Scindi 2041414Scindisub state_funcunit() { 2051414Scindi my $val = $_[0]; 2061414Scindi 2071414Scindi if (defined $::funcunit) { 2081414Scindi &funcunit_end(); 2091414Scindi } 2101414Scindi 2111414Scindi $::funcunit = $val; 2121414Scindi undef $::error; 2131414Scindi &funcunit_begin($::funcunit); 2141414Scindi} 2151414Scindi 2161414Scindisub state_desc() { 2171414Scindi my $desc = $_[0]; 2181414Scindi 2193164Sgavinm &error_init(); 2203164Sgavinm 2213164Sgavinm &errout("\t/* $desc */\n\t{\n"); 2221414Scindi} 2231414Scindi 2241414Scindisub state_error() { 2251414Scindi $::error = $_[0]; 2261414Scindi &error_begin($::error); 2271414Scindi} 2281414Scindi 2291414Scindisub state_mask_on() { 2301414Scindi @::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 2311414Scindi} 2321414Scindi 2331414Scindisub state_mask_off() { 2341414Scindi my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 2351414Scindi 2363164Sgavinm &errout(&print_bits("mask", @::mask_on, @mask_off)); 2373164Sgavinm &errout(&print_bits("mask_res", @::mask_on)); 2381414Scindi} 2391414Scindi 2401414Scindisub state_code() { 2413164Sgavinm my ($ext, $type, $pp, $t, $r4, $addr, $ii, $ll, $tt) = 2423164Sgavinm split(/\s+/, $_[0]); 2431414Scindi 2441414Scindi my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 ); 2451414Scindi my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 ); 2461414Scindi 2471414Scindi my %r4_values = ( 248*5254Sgavinm 'err' => 'err', 249*5254Sgavinm 'rd' => 'rd', 250*5254Sgavinm 'wr' => 'wr', 251*5254Sgavinm 'drd' => 'drd', 252*5254Sgavinm 'dwr' => 'dwr', 253*5254Sgavinm 'ird' => 'ird', 254*5254Sgavinm 'pf' => 'prefetch', 255*5254Sgavinm 'ev' => 'evict', 256*5254Sgavinm 'snp' => 'snoop', 2571414Scindi '-' => '-'); 2581414Scindi 2591414Scindi my %pp_values = ( 260*5254Sgavinm 'src' => 'src', 261*5254Sgavinm 'res' => 'res', 262*5254Sgavinm 'obs' => 'obs', 263*5254Sgavinm 'gen' => 'gen', 2641414Scindi '-' => '-' ); 2651414Scindi 2661414Scindi my %t_values = ( 0 => 1, 1 => 1, '-' => 1 ); 2671414Scindi 2681414Scindi my %ii_values = ( 269*5254Sgavinm 'mem' => 'mem', 270*5254Sgavinm 'io' => 'io', 271*5254Sgavinm 'gen' => 'gen', 2721414Scindi '-' => '-' ); 2731414Scindi 2743164Sgavinm my $instance = &code_lines(); 2753164Sgavinm if ($instance > 0) { 2763164Sgavinm &error_dup($::codeoutlen); # dup info thus far 2773164Sgavinm } 2783164Sgavinm 2791414Scindi if (!defined $tt_values{$tt}) { 2801414Scindi &parsebail("unknown tt value `$tt'"); 2811414Scindi } 2821414Scindi 2831414Scindi if (!defined $ll_values{$ll}) { 2841414Scindi &parsebail("unknown ll value `$ll'"); 2851414Scindi } 2861414Scindi 2871414Scindi my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT"); 2881414Scindi 2891414Scindi my @pp = ($pp eq '-') ? () : 2901414Scindi &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT"); 2911414Scindi 2921414Scindi if (!defined $t_values{$t}) { 2931414Scindi &parsebail("unknown t value `$t'"); 2941414Scindi } 2951414Scindi 2961414Scindi my @ii = ($ii eq '-') ? () : 2971414Scindi &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT"); 2981414Scindi 2991414Scindi map { 3001414Scindi tr/[a-z]/[A-Z]/; 3011414Scindi } ($ii, $ll, $tt); 3021414Scindi 3031414Scindi if ($type eq "bus") { 3041414Scindi if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" || 3051414Scindi $ll eq "-" || 3061414Scindi $tt ne "-") { 3071414Scindi &parsebail("invalid members for bus code type"); 3081414Scindi } 3091414Scindi 3103164Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKBUS(" . 3111414Scindi "0, " . # pp 312*5254Sgavinm "MCAX86_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " . 3131414Scindi "0, " . # r4 3141414Scindi "0, " . # ii 315*5254Sgavinm "MCAX86_ERRCODE_LL_$ll),\n"); 3161414Scindi 3171414Scindi } elsif ($type eq "mem") { 3181414Scindi if ($r4 eq "-" || $tt eq "-" || $ll eq "-" || 3191414Scindi $pp ne "-" || $t ne "-" || $ii ne "-") { 3201414Scindi &parsebail("invalid members for mem code type"); 3211414Scindi } 3221414Scindi 3233164Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKMEM(" . 3241414Scindi "0, " . # r4 325*5254Sgavinm "MCAX86_ERRCODE_TT_$tt, " . 326*5254Sgavinm "MCAX86_ERRCODE_LL_$ll),\n"); 3271414Scindi 3281414Scindi } elsif ($type eq "tlb") { 3291414Scindi if ($tt eq "-" || $ll eq "-" || 3301414Scindi $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") { 3311414Scindi &parsebail("invalid members for tlb code type"); 3321414Scindi } 3331414Scindi 3343164Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKTLB(" . 335*5254Sgavinm "MCAX86_ERRCODE_TT_$tt, " . 336*5254Sgavinm "MCAX86_ERRCODE_LL_$ll),\n"); 3371414Scindi } else { 3381414Scindi &parsebail("unknown code type `$type'"); 3391414Scindi } 3401414Scindi 3413164Sgavinm $::codeoutlen += &errout_N($instance, "\t" . &bin2dec($ext) . 3423164Sgavinm ", /* ext code $ext */\n"); 3433164Sgavinm 3443164Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("pp_bits", @pp)); 3453164Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("ii_bits", @ii)); 3463164Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("r4_bits", @r4)); 3473164Sgavinm 3483164Sgavinm my $valid_hi; 3493164Sgavinm my $valid_lo; 3501414Scindi 3513164Sgavinm if ($addr eq "none") { 3523164Sgavinm $valid_hi = $valid_lo = 0; 3533164Sgavinm } elsif ($addr =~ /<(\d+):(\d+)>/) { 3543164Sgavinm $valid_hi = $1; 3553164Sgavinm $valid_lo = $2; 3563164Sgavinm } else { 3573164Sgavinm &parsebail("invalid addr specification"); 3583164Sgavinm } 3593164Sgavinm $::codeoutlen += &errout_N($instance, "\t" . $valid_hi . 3603164Sgavinm ", /* addr valid hi */\n"); 3613164Sgavinm $::codeoutlen += &errout_N($instance, "\t" . $valid_lo . 3623164Sgavinm ", /* addr valid lo */\n"); 3631414Scindi} 3641414Scindi 3651414Scindisub state_panic() { 3661538Sgavinm my @vals = split(/,\s*/, $_[0]); 3671414Scindi 3681538Sgavinm if ($#vals < 0) { 3693164Sgavinm &errout("\t0, /* panic_when */\n"); 3701414Scindi } else { 3711538Sgavinm @vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals; 3723164Sgavinm &errout(&print_bits("panic_when", @vals)); 3731414Scindi } 3741414Scindi} 3751414Scindi 3761414Scindisub state_flags() { 3771414Scindi my @flags = split(/,\s*/, $_[0]); 3781414Scindi 3791414Scindi @flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags; 3801414Scindi 3813164Sgavinm &errout(&print_bits("flags", @flags)); 3821414Scindi} 3831414Scindi 384*5254Sgavinmsub state_errtype() { 385*5254Sgavinm my @types = split(/,\s*/, $_[0]); 386*5254Sgavinm 387*5254Sgavinm @types = map { tr/[a-z]/[A-Z]/; "AO_AED_ET_" . $_; } @types; 388*5254Sgavinm 389*5254Sgavinm &errout(&print_bits("errtype", @types)); 390*5254Sgavinm} 391*5254Sgavinm 3921414Scindimy %stateparse = ( 3933164Sgavinm funcunit => [ \&state_funcunit, 'desc' ], 3943164Sgavinm desc => [ \&state_desc, 'error' ], 3953164Sgavinm error => [ \&state_error, 'mask on' ], 3963164Sgavinm 'mask on' => [ \&state_mask_on, 'mask off' ], 3973164Sgavinm 'mask off' => [ \&state_mask_off, 'code' ], 3983164Sgavinm code => [ \&state_code, 'code|panic' ], 3993164Sgavinm panic => [ \&state_panic, 'flags' ], 400*5254Sgavinm flags => [ \&state_flags, 'errtype' ], 401*5254Sgavinm errtype => [ \&state_errtype, 'initial' ] 4021414Scindi); 4031414Scindi 4041414Scindiusage unless (@ARGV == 1); 4051414Scindi 4061414Scindimy $infile = $ARGV[0]; 4071414Scindiopen(INFILE, "<$infile") || &bail("failed to open $infile: $!"); 4081414Scindi 4091414Scindi&print_header(); 4101414Scindi 4111414Scindiwhile (<INFILE>) { 4121414Scindi chop; 4131414Scindi 4141414Scindi /^#/ && next; 4151414Scindi /^$/ && next; 4161414Scindi 4171414Scindi if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) { 4181414Scindi &parsebail("failed to parse"); 4191414Scindi } 4201414Scindi 4211414Scindi my ($keyword, $val) = ($1, $2); 4221414Scindi 4231414Scindi if ($state eq "initial") { 4241414Scindi if ($keyword eq "funcunit") { 4251414Scindi $state = "funcunit"; 4261414Scindi } elsif ($keyword eq "desc") { 4271414Scindi $state = "desc"; 4281414Scindi } else { 4291414Scindi &parsebail("unexpected keyword $keyword between " . 4301414Scindi "errors"); 4311414Scindi } 4321414Scindi 4331414Scindi } elsif ($state eq "desc") { 4341414Scindi if ($keyword eq "funcunit") { 4351414Scindi $state = "funcunit"; 4361414Scindi } 4371414Scindi } 4381414Scindi 4393164Sgavinm if (!($keyword =~ /$state/)) { 4403164Sgavinm &parsebail("keyword `$keyword' invalid here; expected " . 4413164Sgavinm "`$state'"); 4421414Scindi } 4433164Sgavinm $state = $keyword; # disambiguate between multiple legal states 4441414Scindi 4451414Scindi if (!defined $stateparse{$state}) { 4461414Scindi &parsebail("attempt to transition to invalid state `$state'"); 4471414Scindi } 4481414Scindi 4491414Scindi my ($handler, $next) = @{$stateparse{$state}}; 4501414Scindi 4511414Scindi &{$handler}($val); 4521414Scindi 4531414Scindi $state = $next; 4541414Scindi 4551414Scindi if ($state eq "initial") { 4561414Scindi &error_end(); 4571414Scindi } 4581414Scindi} 4591414Scindi 4601414Scindiclose(INFILE); 4611414Scindi 4621414Scindiif ($state ne "initial" && $state ne "desc") { 4631414Scindi &bail("input file ended prematurely"); 4641414Scindi} 4651414Scindi 4661414Scindiif (defined $::funcunit) { 4671414Scindi &funcunit_end(); 4681414Scindi} else { 4691414Scindi &bail("no functional units defined"); 4701414Scindi} 4711414Scindi 4721414Scindi&print_footer; 473