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