1#!/usr/bin/perl 2 3use strict; 4use warnings; 5use utf8; 6 7use File::Basename; 8 9my $progname = basename($0); 10 11sub parse_linux_header ($) 12{ 13 my ($header) = @_; 14 15 open(my $fh, '<', $header) or die "Can't open Linux header: $!\n"; 16 17 my $in_list = 0; 18 19 my %pciids = (); 20 21 my $current_vendor_define; 22 23 while (my $line = <$fh>) { 24 if ($line =~ /^#define +([^ ]+) +/) { 25 $current_vendor_define = $1; 26 $pciids{$current_vendor_define} = {}; 27 } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}),[^,]+,[^,]+,[^,]+,[^,]+, *([^}]+)\}/) { 28 my $vendor_id = uc($1); 29 my $device_id = uc($2); 30 my $flags = $3; 31 32 $pciids{$current_vendor_define}{$device_id} = { 33 'vendor_id' => $vendor_id, 34 'flags' => $flags 35 }; 36 } 37 } 38 39 close($fh); 40 41 return %pciids; 42} 43 44sub parse_freebsd_header ($) { 45 my ($header) = @_; 46 47 open(my $fh, '<', $header) or die "Can't open FreeBSD header: $!\n"; 48 49 my $in_list = 0; 50 51 my %pciids = (); 52 53 my $current_vendor_define; 54 55 while (my $line = <$fh>) { 56 if ($line =~ /^#define +([^ ]+) +/) { 57 $current_vendor_define = $1; 58 $pciids{$current_vendor_define} = {}; 59 } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}), *([^,]+), *"([^"]+)"\}/) { 60 my $vendor_id = uc($1); 61 my $device_id = uc($2); 62 my $flags = $3; 63 my $name = $4; 64 65 $pciids{$current_vendor_define}{$device_id} = { 66 'vendor_id' => $vendor_id, 67 'flags' => $flags, 68 'name' => $name 69 }; 70 } 71 } 72 73 close($fh); 74 75 return %pciids; 76} 77 78sub parse_pciids_db ($) { 79 my ($header) = @_; 80 81 open(my $fh, '<', $header) or die "Can't open PCI IDs database: $!\n"; 82 83 my %pciids = (); 84 85 my $current_vendor_id; 86 87 while (my $line = <$fh>) { 88 if (!$line || $line =~ /^#/) { 89 next; 90 } 91 if ($line =~ /^([0-9a-fA-F]{4}) (.+)/) { 92 # Vendor ID & name. 93 my $vendor_id = uc($1); 94 my $vendor_name = $2; 95 $pciids{$vendor_id} = { 96 'name' => $vendor_name, 97 'devices' => {} 98 }; 99 100 $current_vendor_id = $vendor_id; 101 } elsif ($line =~ /^\t([0-9a-fA-F]{4}) (.+)/) { 102 # Device ID & name. 103 my $device_id = uc($1); 104 my $device_name = $2; 105 $pciids{$current_vendor_id}{'devices'}{$device_id} = $device_name; 106 } 107 } 108 109 close($fh); 110 111 return %pciids; 112} 113 114if (scalar(@ARGV) != 3) { 115 print STDERR "Syntax: $progname <linux_header> <freebsd_header> <pciids_db> [<vendor_define>]\n"; 116 exit 1; 117} 118 119my $linux_header = $ARGV[0]; 120my $freebsd_header = $ARGV[1]; 121my $pciids_db = $ARGV[2]; 122my $only_vendor = $ARGV[3]; 123 124my %linux_pciids = parse_linux_header($linux_header); 125my %freebsd_pciids = parse_freebsd_header($freebsd_header); 126my %pciids_db = parse_pciids_db($pciids_db); 127 128print STDERR "Update FreeBSD's PCI IDs:\n"; 129foreach my $vendor_define (sort keys(%linux_pciids)) { 130 if ($only_vendor && $vendor_define ne $only_vendor) { 131 print STDERR "(skip unwanted define: $vendor_define)\n"; 132 next; 133 } elsif (!$only_vendor && !exists($freebsd_pciids{$vendor_define})) { 134 print STDERR "(skip unsupport define: $vendor_define)\n"; 135 next; 136 } 137 138 foreach my $device_id (sort keys(%{$linux_pciids{$vendor_define}})) { 139 my $vendor_id = $linux_pciids{$vendor_define}{$device_id}{'vendor_id'}; 140 141 if (exists($freebsd_pciids{$vendor_define}{$device_id})) { 142 print STDERR " $vendor_define: $vendor_id:$device_id already in header\n"; 143 next; 144 } 145 146 my $flags = $linux_pciids{$vendor_define}{$device_id}{'flags'}; 147 my $name = $pciids_db{$vendor_id}{'devices'}{$device_id} || "Unknown device name"; 148 print STDERR " $vendor_define: $vendor_id:$device_id is missing ($name)\n"; 149 $freebsd_pciids{$vendor_define}{$device_id} = { 150 'vendor_id' => $vendor_id, 151 'flags' => $flags, 152 'name' => $name 153 }; 154 } 155} 156 157print STDERR "\nWrite FreeBSD header to stdout...\n"; 158print <<"EOF"; 159/* 160 * Generated by $progname from: 161 * o previous FreeBSD's drm_pciids.h 162 * o Linux' drm_pciids.h 163 * o the PCI ID repository (http://pciids.sourceforge.net/) 164 * 165 * See tools/tools/drm/$progname. 166 */ 167EOF 168foreach my $vendor_define (sort keys(%freebsd_pciids)) { 169 print "\n#define $vendor_define \\\n"; 170 foreach my $device_id (sort keys(%{$freebsd_pciids{$vendor_define}})) { 171 my $vendor_id = $freebsd_pciids{$vendor_define}{$device_id}{'vendor_id'}; 172 my $flags = $freebsd_pciids{$vendor_define}{$device_id}{'flags'}; 173 my $name = $freebsd_pciids{$vendor_define}{$device_id}{'name'}; 174 175 print "\t{0x$vendor_id, 0x$device_id, $flags, \"$name\"}, \\\n"; 176 } 177 print "\t{0, 0, 0, NULL}\n"; 178} 179