xref: /onnv-gate/usr/src/uts/i86pc/cpu/scripts/ao_gendisp.pl (revision 5254:38162db71c7d)
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