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