void pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus) { int dev, multi, ht; struct pci_dev *t; a->debug("Scanning bus %02x for devices...\n", bus); if (busmap[bus]) { a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus); return; } busmap[bus] = 1; t = pci_alloc_dev(a); t->bus = bus; for (dev=0; dev<32; dev++) { t->dev = dev; multi = 0; for (t->func=0; !t->func || multi && t->func<8; t->func++) { u32 vd = pci_read_long(t, PCI_VENDOR_ID); struct pci_dev *d; if (!vd || vd == 0xffffffff) continue; ht = pci_read_byte(t, PCI_HEADER_TYPE); if (!t->func) multi = ht & 0x80; ht &= 0x7f; d = pci_alloc_dev(a); d->bus = t->bus; d->dev = t->dev; d->func = t->func; d->vendor_id = vd & 0xffff; d->device_id = vd >> 16U; d->known_fields = PCI_FILL_IDENT; d->hdrtype = ht; pci_link_dev(a, d); switch (ht) { case PCI_HEADER_TYPE_NORMAL: break; case PCI_HEADER_TYPE_BRIDGE: case PCI_HEADER_TYPE_CARDBUS: pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS)); break; default: a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht); } } } pci_free_dev(t); }
int print_ambs(struct pci_dev *dev, struct pci_access *pacc) { struct pci_dev *dev16; int branch, channel, amb; int max_branch, max_channel, max_amb; volatile void *ambconfig; uint64_t ambconfig_phys; printf("\n============= AMBs ============\n\n"); switch (dev->device_id) { case PCI_DEVICE_ID_INTEL_I5000P: case PCI_DEVICE_ID_INTEL_I5000X: case PCI_DEVICE_ID_INTEL_I5000Z: max_branch = 2; if (!(dev16 = pci_get_dev(pacc, 0, 0, 0x10, 0))) { perror("Error: no device 0:16.0\n"); return 1; } ambconfig_phys = ((uint64_t)pci_read_long(dev16, 0x4c) << 32) | pci_read_long(dev16, 0x48); max_channel = pci_read_byte(dev16, 0x56)/max_branch; max_amb = pci_read_byte(dev16, 0x57); pci_free_dev(dev16); break; default: fprintf(stderr, "Error: Dumping AMBs on this MCH is not (yet) supported.\n"); return 1; } if (!(ambconfig = map_physical(ambconfig_phys, AMB_CONFIG_SPACE_SIZE))) { fprintf(stderr, "Error mapping AMB config space\n"); return 1; } for(branch = 0; branch < max_branch; branch++) { for(channel = 0; channel < max_channel; channel++) { for(amb = 0; amb < max_amb; amb++) { dump_amb(ambconfig, branch, channel, amb); } } } unmap_physical((void *)ambconfig, AMB_CONFIG_SPACE_SIZE); return 0; }
void pci_cleanup(struct pci_access *a) { struct pci_dev *d, *e; for(d=a->devices; d; d=e) { e = d->next; pci_free_dev(d); } if (a->methods) a->methods->cleanup(a); pci_free_name_list(a); pci_mfree(a); }
void pci_cleanup(struct pci_access *a) { struct pci_dev *d, *e; for(d=a->devices; d; d=e) { e = d->next; pci_free_dev(d); } if (a->methods) { if( a->methods->cleanup != NULL ) { a->methods->cleanup(a); } //this is the bug, we don't need iopl3 cleanup in windows } pci_mfree(a); }
int main(int argc, char* argv[]) { int err = EXIT_FAILURE; struct cmd_line cmd_line; setlocale(LC_ALL, ""); if (parse_cmd_line(argc, argv, &cmd_line) < 0) goto arg_check_failed; struct pci_access * pci = pci_alloc(); if (! pci) goto pci_alloc_failed; /* This access bypass the kernel and use a memory mapping * to PCI configuration registers */ pci->method = PCI_ACCESS_I386_TYPE1; struct pci_dev * dev = create_pci_dev(pci, cmd_line.slot); if (! dev) goto create_pci_dev_failed; print_device_name(pci, dev); unsigned long * timestamps = malloc(sizeof(*timestamps) * cmd_line.iteration_count); if (! timestamps) { fprintf(stderr, "Can't allocate timestamp storage (%s)\n", strerror(errno)); goto malloc_failed; } struct timestamp t; read_timestamp_counter(&t); perform_reads(dev, timestamps, cmd_line.iteration_count, cmd_line.wait_time_us); unsigned long test_duration_cycles = cycle_since_timestamp(&t); double cpu_mhz = get_cpu_mhz(); if (cpu_mhz < 0) goto get_cpu_mhz_failed; print_results(cpu_mhz, timestamps, cmd_line.iteration_count, test_duration_cycles, cmd_line.limit_ns); err = EXIT_SUCCESS; get_cpu_mhz_failed: free(timestamps); malloc_failed: pci_free_dev(dev); create_pci_dev_failed: pci_cleanup(pci); pci_alloc_failed: arg_check_failed: return err; }
sbone_err_t sbone_dev_open_pcie (sbone_dev_t* dev, int dom, int bus, int _dev, int fun) { static const size_t nbar = sizeof(dev->bar_addrs) / sizeof(dev->bar_addrs[0]); int mem_fd; size_t i; struct pci_access* pci_access; struct pci_dev* pci_dev; int err = -1; /* zero device */ for (i = 0; i < nbar; ++i) dev->bar_sizes[i] = 0; dev->nid = -1; /* find the pci device */ pci_access = pci_alloc(); if (pci_access == NULL) { PERROR(); goto on_error_0; } pci_init(pci_access); pci_scan_bus(pci_access); pci_dev = pci_get_dev(pci_access, dom, bus, _dev, fun); if (pci_dev == NULL) { PERROR(); goto on_error_1; } pci_fill_info(pci_dev, PCI_FILL_IDENT | PCI_FILL_BASES); /* map bars */ mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if (mem_fd == -1) { PERROR(); goto on_error_2; } for (i = 0; i < nbar; ++i) { #if 1 /* FIXME: pci_dev->size[i] not detected by pci_fill_info ... */ if (pci_dev->base_addr[i] != 0) pci_dev->size[i] = get_bar_size(pci_access, pci_dev, i); #endif /* FIXME */ dev->bar_sizes[i] = pci_dev->size[i]; if (dev->bar_sizes[i] == 0) continue ; dev->bar_addrs[i] = (uintptr_t)mmap ( NULL, pci_dev->size[i], PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, mem_fd, pci_dev->base_addr[i] ); if (dev->bar_addrs[i] == (uintptr_t)MAP_FAILED) { size_t j; for (j = 0; j < i; ++j) munmap((void*)dev->bar_addrs[i], dev->bar_sizes[i]); PERROR(); goto on_error_3; } } if ((dev->fd = open("/dev/sbone", O_RDWR)) == -1) { PERROR(); goto on_error_3; } /* success */ err = 0; on_error_3: close(mem_fd); on_error_2: pci_free_dev(pci_dev); on_error_1: pci_cleanup(pci_access); on_error_0: return err; }