Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / i86pc / cpu / scripts / ao_gendisp.pl
blob6c64e672a32e4f709c3ea3a552ccacf42175800e
1 #!/bin/perl
3 # CDDL HEADER START
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.
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.
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]
20 # CDDL HEADER END
24 # Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
27 # ident "%Z%%M% %I% %E% SMI"
30 use strict;
31 use File::Basename;
33 my $PROGNAME = basename($0);
35 my ($funcunit, $error);
36 my @funcunits = ();
37 my @errorrefs = ();
39 my $codelinesin = 0; # number of input 'code' lines for an ereport type
40 my $codeoutlen = 0; # number of output lines from sub state_code
42 my $state = "initial";
44 sub usage() {
45 print STDERR "Usage: $PROGNAME inputfile\n";
46 exit(2);
49 sub bail() {
50 print STDERR "$PROGNAME: ", join(" ", @_), "\n";
51 exit(1);
54 sub parsebail() {
55 print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n";
56 exit(1);
59 sub error_alloc() {
60 my @a = ();
62 push(@::errorrefs, \@a);
63 return (\@a);
66 sub error_dup() {
67 my ($drop) = @_;
68 my $newref = &error_alloc();
70 my $zeroref = $::errorrefs[0];
72 my $n = $#$zeroref - $drop;
74 @$newref = @$zeroref[0 .. $n];
77 sub code_lines() {
78 return ($::codelinesin++);
81 sub error_init() {
82 &error_alloc();
83 $::codelinesin = 0;
86 sub error_reset() {
87 @::errorrefs = ();
88 $::codelinesin = 0;
89 $::codeoutlen = 0;
92 sub errout() {
93 my ($line) = @_;
95 foreach my $ref (@::errorrefs) {
96 push(@$ref, $line);
100 sub errout_N() {
101 my ($instance, $line) = @_;
102 my $ref = @::errorrefs[$instance];
103 push(@$ref, $line);
104 return 1;
107 sub print_errout() {
108 foreach my $ref (@::errorrefs) {
109 print @$ref;
113 sub print_header() {
114 print "#include <sys/mca_x86.h>\n";
115 print "#include \"ao_mca_disp.h\"\n\n";
118 sub print_footer() {
119 print 'const ao_error_disp_t *ao_error_disp[] = {' . "\n";
121 foreach my $name (@funcunits) {
122 print "\t$name,\n";
125 print "};\n";
128 sub funcunit_begin() {
129 my $arrnm = "ao_error_disp_" . $_[0];
130 print "static const ao_error_disp_t " . $arrnm . "[] = {\n";
132 @funcunits = (@funcunits, $arrnm);
135 sub funcunit_end() {
136 print "\t{ NULL }\n};\n\n";
139 sub error_begin() {
140 my ($ereport_name) = @_;
142 $ereport_name =~ tr/[a-z]./[A-Z]_/;
143 my $flags_name = $ereport_name;
144 $flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/;
146 &errout("\tFM_$ereport_name,\n\tFM_$flags_name,\n");
149 sub error_end() {
150 &errout("\t},\n\n");
152 &print_errout();
154 &error_reset();
157 sub print_bits() {
158 my $name = $_[0];
159 my @bits = @_[1..$#_];
160 my $out = "";
162 if (@bits == 0) {
163 $out = "\t0,";
164 } elsif (@bits == 1) {
165 $out = "\t$bits[0],";
166 } else {
167 $out = "\t( " . join(" | ", @bits) . " ),";
170 $out .= " /* $name */" if (defined $name);
171 $out .= "\n";
173 return ($out);
176 sub field_burst() {
177 my ($field, $valuesref, $name, $prefix) = @_;
179 if ($field eq "-") {
180 return ();
183 map {
184 if (!defined ${$valuesref}{$_}) {
185 &parsebail("unknown $name value `$_'");
187 $_ = ${$valuesref}{$_};
188 tr/[a-z]/[A-Z]/;
189 $prefix . "_" . $_;
190 } split(/\//, $field);
193 sub bin2dec() {
194 my $bin = $_[0];
195 my $dec = 0;
197 foreach my $bit (split(//, $bin)) {
198 $dec = $dec * 2 + ($bit eq "1" ? 1 : 0);
201 $dec;
204 sub state_funcunit() {
205 my $val = $_[0];
207 if (defined $::funcunit) {
208 &funcunit_end();
211 $::funcunit = $val;
212 undef $::error;
213 &funcunit_begin($::funcunit);
216 sub state_desc() {
217 my $desc = $_[0];
219 &error_init();
221 &errout("\t/* $desc */\n\t{\n");
224 sub state_error() {
225 $::error = $_[0];
226 &error_begin($::error);
229 sub state_mask_on() {
230 @::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]);
233 sub state_mask_off() {
234 my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]);
236 &errout(&print_bits("mask", @::mask_on, @mask_off));
237 &errout(&print_bits("mask_res", @::mask_on));
240 sub state_code() {
241 my ($ext, $type, $pp, $t, $r4, $addr, $ii, $ll, $tt) =
242 split(/\s+/, $_[0]);
244 my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 );
245 my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 );
247 my %r4_values = (
248 'err' => 'err',
249 'rd' => 'rd',
250 'wr' => 'wr',
251 'drd' => 'drd',
252 'dwr' => 'dwr',
253 'ird' => 'ird',
254 'pf' => 'prefetch',
255 'ev' => 'evict',
256 'snp' => 'snoop',
257 '-' => '-');
259 my %pp_values = (
260 'src' => 'src',
261 'res' => 'res',
262 'obs' => 'obs',
263 'gen' => 'gen',
264 '-' => '-' );
266 my %t_values = ( 0 => 1, 1 => 1, '-' => 1 );
268 my %ii_values = (
269 'mem' => 'mem',
270 'io' => 'io',
271 'gen' => 'gen',
272 '-' => '-' );
274 my $instance = &code_lines();
275 if ($instance > 0) {
276 &error_dup($::codeoutlen); # dup info thus far
279 if (!defined $tt_values{$tt}) {
280 &parsebail("unknown tt value `$tt'");
283 if (!defined $ll_values{$ll}) {
284 &parsebail("unknown ll value `$ll'");
287 my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT");
289 my @pp = ($pp eq '-') ? () :
290 &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT");
292 if (!defined $t_values{$t}) {
293 &parsebail("unknown t value `$t'");
296 my @ii = ($ii eq '-') ? () :
297 &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT");
299 map {
300 tr/[a-z]/[A-Z]/;
301 } ($ii, $ll, $tt);
303 if ($type eq "bus") {
304 if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" ||
305 $ll eq "-" ||
306 $tt ne "-") {
307 &parsebail("invalid members for bus code type");
310 $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKBUS(" .
311 "0, " . # pp
312 "MCAX86_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " .
313 "0, " . # r4
314 "0, " . # ii
315 "MCAX86_ERRCODE_LL_$ll),\n");
317 } elsif ($type eq "mem") {
318 if ($r4 eq "-" || $tt eq "-" || $ll eq "-" ||
319 $pp ne "-" || $t ne "-" || $ii ne "-") {
320 &parsebail("invalid members for mem code type");
323 $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKMEM(" .
324 "0, " . # r4
325 "MCAX86_ERRCODE_TT_$tt, " .
326 "MCAX86_ERRCODE_LL_$ll),\n");
328 } elsif ($type eq "tlb") {
329 if ($tt eq "-" || $ll eq "-" ||
330 $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") {
331 &parsebail("invalid members for tlb code type");
334 $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKTLB(" .
335 "MCAX86_ERRCODE_TT_$tt, " .
336 "MCAX86_ERRCODE_LL_$ll),\n");
337 } else {
338 &parsebail("unknown code type `$type'");
341 $::codeoutlen += &errout_N($instance, "\t" . &bin2dec($ext) .
342 ", /* ext code $ext */\n");
344 $::codeoutlen += &errout_N($instance, &print_bits("pp_bits", @pp));
345 $::codeoutlen += &errout_N($instance, &print_bits("ii_bits", @ii));
346 $::codeoutlen += &errout_N($instance, &print_bits("r4_bits", @r4));
348 my $valid_hi;
349 my $valid_lo;
351 if ($addr eq "none") {
352 $valid_hi = $valid_lo = 0;
353 } elsif ($addr =~ /<(\d+):(\d+)>/) {
354 $valid_hi = $1;
355 $valid_lo = $2;
356 } else {
357 &parsebail("invalid addr specification");
359 $::codeoutlen += &errout_N($instance, "\t" . $valid_hi .
360 ", /* addr valid hi */\n");
361 $::codeoutlen += &errout_N($instance, "\t" . $valid_lo .
362 ", /* addr valid lo */\n");
365 sub state_panic() {
366 my @vals = split(/,\s*/, $_[0]);
368 if ($#vals < 0) {
369 &errout("\t0, /* panic_when */\n");
370 } else {
371 @vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals;
372 &errout(&print_bits("panic_when", @vals));
376 sub state_flags() {
377 my @flags = split(/,\s*/, $_[0]);
379 @flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags;
381 &errout(&print_bits("flags", @flags));
384 sub state_errtype() {
385 my @types = split(/,\s*/, $_[0]);
387 @types = map { tr/[a-z]/[A-Z]/; "AO_AED_ET_" . $_; } @types;
389 &errout(&print_bits("errtype", @types));
392 my %stateparse = (
393 funcunit => [ \&state_funcunit, 'desc' ],
394 desc => [ \&state_desc, 'error' ],
395 error => [ \&state_error, 'mask on' ],
396 'mask on' => [ \&state_mask_on, 'mask off' ],
397 'mask off' => [ \&state_mask_off, 'code' ],
398 code => [ \&state_code, 'code|panic' ],
399 panic => [ \&state_panic, 'flags' ],
400 flags => [ \&state_flags, 'errtype' ],
401 errtype => [ \&state_errtype, 'initial' ]
404 usage unless (@ARGV == 1);
406 my $infile = $ARGV[0];
407 open(INFILE, "<$infile") || &bail("failed to open $infile: $!");
409 &print_header();
411 while (<INFILE>) {
412 chop;
414 /^#/ && next;
415 /^$/ && next;
417 if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) {
418 &parsebail("failed to parse");
421 my ($keyword, $val) = ($1, $2);
423 if ($state eq "initial") {
424 if ($keyword eq "funcunit") {
425 $state = "funcunit";
426 } elsif ($keyword eq "desc") {
427 $state = "desc";
428 } else {
429 &parsebail("unexpected keyword $keyword between " .
430 "errors");
433 } elsif ($state eq "desc") {
434 if ($keyword eq "funcunit") {
435 $state = "funcunit";
439 if (!($keyword =~ /$state/)) {
440 &parsebail("keyword `$keyword' invalid here; expected " .
441 "`$state'");
443 $state = $keyword; # disambiguate between multiple legal states
445 if (!defined $stateparse{$state}) {
446 &parsebail("attempt to transition to invalid state `$state'");
449 my ($handler, $next) = @{$stateparse{$state}};
451 &{$handler}($val);
453 $state = $next;
455 if ($state eq "initial") {
456 &error_end();
460 close(INFILE);
462 if ($state ne "initial" && $state ne "desc") {
463 &bail("input file ended prematurely");
466 if (defined $::funcunit) {
467 &funcunit_end();
468 } else {
469 &bail("no functional units defined");
472 &print_footer;