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