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