gen-drm_pciids revision 254852
1#!/usr/bin/perl
2# $FreeBSD: head/tools/tools/drm/gen-drm_pciids 254852 2013-08-25 12:20:57Z dumbbell $
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