#!/usr/bin/perl # Automatically generate the data structures for PCI vendor/device lists # from the pci.ids file. # # It should be run as: # # perl pciid2c.pl ../common/xf86PciInfo.h < pci.ids > xf86PciIds.h # # # Copyright © 2002 by The XFree86 Project, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the copyright holder(s) # and author(s) shall not be used in advertising or otherwise to promote # the sale, use or other dealings in this Software without prior written # authorization from the copyright holder(s) and author(s). # # # Author: David Dawes # # $XFree86: xc/programs/Xserver/hw/xfree86/scanpci/pciid2c.pl,v 1.3 2003/08/24 17:37:10 dawes Exp $ # if (@ARGV[0]) { $infofile = @ARGV[0]; } # # The basic pci.ids format is: # - Vendor lines start with four (lower case) hex digits # - Device lines start with one tab followed by four hex digits # - Subsystem lines start with two tabs followed by two sets of four # hex digits. # - Class overrides for devices start with two tabs followed by a "C", # followed by four hex digits with the class/subclass value. # - Class lines start with a "C". # - Comment lines start with a '#'. # - Blank lines are ignored. # # We allow for extra lines to be appended to modify existing entries or # add new ones. To add/modify Device entries without modifying the # Vendor name, a special vendor name of '"' is used (mnemonic: "ditto"). # Similarly for adding subsystem names without modifying (or adding) # a corresponding device entry. To rename an existing entry, simply # provide the new name. To remove an existing entry, use the special # name '-'. # while () { # Process data lines if (/^([0-9a-f]{4})\s+(.*)/) { $vendor = $1; if ($2 eq '-') { delete($vendors{$vendor}); } elsif ($2 ne '"') { $vendors{$vendor} = $2; # Remove " characters $vendors{$vendor} =~ s/"//g; # Remove multiple "?" sequences to avoid trigraphs $vendors{$vendor} =~ s/\?+/\?/g; } } elsif (/^\t([0-9a-f]{4})\s+(.*)/) { $device = $1; if ($2 eq '-') { delete($devices{$vendor}{$device}); } elsif ($2 ne '"') { $devices{$vendor}{$device} = $2; # Remove " characters $devices{$vendor}{$device} =~ s/"//g; # Remove multiple "?" sequences to avoid trigraphs $devices{$vendor}{$device} =~ s/\?+/\?/g; } } elsif (/^\t\t([0-9a-f]{4})\s+([0-9a-f]{4})\s+(.*)/) { $v = $1; $s = $2; if ($3 eq '-') { delete($subsystems{$v}{$s}); delete($devsubsystems{$vendor}{$device}{"$v-$s"}); } elsif ($3 ne '"') { if ($subsystems{$v}{$s}) { #print STDERR "Duplicate subsytem: $v, $s, \"$subsystems{$v}{$s}\", \"$3\"\n"; } $subsystems{$v}{$s} = $3; # Remove " characters $subsystems{$v}{$s} =~ s/"//g; # Remove multiple "?" sequences to avoid trigraphs $subsystems{$v}{$s} =~ s/\?+/\?/g; $devsubsystems{$vendor}{$device}{"$v-$s"} = $subsystems{$v}{$s}; } } elsif (/^\t\tC\s+([0-9a-f]{4})/) { $classes{$vendor}{$device} = $1; } # Ignore all other lines. } # Find which vendors are "video" vendors. if ($infofile) { open(INFO, "<$infofile") || die "Can't open $infofile"; while () { if (/^#define\s+PCI_VENDOR_.*0x([0-9a-fA-F]{4})/) { $vendor = $1; $vendor =~ tr/A-F/a-f/; $video{$vendor} = 1; } } } # # This layout is quite different from that used in the old xf86PciInfo.h # file. One main difference is that the list is initialised at runtime. # It's currently a flat list. This could be improved. # # Print out header information. $proj = "XFree86"; print "/* \$$proj\$ */ /* * THIS FILE IS AUTOMATICALLY GENERATED -- DO NOT EDIT * * It is generated by pciid2c.pl using data from the following files: * * ../etc/pci.ids * ../etc/extrapci.ids * ../common/xf86PciInfo.h */ /* * Copyright © 2002 by the XFree86 Project, Inc. * * The pci.ids file and the data it contains are from the Linux PCI ID's * Project (http://pciids.sf.net/). It is maintained by Martin Mares * and other volunteers. The pci.ids file contains no * copyright notice. */ #include \"xf86PciInfo.h\" #ifndef NULL #define NULL (void *)0 #endif "; # The following #ifdefs are used: # - INIT_SUBSYS_INFO -- initialise subsystem data # - INIT_VENDOR_SUBSYS_INFO -- initialise a vendor<->subsystem table. # - VENDOR_INCLUDE_NONVIDEO -- include data for non-video vendors. # Define static variables with all of the strings. foreach $vendor (sort keys %vendors) { if ($infofile && !$video{$vendor}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } print "static const char pci_vendor_${vendor}[] = \"$vendors{$vendor}\";\n"; foreach $device (sort keys %{$devices{$vendor}}) { print "static const char pci_device_${vendor}_${device}[] = " . "\"$devices{$vendor}{$device}\";\n"; foreach $subsys (sort keys %{$devsubsystems{$vendor}{$device}}) { $s = $subsys; ($v) = split /-/, $s; if ($infofile && !$video{$vendor} && $video{$v}) { print "#endif\n"; } $s =~ s/-/_/; print "#ifdef INIT_SUBSYS_INFO\n"; print "static const char pci_subsys_${vendor}_${device}_${s}[] = " . "\"$devsubsystems{$vendor}{$device}{$subsys}\";\n"; print "#endif\n"; if ($infofile && !$video{$vendor} && $video{$v}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } } } if ($infofile && !$video{$vendor}) { print "#endif\n"; } } # Pre-initialise the table structures (from the inner to the outer). # First, the subsys structures. print "#ifdef INIT_SUBSYS_INFO\n"; foreach $vendor (sort keys %vendors) { if ($infofile && !$video{$vendor}) { $pre = "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } else { undef($pre); undef($post); } foreach $device (sort keys %{$devices{$vendor}}) { foreach $subsys (sort keys %{$devsubsystems{$vendor}{$device}}) { $s = $subsys; $s =~ tr/-/_/; ($vid, $sid) = split /_/, $s; if ($pre) { print $pre; undef($pre); $post = "#endif\n"; } if ($infofile && !$video{$vendor} && $video{$vid}) { print "#endif\n"; } print "static const pciSubsystemInfo " . "pci_ss_info_${vendor}_${device}_$s =\n"; print "\t{0x$vid, 0x$sid, pci_subsys_${vendor}_${device}_$s, 0};\n"; print "#undef pci_ss_info_$s\n"; print "#define pci_ss_info_$s pci_ss_info_${vendor}_${device}_$s\n"; if ($infofile && !$video{$vendor} && $video{$vid}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } } } if ($post) { print $post; undef($post); } } # Next, the list of per vendor+device subsystem arrays foreach $vendor (sort keys %vendors) { if ($infofile && !$video{$vendor}) { $pre = "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } else { undef($pre); undef($post); } foreach $device (sort keys %{$devices{$vendor}}) { if (scalar(keys %{$devsubsystems{$vendor}{$device}}) > 0) { if ($pre) { print $pre; undef($pre); $post = "#endif\n"; } print "static const pciSubsystemInfo *pci_ss_list_${vendor}_${device}[] = {\n"; foreach $sub (sort keys %{$devsubsystems{$vendor}{$device}}) { $sub =~ s/-/_/; print "\t&pci_ss_info_${vendor}_${device}_${sub},\n"; } print "\tNULL\n};\n"; } else { print "#define pci_ss_list_${vendor}_${device} NULL\n"; } } if ($post) { print $post; undef($post); } } # Next, the list of per vendor subsystem arrays print "#ifdef INIT_VENDOR_SUBSYS_INFO\n"; foreach $vendor (sort keys %vendors) { if (scalar(keys %{$subsystems{$vendor}}) > 0) { if ($infofile && !$video{$vendor}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } print "static const pciSubsystemInfo *pci_ss_list_${vendor}[] = {\n"; foreach $sub (sort keys %{$subsystems{$vendor}}) { print "\t&pci_ss_info_${vendor}_${sub},\n"; } print "\tNULL\n};\n"; if ($infofile && !$video{$vendor}) { print "#endif\n"; } } else { print "#define pci_ss_list_${vendor} NULL\n"; } } print "#endif /* INIT_VENDOR_SUBSYS_INFO */\n"; print "#endif /* INIT_SUBSYS_INFO */\n"; # Next the device structures foreach $vendor (sort keys %vendors) { if ($infofile && !$video{$vendor}) { $pre = "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } else { undef($pre); undef($post); } foreach $device (sort keys %{$devices{$vendor}}) { if ($pre) { print $pre; undef($pre); $post = "#endif\n"; } if ($classes{$vendor}{$device}) { $class = "0x$classes{$vendor}{$device}"; } else { $class = "0"; } print "static const pciDeviceInfo " . "pci_dev_info_${vendor}_${device} = {\n"; print "\t0x$device, pci_device_${vendor}_${device},\n"; print "#ifdef INIT_SUBSYS_INFO\n"; print "\tpci_ss_list_${vendor}_${device},\n"; print "#else\n"; print "\tNULL,\n"; print "#endif\n"; print "\t$class\n};\n"; } if ($post) { print $post; undef($post); } } # Next, the list of per vendor device arrays foreach $vendor (sort keys %vendors) { if (scalar(keys %{$devices{$vendor}}) > 0) { if ($infofile && !$video{$vendor}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } print "static const pciDeviceInfo *pci_dev_list_${vendor}[] = {\n"; foreach $device (sort keys %{$devices{$vendor}}) { print "\t&pci_dev_info_${vendor}_${device},\n"; } print "\tNULL\n};\n"; if ($infofile && !$video{$vendor}) { print "#endif\n"; } } else { print "#define pci_dev_list_${vendor} NULL\n"; } } # Next, the main vendor list print " static const pciVendorInfo pciVendorInfoList[] = { "; foreach $vendor (sort keys %vendors) { if ($infofile && !$video{$vendor}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } print "\t{0x$vendor, pci_vendor_$vendor, pci_dev_list_$vendor},\n"; if ($infofile && !$video{$vendor}) { print "#endif\n"; } } print "\t{0x0000, NULL, NULL}\n};\n"; # Finally, the main vendor/subsystem list print " #if defined(INIT_VENDOR_SUBSYS_INFO) && defined(INIT_SUBSYS_INFO) static const pciVendorSubsysInfo pciVendorSubsysInfoList[] = { "; foreach $vendor (sort keys %vendors) { if ($infofile && !$video{$vendor}) { print "#ifdef VENDOR_INCLUDE_NONVIDEO\n"; } print "\t{0x$vendor, pci_vendor_$vendor, pci_ss_list_$vendor},\n"; if ($infofile && !$video{$vendor}) { print "#endif\n"; } } print "\t{0x0000, NULL, NULL}\n};\n"; print "#endif\n";