1254852Sdumbbell#!/usr/bin/perl 2254852Sdumbbell# $FreeBSD$ 3254852Sdumbbell 4254852Sdumbbelluse strict; 5254852Sdumbbelluse warnings; 6254852Sdumbbelluse utf8; 7254852Sdumbbell 8254852Sdumbbelluse File::Basename; 9254852Sdumbbell 10254852Sdumbbellmy $progname = basename($0); 11254852Sdumbbell 12254852Sdumbbellsub parse_linux_header ($) 13254852Sdumbbell{ 14254852Sdumbbell my ($header) = @_; 15254852Sdumbbell 16254852Sdumbbell open(my $fh, '<', $header) or die "Can't open Linux header: $!\n"; 17254852Sdumbbell 18254852Sdumbbell my $in_list = 0; 19254852Sdumbbell 20254852Sdumbbell my %pciids = (); 21254852Sdumbbell 22254852Sdumbbell my $current_vendor_define; 23254852Sdumbbell 24254852Sdumbbell while (my $line = <$fh>) { 25254852Sdumbbell if ($line =~ /^#define +([^ ]+) +/) { 26254852Sdumbbell $current_vendor_define = $1; 27254852Sdumbbell $pciids{$current_vendor_define} = {}; 28254852Sdumbbell } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}),[^,]+,[^,]+,[^,]+,[^,]+, *([^}]+)\}/) { 29254852Sdumbbell my $vendor_id = uc($1); 30254852Sdumbbell my $device_id = uc($2); 31254852Sdumbbell my $flags = $3; 32254852Sdumbbell 33254852Sdumbbell $pciids{$current_vendor_define}{$device_id} = { 34254852Sdumbbell 'vendor_id' => $vendor_id, 35254852Sdumbbell 'flags' => $flags 36254852Sdumbbell }; 37254852Sdumbbell } 38254852Sdumbbell } 39254852Sdumbbell 40254852Sdumbbell close($fh); 41254852Sdumbbell 42254852Sdumbbell return %pciids; 43254852Sdumbbell} 44254852Sdumbbell 45254852Sdumbbellsub parse_freebsd_header ($) { 46254852Sdumbbell my ($header) = @_; 47254852Sdumbbell 48254852Sdumbbell open(my $fh, '<', $header) or die "Can't open FreeBSD header: $!\n"; 49254852Sdumbbell 50254852Sdumbbell my $in_list = 0; 51254852Sdumbbell 52254852Sdumbbell my %pciids = (); 53254852Sdumbbell 54254852Sdumbbell my $current_vendor_define; 55254852Sdumbbell 56254852Sdumbbell while (my $line = <$fh>) { 57254852Sdumbbell if ($line =~ /^#define +([^ ]+) +/) { 58254852Sdumbbell $current_vendor_define = $1; 59254852Sdumbbell $pciids{$current_vendor_define} = {}; 60254852Sdumbbell } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}), *([^,]+), *"([^"]+)"\}/) { 61254852Sdumbbell my $vendor_id = uc($1); 62254852Sdumbbell my $device_id = uc($2); 63254852Sdumbbell my $flags = $3; 64254852Sdumbbell my $name = $4; 65254852Sdumbbell 66254852Sdumbbell $pciids{$current_vendor_define}{$device_id} = { 67254852Sdumbbell 'vendor_id' => $vendor_id, 68254852Sdumbbell 'flags' => $flags, 69254852Sdumbbell 'name' => $name 70254852Sdumbbell }; 71254852Sdumbbell } 72254852Sdumbbell } 73254852Sdumbbell 74254852Sdumbbell close($fh); 75254852Sdumbbell 76254852Sdumbbell return %pciids; 77254852Sdumbbell} 78254852Sdumbbell 79254852Sdumbbellsub parse_pciids_db ($) { 80254852Sdumbbell my ($header) = @_; 81254852Sdumbbell 82254852Sdumbbell open(my $fh, '<', $header) or die "Can't open PCI IDs database: $!\n"; 83254852Sdumbbell 84254852Sdumbbell my %pciids = (); 85254852Sdumbbell 86254852Sdumbbell my $current_vendor_id; 87254852Sdumbbell 88254852Sdumbbell while (my $line = <$fh>) { 89254852Sdumbbell if (!$line || $line =~ /^#/) { 90254852Sdumbbell next; 91254852Sdumbbell } 92254852Sdumbbell if ($line =~ /^([0-9a-fA-F]{4}) (.+)/) { 93254852Sdumbbell # Vendor ID & name. 94254852Sdumbbell my $vendor_id = uc($1); 95254852Sdumbbell my $vendor_name = $2; 96254852Sdumbbell $pciids{$vendor_id} = { 97254852Sdumbbell 'name' => $vendor_name, 98254852Sdumbbell 'devices' => {} 99254852Sdumbbell }; 100254852Sdumbbell 101254852Sdumbbell $current_vendor_id = $vendor_id; 102254852Sdumbbell } elsif ($line =~ /^\t([0-9a-fA-F]{4}) (.+)/) { 103254852Sdumbbell # Device ID & name. 104254852Sdumbbell my $device_id = uc($1); 105254852Sdumbbell my $device_name = $2; 106254852Sdumbbell $pciids{$current_vendor_id}{'devices'}{$device_id} = $device_name; 107254852Sdumbbell } 108254852Sdumbbell } 109254852Sdumbbell 110254852Sdumbbell close($fh); 111254852Sdumbbell 112254852Sdumbbell return %pciids; 113254852Sdumbbell} 114254852Sdumbbell 115254852Sdumbbellif (scalar(@ARGV) != 3) { 116254852Sdumbbell print STDERR "Syntax: $progname <linux_header> <freebsd_header> <pciids_db> [<vendor_define>]\n"; 117254852Sdumbbell exit 1; 118254852Sdumbbell} 119254852Sdumbbell 120254852Sdumbbellmy $linux_header = $ARGV[0]; 121254852Sdumbbellmy $freebsd_header = $ARGV[1]; 122254852Sdumbbellmy $pciids_db = $ARGV[2]; 123254852Sdumbbellmy $only_vendor = $ARGV[3]; 124254852Sdumbbell 125254852Sdumbbellmy %linux_pciids = parse_linux_header($linux_header); 126254852Sdumbbellmy %freebsd_pciids = parse_freebsd_header($freebsd_header); 127254852Sdumbbellmy %pciids_db = parse_pciids_db($pciids_db); 128254852Sdumbbell 129254852Sdumbbellprint STDERR "Update FreeBSD's PCI IDs:\n"; 130254852Sdumbbellforeach my $vendor_define (sort keys(%linux_pciids)) { 131254852Sdumbbell if ($only_vendor && $vendor_define ne $only_vendor) { 132254852Sdumbbell print STDERR "(skip unwanted define: $vendor_define)\n"; 133254852Sdumbbell next; 134254852Sdumbbell } elsif (!$only_vendor && !exists($freebsd_pciids{$vendor_define})) { 135254852Sdumbbell print STDERR "(skip unsupport define: $vendor_define)\n"; 136254852Sdumbbell next; 137254852Sdumbbell } 138254852Sdumbbell 139254852Sdumbbell foreach my $device_id (sort keys(%{$linux_pciids{$vendor_define}})) { 140254852Sdumbbell my $vendor_id = $linux_pciids{$vendor_define}{$device_id}{'vendor_id'}; 141254852Sdumbbell 142254852Sdumbbell if (exists($freebsd_pciids{$vendor_define}{$device_id})) { 143254852Sdumbbell print STDERR " $vendor_define: $vendor_id:$device_id already in header\n"; 144254852Sdumbbell next; 145254852Sdumbbell } 146254852Sdumbbell 147254852Sdumbbell my $flags = $linux_pciids{$vendor_define}{$device_id}{'flags'}; 148254852Sdumbbell my $name = $pciids_db{$vendor_id}{'devices'}{$device_id} || "Unknown device name"; 149254852Sdumbbell print STDERR " $vendor_define: $vendor_id:$device_id is missing ($name)\n"; 150254852Sdumbbell $freebsd_pciids{$vendor_define}{$device_id} = { 151254852Sdumbbell 'vendor_id' => $vendor_id, 152254852Sdumbbell 'flags' => $flags, 153254852Sdumbbell 'name' => $name 154254852Sdumbbell }; 155254852Sdumbbell } 156254852Sdumbbell} 157254852Sdumbbell 158254852Sdumbbellprint STDERR "\nWrite FreeBSD header to stdout...\n"; 159254852Sdumbbellprint <<"EOF"; 160254852Sdumbbell/* 161254852Sdumbbell * \$FreeBSD\$ 162254852Sdumbbell */ 163254852Sdumbbell 164254852Sdumbbell/* 165254852Sdumbbell * Generated by $progname from: 166254852Sdumbbell * o previous FreeBSD's drm_pciids.h 167254852Sdumbbell * o Linux' drm_pciids.h 168254852Sdumbbell * o the PCI ID repository (http://pciids.sourceforge.net/) 169254852Sdumbbell * 170254852Sdumbbell * See tools/tools/drm/$progname. 171254852Sdumbbell */ 172254852SdumbbellEOF 173254852Sdumbbellforeach my $vendor_define (sort keys(%freebsd_pciids)) { 174254852Sdumbbell print "\n#define $vendor_define \\\n"; 175254852Sdumbbell foreach my $device_id (sort keys(%{$freebsd_pciids{$vendor_define}})) { 176254852Sdumbbell my $vendor_id = $freebsd_pciids{$vendor_define}{$device_id}{'vendor_id'}; 177254852Sdumbbell my $flags = $freebsd_pciids{$vendor_define}{$device_id}{'flags'}; 178254852Sdumbbell my $name = $freebsd_pciids{$vendor_define}{$device_id}{'name'}; 179254852Sdumbbell 180254852Sdumbbell print "\t{0x$vendor_id, 0x$device_id, $flags, \"$name\"}, \\\n"; 181254852Sdumbbell } 182254852Sdumbbell print "\t{0, 0, 0, NULL}\n"; 183254852Sdumbbell} 184