pciconf.c revision 69785
1100616Smp/* 259243Sobrien * Copyright 1996 Massachusetts Institute of Technology 359243Sobrien * 459243Sobrien * Permission to use, copy, modify, and distribute this software and 559243Sobrien * its documentation for any purpose and without fee is hereby 659243Sobrien * granted, provided that both the above copyright notice and this 759243Sobrien * permission notice appear in all copies, that both the above 859243Sobrien * copyright notice and this permission notice appear in all 959243Sobrien * supporting documentation, and that the name of M.I.T. not be used 1059243Sobrien * in advertising or publicity pertaining to distribution of the 1159243Sobrien * software without specific, written prior permission. M.I.T. makes 1259243Sobrien * no representations about the suitability of this software for any 1359243Sobrien * purpose. It is provided "as is" without express or implied 1459243Sobrien * warranty. 1559243Sobrien * 1659243Sobrien * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 17100616Smp * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 1859243Sobrien * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1959243Sobrien * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 2059243Sobrien * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2159243Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2259243Sobrien * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2359243Sobrien * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2459243Sobrien * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2559243Sobrien * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2659243Sobrien * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2759243Sobrien * SUCH DAMAGE. 2859243Sobrien */ 2959243Sobrien 3059243Sobrien#ifndef lint 3159243Sobrienstatic const char rcsid[] = 3259243Sobrien "$FreeBSD: head/usr.sbin/pciconf/pciconf.c 69785 2000-12-09 00:07:46Z msmith $"; 3359243Sobrien#endif /* not lint */ 3459243Sobrien 35100616Smp#include <sys/types.h> 3659243Sobrien#include <sys/fcntl.h> 3759243Sobrien 3859243Sobrien#include <err.h> 3959243Sobrien#include <stdlib.h> 4069408Sache#include <stdio.h> 4159243Sobrien#include <string.h> 4269408Sache#include <unistd.h> 4359243Sobrien#include <sys/pciio.h> 4459243Sobrien#include <sys/queue.h> 4559243Sobrien 4659243Sobrien#include <dev/pci/pcireg.h> 4759243Sobrien 4859243Sobrien#include "pathnames.h" 4959243Sobrien 5059243Sobrienstruct pci_device_info 5159243Sobrien{ 5259243Sobrien TAILQ_ENTRY(pci_device_info) link; 5359243Sobrien int id; 5459243Sobrien char *desc; 5559243Sobrien}; 5659243Sobrien 5759243Sobrienstruct pci_vendor_info 5859243Sobrien{ 5959243Sobrien TAILQ_ENTRY(pci_vendor_info) link; 6059243Sobrien TAILQ_HEAD(,pci_device_info) devs; 6159243Sobrien int id; 6259243Sobrien char *desc; 6359243Sobrien}; 6459243Sobrien 6559243SobrienTAILQ_HEAD(,pci_vendor_info) pci_vendors; 6659243Sobrien 6759243Sobrienstatic void list_devs(int vendors); 6859243Sobrienstatic void list_verbose(struct pci_conf *p); 6959243Sobrienstatic char *guess_class(struct pci_conf *p); 7059243Sobrienstatic char *guess_subclass(struct pci_conf *p); 7159243Sobrienstatic int load_vendors(void); 7259243Sobrienstatic void readit(const char *, const char *, int); 7359243Sobrienstatic void writeit(const char *, const char *, const char *, int); 7459243Sobrienstatic void chkattached(const char *, int); 7559243Sobrien 7659243Sobrienstatic int exitstatus = 0; 7759243Sobrien 7859243Sobrienstatic void 7959243Sobrienusage() 8059243Sobrien{ 8159243Sobrien fprintf(stderr, "%s\n%s\n%s\n%s\n", 8259243Sobrien "usage: pciconf -l [-v]", 8359243Sobrien " pciconf -a sel", 8459243Sobrien " pciconf -r [-b | -h] sel addr", 8559243Sobrien " pciconf -w [-b | -h] sel addr [value]"); 8659243Sobrien exit (1); 8759243Sobrien} 8859243Sobrien 8959243Sobrienint 9059243Sobrienmain(int argc, char **argv) 9159243Sobrien{ 9259243Sobrien int c; 9359243Sobrien int listmode, readmode, writemode, attachedmode, verbose; 9459243Sobrien int byte, isshort; 9559243Sobrien 9659243Sobrien listmode = readmode = writemode = attachedmode = verbose = byte = isshort = 0; 9759243Sobrien 9859243Sobrien while ((c = getopt(argc, argv, "alrwbhv")) != -1) { 9959243Sobrien switch(c) { 10059243Sobrien case 'a': 10159243Sobrien attachedmode = 1; 10259243Sobrien break; 10359243Sobrien 10459243Sobrien case 'l': 10559243Sobrien listmode = 1; 10659243Sobrien break; 10759243Sobrien 10859243Sobrien case 'r': 10959243Sobrien readmode = 1; 11059243Sobrien break; 11159243Sobrien 11259243Sobrien case 'w': 11359243Sobrien writemode = 1; 11459243Sobrien break; 11559243Sobrien 11659243Sobrien case 'b': 11759243Sobrien byte = 1; 11859243Sobrien break; 11959243Sobrien 12059243Sobrien case 'h': 12159243Sobrien isshort = 1; 12259243Sobrien break; 12359243Sobrien 12459243Sobrien case 'v': 12569408Sache verbose = 1; 12659243Sobrien break; 12769408Sache 12859243Sobrien default: 12959243Sobrien usage(); 13059243Sobrien } 13159243Sobrien } 13259243Sobrien 13359243Sobrien if ((listmode && optind != argc) 13459243Sobrien || (writemode && optind + 3 != argc) 13559243Sobrien || (readmode && optind + 2 != argc) 13659243Sobrien || (attachedmode && optind + 1 != argc)) 13759243Sobrien usage(); 13859243Sobrien 13959243Sobrien if (listmode) { 14059243Sobrien list_devs(verbose); 14159243Sobrien } else if(attachedmode) { 14259243Sobrien chkattached(argv[optind], 14359243Sobrien byte ? 1 : isshort ? 2 : 4); 14459243Sobrien } else if(readmode) { 14559243Sobrien readit(argv[optind], argv[optind + 1], 14659243Sobrien byte ? 1 : isshort ? 2 : 4); 14759243Sobrien } else if(writemode) { 14859243Sobrien writeit(argv[optind], argv[optind + 1], argv[optind + 2], 14959243Sobrien byte ? 1 : isshort ? 2 : 4); 15059243Sobrien } else { 15159243Sobrien usage(); 15259243Sobrien } 15359243Sobrien 15459243Sobrien return exitstatus; 15559243Sobrien} 15659243Sobrien 15759243Sobrienstatic void 15859243Sobrienlist_devs(int verbose) 15959243Sobrien{ 16059243Sobrien int fd; 16159243Sobrien struct pci_conf_io pc; 16259243Sobrien struct pci_conf conf[255], *p; 16359243Sobrien int none_count = 0; 16459243Sobrien 16559243Sobrien if (verbose) 16659243Sobrien load_vendors(); 16759243Sobrien 16859243Sobrien fd = open(_PATH_DEVPCI, O_RDWR, 0); 16959243Sobrien if (fd < 0) 17059243Sobrien err(1, "%s", _PATH_DEVPCI); 17159243Sobrien 17259243Sobrien bzero(&pc, sizeof(struct pci_conf_io)); 17359243Sobrien pc.match_buf_len = sizeof(conf); 17459243Sobrien pc.matches = conf; 17559243Sobrien 17659243Sobrien do { 17759243Sobrien if (ioctl(fd, PCIOCGETCONF, &pc) == -1) 17859243Sobrien err(1, "ioctl(PCIOCGETCONF)"); 17959243Sobrien 18059243Sobrien /* 18159243Sobrien * 255 entries should be more than enough for most people, 18259243Sobrien * but if someone has more devices, and then changes things 18359243Sobrien * around between ioctls, we'll do the cheezy thing and 18459243Sobrien * just bail. The alternative would be to go back to the 18559243Sobrien * beginning of the list, and print things twice, which may 18659243Sobrien * not be desireable. 18759243Sobrien */ 18859243Sobrien if (pc.status == PCI_GETCONF_LIST_CHANGED) { 18959243Sobrien warnx("PCI device list changed, please try again"); 19059243Sobrien exitstatus = 1; 19159243Sobrien close(fd); 19259243Sobrien return; 19359243Sobrien } else if (pc.status == PCI_GETCONF_ERROR) { 19459243Sobrien warnx("error returned from PCIOCGETCONF ioctl"); 19559243Sobrien exitstatus = 1; 19659243Sobrien close(fd); 19759243Sobrien return; 19859243Sobrien } 19959243Sobrien for (p = conf; p < &conf[pc.num_matches]; p++) { 20059243Sobrien 20159243Sobrien printf("%s%d@pci%d:%d:%d:\tclass=0x%06x card=0x%08x " 20259243Sobrien "chip=0x%08x rev=0x%02x hdr=0x%02x\n", 20359243Sobrien (p->pd_name && *p->pd_name) ? p->pd_name : 20459243Sobrien "none", 20559243Sobrien (p->pd_name && *p->pd_name) ? (int)p->pd_unit : 20659243Sobrien none_count++, 20759243Sobrien p->pc_sel.pc_bus, p->pc_sel.pc_dev, 20859243Sobrien p->pc_sel.pc_func, (p->pc_class << 16) | 20959243Sobrien (p->pc_subclass << 8) | p->pc_progif, 21059243Sobrien (p->pc_subdevice << 16) | p->pc_subvendor, 21159243Sobrien (p->pc_device << 16) | p->pc_vendor, 21259243Sobrien p->pc_revid, p->pc_hdr); 21359243Sobrien if (verbose) 21459243Sobrien list_verbose(p); 21559243Sobrien } 21659243Sobrien } while (pc.status == PCI_GETCONF_MORE_DEVS); 21759243Sobrien 21859243Sobrien close(fd); 21959243Sobrien} 22059243Sobrien 22159243Sobrienstatic void 22259243Sobrienlist_verbose(struct pci_conf *p) 22359243Sobrien{ 22459243Sobrien struct pci_vendor_info *vi; 22559243Sobrien struct pci_device_info *di; 22659243Sobrien char *dp; 22759243Sobrien 22859243Sobrien TAILQ_FOREACH(vi, &pci_vendors, link) { 22959243Sobrien if (vi->id == p->pc_vendor) { 23059243Sobrien printf(" vendor = '%s'\n", vi->desc); 23159243Sobrien break; 23259243Sobrien } 23359243Sobrien } 23459243Sobrien if (vi == NULL) { 23559243Sobrien di = NULL; 23659243Sobrien } else { 23759243Sobrien TAILQ_FOREACH(di, &vi->devs, link) { 23859243Sobrien if (di->id == p->pc_device) { 23959243Sobrien printf(" device = '%s'\n", di->desc); 24059243Sobrien break; 24159243Sobrien } 24259243Sobrien } 24359243Sobrien } 24459243Sobrien if ((dp = guess_class(p)) != NULL) 24559243Sobrien printf(" class = %s\n", dp); 24659243Sobrien if ((dp = guess_subclass(p)) != NULL) 24759243Sobrien printf(" subclass = %s\n", dp); 24859243Sobrien} 24959243Sobrien 25059243Sobrien/* 25159243Sobrien * This is a direct cut-and-paste from the table in sys/dev/pci/pci.c. 25259243Sobrien */ 25359243Sobrienstatic struct 25459243Sobrien{ 25559243Sobrien int class; 25659243Sobrien int subclass; 25759243Sobrien char *desc; 25859243Sobrien} pci_nomatch_tab[] = { 25959243Sobrien {PCIC_OLD, -1, "old"}, 26059243Sobrien {PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"}, 26159243Sobrien {PCIC_OLD, PCIS_OLD_VGA, "VGA-compatible display device"}, 26259243Sobrien {PCIC_STORAGE, -1, "mass storage"}, 26359243Sobrien {PCIC_STORAGE, PCIS_STORAGE_SCSI, "SCSI"}, 26459243Sobrien {PCIC_STORAGE, PCIS_STORAGE_IDE, "ATA"}, 26559243Sobrien {PCIC_STORAGE, PCIS_STORAGE_FLOPPY, "floppy disk"}, 26659243Sobrien {PCIC_STORAGE, PCIS_STORAGE_IPI, "IPI"}, 26759243Sobrien {PCIC_STORAGE, PCIS_STORAGE_RAID, "RAID"}, 26859243Sobrien {PCIC_NETWORK, -1, "network"}, 26959243Sobrien {PCIC_NETWORK, PCIS_NETWORK_ETHERNET, "ethernet"}, 27059243Sobrien {PCIC_NETWORK, PCIS_NETWORK_TOKENRING, "token ring"}, 27159243Sobrien {PCIC_NETWORK, PCIS_NETWORK_FDDI, "fddi"}, 27259243Sobrien {PCIC_NETWORK, PCIS_NETWORK_ATM, "ATM"}, 27359243Sobrien {PCIC_DISPLAY, -1, "display"}, 27459243Sobrien {PCIC_DISPLAY, PCIS_DISPLAY_VGA, "VGA"}, 27559243Sobrien {PCIC_DISPLAY, PCIS_DISPLAY_XGA, "XGA"}, 27659243Sobrien {PCIC_MULTIMEDIA, -1, "multimedia"}, 27759243Sobrien {PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_VIDEO, "video"}, 27859243Sobrien {PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_AUDIO, "audio"}, 27959243Sobrien {PCIC_MEMORY, -1, "memory"}, 28059243Sobrien {PCIC_MEMORY, PCIS_MEMORY_RAM, "RAM"}, 28159243Sobrien {PCIC_MEMORY, PCIS_MEMORY_FLASH, "flash"}, 28259243Sobrien {PCIC_BRIDGE, -1, "bridge"}, 28359243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_HOST, "HOST-PCI"}, 28459243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_ISA, "PCI-ISA"}, 28559243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_EISA, "PCI-EISA"}, 28659243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_MCA, "PCI-MCA"}, 28759243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_PCI, "PCI-PCI"}, 28859243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_PCMCIA, "PCI-PCMCIA"}, 28959243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_NUBUS, "PCI-NuBus"}, 29059243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_CARDBUS, "PCI-CardBus"}, 29159243Sobrien {PCIC_BRIDGE, PCIS_BRIDGE_OTHER, "PCI-unknown"}, 29259243Sobrien {PCIC_SIMPLECOMM, -1, "simple comms"}, 29359243Sobrien {PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_UART, "UART"}, /* could detect 16550 */ 29459243Sobrien {PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_PAR, "parallel port"}, 29559243Sobrien {PCIC_BASEPERIPH, -1, "base peripheral"}, 29659243Sobrien {PCIC_BASEPERIPH, PCIS_BASEPERIPH_PIC, "interrupt controller"}, 29759243Sobrien {PCIC_BASEPERIPH, PCIS_BASEPERIPH_DMA, "DMA controller"}, 29859243Sobrien {PCIC_BASEPERIPH, PCIS_BASEPERIPH_TIMER, "timer"}, 29959243Sobrien {PCIC_BASEPERIPH, PCIS_BASEPERIPH_RTC, "realtime clock"}, 30059243Sobrien {PCIC_INPUTDEV, -1, "input device"}, 30159243Sobrien {PCIC_INPUTDEV, PCIS_INPUTDEV_KEYBOARD, "keyboard"}, 30259243Sobrien {PCIC_INPUTDEV, PCIS_INPUTDEV_DIGITIZER,"digitizer"}, 303100616Smp {PCIC_INPUTDEV, PCIS_INPUTDEV_MOUSE, "mouse"}, 30459243Sobrien {PCIC_DOCKING, -1, "docking station"}, 30559243Sobrien {PCIC_PROCESSOR, -1, "processor"}, 30659243Sobrien {PCIC_SERIALBUS, -1, "serial bus"}, 30759243Sobrien {PCIC_SERIALBUS, PCIS_SERIALBUS_FW, "FireWire"}, 30859243Sobrien {PCIC_SERIALBUS, PCIS_SERIALBUS_ACCESS, "AccessBus"}, 30959243Sobrien {PCIC_SERIALBUS, PCIS_SERIALBUS_SSA, "SSA"}, 31059243Sobrien {PCIC_SERIALBUS, PCIS_SERIALBUS_USB, "USB"}, 31159243Sobrien {PCIC_SERIALBUS, PCIS_SERIALBUS_FC, "Fibre Channel"}, 31259243Sobrien {PCIC_SERIALBUS, PCIS_SERIALBUS_SMBUS, "SMBus"}, 31359243Sobrien {0, 0, NULL} 31459243Sobrien}; 31559243Sobrien 31659243Sobrienstatic char * 31759243Sobrienguess_class(struct pci_conf *p) 31859243Sobrien{ 31959243Sobrien int i; 32059243Sobrien 32159243Sobrien for (i = 0; pci_nomatch_tab[i].desc != NULL; i++) { 32259243Sobrien if (pci_nomatch_tab[i].class == p->pc_class) 32359243Sobrien return(pci_nomatch_tab[i].desc); 32459243Sobrien } 32559243Sobrien return(NULL); 32659243Sobrien} 32759243Sobrien 32859243Sobrienstatic char * 32959243Sobrienguess_subclass(struct pci_conf *p) 33059243Sobrien{ 33159243Sobrien int i; 33259243Sobrien 33359243Sobrien for (i = 0; pci_nomatch_tab[i].desc != NULL; i++) { 33459243Sobrien if ((pci_nomatch_tab[i].class == p->pc_class) && 33559243Sobrien (pci_nomatch_tab[i].subclass == p->pc_subclass)) 33659243Sobrien return(pci_nomatch_tab[i].desc); 33759243Sobrien } 33859243Sobrien return(NULL); 33959243Sobrien} 34059243Sobrien 34159243Sobrienstatic int 34259243Sobrienload_vendors(void) 34359243Sobrien{ 34459243Sobrien char *dbf; 34559243Sobrien FILE *db; 34669408Sache struct pci_vendor_info *cv; 34759243Sobrien struct pci_device_info *cd; 34869408Sache char buf[100], str[100]; 34959243Sobrien int id, error; 35059243Sobrien 35159243Sobrien /* 35259243Sobrien * Locate the database and initialise. 35359243Sobrien */ 35459243Sobrien TAILQ_INIT(&pci_vendors); 35559243Sobrien if ((dbf = getenv("PCICONF_VENDOR_DATABASE")) == NULL) 35669408Sache dbf = _PATH_PCIVDB; 35759243Sobrien if ((db = fopen(dbf, "r")) == NULL) 35859243Sobrien return(1); 35959243Sobrien cv = NULL; 36059243Sobrien cd = NULL; 36159243Sobrien error = 0; 36259243Sobrien 36359243Sobrien /* 36459243Sobrien * Scan input lines from the database 36559243Sobrien */ 36659243Sobrien for (;;) { 36759243Sobrien if (fgets(buf, sizeof(buf), db) == NULL) 36859243Sobrien break; 36959243Sobrien 37059243Sobrien /* Check for vendor entry */ 37159243Sobrien if ((buf[0] != '\t') && (sscanf(buf, "%04x\t%[^\n]", &id, str) == 2)) { 37259243Sobrien if ((id == 0) || (strlen(str) < 1)) 37359243Sobrien continue; 37459243Sobrien if ((cv = malloc(sizeof(struct pci_vendor_info))) == NULL) { 37559243Sobrien warn("allocating vendor entry"); 37659243Sobrien error = 1; 37759243Sobrien break; 37859243Sobrien } 37959243Sobrien if ((cv->desc = strdup(str)) == NULL) { 38059243Sobrien free(cv); 38159243Sobrien warn("allocating vendor description"); 38259243Sobrien error = 1; 38359243Sobrien break; 38459243Sobrien } 38559243Sobrien cv->id = id; 38659243Sobrien TAILQ_INIT(&cv->devs); 38759243Sobrien TAILQ_INSERT_TAIL(&pci_vendors, cv, link); 38859243Sobrien continue; 38959243Sobrien } 39059243Sobrien 39159243Sobrien /* Check for device entry */ 39259243Sobrien if ((buf[0] == '\t') && (sscanf(buf + 1, "%04x\t%[^\n]", &id, str) == 2)) { 39359243Sobrien if ((id == 0) || (strlen(str) < 1)) 39459243Sobrien continue; 39559243Sobrien if (cv == NULL) { 39659243Sobrien warnx("device entry with no vendor!"); 39759243Sobrien continue; 39859243Sobrien } 39959243Sobrien if ((cd = malloc(sizeof(struct pci_device_info))) == NULL) { 40059243Sobrien warn("allocating device entry"); 40159243Sobrien error = 1; 40259243Sobrien break; 40359243Sobrien } 40459243Sobrien if ((cd->desc = strdup(str)) == NULL) { 40559243Sobrien free(cd); 40659243Sobrien warn("allocating device description"); 40759243Sobrien error = 1; 40859243Sobrien break; 40959243Sobrien } 41059243Sobrien cd->id = id; 41159243Sobrien TAILQ_INSERT_TAIL(&cv->devs, cd, link); 41259243Sobrien continue; 41359243Sobrien } 41459243Sobrien 41559243Sobrien /* It's a comment or junk, ignore it */ 41659243Sobrien } 41759243Sobrien if (ferror(db)) 41859243Sobrien error = 1; 41959243Sobrien fclose(db); 42059243Sobrien 42159243Sobrien return(error); 42259243Sobrien} 42359243Sobrien 42459243Sobrien 42559243Sobrienstatic struct pcisel 42659243Sobriengetsel(const char *str) 42759243Sobrien{ 42859243Sobrien char *ep = (char*) str; 42959243Sobrien struct pcisel sel; 43059243Sobrien 43159243Sobrien if (strncmp(ep, "pci", 3) == 0) { 43259243Sobrien ep += 3; 43359243Sobrien sel.pc_bus = strtoul(ep, &ep, 0); 43459243Sobrien if (!ep || *ep++ != ':') 43559243Sobrien errx(1, "cannot parse selector %s", str); 43659243Sobrien sel.pc_dev = strtoul(ep, &ep, 0); 43759243Sobrien if (!ep || *ep != ':') { 43859243Sobrien sel.pc_func = 0; 43959243Sobrien } else { 44059243Sobrien ep++; 44159243Sobrien sel.pc_func = strtoul(ep, &ep, 0); 44259243Sobrien } 44359243Sobrien } 44459243Sobrien if (*ep == ':') 445100616Smp ep++; 44659243Sobrien if (*ep || ep == str) 44759243Sobrien errx(1, "cannot parse selector %s", str); 44859243Sobrien return sel; 44959243Sobrien} 45059243Sobrien 45159243Sobrienstatic void 45259243Sobrienreadit(const char *name, const char *reg, int width) 45359243Sobrien{ 45459243Sobrien int fd; 45559243Sobrien struct pci_io pi; 45659243Sobrien 45759243Sobrien pi.pi_sel = getsel(name); 45859243Sobrien pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */ 45959243Sobrien pi.pi_width = width; 46059243Sobrien 46159243Sobrien fd = open(_PATH_DEVPCI, O_RDWR, 0); 46259243Sobrien if (fd < 0) 46359243Sobrien err(1, "%s", _PATH_DEVPCI); 46459243Sobrien 46559243Sobrien if (ioctl(fd, PCIOCREAD, &pi) < 0) 46659243Sobrien err(1, "ioctl(PCIOCREAD)"); 46759243Sobrien 46859243Sobrien printf("0x%08x\n", pi.pi_data); 46959243Sobrien} 47059243Sobrien 47159243Sobrienstatic void 47259243Sobrienwriteit(const char *name, const char *reg, const char *data, int width) 47359243Sobrien{ 47459243Sobrien int fd; 47559243Sobrien struct pci_io pi; 47659243Sobrien 47759243Sobrien pi.pi_sel = getsel(name); 47859243Sobrien pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */ 47959243Sobrien pi.pi_width = width; 48059243Sobrien pi.pi_data = strtoul(data, (char **)0, 0); /* XXX error check */ 48159243Sobrien 48259243Sobrien fd = open(_PATH_DEVPCI, O_RDWR, 0); 48369408Sache if (fd < 0) 48459243Sobrien err(1, "%s", _PATH_DEVPCI); 48559243Sobrien 48659243Sobrien if (ioctl(fd, PCIOCWRITE, &pi) < 0) 48759243Sobrien err(1, "ioctl(PCIOCWRITE)"); 48859243Sobrien} 48959243Sobrien 49059243Sobrienstatic void 49159243Sobrienchkattached (const char *name, int width) 49259243Sobrien{ 49359243Sobrien int fd; 49459243Sobrien struct pci_io pi; 49559243Sobrien 49659243Sobrien pi.pi_sel = getsel(name); 49759243Sobrien pi.pi_reg = 0; 49859243Sobrien pi.pi_width = width; 49959243Sobrien pi.pi_data = 0; 50059243Sobrien 50159243Sobrien fd = open(_PATH_DEVPCI, O_RDWR, 0); 50259243Sobrien if (fd < 0) 50359243Sobrien err(1, "%s", _PATH_DEVPCI); 50459243Sobrien 50559243Sobrien if (ioctl(fd, PCIOCATTACHED, &pi) < 0) 50659243Sobrien err(1, "ioctl(PCIOCATTACHED)"); 50759243Sobrien 50859243Sobrien exitstatus = pi.pi_data ? 0 : 2; /* exit(2), if NOT attached */ 50959243Sobrien printf("%s: %s%s\n", name, pi.pi_data == 0 ? "not " : "", "attached"); 51059243Sobrien} 51159243Sobrien