1/* 2 * Copyright 1996 Massachusetts Institute of Technology 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose and without fee is hereby 6 * granted, provided that both the above copyright notice and this 7 * permission notice appear in all copies, that both the above 8 * copyright notice and this permission notice appear in all --- 15 unchanged lines hidden (view full) --- 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#ifndef lint 31static const char rcsid[] = |
32 "$FreeBSD: stable/10/usr.sbin/pciconf/pciconf.c 261250 2014-01-28 21:56:18Z jhb $"; |
33#endif /* not lint */ 34 35#include <sys/types.h> 36#include <sys/fcntl.h> 37 |
38#include <assert.h> |
39#include <ctype.h> 40#include <err.h> 41#include <inttypes.h> 42#include <stdlib.h> 43#include <stdio.h> 44#include <string.h> 45#include <unistd.h> 46#include <sys/pciio.h> --- 16 unchanged lines hidden (view full) --- 63 TAILQ_ENTRY(pci_vendor_info) link; 64 TAILQ_HEAD(,pci_device_info) devs; 65 int id; 66 char *desc; 67}; 68 69TAILQ_HEAD(,pci_vendor_info) pci_vendors; 70 |
71static struct pcisel getsel(const char *str); |
72static void list_bars(int fd, struct pci_conf *p); |
73static void list_devs(const char *name, int verbose, int bars, int caps, 74 int errors); |
75static void list_verbose(struct pci_conf *p); 76static const char *guess_class(struct pci_conf *p); 77static const char *guess_subclass(struct pci_conf *p); 78static int load_vendors(void); 79static void readit(const char *, const char *, int); 80static void writeit(const char *, const char *, const char *, int); 81static void chkattached(const char *); 82 83static int exitstatus = 0; 84 85static void 86usage(void) 87{ 88 fprintf(stderr, "%s\n%s\n%s\n%s\n", |
89 "usage: pciconf -l [-bcev] [device]", 90 " pciconf -a device", 91 " pciconf -r [-b | -h] device addr[:addr2]", 92 " pciconf -w [-b | -h] device addr value"); |
93 exit (1); 94} 95 96int 97main(int argc, char **argv) 98{ 99 int c; 100 int listmode, readmode, writemode, attachedmode; --- 42 unchanged lines hidden (view full) --- 143 verbose = 1; 144 break; 145 146 default: 147 usage(); 148 } 149 } 150 |
151 if ((listmode && optind >= argc + 1) |
152 || (writemode && optind + 3 != argc) 153 || (readmode && optind + 2 != argc) 154 || (attachedmode && optind + 1 != argc)) 155 usage(); 156 157 if (listmode) { |
158 list_devs(optind + 1 == argc ? argv[optind] : NULL, verbose, 159 bars, caps, errors); |
160 } else if (attachedmode) { 161 chkattached(argv[optind]); 162 } else if (readmode) { 163 readit(argv[optind], argv[optind + 1], 164 byte ? 1 : isshort ? 2 : 4); 165 } else if (writemode) { 166 writeit(argv[optind], argv[optind + 1], argv[optind + 2], 167 byte ? 1 : isshort ? 2 : 4); 168 } else { 169 usage(); 170 } 171 172 return exitstatus; 173} 174 175static void |
176list_devs(const char *name, int verbose, int bars, int caps, int errors) |
177{ 178 int fd; 179 struct pci_conf_io pc; 180 struct pci_conf conf[255], *p; |
181 struct pci_match_conf patterns[1]; |
182 int none_count = 0; 183 184 if (verbose) 185 load_vendors(); 186 187 fd = open(_PATH_DEVPCI, (caps || errors) ? O_RDWR : O_RDONLY, 0); 188 if (fd < 0) 189 err(1, "%s", _PATH_DEVPCI); 190 191 bzero(&pc, sizeof(struct pci_conf_io)); 192 pc.match_buf_len = sizeof(conf); 193 pc.matches = conf; |
194 if (name != NULL) { 195 bzero(&patterns, sizeof(patterns)); 196 patterns[0].pc_sel = getsel(name); 197 patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN | 198 PCI_GETCONF_MATCH_BUS | PCI_GETCONF_MATCH_DEV | 199 PCI_GETCONF_MATCH_FUNC; 200 pc.num_patterns = 1; 201 pc.pat_buf_len = sizeof(patterns); 202 pc.patterns = patterns; 203 } |
204 205 do { 206 if (ioctl(fd, PCIOCGETCONF, &pc) == -1) 207 err(1, "ioctl(PCIOCGETCONF)"); 208 209 /* 210 * 255 entries should be more than enough for most people, 211 * but if someone has more devices, and then changes things --- 355 unchanged lines hidden (view full) --- 567 568 if (ioctl(fd, PCIOCREAD, &pi) < 0) 569 err(1, "ioctl(PCIOCREAD)"); 570 571 return (pi.pi_data); 572} 573 574static struct pcisel |
575getdevice(const char *name) |
576{ |
577 struct pci_conf_io pc; 578 struct pci_conf conf[1]; 579 struct pci_match_conf patterns[1]; 580 char *cp; 581 int fd; 582 583 fd = open(_PATH_DEVPCI, O_RDONLY, 0); 584 if (fd < 0) 585 err(1, "%s", _PATH_DEVPCI); 586 587 bzero(&pc, sizeof(struct pci_conf_io)); 588 pc.match_buf_len = sizeof(conf); 589 pc.matches = conf; 590 591 bzero(&patterns, sizeof(patterns)); 592 593 /* 594 * The pattern structure requires the unit to be split out from 595 * the driver name. Walk backwards from the end of the name to 596 * find the start of the unit. 597 */ 598 if (name[0] == '\0') 599 err(1, "Empty device name"); 600 cp = strchr(name, '\0'); 601 assert(cp != NULL && cp != name); 602 cp--; 603 while (cp != name && isdigit(cp[-1])) 604 cp--; 605 if (cp == name) 606 errx(1, "Invalid device name"); 607 if ((size_t)(cp - name) + 1 > sizeof(patterns[0].pd_name)) 608 errx(1, "Device name i2s too long"); 609 memcpy(patterns[0].pd_name, name, cp - name); 610 patterns[0].pd_unit = strtol(cp, &cp, 10); 611 assert(*cp == '\0'); 612 patterns[0].flags = PCI_GETCONF_MATCH_NAME | PCI_GETCONF_MATCH_UNIT; 613 pc.num_patterns = 1; 614 pc.pat_buf_len = sizeof(patterns); 615 pc.patterns = patterns; 616 617 if (ioctl(fd, PCIOCGETCONF, &pc) == -1) 618 err(1, "ioctl(PCIOCGETCONF)"); 619 if (pc.status != PCI_GETCONF_LAST_DEVICE && 620 pc.status != PCI_GETCONF_MORE_DEVS) 621 errx(1, "error returned from PCIOCGETCONF ioctl"); 622 close(fd); 623 if (pc.num_matches == 0) 624 errx(1, "Device not found"); 625 return (conf[0].pc_sel); 626} 627 628static struct pcisel 629parsesel(const char *str) 630{ |
631 char *ep = strchr(str, '@'); 632 char *epbase; 633 struct pcisel sel; 634 unsigned long selarr[4]; 635 int i; 636 637 if (ep == NULL) 638 ep = (char *)str; --- 20 unchanged lines hidden (view full) --- 659 else 660 sel.pc_domain = 0; 661 } 662 if (*ep != '\x0' || ep == epbase) 663 errx(1, "cannot parse selector %s", str); 664 return sel; 665} 666 |
667static struct pcisel 668getsel(const char *str) 669{ 670 671 /* 672 * No device names contain colons and selectors always contain 673 * at least one colon. 674 */ 675 if (strchr(str, ':') == NULL) 676 return (getdevice(str)); 677 else 678 return (parsesel(str)); 679} 680 |
681static void 682readone(int fd, struct pcisel *sel, long reg, int width) 683{ 684 685 printf("%0*x", width*2, read_config(fd, sel, reg, width)); 686} 687 688static void --- 68 unchanged lines hidden --- |