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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* This file is the main module for the pcitool. */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <unistd.h> 30 #include <sys/inttypes.h> 31 #include <signal.h> 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <fcntl.h> 35 #include <strings.h> 36 #include <ctype.h> 37 #include <errno.h> 38 #include <libdevinfo.h> 39 #include <sys/sunddi.h> 40 41 #ifdef __x86 42 #include <sys/apic_ctlr.h> 43 #endif 44 45 #include <sys/pci.h> 46 #include <sys/pci_tools.h> 47 48 #include "pcitool_ui.h" 49 50 /* First 16 longs of device PCI config header. */ 51 typedef union { 52 uint8_t bytes[16 * sizeof (uint32_t)]; 53 uint32_t dwords[16]; 54 } pci_conf_hdr_t; 55 56 /* Used by probe printing functions. */ 57 typedef struct { 58 uint16_t cfg_offset; /* Offset of data within config space. */ 59 uint8_t size; /* Size of desired data field. */ 60 char *abbrev_hdr; /* Abbreviated header for this data. */ 61 char *full_hdr; /* Full header for this data, verbose option. */ 62 } field_type_t; 63 64 /* Used to package many args into one arg for probe di_node walk function. */ 65 typedef struct { 66 pcitool_uiargs_t *input_args_p; 67 char *pathname; 68 di_prom_handle_t di_phdl; 69 } probe_walk_args_t; 70 71 /* 72 * Read config space in native processor endianness. Endian-neutral 73 * processing can then take place. On big endian machines, MSB and LSB 74 * of little endian data end up switched if read as little endian. 75 * They are in correct order if read as big endian. 76 */ 77 #if defined(__sparc) 78 #define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_BIG 79 #elif defined(__x86) 80 #define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_LTL 81 #else 82 #error "ISA is neither __sparc nor __x86" 83 #endif 84 85 /* status error lookup table. */ 86 static struct { 87 pcitool_errno_t value; 88 char *string; 89 } pcitool_stat_str[] = { 90 { PCITOOL_SUCCESS, 91 "No error status returned from driver" }, 92 { PCITOOL_INVALID_CPUID, 93 "CPU is non-existent or not online" }, 94 { PCITOOL_INVALID_INO, 95 "INO is out of range or invalid" }, 96 { PCITOOL_INVALID_MSI, 97 "MSI is out of range or invalid" }, 98 { PCITOOL_PENDING_INTRTIMEOUT, 99 "Timeout waiting for pending interrupts to clear" }, 100 { PCITOOL_REGPROP_NOTWELLFORMED, 101 "Reg property has invalid format" }, 102 { PCITOOL_INVALID_ADDRESS, 103 "Address out of range or invalid" }, 104 { PCITOOL_NOT_ALIGNED, 105 "Improper address alignment for access attempted" }, 106 { PCITOOL_OUT_OF_RANGE, 107 "Argument out of range" }, 108 { PCITOOL_END_OF_RANGE, 109 "End of address range" }, 110 { PCITOOL_ROM_DISABLED, 111 "Device ROM is disabled. Cannot read" }, 112 { PCITOOL_ROM_WRITE, 113 "Write to ROM not allowed" }, 114 { PCITOOL_IO_ERROR, 115 "IO error encountered" }, 116 { PCITOOL_INVALID_SIZE, 117 "Size is invalid for this platform" }, 118 { 0, NULL } 119 }; 120 121 122 /* Used with ^C handler to stop looping in repeat mode in do_device_or_nexus. */ 123 static boolean_t keep_looping = B_TRUE; 124 125 static void signal_handler(int dummy); 126 static char *strstatus(pcitool_errno_t pcitool_status); 127 static int open_node(char *device, pcitool_uiargs_t *input_args_p); 128 static void print_probe_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset, 129 uint8_t size); 130 static void print_probe_info_verbose(pci_conf_hdr_t *config_hdr_p, 131 pcitool_reg_t *info_p); 132 static void print_probe_info_nonverbose(pci_conf_hdr_t *config_hdr_p, 133 pcitool_reg_t *info_p); 134 static void print_probe_info(pci_conf_hdr_t *config_hdr_p, 135 pcitool_reg_t *info_p, boolean_t verbose); 136 static int get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, 137 uint8_t func_no, pci_conf_hdr_t *config_hdr_p); 138 static int supports_ari(int fd, uint8_t bus_no); 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 return (rval); 461 } 462 463 static int 464 supports_ari(int fd, uint8_t bus_no) 465 { 466 pcitool_reg_t cfg_prg; 467 int deadcount = 0; 468 uint32_t data, hdr_next_ptr, hdr_cap_id; 469 uint8_t dev_no = 0; 470 uint8_t func_no = 0; 471 472 /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */ 473 cfg_prg.bus_no = bus_no; 474 cfg_prg.dev_no = dev_no; 475 cfg_prg.func_no = func_no; 476 cfg_prg.barnum = 0; 477 cfg_prg.user_version = PCITOOL_VERSION; 478 cfg_prg.offset = 0; 479 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + PCITOOL_ACC_ATTR_ENDN_LTL; 480 481 if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) { 482 return (FAILURE); 483 } 484 485 data = (uint32_t)cfg_prg.data; 486 if (data == (uint32_t)(-1)) 487 return (FAILURE); 488 489 cfg_prg.offset = PCI_CONF_COMM; 490 if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) { 491 return (FAILURE); 492 } 493 494 data = (uint32_t)cfg_prg.data; 495 if (!((data >> 16) & PCI_STAT_CAP)) 496 return (FAILURE); 497 498 cfg_prg.offset = PCI_CONF_CAP_PTR; 499 if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) { 500 return (FAILURE); 501 } 502 data = (uint32_t)cfg_prg.data; 503 hdr_next_ptr = data & 0xff; 504 hdr_cap_id = 0; 505 506 /* 507 * Find the PCIe capability. 508 */ 509 while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) && 510 (hdr_cap_id != PCI_CAP_ID_PCI_E)) { 511 512 if (hdr_next_ptr < 0x40) 513 break; 514 515 cfg_prg.offset = hdr_next_ptr; 516 517 if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) 518 return (FAILURE); 519 520 data = (uint32_t)cfg_prg.data; 521 522 hdr_next_ptr = (data >> 8) & 0xFF; 523 hdr_cap_id = data & 0xFF; 524 525 if (deadcount++ > 100) 526 return (FAILURE); 527 } 528 529 if (hdr_cap_id != PCI_CAP_ID_PCI_E) 530 return (FAILURE); 531 532 /* Found a PCIe Capability */ 533 534 hdr_next_ptr = 0x100; 535 hdr_cap_id = 0; 536 537 /* 538 * Now find the ARI Capability. 539 */ 540 while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) && 541 (hdr_cap_id != 0xe)) { 542 543 if (hdr_next_ptr < 0x40) 544 break; 545 546 cfg_prg.offset = hdr_next_ptr; 547 548 if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) { 549 return (FAILURE); 550 } 551 data = (uint32_t)cfg_prg.data; 552 553 hdr_next_ptr = (data >> 20) & 0xFFF; 554 hdr_cap_id = data & 0xFFFF; 555 556 if (deadcount++ > 100) 557 return (FAILURE); 558 } 559 560 if (hdr_cap_id != 0xe) 561 return (FAILURE); 562 563 return (SUCCESS); 564 } 565 566 /* 567 * Identify problematic southbridges. These have device id 0x5249 and 568 * vendor id 0x10b9. Check for revision ID 0 and class code 060400 as well. 569 * Values are little endian, so they are reversed for SPARC. 570 * 571 * Check for these southbridges on all architectures, as the issue is a 572 * southbridge issue, independent of processor. 573 * 574 * If one of these is found during probing, skip probing other devs/funcs on 575 * the rest of the bus, since the southbridge and all devs underneath will 576 * otherwise disappear. 577 */ 578 #if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG) 579 #define U45_SB_DEVID_VID 0xb9104952 580 #define U45_SB_CLASS_RID 0x00000406 581 #else 582 #define U45_SB_DEVID_VID 0x524910b9 583 #define U45_SB_CLASS_RID 0x06040000 584 #endif 585 586 /* 587 * Probe device's functions. Modifies many fields in the prg_p. 588 */ 589 static int 590 probe_dev(int fd, pcitool_reg_t *prg_p, pcitool_uiargs_t *input_args_p) 591 { 592 pci_conf_hdr_t config_hdr; 593 boolean_t multi_function_device = B_FALSE; 594 int func; 595 int first_func = 0; 596 int last_func = PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT; 597 int rval = SUCCESS; 598 599 if (input_args_p->flags & FUNC_SPEC_FLAG) { 600 first_func = last_func = input_args_p->function; 601 } else if (supports_ari(fd, prg_p->bus_no) == SUCCESS) { 602 multi_function_device = B_TRUE; 603 if (!(input_args_p->flags & DEV_SPEC_FLAG)) 604 last_func = 255; 605 } 606 607 /* 608 * Loop through at least func=first_func. Continue looping through 609 * functions if there are no errors and the device is a multi-function 610 * device. 611 * 612 * (Note, if first_func == 0, header will show whether multifunction 613 * device and set multi_function_device. If first_func != 0, then we 614 * will force the loop as the user wants a specific function to be 615 * checked. 616 */ 617 for (func = first_func; ((func <= last_func) && 618 ((func == first_func) || (multi_function_device))); 619 func++) { 620 if (last_func > 7) { 621 prg_p->func_no = func & 0x7; 622 prg_p->dev_no = (func >> 3) & 0x1f; 623 } else 624 prg_p->func_no = func; 625 626 /* 627 * Four things can happen here: 628 * 629 * 1) ioctl comes back as EFAULT and prg_p->status is 630 * PCITOOL_INVALID_ADDRESS. There is no device at this 631 * location. 632 * 633 * 2) ioctl comes back successful and the data comes back as 634 * zero. Config space is mapped but no device responded. 635 * 636 * 3) ioctl comes back successful and the data comes back as 637 * non-zero. We've found a device. 638 * 639 * 4) Some other error occurs in an ioctl. 640 */ 641 642 prg_p->status = PCITOOL_SUCCESS; 643 prg_p->offset = 0; 644 prg_p->data = 0; 645 prg_p->user_version = PCITOOL_VERSION; 646 if (((rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, prg_p)) != 0) || 647 (prg_p->data == 0xffffffff)) { 648 649 /* 650 * Accept errno == EINVAL along with status of 651 * PCITOOL_OUT_OF_RANGE because some systems 652 * don't implement the full range of config space. 653 * Leave the loop quietly in this case. 654 */ 655 if ((errno == EINVAL) || 656 (prg_p->status == PCITOOL_OUT_OF_RANGE)) { 657 break; 658 } 659 660 /* 661 * Exit silently with ENXIO as this means that there are 662 * no devices under the pci root nexus. 663 */ 664 else if ((errno == ENXIO) && 665 (prg_p->status == PCITOOL_IO_ERROR)) { 666 break; 667 } 668 669 /* 670 * Expect errno == EFAULT along with status of 671 * PCITOOL_INVALID_ADDRESS because there won't be 672 * devices at each stop. Quit on any other error. 673 */ 674 else if (((errno != EFAULT) || 675 (prg_p->status != PCITOOL_INVALID_ADDRESS)) && 676 (prg_p->data != 0xffffffff)) { 677 678 if (!(IS_QUIET(input_args_p->flags))) { 679 (void) fprintf(stderr, 680 "Ioctl error: %s\n", 681 strerror(errno)); 682 } 683 break; 684 685 /* 686 * If no function at this location, 687 * just advance to the next function. 688 */ 689 } else { 690 rval = SUCCESS; 691 } 692 693 /* 694 * Data came back as 0. 695 * Treat as unresponsive device amd check next device. 696 */ 697 } else if (prg_p->data == 0) { 698 rval = SUCCESS; 699 /* Found something. */ 700 } else { 701 config_hdr.dwords[0] = (uint32_t)prg_p->data; 702 703 /* Get the rest of the PCI header. */ 704 if ((rval = get_config_header(fd, prg_p->bus_no, 705 prg_p->dev_no, prg_p->func_no, &config_hdr)) != 706 SUCCESS) { 707 break; 708 } 709 710 /* Print the found information. */ 711 print_probe_info(&config_hdr, prg_p, 712 IS_VERBOSE(input_args_p->flags)); 713 714 /* 715 * Special case for the type of Southbridge found on 716 * Ultra-45 and other sun4u fire workstations. 717 */ 718 if ((config_hdr.dwords[0] == U45_SB_DEVID_VID) && 719 (config_hdr.dwords[2] == U45_SB_CLASS_RID)) { 720 rval = ECANCELED; 721 break; 722 } 723 724 /* 725 * Accomodate devices which state their 726 * multi-functionality only in their function 0 config 727 * space. Note multi-functionality throughout probing 728 * of all of this device's functions. 729 */ 730 if (config_hdr.bytes[PCI_CONF_HEADER] & 731 PCI_HEADER_MULTI) { 732 multi_function_device = B_TRUE; 733 } 734 } 735 } 736 737 return (rval); 738 } 739 740 741 /* 742 * Probe a given nexus config space for devices. 743 * 744 * fd is the file descriptor of the nexus. 745 * input_args contains commandline options as specified by the user. 746 */ 747 static int 748 do_probe(int fd, di_node_t di_node, di_prom_handle_t di_phdl, 749 pcitool_uiargs_t *input_args_p) 750 { 751 pcitool_reg_t prg; 752 int bus; 753 int dev; 754 int last_bus = PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT; 755 int last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT; 756 int first_bus = 0; 757 int first_dev = 0; 758 int rval = SUCCESS; 759 760 prg.barnum = 0; /* Config space. */ 761 762 /* Must read in 4-byte quantities. */ 763 prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; 764 765 prg.data = 0; 766 767 /* If an explicit bus was specified by the user, go with it. */ 768 if (input_args_p->flags & BUS_SPEC_FLAG) { 769 first_bus = last_bus = input_args_p->bus; 770 771 } else if (input_args_p->flags & PROBERNG_FLAG) { 772 /* Otherwise get the bus range from properties. */ 773 int len; 774 uint32_t *rangebuf = NULL; 775 776 len = di_prop_lookup_ints(DDI_DEV_T_ANY, di_node, 777 "bus-range", (int **)&rangebuf); 778 779 /* Try PROM property */ 780 if (len <= 0) { 781 len = di_prom_prop_lookup_ints(di_phdl, di_node, 782 "bus-range", (int **)&rangebuf); 783 } 784 785 /* Take full range for default if cannot get property. */ 786 if (len > 0) { 787 first_bus = rangebuf[0]; 788 last_bus = rangebuf[1]; 789 } 790 } 791 792 /* Take full range for default if not PROBERNG and not BUS_SPEC. */ 793 794 if (last_bus == first_bus) { 795 if (input_args_p->flags & DEV_SPEC_FLAG) { 796 /* Explicit device given. Not probing a whole bus. */ 797 (void) puts(""); 798 } else { 799 (void) printf("*********** Probing bus %x " 800 "***********\n\n", first_bus); 801 } 802 } else { 803 (void) printf("*********** Probing buses %x through %x " 804 "***********\n\n", first_bus, last_bus); 805 } 806 807 /* Print header. */ 808 print_probe_info(NULL, NULL, IS_VERBOSE(input_args_p->flags)); 809 810 /* Device number explicitly specified. */ 811 if (input_args_p->flags & DEV_SPEC_FLAG) { 812 first_dev = last_dev = input_args_p->device; 813 } 814 815 /* 816 * Loop through all valid bus / dev / func combinations to check for 817 * all devices, with the following exceptions: 818 * 819 * When nothing is found at function 0 of a bus / dev combination, skip 820 * the other functions of that bus / dev combination. 821 * 822 * When a found device's function 0 is probed and it is determined that 823 * it is not a multifunction device, skip probing of that device's 824 * other functions. 825 */ 826 for (bus = first_bus; ((bus <= last_bus) && (rval == SUCCESS)); bus++) { 827 prg.bus_no = bus; 828 829 /* Device number explicitly specified. */ 830 if (input_args_p->flags & DEV_SPEC_FLAG) { 831 first_dev = last_dev = input_args_p->device; 832 } else if (supports_ari(fd, bus) == SUCCESS) { 833 last_dev = 0; 834 first_dev = 0; 835 } else { 836 last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT; 837 } 838 839 for (dev = first_dev; 840 ((dev <= last_dev) && (rval == SUCCESS)); dev++) { 841 prg.dev_no = dev; 842 rval = probe_dev(fd, &prg, input_args_p); 843 } 844 845 /* 846 * Ultra-45 southbridge workaround: 847 * ECANCELED tells to skip to the next bus. 848 */ 849 if (rval == ECANCELED) { 850 rval = SUCCESS; 851 } 852 } 853 854 return (rval); 855 } 856 857 /* 858 * This function is called-back from di_walk_minor() when any PROBE is processed 859 */ 860 /*ARGSUSED*/ 861 static int 862 process_nexus_node(di_node_t di_node, di_minor_t minor, void *arg) 863 { 864 int fd; 865 char *trunc; 866 probe_walk_args_t *walk_args_p = (probe_walk_args_t *)arg; 867 char *pathname = walk_args_p->pathname; 868 char *nexus_path = di_devfs_minor_path(minor); 869 870 if (nexus_path == NULL) { 871 (void) fprintf(stderr, "Error getting nexus path: %s\n", 872 strerror(errno)); 873 return (DI_WALK_CONTINUE); 874 } 875 876 /* 877 * Display this node if pathname not specified (as all nodes are 878 * displayed) or if the current node matches the single specified 879 * pathname. Pathname form: xxx, nexus form: xxx:reg 880 */ 881 if ((pathname != NULL) && 882 ((strstr(nexus_path, pathname) != nexus_path) || 883 (strlen(nexus_path) != 884 (strlen(pathname) + strlen(PCI_MINOR_REG) + 1)))) { 885 di_devfs_path_free(nexus_path); 886 return (DI_WALK_CONTINUE); 887 } 888 889 if ((fd = open_node(nexus_path, walk_args_p->input_args_p)) >= 0) { 890 891 /* Strip off the suffix at the end of the nexus path. */ 892 if ((trunc = strstr(nexus_path, PCI_MINOR_REG)) != NULL) { 893 trunc--; /* Get the : just before too. */ 894 *trunc = '\0'; 895 } 896 897 /* Show header only if no explicit nexus node name given. */ 898 (void) puts(""); 899 if (pathname == NULL) { 900 (void) printf("********** Devices in tree under %s " 901 "**********\n", nexus_path); 902 } 903 904 /* 905 * Exit silently with ENXIO as this means that there are 906 * no devices under the pci root nexus. 907 */ 908 if ((do_probe(fd, di_node, walk_args_p->di_phdl, 909 walk_args_p->input_args_p) != SUCCESS) && 910 (errno != ENXIO)) { 911 (void) fprintf(stderr, "Error probing node %s: %s\n", 912 nexus_path, strerror(errno)); 913 } 914 915 (void) close(fd); 916 } 917 di_devfs_path_free(nexus_path); 918 919 /* 920 * If node was explicitly specified, it has just been displayed 921 * and no more looping is required. 922 * Otherwise, keep looping for more nodes. 923 */ 924 return ((pathname == NULL) ? DI_WALK_CONTINUE : DI_WALK_TERMINATE); 925 } 926 927 928 /* 929 * Start of probe. If pathname is NULL, search all devices. 930 * 931 * di_walk_minor() walks all DDI_NT_REGACC (PCItool register access) nodes 932 * and calls process_nexus_node on them. process_nexus_node will then check 933 * the pathname for a match, unless it is NULL which works like a wildcard. 934 */ 935 static int 936 do_probe_walk(pcitool_uiargs_t *input_args_p, char *pathname) 937 { 938 di_node_t di_node; 939 di_prom_handle_t di_phdl = DI_PROM_HANDLE_NIL; 940 probe_walk_args_t walk_args; 941 942 int rval = SUCCESS; 943 944 if ((di_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 945 (void) fprintf(stderr, "di_init() failed: %s\n", 946 strerror(errno)); 947 rval = errno; 948 949 } else if ((input_args_p->flags & PROBERNG_FLAG) && 950 ((di_phdl = di_prom_init()) == DI_PROM_HANDLE_NIL)) { 951 (void) fprintf(stderr, "di_prom_init failed: %s\n", 952 strerror(errno)); 953 rval = errno; 954 955 } else { 956 walk_args.input_args_p = input_args_p; 957 walk_args.di_phdl = di_phdl; 958 walk_args.pathname = pathname; 959 (void) di_walk_minor(di_node, DDI_NT_REGACC, 0, 960 &walk_args, process_nexus_node); 961 } 962 963 if (di_phdl != DI_PROM_HANDLE_NIL) { 964 di_prom_fini(di_phdl); 965 } 966 967 if (di_node != DI_NODE_NIL) { 968 di_fini(di_node); 969 } 970 971 return (rval); 972 } 973 974 975 /* **************** Byte dump specific **************** */ 976 977 static void 978 print_bytedump_header(boolean_t do_chardump) 979 { 980 static char header1[] = {" " 981 "0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00"}; 982 static char header2[] = {" " 983 "-----------------------------------------------"}; 984 static char cheader1[] = {" 0123456789ABCDEF"}; 985 static char cheader2[] = {" ----------------"}; 986 987 (void) puts(""); 988 (void) printf(header1); 989 if (do_chardump) { 990 (void) printf(cheader1); 991 } 992 (void) puts(""); 993 (void) printf(header2); 994 if (do_chardump) { 995 (void) printf(cheader2); 996 } 997 } 998 999 1000 /* Number of bytes per line in a dump. */ 1001 #define DUMP_BUF_SIZE 16 1002 #define LINES_BTWN_HEADER 16 1003 1004 /* 1005 * Retrieve several bytes over several reads, and print a formatted byte-dump 1006 * 1007 * fd is the nexus by which device is accessed. 1008 * prg provided has bus, dev, func, bank, initial offset already specified, 1009 * as well as size and endian attributes. 1010 * 1011 * No checking is made that this is a read operation, although only read 1012 * operations are allowed. 1013 */ 1014 static int 1015 bytedump_get(int fd, int cmd, pcitool_reg_t *prg_p, 1016 pcitool_uiargs_t *input_args_p) 1017 { 1018 typedef union { 1019 uint8_t bytes[DUMP_BUF_SIZE]; 1020 uint16_t shorts[DUMP_BUF_SIZE / sizeof (uint16_t)]; 1021 uint32_t dwords[DUMP_BUF_SIZE / sizeof (uint32_t)]; 1022 uint64_t longs[DUMP_BUF_SIZE / sizeof (uint64_t)]; 1023 } buffer_t; 1024 1025 /* 1026 * Local copy of pcitool_reg_t, since offset and phys_addrs are 1027 * modified. 1028 */ 1029 pcitool_reg_t local_prg; 1030 1031 /* Loop parameters. */ 1032 uint32_t dump_end = prg_p->offset + input_args_p->bytedump_amt; 1033 uint32_t dump_curr = prg_p->offset; 1034 1035 int read_size = input_args_p->size; 1036 1037 /* How many stores to the buffer before it is full. */ 1038 int wrap_size = DUMP_BUF_SIZE / read_size; 1039 1040 /* Address prints at the beginning of each line. */ 1041 uint64_t print_addr = 0; 1042 1043 /* Skip this num bytes at the beginning of the first dump. */ 1044 int skip_begin; 1045 1046 /* Skip this num bytes at the end of the last dump. */ 1047 int skip_end = 0; 1048 1049 /* skip_begin and skip_end are needed twice. */ 1050 int skip_begin2; 1051 int skip_end2; 1052 1053 /* Number of lines between headers */ 1054 int lines_since_header = 0; 1055 1056 boolean_t do_chardump = input_args_p->flags & CHARDUMP_FLAG; 1057 boolean_t continue_on_errs = input_args_p->flags & ERRCONT_FLAG; 1058 1059 int rval = SUCCESS; /* Return status. */ 1060 1061 int next; 1062 int i; 1063 1064 buffer_t buffer; 1065 uint16_t error_mask = 0; /* 1 bit/byte in buf. Err when set */ 1066 1067 bzero(buffer.bytes, sizeof (uint8_t) * DUMP_BUF_SIZE); 1068 1069 local_prg = *prg_p; /* Make local copy. */ 1070 1071 /* 1072 * Flip the bytes to proper order if reading on a big endian machine. 1073 * Do this by reading big as little and vs. 1074 */ 1075 #if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG) 1076 local_prg.acc_attr = 1077 (PCITOOL_ACC_IS_BIG_ENDIAN(local_prg.acc_attr) ? 1078 (local_prg.acc_attr & ~PCITOOL_ACC_ATTR_ENDN_BIG) : 1079 (local_prg.acc_attr | PCITOOL_ACC_ATTR_ENDN_BIG)); 1080 #endif 1081 1082 /* 1083 * Get offset into buffer for first store. Assumes the buffer size is 1084 * a multiple of the read size. "next" is the next buffer index to do 1085 * a store. 1086 */ 1087 skip_begin = local_prg.offset % DUMP_BUF_SIZE; 1088 next = skip_begin / read_size; 1089 1090 print_bytedump_header(do_chardump); 1091 1092 while (dump_curr < dump_end) { 1093 1094 /* For reading from the next location. */ 1095 local_prg.offset = dump_curr; 1096 1097 /* Access the device. Abort on error. */ 1098 if (((rval = ioctl(fd, cmd, &local_prg)) != SUCCESS) && 1099 (!(continue_on_errs))) { 1100 if (!(IS_QUIET(input_args_p->flags))) { 1101 (void) fprintf(stderr, 1102 "Ioctl failed:\n errno: %s\n status: %s\n", 1103 strerror(errno), 1104 strstatus(local_prg.status)); 1105 } 1106 break; 1107 } 1108 1109 /* 1110 * Initialize print_addr first time through, in case printing 1111 * is starting in the middle of the buffer. Also reinitialize 1112 * when wrap. 1113 */ 1114 if (print_addr == 0) { 1115 1116 /* 1117 * X86 config space doesn't return phys addr. 1118 * Use offset instead in this case. 1119 */ 1120 if (local_prg.phys_addr == 0) { /* No phys addr ret */ 1121 print_addr = local_prg.offset - 1122 (local_prg.offset % DUMP_BUF_SIZE); 1123 } else { 1124 print_addr = local_prg.phys_addr - 1125 (local_prg.phys_addr % DUMP_BUF_SIZE); 1126 } 1127 } 1128 1129 /* 1130 * Read error occurred. 1131 * Shift the right number of error bits ((1 << read_size) - 1) 1132 * into the right place (next * read_size) 1133 */ 1134 if (rval != SUCCESS) { /* Read error occurred */ 1135 error_mask |= 1136 ((1 << read_size) - 1) << (next * read_size); 1137 1138 } else { /* Save data to the buffer. */ 1139 1140 switch (read_size) { 1141 case 1: 1142 buffer.bytes[next] = (uint8_t)local_prg.data; 1143 break; 1144 case 2: 1145 buffer.shorts[next] = (uint16_t)local_prg.data; 1146 break; 1147 case 4: 1148 buffer.dwords[next] = (uint32_t)local_prg.data; 1149 break; 1150 case 8: 1151 buffer.longs[next] = (uint64_t)local_prg.data; 1152 break; 1153 default: 1154 rval = EIO; 1155 break; 1156 } 1157 } 1158 next++; 1159 1160 /* Increment index for next store, and wrap. */ 1161 next %= wrap_size; 1162 dump_curr += read_size; 1163 1164 /* Zero out the remainder of the buffer if done. */ 1165 if (dump_curr >= dump_end) { 1166 if (next != 0) { 1167 bzero(&buffer.bytes[next * read_size], 1168 (wrap_size - next) * read_size); 1169 skip_end = (wrap_size - next) * read_size; 1170 next = 0; /* For printing below. */ 1171 } 1172 } 1173 1174 /* Dump the buffer if full or if done. */ 1175 if (next == 0) { 1176 1177 skip_begin2 = skip_begin; 1178 skip_end2 = skip_end; 1179 1180 (void) printf("\n0x%16.16" PRIx64 ":", print_addr); 1181 for (i = DUMP_BUF_SIZE - 1; i >= 0; i--) { 1182 if (skip_end) { 1183 skip_end--; 1184 (void) printf(" --"); 1185 } else if (skip_begin > i) { 1186 skip_begin--; 1187 (void) printf(" --"); 1188 } else if (error_mask & (1 << i)) { 1189 (void) printf(" XX"); 1190 } else { 1191 (void) printf(" %2.2x", 1192 buffer.bytes[i]); 1193 } 1194 } 1195 1196 if (do_chardump) { 1197 (void) putchar(' '); 1198 for (i = 0; i < DUMP_BUF_SIZE; i++) { 1199 if (skip_begin2) { 1200 skip_begin2--; 1201 (void) printf("-"); 1202 } else if ( 1203 (DUMP_BUF_SIZE - skip_end2) <= i) { 1204 (void) printf("-"); 1205 } else if (error_mask & (1 << i)) { 1206 (void) putchar('X'); 1207 } else if (isprint(buffer.bytes[i])) { 1208 (void) putchar(buffer.bytes[i]); 1209 } else { 1210 (void) putchar('@'); 1211 } 1212 } 1213 } 1214 1215 if ((++lines_since_header == LINES_BTWN_HEADER) && 1216 (dump_curr < dump_end)) { 1217 lines_since_header = 0; 1218 (void) puts(""); 1219 print_bytedump_header(do_chardump); 1220 } 1221 1222 print_addr += DUMP_BUF_SIZE; 1223 error_mask = 0; 1224 } 1225 } 1226 (void) printf("\n"); 1227 1228 return (rval); 1229 } 1230 1231 1232 /* ************** Device and nexus access commands ************** */ 1233 1234 /* 1235 * Helper function to set access attributes. Assumes size is valid. 1236 */ 1237 static uint32_t 1238 set_acc_attr(pcitool_uiargs_t *input_args_p) 1239 { 1240 uint32_t access_attrs; 1241 1242 switch (input_args_p->size) { 1243 case 1: 1244 access_attrs = PCITOOL_ACC_ATTR_SIZE_1; 1245 break; 1246 case 2: 1247 access_attrs = PCITOOL_ACC_ATTR_SIZE_2; 1248 break; 1249 case 4: 1250 access_attrs = PCITOOL_ACC_ATTR_SIZE_4; 1251 break; 1252 case 8: 1253 access_attrs = PCITOOL_ACC_ATTR_SIZE_8; 1254 break; 1255 } 1256 1257 if (input_args_p->big_endian) { 1258 access_attrs |= PCITOOL_ACC_ATTR_ENDN_BIG; 1259 } 1260 1261 return (access_attrs); 1262 } 1263 1264 static int 1265 do_single_access(int fd, int cmd, pcitool_reg_t *prg_p, 1266 pcitool_uiargs_t *input_args_p) 1267 { 1268 boolean_t is_write = B_FALSE; 1269 int rval; 1270 1271 switch (cmd) { 1272 case PCITOOL_NEXUS_SET_REG: 1273 case PCITOOL_DEVICE_SET_REG: 1274 is_write = B_TRUE; 1275 break; 1276 default: 1277 break; 1278 } 1279 1280 /* Do the access. Return on error. */ 1281 if ((rval = ioctl(fd, cmd, prg_p)) != SUCCESS) { 1282 if (!(IS_QUIET(input_args_p->flags))) { 1283 (void) fprintf(stderr, 1284 "%s ioctl failed:\n errno: %s\n status: %s\n", 1285 is_write ? "write" : "read", 1286 strerror(errno), strstatus(prg_p->status)); 1287 } 1288 1289 return (rval); 1290 } 1291 1292 /* Print on all verbose requests. */ 1293 if (IS_VERBOSE(input_args_p->flags)) { 1294 1295 /* 1296 * Return offset on platforms which return phys_addr == 0 1297 * for config space. 1298 */ 1299 if (prg_p->phys_addr == 0) 1300 prg_p->phys_addr = input_args_p->offset; 1301 1302 (void) printf("Addr:0x%" PRIx64 ", %d-byte %s endian " 1303 "register value: 0x%" PRIx64 "\n", 1304 prg_p->phys_addr, input_args_p->size, 1305 (input_args_p->big_endian ? "big" : "little"), prg_p->data); 1306 1307 /* Non-verbose, read requests. */ 1308 } else if (!(is_write)) { 1309 (void) printf("0x%" PRIx64 "\n", prg_p->data); 1310 } 1311 1312 return (rval); 1313 } 1314 1315 1316 /* 1317 * fd is the file descriptor of the nexus to access, either to get its 1318 * registers or to access a device through that nexus. 1319 * 1320 * input args are commandline arguments specified by the user. 1321 */ 1322 static int 1323 do_device_or_nexus(int fd, pcitool_uiargs_t *input_args_p) 1324 { 1325 pcitool_reg_t prg; /* Request details given to the driver. */ 1326 uint32_t write_cmd = 0; /* Command given to the driver. */ 1327 uint32_t read_cmd = 0; /* Command given to the driver. */ 1328 int rval = SUCCESS; /* Return status. */ 1329 1330 if (input_args_p->flags & WRITE_FLAG) { 1331 prg.data = input_args_p->write_value; 1332 if (input_args_p->flags & NEXUS_FLAG) { 1333 write_cmd = PCITOOL_NEXUS_SET_REG; 1334 } else { 1335 write_cmd = PCITOOL_DEVICE_SET_REG; 1336 } 1337 } 1338 if (input_args_p->flags & READ_FLAG) { 1339 if (input_args_p->flags & NEXUS_FLAG) { 1340 read_cmd = PCITOOL_NEXUS_GET_REG; 1341 } else { 1342 read_cmd = PCITOOL_DEVICE_GET_REG; 1343 } 1344 } 1345 1346 /* Finish initializing access details for driver. */ 1347 1348 /* 1349 * For nexus, barnum is the exact bank number, unless it is 0xFF, which 1350 * indicates that it is inactive and a base_address should be read from 1351 * the input_args instead. 1352 * 1353 * For devices, barnum is the offset to the desired BAR, or 0 for 1354 * config space. 1355 */ 1356 if ((input_args_p->flags & (BASE_SPEC_FLAG | NEXUS_FLAG)) == 1357 (BASE_SPEC_FLAG | NEXUS_FLAG)) { 1358 prg.barnum = PCITOOL_BASE; 1359 prg.phys_addr = input_args_p->base_address; 1360 } else 1361 prg.barnum = input_args_p->bank; 1362 1363 prg.offset = input_args_p->offset; 1364 prg.acc_attr = set_acc_attr(input_args_p); 1365 prg.bus_no = input_args_p->bus; 1366 prg.dev_no = input_args_p->device; 1367 prg.func_no = input_args_p->function; 1368 prg.user_version = PCITOOL_VERSION; 1369 1370 do { 1371 /* Do a bytedump if desired, or else do single ioctl access. */ 1372 if (input_args_p->flags & BYTEDUMP_FLAG) { 1373 1374 if (IS_VERBOSE(input_args_p->flags)) { 1375 (void) printf( 1376 "\nDoing %d-byte %s endian reads:", 1377 input_args_p->size, 1378 input_args_p->big_endian ? 1379 "big" : "little"); 1380 } 1381 rval = bytedump_get(fd, read_cmd, &prg, input_args_p); 1382 1383 } else { 1384 1385 /* Single write and/or read. */ 1386 if (write_cmd != 0) { 1387 rval = do_single_access( 1388 fd, write_cmd, &prg, input_args_p); 1389 } 1390 1391 if ((rval == SUCCESS) && (read_cmd != 0)) { 1392 rval = do_single_access( 1393 fd, read_cmd, &prg, input_args_p); 1394 } 1395 } 1396 } while ((IS_LOOP(input_args_p->flags)) && (rval == SUCCESS) && 1397 (keep_looping)); 1398 1399 return (rval != SUCCESS ? errno : SUCCESS); 1400 } 1401 1402 /* *************** Interrupt routing ************** */ 1403 1404 /* 1405 * Display interrupt information. 1406 * iget is filled in with the info to display 1407 */ 1408 static void 1409 print_intr_info(pcitool_intr_get_t *iget_p) 1410 { 1411 int i; 1412 1413 if (iget_p->flags & PCITOOL_INTR_FLAG_GET_MSI) 1414 (void) printf("\nmsi 0x%x mapped to cpu 0x%x\n", 1415 iget_p->msi, iget_p->cpu_id); 1416 else 1417 (void) printf("\nino 0x%x mapped to cpu 0x%x\n", 1418 iget_p->ino, iget_p->cpu_id); 1419 1420 for (i = 0; i < iget_p->num_devs; i++) { 1421 (void) printf("Device: %s\n", iget_p->dev[i].path); 1422 (void) printf(" Driver: %s, instance %d\n", 1423 iget_p->dev[i].driver_name, iget_p->dev[i].dev_inst); 1424 } 1425 } 1426 1427 /* 1428 * Interrupt command support. 1429 * 1430 * fd is the file descriptor of the nexus being probed. 1431 * input_args are commandline options entered by the user. 1432 */ 1433 static int 1434 get_single_interrupt(int fd, pcitool_intr_get_t **iget_pp, 1435 pcitool_uiargs_t *input_args_p) 1436 { 1437 pcitool_intr_get_t *iget_p = *iget_pp; 1438 const char *str_type = NULL; 1439 uint32_t intr; 1440 1441 if (input_args_p->flags & MSI_SPEC_FLAG) { 1442 intr = input_args_p->intr_msi; 1443 str_type = "msi"; 1444 } else { 1445 intr = input_args_p->intr_ino; 1446 str_type = "ino"; 1447 } 1448 1449 /* 1450 * Check if interrupts are active on this ino/msi. Get as much 1451 * device info as there is room for at the moment. If there 1452 * is not enough room for all devices, will call again with a 1453 * larger buffer. 1454 */ 1455 if (ioctl(fd, PCITOOL_DEVICE_GET_INTR, iget_p) != 0) { 1456 /* 1457 * Let EIO errors silently slip through, as 1458 * some inos may not be viewable by design. 1459 * We don't want to stop or print an error for these. 1460 */ 1461 if (errno == EIO) { 1462 return (SUCCESS); 1463 } 1464 1465 if (!(IS_QUIET(input_args_p->flags))) { 1466 (void) fprintf(stderr, "Ioctl to get %s 0x%x " 1467 "info failed: %s\n", str_type, intr, 1468 strerror(errno)); 1469 1470 if (errno != EFAULT) { 1471 (void) fprintf(stderr, "Pcitool status: %s\n", 1472 strstatus(iget_p->status)); 1473 } 1474 } 1475 return (errno); 1476 } 1477 1478 /* Nothing to report for this interrupt. */ 1479 if (iget_p->num_devs == 0) { 1480 return (SUCCESS); 1481 } 1482 1483 /* Need more room to return additional device info. */ 1484 if (iget_p->num_devs_ret < iget_p->num_devs) { 1485 iget_p = *iget_pp = 1486 realloc(iget_p, PCITOOL_IGET_SIZE(iget_p->num_devs)); 1487 iget_p->num_devs_ret = iget_p->num_devs; 1488 1489 if (ioctl(fd, PCITOOL_DEVICE_GET_INTR, iget_p) != 0) { 1490 if (!(IS_QUIET(input_args_p->flags))) { 1491 (void) fprintf(stderr, "Ioctl to get %s 0x%x" 1492 "device info failed: %s\n", str_type, 1493 intr, strerror(errno)); 1494 if (errno != EFAULT) { 1495 (void) fprintf(stderr, 1496 "Pcitool status: %s\n", 1497 strstatus(iget_p->status)); 1498 } 1499 } 1500 return (errno); 1501 } 1502 } 1503 1504 print_intr_info(iget_p); 1505 return (SUCCESS); 1506 } 1507 1508 #define INIT_NUM_DEVS 0 1509 1510 static int 1511 get_interrupts(int fd, pcitool_uiargs_t *input_args_p) 1512 { 1513 int rval = SUCCESS; /* Return status. */ 1514 1515 /* 1516 * Start with a struct with space for info of INIT_NUM_DEVS devs 1517 * to be returned. 1518 */ 1519 pcitool_intr_get_t *iget_p = malloc(PCITOOL_IGET_SIZE(INIT_NUM_DEVS)); 1520 1521 iget_p->num_devs_ret = INIT_NUM_DEVS; 1522 iget_p->user_version = PCITOOL_VERSION; 1523 1524 /* Explicit MSI requested. */ 1525 if (input_args_p->flags & MSI_SPEC_FLAG) { 1526 iget_p->msi = input_args_p->intr_msi; 1527 iget_p->flags = PCITOOL_INTR_FLAG_GET_MSI; 1528 rval = get_single_interrupt(fd, &iget_p, input_args_p); 1529 /* Return all MSIs. */ 1530 } else if (input_args_p->flags & MSI_ALL_FLAG) { 1531 pcitool_intr_info_t intr_info; 1532 intr_info.flags = PCITOOL_INTR_FLAG_GET_MSI; 1533 1534 if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) { 1535 if (!(IS_QUIET(input_args_p->flags))) { 1536 (void) fprintf(stderr, 1537 "intr info ioctl failed: %s\n", 1538 strerror(errno)); 1539 } 1540 } else { 1541 int msi; 1542 1543 /* 1544 * Search through all interrupts. 1545 * Display info on enabled ones. 1546 */ 1547 for (msi = 0; 1548 ((msi < intr_info.num_intr) && (rval == SUCCESS)); 1549 msi++) { 1550 bzero(iget_p, sizeof (pcitool_intr_get_t)); 1551 iget_p->num_devs_ret = INIT_NUM_DEVS; 1552 iget_p->user_version = PCITOOL_VERSION; 1553 iget_p->flags = PCITOOL_INTR_FLAG_GET_MSI; 1554 iget_p->msi = msi; 1555 rval = get_single_interrupt( 1556 fd, &iget_p, input_args_p); 1557 } 1558 } 1559 /* Explicit INO requested. */ 1560 } else if (input_args_p->flags & INO_SPEC_FLAG) { 1561 iget_p->ino = input_args_p->intr_ino; 1562 rval = get_single_interrupt(fd, &iget_p, input_args_p); 1563 /* Return all INOs. */ 1564 } else if (input_args_p->flags & INO_ALL_FLAG) { 1565 pcitool_intr_info_t intr_info; 1566 intr_info.flags = 0; 1567 1568 if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) { 1569 if (!(IS_QUIET(input_args_p->flags))) { 1570 (void) fprintf(stderr, 1571 "intr info ioctl failed: %s\n", 1572 strerror(errno)); 1573 } 1574 } else { 1575 int ino; 1576 1577 /* 1578 * Search through all interrupts. 1579 * Display info on enabled ones. 1580 */ 1581 for (ino = 0; 1582 ((ino < intr_info.num_intr) && (rval == SUCCESS)); 1583 ino++) { 1584 bzero(iget_p, sizeof (pcitool_intr_get_t)); 1585 iget_p->num_devs_ret = INIT_NUM_DEVS; 1586 iget_p->user_version = PCITOOL_VERSION; 1587 iget_p->ino = ino; 1588 rval = get_single_interrupt( 1589 fd, &iget_p, input_args_p); 1590 } 1591 } 1592 } 1593 1594 free(iget_p); 1595 1596 return (rval); 1597 } 1598 1599 1600 static int 1601 get_interrupt_ctlr(int fd, pcitool_uiargs_t *input_args_p) 1602 { 1603 pcitool_intr_info_t intr_info; 1604 char *ctlr_type = NULL; 1605 int rval = SUCCESS; 1606 1607 intr_info.flags = 0; 1608 if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) { 1609 if (!(IS_QUIET(input_args_p->flags))) { 1610 (void) perror("Ioctl to get intr ctlr info failed"); 1611 } 1612 rval = errno; 1613 1614 } else { 1615 (void) fputs("Controller type: ", stdout); 1616 switch (intr_info.ctlr_type) { 1617 case PCITOOL_CTLR_TYPE_RISC: 1618 ctlr_type = "RISC"; 1619 break; 1620 case PCITOOL_CTLR_TYPE_UPPC: 1621 ctlr_type = "UPPC"; 1622 break; 1623 case PCITOOL_CTLR_TYPE_PCPLUSMP: 1624 ctlr_type = "PCPLUSMP"; 1625 break; 1626 default: 1627 break; 1628 } 1629 1630 if (ctlr_type == NULL) { 1631 (void) printf("Unknown or new (%d)", 1632 intr_info.ctlr_type); 1633 } else { 1634 (void) fputs(ctlr_type, stdout); 1635 } 1636 1637 #ifdef __x86 1638 if (intr_info.ctlr_type == PCITOOL_CTLR_TYPE_PCPLUSMP) 1639 (void) printf(", IO APIC version: 0x%x, " 1640 "local APIC version: 0x%x\n", 1641 PSMAT_IO_APIC_VER(intr_info.ctlr_version), 1642 PSMAT_LOCAL_APIC_VER(intr_info.ctlr_version)); 1643 else 1644 #endif /* __x86 */ 1645 (void) printf(", version: %2.2x.%2.2x.%2.2x.%2.2x\n", 1646 ((intr_info.ctlr_version >> 24) & 0xff), 1647 ((intr_info.ctlr_version >> 16) & 0xff), 1648 ((intr_info.ctlr_version >> 8) & 0xff), 1649 (intr_info.ctlr_version & 0xff)); 1650 } 1651 1652 return (rval); 1653 } 1654 1655 /* 1656 * 1657 * fd is the file descriptor of the nexus being changed. 1658 * input_args are commandline options entered by the user. 1659 */ 1660 static int 1661 set_interrupts(int fd, pcitool_uiargs_t *input_args_p) 1662 { 1663 pcitool_intr_set_t iset; 1664 const char *str_type = NULL; 1665 uint32_t intr; 1666 int rval = SUCCESS; /* Return status. */ 1667 1668 /* Load interrupt number and cpu from commandline. */ 1669 if (input_args_p->flags & MSI_SPEC_FLAG) { 1670 iset.msi = intr = input_args_p->intr_msi; 1671 iset.flags = PCITOOL_INTR_FLAG_SET_MSI; 1672 str_type = "msi"; 1673 } else { 1674 iset.ino = intr = input_args_p->intr_ino; 1675 iset.flags = 0; 1676 str_type = "ino"; 1677 } 1678 1679 iset.cpu_id = input_args_p->intr_cpu; 1680 iset.user_version = PCITOOL_VERSION; 1681 iset.flags |= (input_args_p->flags & SETGRP_FLAG) ? 1682 PCITOOL_INTR_FLAG_SET_GROUP : 0; 1683 1684 /* Do the deed. */ 1685 if (ioctl(fd, PCITOOL_DEVICE_SET_INTR, &iset) != 0) { 1686 if (!(IS_QUIET(input_args_p->flags))) { 1687 (void) fprintf(stderr, 1688 "Ioctl to set %s 0x%x failed: %s\n", 1689 str_type, intr, strerror(errno)); 1690 (void) fprintf(stderr, "pcitool status: %s\n", 1691 strstatus(iset.status)); 1692 } 1693 rval = errno; 1694 } else { 1695 if (input_args_p->flags & SETGRP_FLAG) { 1696 (void) printf("\nInterrupts on %s group starting " 1697 "at %s 0x%x reassigned:", str_type, str_type, intr); 1698 } else { 1699 (void) printf("\nInterrupts on %s 0x%x reassigned:", 1700 str_type, intr); 1701 } 1702 (void) printf(" Old cpu: 0x%x, New cpu: 0x%x\n", iset.cpu_id, 1703 input_args_p->intr_cpu); 1704 } 1705 1706 return (rval); 1707 } 1708 1709 1710 static int 1711 do_interrupts(int fd, pcitool_uiargs_t *input_args_p) 1712 { 1713 if (input_args_p->flags & READ_FLAG) { 1714 1715 int gic_rval = SUCCESS; 1716 int gi_rval = SUCCESS; 1717 1718 if (input_args_p->flags & SHOWCTLR_FLAG) { 1719 gic_rval = get_interrupt_ctlr(fd, input_args_p); 1720 } 1721 1722 gi_rval = get_interrupts(fd, input_args_p); 1723 return ((gi_rval != SUCCESS) ? gi_rval : gic_rval); 1724 1725 } else { 1726 1727 return (set_interrupts(fd, input_args_p)); 1728 } 1729 } 1730 1731 1732 /* *********** Where it all begins... ************* */ 1733 1734 int 1735 main(int argc, char **argv) 1736 { 1737 pcitool_uiargs_t input_args; /* Commandline args. */ 1738 int fd; /* Nexus file descriptor. */ 1739 int rval = SUCCESS; /* Return status value. */ 1740 1741 1742 /* Get commandline args and options from user. */ 1743 if (get_commandline_args(argc, argv, &input_args) != SUCCESS) { 1744 return (EINVAL); 1745 } 1746 1747 /* Help. */ 1748 if (!(input_args.flags & ALL_COMMANDS)) 1749 return (SUCCESS); 1750 1751 /* 1752 * Probe mode. 1753 * Nexus is provided as argv[1] unless PROBEALL mode. 1754 */ 1755 if (input_args.flags & PROBE_FLAGS) { 1756 rval = do_probe_walk(&input_args, 1757 ((input_args.flags & PROBEALL_FLAG) ? NULL : argv[1])); 1758 1759 } else if ((fd = open_node(argv[1], &input_args)) >= 0) { 1760 if (input_args.flags & (NEXUS_FLAG | LEAF_FLAG)) { 1761 (void) signal(SIGINT, signal_handler); 1762 (void) signal(SIGTERM, signal_handler); 1763 rval = do_device_or_nexus(fd, &input_args); 1764 } else if (input_args.flags & INTR_FLAG) { 1765 rval = do_interrupts(fd, &input_args); 1766 } else { 1767 /* Should never see this. */ 1768 (void) fprintf(stderr, "Nothing to do.\n"); 1769 rval = ENOTTY; 1770 } 1771 1772 (void) close(fd); 1773 } 1774 1775 return (rval); 1776 } 1777