1# PCI Header script 2# 3# Copyright 2006, Haiku. 4# Distributed under the terms of the MIT License. 5# 6# Authors: 7# John Drinkwater, john@nextraweb.com 8# 9# Use with http://pciids.sourceforge.net/pci.ids 10# run as: awk -v HEADERFILE=pcihdr.h -f pci-header.awk pci.ids 11 12BEGIN { 13 14 # field separator, defining because user could have overridden 15 FS = " " 16 17 # Pass this in from outside with -v HEADERFILE=filenametouse 18 # we require pcihdr.h for our system 19 ofile = HEADERFILE 20 21 # possibly use this in the future 22 cleanvalues = "[^A-Za-z0-9{}\"'&@?!*.,:;+<> \\t\\/_\\[\\]=#()-]" 23 # ToDo: currently IDs aren't checked, we dumbly assume the source is clean 24 25 # descriptive output header 26 print "#if 0" > ofile 27 print "#\tPCIHDR.H: PCI Vendors, Devices, and Class Type information\n#" > ofile 28 print "#\tGenerated by pci-header.awk, source data from the following URI:\n#\thttp://pciids.sourceforge.net/pci.ids\n#" > ofile 29 print "#\tHeader created on " strftime( "%A, %d %b %Y %H:%M:%S %Z", systime() ) > ofile 30 print "#endif" > ofile 31 32 # and we start with vendors.. 33 print "\ntypedef struct _PCI_VENTABLE\n{\n\tunsigned short\tVenId ;\n\tconst char *\tVenFull ;\n\tconst char *\tVenShort ;\n} PCI_VENTABLE, *PPCI_VENTABLE ;\n" > ofile 34 print "PCI_VENTABLE\tPciVenTable [] =\n{" > ofile 35} 36 37# matches vendor - starts with an id as first thing on the line 38# because this occurs first in the header file, we output it without worry 39/^[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 40 41 if ( vendorcount++ > 0 ) { 42 formatting = ",\n" 43 } else { 44 formatting = "" 45 } 46 47 # store vendor ID for possible devices afterwards 48 vendorid = $1 49 vendor = substr($0, 7) 50 gsub( /\"/, "&&", vendor ) 51 52 # Remove double interrogation points that may be interpreted as trigraphs 53 gsub( /\?\?\?/, "xxx", vendor ) 54 gsub( /\?\?/, "xx", vendor ) 55 56 printf formatting "\t{ 0x" vendorid ", \"" vendor "\", \"\" }" > ofile 57} 58 59# matches device 60/^\t[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 61 62 device = substr($0, 8) 63 gsub( /\\/, "&&", device ) 64 gsub( /\"/, "&&", device ) 65 66 # Remove double interrogation points that may be interpreted as trigraphs 67 gsub( /\?\?\?/, "xxx", device ) 68 gsub( /\?\?/, "xx", device ) 69 70 # store device ID for possible devices afterwards 71 deviceid = $1 72 devicecount++ 73 devices[devicecount, 1] = vendorid 74 devices[devicecount, 2] = $1 75 devices[devicecount, 3] = 0 76 devices[devicecount, 4] = 0 77 devices[devicecount, 5] = device 78} 79 80# matches subvendor device 81/^\t\t[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] / { 82 83 device = substr($0, 14) 84 gsub( /\"/, "\\\"", device ) 85 86 devicecount++ 87 devices[devicecount, 1] = vendorid 88 devices[devicecount, 2] = deviceid 89 devices[devicecount, 3] = $1 90 devices[devicecount, 4] = $2 91 devices[devicecount, 5] = device 92} 93 94# match device class - store data for later 95/^C [[:xdigit:]][[:xdigit:]] / { 96 97 class = $2 98 classname = substr($0, 7) 99 gsub( /\"/, "\\\"", classname ) 100} 101 102# match subclass, use device class data captured earlier, and output 103/^\t[[:xdigit:]][[:xdigit:]] / { 104 105 subclass = $1 106 subclassname = substr($0, 6) 107 gsub( /\"/, "\\\"", subclassname ) 108 109 classcount++ 110 classes[classcount, 1] = class 111 classes[classcount, 2] = subclass 112 classes[classcount, 3] = "00" 113 classes[classcount, 4] = classname 114 classes[classcount, 5] = subclassname 115 classes[classcount, 6] = "" 116} 117 118# match programming interface 119/^\t\t[[:xdigit:]][[:xdigit:]] / { 120 121 proginterface = $1 122 proginterfacename = substr($0, 7) 123 gsub( /\"/, "\\\"", proginterfacename ) 124 125 classcount++ 126 classes[classcount, 1] = class 127 classes[classcount, 2] = subclass 128 classes[classcount, 3] = proginterface 129 classes[classcount, 4] = classname 130 classes[classcount, 5] = subclassname 131 classes[classcount, 6] = proginterfacename 132} 133 134# We've processed the file, now output. 135END { 136 137 print "\n};\n\n// Use this value for loop control during searching:\n#define\tPCI_VENTABLE_LEN\t(sizeof(PciVenTable)/sizeof(PCI_VENTABLE))\n" > ofile 138 139 if ( devicecount > 0 ) { 140 141 print "typedef struct _PCI_DEVTABLE\n{\n\tunsigned short VenId ;\n\tunsigned short DevId ;\n\tunsigned short\tSubVenId ;\n\tunsigned short\tSubDevId ;\n\tconst char *\tChipDesc ;\n} PCI_DEVTABLE, *PPCI_DEVTABLE ;\n" > ofile 142 print "PCI_DEVTABLE\tPciDevTable [] =\n{" > ofile 143 for (i = 1; i <= devicecount; i++) { 144 145 if (i != 1) { 146 formatting = ",\n" 147 } else { 148 formatting = "" 149 } 150 printf formatting "\t{ 0x" devices[i, 1] ", 0x" devices[i, 2] ", 0x" devices[i, 3] ", 0x" devices[i, 4] ", \"" devices[i, 5] "\" }" > ofile 151 } 152 print "\n} ;\n\n// Use this value for loop control during searching:\n#define PCI_DEVTABLE_LEN (sizeof(PciDevTable)/sizeof(PCI_DEVTABLE))\n" > ofile 153 154 } 155 156 if ( classcount > 0 ) { 157 print "typedef struct _PCI_CLASSCODETABLE\n{\n\tunsigned char BaseClass ;\n\tunsigned char SubClass ;\n\tunsigned char ProgIf ;" > ofile 158 print "\tconst char *\t\tBaseDesc ;\n\tconst char *\t\tSubDesc ;\n\tconst char *\t\tProgDesc ;\n} PCI_CLASSCODETABLE, *PPCI_CLASSCODETABLE ;\n" > ofile 159 print "PCI_CLASSCODETABLE PciClassCodeTable [] =\n{" > ofile 160 currentclass = classes[1, 1] 161 for (i = 1; i <= classcount; i++) { 162 163 if (i != 1) { 164 formatting = ",\n" 165 } else { 166 formatting = "" 167 } 168 169 # pretty print separate classes 170 if ( currentclass != classes[i, 1] ) { 171 formatting = formatting "\n" 172 currentclass = classes[i, 1] 173 } 174 175 # if the next item has the same details, we know we're to skip ourselves 176 # this is because the programming interface name needs to be used, and we dont have it ourselves 177 if ( ( classes[i, 1] != classes[i+1, 1] ) || ( classes[i, 2] != classes[i+1, 2] ) || ( classes[i, 3] != classes[i+1, 3] ) ) { 178 printf formatting "\t{ 0x" classes[i, 1] ", 0x" classes[i, 2] ", 0x" classes[i, 3] ", \"" classes[i, 4] "\", \"" classes[i, 5] "\", \"" classes[i, 6] "\" }" > ofile 179 } 180 } 181 print "\n} ;\n\n// Use this value for loop control during searching:\n#define PCI_CLASSCODETABLE_LEN (sizeof(PciClassCodeTable)/sizeof(PCI_CLASSCODETABLE))\n" > ofile 182 183 } 184 185 # this is rather ugly, maybe we should include this in a seperate file, and pull it in ? 186 print "const char *\tPciCommandFlags [] =\n{\n\t\"I/O Access\",\n\t\"Memory Access\",\n\t\"Bus Mastering\",\n\t\"Special Cycles\",\n\t\"Memory Write & Invalidate\",\n\t\"Palette Snoop\",\n\t\"Parity Errors\",\n\t\"Wait Cycles\",\n\t\"System Errors\",\n\t\"Fast Back-To-Back\",\n\t\"Reserved 10\",\n\t\"Reserved 11\",\n\t\"Reserved 12\",\n\t\"Reserved 13\",\n\t\"Reserved 14\",\n\t\"Reserved 15\"\n} ;\n" > ofile 187 print "// Use this value for loop control during searching:\n#define PCI_COMMANDFLAGS_LEN (sizeof(PciCommandFlags)/sizeof(char *))\n" > ofile 188 print "const char *\tPciStatusFlags [] =\n{\n\t\"Reserved 0\",\n\t\"Reserved 1\",\n\t\"Reserved 2\",\n\t\"Reserved 3\",\n\t\"Reserved 4\",\n\t\"66 MHz Capable\",\n\t\"User-Defined Features\",\n\t\"Fast Back-To-Back\",\n\t\"Data Parity Reported\",\n\t\"\",\n\t\"\",\n\t\"Signalled Target Abort\",\n\t\"Received Target Abort\",\n\t\"Received Master Abort\",\n\t\"Signalled System Error\",\n\t\"Detected Parity Error\"\n} ;\n" > ofile 189 print "// Use this value for loop control during searching:\n#define PCI_STATUSFLAGS_LEN (sizeof(PciStatusFlags)/sizeof(char *))\n" > ofile 190 print "const char *\tPciDevSelFlags [] =\n{\n\t\"Fast Devsel Speed\",\n\t\"Medium Devsel Speed\",\n\t\"Slow Devsel Speed\",\n\t\"Reserved 9&10\"\n} ;\n" > ofile 191 print "// Use this value for loop control during searching:\n#define PCI_DEVSELFLAGS_LEN (sizeof(PciDevSelFlags)/sizeof(char *))\n\n" > ofile 192 193 close(ofile) 194} 195 196 197