[syslinux] [PATCH] pci: Introduce slot and function information
Sebastian Herbszt
herbszt at gmx.de
Sun Aug 3 13:57:19 PDT 2008
H. Peter Anvin wrote:
> Here is a preliminary patch if you are interested...
I noticed pci_device_list is gone. If i don't mistake it was possible to
create a "custom" pci_device_list without using pci_scan() and use
get_module_name_from_pci_ids() to resolve it.
The new get_module_name_from_pci_ids() expects a pci_domain
which implies bus, slot and device hierarchy which is not needed
in this case. But since we got no users i don't think it does matter.
Just trivial comments below.
> diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c
> index 1c3f526..298c4db 100644
> --- a/com32/lib/pci/scan.c
> +++ b/com32/lib/pci/scan.c
> @@ -65,7 +65,7 @@ static void remove_eol(char *string)
> for(i = 0; i < j; i++) if(string[i] == '\n') string[i] = 0;
> }
>
> -/* converting a hexa string into its numerical value*/
> +/* converting a hexa string into its numerical value */
> static int hex_to_int(char *hexa)
> {
> return strtoul(hexa, NULL, 16);
> @@ -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*/
/* it uses the modules.pcimap from the boot device */
> -void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list)
> +int get_module_name_from_pci_ids(struct pci_domain *domain)
> {
> char line[MAX_LINE];
> char module_name[21]; // the module name field is 21 char long
> @@ -83,29 +83,24 @@ void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list)
> char sub_vendor_id[16];
> char sub_product_id[16];
> FILE *f;
> - int pci_dev;
> + struct pci_device *dev;
>
> /* Intializing the linux_kernel_module for each pci device to "unknow" */
/* Initializing the linux_kernel_module for each pci device to "unknown" */
> - /* adding a pci_dev_info member if needed*/
> - for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device = &(pci_device_list->pci_device[pci_dev]);
> -
> - /* initialize the pci_dev_info structure if it doesn't exist yet. */
> - if (! pci_device->pci_dev_info) {
> - pci_device->pci_dev_info = calloc(1,sizeof *pci_device->pci_dev_info);
> -
> - if (!pci_device->pci_dev_info) {
> - printf("Can't allocate memory\n");
> - return;
> - }
> + /* adding a dev_info member if needed*/
/* 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)
if (! dev->dev_info) vs. if (!dev->dev_info) ?
> + return -1;
> }
> - strlcpy(pci_device->pci_dev_info->linux_kernel_module,"unknown",7);
> + strcpy(dev->dev_info->linux_kernel_module, "unknown");
> }
>
> /* Opening the modules.pcimap (ofa linux kernel) from the boot device*/
/* Opening the modules.pcimap (of a linux kernel) from the boot device */
> - f=fopen("modules.pcimap","r");
> + f=fopen("modules.pcimap", "r");
> if (!f)
> - return;
> + return -1;
>
> strcpy(vendor_id,"0000");
> strcpy(product_id,"0000");
> @@ -141,26 +136,23 @@ void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list)
> }
> /* if a pci_device match an entry, fill the linux_kernel_module with
/* if a pci_device matches an entry, fill the linux_kernel_module with
> the appropriate kernel module */
> - for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device =
> - &pci_device_list->pci_device[pci_dev];
> -
> - if (hex_to_int(vendor_id) == pci_device->vendor &&
> - hex_to_int(product_id) == pci_device->product &&
> - (hex_to_int(sub_product_id) & pci_device->sub_product)
> - == pci_device->sub_product &&
> - (hex_to_int(sub_vendor_id) & pci_device->sub_vendor)
> - == pci_device->sub_vendor)
> - strcpy(pci_device->pci_dev_info->linux_kernel_module,
> - module_name);
> + 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)
> + == dev->sub_product &&
> + (hex_to_int(sub_vendor_id) & dev->sub_vendor)
> + == dev->sub_vendor)
> + strcpy(dev->dev_info->linux_kernel_module, module_name);
> }
> }
> - fclose(f);
> + 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*/
/* it uses the pci.ids from the boot device */
> -void get_name_from_pci_ids(struct pci_device_list *pci_device_list)
> +int get_name_from_pci_ids(struct pci_domain *domain)
> {
> char line[MAX_LINE];
> char vendor[255];
> @@ -170,156 +162,138 @@ void get_name_from_pci_ids(struct pci_device_list *pci_device_list)
> char sub_product_id[5];
> char sub_vendor_id[5];
> FILE *f;
> - int pci_dev;
> -
> - /* Intializing the vendor/product name for each pci device to "unknow" */
> - /* adding a pci_dev_info member if needed*/
> - for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device = &pci_device_list->pci_device[pci_dev];
> -
> - /* initialize the pci_dev_info structure if it doesn't exist yet. */
> - if (! pci_device->pci_dev_info) {
> - pci_device->pci_dev_info = calloc(1,sizeof *pci_device->pci_dev_info);
> -
> - if (!pci_device->pci_dev_info) {
> - printf("Can't allocate memory\n");
> - return;
> - }
> + struct pci_device *dev;
> +
> + /* Intializing the vendor/product name for each pci device to "unknown" */
> + /* adding a dev_info member if needed*/
/* 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(pci_device->pci_dev_info->vendor_name,"unknown",7);
> - strlcpy(pci_device->pci_dev_info->product_name,"unknown",7);
> + strcpy(dev->dev_info->vendor_name,"unknown");
> + strcpy(dev->dev_info->product_name,"unknown");
> }
>
> /* Opening the pci.ids from the boot device*/
/* Opening the pci.ids from the boot device */
> - f=fopen("pci.ids","r");
> + f = fopen("pci.ids","r");
f = fopen("pci.ids", "r");
> if (!f)
> - return;
> + return -1;
> +
> strcpy(vendor_id,"0000");
> strcpy(product_id,"0000");
> strcpy(sub_product_id,"0000");
> strcpy(sub_vendor_id,"0000");
>
> -
> /* for each line we found in the pci.ids*/
/* 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] == 'C') ||
> (line[0] == 10))
> - continue;
> + continue;
> /* If the line doesn't start with a tab, it means that's a vendor id */
> if (line[0] != '\t') {
> -
> - /* the 4th first chars are the vendor_id */
> - strlcpy(vendor_id,line,4);
> -
> - /* the vendor name is the next field*/
> - vendor_id[4]=0;
> - strlcpy(vendor,skipspace(strstr(line," ")),255);
> -
> - 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");
> -
> - /* ffff is an invalid vendor id */
> - if (strstr(vendor_id,"ffff")) break;
> - /* assign the vendor_name to any matching pci device*/
> - for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device =
> - &pci_device_list->pci_device[pci_dev];
> -
> - if (hex_to_int(vendor_id) == pci_device->vendor)
> - strlcpy(pci_device->pci_dev_info->vendor_name,vendor,255);
> - }
> - /* if we have a tab + a char, it means this is a product id */
> +
> + /* the 4th first chars are the vendor_id */
/* the 4 first chars are the vendor_id */
> + strlcpy(vendor_id,line,4);
> +
> + /* the vendor name is the next field*/
/* the vendor name is the next field */
> + vendor_id[4]=0;
> + strlcpy(vendor,skipspace(strstr(line," ")),255);
> +
> + 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");
> +
> + /* ffff is an invalid vendor id */
> + if (strstr(vendor_id,"ffff")) break;
> + /* assign the vendor_name to any matching pci device*/
/* assign the vendor_name to any matching pci device */
> + for_each_pci_func(dev, domain) {
> + if (hex_to_int(vendor_id) == dev->vendor)
> + strlcpy(dev->dev_info->vendor_name,vendor,255);
> + }
> + /* if we have a tab + a char, it means this is a product id */
> } else if ((line[0] == '\t') && (line[1] != '\t')) {
> -
> - /* the product name the second field */
> - strlcpy(product,skipspace(strstr(line," ")),255);
> - remove_eol(product);
> -
> - /* the product id is first field */
> - strlcpy(product_id,&line[1],4);
> - product_id[4]=0;
> -
> - /* init sub_product and sub_vendor */
> - strcpy(sub_product_id,"0000");
> - strcpy(sub_vendor_id,"0000");
> -
> - /* assign the product_name to any matching pci device*/
> - for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device =
> - &pci_device_list->pci_device[pci_dev];
> - if (hex_to_int(vendor_id) == pci_device->vendor &&
> - hex_to_int(product_id) == pci_device->product)
> - strlcpy(pci_device->pci_dev_info->product_name,product,255);
> - }
> -
> - /* if we have two tabs, it means this is a sub product */
> +
> + /* the product name the second field */
/* the product name is the second field */
> + strlcpy(product,skipspace(strstr(line," ")),255);
> + remove_eol(product);
> +
> + /* the product id is first field */
> + strlcpy(product_id,&line[1],4);
> + product_id[4]=0;
> +
> + /* init sub_product and sub_vendor */
> + strcpy(sub_product_id,"0000");
> + strcpy(sub_vendor_id,"0000");
> +
> + /* assign the product_name to any matching pci device*/
/* 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 we have two tabs, it means this is a sub product */
> } else if ((line[0] == '\t') && (line[1] == '\t')) {
> -
> +
> /* the product name is last field */
> strlcpy(product,skipspace(strstr(line," ")),255);
> strlcpy(product,skipspace(strstr(product," ")),255);
> remove_eol(product);
> -
> +
> /* the sub_vendor id is first field */
> strlcpy(sub_vendor_id,&line[2],4);
> sub_vendor_id[4]=0;
> -
> +
> /* the sub_vendor id is second field */
> strlcpy(sub_product_id,&line[7],4);
> sub_product_id[4]=0;
> -
> +
> /* assign the product_name to any matching pci device*/
/* assign the product_name to any matching pci device */
> - for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device =
> - &pci_device_list->pci_device[pci_dev];
> -
> - if (hex_to_int(vendor_id) == pci_device->vendor &&
> - hex_to_int(product_id) == pci_device->product &&
> - hex_to_int(sub_product_id) == pci_device->sub_product &&
> - hex_to_int(sub_vendor_id) == pci_device->sub_vendor)
> - strlcpy(pci_device->pci_dev_info->product_name,product,255);
> + 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);
> }
> }
> }
> fclose(f);
> + return 0;
> }
>
> /* searching if any pcidevice match our query */
> -struct match *find_pci_device(struct pci_device_list * pci_device_list,
> +struct match *find_pci_device(const struct pci_domain *domain,
> struct match *list)
> {
> - int pci_dev;
> uint32_t did, sid;
> struct match *m;
> + const struct pci_device *dev;
> +
> /* for all matches we have to search */
> for (m = list; m; m = m->next) {
> - /* for each pci device we know */
> - for (pci_dev = 0; pci_dev < pci_device_list->count; pci_dev++) {
> - struct pci_device *pci_device =
> - &pci_device_list->pci_device[pci_dev];
> -
> + /* for each pci device we know */
> + for_each_pci_func(dev, domain) {
> /* sid & did are the easiest way to compare devices */
> /* they are made of vendor/product subvendor/subproduct ids */
> - sid =
> - ((pci_device->sub_product) << 16 | (pci_device->
> - sub_vendor));
> - did = ((pci_device->product << 16) | (pci_device->vendor));
> -
> + sid = dev->svid_sdid;
> + did = dev->vid_did;
> /*if the current device match */
> if (((did ^ m->did) & m->did_mask) == 0 &&
> ((sid ^ m->sid) & m->sid_mask) == 0 &&
> - pci_device->revision >= m->rid_min
> - && pci_device->revision <= m->rid_max) {
> + dev->revision >= m->rid_min
> + && dev->revision <= m->rid_max) {
> dprintf("PCI Match: Vendor=%04x Product=%04x Sub_vendor=%04x Sub_Product=%04x Release=%02x\n",
> - pci_device->vendor, pci_device->product,
> - pci_device->sub_vendor,
> - pci_device->sub_product,
> - pci_device->revision);
> + dev->vendor, dev->product,
> + dev->sub_vendor,
> + dev->sub_product,
> + dev->revision);
> /* returning the matched pci device */
> return m;
> }
> @@ -329,45 +303,32 @@ struct match *find_pci_device(struct pci_device_list * pci_device_list,
> }
>
> /* scanning the pci bus to find pci devices */
> -int pci_scan(struct pci_bus_list * pci_bus_list, struct pci_device_list * pci_device_list)
> +struct pci_domain *pci_scan(void)
> {
> - unsigned int bus, dev, func, maxfunc;
> - uint32_t did, sid;
> - uint8_t hdrtype, rid;
> + struct pci_domain *domain = NULL;
> + struct pci_bus *bus = NULL;
> + struct pci_slot *slot = NULL;
> + struct pci_device *func = NULL;
> + unsigned int nbus, ndev, nfunc, maxfunc;
> + uint32_t did, sid, rcid;
> + uint8_t hdrtype;
> pciaddr_t a;
> int cfgtype;
>
> - pci_device_list->count = 0;
> -
> -#ifdef DEBUG
> - outl(~0, 0xcf8);
> - printf("Poking at port CF8 = %#08x\n", inl(0xcf8));
> - outl(0, 0xcf8);
> -#endif
> -
> cfgtype = pci_set_config_type(PCI_CFG_AUTO);
> (void)cfgtype;
>
> dprintf("PCI configuration type %d\n", cfgtype);
> dprintf("Scanning PCI Buses\n");
>
> - /* We try to detect 256 buses */
> - for (bus = 0; bus < MAX_PCI_BUSES; bus++) {
> -
> + for (nbus = 0; nbus < MAX_PCI_BUSSES; nbus++) {
> dprintf("Probing bus 0x%02x... \n", bus);
>
> - pci_bus_list->pci_bus[bus].id = bus;
> - pci_bus_list->pci_bus[bus].pci_device_count = 0;
> - pci_bus_list->count = 0;;
> -
> - for (dev = 0; dev < MAX_PCI_DEVICES ; dev++) {
> + for (ndev = 0; ndev < MAX_PCI_DEVICES ; ndev++) {
for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) {
> maxfunc = 1; /* Assume a single-function device */
> - for (func = 0; func < maxfunc; func++) {
> - struct pci_device *pci_device =
> - &pci_device_list->pci_device[pci_device_list->count];
> -
> - a = pci_mkaddr(bus, dev, func, 0);
>
> + for (nfunc = 0; nfunc < maxfunc; nfunc++) {
> + a = pci_mkaddr(nbus, ndev, nfunc, 0);
> did = pci_readl(a);
>
> if (did == 0xffffffff || did == 0xffff0000 ||
> @@ -379,36 +340,79 @@ int pci_scan(struct pci_bus_list * pci_bus_list, struct pci_device_list * pci_de
> if (hdrtype & 0x80)
> maxfunc = MAX_PCI_FUNC; /* Multifunction device */
>
> - rid = pci_readb(a + 0x08);
> - sid = pci_readl(a + 0x2c);
> + rcid = pci_readl(a + 0x08);
> + sid = pci_readl(a + 0x2c);
>
> - pci_device->addr = a;
> - pci_device->product = did >> 16;
> - pci_device->sub_product = sid >> 16;
> - pci_device->vendor = (did << 16) >> 16;
> - pci_device->sub_vendor = (sid << 16) >> 16;
> - pci_device->revision = rid;
> - pci_device_list->count++;
> - pci_device++;
> + if (!domain) {
> + domain = zalloc(sizeof *domain);
> + if (!domain)
> + goto bail;
> + }
> + if (!bus) {
> + bus = zalloc(sizeof *bus);
> + if (!bus)
> + goto bail;
> + domain->bus[nbus] = bus;
> + }
> + if (!slot) {
> + slot = zalloc(sizeof *slot);
> + if (!slot)
> + goto bail;
> + bus->slot[ndev] = slot;
> + }
> + func = zalloc(sizeof *func);
> + if (!func)
> + goto bail;
> +
> + slot->func[nfunc] = func;
> +
> + func->vid_did = did;
> + func->svid_sdid = sid;
> + func->rid_class = rcid;
>
> dprintf
> ("Scanning: BUS %02x DID %08x (%04x:%04x) SID %08x RID %02x\n",
> bus, did, did >> 16, (did << 16) >> 16,
> - sid, rid);
> - /* Adding the detected pci device to the bus */
> - pci_bus_list->pci_bus[bus].
> - pci_device[pci_bus_list->pci_bus[bus].
> - pci_device_count] = pci_device;
> - pci_bus_list->pci_bus[bus].pci_device_count++;
> + sid, rcid & 0xff);
> }
> }
> }
>
> - /* Detecting pci buses that have pci devices connected */
> - for (bus = 0; bus < MAX_PCI_BUSES; bus++) {
> - if (pci_bus_list->pci_bus[bus].pci_device_count > 0) {
> - pci_bus_list->count++;
> + return domain;
> +
> + bail:
> + free_pci_domain(domain);
> + return NULL;
> +}
> +
> +void free_pci_domain(struct pci_domain *domain)
> +{
> + struct pci_bus *bus;
> + struct pci_slot *slot;
> + struct pci_device *func;
> + unsigned int nbus, ndev, nfunc;
> +
> + if (domain) {
> + for (nbus = 0; nbus < MAX_PCI_BUSSES; nbus++) {
> + bus = domain->bus[nbus];
> + if (bus) {
> + for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) {
> + slot = bus->slot[ndev];
> + if (slot) {
> + for (nfunc = 0; nfunc < MAX_PCI_FUNC; nfunc++) {
> + func = slot->func[nfunc];
> + if (func) {
> + if (func->dev_info)
> + free(func->dev_info);
> + free(func);
> + }
> + free(slot);
> + }
> + }
> + free(bus);
> + }
> + }
> + free(domain);
> }
> }
> - return 0;
> }
>
- Sebastian
More information about the Syslinux
mailing list