Index: usr.sbin/pcictl/pcictl.c =================================================================== RCS file: /cvsroot/src/usr.sbin/pcictl/pcictl.c,v retrieving revision 1.16 diff -u -p -r1.16 pcictl.c --- usr.sbin/pcictl/pcictl.c 4 Jul 2009 20:34:23 -0000 1.16 +++ usr.sbin/pcictl/pcictl.c 4 Jul 2009 21:38:55 -0000 @@ -61,6 +61,7 @@ struct command { const char *arg_names; void (*cmd_func)(int, char *[]); int open_flags; + int need_device; }; static void usage(void); @@ -68,29 +69,44 @@ static void usage(void); int pcifd; struct pciio_businfo pci_businfo; +struct pciio_domaininfo pci_domaininfo; const char *dvname; char dvname_store[MAXPATHLEN]; const char *cmdname; int print_numbers = 0; +static void cmd_list_pcibridges(int, char *[]); static void cmd_list(int, char *[]); static void cmd_dump(int, char *[]); +#define CMD_NEED_DEVICE 1 +#define CMD_NEED_NODEVICE 0 + const struct command commands[] = { { "list", + "[-v[v]]", + cmd_list_pcibridges, + O_RDONLY, + CMD_NEED_NODEVICE }, + + { "list", "[-n] [-b bus] [-d device] [-f function]", cmd_list, - O_RDONLY }, + O_RDONLY, + CMD_NEED_DEVICE }, { "dump", "[-b bus] -d device [-f function]", cmd_dump, - O_RDONLY }, + O_RDONLY, + CMD_NEED_DEVICE }, - { 0, 0, 0, 0 }, + { NULL, NULL, NULL, 0, 0 }, }; +const struct command *command; + static int parse_bdf(const char *); static void scan_pci(int, int, int, void (*)(u_int, u_int, u_int)); @@ -102,30 +118,47 @@ int main(int argc, char *argv[]) { int i; + int need_device; - /* Must have at least: device command */ - if (argc < 3) + /* Must have at least: command */ + if (argc < 2) usage(); /* Skip program name, get and skip device name, get command. */ dvname = argv[1]; - cmdname = argv[2]; - argv += 2; - argc -= 2; + if (strncmp(dvname, "pci", 3) == 0) { + if (argc < 3) + usage(); + need_device = CMD_NEED_DEVICE; + cmdname = argv[2]; + argv += 2; + argc -= 2; + } else { + need_device = CMD_NEED_NODEVICE; + dvname = _PATH_DEV"pci0"; + cmdname = argv[1]; + argv++; + argc--; + } /* Look up and call the command. */ - for (i = 0; commands[i].cmd_name != NULL; i++) + for (i = 0; commands[i].cmd_name != NULL; i++) { + if (need_device != commands[i].need_device) + continue; if (strcmp(cmdname, commands[i].cmd_name) == 0) break; + } if (commands[i].cmd_name == NULL) errx(EXIT_FAILURE, "unknown command: %s", cmdname); + command = &commands[i]; + /* Open the device. */ if ((strchr(dvname, '/') == NULL) && (snprintf(dvname_store, sizeof(dvname_store), _PATH_DEV "%s", dvname) < (int)sizeof(dvname_store))) dvname = dvname_store; - pcifd = open(dvname, commands[i].open_flags); + pcifd = open(dvname, command->open_flags); if (pcifd < 0) err(EXIT_FAILURE, "%s", dvname); @@ -133,7 +166,11 @@ main(int argc, char *argv[]) if (ioctl(pcifd, PCI_IOC_BUSINFO, &pci_businfo) != 0) errx(EXIT_FAILURE, "%s: not a PCI bus device", dvname); - (*commands[i].cmd_func)(argc, argv); + if (ioctl(pcifd, PCI_IOC_DOMAININFO, &pci_domaininfo) != 0) + errx(EXIT_FAILURE, "%s: not a PCI host device", dvname); + + (*command->cmd_func)(argc, argv); + close(pcifd); exit(EXIT_SUCCESS); } @@ -142,18 +179,81 @@ usage(void) { int i; + fprintf(stderr, "usage: %s command [arg [...]]\n", + getprogname()); + fprintf(stderr, " Available commands:\n"); + for (i = 0; commands[i].cmd_name != NULL; i++) + if (!commands[i].need_device) + fprintf(stderr, "\t%s %s\n", commands[i].cmd_name, + commands[i].arg_names); + fprintf(stderr, "usage: %s device command [arg [...]]\n", getprogname()); fprintf(stderr, " Available commands:\n"); for (i = 0; commands[i].cmd_name != NULL; i++) - fprintf(stderr, "\t%s %s\n", commands[i].cmd_name, - commands[i].arg_names); + if (commands[i].need_device) + fprintf(stderr, "\t%s %s\n", commands[i].cmd_name, + commands[i].arg_names); exit(EXIT_FAILURE); } static void +cmd_list_pcibridges(int argc, char *argv[]) +{ + char _str[MAXPATHLEN]; + char _dvname[MAXPATHLEN]; + u_int i; + int fd; + int ch; + int verbose_lvl = 0; + struct pciio_domaininfo dinfo; + + while ((ch = getopt(argc, argv, "vv")) != -1) { + switch (ch) { + case 'v': + verbose_lvl++; + break; + default: + usage(); + } + } + argv += optind; + argc -= optind; + + if (argc != 0) + usage(); + + for (i = 0; i < pci_domaininfo.maxdomains; i++) { + snprintf(_str, sizeof(_str), "pci%u", i); + snprintf(_dvname, sizeof(_dvname), _PATH_DEV"%s", _str); + fd = open(_dvname, O_RDONLY); + if (fd < 0) { + if (verbose_lvl == 2) + fprintf(stderr, "%s: %s\n", + _str, strerror(errno)); + continue; + } + if (verbose_lvl) { + if (ioctl(fd, PCI_IOC_DOMAININFO, &dinfo) != 0) { + if (verbose_lvl == 2) + fprintf(stderr, + "%s: not a PCI bus device", + _dvname); + } + snprintf(_str + strlen(_str), + sizeof(_str) - strlen(_str), + ": %u domno %u maxdomains %u busses %u minbus %u maxbus", + dinfo.domno, dinfo.maxdomains, + dinfo.buscnt, dinfo.minbus, dinfo.maxbus); + } + close(fd); + fprintf(stdout, "%s\n", _str); + } +} + +static void cmd_list(int argc, char *argv[]) { int bus, dev, func; @@ -257,11 +357,18 @@ scan_pci(int busarg, int devarg, int fun pcireg_t id, bhlcr; if (busarg == -1) { - busmin = 0; - busmax = 255; + busmin = pci_domaininfo.minbus; + busmax = pci_domaininfo.maxbus; } else busmin = busmax = busarg; + if (busmax > pci_domaininfo.maxbus) + errx(EXIT_FAILURE, "bus \"%u\" does not exist on %s\n", + busmax, dvname); + if (busmin < pci_domaininfo.minbus) + errx(EXIT_FAILURE, "bus \"%u\" does not exist on %s\n", + busmin, dvname); + if (devarg == -1) { devmin = 0; if (pci_businfo.maxdevs <= 0) Index: sys/dev/pci/pci.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/pci.c,v retrieving revision 1.123 diff -u -p -r1.123 pci.c --- sys/dev/pci/pci.c 4 Jul 2009 21:01:10 -0000 1.123 +++ sys/dev/pci/pci.c 4 Jul 2009 21:38:55 -0000 @@ -193,6 +193,8 @@ do { \ sc->sc_dmat = pba->pba_dmat; sc->sc_dmat64 = pba->pba_dmat64; sc->sc_pc = pba->pba_pc; + sc->sc_domain = pba->pba_domain; + printf("%s:%s: domain: %u\n", __func__, device_xname(self), sc->sc_domain); sc->sc_bus = pba->pba_bus; sc->sc_bridgetag = pba->pba_bridgetag; sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus); @@ -304,6 +306,7 @@ pci_probe_device(struct pci_softc *sc, p pa.pa_dmat = sc->sc_dmat; pa.pa_dmat64 = sc->sc_dmat64; pa.pa_pc = pc; + pa.pa_domain = sc->sc_domain; pa.pa_bus = bus; pa.pa_device = device; pa.pa_function = function; Index: sys/dev/pci/pci_usrreq.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/pci_usrreq.c,v retrieving revision 1.18 diff -u -p -r1.18 pci_usrreq.c --- sys/dev/pci/pci_usrreq.c 4 Jul 2009 21:20:56 -0000 1.18 +++ sys/dev/pci/pci_usrreq.c 4 Jul 2009 21:38:55 -0000 @@ -67,6 +67,37 @@ pciopen(dev_t dev, int flags, int mode, return 0; } +static void +pci_bus_count(struct pci_softc *sc, + u_int *buscnt, u_int *minbus, u_int *maxbus) +{ + u_int _buscnt = 0; + u_int _minbus = 255; + u_int _maxbus = 0; + struct pci_softc *tmp; + int i; + + for (i = 0; i < pci_cd.cd_ndevs; i++) { + tmp = device_lookup_private(&pci_cd, i); + if (tmp == NULL) + continue; + printf("%s:%s: sc_domain %u/%u\n", + __func__, + device_xname(device_lookup(&pci_cd, i)), + tmp->sc_domain, sc->sc_domain); + if (sc->sc_domain != tmp->sc_domain) + continue; + if (sc->sc_bus > _maxbus) + _maxbus = sc->sc_bus; + if (sc->sc_bus < _minbus) + _minbus = sc->sc_bus; + _buscnt++; + } + *buscnt = _buscnt; + *minbus = _minbus; + *maxbus = _maxbus; +} + static int pciioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { @@ -74,8 +105,10 @@ pciioctl(dev_t dev, u_long cmd, void *da device_lookup_private(&pci_cd, minor(dev)); struct pciio_bdf_cfgreg *bdfr = (void *) data; struct pciio_businfo *binfo = (void *) data; + struct pciio_domaininfo *dinfo = (void *)data; pcitag_t tag; + /* Check bounds */ switch (cmd) { case PCI_IOC_BDF_CFGREAD: case PCI_IOC_BDF_CFGWRITE: @@ -108,6 +141,13 @@ pciioctl(dev_t dev, u_long cmd, void *da binfo->maxdevs = sc->sc_maxndevs; break; + case PCI_IOC_DOMAININFO: + dinfo->domno = minor(dev); + dinfo->maxdomains = pci_cd.cd_ndevs; + pci_bus_count(sc, &dinfo->buscnt, + &dinfo->minbus, &dinfo->maxbus); + break; + default: return ENOTTY; } Index: sys/dev/pci/pciio.h =================================================================== RCS file: /cvsroot/src/sys/dev/pci/pciio.h,v retrieving revision 1.3 diff -u -p -r1.3 pciio.h --- sys/dev/pci/pciio.h 6 Jun 2009 12:56:43 -0000 1.3 +++ sys/dev/pci/pciio.h 4 Jul 2009 21:38:55 -0000 @@ -93,4 +93,20 @@ struct pciio_businfo { #define PCI_IOC_BUSINFO _IOR('P', 4, struct pciio_businfo) +/* + * pciio_domaininfo: + * + * Information for a PCI domain instance. + * (There's one PCI domain per host bridge) + */ +struct pciio_domaininfo { + u_int domno; /* domain number */ + u_int maxdomains; /* max domains */ + u_int buscnt; /* busses in this domain */ + u_int minbus; /* min busno on this domain */ + u_int maxbus; /* max busno on this domain */ +}; + +#define PCI_IOC_DOMAININFO _IOR('P', 5, struct pciio_domaininfo) + #endif /* _DEV_PCI_PCIIO_H_ */ Index: sys/dev/pci/pcivar.h =================================================================== RCS file: /cvsroot/src/sys/dev/pci/pcivar.h,v retrieving revision 1.83 diff -u -p -r1.83 pcivar.h --- sys/dev/pci/pcivar.h 22 Jul 2008 04:52:19 -0000 1.83 +++ sys/dev/pci/pcivar.h 4 Jul 2009 21:38:55 -0000 @@ -71,6 +71,7 @@ struct pcibus_attach_args { pci_chipset_tag_t pba_pc; int pba_flags; /* flags; see below */ + int pba_domain; /* PCI domain */ int pba_bus; /* PCI bus number */ /* @@ -98,6 +99,7 @@ struct pci_attach_args { pci_chipset_tag_t pa_pc; int pa_flags; /* flags; see below */ + u_int pa_domain; u_int pa_bus; u_int pa_device; u_int pa_function; @@ -173,7 +175,7 @@ struct pci_softc { bus_dma_tag_t sc_dmat; bus_dma_tag_t sc_dmat64; pci_chipset_tag_t sc_pc; - int sc_bus, sc_maxndevs; + int sc_domain, sc_bus, sc_maxndevs; pcitag_t *sc_bridgetag; u_int sc_intrswiz; pcitag_t sc_intrtag; Index: sys/dev/pci/ppb.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/ppb.c,v retrieving revision 1.40 diff -u -p -r1.40 ppb.c --- sys/dev/pci/ppb.c 2 Apr 2009 00:09:33 -0000 1.40 +++ sys/dev/pci/ppb.c 4 Jul 2009 21:38:55 -0000 @@ -149,6 +149,8 @@ ppbattach(device_t parent, device_t self pba.pba_dmat64 = pa->pa_dmat64; pba.pba_pc = pc; pba.pba_flags = pa->pa_flags & ~PCI_FLAGS_MRM_OKAY; + pba.pba_domain = pa->pa_domain; + printf("%s:%s: domain: %u\n", __func__, device_xname(self), pa->pa_domain); pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata); pba.pba_bridgetag = &sc->sc_tag; pba.pba_intrswiz = pa->pa_intrswiz; Index: sys/arch/amd64/amd64/mainbus.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/mainbus.c,v retrieving revision 1.28 diff -u -p -r1.28 mainbus.c --- sys/arch/amd64/amd64/mainbus.c 13 Jun 2009 13:35:11 -0000 1.28 +++ sys/arch/amd64/amd64/mainbus.c 4 Jul 2009 21:38:56 -0000 @@ -261,6 +261,7 @@ mainbus_attach(device_t parent, device_t mba.mba_pba.pba_dmat64 = &pci_bus_dma64_tag; mba.mba_pba.pba_pc = NULL; mba.mba_pba.pba_flags = pci_bus_flags(); + mba.mba_pba.pba_domain = 0; mba.mba_pba.pba_bus = 0; mba.mba_pba.pba_bridgetag = NULL; #if NACPI > 0 && defined(ACPI_SCANPCI) Index: sys/arch/i386/i386/mainbus.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/mainbus.c,v retrieving revision 1.85 diff -u -p -r1.85 mainbus.c --- sys/arch/i386/i386/mainbus.c 13 Jun 2009 13:35:11 -0000 1.85 +++ sys/arch/i386/i386/mainbus.c 4 Jul 2009 21:38:57 -0000 @@ -404,6 +404,7 @@ mainbus_rescan(device_t self, const char mba.mba_pba.pba_dmat64 = NULL; mba.mba_pba.pba_pc = NULL; mba.mba_pba.pba_flags = pci_bus_flags(); + mba.mba_pba.pba_domain = 0; mba.mba_pba.pba_bus = 0; mba.mba_pba.pba_bridgetag = NULL; #if NACPI > 0 && defined(ACPI_SCANPCI) Index: sys/arch/x86/pci/pchb.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/pci/pchb.c,v retrieving revision 1.18 diff -u -p -r1.18 pchb.c --- sys/arch/x86/pci/pchb.c 7 Apr 2009 17:52:36 -0000 1.18 +++ sys/arch/x86/pci/pchb.c 4 Jul 2009 21:38:58 -0000 @@ -430,6 +430,8 @@ pchbattach(device_t parent, device_t sel pba.pba_dmat64 = pa->pa_dmat64; pba.pba_pc = pa->pa_pc; pba.pba_flags = attachflags; + pba.pba_domain = device_unit(self); + printf("%s:%s: domain: %u\n", __func__, device_xname(self), pba.pba_domain); pba.pba_bus = pbnum; pba.pba_bridgetag = NULL; pba.pba_pc = pa->pa_pc; Index: sys/arch/x86/x86/mp.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/mp.c,v retrieving revision 1.2 diff -u -p -r1.2 mp.c --- sys/arch/x86/x86/mp.c 13 Jun 2009 13:35:11 -0000 1.2 +++ sys/arch/x86/x86/mp.c 4 Jul 2009 21:38:58 -0000 @@ -73,6 +73,9 @@ mp_pci_scan(device_t self, struct pcibus if (mpb->mb_name == NULL) continue; if (strcmp(mpb->mb_name, "pci") == 0 && mpb->mb_dev == NULL) { + pba->pba_domain = device_unit(self); + printf("%s:%s: domain %u\n", __func__, + device_xname(self), pba->pba_domain); pba->pba_bus = i; mpb->mb_dev = config_found_ia(self, "pcibus", pba, print); Index: sys/arch/xen/xen/hypervisor.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/xen/hypervisor.c,v retrieving revision 1.46 diff -u -p -r1.46 hypervisor.c --- sys/arch/xen/xen/hypervisor.c 18 Apr 2009 09:51:21 -0000 1.46 +++ sys/arch/xen/xen/hypervisor.c 4 Jul 2009 21:38:58 -0000 @@ -310,6 +310,7 @@ hypervisor_attach(device_t parent, devic #endif /* _LP64 */ hac.hac_pba.pba_flags = PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_IO_ENABLED; hac.hac_pba.pba_bridgetag = NULL; + hac.hac_pba.pba_domain = 0; hac.hac_pba.pba_bus = 0; #if NACPI > 0 && defined(ACPI_SCANPCI) if (mpacpi_active) Index: sys/arch/xen/xen/xpci_xenbus.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/xen/xpci_xenbus.c,v retrieving revision 1.2 diff -u -p -r1.2 xpci_xenbus.c --- sys/arch/xen/xen/xpci_xenbus.c 6 Mar 2009 23:35:34 -0000 1.2 +++ sys/arch/xen/xen/xpci_xenbus.c 4 Jul 2009 21:38:58 -0000 @@ -398,6 +398,7 @@ xpci_attach_pcibus(int domain, int busn) pba.pba_flags = PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; pba.pba_bridgetag = NULL; + pba.pba_domain = domain; pba.pba_bus = busn; config_found_ia(xpci_sc->sc_dev, "pcibus", &pba, pcibusprint); }