pciconf.c revision 133271
119102Sse/* 219102Sse * Copyright 1996 Massachusetts Institute of Technology 319102Sse * 419102Sse * Permission to use, copy, modify, and distribute this software and 519102Sse * its documentation for any purpose and without fee is hereby 619102Sse * granted, provided that both the above copyright notice and this 719102Sse * permission notice appear in all copies, that both the above 819102Sse * copyright notice and this permission notice appear in all 919102Sse * supporting documentation, and that the name of M.I.T. not be used 1019102Sse * in advertising or publicity pertaining to distribution of the 1119102Sse * software without specific, written prior permission. M.I.T. makes 1219102Sse * no representations about the suitability of this software for any 1319102Sse * purpose. It is provided "as is" without express or implied 1419102Sse * warranty. 1519102Sse * 1619102Sse * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 1719102Sse * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 1819102Sse * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1919102Sse * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 2019102Sse * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2119102Sse * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2219102Sse * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2319102Sse * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2419102Sse * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2519102Sse * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2619102Sse * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2719102Sse * SUCH DAMAGE. 2819102Sse */ 2919102Sse 3030172Scharnier#ifndef lint 3130172Scharnierstatic const char rcsid[] = 3250479Speter "$FreeBSD: head/usr.sbin/pciconf/pciconf.c 133271 2004-08-07 16:36:46Z imp $"; 3330172Scharnier#endif /* not lint */ 3430172Scharnier 3519102Sse#include <sys/types.h> 3619102Sse#include <sys/fcntl.h> 3719102Sse 3819102Sse#include <err.h> 3919102Sse#include <stdlib.h> 4019102Sse#include <stdio.h> 4119102Sse#include <string.h> 4219102Sse#include <unistd.h> 4354322Sken#include <sys/pciio.h> 4469700Smsmith#include <sys/queue.h> 4519102Sse 4669785Smsmith#include <dev/pci/pcireg.h> 4769700Smsmith 4819102Sse#include "pathnames.h" 4919102Sse 5069700Smsmithstruct pci_device_info 5169700Smsmith{ 5269700Smsmith TAILQ_ENTRY(pci_device_info) link; 5369700Smsmith int id; 5469700Smsmith char *desc; 5569700Smsmith}; 5669700Smsmith 5769700Smsmithstruct pci_vendor_info 5869700Smsmith{ 5969700Smsmith TAILQ_ENTRY(pci_vendor_info) link; 6069700Smsmith TAILQ_HEAD(,pci_device_info) devs; 6169700Smsmith int id; 6269700Smsmith char *desc; 6369700Smsmith}; 6469700Smsmith 6569700SmsmithTAILQ_HEAD(,pci_vendor_info) pci_vendors; 6669700Smsmith 6768677Smsmithstatic void list_devs(int vendors); 6869700Smsmithstatic void list_verbose(struct pci_conf *p); 6969700Smsmithstatic char *guess_class(struct pci_conf *p); 7069700Smsmithstatic char *guess_subclass(struct pci_conf *p); 7169700Smsmithstatic int load_vendors(void); 7219102Ssestatic void readit(const char *, const char *, int); 7319102Ssestatic void writeit(const char *, const char *, const char *, int); 7421935Ssestatic void chkattached(const char *, int); 7519102Sse 7650225Speterstatic int exitstatus = 0; 7719102Sse 7819102Ssestatic void 7930172Scharnierusage() 8030172Scharnier{ 8130172Scharnier fprintf(stderr, "%s\n%s\n%s\n%s\n", 8268677Smsmith "usage: pciconf -l [-v]", 83103499Sjdp " pciconf -a selector", 84103499Sjdp " pciconf -r [-b | -h] selector addr[:addr2]", 85103499Sjdp " pciconf -w [-b | -h] selector addr value"); 8619817Sse exit (1); 8719102Sse} 8819102Sse 8919102Sseint 9019102Ssemain(int argc, char **argv) 9119102Sse{ 9219102Sse int c; 93133271Simp int listmode, readmode, writemode, attachedmode, verbose; 9419102Sse int byte, isshort; 9519102Sse 96133271Simp listmode = readmode = writemode = attachedmode = verbose = byte = isshort = 0; 9719102Sse 98133271Simp while ((c = getopt(argc, argv, "alrwbhv")) != -1) { 9919102Sse switch(c) { 10021935Sse case 'a': 10121935Sse attachedmode = 1; 10221935Sse break; 10321935Sse 10419102Sse case 'l': 10519102Sse listmode = 1; 10619102Sse break; 10719102Sse 10819102Sse case 'r': 10919102Sse readmode = 1; 11019102Sse break; 11119102Sse 11219102Sse case 'w': 11319102Sse writemode = 1; 11419102Sse break; 11519102Sse 116133271Simp case 'b': 117133271Simp byte = 1; 118133271Simp break; 119133271Simp 120133271Simp case 'h': 121133271Simp isshort = 1; 122133271Simp break; 123133271Simp 12468677Smsmith case 'v': 12569700Smsmith verbose = 1; 12668677Smsmith break; 12768677Smsmith 12819102Sse default: 12930172Scharnier usage(); 13019102Sse } 13119102Sse } 13219102Sse 13319102Sse if ((listmode && optind != argc) 13419102Sse || (writemode && optind + 3 != argc) 13521935Sse || (readmode && optind + 2 != argc) 136133271Simp || (attachedmode && optind + 1 != argc)) 13730172Scharnier usage(); 13819102Sse 13919102Sse if (listmode) { 14069700Smsmith list_devs(verbose); 14177513Simp } else if (attachedmode) { 14221935Sse chkattached(argv[optind], 14321935Sse byte ? 1 : isshort ? 2 : 4); 14477513Simp } else if (readmode) { 14519102Sse readit(argv[optind], argv[optind + 1], 14619102Sse byte ? 1 : isshort ? 2 : 4); 14777513Simp } else if (writemode) { 14819102Sse writeit(argv[optind], argv[optind + 1], argv[optind + 2], 14919102Sse byte ? 1 : isshort ? 2 : 4); 15019102Sse } else { 15130172Scharnier usage(); 15219102Sse } 15319102Sse 15421935Sse return exitstatus; 15519102Sse} 15619102Sse 15719102Ssestatic void 15869700Smsmithlist_devs(int verbose) 15919102Sse{ 16019102Sse int fd; 16119102Sse struct pci_conf_io pc; 16219102Sse struct pci_conf conf[255], *p; 16341103Sken int none_count = 0; 16419102Sse 16569700Smsmith if (verbose) 16669700Smsmith load_vendors(); 16769700Smsmith 168124031Srwatson fd = open(_PATH_DEVPCI, O_RDONLY, 0); 16919102Sse if (fd < 0) 17019102Sse err(1, "%s", _PATH_DEVPCI); 17119102Sse 17239231Sgibbs bzero(&pc, sizeof(struct pci_conf_io)); 17339231Sgibbs pc.match_buf_len = sizeof(conf); 17439231Sgibbs pc.matches = conf; 17519102Sse 17639231Sgibbs do { 17739231Sgibbs if (ioctl(fd, PCIOCGETCONF, &pc) == -1) 17839231Sgibbs err(1, "ioctl(PCIOCGETCONF)"); 17919102Sse 18039231Sgibbs /* 18139231Sgibbs * 255 entries should be more than enough for most people, 18239231Sgibbs * but if someone has more devices, and then changes things 18339231Sgibbs * around between ioctls, we'll do the cheezy thing and 18439231Sgibbs * just bail. The alternative would be to go back to the 18539231Sgibbs * beginning of the list, and print things twice, which may 18639231Sgibbs * not be desireable. 18739231Sgibbs */ 18839231Sgibbs if (pc.status == PCI_GETCONF_LIST_CHANGED) { 18939231Sgibbs warnx("PCI device list changed, please try again"); 19039231Sgibbs exitstatus = 1; 19139231Sgibbs close(fd); 19239231Sgibbs return; 19339231Sgibbs } else if (pc.status == PCI_GETCONF_ERROR) { 19453761Scharnier warnx("error returned from PCIOCGETCONF ioctl"); 19539231Sgibbs exitstatus = 1; 19639231Sgibbs close(fd); 19739231Sgibbs return; 19839231Sgibbs } 19939231Sgibbs for (p = conf; p < &conf[pc.num_matches]; p++) { 20039231Sgibbs 20150225Speter printf("%s%d@pci%d:%d:%d:\tclass=0x%06x card=0x%08x " 20250225Speter "chip=0x%08x rev=0x%02x hdr=0x%02x\n", 20341103Sken (p->pd_name && *p->pd_name) ? p->pd_name : 20441103Sken "none", 20550225Speter (p->pd_name && *p->pd_name) ? (int)p->pd_unit : 20641103Sken none_count++, 20739231Sgibbs p->pc_sel.pc_bus, p->pc_sel.pc_dev, 20839231Sgibbs p->pc_sel.pc_func, (p->pc_class << 16) | 20939231Sgibbs (p->pc_subclass << 8) | p->pc_progif, 21039231Sgibbs (p->pc_subdevice << 16) | p->pc_subvendor, 21139231Sgibbs (p->pc_device << 16) | p->pc_vendor, 21239231Sgibbs p->pc_revid, p->pc_hdr); 21369700Smsmith if (verbose) 21469700Smsmith list_verbose(p); 21539231Sgibbs } 21639231Sgibbs } while (pc.status == PCI_GETCONF_MORE_DEVS); 21739231Sgibbs 21819102Sse close(fd); 21919102Sse} 22019102Sse 22168677Smsmithstatic void 22269700Smsmithlist_verbose(struct pci_conf *p) 22368677Smsmith{ 22469700Smsmith struct pci_vendor_info *vi; 22569700Smsmith struct pci_device_info *di; 22669700Smsmith char *dp; 22769700Smsmith 22869700Smsmith TAILQ_FOREACH(vi, &pci_vendors, link) { 22969700Smsmith if (vi->id == p->pc_vendor) { 23069700Smsmith printf(" vendor = '%s'\n", vi->desc); 23168677Smsmith break; 23269700Smsmith } 23369700Smsmith } 23469700Smsmith if (vi == NULL) { 23569700Smsmith di = NULL; 23668677Smsmith } else { 23769700Smsmith TAILQ_FOREACH(di, &vi->devs, link) { 23869700Smsmith if (di->id == p->pc_device) { 23969700Smsmith printf(" device = '%s'\n", di->desc); 24069700Smsmith break; 24169700Smsmith } 24269700Smsmith } 24368677Smsmith } 24469700Smsmith if ((dp = guess_class(p)) != NULL) 24569700Smsmith printf(" class = %s\n", dp); 24669700Smsmith if ((dp = guess_subclass(p)) != NULL) 24769700Smsmith printf(" subclass = %s\n", dp); 24869700Smsmith} 24969700Smsmith 25069700Smsmith/* 25169700Smsmith * This is a direct cut-and-paste from the table in sys/dev/pci/pci.c. 25269700Smsmith */ 25369700Smsmithstatic struct 25469700Smsmith{ 25569700Smsmith int class; 25669700Smsmith int subclass; 25769700Smsmith char *desc; 25869700Smsmith} pci_nomatch_tab[] = { 25969700Smsmith {PCIC_OLD, -1, "old"}, 26069700Smsmith {PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"}, 26169700Smsmith {PCIC_OLD, PCIS_OLD_VGA, "VGA-compatible display device"}, 26269700Smsmith {PCIC_STORAGE, -1, "mass storage"}, 26369700Smsmith {PCIC_STORAGE, PCIS_STORAGE_SCSI, "SCSI"}, 26469700Smsmith {PCIC_STORAGE, PCIS_STORAGE_IDE, "ATA"}, 26569700Smsmith {PCIC_STORAGE, PCIS_STORAGE_FLOPPY, "floppy disk"}, 26669700Smsmith {PCIC_STORAGE, PCIS_STORAGE_IPI, "IPI"}, 26769700Smsmith {PCIC_STORAGE, PCIS_STORAGE_RAID, "RAID"}, 26869700Smsmith {PCIC_NETWORK, -1, "network"}, 26969700Smsmith {PCIC_NETWORK, PCIS_NETWORK_ETHERNET, "ethernet"}, 27069700Smsmith {PCIC_NETWORK, PCIS_NETWORK_TOKENRING, "token ring"}, 27169700Smsmith {PCIC_NETWORK, PCIS_NETWORK_FDDI, "fddi"}, 27269700Smsmith {PCIC_NETWORK, PCIS_NETWORK_ATM, "ATM"}, 27369700Smsmith {PCIC_DISPLAY, -1, "display"}, 27469700Smsmith {PCIC_DISPLAY, PCIS_DISPLAY_VGA, "VGA"}, 27569700Smsmith {PCIC_DISPLAY, PCIS_DISPLAY_XGA, "XGA"}, 27669700Smsmith {PCIC_MULTIMEDIA, -1, "multimedia"}, 27769700Smsmith {PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_VIDEO, "video"}, 27869700Smsmith {PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_AUDIO, "audio"}, 27969700Smsmith {PCIC_MEMORY, -1, "memory"}, 28069700Smsmith {PCIC_MEMORY, PCIS_MEMORY_RAM, "RAM"}, 28169700Smsmith {PCIC_MEMORY, PCIS_MEMORY_FLASH, "flash"}, 28269700Smsmith {PCIC_BRIDGE, -1, "bridge"}, 28369700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_HOST, "HOST-PCI"}, 28469700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_ISA, "PCI-ISA"}, 28569700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_EISA, "PCI-EISA"}, 28669700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_MCA, "PCI-MCA"}, 28769700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_PCI, "PCI-PCI"}, 28869700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_PCMCIA, "PCI-PCMCIA"}, 28969700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_NUBUS, "PCI-NuBus"}, 29069700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_CARDBUS, "PCI-CardBus"}, 29169700Smsmith {PCIC_BRIDGE, PCIS_BRIDGE_OTHER, "PCI-unknown"}, 29269700Smsmith {PCIC_SIMPLECOMM, -1, "simple comms"}, 29369700Smsmith {PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_UART, "UART"}, /* could detect 16550 */ 29469700Smsmith {PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_PAR, "parallel port"}, 29569700Smsmith {PCIC_BASEPERIPH, -1, "base peripheral"}, 29669700Smsmith {PCIC_BASEPERIPH, PCIS_BASEPERIPH_PIC, "interrupt controller"}, 29769700Smsmith {PCIC_BASEPERIPH, PCIS_BASEPERIPH_DMA, "DMA controller"}, 29869700Smsmith {PCIC_BASEPERIPH, PCIS_BASEPERIPH_TIMER, "timer"}, 29969700Smsmith {PCIC_BASEPERIPH, PCIS_BASEPERIPH_RTC, "realtime clock"}, 30069700Smsmith {PCIC_INPUTDEV, -1, "input device"}, 30169700Smsmith {PCIC_INPUTDEV, PCIS_INPUTDEV_KEYBOARD, "keyboard"}, 30269700Smsmith {PCIC_INPUTDEV, PCIS_INPUTDEV_DIGITIZER,"digitizer"}, 30369700Smsmith {PCIC_INPUTDEV, PCIS_INPUTDEV_MOUSE, "mouse"}, 30469700Smsmith {PCIC_DOCKING, -1, "docking station"}, 30569700Smsmith {PCIC_PROCESSOR, -1, "processor"}, 30669700Smsmith {PCIC_SERIALBUS, -1, "serial bus"}, 30769700Smsmith {PCIC_SERIALBUS, PCIS_SERIALBUS_FW, "FireWire"}, 30869700Smsmith {PCIC_SERIALBUS, PCIS_SERIALBUS_ACCESS, "AccessBus"}, 30969700Smsmith {PCIC_SERIALBUS, PCIS_SERIALBUS_SSA, "SSA"}, 31069700Smsmith {PCIC_SERIALBUS, PCIS_SERIALBUS_USB, "USB"}, 31169700Smsmith {PCIC_SERIALBUS, PCIS_SERIALBUS_FC, "Fibre Channel"}, 31269700Smsmith {PCIC_SERIALBUS, PCIS_SERIALBUS_SMBUS, "SMBus"}, 31369700Smsmith {0, 0, NULL} 31469700Smsmith}; 31569700Smsmith 31669700Smsmithstatic char * 31769700Smsmithguess_class(struct pci_conf *p) 31869700Smsmith{ 31969700Smsmith int i; 32069700Smsmith 32169700Smsmith for (i = 0; pci_nomatch_tab[i].desc != NULL; i++) { 32269700Smsmith if (pci_nomatch_tab[i].class == p->pc_class) 32369700Smsmith return(pci_nomatch_tab[i].desc); 32469700Smsmith } 32569700Smsmith return(NULL); 32669700Smsmith} 32769700Smsmith 32869700Smsmithstatic char * 32969700Smsmithguess_subclass(struct pci_conf *p) 33069700Smsmith{ 33169700Smsmith int i; 33269700Smsmith 33369700Smsmith for (i = 0; pci_nomatch_tab[i].desc != NULL; i++) { 33469700Smsmith if ((pci_nomatch_tab[i].class == p->pc_class) && 33569700Smsmith (pci_nomatch_tab[i].subclass == p->pc_subclass)) 33669700Smsmith return(pci_nomatch_tab[i].desc); 33769700Smsmith } 33869700Smsmith return(NULL); 33969700Smsmith} 34069700Smsmith 34169700Smsmithstatic int 34269700Smsmithload_vendors(void) 34369700Smsmith{ 34469700Smsmith char *dbf; 34569700Smsmith FILE *db; 34669700Smsmith struct pci_vendor_info *cv; 34769700Smsmith struct pci_device_info *cd; 34869700Smsmith char buf[100], str[100]; 34969700Smsmith int id, error; 35069700Smsmith 35169700Smsmith /* 35269700Smsmith * Locate the database and initialise. 35369700Smsmith */ 35469700Smsmith TAILQ_INIT(&pci_vendors); 35569700Smsmith if ((dbf = getenv("PCICONF_VENDOR_DATABASE")) == NULL) 35669700Smsmith dbf = _PATH_PCIVDB; 35769700Smsmith if ((db = fopen(dbf, "r")) == NULL) 35869700Smsmith return(1); 35969700Smsmith cv = NULL; 36069700Smsmith cd = NULL; 36169700Smsmith error = 0; 36269700Smsmith 36369700Smsmith /* 36469700Smsmith * Scan input lines from the database 36569700Smsmith */ 36669700Smsmith for (;;) { 36769700Smsmith if (fgets(buf, sizeof(buf), db) == NULL) 36868677Smsmith break; 36969700Smsmith 37069700Smsmith /* Check for vendor entry */ 37169700Smsmith if ((buf[0] != '\t') && (sscanf(buf, "%04x\t%[^\n]", &id, str) == 2)) { 37269700Smsmith if ((id == 0) || (strlen(str) < 1)) 37369700Smsmith continue; 37469700Smsmith if ((cv = malloc(sizeof(struct pci_vendor_info))) == NULL) { 37569700Smsmith warn("allocating vendor entry"); 37669700Smsmith error = 1; 37769700Smsmith break; 37869700Smsmith } 37969700Smsmith if ((cv->desc = strdup(str)) == NULL) { 38069700Smsmith free(cv); 38169700Smsmith warn("allocating vendor description"); 38269700Smsmith error = 1; 38369700Smsmith break; 38469700Smsmith } 38569700Smsmith cv->id = id; 38669700Smsmith TAILQ_INIT(&cv->devs); 38769700Smsmith TAILQ_INSERT_TAIL(&pci_vendors, cv, link); 38869700Smsmith continue; 38969700Smsmith } 39069700Smsmith 39169700Smsmith /* Check for device entry */ 39269700Smsmith if ((buf[0] == '\t') && (sscanf(buf + 1, "%04x\t%[^\n]", &id, str) == 2)) { 39369700Smsmith if ((id == 0) || (strlen(str) < 1)) 39469700Smsmith continue; 39569700Smsmith if (cv == NULL) { 39669700Smsmith warnx("device entry with no vendor!"); 39769700Smsmith continue; 39869700Smsmith } 39969700Smsmith if ((cd = malloc(sizeof(struct pci_device_info))) == NULL) { 40069700Smsmith warn("allocating device entry"); 40169700Smsmith error = 1; 40269700Smsmith break; 40369700Smsmith } 40469700Smsmith if ((cd->desc = strdup(str)) == NULL) { 40569700Smsmith free(cd); 40669700Smsmith warn("allocating device description"); 40769700Smsmith error = 1; 40869700Smsmith break; 40969700Smsmith } 41069700Smsmith cd->id = id; 41169700Smsmith TAILQ_INSERT_TAIL(&cv->devs, cd, link); 41269700Smsmith continue; 41369700Smsmith } 41469700Smsmith 41569700Smsmith /* It's a comment or junk, ignore it */ 41668677Smsmith } 41769700Smsmith if (ferror(db)) 41869700Smsmith error = 1; 41969700Smsmith fclose(db); 42069700Smsmith 42169700Smsmith return(error); 42268677Smsmith} 42368677Smsmith 42469700Smsmith 42519102Ssestatic struct pcisel 42619102Ssegetsel(const char *str) 42719102Sse{ 428116640Sjmg char *ep = strchr(str, '@'); 429116640Sjmg char *epbase; 43019102Sse struct pcisel sel; 431116640Sjmg 432116640Sjmg if (ep == NULL) 433116640Sjmg ep = (char *)str; 434116640Sjmg else 435116640Sjmg ep++; 436116640Sjmg 437116640Sjmg epbase = ep; 438116640Sjmg 43919102Sse if (strncmp(ep, "pci", 3) == 0) { 44019102Sse ep += 3; 44119102Sse sel.pc_bus = strtoul(ep, &ep, 0); 44219102Sse if (!ep || *ep++ != ':') 44319102Sse errx(1, "cannot parse selector %s", str); 44419102Sse sel.pc_dev = strtoul(ep, &ep, 0); 44519102Sse if (!ep || *ep != ':') { 44619102Sse sel.pc_func = 0; 44719102Sse } else { 44819102Sse ep++; 44919102Sse sel.pc_func = strtoul(ep, &ep, 0); 45019102Sse } 451116640Sjmg if (*ep == ':') 452116640Sjmg ep++; 45319102Sse } 454116640Sjmg if (*ep != '\x0' || ep == epbase) 45519102Sse errx(1, "cannot parse selector %s", str); 45619102Sse return sel; 45719102Sse} 45819102Sse 45919102Ssestatic void 46077533Simpreadone(int fd, struct pcisel *sel, long reg, int width) 46119102Sse{ 46219102Sse struct pci_io pi; 46319102Sse 46477533Simp pi.pi_sel = *sel; 46577533Simp pi.pi_reg = reg; 46619102Sse pi.pi_width = width; 46719102Sse 46877533Simp if (ioctl(fd, PCIOCREAD, &pi) < 0) 46977533Simp err(1, "ioctl(PCIOCREAD)"); 47077533Simp 47191299Ssos printf("%0*x", width*2, pi.pi_data); 47277533Simp} 47377533Simp 47477533Simpstatic void 47577533Simpreadit(const char *name, const char *reg, int width) 47677533Simp{ 47777533Simp long rstart; 47877533Simp long rend; 47977533Simp long r; 48077533Simp char *end; 48177533Simp int i; 48277533Simp int fd; 48377533Simp struct pcisel sel; 48477533Simp 48519102Sse fd = open(_PATH_DEVPCI, O_RDWR, 0); 48619102Sse if (fd < 0) 48719102Sse err(1, "%s", _PATH_DEVPCI); 48819102Sse 48977533Simp rend = rstart = strtol(reg, &end, 0); 49077533Simp if (end && *end == ':') { 49177533Simp end++; 49277533Simp rend = strtol(end, (char **) 0, 0); 49377533Simp } 49477533Simp sel = getsel(name); 49577533Simp for (i = 1, r = rstart; r <= rend; i++, r += width) { 49677533Simp readone(fd, &sel, r, width); 49791299Ssos if (i && !(i % 8)) putchar(' '); 49891299Ssos putchar(i % (16/width) ? ' ' : '\n'); 49977533Simp } 50091299Ssos if (i % (16/width) != 1) 50177533Simp putchar('\n'); 50277533Simp close(fd); 50319102Sse} 50419102Sse 50519102Ssestatic void 50619102Ssewriteit(const char *name, const char *reg, const char *data, int width) 50719102Sse{ 50819102Sse int fd; 50919102Sse struct pci_io pi; 51019102Sse 51119102Sse pi.pi_sel = getsel(name); 51219102Sse pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */ 51319102Sse pi.pi_width = width; 51419102Sse pi.pi_data = strtoul(data, (char **)0, 0); /* XXX error check */ 51519102Sse 51619102Sse fd = open(_PATH_DEVPCI, O_RDWR, 0); 51719102Sse if (fd < 0) 51819102Sse err(1, "%s", _PATH_DEVPCI); 51919102Sse 52019102Sse if (ioctl(fd, PCIOCWRITE, &pi) < 0) 52119102Sse err(1, "ioctl(PCIOCWRITE)"); 52219102Sse} 52321935Sse 52421935Ssestatic void 52521935Ssechkattached (const char *name, int width) 52621935Sse{ 52721935Sse int fd; 52821935Sse struct pci_io pi; 52921935Sse 53021935Sse pi.pi_sel = getsel(name); 53121935Sse pi.pi_reg = 0; 53221935Sse pi.pi_width = width; 53321935Sse pi.pi_data = 0; 53421935Sse 53521935Sse fd = open(_PATH_DEVPCI, O_RDWR, 0); 53621935Sse if (fd < 0) 53721935Sse err(1, "%s", _PATH_DEVPCI); 53821935Sse 53921935Sse if (ioctl(fd, PCIOCATTACHED, &pi) < 0) 54021935Sse err(1, "ioctl(PCIOCATTACHED)"); 54121935Sse 54221935Sse exitstatus = pi.pi_data ? 0 : 2; /* exit(2), if NOT attached */ 54321935Sse printf("%s: %s%s\n", name, pi.pi_data == 0 ? "not " : "", "attached"); 54421935Sse} 545