#!/usr/bin/env perl # $FreeBSD: head/tools/tools/drm/gen-drm_pciids 254852 2013-08-25 12:20:57Z dumbbell $ use strict; use warnings; use utf8; use File::Basename; my $progname = basename($0); sub parse_linux_header ($) { my ($header) = @_; open(my $fh, '<', $header) or die "Can't open Linux header: $!\n"; my $in_list = 0; my %pciids = (); my $current_vendor_define; while (my $line = <$fh>) { if ($line =~ /^#define +([^ ]+) +/) { $current_vendor_define = $1; $pciids{$current_vendor_define} = {}; } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}),[^,]+,[^,]+,[^,]+,[^,]+, *([^}]+)\}/) { my $vendor_id = uc($1); my $device_id = uc($2); my $flags = $3; $pciids{$current_vendor_define}{$device_id} = { 'vendor_id' => $vendor_id, 'flags' => $flags }; } } close($fh); return %pciids; } sub parse_dragonfly_header ($) { my ($header) = @_; open(my $fh, '<', $header) or die "Can't open DragonFly header: $!\n"; my $in_list = 0; my %pciids = (); my $current_vendor_define; while (my $line = <$fh>) { if ($line =~ /^#define +([^ ]+) +/) { $current_vendor_define = $1; $pciids{$current_vendor_define} = {}; } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}), *([^,]+), *"([^"]+)"\}/) { my $vendor_id = uc($1); my $device_id = uc($2); my $flags = $3; my $name = $4; $pciids{$current_vendor_define}{$device_id} = { 'vendor_id' => $vendor_id, 'flags' => $flags, 'name' => $name }; } } close($fh); return %pciids; } sub parse_pciids_db ($) { my ($header) = @_; open(my $fh, '<', $header) or die "Can't open PCI IDs database: $!\n"; my %pciids = (); my $current_vendor_id; while (my $line = <$fh>) { if (!$line || $line =~ /^#/) { next; } if ($line =~ /^([0-9a-fA-F]{4}) (.+)/) { # Vendor ID & name. my $vendor_id = uc($1); my $vendor_name = $2; $pciids{$vendor_id} = { 'name' => $vendor_name, 'devices' => {} }; $current_vendor_id = $vendor_id; } elsif ($line =~ /^\t([0-9a-fA-F]{4}) (.+)/) { # Device ID & name. my $device_id = uc($1); my $device_name = $2; $pciids{$current_vendor_id}{'devices'}{$device_id} = $device_name; } } close($fh); return %pciids; } if (scalar(@ARGV) != 3) { print STDERR "Syntax: $progname []\n"; exit 1; } my $linux_header = $ARGV[0]; my $dfly_header = $ARGV[1]; my $pciids_db = $ARGV[2]; my $only_vendor = $ARGV[3]; my %linux_pciids = parse_linux_header($linux_header); my %dfly_pciids = parse_dragonfly_header($dfly_header); my %pciids_db = parse_pciids_db($pciids_db); print STDERR "Update DragonFly's PCI IDs:\n"; foreach my $vendor_define (sort keys(%linux_pciids)) { if ($only_vendor && $vendor_define ne $only_vendor) { print STDERR "(skip unwanted define: $vendor_define)\n"; next; } elsif (!$only_vendor && !exists($dfly_pciids{$vendor_define})) { print STDERR "(skip unsupport define: $vendor_define)\n"; next; } foreach my $device_id (sort keys(%{$linux_pciids{$vendor_define}})) { my $vendor_id = $linux_pciids{$vendor_define}{$device_id}{'vendor_id'}; if (exists($dfly_pciids{$vendor_define}{$device_id})) { print STDERR " $vendor_define: $vendor_id:$device_id already in header\n"; next; } my $flags = $linux_pciids{$vendor_define}{$device_id}{'flags'}; my $name = $pciids_db{$vendor_id}{'devices'}{$device_id} || "Unknown device name"; print STDERR " $vendor_define: $vendor_id:$device_id is missing ($name)\n"; $dfly_pciids{$vendor_define}{$device_id} = { 'vendor_id' => $vendor_id, 'flags' => $flags, 'name' => $name }; } } print STDERR "\nWrite DragonFly header to stdout...\n"; print <<"EOF"; /* * Generated by $progname from: * o previous DragonFly's drm_pciids.h * o Linux' drm_pciids.h * o the PCI ID repository (http://pciids.sourceforge.net/) * * See tools/tools/drm/$progname. */ EOF foreach my $vendor_define (sort keys(%dfly_pciids)) { print "\n#define $vendor_define \\\n"; foreach my $device_id (sort keys(%{$dfly_pciids{$vendor_define}})) { my $vendor_id = $dfly_pciids{$vendor_define}{$device_id}{'vendor_id'}; my $flags = $dfly_pciids{$vendor_define}{$device_id}{'flags'}; my $name = $dfly_pciids{$vendor_define}{$device_id}{'name'}; print "\t{0x$vendor_id, 0x$device_id, $flags, \"$name\"}, \\\n"; } print "\t{0, 0, 0, NULL}\n"; }