#!/usr/bin/perl -w
use strict;

#########################################################################
# Variables
#
my $EXEDIR    = `dirname $0`;
chomp $EXEDIR;
my $BASEDIR   = "$EXEDIR/confdb";
my $PCIDBDIR  = "$BASEDIR/pci";
my $VENDORDB  = "$PCIDBDIR/vendors";
my $CONF_FILE = "./.config";


# Vendor ID's
my %VENDORIDS;

# Data for current card
my @carddata;

# Total number of cards found
my $numcards = 0;

# Hash to convert numbers to words...
my %enumnames = (
		 "1" => "first",
		 "2" => "secondary",
		 "3" => "third",
		 "4" => "fourth",
		 "5" => "fifth",
		 "6" => "sixth",
		 "7" => "seventh",
		 );

# The options we should write to the config file
my %configoptions = (
		     "2" => "CHIP:Chipset driver",
		     "3" => "ACCEL:Acceleration driver",
		     "4" => "CLK:Clockchip driver",
		     "5" => "DAC:RAMDAC driver",
		     );

#########################################################################
# Functions
#

sub make_vendorids {
    my $line;

    if (!open(FIL, "$VENDORDB")) {
	return 0;
    }
    my @lines = <FIL>;
    close(FIL);

    foreach $line (@lines) {
	my $id;
	my $name;
	chomp $line;
	($id, $name) = split(',', $line);
	%VENDORIDS = (%VENDORIDS, $id, $name);
    }
    return 1;
}

sub find_pcidevices {
    my $filename = "/proc/bus/pci/devices";
    my @devices = ();
    my $line;

    if (!open(FIL, "$filename")) {
	return ();
    }
    
    my @lines = <FIL>;
    close(FIL);

    foreach $line (@lines) {
	my $ven_dev = (split('\t', $line))[1];
	my $vendor = join('', (split(/ */, $ven_dev))[0..3]);
	my $device = join('', (split(/ */, $ven_dev))[4..7]);
	@devices = (($device, $vendor), @devices);
    }
    return @devices;
}

sub parse_cardfile {
    my $filename = $_[0];
    my $deviceid = $_[1];
    my $completevendorname = "";
    my $line;
    
    if (!open(FIL, "$filename")) {
	return ();
    }
    my @lines = <FIL>;
    close(FIL);
    
    foreach $line (@lines) {
	my @cardconf = split(',', $line);
	if ($cardconf[0] eq $deviceid) {
	    chomp @cardconf;
	    return (@cardconf, $completevendorname);
	} else {
	    if ($#cardconf < 5
		&& !($line eq "\n")
		&& !((split(/ */, $cardconf[0]))[0] eq '#')) {
		$completevendorname = $line;
		chomp $completevendorname;
	    }
	}
    }
    return ();
}
    
sub found_card {
    my @cardinfo = @_;
    my $numstr = $enumnames{$numcards};
    my $tmpstr = build_configstring(@cardinfo);
    my $ans;
    
    system("clear");
    print "Your $numstr PCI/AGP graphics board seems to be a:
  $cardinfo[6] $cardinfo[1]
A driver for this card would use the following options:\n";
    print "$tmpstr";
    print "\nDo you want to build this driver? [Y/n] ";
    $ans = getc(STDIN);
    getc;
    if ($ans eq "n" || $ans eq "N") {
	return 0;
    } else {
	return 1;
    }
}

sub build_configstring {
    my @cardinfo = @_;
    my $confstr = "\n";
    
    for (my $i=2; $i < 6; $i++) {
	my $class;
	my $type;
	my $option;
	my $desc;

	($option, $desc) = split(':', $configoptions{$i});
	($class, $type) = split(':', $cardinfo[$i]);
	$confstr = $confstr.
"# $desc
  $option"."_CLASS = $class
  $option"."_TYPE = $type\n";
    }
    return $confstr;
}

sub write_configuration {
    my $outfile = $_[0];

    if (!open(OUT, ">$outfile")) {
	return 0;
    }
    open(OUT, ">$outfile");
    print OUT "#\n# Autogenerated by $0\n#\n";
    print OUT "# Monitor driver\n  MON_CLASS = generic\n  MON_TYPE = generic";
    print OUT build_configstring(@carddata);
    print OUT "# VideoIO driver\n  VIDEO_CLASS = none\n  VIDEO_TYPE = none\n";
    close(OUT);
    return 1;
}


#########################################################################
# Now start the real work.
#

my @devices = find_pcidevices();
my $vendorid;
my $vendorname;
my $deviceid;

if (!make_vendorids()) {
    print "\nUnable to read vendor IDs from file: $VENDORDB\n\n";
    exit 1;
}

while ($vendorid = pop(@devices)) {
    $deviceid = pop(@devices);
    if ($vendorname = $VENDORIDS{$vendorid}) {
	if ((@carddata = parse_cardfile("$PCIDBDIR/$vendorname", $deviceid))) {
	    $numcards++;
	    if ($carddata[6] eq "") {
		$carddata[6] = $vendorname;
	    }
	    if (found_card(@carddata)) {
		print "Writing configuration for $carddata[6] $carddata[1] to file $CONF_FILE\n";
		if (!write_configuration($CONF_FILE)) {
		    print "\nUnable to write configfile!\n";
		    exit 1;
		} else {
		    print "DONE\n";
		    exit 0;
		}
	    }
#	    print "@carddata\n";
	}
    }
}
