Merge branch 'vendor/DHCPCD'
[dragonfly.git] / tools / tools / drm / gen-drm_pciids
1 #!/usr/bin/env perl
2 # $FreeBSD: head/tools/tools/drm/gen-drm_pciids 254852 2013-08-25 12:20:57Z dumbbell $
3
4 use strict;
5 use warnings;
6 use utf8;
7
8 use File::Basename;
9
10 my $progname = basename($0);
11
12 sub 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
45 sub parse_dragonfly_header ($) {
46     my ($header) = @_;
47
48     open(my $fh, '<', $header) or die "Can't open DragonFly 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
79 sub 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
115 if (scalar(@ARGV) != 3) {
116     print STDERR "Syntax: $progname <linux_header> <dragonfly_header> <pciids_db> [<vendor_define>]\n";
117     exit 1;
118 }
119
120 my $linux_header   = $ARGV[0];
121 my $dfly_header    = $ARGV[1];
122 my $pciids_db      = $ARGV[2];
123 my $only_vendor    = $ARGV[3];
124
125 my %linux_pciids   = parse_linux_header($linux_header);
126 my %dfly_pciids    = parse_dragonfly_header($dfly_header);
127 my %pciids_db      = parse_pciids_db($pciids_db);
128
129 print STDERR "Update DragonFly's PCI IDs:\n";
130 foreach 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($dfly_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($dfly_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         $dfly_pciids{$vendor_define}{$device_id} = {
151             'vendor_id' => $vendor_id,
152             'flags'     => $flags,
153             'name'      => $name
154         };
155     }
156 }
157
158 print STDERR "\nWrite DragonFly header to stdout...\n";
159 print <<"EOF";
160 /*
161  * Generated by $progname from:
162  *   o  previous DragonFly's drm_pciids.h
163  *   o  Linux' drm_pciids.h
164  *   o  the PCI ID repository (http://pciids.sourceforge.net/)
165  *
166  * See tools/tools/drm/$progname.
167  */
168 EOF
169 foreach my $vendor_define (sort keys(%dfly_pciids)) {
170     print "\n#define $vendor_define \\\n";
171     foreach my $device_id (sort keys(%{$dfly_pciids{$vendor_define}})) {
172         my $vendor_id = $dfly_pciids{$vendor_define}{$device_id}{'vendor_id'};
173         my $flags     = $dfly_pciids{$vendor_define}{$device_id}{'flags'};
174         my $name      = $dfly_pciids{$vendor_define}{$device_id}{'name'};
175
176         print "\t{0x$vendor_id, 0x$device_id, $flags, \"$name\"}, \\\n";
177     }
178     print "\t{0, 0, 0, NULL}\n";
179 }