aboutsummaryrefslogtreecommitdiffstats
path: root/com32/lib/pci/scan.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-03-12 21:26:39 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-03-12 21:26:39 -0700
commit4171516d8fa8997db187a8d41a51344402c2dc8d (patch)
treefb2e1f310dc4bf6e9b442a09c1bc343767e8aa59 /com32/lib/pci/scan.c
parent14b47f77ec944c0cc8cb56d5e220ce67846dcf4d (diff)
parent7a708f025b241d8aca62014ebe7279fc605b1a46 (diff)
downloadsyslinux.git-4171516d8fa8997db187a8d41a51344402c2dc8d.tar.gz
syslinux.git-4171516d8fa8997db187a8d41a51344402c2dc8d.tar.xz
syslinux.git-4171516d8fa8997db187a8d41a51344402c2dc8d.zip
Merge branch 'hdt'
Diffstat (limited to 'com32/lib/pci/scan.c')
-rw-r--r--com32/lib/pci/scan.c219
1 files changed, 172 insertions, 47 deletions
diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c
index 98df0dd3..cfd9e654 100644
--- a/com32/lib/pci/scan.c
+++ b/com32/lib/pci/scan.c
@@ -73,7 +73,7 @@ static int hex_to_int(char *hexa)
/* Try to match any pci device to the appropriate kernel module */
/* it uses the modules.pcimap from the boot device */
-int get_module_name_from_pci_ids(struct pci_domain *domain)
+int get_module_name_from_pci_ids(struct pci_domain *domain, char *modules_pcimap_path)
{
char line[MAX_LINE];
char module_name[21]; // the module name field is 21 char long
@@ -94,18 +94,21 @@ int get_module_name_from_pci_ids(struct pci_domain *domain)
if (!dev->dev_info)
return -1;
}
- strcpy(dev->dev_info->linux_kernel_module, "unknown");
+ for (int i=0;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) {
+ strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7);
+ }
}
/* Opening the modules.pcimap (of a linux kernel) from the boot device */
- f=fopen("modules.pcimap", "r");
+ f=fopen(modules_pcimap_path, "r");
if (!f)
- return -1;
+ return -ENOMODULESPCIMAP;
strcpy(vendor_id,"0000");
strcpy(product_id,"0000");
strcpy(sub_product_id,"0000");
strcpy(sub_vendor_id,"0000");
+ dev->dev_info->linux_kernel_module_count=0;
/* for each line we found in the modules.pcimap */
while ( fgets(line, sizeof line, f) ) {
@@ -134,35 +137,136 @@ int get_module_name_from_pci_ids(struct pci_domain *domain)
/* Searching the next field */
result = strtok( NULL, delims );
}
+ int int_vendor_id=hex_to_int(vendor_id);
+ int int_sub_vendor_id=hex_to_int(sub_vendor_id);
+ int int_product_id=hex_to_int(product_id);
+ int int_sub_product_id=hex_to_int(sub_product_id);
/* if a pci_device matches an entry, fill the linux_kernel_module with
the appropriate kernel module */
for_each_pci_func(dev, domain) {
- if (hex_to_int(vendor_id) == dev->vendor &&
- hex_to_int(product_id) == dev->product &&
- (hex_to_int(sub_product_id) & dev->sub_product)
+ if (int_vendor_id == dev->vendor &&
+ int_product_id == dev->product &&
+ (int_sub_product_id & dev->sub_product)
== dev->sub_product &&
- (hex_to_int(sub_vendor_id) & dev->sub_vendor)
- == dev->sub_vendor)
- strcpy(dev->dev_info->linux_kernel_module, module_name);
+ (int_sub_vendor_id & dev->sub_vendor)
+ == dev->sub_vendor) {
+ strcpy(dev->dev_info->linux_kernel_module[dev->dev_info->linux_kernel_module_count], module_name);
+ dev->dev_info->linux_kernel_module_count++;
+ }
+ }
+ }
+ fclose(f);
+ return 0;
+}
+
+/* Try to match any pci device to the appropriate class name */
+/* it uses the pci.ids from the boot device */
+int get_class_name_from_pci_ids(struct pci_domain *domain, char *pciids_path)
+{
+ char line[MAX_LINE];
+ char class_name[PCI_CLASS_NAME_SIZE];
+ char sub_class_name[PCI_CLASS_NAME_SIZE];
+ char class_id_str[5];
+ char sub_class_id_str[5];
+ FILE *f;
+ struct pci_device *dev;
+ bool class_mode=false;
+
+ /* Intializing the vendor/product name for each pci device to "unknown" */
+ /* adding a dev_info member if needed */
+ for_each_pci_func(dev, domain) {
+ /* initialize the dev_info structure if it doesn't exist yet. */
+ if (! dev->dev_info) {
+ dev->dev_info = zalloc(sizeof *dev->dev_info);
+ if (!dev->dev_info)
+ return -1;
+ }
+ strlcpy(dev->dev_info->class_name,"unknown",7);
+ }
+
+ /* Opening the pci.ids from the boot device */
+ f = fopen(pciids_path,"r");
+ if (!f)
+ return -ENOPCIIDS;
+
+ /* for each line we found in the pci.ids */
+ while ( fgets(line, sizeof line, f) ) {
+ /* Skipping uncessary lines */
+ if ((line[0] == '#') || (line[0] == ' ') ||
+ (line[0] == 10))
+ continue;
+
+ /* Until we found a line starting with a 'C', we are not parsing classes */
+ if (line[0] == 'C')
+ class_mode=true;
+ if (class_mode == false)
+ continue;
+ strlcpy(class_name,"unknown",7);
+ /* If the line doesn't start with a tab, it means that's a class name */
+ if (line[0] != '\t') {
+
+ /* ignore the two first char and then copy 2 chars (class id)*/
+ strlcpy(class_id_str,&line[2],2);
+ class_id_str[2]=0;
+
+ /* the class name is the next field */
+ strlcpy(class_name,skipspace(strstr(line," ")),PCI_CLASS_NAME_SIZE-1);
+ remove_eol(class_name);
+
+ int int_class_id_str=hex_to_int(class_id_str);
+ /* assign the class_name to any matching pci device */
+ for_each_pci_func(dev, domain) {
+ if (int_class_id_str == dev->class[2]) {
+ strlcpy(dev->dev_info->class_name,class_name,PCI_CLASS_NAME_SIZE-1);
+ /* This value is usually the main category*/
+ strlcpy(dev->dev_info->category_name,class_name+4,PCI_CLASS_NAME_SIZE-1);
+ }
+ }
+ /* if we have a tab + a char, it means this is a sub class name */
+ } else if ((line[0] == '\t') && (line[1] != '\t')) {
+
+ /* the sub class name the second field */
+ strlcpy(sub_class_name,skipspace(strstr(line," ")),PCI_CLASS_NAME_SIZE-1);
+ remove_eol(sub_class_name);
+
+ /* the sub class id is first field */
+ strlcpy(sub_class_id_str,&line[1],2);
+ sub_class_id_str[2]=0;
+
+ int int_class_id_str=hex_to_int(class_id_str);
+ int int_sub_class_id_str=hex_to_int(sub_class_id_str);
+ /* assign the product_name to any matching pci device */
+ for_each_pci_func(dev, domain) {
+ if (int_class_id_str == dev->class[2] &&
+ int_sub_class_id_str == dev->class[1])
+ strlcpy(dev->dev_info->class_name,sub_class_name,PCI_CLASS_NAME_SIZE-1);
+ }
+
}
}
fclose(f);
return 0;
}
+
/* Try to match any pci device to the appropriate vendor and product name */
/* it uses the pci.ids from the boot device */
-int get_name_from_pci_ids(struct pci_domain *domain)
+int get_name_from_pci_ids(struct pci_domain *domain, char *pciids_path)
{
char line[MAX_LINE];
- char vendor[255];
+ char vendor[PCI_VENDOR_NAME_SIZE];
char vendor_id[5];
- char product[255];
+ char product[PCI_PRODUCT_NAME_SIZE];
char product_id[5];
char sub_product_id[5];
char sub_vendor_id[5];
FILE *f;
struct pci_device *dev;
+ bool skip_to_next_vendor=false;
+ uint16_t int_vendor_id;
+ uint16_t int_product_id;
+ uint16_t int_sub_product_id;
+ uint16_t int_sub_vendor_id;
/* Intializing the vendor/product name for each pci device to "unknown" */
/* adding a dev_info member if needed */
@@ -173,19 +277,19 @@ int get_name_from_pci_ids(struct pci_domain *domain)
if (!dev->dev_info)
return -1;
}
- strcpy(dev->dev_info->vendor_name,"unknown");
- strcpy(dev->dev_info->product_name,"unknown");
+ strlcpy(dev->dev_info->vendor_name,"unknown",7);
+ strlcpy(dev->dev_info->product_name,"unknown",7);
}
/* Opening the pci.ids from the boot device */
- f = fopen("pci.ids","r");
+ f = fopen(pciids_path,"r");
if (!f)
- return -1;
+ return -ENOPCIIDS;
- strcpy(vendor_id,"0000");
- strcpy(product_id,"0000");
- strcpy(sub_product_id,"0000");
- strcpy(sub_vendor_id,"0000");
+ strlcpy(vendor_id,"0000",4);
+ strlcpy(product_id,"0000",4);
+ strlcpy(sub_product_id,"0000",4);
+ strlcpy(sub_vendor_id,"0000",4);
/* for each line we found in the pci.ids */
while ( fgets(line, sizeof line, f) ) {
@@ -193,6 +297,7 @@ int get_name_from_pci_ids(struct pci_domain *domain)
if ((line[0] == '#') || (line[0] == ' ') || (line[0] == 'C') ||
(line[0] == 10))
continue;
+
/* If the line doesn't start with a tab, it means that's a vendor id */
if (line[0] != '\t') {
@@ -201,26 +306,35 @@ int get_name_from_pci_ids(struct pci_domain *domain)
/* the vendor name is the next field */
vendor_id[4]=0;
- strlcpy(vendor,skipspace(strstr(line," ")),255);
+ strlcpy(vendor,skipspace(strstr(line," ")),PCI_VENDOR_NAME_SIZE-1);
remove_eol(vendor);
/* init product_id, sub_product and sub_vendor */
- strcpy(product_id,"0000");
- strcpy(sub_product_id,"0000");
- strcpy(sub_vendor_id,"0000");
+ strlcpy(product_id,"0000",4);
+ strlcpy(sub_product_id,"0000",4);
+ strlcpy(sub_vendor_id,"0000",4);
- /* ffff is an invalid vendor id */
- if (strstr(vendor_id,"ffff")) break;
- /* assign the vendor_name to any matching pci device */
+ /* Unless we found a matching device, we have to skip to the next vendor */
+ skip_to_next_vendor=true;
+
+ int_vendor_id=hex_to_int(vendor_id);
+ /* Iterate in all pci devices to find a matching vendor */
for_each_pci_func(dev, domain) {
- if (hex_to_int(vendor_id) == dev->vendor)
- strlcpy(dev->dev_info->vendor_name,vendor,255);
+ /* if one device that match this vendor */
+ if (int_vendor_id == dev->vendor) {
+ /* copy the vendor name for this device */
+ strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1);
+ /* Some pci devices match this vendor, so we have to found them */
+ skip_to_next_vendor=false;
+ /* Let's loop on the other devices as some may have the same vendor */
+ }
}
- /* if we have a tab + a char, it means this is a product id */
- } else if ((line[0] == '\t') && (line[1] != '\t')) {
+ /* if we have a tab + a char, it means this is a product id
+ * but we only look at it if we own some pci devices of the current vendor*/
+ } else if ((line[0] == '\t') && (line[1] != '\t') && (skip_to_next_vendor == false)) {
/* the product name the second field */
- strlcpy(product,skipspace(strstr(line," ")),255);
+ strlcpy(product,skipspace(strstr(line," ")),PCI_PRODUCT_NAME_SIZE-1);
remove_eol(product);
/* the product id is first field */
@@ -228,22 +342,27 @@ int get_name_from_pci_ids(struct pci_domain *domain)
product_id[4]=0;
/* init sub_product and sub_vendor */
- strcpy(sub_product_id,"0000");
- strcpy(sub_vendor_id,"0000");
+ strlcpy(sub_product_id,"0000",4);
+ strlcpy(sub_vendor_id,"0000",4);
+ int_vendor_id=hex_to_int(vendor_id);
+ int_product_id=hex_to_int(product_id);
/* assign the product_name to any matching pci device */
for_each_pci_func(dev, domain) {
- if (hex_to_int(vendor_id) == dev->vendor &&
- hex_to_int(product_id) == dev->product)
- strlcpy(dev->dev_info->product_name,product,255);
+ if (int_vendor_id == dev->vendor &&
+ int_product_id == dev->product) {
+ strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1);
+ strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1);
+ }
}
- /* if we have two tabs, it means this is a sub product */
- } else if ((line[0] == '\t') && (line[1] == '\t')) {
+ /* if we have two tabs, it means this is a sub product
+ * but we only look at it if we own some pci devices of the current vendor*/
+ } else if ((line[0] == '\t') && (line[1] == '\t') && (skip_to_next_vendor == false)) {
/* the product name is last field */
- strlcpy(product,skipspace(strstr(line," ")),255);
- strlcpy(product,skipspace(strstr(product," ")),255);
+ strlcpy(product,skipspace(strstr(line," ")),PCI_PRODUCT_NAME_SIZE-1);
+ strlcpy(product,skipspace(strstr(product," ")),PCI_PRODUCT_NAME_SIZE-1);
remove_eol(product);
/* the sub_vendor id is first field */
@@ -254,13 +373,19 @@ int get_name_from_pci_ids(struct pci_domain *domain)
strlcpy(sub_product_id,&line[7],4);
sub_product_id[4]=0;
+ int_vendor_id=hex_to_int(vendor_id);
+ int_sub_vendor_id=hex_to_int(sub_vendor_id);
+ int_product_id=hex_to_int(product_id);
+ int_sub_product_id=hex_to_int(sub_product_id);
/* assign the product_name to any matching pci device */
for_each_pci_func(dev, domain) {
- if (hex_to_int(vendor_id) == dev->vendor &&
- hex_to_int(product_id) == dev->product &&
- hex_to_int(sub_product_id) == dev->sub_product &&
- hex_to_int(sub_vendor_id) == dev->sub_vendor)
- strlcpy(dev->dev_info->product_name,product,255);
+ if (int_vendor_id == dev->vendor &&
+ int_product_id == dev->product &&
+ int_sub_product_id == dev->sub_product &&
+ int_sub_vendor_id == dev->sub_vendor) {
+ strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1);
+ strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1);
+ }
}
}
}