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);
/* Try to match any pci device to the appropriate kernel module */
/* 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
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" */
- /* 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*/
+ 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->linux_kernel_module,"unknown",7);
+ strcpy(dev->dev_info->linux_kernel_module, "unknown");
}
/* Opening the modules.pcimap (ofa 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");
}
/* if a pci_device match 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*/
-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];
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*/
+ 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*/
- 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*/
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 */
+ 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_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 */
+ 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_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*/
- 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;
}
}
/* 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_BUSES; 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++) {
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 ||
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_BUSES; 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;
}
printf ( __VA_ARGS__); \
} while (0);
-void display_pci_devices(struct pci_device_list *pci_device_list) {
- int pci_dev;
- for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
- struct pci_device *pci_device = &pci_device_list->pci_device[pci_dev];
- printf("PCI: Vendor=%04x(%s) Product=%04x(%s) "
- "Sub_vendor=%04x Sub_Product=%04x Release=%02x\n",
- pci_device->vendor, pci_device->pci_dev_info->vendor_name,
- pci_device->product, pci_device->pci_dev_info->product_name,
- pci_device->sub_vendor, pci_device->sub_product,
- pci_device->revision);
+void display_pci_devices(struct pci_domain *pci_domain) {
+ struct pci_device *pci_device;
+ int ndev = 0;
+ for_each_pci_func(pci_device, pci_domain) {
+ printf("[%02x:%02x.%01x]: %s: %04x:%04x[%04x:%04x]) %s:%s\n",
+ __pci_bus, __pci_slot, __pci_func,
+ pci_device->dev_info->linux_kernel_module,
+ pci_device->vendor, pci_device->product,
+ pci_device->sub_vendor, pci_device->sub_product,
+ pci_device->dev_info->vendor_name,
+ pci_device->dev_info->product_name);
+ ndev++;
}
- printf("PCI: %d devices found\n",pci_device_list->count);
-}
-
-void display_pci_bus(struct pci_bus_list *pci_bus_list, bool display_pci_devices) {
- int bus;
- for (bus=0; bus<pci_bus_list->count;bus++) {
- struct pci_bus pci_bus = pci_bus_list->pci_bus[bus];
- printf("\nPCI BUS No %d:\n", pci_bus.id);
- if (display_pci_devices) {
- int pci_dev;
- for (pci_dev=0; pci_dev < pci_bus.pci_device_count; pci_dev++) {
- struct pci_device pci_device=*(pci_bus.pci_device[pci_dev]);
- printf("%s :%04x:%04x[%04x:%04x]) %s:%s\n",
- pci_device.pci_dev_info->linux_kernel_module,
- pci_device.vendor, pci_device.product,
- pci_device.sub_vendor, pci_device.sub_product,
- pci_device.pci_dev_info->vendor_name,
- pci_device.pci_dev_info->product_name);
- }
- }
- }
- printf("PCI: %d bus%s found\n",
- pci_bus_list->count,
- pci_bus_list->count == 1 ? "" : "es");
+ printf("PCI: %d devices found\n", ndev);
}
int main(int argc, char *argv[])
{
- struct pci_device_list pci_device_list;
- struct pci_bus_list pci_bus_list;
+ struct pci_domain *pci_domain;
+
openconsole(&dev_null_r, &dev_stdcon_w);
/* Scanning to detect pci buses and devices */
- pci_scan(&pci_bus_list,&pci_device_list);
+ pci_domain = pci_scan();
/* Assigning product & vendor name for each device*/
- get_name_from_pci_ids(&pci_device_list);
+ get_name_from_pci_ids(pci_domain);
/* Detecting which kernel module should match each device */
- get_module_name_from_pci_ids(&pci_device_list);
+ get_module_name_from_pci_ids(pci_domain);
/* display the pci devices we found */
- display_pci_bus(&pci_bus_list,true);
+ display_pci_devices(pci_domain);
return 1;
}