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 9 * supporting documentation, and that the name of M.I.T. not be used 10 * in advertising or publicity pertaining to distribution of the 11 * software without specific, written prior permission. M.I.T. makes 12 * no representations about the suitability of this software for any 13 * purpose. It is provided "as is" without express or implied 14 * warranty. 15 * 16 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 17 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 20 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 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 * $ANA: pciconf.c,v 1.1.1.1 1996/09/25 21:12:57 wollman Exp $ 30 */ 31 32 #include <sys/types.h> 33 #include <sys/fcntl.h> 34 35 #include <err.h> 36 #include <stdlib.h> 37 #include <stdio.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include <pci/pcivar.h> 42 #include <pci/pci_ioctl.h> 43 44 #include "pathnames.h" 45 46 static void list_devs(void); 47 static void readit(const char *, const char *, int); 48 static void writeit(const char *, const char *, const char *, int); 49 static void chkattached(const char *, int); 50 51 static exitstatus = 0; 52 53 static void 54 usage(const char *argv0) { 55 fprintf(stderr, "usage:\n\t%s -l\n" 56 "\t%s -a sel\n" 57 "\t%s [-r|-w] [-bh] sel addr [value]\n", 58 argv0, argv0, argv0); 59 exit (1); 60 } 61 62 int 63 main(int argc, char **argv) 64 { 65 int c; 66 int listmode, readmode, writemode, attachedmode; 67 int byte, isshort; 68 69 listmode = readmode = writemode = attachedmode = byte = isshort = 0; 70 71 while ((c = getopt(argc, argv, "alrwbh")) != -1) { 72 switch(c) { 73 case 'a': 74 attachedmode = 1; 75 break; 76 77 case 'l': 78 listmode = 1; 79 break; 80 81 case 'r': 82 readmode = 1; 83 break; 84 85 case 'w': 86 writemode = 1; 87 break; 88 89 case 'b': 90 byte = 1; 91 break; 92 93 case 'h': 94 isshort = 1; 95 break; 96 97 default: 98 usage(argv[0]); 99 } 100 } 101 102 if ((listmode && optind != argc) 103 || (writemode && optind + 3 != argc) 104 || (readmode && optind + 2 != argc) 105 || (attachedmode && optind + 1 != argc)) 106 usage(argv[0]); 107 108 if (listmode) { 109 list_devs(); 110 } else if(attachedmode) { 111 chkattached(argv[optind], 112 byte ? 1 : isshort ? 2 : 4); 113 } else if(readmode) { 114 readit(argv[optind], argv[optind + 1], 115 byte ? 1 : isshort ? 2 : 4); 116 } else if(writemode) { 117 writeit(argv[optind], argv[optind + 1], argv[optind + 2], 118 byte ? 1 : isshort ? 2 : 4); 119 } else { 120 usage(argv[0]); 121 } 122 123 return exitstatus; 124 } 125 126 static void 127 list_devs(void) 128 { 129 int fd; 130 struct pci_conf_io pc; 131 struct pci_conf conf[255], *p; 132 133 fd = open(_PATH_DEVPCI, O_RDONLY, 0); 134 if (fd < 0) 135 err(1, "%s", _PATH_DEVPCI); 136 137 pc.pci_len = sizeof(conf); 138 pc.pci_buf = conf; 139 140 if (ioctl(fd, PCIOCGETCONF, &pc) < 0) 141 err(1, "ioctl(PCIOCGETCONF)"); 142 143 close(fd); 144 145 for (p = conf; p < &conf[pc.pci_len / sizeof conf[0]]; p++) { 146 printf("pci%d:%d:%d:\tclass=0x%06x card=0x%08lx chip=0x%08lx rev=0x%02x hdr=0x%02x\n", 147 p->pc_sel.pc_bus, p->pc_sel.pc_dev, p->pc_sel.pc_func, 148 p->pc_class >> 8, p->pc_subid, 149 p->pc_devid, p->pc_class & 0xff, p->pc_hdr); 150 } 151 } 152 153 static struct pcisel 154 getsel(const char *str) 155 { 156 char *ep = (char*) str; 157 struct pcisel sel; 158 159 if (strncmp(ep, "pci", 3) == 0) { 160 ep += 3; 161 sel.pc_bus = strtoul(ep, &ep, 0); 162 if (!ep || *ep++ != ':') 163 errx(1, "cannot parse selector %s", str); 164 sel.pc_dev = strtoul(ep, &ep, 0); 165 if (!ep || *ep != ':') { 166 sel.pc_func = 0; 167 } else { 168 ep++; 169 sel.pc_func = strtoul(ep, &ep, 0); 170 } 171 } 172 if (*ep == ':') 173 ep++; 174 if (*ep || ep == str) 175 errx(1, "cannot parse selector %s", str); 176 return sel; 177 } 178 179 static void 180 readit(const char *name, const char *reg, int width) 181 { 182 int fd; 183 struct pci_io pi; 184 185 pi.pi_sel = getsel(name); 186 pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */ 187 pi.pi_width = width; 188 189 fd = open(_PATH_DEVPCI, O_RDWR, 0); 190 if (fd < 0) 191 err(1, "%s", _PATH_DEVPCI); 192 193 if (ioctl(fd, PCIOCREAD, &pi) < 0) 194 err(1, "ioctl(PCIOCREAD)"); 195 196 printf("0x%08x\n", pi.pi_data); 197 } 198 199 static void 200 writeit(const char *name, const char *reg, const char *data, int width) 201 { 202 int fd; 203 struct pci_io pi; 204 205 pi.pi_sel = getsel(name); 206 pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */ 207 pi.pi_width = width; 208 pi.pi_data = strtoul(data, (char **)0, 0); /* XXX error check */ 209 210 fd = open(_PATH_DEVPCI, O_RDWR, 0); 211 if (fd < 0) 212 err(1, "%s", _PATH_DEVPCI); 213 214 if (ioctl(fd, PCIOCWRITE, &pi) < 0) 215 err(1, "ioctl(PCIOCWRITE)"); 216 } 217 218 static void 219 chkattached (const char *name, int width) 220 { 221 int fd; 222 struct pci_io pi; 223 224 pi.pi_sel = getsel(name); 225 pi.pi_reg = 0; 226 pi.pi_width = width; 227 pi.pi_data = 0; 228 229 fd = open(_PATH_DEVPCI, O_RDWR, 0); 230 if (fd < 0) 231 err(1, "%s", _PATH_DEVPCI); 232 233 if (ioctl(fd, PCIOCATTACHED, &pi) < 0) 234 err(1, "ioctl(PCIOCATTACHED)"); 235 236 exitstatus = pi.pi_data ? 0 : 2; /* exit(2), if NOT attached */ 237 printf("%s: %s%s\n", name, pi.pi_data == 0 ? "not " : "", "attached"); 238 } 239