1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* This file is the main module for the pcitool. */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <sys/inttypes.h> 32 #include <signal.h> 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <fcntl.h> 36 #include <strings.h> 37 #include <ctype.h> 38 #include <errno.h> 39 #include <libdevinfo.h> 40 #include <sys/sunddi.h> 41 42 #ifdef __x86 43 #include <sys/apic_ctlr.h> 44 #endif 45 46 #include <sys/pci.h> 47 #include <sys/pci_tools.h> 48 49 #include "pcitool_ui.h" 50 51 /* First 16 longs of device PCI config header. */ 52 typedef union { 53 uint8_t bytes[16 * sizeof (uint32_t)]; 54 uint32_t dwords[16]; 55 } pci_conf_hdr_t; 56 57 /* Used by probe printing functions. */ 58 typedef struct { 59 uint16_t cfg_offset; /* Offset of data within config space. */ 60 uint8_t size; /* Size of desired data field. */ 61 char *abbrev_hdr; /* Abbreviated header for this data. */ 62 char *full_hdr; /* Full header for this data, verbose option. */ 63 } field_type_t; 64 65 /* Used to package many args into one arg for probe di_node walk function. */ 66 typedef struct { 67 pcitool_uiargs_t *input_args_p; 68 char *pathname; 69 di_prom_handle_t di_phdl; 70 } probe_walk_args_t; 71 72 /* 73 * Read config space in native processor endianness. Endian-neutral 74 * processing can then take place. On big endian machines, MSB and LSB 75 * of little endian data end up switched if read as little endian. 76 * They are in correct order if read as big endian. 77 */ 78 #if defined(__sparc) 79 #define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_BIG 80 #elif defined(__x86) 81 #define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_LTL 82 #else 83 #error "ISA is neither __sparc nor __x86" 84 #endif 85 86 /* status error lookup table. */ 87 static struct { 88 pcitool_errno_t value; 89 char *string; 90 } pcitool_stat_str[] = { 91 { PCITOOL_SUCCESS, 92 "No error status returned from driver" }, 93 { PCITOOL_INVALID_CPUID, 94 "CPU is non-existent or not online" }, 95 { PCITOOL_INVALID_INO, 96 "INO is out of range or invalid" }, 97 { PCITOOL_INVALID_MSI, 98 "MSI is out of range or invalid" }, 99 { PCITOOL_PENDING_INTRTIMEOUT, 100 "Timeout waiting for pending interrupts to clear" }, 101 { PCITOOL_REGPROP_NOTWELLFORMED, 102 "Reg property has invalid format" }, 103 { PCITOOL_INVALID_ADDRESS, 104 "Address out of range or invalid" }, 105 { PCITOOL_NOT_ALIGNED, 106 "Improper address alignment for access attempted" }, 107 { PCITOOL_OUT_OF_RANGE, 108 "Argument out of range" }, 109 { PCITOOL_END_OF_RANGE, 110 "End of address range" }, 111 { PCITOOL_ROM_DISABLED, 112 "Device ROM is disabled. Cannot read" }, 113 { PCITOOL_ROM_WRITE, 114 "Write to ROM not allowed" }, 115 { PCITOOL_IO_ERROR, 116 "IO error encountered" }, 117 { PCITOOL_INVALID_SIZE, 118 "Size is invalid for this platform" }, 119 { 0, NULL } 120 }; 121 122 123 /* Used with ^C handler to stop looping in repeat mode in do_device_or_nexus. */ 124 static boolean_t keep_looping = B_TRUE; 125 126 static void signal_handler(int dummy); 127 static char *strstatus(pcitool_errno_t pcitool_status); 128 static int open_node(char *device, pcitool_uiargs_t *input_args_p); 129 static void print_probe_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset, 130 uint8_t size); 131 static void print_probe_info_verbose(pci_conf_hdr_t *config_hdr_p, 132 pcitool_reg_t *info_p); 133 static void print_probe_info_nonverbose(pci_conf_hdr_t *config_hdr_p, 134 pcitool_reg_t *info_p); 135 static void print_probe_info(pci_conf_hdr_t *config_hdr_p, 136 pcitool_reg_t *info_p, boolean_t verbose); 137 static int get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, 138 uint8_t func_no, pci_conf_hdr_t *config_hdr_p); 139 static int probe_dev(int fd, pcitool_reg_t *prg_p, 140 pcitool_uiargs_t *input_args_p); 141 static int do_probe(int fd, di_node_t di_node, di_prom_handle_t di_phdl, 142 pcitool_uiargs_t *input_args_p); 143 static int process_nexus_node(di_node_t node, di_minor_t minor, void *arg); 144 static int do_probe_walk(pcitool_uiargs_t *input_args_p, char *pathname); 145 static void print_bytedump_header(boolean_t do_chardump); 146 static int bytedump_get(int fd, int cmd, pcitool_reg_t *prg_p, 147 pcitool_uiargs_t *input_args_p); 148 static uint32_t set_acc_attr(pcitool_uiargs_t *input_args_p); 149 static int do_single_access(int fd, int cmd, pcitool_reg_t *prg_p, 150 pcitool_uiargs_t *input_args_p); 151 static int do_device_or_nexus(int fd, pcitool_uiargs_t *input_args_p); 152 static void print_intr_info(pcitool_intr_get_t *iget_p); 153 static int get_single_interrupt(int fd, pcitool_intr_get_t **iget_pp, 154 pcitool_uiargs_t *input_args_p); 155 static int get_interrupts(int fd, pcitool_uiargs_t *input_args_p); 156 static int set_interrupts(int fd, pcitool_uiargs_t *input_args_p); 157 static int do_interrupts(int fd, pcitool_uiargs_t *input_args_p); 158 159 160 /* *************** General ************** */ 161 162 /* 163 * Handler for ^C to stop looping. 164 */ 165 /*ARGSUSED*/ 166 static void 167 signal_handler(int dummy) 168 { 169 keep_looping = B_FALSE; 170 } 171 172 173 /* 174 * Print string based on PCItool status returned from driver. 175 */ 176 static char * 177 strstatus(pcitool_errno_t pcitool_status) 178 { 179 int i; 180 181 for (i = 0; pcitool_stat_str[i].string != NULL; i++) { 182 if (pcitool_stat_str[i].value == pcitool_status) { 183 184 return (pcitool_stat_str[i].string); 185 } 186 } 187 188 return ("Unknown status returned from driver."); 189 } 190 191 192 static int 193 open_node(char *device, pcitool_uiargs_t *input_args_p) 194 { 195 int fd; 196 char *path; /* For building full nexus pathname. */ 197 int stringsize; /* Device name size. */ 198 char *prefix; 199 char *suffix; 200 char *format; 201 202 static char slash_devices[] = {"/devices"}; 203 static char wcolon[] = {"%s%s:%s"}; 204 static char wocolon[] = {"%s%s%s"}; 205 206 /* Check for names starting with /devices. */ 207 prefix = (strstr(device, slash_devices) == device) ? "" : slash_devices; 208 209 format = wcolon; 210 if (input_args_p->flags & INTR_FLAG) { 211 if (strstr(device, PCI_MINOR_INTR) == 212 device + (strlen(device) - strlen(PCI_MINOR_INTR))) { 213 suffix = ""; 214 format = wocolon; 215 } else { 216 suffix = PCI_MINOR_INTR; 217 } 218 } else { 219 if (strstr(device, PCI_MINOR_REG) == 220 device + (strlen(device) - strlen(PCI_MINOR_REG))) { 221 suffix = ""; 222 format = wocolon; 223 } else { 224 suffix = PCI_MINOR_REG; 225 } 226 } 227 228 /* 229 * Build nexus pathname. 230 * User specified /pci@1f,700000 becomes /devices/pci@1f,700000:intr 231 * for interrupt nodes, and ...:reg for register nodes. 232 * 233 * ...The 2 at the end leaves room for a : and the terminating NULL. 234 */ 235 stringsize = strlen(prefix) + strlen(device) + strlen(suffix) + 2; 236 path = malloc(stringsize); 237 238 /*LINTED*/ 239 (void) snprintf(path, stringsize, format, prefix, device, suffix); 240 241 /* Open the nexus. */ 242 if ((fd = open(path, O_RDWR)) == -1) { 243 if (!(IS_QUIET(input_args_p->flags))) { 244 (void) fprintf(stderr, 245 "Could not open nexus node %s: %s\n", 246 path, strerror(errno)); 247 } 248 } 249 250 return (fd); 251 } 252 253 254 /* ****************** Probe **************** */ 255 256 /* The following are used by the probe printing functions. */ 257 258 /* Header 0 and 1 config space headers have these fields. */ 259 static field_type_t first_fields[] = { 260 { PCI_CONF_VENID, 2, "Vend", "Vendor ID" }, 261 { PCI_CONF_DEVID, 2, "Dev ", "Device ID" }, 262 { PCI_CONF_COMM, 2, "Cmd ", "Command" }, 263 { PCI_CONF_STAT, 2, "Stat", "Status" }, 264 { PCI_CONF_REVID, 1, "Rv", "Revision ID" }, 265 { PCI_CONF_PROGCLASS, 3, "Class ", "Class Code" }, 266 { PCI_CONF_CACHE_LINESZ, 1, "Ca", "Cache Line Size" }, 267 { PCI_CONF_LATENCY_TIMER, 1, "LT", "Latency Timer" }, 268 { PCI_CONF_HEADER, 1, "Hd", "Header Type" }, 269 { PCI_CONF_BIST, 1, "BI", "BIST" }, 270 { 0, 0, NULL, NULL } 271 }; 272 273 /* Header 0 (for regular devices) have these fields. */ 274 static field_type_t last_dev_fields[] = { 275 { PCI_CONF_BASE0, 4, "BAR0", "Base Address Register 0 (@10)" }, 276 { PCI_CONF_BASE1, 4, "BAR1", "Base Address Register 1 (@14)" }, 277 { PCI_CONF_BASE2, 4, "BAR2", "Base Address Register 2 (@18)" }, 278 { PCI_CONF_BASE3, 4, "BAR3", "Base Address Register 3 (@1C)" }, 279 { PCI_CONF_BASE4, 4, "BAR4", "Base Address Register 4 (@20)" }, 280 { PCI_CONF_BASE5, 4, "BAR5", "Base Address Register 5 (@24)" }, 281 { PCI_CONF_ROM, 4, "ROM", "Expansion ROM Base Address Register (@30)" }, 282 { 0, 0, NULL, NULL } 283 }; 284 285 /* Header 1 (PCI-PCI bridge devices) have these fields. */ 286 static field_type_t last_pcibrg_fields[] = { 287 { PCI_CONF_BASE0, 4, "BAR0", "Base Address Register 0 (@10)" }, 288 { PCI_CONF_BASE1, 4, "BAR1", "Base Address Register 1 (@14)" }, 289 { PCI_BCNF_ROM, 4, "ROM", "Expansion ROM Base Address Register (@38)" }, 290 { 0, 0, NULL, NULL } 291 }; 292 293 /* Header 2 (PCI-Cardbus bridge devices) have these fields. */ 294 static field_type_t last_cbbrg_fields[] = { 295 { PCI_CBUS_SOCK_REG, 4, "SCKT", "Socket/ExCA Base Address (@10)" }, 296 { 0, 0, NULL, NULL } 297 }; 298 299 #define FMT_SIZE 7 300 301 static void 302 print_probe_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset, uint8_t size) 303 { 304 305 char format[FMT_SIZE]; 306 307 308 /* Size cannot be any larger than 4 bytes. This is not checked. */ 309 uint32_t value = 0; 310 311 /* Build format of print, "%<size*2>.<size*2>x" */ 312 (void) snprintf(format, FMT_SIZE, "%%%d.%dx ", size * 2, size * 2); 313 314 while (size-- > 0) { 315 value = (value << 8) + config_hdr_p->bytes[offset + size]; 316 } 317 318 /*LINTED*/ 319 (void) printf(format, value); 320 } 321 322 static void 323 print_probe_info_verbose(pci_conf_hdr_t *config_hdr_p, pcitool_reg_t *info_p) 324 { 325 field_type_t *last_fields = NULL; 326 int i; 327 328 (void) printf("\n" 329 "Bus Number: %x Device Number: %x Function Number: %x\n", 330 info_p->bus_no, info_p->dev_no, info_p->func_no); 331 if (info_p->phys_addr != 0) { 332 (void) printf("Physical Address: 0x%" PRIx64 " \n", 333 info_p->phys_addr); 334 } 335 336 switch (config_hdr_p->bytes[PCI_CONF_HEADER] & PCI_HEADER_TYPE_M) { 337 338 case PCI_HEADER_ZERO: /* Header type 0 is a regular device. */ 339 last_fields = last_dev_fields; 340 break; 341 342 case PCI_HEADER_PPB: /* Header type 1 is a PCI-PCI bridge. */ 343 last_fields = last_pcibrg_fields; 344 (void) printf("PCI-PCI bridge\n"); 345 break; 346 347 case PCI_HEADER_CARDBUS: /* Header type 2 is a cardbus bridge */ 348 last_fields = last_cbbrg_fields; 349 (void) printf("PCI-Cardbus bridge\n"); 350 break; 351 352 default: 353 (void) printf("Unknown device\n"); 354 break; 355 } 356 357 if (last_fields != NULL) { 358 359 for (i = 0; first_fields[i].size != 0; i++) { 360 (void) printf("%s: ", first_fields[i].full_hdr); 361 print_probe_value(config_hdr_p, 362 first_fields[i].cfg_offset, first_fields[i].size); 363 (void) putchar('\n'); 364 } 365 366 for (i = 0; last_fields[i].size != 0; i++) { 367 (void) printf("%s: ", last_fields[i].full_hdr); 368 print_probe_value(config_hdr_p, 369 last_fields[i].cfg_offset, last_fields[i].size); 370 (void) putchar('\n'); 371 } 372 } 373 } 374 375 static void 376 print_probe_info_nonverbose(pci_conf_hdr_t *config_hdr_p, pcitool_reg_t *info_p) 377 { 378 int i; 379 380 (void) printf("%2.2x %2.2x %1.1x ", 381 info_p->bus_no, info_p->dev_no, info_p->func_no); 382 for (i = 0; first_fields[i].size != 0; i++) { 383 print_probe_value(config_hdr_p, 384 first_fields[i].cfg_offset, first_fields[i].size); 385 } 386 (void) putchar('\n'); 387 } 388 389 390 /* 391 * Print device information retrieved during probe mode. 392 * Takes the PCI config header, plus address information retrieved from the 393 * driver. 394 * 395 * When called with config_hdr_p == NULL, this function just prints a header 396 * when not in verbose mode. 397 */ 398 399 static void 400 print_probe_info( 401 pci_conf_hdr_t *config_hdr_p, pcitool_reg_t *info_p, boolean_t verbose) 402 { 403 int i; 404 405 /* Print header if not in verbose mode. */ 406 if (config_hdr_p == NULL) { 407 if (!verbose) { 408 409 /* Bus dev func not from tble */ 410 (void) printf("B D F "); 411 412 for (i = 0; first_fields[i].size != 0; i++) { 413 (void) printf("%s ", 414 first_fields[i].abbrev_hdr); 415 } 416 (void) putchar('\n'); 417 } 418 419 return; 420 } 421 422 if (verbose) { 423 print_probe_info_verbose(config_hdr_p, info_p); 424 } else { 425 print_probe_info_nonverbose(config_hdr_p, info_p); 426 } 427 } 428 429 430 /* 431 * Retrieve first 16 dwords of device's config header, except for the first 432 * dword. First 16 dwords are defined by the PCI specification. 433 */ 434 static int 435 get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, uint8_t func_no, 436 pci_conf_hdr_t *config_hdr_p) 437 { 438 pcitool_reg_t cfg_prg; 439 int i; 440 int rval = SUCCESS; 441 442 /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */ 443 cfg_prg.offset = 0; 444 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; 445 cfg_prg.bus_no = bus_no; 446 cfg_prg.dev_no = dev_no; 447 cfg_prg.func_no = func_no; 448 cfg_prg.barnum = 0; 449 cfg_prg.user_version = PCITOOL_VERSION; 450 451 /* Get dwords 1-15 of config space. They must be read as uint32_t. */ 452 for (i = 1; i < (sizeof (pci_conf_hdr_t) / sizeof (uint32_t)); i++) { 453 cfg_prg.offset += sizeof (uint32_t); 454 if ((rval = 455 ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != SUCCESS) { 456 break; 457 } 458 config_hdr_p->dwords[i] = (uint32_t)cfg_prg.data; 459 } 460 461 return (rval); 462 } 463 464 /* 465 * Identify problematic southbridges. These have device id 0x5249 and 466 * vendor id 0x10b9. Check for revision ID 0 and class code 060400 as well. 467 * Values are little endian, so they are reversed for SPARC. 468 * 469 * Check for these southbridges on all architectures, as the issue is a 470 * southbridge issue, independent of processor. 471 * 472 * If one of these is found during probing, skip probing other devs/funcs on 473 * the rest of the bus, since the southbridge and all devs underneath will 474 * otherwise disappear. 475 */ 476 #if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG) 477 #define U45_SB_DEVID_VID 0xb9104952 478 #define U45_SB_CLASS_RID 0x00000406 479 #else 480 #define U45_SB_DEVID_VID 0x524910b9 481 #define U45_SB_CLASS_RID 0x06040000 482 #endif 483 484 /* 485 * Probe device's functions. Modifies many fields in the prg_p. 486 */ 487 static int 488 probe_dev(int fd, pcitool_reg_t *prg_p, pcitool_uiargs_t *input_args_p) 489 { 490 pci_conf_hdr_t config_hdr; 491 boolean_t multi_function_device; 492 int func; 493 int first_func = 0; 494 int last_func = PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT; 495 int rval = SUCCESS; 496 497 if (input_args_p->flags & FUNC_SPEC_FLAG) { 498 first_func = last_func = input_args_p->function; 499 } 500 501 /* 502 * Loop through at least func=first_func. Continue looping through 503 * functions if there are no errors and the device is a multi-function 504 * device. 505 * 506 * (Note, if first_func == 0, header will show whether multifunction 507 * device and set multi_function_device. If first_func != 0, then we 508 * will force the loop as the user wants a specific function to be 509 * checked. 510 */ 511 for (func = first_func, multi_function_device = B_FALSE; 512 ((func <= last_func) && 513 ((func == first_func) || (multi_function_device))); 514 func++) { 515 prg_p->func_no = func; 516 517 /* 518 * Four things can happen here: 519 * 520 * 1) ioctl comes back as EFAULT and prg_p->status is 521 * PCITOOL_INVALID_ADDRESS. There is no device at this 522 * location. 523 * 524 * 2) ioctl comes back successful and the data comes back as 525 * zero. Config space is mapped but no device responded. 526 * 527 * 3) ioctl comes back successful and the data comes back as 528 * non-zero. We've found a device. 529 * 530 * 4) Some other error occurs in an ioctl. 531 */ 532 533 prg_p->status = PCITOOL_SUCCESS; 534 prg_p->offset = 0; 535 prg_p->data = 0; 536 prg_p->user_version = PCITOOL_VERSION; 537 if (((rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, prg_p)) != 0) || 538 (prg_p->data == 0xffffffff)) { 539 540 /* 541 * Accept errno == EINVAL along with status of 542 * PCITOOL_OUT_OF_RANGE because some systems 543 * don't implement the full range of config space. 544 * Leave the loop quietly in this case. 545 */ 546 if ((errno == EINVAL) || 547 (prg_p->status == PCITOOL_OUT_OF_RANGE)) { 548 break; 549 } 550 551 /* 552 * Exit silently with ENXIO as this means that there are 553 * no devices under the pci root nexus. 554 */ 555 else if ((errno == ENXIO) && 556 (prg_p->status == PCITOOL_IO_ERROR)) { 557 break; 558 } 559 560 /* 561 * Expect errno == EFAULT along with status of 562 * PCITOOL_INVALID_ADDRESS because there won't be 563 * devices at each stop. Quit on any other error. 564 */ 565 else if (((errno != EFAULT) || 566 (prg_p->status != PCITOOL_INVALID_ADDRESS)) && 567 (prg_p->data != 0xffffffff)) { 568 569 if (!(IS_QUIET(input_args_p->flags))) { 570 (void) fprintf(stderr, 571 "Ioctl error: %s\n", 572 strerror(errno)); 573 } 574 break; 575 576 /* 577 * If no function at this location, 578 * just advance to the next function. 579 */ 580 } else { 581 rval = SUCCESS; 582 } 583 584 /* 585 * Data came back as 0. 586 * Treat as unresponsive device amd check next device. 587 */ 588 } else if (prg_p->data == 0) { 589 rval = SUCCESS; 590 break; /* Func loop. */ 591 592 /* Found something. */ 593 } else { 594 config_hdr.dwords[0] = (uint32_t)prg_p->data; 595 596 /* Get the rest of the PCI header. */ 597 if ((rval = get_config_header(fd, prg_p->bus_no, 598 prg_p->dev_no, prg_p->func_no, &config_hdr)) != 599 SUCCESS) { 600 break; 601 } 602 603 /* Print the found information. */ 604 print_probe_info(&config_hdr, prg_p, 605 IS_VERBOSE(input_args_p->flags)); 606 607 /* 608 * Special case for the type of Southbridge found on 609 * Ultra-45 and other sun4u fire workstations. 610 */ 611 if ((config_hdr.dwords[0] == U45_SB_DEVID_VID) && 612 (config_hdr.dwords[2] == U45_SB_CLASS_RID)) { 613 rval = ECANCELED; 614 break; 615 } 616 617 /* 618 * Accomodate devices which state their 619 * multi-functionality only in their function 0 config 620 * space. Note multi-functionality throughout probing 621 * of all of this device's functions. 622 */ 623 if (config_hdr.bytes[PCI_CONF_HEADER] & 624 PCI_HEADER_MULTI) { 625 multi_function_device = B_TRUE; 626 } 627 } 628 } 629 630 return (rval); 631 } 632 633 634 /* 635 * Probe a given nexus config space for devices. 636 * 637 * fd is the file descriptor of the nexus. 638 * input_args contains commandline options as specified by the user. 639 */ 640 static int 641 do_probe(int fd, di_node_t di_node, di_prom_handle_t di_phdl, 642 pcitool_uiargs_t *input_args_p) 643 { 644 pcitool_reg_t prg; 645 int bus; 646 int dev; 647 int last_bus = PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT; 648 int last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT; 649 int first_bus = 0; 650 int first_dev = 0; 651 int rval = SUCCESS; 652 653 prg.barnum = 0; /* Config space. */ 654 655 /* Must read in 4-byte quantities. */ 656 prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; 657 658 prg.data = 0; 659 660 /* If an explicit bus was specified by the user, go with it. */ 661 if (input_args_p->flags & BUS_SPEC_FLAG) { 662 first_bus = last_bus = input_args_p->bus; 663 664 } else if (input_args_p->flags & PROBERNG_FLAG) { 665 /* Otherwise get the bus range from properties. */ 666 int len; 667 uint32_t *rangebuf = NULL; 668 669 len = di_prop_lookup_ints(DDI_DEV_T_ANY, di_node, 670 "bus-range", (int **)&rangebuf); 671 672 /* Try PROM property */ 673 if (len <= 0) { 674 len = di_prom_prop_lookup_ints(di_phdl, di_node, 675 "bus-range", (int **)&rangebuf); 676 } 677 678 /* Take full range for default if cannot get property. */ 679 if (len > 0) { 680 first_bus = rangebuf[0]; 681 last_bus = rangebuf[1]; 682 } 683 } 684 685 /* Take full range for default if not PROBERNG and not BUS_SPEC. */ 686 687 if (last_bus == first_bus) { 688 if (input_args_p->flags & DEV_SPEC_FLAG) { 689 /* Explicit device given. Not probing a whole bus. */ 690 (void) puts(""); 691 } else { 692 (void) printf("*********** Probing bus %x " 693 "***********\n\n", first_bus); 694 } 695 } else { 696 (void) printf("*********** Probing buses %x through %x " 697 "***********\n\n", first_bus, last_bus); 698 } 699 700 /* Print header. */ 701 print_probe_info(NULL, NULL, IS_VERBOSE(input_args_p->flags)); 702 703 /* Device number explicitly specified. */ 704 if (input_args_p->flags & DEV_SPEC_FLAG) { 705 first_dev = last_dev = input_args_p->device; 706 } 707 708 /* 709 * Loop through all valid bus / dev / func combinations to check for 710 * all devices, with the following exceptions: 711 * 712 * When nothing is found at function 0 of a bus / dev combination, skip 713 * the other functions of that bus / dev combination. 714 * 715 * When a found device's function 0 is probed and it is determined that 716 * it is not a multifunction device, skip probing of that device's 717 * other functions. 718 */ 719 for (bus = first_bus; ((bus <= last_bus) && (rval == SUCCESS)); bus++) { 720 prg.bus_no = bus; 721 for (dev = first_dev; 722 ((dev <= last_dev) && (rval == SUCCESS)); dev++) { 723 prg.dev_no = dev; 724 rval = probe_dev(fd, &prg, input_args_p); 725 } 726 727 /* 728 * Ultra-45 southbridge workaround: 729 * ECANCELED tells to skip to the next bus. 730 */ 731 if (rval == ECANCELED) { 732 rval = SUCCESS; 733 } 734 } 735 736 return (rval); 737 } 738 739 /* 740 * This function is called-back from di_walk_minor() when any PROBE is processed 741 */ 742 /*ARGSUSED*/ 743 static int 744 process_nexus_node(di_node_t di_node, di_minor_t minor, void *arg) 745 { 746 int fd; 747 char *trunc; 748 probe_walk_args_t *walk_args_p = (probe_walk_args_t *)arg; 749 char *pathname = walk_args_p->pathname; 750 char *nexus_path = di_devfs_minor_path(minor); 751 752 if (nexus_path == NULL) { 753 (void) fprintf(stderr, "Error getting nexus path: %s\n", 754 strerror(errno)); 755 return (DI_WALK_CONTINUE); 756 } 757 758 /* 759 * Display this node if pathname not specified (as all nodes are 760 * displayed) or if the current node matches the single specified 761 * pathname. Pathname form: xxx, nexus form: xxx:reg 762 */ 763 if ((pathname != NULL) && 764 ((strstr(nexus_path, pathname) != nexus_path) || 765 (strlen(nexus_path) != 766 (strlen(pathname) + strlen(PCI_MINOR_REG) + 1)))) { 767 di_devfs_path_free(nexus_path); 768 return (DI_WALK_CONTINUE); 769 } 770 771 if ((fd = open_node(nexus_path, walk_args_p->input_args_p)) >= 0) { 772 773 /* Strip off the suffix at the end of the nexus path. */ 774 if ((trunc = strstr(nexus_path, PCI_MINOR_REG)) != NULL) { 775 trunc--; /* Get the : just before too. */ 776 *trunc = '\0'; 777 } 778 779 /* Show header only if no explicit nexus node name given. */ 780 (void) puts(""); 781 if (pathname == NULL) { 782 (void) printf("********** Devices in tree under %s " 783 "**********\n", nexus_path); 784 } 785 786 /* 787 * Exit silently with ENXIO as this means that there are 788 * no devices under the pci root nexus. 789 */ 790 if ((do_probe(fd, di_node, walk_args_p->di_phdl, 791 walk_args_p->input_args_p) != SUCCESS) && 792 (errno != ENXIO)) { 793 (void) fprintf(stderr, "Error probing node %s: %s\n", 794 nexus_path, strerror(errno)); 795 } 796 797 (void) close(fd); 798 } 799 di_devfs_path_free(nexus_path); 800 801 /* 802 * If node was explicitly specified, it has just been displayed 803 * and no more looping is required. 804 * Otherwise, keep looping for more nodes. 805 */ 806 return ((pathname == NULL) ? DI_WALK_CONTINUE : DI_WALK_TERMINATE); 807 } 808 809 810 /* 811 * Start of probe. If pathname is NULL, search all devices. 812 * 813 * di_walk_minor() walks all DDI_NT_REGACC (PCItool register access) nodes 814 * and calls process_nexus_node on them. process_nexus_node will then check 815 * the pathname for a match, unless it is NULL which works like a wildcard. 816 */ 817 static int 818 do_probe_walk(pcitool_uiargs_t *input_args_p, char *pathname) 819 { 820 di_node_t di_node; 821 di_prom_handle_t di_phdl = DI_PROM_HANDLE_NIL; 822 probe_walk_args_t walk_args; 823 824 int rval = SUCCESS; 825 826 if ((di_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 827 (void) fprintf(stderr, "di_init() failed: %s\n", 828 strerror(errno)); 829 rval = errno; 830 831 } else if ((input_args_p->flags & PROBERNG_FLAG) && 832 ((di_phdl = di_prom_init()) == DI_PROM_HANDLE_NIL)) { 833 (void) fprintf(stderr, "di_prom_init failed: %s\n", 834 strerror(errno)); 835 rval = errno; 836 837 } else { 838 walk_args.input_args_p = input_args_p; 839 walk_args.di_phdl = di_phdl; 840 walk_args.pathname = pathname; 841 (void) di_walk_minor(di_node, DDI_NT_REGACC, 0, 842 &walk_args, process_nexus_node); 843 } 844 845 if (di_phdl != DI_PROM_HANDLE_NIL) { 846 di_prom_fini(di_phdl); 847 } 848 849 if (di_node != DI_NODE_NIL) { 850 di_fini(di_node); 851 } 852 853 return (rval); 854 } 855 856 857 /* **************** Byte dump specific **************** */ 858 859 static void 860 print_bytedump_header(boolean_t do_chardump) 861 { 862 static char header1[] = {" " 863 "0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00"}; 864 static char header2[] = {" " 865 "-----------------------------------------------"}; 866 static char cheader1[] = {" 0123456789ABCDEF"}; 867 static char cheader2[] = {" ----------------"}; 868 869 (void) puts(""); 870 (void) printf(header1); 871 if (do_chardump) { 872 (void) printf(cheader1); 873 } 874 (void) puts(""); 875 (void) printf(header2); 876 if (do_chardump) { 877 (void) printf(cheader2); 878 } 879 } 880 881 882 /* Number of bytes per line in a dump. */ 883 #define DUMP_BUF_SIZE 16 884 #define LINES_BTWN_HEADER 16 885 886 /* 887 * Retrieve several bytes over several reads, and print a formatted byte-dump 888 * 889 * fd is the nexus by which device is accessed. 890 * prg provided has bus, dev, func, bank, initial offset already specified, 891 * as well as size and endian attributes. 892 * 893 * No checking is made that this is a read operation, although only read 894 * operations are allowed. 895 */ 896 static int 897 bytedump_get(int fd, int cmd, pcitool_reg_t *prg_p, 898 pcitool_uiargs_t *input_args_p) 899 { 900 typedef union { 901 uint8_t bytes[DUMP_BUF_SIZE]; 902 uint16_t shorts[DUMP_BUF_SIZE / sizeof (uint16_t)]; 903 uint32_t dwords[DUMP_BUF_SIZE / sizeof (uint32_t)]; 904 uint64_t longs[DUMP_BUF_SIZE / sizeof (uint64_t)]; 905 } buffer_t; 906 907 /* 908 * Local copy of pcitool_reg_t, since offset and phys_addrs are 909 * modified. 910 */ 911 pcitool_reg_t local_prg; 912 913 /* Loop parameters. */ 914 uint32_t dump_end = prg_p->offset + input_args_p->bytedump_amt; 915 uint32_t dump_curr = prg_p->offset; 916 917 int read_size = input_args_p->size; 918 919 /* How many stores to the buffer before it is full. */ 920 int wrap_size = DUMP_BUF_SIZE / read_size; 921 922 /* Address prints at the beginning of each line. */ 923 uint64_t print_addr = 0; 924 925 /* Skip this num bytes at the beginning of the first dump. */ 926 int skip_begin; 927 928 /* Skip this num bytes at the end of the last dump. */ 929 int skip_end = 0; 930 931 /* skip_begin and skip_end are needed twice. */ 932 int skip_begin2; 933 int skip_end2; 934 935 /* Number of lines between headers */ 936 int lines_since_header = 0; 937 938 boolean_t do_chardump = input_args_p->flags & CHARDUMP_FLAG; 939 boolean_t continue_on_errs = input_args_p->flags & ERRCONT_FLAG; 940 941 int rval = SUCCESS; /* Return status. */ 942 943 int next; 944 int i; 945 946 buffer_t buffer; 947 uint16_t error_mask = 0; /* 1 bit/byte in buf. Err when set */ 948 949 bzero(buffer.bytes, sizeof (uint8_t) * DUMP_BUF_SIZE); 950 951 local_prg = *prg_p; /* Make local copy. */ 952 953 /* 954 * Flip the bytes to proper order if reading on a big endian machine. 955 * Do this by reading big as little and vs. 956 */ 957 #if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG) 958 local_prg.acc_attr = 959 (PCITOOL_ACC_IS_BIG_ENDIAN(local_prg.acc_attr) ? 960 (local_prg.acc_attr & ~PCITOOL_ACC_ATTR_ENDN_BIG) : 961 (local_prg.acc_attr | PCITOOL_ACC_ATTR_ENDN_BIG)); 962 #endif 963 964 /* 965 * Get offset into buffer for first store. Assumes the buffer size is 966 * a multiple of the read size. "next" is the next buffer index to do 967 * a store. 968 */ 969 skip_begin = local_prg.offset % DUMP_BUF_SIZE; 970 next = skip_begin / read_size; 971 972 print_bytedump_header(do_chardump); 973 974 while (dump_curr < dump_end) { 975 976 /* For reading from the next location. */ 977 local_prg.offset = dump_curr; 978 979 /* Access the device. Abort on error. */ 980 if (((rval = ioctl(fd, cmd, &local_prg)) != SUCCESS) && 981 (!(continue_on_errs))) { 982 if (!(IS_QUIET(input_args_p->flags))) { 983 (void) fprintf(stderr, 984 "Ioctl failed:\n errno: %s\n status: %s\n", 985 strerror(errno), 986 strstatus(local_prg.status)); 987 } 988 break; 989 } 990 991 /* 992 * Initialize print_addr first time through, in case printing 993 * is starting in the middle of the buffer. Also reinitialize 994 * when wrap. 995 */ 996 if (print_addr == 0) { 997 998 /* 999 * X86 config space doesn't return phys addr. 1000 * Use offset instead in this case. 1001 */ 1002 if (local_prg.phys_addr == 0) { /* No phys addr ret */ 1003 print_addr = local_prg.offset - 1004 (local_prg.offset % DUMP_BUF_SIZE); 1005 } else { 1006 print_addr = local_prg.phys_addr - 1007 (local_prg.phys_addr % DUMP_BUF_SIZE); 1008 } 1009 } 1010 1011 /* 1012 * Read error occurred. 1013 * Shift the right number of error bits ((1 << read_size) - 1) 1014 * into the right place (next * read_size) 1015 */ 1016 if (rval != SUCCESS) { /* Read error occurred */ 1017 error_mask |= 1018 ((1 << read_size) - 1) << (next * read_size); 1019 1020 } else { /* Save data to the buffer. */ 1021 1022 switch (read_size) { 1023 case 1: 1024 buffer.bytes[next] = (uint8_t)local_prg.data; 1025 break; 1026 case 2: 1027 buffer.shorts[next] = (uint16_t)local_prg.data; 1028 break; 1029 case 4: 1030 buffer.dwords[next] = (uint32_t)local_prg.data; 1031 break; 1032 case 8: 1033 buffer.longs[next] = (uint64_t)local_prg.data; 1034 break; 1035 default: 1036 rval = EIO; 1037 break; 1038 } 1039 } 1040 next++; 1041 1042 /* Increment index for next store, and wrap. */ 1043 next %= wrap_size; 1044 dump_curr += read_size; 1045 1046 /* Zero out the remainder of the buffer if done. */ 1047 if (dump_curr >= dump_end) { 1048 if (next != 0) { 1049 bzero(&buffer.bytes[next * read_size], 1050 (wrap_size - next) * read_size); 1051 skip_end = (wrap_size - next) * read_size; 1052 next = 0; /* For printing below. */ 1053 } 1054 } 1055 1056 /* Dump the buffer if full or if done. */ 1057 if (next == 0) { 1058 1059 skip_begin2 = skip_begin; 1060 skip_end2 = skip_end; 1061 1062 (void) printf("\n0x%16.16" PRIx64 ":", print_addr); 1063 for (i = DUMP_BUF_SIZE - 1; i >= 0; i--) { 1064 if (skip_end) { 1065 skip_end--; 1066 (void) printf(" --"); 1067 } else if (skip_begin > i) { 1068 skip_begin--; 1069 (void) printf(" --"); 1070 } else if (error_mask & (1 << i)) { 1071 (void) printf(" XX"); 1072 } else { 1073 (void) printf(" %2.2x", 1074 buffer.bytes[i]); 1075 } 1076 } 1077 1078 if (do_chardump) { 1079 (void) putchar(' '); 1080 for (i = 0; i < DUMP_BUF_SIZE; i++) { 1081 if (skip_begin2) { 1082 skip_begin2--; 1083 (void) printf("-"); 1084 } else if ( 1085 (DUMP_BUF_SIZE - skip_end2) <= i) { 1086 (void) printf("-"); 1087 } else if (error_mask & (1 << i)) { 1088 (void) putchar('X'); 1089 } else if (isprint(buffer.bytes[i])) { 1090 (void) putchar(buffer.bytes[i]); 1091 } else { 1092 (void) putchar('@'); 1093 } 1094 } 1095 } 1096 1097 if ((++lines_since_header == LINES_BTWN_HEADER) && 1098 (dump_curr < dump_end)) { 1099 lines_since_header = 0; 1100 (void) puts(""); 1101 print_bytedump_header(do_chardump); 1102 } 1103 1104 print_addr += DUMP_BUF_SIZE; 1105 error_mask = 0; 1106 } 1107 } 1108 (void) printf("\n"); 1109 1110 return (rval); 1111 } 1112 1113 1114 /* ************** Device and nexus access commands ************** */ 1115 1116 /* 1117 * Helper function to set access attributes. Assumes size is valid. 1118 */ 1119 static uint32_t 1120 set_acc_attr(pcitool_uiargs_t *input_args_p) 1121 { 1122 uint32_t access_attrs; 1123 1124 switch (input_args_p->size) { 1125 case 1: 1126 access_attrs = PCITOOL_ACC_ATTR_SIZE_1; 1127 break; 1128 case 2: 1129 access_attrs = PCITOOL_ACC_ATTR_SIZE_2; 1130 break; 1131 case 4: 1132 access_attrs = PCITOOL_ACC_ATTR_SIZE_4; 1133 break; 1134 case 8: 1135 access_attrs = PCITOOL_ACC_ATTR_SIZE_8; 1136 break; 1137 } 1138 1139 if (input_args_p->big_endian) { 1140 access_attrs |= PCITOOL_ACC_ATTR_ENDN_BIG; 1141 } 1142 1143 return (access_attrs); 1144 } 1145 1146 static int 1147 do_single_access(int fd, int cmd, pcitool_reg_t *prg_p, 1148 pcitool_uiargs_t *input_args_p) 1149 { 1150 boolean_t is_write = B_FALSE; 1151 int rval; 1152 1153 switch (cmd) { 1154 case PCITOOL_NEXUS_SET_REG: 1155 case PCITOOL_DEVICE_SET_REG: 1156 is_write = B_TRUE; 1157 break; 1158 default: 1159 break; 1160 } 1161 1162 /* Do the access. Return on error. */ 1163 if ((rval = ioctl(fd, cmd, prg_p)) != SUCCESS) { 1164 if (!(IS_QUIET(input_args_p->flags))) { 1165 (void) fprintf(stderr, 1166 "%s ioctl failed:\n errno: %s\n status: %s\n", 1167 is_write ? "write" : "read", 1168 strerror(errno), strstatus(prg_p->status)); 1169 } 1170 1171 return (rval); 1172 } 1173 1174 /* Print on all verbose requests. */ 1175 if (IS_VERBOSE(input_args_p->flags)) { 1176 1177 /* 1178 * Return offset on platforms which return phys_addr == 0 1179 * for config space. 1180 */ 1181 if (prg_p->phys_addr == 0) 1182 prg_p->phys_addr = input_args_p->offset; 1183 1184 (void) printf("Addr:0x%" PRIx64 ", %d-byte %s endian " 1185 "register value: 0x%" PRIx64 "\n", 1186 prg_p->phys_addr, input_args_p->size, 1187 (input_args_p->big_endian ? "big" : "little"), prg_p->data); 1188 1189 /* Non-verbose, read requests. */ 1190 } else if (!(is_write)) { 1191 (void) printf("0x%" PRIx64 "\n", prg_p->data); 1192 } 1193 1194 return (rval); 1195 } 1196 1197 1198 /* 1199 * fd is the file descriptor of the nexus to access, either to get its 1200 * registers or to access a device through that nexus. 1201 * 1202 * input args are commandline arguments specified by the user. 1203 */ 1204 static int 1205 do_device_or_nexus(int fd, pcitool_uiargs_t *input_args_p) 1206 { 1207 pcitool_reg_t prg; /* Request details given to the driver. */ 1208 uint32_t write_cmd = 0; /* Command given to the driver. */ 1209 uint32_t read_cmd = 0; /* Command given to the driver. */ 1210 int rval = SUCCESS; /* Return status. */ 1211 1212 if (input_args_p->flags & WRITE_FLAG) { 1213 prg.data = input_args_p->write_value; 1214 if (input_args_p->flags & NEXUS_FLAG) { 1215 write_cmd = PCITOOL_NEXUS_SET_REG; 1216 } else { 1217 write_cmd = PCITOOL_DEVICE_SET_REG; 1218 } 1219 } 1220 if (input_args_p->flags & READ_FLAG) { 1221 if (input_args_p->flags & NEXUS_FLAG) { 1222 read_cmd = PCITOOL_NEXUS_GET_REG; 1223 } else { 1224 read_cmd = PCITOOL_DEVICE_GET_REG; 1225 } 1226 } 1227 1228 /* Finish initializing access details for driver. */ 1229 1230 /* 1231 * For nexus, barnum is the exact bank number, unless it is 0xFF, which 1232 * indicates that it is inactive and a base_address should be read from 1233 * the input_args instead. 1234 * 1235 * For devices, barnum is the offset to the desired BAR, or 0 for 1236 * config space. 1237 */ 1238 if ((input_args_p->flags & (BASE_SPEC_FLAG | NEXUS_FLAG)) == 1239 (BASE_SPEC_FLAG | NEXUS_FLAG)) { 1240 prg.barnum = PCITOOL_BASE; 1241 prg.phys_addr = input_args_p->base_address; 1242 } else 1243 prg.barnum = input_args_p->bank; 1244 1245 prg.offset = input_args_p->offset; 1246 prg.acc_attr = set_acc_attr(input_args_p); 1247 prg.bus_no = input_args_p->bus; 1248 prg.dev_no = input_args_p->device; 1249 prg.func_no = input_args_p->function; 1250 prg.user_version = PCITOOL_VERSION; 1251 1252 do { 1253 /* Do a bytedump if desired, or else do single ioctl access. */ 1254 if (input_args_p->flags & BYTEDUMP_FLAG) { 1255 1256 if (IS_VERBOSE(input_args_p->flags)) { 1257 (void) printf( 1258 "\nDoing %d-byte %s endian reads:", 1259 input_args_p->size, 1260 input_args_p->big_endian ? 1261 "big" : "little"); 1262 } 1263 rval = bytedump_get(fd, read_cmd, &prg, input_args_p); 1264 1265 } else { 1266 1267 /* Single write and/or read. */ 1268 if (write_cmd != 0) { 1269 rval = do_single_access( 1270 fd, write_cmd, &prg, input_args_p); 1271 } 1272 1273 if ((rval == SUCCESS) && (read_cmd != 0)) { 1274 rval = do_single_access( 1275 fd, read_cmd, &prg, input_args_p); 1276 } 1277 } 1278 } while ((IS_LOOP(input_args_p->flags)) && (rval == SUCCESS) && 1279 (keep_looping)); 1280 1281 return (rval != SUCCESS ? errno : SUCCESS); 1282 } 1283 1284 /* *************** Interrupt routing ************** */ 1285 1286 /* 1287 * Display interrupt information. 1288 * iget is filled in with the info to display 1289 */ 1290 static void 1291 print_intr_info(pcitool_intr_get_t *iget_p) 1292 { 1293 int i; 1294 1295 if (iget_p->flags & PCITOOL_INTR_FLAG_GET_MSI) 1296 (void) printf("\nmsi 0x%x mapped to cpu 0x%x\n", 1297 iget_p->msi, iget_p->cpu_id); 1298 else 1299 (void) printf("\nino 0x%x mapped to cpu 0x%x\n", 1300 iget_p->ino, iget_p->cpu_id); 1301 1302 for (i = 0; i < iget_p->num_devs; i++) { 1303 (void) printf("Device: %s\n", iget_p->dev[i].path); 1304 (void) printf(" Driver: %s, instance %d\n", 1305 iget_p->dev[i].driver_name, iget_p->dev[i].dev_inst); 1306 } 1307 } 1308 1309 /* 1310 * Interrupt command support. 1311 * 1312 * fd is the file descriptor of the nexus being probed. 1313 * input_args are commandline options entered by the user. 1314 */ 1315 static int 1316 get_single_interrupt(int fd, pcitool_intr_get_t **iget_pp, 1317 pcitool_uiargs_t *input_args_p) 1318 { 1319 pcitool_intr_get_t *iget_p = *iget_pp; 1320 const char *str_type = NULL; 1321 uint32_t intr; 1322 1323 if (input_args_p->flags & MSI_SPEC_FLAG) { 1324 intr = input_args_p->intr_msi; 1325 str_type = "msi"; 1326 } else { 1327 intr = input_args_p->intr_ino; 1328 str_type = "ino"; 1329 } 1330 1331 /* 1332 * Check if interrupts are active on this ino/msi. Get as much 1333 * device info as there is room for at the moment. If there 1334 * is not enough room for all devices, will call again with a 1335 * larger buffer. 1336 */ 1337 if (ioctl(fd, PCITOOL_DEVICE_GET_INTR, iget_p) != 0) { 1338 /* 1339 * Let EIO errors silently slip through, as 1340 * some inos may not be viewable by design. 1341 * We don't want to stop or print an error for these. 1342 */ 1343 if (errno == EIO) { 1344 return (SUCCESS); 1345 } 1346 1347 if (!(IS_QUIET(input_args_p->flags))) { 1348 (void) fprintf(stderr, "Ioctl to get %s 0x%x " 1349 "info failed: %s\n", str_type, intr, 1350 strerror(errno)); 1351 1352 if (errno != EFAULT) { 1353 (void) fprintf(stderr, "Pcitool status: %s\n", 1354 strstatus(iget_p->status)); 1355 } 1356 } 1357 return (errno); 1358 } 1359 1360 /* Nothing to report for this interrupt. */ 1361 if (iget_p->num_devs == 0) { 1362 return (SUCCESS); 1363 } 1364 1365 /* Need more room to return additional device info. */ 1366 if (iget_p->num_devs_ret < iget_p->num_devs) { 1367 iget_p = *iget_pp = 1368 realloc(iget_p, PCITOOL_IGET_SIZE(iget_p->num_devs)); 1369 iget_p->num_devs_ret = iget_p->num_devs; 1370 1371 if (ioctl(fd, PCITOOL_DEVICE_GET_INTR, iget_p) != 0) { 1372 if (!(IS_QUIET(input_args_p->flags))) { 1373 (void) fprintf(stderr, "Ioctl to get %s 0x%x" 1374 "device info failed: %s\n", str_type, 1375 intr, strerror(errno)); 1376 if (errno != EFAULT) { 1377 (void) fprintf(stderr, 1378 "Pcitool status: %s\n", 1379 strstatus(iget_p->status)); 1380 } 1381 } 1382 return (errno); 1383 } 1384 } 1385 1386 print_intr_info(iget_p); 1387 return (SUCCESS); 1388 } 1389 1390 #define INIT_NUM_DEVS 0 1391 1392 static int 1393 get_interrupts(int fd, pcitool_uiargs_t *input_args_p) 1394 { 1395 int rval = SUCCESS; /* Return status. */ 1396 1397 /* 1398 * Start with a struct with space for info of INIT_NUM_DEVS devs 1399 * to be returned. 1400 */ 1401 pcitool_intr_get_t *iget_p = malloc(PCITOOL_IGET_SIZE(INIT_NUM_DEVS)); 1402 1403 iget_p->num_devs_ret = INIT_NUM_DEVS; 1404 iget_p->user_version = PCITOOL_VERSION; 1405 1406 /* Explicit MSI requested. */ 1407 if (input_args_p->flags & MSI_SPEC_FLAG) { 1408 iget_p->msi = input_args_p->intr_msi; 1409 iget_p->flags = PCITOOL_INTR_FLAG_GET_MSI; 1410 rval = get_single_interrupt(fd, &iget_p, input_args_p); 1411 /* Return all MSIs. */ 1412 } else if (input_args_p->flags & MSI_ALL_FLAG) { 1413 pcitool_intr_info_t intr_info; 1414 intr_info.flags = PCITOOL_INTR_FLAG_GET_MSI; 1415 1416 if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) { 1417 if (!(IS_QUIET(input_args_p->flags))) { 1418 (void) fprintf(stderr, 1419 "intr info ioctl failed: %s\n", 1420 strerror(errno)); 1421 } 1422 } else { 1423 int msi; 1424 1425 /* 1426 * Search through all interrupts. 1427 * Display info on enabled ones. 1428 */ 1429 for (msi = 0; 1430 ((msi < intr_info.num_intr) && (rval == SUCCESS)); 1431 msi++) { 1432 bzero(iget_p, sizeof (pcitool_intr_get_t)); 1433 iget_p->num_devs_ret = INIT_NUM_DEVS; 1434 iget_p->user_version = PCITOOL_VERSION; 1435 iget_p->flags = PCITOOL_INTR_FLAG_GET_MSI; 1436 iget_p->msi = msi; 1437 rval = get_single_interrupt( 1438 fd, &iget_p, input_args_p); 1439 } 1440 } 1441 /* Explicit INO requested. */ 1442 } else if (input_args_p->flags & INO_SPEC_FLAG) { 1443 iget_p->ino = input_args_p->intr_ino; 1444 rval = get_single_interrupt(fd, &iget_p, input_args_p); 1445 /* Return all INOs. */ 1446 } else if (input_args_p->flags & INO_ALL_FLAG) { 1447 pcitool_intr_info_t intr_info; 1448 intr_info.flags = 0; 1449 1450 if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) { 1451 if (!(IS_QUIET(input_args_p->flags))) { 1452 (void) fprintf(stderr, 1453 "intr info ioctl failed: %s\n", 1454 strerror(errno)); 1455 } 1456 } else { 1457 int ino; 1458 1459 /* 1460 * Search through all interrupts. 1461 * Display info on enabled ones. 1462 */ 1463 for (ino = 0; 1464 ((ino < intr_info.num_intr) && (rval == SUCCESS)); 1465 ino++) { 1466 bzero(iget_p, sizeof (pcitool_intr_get_t)); 1467 iget_p->num_devs_ret = INIT_NUM_DEVS; 1468 iget_p->user_version = PCITOOL_VERSION; 1469 iget_p->ino = ino; 1470 rval = get_single_interrupt( 1471 fd, &iget_p, input_args_p); 1472 } 1473 } 1474 } 1475 1476 free(iget_p); 1477 1478 return (rval); 1479 } 1480 1481 1482 static int 1483 get_interrupt_ctlr(int fd, pcitool_uiargs_t *input_args_p) 1484 { 1485 pcitool_intr_info_t intr_info; 1486 char *ctlr_type = NULL; 1487 int rval = SUCCESS; 1488 1489 intr_info.flags = 0; 1490 if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) { 1491 if (!(IS_QUIET(input_args_p->flags))) { 1492 (void) perror("Ioctl to get intr ctlr info failed"); 1493 } 1494 rval = errno; 1495 1496 } else { 1497 (void) fputs("Controller type: ", stdout); 1498 switch (intr_info.ctlr_type) { 1499 case PCITOOL_CTLR_TYPE_RISC: 1500 ctlr_type = "RISC"; 1501 break; 1502 case PCITOOL_CTLR_TYPE_UPPC: 1503 ctlr_type = "UPPC"; 1504 break; 1505 case PCITOOL_CTLR_TYPE_PCPLUSMP: 1506 ctlr_type = "PCPLUSMP"; 1507 break; 1508 default: 1509 break; 1510 } 1511 1512 if (ctlr_type == NULL) { 1513 (void) printf("Unknown or new (%d)", 1514 intr_info.ctlr_type); 1515 } else { 1516 (void) fputs(ctlr_type, stdout); 1517 } 1518 1519 #ifdef __x86 1520 if (intr_info.ctlr_type == PCITOOL_CTLR_TYPE_PCPLUSMP) 1521 (void) printf(", IO APIC version: 0x%x, " 1522 "local APIC version: 0x%x\n", 1523 PSMAT_IO_APIC_VER(intr_info.ctlr_version), 1524 PSMAT_LOCAL_APIC_VER(intr_info.ctlr_version)); 1525 else 1526 #endif /* __x86 */ 1527 (void) printf(", version: %2.2x.%2.2x.%2.2x.%2.2x\n", 1528 ((intr_info.ctlr_version >> 24) & 0xff), 1529 ((intr_info.ctlr_version >> 16) & 0xff), 1530 ((intr_info.ctlr_version >> 8) & 0xff), 1531 (intr_info.ctlr_version & 0xff)); 1532 } 1533 1534 return (rval); 1535 } 1536 1537 /* 1538 * 1539 * fd is the file descriptor of the nexus being changed. 1540 * input_args are commandline options entered by the user. 1541 */ 1542 static int 1543 set_interrupts(int fd, pcitool_uiargs_t *input_args_p) 1544 { 1545 pcitool_intr_set_t iset; 1546 const char *str_type = NULL; 1547 uint32_t intr; 1548 int rval = SUCCESS; /* Return status. */ 1549 1550 /* Load interrupt number and cpu from commandline. */ 1551 if (input_args_p->flags & MSI_SPEC_FLAG) { 1552 iset.msi = intr = input_args_p->intr_msi; 1553 iset.flags = PCITOOL_INTR_FLAG_SET_MSI; 1554 str_type = "msi"; 1555 } else { 1556 iset.ino = intr = input_args_p->intr_ino; 1557 iset.flags = 0; 1558 str_type = "ino"; 1559 } 1560 1561 iset.cpu_id = input_args_p->intr_cpu; 1562 iset.user_version = PCITOOL_VERSION; 1563 iset.flags |= (input_args_p->flags & SETGRP_FLAG) ? 1564 PCITOOL_INTR_FLAG_SET_GROUP : 0; 1565 1566 /* Do the deed. */ 1567 if (ioctl(fd, PCITOOL_DEVICE_SET_INTR, &iset) != 0) { 1568 if (!(IS_QUIET(input_args_p->flags))) { 1569 (void) fprintf(stderr, 1570 "Ioctl to set %s 0x%x failed: %s\n", 1571 str_type, intr, strerror(errno)); 1572 (void) fprintf(stderr, "pcitool status: %s\n", 1573 strstatus(iset.status)); 1574 } 1575 rval = errno; 1576 } else { 1577 if (input_args_p->flags & SETGRP_FLAG) { 1578 (void) printf("\nInterrupts on %s group starting " 1579 "at %s 0x%x reassigned:", str_type, str_type, intr); 1580 } else { 1581 (void) printf("\nInterrupts on %s 0x%x reassigned:", 1582 str_type, intr); 1583 } 1584 (void) printf(" Old cpu: 0x%x, New cpu: 0x%x\n", iset.cpu_id, 1585 input_args_p->intr_cpu); 1586 } 1587 1588 return (rval); 1589 } 1590 1591 1592 static int 1593 do_interrupts(int fd, pcitool_uiargs_t *input_args_p) 1594 { 1595 if (input_args_p->flags & READ_FLAG) { 1596 1597 int gic_rval; 1598 int gi_rval; 1599 1600 if (input_args_p->flags & SHOWCTLR_FLAG) { 1601 gic_rval = get_interrupt_ctlr(fd, input_args_p); 1602 } 1603 1604 gi_rval = get_interrupts(fd, input_args_p); 1605 return ((gi_rval != SUCCESS) ? gi_rval : gic_rval); 1606 1607 } else { 1608 1609 return (set_interrupts(fd, input_args_p)); 1610 } 1611 } 1612 1613 1614 /* *********** Where it all begins... ************* */ 1615 1616 int 1617 main(int argc, char **argv) 1618 { 1619 pcitool_uiargs_t input_args; /* Commandline args. */ 1620 int fd; /* Nexus file descriptor. */ 1621 int rval = SUCCESS; /* Return status value. */ 1622 1623 1624 /* Get commandline args and options from user. */ 1625 if (get_commandline_args(argc, argv, &input_args) != SUCCESS) { 1626 return (EINVAL); 1627 } 1628 1629 /* Help. */ 1630 if (!(input_args.flags & ALL_COMMANDS)) 1631 return (SUCCESS); 1632 1633 /* 1634 * Probe mode. 1635 * Nexus is provided as argv[1] unless PROBEALL mode. 1636 */ 1637 if (input_args.flags & PROBE_FLAGS) { 1638 rval = do_probe_walk(&input_args, 1639 ((input_args.flags & PROBEALL_FLAG) ? NULL : argv[1])); 1640 1641 } else if ((fd = open_node(argv[1], &input_args)) >= 0) { 1642 if (input_args.flags & (NEXUS_FLAG | LEAF_FLAG)) { 1643 (void) signal(SIGINT, signal_handler); 1644 (void) signal(SIGTERM, signal_handler); 1645 rval = do_device_or_nexus(fd, &input_args); 1646 } else if (input_args.flags & INTR_FLAG) { 1647 rval = do_interrupts(fd, &input_args); 1648 } else { 1649 /* Should never see this. */ 1650 (void) fprintf(stderr, "Nothing to do.\n"); 1651 rval = ENOTTY; 1652 } 1653 1654 (void) close(fd); 1655 } 1656 1657 return (rval); 1658 } 1659