xf86pciBus.c revision 4642e01f
1/* 2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 */ 27 28/* 29 * This file contains the interfaces to the bus-specific code 30 */ 31#ifdef HAVE_XORG_CONFIG_H 32#include <xorg-config.h> 33#endif 34 35#include <ctype.h> 36#include <stdlib.h> 37#include <unistd.h> 38#include <X11/X.h> 39#include <pciaccess.h> 40#include "os.h" 41#include "Pci.h" 42#include "xf86.h" 43#include "xf86Priv.h" 44#include "xf86Resources.h" 45 46/* Bus-specific headers */ 47#include "xf86Bus.h" 48 49#define XF86_OS_PRIVS 50#define NEED_OS_RAC_PROTOS 51#include "xf86_OSproc.h" 52 53#include "xf86RAC.h" 54 55/* Bus-specific globals */ 56Bool pciSlotClaimed = FALSE; 57static struct pci_device ** xf86PciVideoInfo = NULL; /* PCI probe for video hw */ 58 59 60/* PCI classes that get included in xf86PciVideoInfo */ 61#define PCIINFOCLASSES(c) \ 62 ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \ 63 || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ 64 || ((((c) & 0x00ffff00) \ 65 == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \ 66 || ((((c) & 0x00ffff00) \ 67 == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) ) 68 69/* 70 * PCI classes that have messages printed always. The others are only 71 * have a message printed when the vendor/dev IDs are recognised. 72 */ 73#define PCIALWAYSPRINTCLASSES(c) \ 74 ( (((c) & 0x00ffff00) \ 75 == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ 76 || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ 77 || ((((c) & 0x00ffff00) \ 78 == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) ) 79 80#define IS_VGA(c) \ 81 (((c) & 0x00ffff00) \ 82 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) 83 84/* 85 * PCI classes for which potentially destructive checking of the map sizes 86 * may be done. Any classes where this may be unsafe should be omitted 87 * from this list. 88 */ 89#define PCINONSYSTEMCLASSES(c) PCIALWAYSPRINTCLASSES(c) 90 91/* 92 * PCI classes that use RAC 93 */ 94#define PCISHAREDIOCLASSES(c) \ 95 ( (((c) & 0x00ffff00) \ 96 == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ 97 || IS_VGA(c) ) 98 99 100_X_EXPORT void 101xf86FormatPciBusNumber(int busnum, char *buffer) 102{ 103 /* 'buffer' should be at least 8 characters long */ 104 if (busnum < 256) 105 sprintf(buffer, "%d", busnum); 106 else 107 sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8); 108} 109 110/* 111 * IO enable/disable related routines for PCI 112 */ 113#define pArg ((pciArg*)arg) 114#define SETBITS PCI_CMD_IO_ENABLE 115static void 116pciIoAccessEnable(void* arg) 117{ 118#if 0 119#ifdef DEBUG 120 ErrorF("pciIoAccessEnable: 0x%05lx\n", *(PCITAG *)arg); 121#endif 122 pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE; 123 pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG); 124#endif 125} 126 127static void 128pciIoAccessDisable(void* arg) 129{ 130#if 0 131#ifdef DEBUG 132 ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG *)arg); 133#endif 134 pArg->ctrl &= ~SETBITS; 135 pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG); 136#endif 137} 138 139#undef SETBITS 140#define SETBITS (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE) 141static void 142pciIo_MemAccessEnable(void* arg) 143{ 144#if 0 145#ifdef DEBUG 146 ErrorF("pciIo_MemAccessEnable: 0x%05lx\n", *(PCITAG *)arg); 147#endif 148 pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE; 149 pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG); 150#endif 151} 152 153static void 154pciIo_MemAccessDisable(void* arg) 155{ 156#if 0 157#ifdef DEBUG 158 ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG *)arg); 159#endif 160 pArg->ctrl &= ~SETBITS; 161 pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG); 162#endif 163} 164 165#undef SETBITS 166#define SETBITS (PCI_CMD_MEM_ENABLE) 167static void 168pciMemAccessEnable(void* arg) 169{ 170#if 0 171#ifdef DEBUG 172 ErrorF("pciMemAccessEnable: 0x%05lx\n", *(PCITAG *)arg); 173#endif 174 pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE; 175 pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG); 176#endif 177} 178 179static void 180pciMemAccessDisable(void* arg) 181{ 182#if 0 183#ifdef DEBUG 184 ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG *)arg); 185#endif 186 pArg->ctrl &= ~SETBITS; 187 pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG); 188#endif 189} 190#undef SETBITS 191#undef pArg 192 193 194/* move to OS layer */ 195#define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN) 196static void 197pciBusAccessEnable(BusAccPtr ptr) 198{ 199#if 0 200 struct pci_device * const dev = ptr->busdep.pci.dev; 201 uint16_t ctrl; 202 203#ifdef DEBUG 204 ErrorF("pciBusAccessEnable: bus=%d\n", ptr->busdep.pci.bus); 205#endif 206 pci_device_cfg_read_u16( dev, & ctrl, PCI_PCI_BRIDGE_CONTROL_REG ); 207 if ((ctrl & MASKBITS) != PCI_PCI_BRIDGE_VGA_EN) { 208 ctrl = (ctrl | PCI_PCI_BRIDGE_VGA_EN) & 209 ~(PCI_PCI_BRIDGE_MASTER_ABORT_EN | PCI_PCI_BRIDGE_SECONDARY_RESET); 210 pci_device_cfg_write_u16(dev, ctrl, PCI_PCI_BRIDGE_CONTROL_REG); 211 } 212#endif 213} 214 215/* move to OS layer */ 216static void 217pciBusAccessDisable(BusAccPtr ptr) 218{ 219#if 0 220 struct pci_device * const dev = ptr->busdep.pci.dev; 221 uint16_t ctrl; 222 223#ifdef DEBUG 224 ErrorF("pciBusAccessDisable: bus=%d\n", ptr->busdep.pci.bus); 225#endif 226 pci_device_cfg_read_u16( dev, & ctrl, PCI_PCI_BRIDGE_CONTROL_REG ); 227 if (ctrl & MASKBITS) { 228 ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET); 229 pci_device_cfg_write_u16(dev, ctrl, PCI_PCI_BRIDGE_CONTROL_REG); 230 } 231#endif 232} 233#undef MASKBITS 234 235static void 236pciSetBusAccess(BusAccPtr ptr) 237{ 238#if 0 239#ifdef DEBUG 240 ErrorF("pciSetBusAccess: route VGA to bus %d\n", ptr->busdep.pci.bus); 241#endif 242 243 if (!ptr->primary && !ptr->current) 244 return; 245 246 if (ptr->current && ptr->current->disable_f) 247 (*ptr->current->disable_f)(ptr->current); 248 ptr->current = NULL; 249 250 /* walk down */ 251 while (ptr->primary) { /* No enable for root bus */ 252 if (ptr != ptr->primary->current) { 253 if (ptr->primary->current && ptr->primary->current->disable_f) 254 (*ptr->primary->current->disable_f)(ptr->primary->current); 255 if (ptr->enable_f) 256 (*ptr->enable_f)(ptr); 257 ptr->primary->current = ptr; 258 } 259 ptr = ptr->primary; 260 } 261#endif 262} 263 264/* move to OS layer */ 265static void 266savePciState( struct pci_device * dev, pciSavePtr ptr ) 267{ 268#if 0 269 int i; 270 271 pci_device_cfg_read_u32( dev, & ptr->command, PCI_CMD_STAT_REG ); 272 273 for ( i = 0; i < 6; i++ ) { 274 pci_device_cfg_read_u32( dev, & ptr->base[i], 275 PCI_CMD_BASE_REG + (i * 4) ); 276 } 277 278 pci_device_cfg_read_u32( dev, & ptr->biosBase, PCI_CMD_BIOS_REG ); 279#endif 280} 281 282/* move to OS layer */ 283#if 0 284static void 285restorePciState( struct pci_device * dev, pciSavePtr ptr) 286{ 287 int i; 288 289 /* disable card before setting anything */ 290 pci_device_cfg_write_bits(dev, PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE, 0, 291 PCI_CMD_STAT_REG); 292 293 pci_device_cfg_write_u32(dev, ptr->biosBase, PCI_CMD_BIOS_REG); 294 295 for ( i = 0; i < 6; i++ ) { 296 pci_device_cfg_write_u32(dev, ptr->base[i], 297 PCI_CMD_BASE_REG + (i * 4)); 298 } 299 300 pci_device_cfg_write_u32(dev, ptr->command, PCI_CMD_STAT_REG); 301} 302#endif 303 304/* move to OS layer */ 305static void 306savePciBusState(BusAccPtr ptr) 307{ 308#if 0 309 struct pci_device * const dev = ptr->busdep.pci.dev; 310 uint16_t temp; 311 312 pci_device_cfg_read_u16( dev, & temp, PCI_PCI_BRIDGE_CONTROL_REG ); 313 ptr->busdep.pci.save.control = temp & ~PCI_PCI_BRIDGE_SECONDARY_RESET; 314 315 /* Allow master aborts to complete normally on non-root buses */ 316 if ( ptr->busdep.pci.save.control & PCI_PCI_BRIDGE_MASTER_ABORT_EN ) { 317 temp = ptr->busdep.pci.save.control & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN; 318 pci_device_cfg_read_u16( dev, & temp, PCI_PCI_BRIDGE_CONTROL_REG ); 319 } 320#endif 321} 322 323/* move to OS layer */ 324#define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN) 325static void 326restorePciBusState(BusAccPtr ptr) 327{ 328#if 0 329 struct pci_device * const dev = ptr->busdep.pci.dev; 330 uint16_t ctrl; 331 332 /* Only restore the bits we've changed (and don't cause resets) */ 333 pci_device_cfg_read_u16( dev, & ctrl, PCI_PCI_BRIDGE_CONTROL_REG ); 334 335 if ((ctrl ^ ptr->busdep.pci.save.control) & MASKBITS) { 336 ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET); 337 ctrl |= ptr->busdep.pci.save.control & MASKBITS; 338 pci_device_cfg_write_u16(dev, ctrl, PCI_PCI_BRIDGE_CONTROL_REG); 339 } 340#endif 341} 342#undef MASKBITS 343 344 345/* 346 * xf86Bus.c interface 347 */ 348 349void 350xf86PciProbe(void) 351{ 352 int i = 0, k; 353 int num = 0; 354 struct pci_device *info; 355 struct pci_device_iterator *iter; 356 357 358 if (!xf86scanpci()) { 359 xf86PciVideoInfo = NULL; 360 return; 361 } 362 363 iter = pci_slot_match_iterator_create(& xf86IsolateDevice); 364 while ((info = pci_device_next(iter)) != NULL) { 365 if (PCIINFOCLASSES(info->device_class)) { 366 num++; 367 xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo, 368 (sizeof(struct pci_device *) 369 * (num + 1))); 370 xf86PciVideoInfo[num] = NULL; 371 xf86PciVideoInfo[num - 1] = info; 372 373 pci_device_probe(info); 374 info->user_data = 0; 375 } 376 } 377 378 379 /* If we haven't found a primary device try a different heuristic */ 380 if (primaryBus.type == BUS_NONE && num) { 381 for (i = 0; i < num; i++) { 382 uint16_t command; 383 384 info = xf86PciVideoInfo[i]; 385 pci_device_cfg_read_u16(info, & command, 4); 386 387 if ((command & PCI_CMD_MEM_ENABLE) 388 && ((num == 1) || IS_VGA(info->device_class))) { 389 if (primaryBus.type == BUS_NONE) { 390 primaryBus.type = BUS_PCI; 391 primaryBus.id.pci = info; 392 } else { 393 xf86Msg(X_NOTICE, 394 "More than one possible primary device found\n"); 395 primaryBus.type ^= (BusType)(-1); 396 } 397 } 398 } 399 } 400 401 /* Print a summary of the video devices found */ 402 for (k = 0; k < num; k++) { 403 const char *vendorname = NULL, *chipname = NULL; 404 const char *prim = " "; 405 Bool memdone = FALSE, iodone = FALSE; 406 407 408 info = xf86PciVideoInfo[k]; 409 410 vendorname = pci_device_get_vendor_name( info ); 411 chipname = pci_device_get_device_name( info ); 412 413 if ((!vendorname || !chipname) && 414 !PCIALWAYSPRINTCLASSES(info->device_class)) 415 continue; 416 417 if (xf86IsPrimaryPci(info)) 418 prim = "*"; 419 420 xf86Msg( X_PROBED, "PCI:%s(%u@%u:%u:%u) ", prim, info->domain, 421 info->bus, info->dev, info->func ); 422 423 if (vendorname) 424 xf86ErrorF("%s ", vendorname); 425 else 426 xf86ErrorF("unknown vendor (0x%04x) ", info->vendor_id); 427 428 if (chipname) 429 xf86ErrorF("%s ", chipname); 430 else 431 xf86ErrorF("unknown chipset (0x%04x) ", info->device_id); 432 433 xf86ErrorF("rev %d", info->revision); 434 435 for (i = 0; i < 6; i++) { 436 struct pci_mem_region * r = & info->regions[i]; 437 438 if ( r->size && ! r->is_IO ) { 439 if (!memdone) { 440 xf86ErrorF(", Mem @ "); 441 memdone = TRUE; 442 } else 443 xf86ErrorF(", "); 444 xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); 445 } 446 } 447 448 for (i = 0; i < 6; i++) { 449 struct pci_mem_region * r = & info->regions[i]; 450 451 if ( r->size && r->is_IO ) { 452 if (!iodone) { 453 xf86ErrorF(", I/O @ "); 454 iodone = TRUE; 455 } else 456 xf86ErrorF(", "); 457 xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); 458 } 459 } 460 461 if ( info->rom_size ) { 462 xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long)info->rom_size); 463 } 464 465 xf86ErrorF("\n"); 466 } 467} 468 469void 470initPciState(void) 471{ 472 unsigned i; 473 pciAccPtr pcaccp; 474 475 if (xf86PciVideoInfo == NULL) { 476 return; 477 } 478 479 for (i = 0 ; xf86PciVideoInfo[i] != NULL ; i++) { 480 struct pci_device * const pvp = xf86PciVideoInfo[i]; 481 482 if (pvp->user_data == 0) { 483 pcaccp = xnfalloc( sizeof( pciAccRec ) ); 484 pvp->user_data = (intptr_t) pcaccp; 485 486 pcaccp->arg.dev = pvp; 487 pcaccp->ioAccess.AccessDisable = pciIoAccessDisable; 488 pcaccp->ioAccess.AccessEnable = pciIoAccessEnable; 489 pcaccp->ioAccess.arg = &pcaccp->arg; 490 pcaccp->io_memAccess.AccessDisable = pciIo_MemAccessDisable; 491 pcaccp->io_memAccess.AccessEnable = pciIo_MemAccessEnable; 492 pcaccp->io_memAccess.arg = &pcaccp->arg; 493 pcaccp->memAccess.AccessDisable = pciMemAccessDisable; 494 pcaccp->memAccess.AccessEnable = pciMemAccessEnable; 495 pcaccp->memAccess.arg = &pcaccp->arg; 496 497 pcaccp->ctrl = PCISHAREDIOCLASSES(pvp->device_class); 498 499 savePciState(pvp, &pcaccp->save); 500 pcaccp->arg.ctrl = pcaccp->save.command; 501 } 502 } 503} 504 505/* 506 * initPciBusState() - fill out the BusAccRec for a PCI bus. 507 * Theory: each bus is associated with one bridge connecting it 508 * to its parent bus. The address of a bridge is therefore stored 509 * in the BusAccRec of the bus it connects to. Each bus can 510 * have several bridges connecting secondary buses to it. Only one 511 * of these bridges can be open. Therefore the status of a bridge 512 * associated with a bus is stored in the BusAccRec of the parent 513 * the bridge connects to. The first member of the structure is 514 * a pointer to a function that open access to this bus. This function 515 * receives a pointer to the structure itself as argument. This 516 * design should be common to BusAccRecs of any type of buses we 517 * support. The remeinder of the structure is bus type specific. 518 * In this case it contains a pointer to the structure of the 519 * parent bus. Thus enabling access to a specific bus is simple: 520 * 1. Close any bridge going to secondary buses. 521 * 2. Climb down the ladder and enable any bridge on buses 522 * on the path from the CPU to this bus. 523 */ 524 525void 526initPciBusState(void) 527{ 528 static const struct pci_id_match bridge_match = { 529 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 530 (PCI_CLASS_BRIDGE << 16), 0x0000ff0000, 0 531 }; 532 struct pci_device *dev; 533 struct pci_device_iterator *iter; 534 BusAccPtr pbap, pbap_tmp; 535 536 iter = pci_id_match_iterator_create(& bridge_match); 537 while((dev = pci_device_next(iter)) != NULL) { 538 const uint8_t subclass = (dev->device_class >> 8) & 0x0ff; 539 int primary; 540 int secondary; 541 int subordinate; 542 543 544 pci_device_get_bridge_buses(dev, &primary, &secondary, &subordinate); 545 546 pbap = xnfcalloc(1,sizeof(BusAccRec)); 547 pbap->busdep.pci.bus = secondary; 548 pbap->busdep.pci.primary_bus = primary; 549 pbap->busdep_type = BUS_PCI; 550 pbap->busdep.pci.dev = dev; 551 552 pbap->set_f = pciSetBusAccess; 553 554 switch (subclass) { 555 case PCI_SUBCLASS_BRIDGE_HOST: 556 pbap->type = BUS_PCI; 557 break; 558 case PCI_SUBCLASS_BRIDGE_PCI: 559 case PCI_SUBCLASS_BRIDGE_CARDBUS: 560 pbap->type = BUS_PCI; 561 pbap->save_f = savePciBusState; 562 pbap->restore_f = restorePciBusState; 563 pbap->enable_f = pciBusAccessEnable; 564 pbap->disable_f = pciBusAccessDisable; 565 savePciBusState(pbap); 566 break; 567 } 568 pbap->next = xf86BusAccInfo; 569 xf86BusAccInfo = pbap; 570 } 571 572 pci_iterator_destroy(iter); 573 574 for (pbap = xf86BusAccInfo; pbap; pbap = pbap->next) { 575 pbap->primary = NULL; 576 577 if (pbap->busdep_type == BUS_PCI 578 && pbap->busdep.pci.primary_bus > -1) { 579 pbap_tmp = xf86BusAccInfo; 580 while (pbap_tmp) { 581 if (pbap_tmp->busdep_type == BUS_PCI && 582 pbap_tmp->busdep.pci.bus == pbap->busdep.pci.primary_bus) { 583 /* Don't create loops */ 584 if (pbap == pbap_tmp) 585 break; 586 pbap->primary = pbap_tmp; 587 break; 588 } 589 pbap_tmp = pbap_tmp->next; 590 } 591 } 592 } 593} 594 595void 596PciStateEnter(void) 597{ 598#if 0 599 unsigned i; 600 601 if (xf86PciVideoInfo == NULL) 602 return; 603 604 for ( i = 0 ; xf86PciVideoInfo[i] != NULL ; i++ ) { 605 pciAccPtr paccp = (pciAccPtr) xf86PciVideoInfo[i]->user_data; 606 607 if ( (paccp != NULL) && paccp->ctrl ) { 608 savePciState(paccp->arg.dev, &paccp->save); 609 restorePciState(paccp->arg.dev, &paccp->restore); 610 paccp->arg.ctrl = paccp->restore.command; 611 } 612 } 613#endif 614} 615 616void 617PciBusStateEnter(void) 618{ 619#if 0 620 BusAccPtr pbap = xf86BusAccInfo; 621 622 while (pbap) { 623 if (pbap->save_f) 624 pbap->save_f(pbap); 625 pbap = pbap->next; 626 } 627#endif 628} 629 630void 631PciStateLeave(void) 632{ 633#if 0 634 unsigned i; 635 636 if (xf86PciVideoInfo == NULL) 637 return; 638 639 for ( i = 0 ; xf86PciVideoInfo[i] != NULL ; i++ ) { 640 pciAccPtr paccp = (pciAccPtr) xf86PciVideoInfo[i]->user_data; 641 642 if ( (paccp != NULL) && paccp->ctrl ) { 643 savePciState(paccp->arg.dev, &paccp->restore); 644 restorePciState(paccp->arg.dev, &paccp->save); 645 } 646 } 647#endif 648} 649 650void 651PciBusStateLeave(void) 652{ 653#if 0 654 BusAccPtr pbap = xf86BusAccInfo; 655 656 while (pbap) { 657 if (pbap->restore_f) 658 pbap->restore_f(pbap); 659 pbap = pbap->next; 660 } 661#endif 662} 663 664void 665DisablePciAccess(void) 666{ 667#if 0 668 unsigned i; 669 670 if (xf86PciVideoInfo == NULL) 671 return; 672 673 for ( i = 0 ; xf86PciVideoInfo[i] != NULL ; i++ ) { 674 pciAccPtr paccp = (pciAccPtr) xf86PciVideoInfo[i]->user_data; 675 676 if ( (paccp != NULL) && paccp->ctrl ) { 677 pciIo_MemAccessDisable(paccp->io_memAccess.arg); 678 } 679 } 680#endif 681} 682 683void 684DisablePciBusAccess(void) 685{ 686#if 0 687 BusAccPtr pbap = xf86BusAccInfo; 688 689 while (pbap) { 690 if (pbap->disable_f) 691 pbap->disable_f(pbap); 692 if (pbap->primary) 693 pbap->primary->current = NULL; 694 pbap = pbap->next; 695 } 696#endif 697} 698 699/* 700 * If the slot requested is already in use, return -1. 701 * Otherwise, claim the slot for the screen requesting it. 702 */ 703 704_X_EXPORT int 705xf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp, 706 int chipset, GDevPtr dev, Bool active) 707{ 708 EntityPtr p = NULL; 709 pciAccPtr paccp = (pciAccPtr) d->user_data; 710 BusAccPtr pbap = xf86BusAccInfo; 711 const unsigned bus = PCI_MAKE_BUS(d->domain, d->bus); 712 713 int num; 714 715 if (xf86CheckPciSlot(d)) { 716 num = xf86AllocateEntity(); 717 p = xf86Entities[num]; 718 p->driver = drvp; 719 p->chipset = chipset; 720 p->bus.type = BUS_PCI; 721 p->bus.id.pci = d; 722 p->active = active; 723 p->inUse = FALSE; 724 if (dev) 725 xf86AddDevToEntity(num, dev); 726 /* Here we initialize the access structure */ 727 p->access = xnfcalloc(1,sizeof(EntityAccessRec)); 728 if (paccp != NULL) { 729 p->access->fallback = & paccp->io_memAccess; 730 p->access->pAccess = & paccp->io_memAccess; 731 paccp->ctrl = TRUE; /* mark control if not already */ 732 } 733 else { 734 p->access->fallback = &AccessNULL; 735 p->access->pAccess = &AccessNULL; 736 } 737 738 p->busAcc = NULL; 739 while (pbap) { 740 if (pbap->type == BUS_PCI && pbap->busdep.pci.bus == bus) 741 p->busAcc = pbap; 742 pbap = pbap->next; 743 } 744 745 pciSlotClaimed = TRUE; 746 747 if (active) { 748 /* Map in this domain's I/O space */ 749 p->domainIO = xf86MapLegacyIO(d); 750 } 751 752 return num; 753 } else 754 return -1; 755} 756 757/* 758 * Parse a BUS ID string, and return the PCI bus parameters if it was 759 * in the correct format for a PCI bus id. 760 */ 761 762_X_EXPORT Bool 763xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func) 764{ 765 /* 766 * The format is assumed to be "bus[@domain]:device[:func]", where domain, 767 * bus, device and func are decimal integers. domain and func may be 768 * omitted and assumed to be zero, although doing this isn't encouraged. 769 */ 770 771 char *p, *s, *d; 772 const char *id; 773 int i; 774 775 if (StringToBusType(busID, &id) != BUS_PCI) 776 return FALSE; 777 778 s = xstrdup(id); 779 p = strtok(s, ":"); 780 if (p == NULL || *p == 0) { 781 xfree(s); 782 return FALSE; 783 } 784 d = strpbrk(p, "@"); 785 if (d != NULL) { 786 *(d++) = 0; 787 for (i = 0; d[i] != 0; i++) { 788 if (!isdigit(d[i])) { 789 xfree(s); 790 return FALSE; 791 } 792 } 793 } 794 for (i = 0; p[i] != 0; i++) { 795 if (!isdigit(p[i])) { 796 xfree(s); 797 return FALSE; 798 } 799 } 800 *bus = atoi(p); 801 if (d != NULL && *d != 0) 802 *bus += atoi(d) << 8; 803 p = strtok(NULL, ":"); 804 if (p == NULL || *p == 0) { 805 xfree(s); 806 return FALSE; 807 } 808 for (i = 0; p[i] != 0; i++) { 809 if (!isdigit(p[i])) { 810 xfree(s); 811 return FALSE; 812 } 813 } 814 *device = atoi(p); 815 *func = 0; 816 p = strtok(NULL, ":"); 817 if (p == NULL || *p == 0) { 818 xfree(s); 819 return TRUE; 820 } 821 for (i = 0; p[i] != 0; i++) { 822 if (!isdigit(p[i])) { 823 xfree(s); 824 return FALSE; 825 } 826 } 827 *func = atoi(p); 828 xfree(s); 829 return TRUE; 830} 831 832/* 833 * Compare a BUS ID string with a PCI bus id. Return TRUE if they match. 834 */ 835 836_X_EXPORT Bool 837xf86ComparePciBusString(const char *busID, int bus, int device, int func) 838{ 839 int ibus, idevice, ifunc; 840 841 if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) { 842 return bus == ibus && device == idevice && func == ifunc; 843 } else { 844 return FALSE; 845 } 846} 847 848/* 849 * xf86IsPrimaryPci() -- return TRUE if primary device 850 * is PCI and bus, dev and func numbers match. 851 */ 852 853_X_EXPORT Bool 854xf86IsPrimaryPci(struct pci_device *pPci) 855{ 856 return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci)); 857} 858 859/* 860 * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity. 861 */ 862_X_EXPORT struct pci_device * 863xf86GetPciInfoForEntity(int entityIndex) 864{ 865 EntityPtr p; 866 867 if (entityIndex >= xf86NumEntities) 868 return NULL; 869 870 p = xf86Entities[entityIndex]; 871 return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL; 872} 873 874/* 875 * xf86CheckPciMemBase() checks that the memory base value matches one of the 876 * PCI base address register values for the given PCI device. 877 */ 878_X_EXPORT Bool 879xf86CheckPciMemBase( struct pci_device * pPci, memType base ) 880{ 881 int i; 882 883 for (i = 0; i < 6; i++) 884 if (base == pPci->regions[i].base_addr) 885 return TRUE; 886 return FALSE; 887} 888 889/* 890 * Check if the slot requested is free. If it is already in use, return FALSE. 891 */ 892 893_X_EXPORT Bool 894xf86CheckPciSlot(const struct pci_device *d) 895{ 896 int i; 897 898 for (i = 0; i < xf86NumEntities; i++) { 899 const EntityPtr p = xf86Entities[i]; 900 901 if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { 902 return FALSE; 903 } 904 } 905 return TRUE; 906} 907 908 909void 910pciConvertRange2Host(int entityIndex, resRange *pRange) 911{ 912 struct pci_device *const pvp = xf86GetPciInfoForEntity(entityIndex); 913 const PCITAG tag = PCI_MAKE_TAG(PCI_MAKE_BUS(pvp->domain, pvp->bus), 914 pvp->dev, pvp->func); 915 916 if (pvp == NULL) { 917 return; 918 } 919 920 if (!(pRange->type & ResBus)) 921 return; 922 923 switch(pRange->type & ResPhysMask) { 924 case ResMem: 925 switch(pRange->type & ResExtMask) { 926 case ResBlock: 927 pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rBegin); 928 pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rEnd); 929 break; 930 case ResSparse: 931 pRange->rBase = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_BASE, 932 pRange->rBegin); 933 pRange->rMask = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_MASK, 934 pRange->rEnd); 935 break; 936 } 937 break; 938 case ResIo: 939 switch(pRange->type & ResExtMask) { 940 case ResBlock: 941 pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rBegin); 942 pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rEnd); 943 break; 944 case ResSparse: 945 pRange->rBase = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_BASE 946 , pRange->rBegin); 947 pRange->rMask = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_MASK 948 , pRange->rEnd); 949 break; 950 } 951 break; 952 } 953 954 /* Set domain number */ 955 pRange->type &= ~(ResDomain | ResBus); 956 pRange->type |= pvp->domain << 24; 957} 958