1 /* 2 * Copyright (c) 2007, Sun Microsystems, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25 /* 26 * Solaris devfs interfaces 27 */ 28 29 #define _GNU_SOURCE 30 31 #include <stdlib.h> 32 #include <strings.h> 33 #include <stdio.h> 34 #include <unistd.h> 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <fcntl.h> 38 #include <sys/mman.h> 39 #include <dirent.h> 40 #include <errno.h> 41 #include <sys/pci.h> 42 #include <assert.h> 43 #include <libdevinfo.h> 44 #include "pci_tools.h" 45 46 #include "pciaccess.h" 47 #include "pciaccess_private.h" 48 49 #define PCI_NEXUS_1 "/devices/pci@0,0:reg" 50 #define MAX_DEVICES 256 51 #define CELL_NUMS_1275 (sizeof(pci_regspec_t)/sizeof(uint_t)) 52 typedef union { 53 uint8_t bytes[16 * sizeof (uint32_t)]; 54 uint32_t dwords[16]; 55 } pci_conf_hdr_t; 56 57 typedef struct i_devnode { 58 uint8_t bus; 59 uint8_t dev; 60 uint8_t func; 61 di_node_t node; 62 }i_devnode_t; 63 64 static int root_fd = -1; 65 static int xsvc_fd = -1; 66 /* 67 * Read config space in native processor endianness. Endian-neutral 68 * processing can then take place. On big endian machines, MSB and LSB 69 * of little endian data end up switched if read as little endian. 70 * They are in correct order if read as big endian. 71 */ 72 #if defined(__sparc) 73 #define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_BIG 74 #elif defined(__x86) 75 #define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_LTL 76 #else 77 #error "ISA is neither __sparc nor __x86" 78 #endif 79 80 /* 81 * Identify problematic southbridges. These have device id 0x5249 and 82 * vendor id 0x10b9. Check for revision ID 0 and class code 060400 as well. 83 * Values are little endian, so they are reversed for SPARC. 84 * 85 * Check for these southbridges on all architectures, as the issue is a 86 * southbridge issue, independent of processor. 87 * 88 * If one of these is found during probing, skip probing other devs/funcs on 89 * the rest of the bus, since the southbridge and all devs underneath will 90 * otherwise disappear. 91 */ 92 #if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG) 93 #define U45_SB_DEVID_VID 0xb9104952 94 #define U45_SB_CLASS_RID 0x00000406 95 #else 96 #define U45_SB_DEVID_VID 0x524910b9 97 #define U45_SB_CLASS_RID 0x06040000 98 #endif 99 100 #define DEBUGON 0 101 102 103 static int pci_device_solx_devfs_map_range(struct pci_device *dev, 104 struct pci_device_mapping *map); 105 106 static int pci_device_solx_devfs_read_rom( struct pci_device * dev, 107 void * buffer ); 108 109 static int pci_device_solx_devfs_probe( struct pci_device * dev ); 110 111 static int pci_device_solx_devfs_read( struct pci_device * dev, void * data, 112 pciaddr_t offset, pciaddr_t size, pciaddr_t * bytes_read ); 113 114 static int pci_device_solx_devfs_write( struct pci_device * dev, 115 const void * data, pciaddr_t offset, pciaddr_t size, 116 pciaddr_t * bytes_wrtten ); 117 118 static int 119 probe_dev(int fd, pcitool_reg_t *prg_p, struct pci_system *pci_sys); 120 121 static int 122 do_probe(int fd, struct pci_system *pci_sys); 123 124 static void 125 pci_system_solx_devfs_destroy( void ); 126 127 static int 128 get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, uint8_t func_no, 129 pci_conf_hdr_t *config_hdr_p); 130 131 int 132 pci_system_solx_devfs_create( void ); 133 134 135 136 137 static const struct pci_system_methods solx_devfs_methods = { 138 .destroy = pci_system_solx_devfs_destroy, 139 .destroy_device = NULL, 140 .read_rom = pci_device_solx_devfs_read_rom, 141 .probe = pci_device_solx_devfs_probe, 142 .map_range = pci_device_solx_devfs_map_range, 143 .unmap_range = pci_device_generic_unmap_range, 144 145 .read = pci_device_solx_devfs_read, 146 .write = pci_device_solx_devfs_write, 147 148 .fill_capabilities = pci_fill_capabilities_generic 149 }; 150 151 /* 152 * Rlease all the resources 153 * Solaris version 154 */ 155 static void 156 pci_system_solx_devfs_destroy( void ) 157 { 158 /* 159 * the memory allocated in create routines 160 * will be freed in pci_system_init 161 * It is more reasonable to free them here 162 */ 163 if (root_fd >= 0) { 164 close(root_fd); 165 root_fd = -1; 166 } 167 168 if (xsvc_fd >= 0) { 169 close(xsvc_fd); 170 xsvc_fd = -1; 171 } 172 173 } 174 /* 175 * Attempt to access PCI subsystem using Solaris's devfs interface. 176 * Solaris version 177 */ 178 int 179 pci_system_solx_devfs_create( void ) 180 { 181 int err = 0; 182 183 184 if (root_fd >= 0) 185 return (err); 186 /* If the directory "/sys/bus/pci/devices" exists, 187 * then the PCI subsystem can be accessed using 188 * this interface. 189 */ 190 if ((root_fd = open(PCI_NEXUS_1, O_RDWR)) == -1) { 191 (void) fprintf(stderr, 192 "Could not open nexus node %s: %s\n", 193 PCI_NEXUS_1, strerror(errno)); 194 195 err = errno; 196 197 return (err); 198 } else { 199 /* 200 * Only allow MAX_DEVICES exists 201 * I will fix it later to get 202 * the total devices first 203 */ 204 if ((pci_sys = calloc(1, sizeof (struct pci_system))) != NULL) { 205 pci_sys->methods = &solx_devfs_methods; 206 if ((pci_sys->devices = 207 calloc(MAX_DEVICES, 208 sizeof (struct pci_device_private))) != NULL) { 209 (void) do_probe(root_fd, pci_sys); 210 } 211 else { 212 err = errno; 213 free(pci_sys); 214 pci_sys = NULL; 215 } 216 } else { 217 err = errno; 218 } 219 220 } 221 222 return (err); 223 } 224 225 /* 226 * Retrieve first 16 dwords of device's config header, except for the first 227 * dword. First 16 dwords are defined by the PCI specification. 228 */ 229 static int 230 get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, uint8_t func_no, 231 pci_conf_hdr_t *config_hdr_p) 232 { 233 pcitool_reg_t cfg_prg; 234 int i; 235 int rval = 0; 236 237 /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */ 238 cfg_prg.offset = 0; 239 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; 240 cfg_prg.bus_no = bus_no; 241 cfg_prg.dev_no = dev_no; 242 cfg_prg.func_no = func_no; 243 cfg_prg.barnum = 0; 244 cfg_prg.user_version = PCITOOL_USER_VERSION; 245 246 /* Get dwords 1-15 of config space. They must be read as uint32_t. */ 247 for (i = 1; i < (sizeof (pci_conf_hdr_t) / sizeof (uint32_t)); i++) { 248 cfg_prg.offset += sizeof (uint32_t); 249 if ((rval = 250 ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != 0) { 251 break; 252 } 253 config_hdr_p->dwords[i] = (uint32_t)cfg_prg.data; 254 } 255 256 return (rval); 257 } 258 259 260 /* 261 * Probe device's functions. Modifies many fields in the prg_p. 262 */ 263 static int 264 probe_dev(int fd, pcitool_reg_t *prg_p, struct pci_system *pci_sys) 265 { 266 pci_conf_hdr_t config_hdr; 267 boolean_t multi_function_device; 268 int8_t func; 269 int8_t first_func = 0; 270 int8_t last_func = PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT; 271 int rval = 0; 272 273 274 /* 275 * Loop through at least func=first_func. Continue looping through 276 * functions if there are no errors and the device is a multi-function 277 * device. 278 * 279 * (Note, if first_func == 0, header will show whether multifunction 280 * device and set multi_function_device. If first_func != 0, then we 281 * will force the loop as the user wants a specific function to be 282 * checked. 283 */ 284 for (func = first_func, multi_function_device = B_FALSE; 285 ((func <= last_func) && 286 ((func == first_func) || (multi_function_device))); 287 func++) { 288 prg_p->func_no = func; 289 290 /* 291 * Four things can happen here: 292 * 293 * 1) ioctl comes back as EFAULT and prg_p->status is 294 * PCITOOL_INVALID_ADDRESS. There is no device at this 295 * location. 296 * 297 * 2) ioctl comes back successful and the data comes back as 298 * zero. Config space is mapped but no device responded. 299 * 300 * 3) ioctl comes back successful and the data comes back as 301 * non-zero. We've found a device. 302 * 303 * 4) Some other error occurs in an ioctl. 304 */ 305 306 prg_p->status = PCITOOL_SUCCESS; 307 prg_p->offset = 0; 308 prg_p->data = 0; 309 prg_p->user_version = PCITOOL_USER_VERSION; 310 if (((rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, prg_p)) != 0) || 311 (prg_p->data == 0xffffffff)) { 312 313 /* 314 * Accept errno == EINVAL along with status of 315 * PCITOOL_OUT_OF_RANGE because some systems 316 * don't implement the full range of config space. 317 * Leave the loop quietly in this case. 318 */ 319 if ((errno == EINVAL) || 320 (prg_p->status == PCITOOL_OUT_OF_RANGE)) { 321 break; 322 } 323 324 /* 325 * Exit silently with ENXIO as this means that there are 326 * no devices under the pci root nexus. 327 */ 328 else if ((errno == ENXIO) && 329 (prg_p->status == PCITOOL_IO_ERROR)) { 330 break; 331 } 332 333 /* 334 * Expect errno == EFAULT along with status of 335 * PCITOOL_INVALID_ADDRESS because there won't be 336 * devices at each stop. Quit on any other error. 337 */ 338 else if (((errno != EFAULT) || 339 (prg_p->status != PCITOOL_INVALID_ADDRESS)) && 340 (prg_p->data != 0xffffffff)) { 341 342 break; 343 344 /* 345 * If no function at this location, 346 * just advance to the next function. 347 */ 348 } else { 349 rval = 0; 350 } 351 352 /* 353 * Data came back as 0. 354 * Treat as unresponsive device amd check next device. 355 */ 356 } else if (prg_p->data == 0) { 357 rval = 0; 358 break; /* Func loop. */ 359 360 /* Found something. */ 361 } else { 362 config_hdr.dwords[0] = (uint32_t)prg_p->data; 363 364 /* Get the rest of the PCI header. */ 365 if ((rval = get_config_header(fd, prg_p->bus_no, 366 prg_p->dev_no, prg_p->func_no, &config_hdr)) != 367 0) { 368 break; 369 } 370 371 /* 372 * Special case for the type of Southbridge found on 373 * Ultra-45 and other sun4u fire workstations. 374 */ 375 if ((config_hdr.dwords[0] == U45_SB_DEVID_VID) && 376 (config_hdr.dwords[2] == U45_SB_CLASS_RID)) { 377 rval = ECANCELED; 378 break; 379 } 380 381 /* 382 * Found one device with bus numer, device number and 383 * function number. 384 */ 385 386 /* 387 * Domain is peer bus?? 388 */ 389 pci_sys->devices[pci_sys->num_devices].base.domain = 0; 390 pci_sys->devices[pci_sys->num_devices].base.bus = 391 prg_p->bus_no; 392 pci_sys->devices[pci_sys->num_devices].base.dev = 393 prg_p->dev_no; 394 pci_sys->devices[pci_sys->num_devices].base.func = func; 395 /* 396 * for the format of device_class, see struct pci_device; 397 */ 398 pci_sys->devices[pci_sys->num_devices].base.device_class = 399 config_hdr.dwords[2]>>8; 400 pci_sys->devices[pci_sys->num_devices].base.revision = 401 (uint8_t)(config_hdr.dwords[2] & 0xff); 402 pci_sys->devices[pci_sys->num_devices].base.vendor_id = 403 (uint16_t)(config_hdr.dwords[0] & 0xffff); 404 pci_sys->devices[pci_sys->num_devices].base.device_id = 405 (uint16_t)((config_hdr.dwords[0]>>16) & 0xffff); 406 pci_sys->devices[pci_sys->num_devices].base.subvendor_id = 407 (uint16_t)(config_hdr.dwords[11] & 0xffff); 408 pci_sys->devices[pci_sys->num_devices].base.subdevice_id = 409 (uint16_t)((config_hdr.dwords[11]>>16) & 0xffff); 410 pci_sys->devices[pci_sys->num_devices].header_type = 411 (uint8_t)(((config_hdr.dwords[3])&0xff0000)>>16); 412 #if DEBUGON 413 fprintf(stderr, "busno = %x, devno = %x, funcno = %x\n", 414 prg_p->bus_no, prg_p->dev_no, func); 415 #endif 416 417 pci_sys->num_devices++; 418 419 /* 420 * Accomodate devices which state their 421 * multi-functionality only in their function 0 config 422 * space. Note multi-functionality throughout probing 423 * of all of this device's functions. 424 */ 425 if (config_hdr.bytes[PCI_CONF_HEADER] & 426 PCI_HEADER_MULTI) { 427 multi_function_device = B_TRUE; 428 } 429 } 430 } 431 432 return (rval); 433 } 434 435 /* 436 * Solaris version 437 * Probe a given nexus config space for devices. 438 * 439 * fd is the file descriptor of the nexus. 440 * input_args contains commandline options as specified by the user. 441 */ 442 static int 443 do_probe(int fd, struct pci_system *pci_sys) 444 { 445 pcitool_reg_t prg; 446 uint32_t bus; 447 uint8_t dev; 448 uint32_t last_bus = PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT; 449 uint8_t last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT; 450 uint8_t first_bus = 0; 451 uint8_t first_dev = 0; 452 int rval = 0; 453 454 prg.barnum = 0; /* Config space. */ 455 456 /* Must read in 4-byte quantities. */ 457 prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; 458 459 prg.data = 0; 460 461 /* 462 * Loop through all valid bus / dev / func combinations to check for 463 * all devices, with the following exceptions: 464 * 465 * When nothing is found at function 0 of a bus / dev combination, skip 466 * the other functions of that bus / dev combination. 467 * 468 * When a found device's function 0 is probed and it is determined that 469 * it is not a multifunction device, skip probing of that device's 470 * other functions. 471 */ 472 for (bus = first_bus; ((bus <= last_bus) && (rval == 0)); bus++) { 473 prg.bus_no = (uint8_t)bus; 474 for (dev = first_dev; 475 ((dev <= last_dev) && (rval == 0)); dev++) { 476 prg.dev_no = dev; 477 rval = probe_dev(fd, &prg, pci_sys); 478 } 479 480 /* 481 * Ultra-45 southbridge workaround: 482 * ECANCELED tells to skip to the next bus. 483 */ 484 if (rval == ECANCELED) { 485 rval = 0; 486 } 487 } 488 if (pci_sys->num_devices > MAX_DEVICES) { 489 (void) fprintf(stderr, "pci devices reach maximu number\n"); 490 } 491 492 return (rval); 493 } 494 495 static int 496 find_target_node(di_node_t node, void *arg) 497 { 498 int *regbuf = NULL; 499 int len = 0; 500 uint32_t busno, funcno, devno; 501 i_devnode_t *devnode; 502 void *prop = DI_PROP_NIL; 503 int i; 504 505 devnode = (i_devnode_t *)arg; 506 507 /* 508 * Test the property funtions, only for testing 509 */ 510 /* 511 (void) fprintf(stderr, "start of node 0x%x\n", node->nodeid); 512 while ((prop = di_prop_hw_next(node, prop)) != DI_PROP_NIL) { 513 (void) fprintf(stderr, "name=%s: ", di_prop_name(prop)); 514 len = 0; 515 if (!strcmp(di_prop_name(prop), "reg")) { 516 len = di_prop_ints(prop, ®buf); 517 } 518 for (i = 0; i < len; i++) { 519 fprintf(stderr, "0x%0x.", regbuf[i]); 520 } 521 fprintf(stderr, "\n"); 522 } 523 (void) fprintf(stderr, "end of node 0x%x\n", node->nodeid); 524 */ 525 526 len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", 527 ®buf); 528 529 if (len <= 0) { 530 #if DEBUGON 531 fprintf(stderr, "error = %x\n", errno); 532 fprintf(stderr, "can not find assigned-address\n"); 533 #endif 534 return (DI_WALK_CONTINUE); 535 } 536 busno = PCI_REG_BUS_G(regbuf[0]); 537 devno = PCI_REG_DEV_G(regbuf[0]); 538 funcno = PCI_REG_FUNC_G(regbuf[0]); 539 540 if ((busno == devnode->bus) && 541 (devno == devnode->dev) && 542 (funcno == devnode->func)) { 543 devnode->node = node; 544 545 return (DI_WALK_TERMINATE); 546 } 547 548 return (DI_WALK_CONTINUE); 549 } 550 551 /* 552 * Solaris version 553 */ 554 static int 555 pci_device_solx_devfs_probe( struct pci_device * dev ) 556 { 557 uint8_t config[256]; 558 int err; 559 di_node_t rnode; 560 i_devnode_t args; 561 int *regbuf; 562 pci_regspec_t *reg; 563 int i; 564 pciaddr_t bytes; 565 int len = 0; 566 567 err = pci_device_solx_devfs_read( dev, config, 0, 256, & bytes ); 568 args.node = DI_NODE_NIL; 569 if ( bytes >= 64 ) { 570 struct pci_device_private *priv = 571 (struct pci_device_private *) dev; 572 573 dev->vendor_id = 574 (uint16_t)config[0] + ((uint16_t)config[1] << 8); 575 dev->device_id = 576 (uint16_t)config[2] + ((uint16_t)config[3] << 8); 577 dev->device_class = (uint32_t)config[9] + 578 ((uint32_t)config[10] << 8) + 579 ((uint16_t)config[11] << 16); 580 /* 581 * device class code is already there. 582 * see probe_dev function. 583 */ 584 dev->revision = config[8]; 585 dev->subvendor_id = 586 (uint16_t)config[44] + ((uint16_t)config[45] << 8); 587 dev->subdevice_id = 588 (uint16_t)config[46] + ((uint16_t)config[47] << 8); 589 dev->irq = config[60]; 590 591 priv->header_type = config[14]; 592 /* 593 * starting to find if it is MEM/MEM64/IO 594 * using libdevinfo 595 */ 596 if ((rnode = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 597 (void) fprintf(stderr, "di_init failed: %s\n", 598 strerror(errno)); 599 err = errno; 600 } else { 601 args.bus = dev->bus; 602 args.dev = dev->dev; 603 args.func = dev->func; 604 (void) di_walk_node(rnode, DI_WALK_CLDFIRST, 605 (void *)&args, find_target_node); 606 di_fini(rnode); 607 } 608 } 609 if (args.node != DI_NODE_NIL) { 610 /* 611 * It will success for sure, because it was 612 * successfully called in find_target_node 613 */ 614 len = di_prop_lookup_ints(DDI_DEV_T_ANY, args.node, 615 "assigned-addresses", 616 ®buf); 617 618 } 619 620 if (len <= 0) 621 return (err); 622 623 624 /* 625 * how to find the size of rom??? 626 * if the device has expansion rom, 627 * it must be listed in the last 628 * cells because solaris find probe 629 * the base address from offset 0x10 630 * to 0x30h. So only check the last 631 * item. 632 */ 633 reg = (pci_regspec_t *)®buf[len - CELL_NUMS_1275]; 634 if (PCI_REG_REG_G(reg->pci_phys_hi) == 635 PCI_CONF_ROM) { 636 /* 637 * rom can only be 32 bits 638 */ 639 dev->rom_size = reg->pci_size_low; 640 len = len - CELL_NUMS_1275; 641 } 642 else { 643 /* 644 * size default to 64K and base address 645 * default to 0xC0000 646 */ 647 dev->rom_size = 0x10000; 648 } 649 650 /* 651 * solaris has its own BAR index. To be sure that 652 * Xorg has the same BAR number as solaris. ???? 653 */ 654 for (i = 0; i < len; i = i + CELL_NUMS_1275) { 655 int ent = i/CELL_NUMS_1275; 656 657 reg = (pci_regspec_t *)®buf[i]; 658 659 /* 660 * non relocatable resource is excluded 661 * such like 0xa0000, 0x3b0. If it is met, 662 * the loop is broken; 663 */ 664 if (!PCI_REG_REG_G(reg->pci_phys_hi)) 665 break; 666 667 668 if (reg->pci_phys_hi & PCI_PREFETCH_B) { 669 dev->regions[ent].is_prefetchable = 1; 670 } 671 672 switch (reg->pci_phys_hi & PCI_REG_ADDR_M) { 673 case PCI_ADDR_IO: 674 dev->regions[ent].is_IO = 1; 675 break; 676 case PCI_ADDR_MEM32: 677 break; 678 case PCI_ADDR_MEM64: 679 dev->regions[ent].is_64 = 1; 680 break; 681 } 682 /* 683 * We split the shift count 32 into two 16 to 684 * avoid the complaining of the compiler 685 */ 686 dev->regions[ent].base_addr = reg->pci_phys_low + 687 ((reg->pci_phys_mid << 16) << 16); 688 dev->regions[ent].size = reg->pci_size_low + 689 ((reg->pci_size_hi << 16) << 16); 690 } 691 692 693 return (err); 694 } 695 696 /* 697 * Solaris version: read the ROM data 698 */ 699 static int 700 pci_device_solx_devfs_read_rom( struct pci_device * dev, void * buffer ) 701 { 702 void *prom = MAP_FAILED; 703 704 if (xsvc_fd < 0) { 705 if ((xsvc_fd = open("/dev/xsvc", O_RDWR)) < 0) { 706 (void) fprintf(stderr, "can not open xsvc driver\n"); 707 708 return (-1); 709 } 710 } 711 712 prom = mmap(NULL, dev->rom_size, 713 PROT_READ, MAP_SHARED, 714 xsvc_fd, 0xC0000); 715 716 if (prom == MAP_FAILED) { 717 (void) fprintf(stderr, "map rom base =0xC0000 failed"); 718 return (-1); 719 } 720 (void) bcopy(prom, buffer, dev->rom_size); 721 722 723 /* 724 * Still used xsvc to do the user space mapping 725 */ 726 return (0); 727 728 } 729 730 /* 731 * solaris version: Read the configurations space of the devices 732 */ 733 static int 734 pci_device_solx_devfs_read( struct pci_device * dev, void * data, 735 pciaddr_t offset, pciaddr_t size, 736 pciaddr_t * bytes_read ) 737 { 738 pcitool_reg_t cfg_prg; 739 int err = 0; 740 int i = 0; 741 742 cfg_prg.offset = offset; 743 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN; 744 cfg_prg.bus_no = dev->bus; 745 cfg_prg.dev_no = dev->dev; 746 cfg_prg.func_no = dev->func; 747 cfg_prg.barnum = 0; 748 cfg_prg.user_version = PCITOOL_USER_VERSION; 749 *bytes_read = 0; 750 751 for (i = 0; i < size; i = i + PCITOOL_ACC_ATTR_SIZE(PCITOOL_ACC_ATTR_SIZE_1)) { 752 753 cfg_prg.offset = offset + i; 754 if ((err = ioctl(root_fd, PCITOOL_DEVICE_GET_REG, 755 &cfg_prg)) != 0) { 756 fprintf(stderr, "read bdf<%x,%x,%x,%llx> config space failure\n", 757 cfg_prg.bus_no, 758 cfg_prg.dev_no, 759 cfg_prg.func_no, 760 cfg_prg.offset); 761 fprintf(stderr, "Failure cause = %x\n", err); 762 break; 763 } 764 765 ((uint8_t *)data)[i] = (uint8_t)cfg_prg.data; 766 /* 767 * DWORDS Offset or bytes Offset ?? 768 */ 769 } 770 *bytes_read = i; 771 772 return (err); 773 } 774 775 /* 776 * Solaris version 777 */ 778 static int 779 pci_device_solx_devfs_write( struct pci_device * dev, const void * data, 780 pciaddr_t offset, pciaddr_t size, 781 pciaddr_t * bytes_written ) 782 { 783 pcitool_reg_t cfg_prg; 784 int err = 0; 785 int cmd; 786 787 788 if ( bytes_written != NULL ) { 789 *bytes_written = 0; 790 } 791 792 cfg_prg.offset = offset; 793 switch (size) { 794 case 1: 795 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN; 796 break; 797 case 2: 798 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_2 + NATIVE_ENDIAN; 799 break; 800 case 4: 801 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN; 802 break; 803 case 8: 804 cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_8 + NATIVE_ENDIAN; 805 break; 806 default: 807 assert(0); 808 809 } 810 cfg_prg.bus_no = dev->bus; 811 cfg_prg.dev_no = dev->dev; 812 cfg_prg.func_no = dev->func; 813 cfg_prg.barnum = 0; 814 cfg_prg.user_version = PCITOOL_USER_VERSION; 815 cfg_prg.data = *((uint64_t *)data); 816 /* 817 * Check if this device is bridge device. 818 * If it is, it is also a nexus node??? 819 * It seems that there is no explicit 820 * PCI nexus device for X86, so not applicable 821 * from pcitool_bus_reg_ops in pci_tools.c 822 */ 823 cmd = PCITOOL_DEVICE_SET_REG; 824 825 if ((err = ioctl(root_fd, cmd, &cfg_prg)) != 0) { 826 return (err); 827 } 828 *bytes_written = size; 829 830 return (err); 831 } 832 833 834 /** 835 * Map a memory region for a device using /dev/xsvc. 836 * 837 * \param dev Device whose memory region is to be mapped. 838 * \param map Parameters of the mapping that is to be created. 839 * 840 * \return 841 * Zero on success or an \c errno value on failure. 842 */ 843 static int 844 pci_device_solx_devfs_map_range(struct pci_device *dev, 845 struct pci_device_mapping *map) 846 { 847 const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0) 848 ? (PROT_READ | PROT_WRITE) : PROT_READ; 849 int err = 0; 850 851 852 if (xsvc_fd < 0) { 853 if ((xsvc_fd = open("/dev/xsvc", O_RDWR)) < 0) { 854 (void) fprintf(stderr, "can not open xsvc driver\n"); 855 return errno; 856 } 857 } 858 859 map->memory = mmap(NULL, map->size, prot, MAP_SHARED, xsvc_fd, 860 map->base); 861 if (map->memory == MAP_FAILED) { 862 err = errno; 863 864 (void) fprintf(stderr, "map rom region =%llx failed", 865 map->base); 866 } 867 868 return err; 869 } 870