xref: /freebsd/tools/tools/drm/gen-drm_pciids (revision 4b9d6057)
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