Changeset 50654 in vbox
- Timestamp:
- Feb 28, 2014 4:19:29 PM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 92585
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
r50638 r50654 100 100 #endif 101 101 102 /** Config register.*/102 /** Value latched in Configuration Address Port (0CF8h) */ 103 103 uint32_t uConfigReg; 104 104 … … 124 124 125 125 126 /** 127 * PCI configuration space address. 128 */ 126 129 typedef struct 127 130 { … … 229 232 } 230 233 234 231 235 /** 232 236 * Port I/O Handler for PCI address OUT operations. 233 237 * 238 * Emulates writes to Configuration Address Port at 0CF8h for 239 * Configuration Mechanism #1. 240 * 234 241 * @returns VBox status code. 235 242 * 236 * @param pDevIns Thedevice instance.243 * @param pDevIns ICH9 device instance. 237 244 * @param pvUser User argument - ignored. 238 245 * @param uPort Port number used for the OUT operation. … … 240 247 * @param cb The value size in bytes. 241 248 */ 242 PDMBOTHCBDECL(int) 249 PDMBOTHCBDECL(int) ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 243 250 { 244 251 LogFlow(("ich9pciIOPortAddressWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb)); … … 248 255 PICH9PCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS); 249 256 257 /* 258 * bits [1:0] are hard-wired, read-only and must return zeroes 259 * when read. 260 */ 261 u32 &= ~3; 262 250 263 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_WRITE); 251 pThis->uConfigReg = u32 & ~3; /* Bits 0-1 are reserved and we silently clear them */264 pThis->uConfigReg = u32; 252 265 PCI_UNLOCK(pDevIns); 253 266 } … … 255 268 return VINF_SUCCESS; 256 269 } 270 257 271 258 272 /** 259 273 * Port I/O Handler for PCI address IN operations. 260 274 * 275 * Emulates reads from Configuration Address Port at 0CF8h for 276 * Configuration Mechanism #1. 277 * 261 278 * @returns VBox status code. 262 279 * 263 * @param pDevIns Thedevice instance.280 * @param pDevIns ICH9 device instance. 264 281 * @param pvUser User argument - ignored. 265 282 * @param uPort Port number used for the IN operation. … … 267 284 * @param cb Number of bytes read. 268 285 */ 269 PDMBOTHCBDECL(int) 286 PDMBOTHCBDECL(int) ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 270 287 { 271 288 NOREF(pvUser); … … 273 290 { 274 291 PICH9PCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS); 292 275 293 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_READ); 276 294 *pu32 = pThis->uConfigReg; 277 295 PCI_UNLOCK(pDevIns); 296 278 297 LogFlow(("ich9pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32)); 279 298 return VINF_SUCCESS; … … 281 300 282 301 Log(("ich9pciIOPortAddressRead: Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", Port, cb)); 283 284 302 return VERR_IOM_IOPORT_UNUSED; 285 303 } 286 304 305 306 /* 307 * Perform configuration space write. 308 */ 287 309 static int ich9pciDataWriteAddr(PICH9PCIGLOBALS pGlobals, PciAddress* pAddr, 288 310 uint32_t val, int cb, int rcReschedule) 289 311 { 290 312 int rc = VINF_SUCCESS; 291 292 if (pAddr->iBus != 0) 313 #ifdef IN_RING3 314 NOREF(rcReschedule); 315 #endif 316 317 if (pAddr->iBus != 0) /* forward to subordinate bus */ 293 318 { 294 319 if (pGlobals->aPciBus.cBridges) … … 302 327 pAddr->iRegister, val, cb); 303 328 } 304 else305 {306 // do nothing, bridge not found307 }308 NOREF(rcReschedule);309 329 #else 310 330 rc = rcReschedule; … … 312 332 } 313 333 } 314 else 315 { 316 if (pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc]) 334 else /* forward to directly connected device */ 335 { 336 R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc]; 337 if (aDev) 317 338 { 318 339 #ifdef IN_RING3 319 R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc];320 340 aDev->Int.s.pfnConfigWrite(aDev, pAddr->iRegister, val, cb); 321 341 #else … … 328 348 pAddr->iBus, pAddr->iDeviceFunc >> 3, pAddr->iDeviceFunc & 0x7, pAddr->iRegister, 329 349 cb, val, rc)); 330 331 350 return rc; 332 351 } 333 352 353 354 /* 355 * Decode value latched in Configuration Address Port and perform 356 * requsted write to the target configuration space register. 357 * 358 * XXX: This code should be probably moved to its only caller 359 * (ich9pciIOPortDataWrite) to avoid prolifiration of confusingly 360 * similarly named functions. 361 */ 334 362 static int ich9pciDataWrite(PICH9PCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len) 335 363 { 336 PciAddress aPciAddr;337 338 364 LogFlow(("ich9pciDataWrite: config=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len)); 339 365 366 /* Configuration space mapping enabled? */ 340 367 if (!(pGlobals->uConfigReg & (1 << 31))) 341 368 return VINF_SUCCESS; 342 369 343 if ((pGlobals->uConfigReg & 0x3) != 0) 344 return VINF_SUCCESS; 345 346 /* Compute destination device */ 370 /* Decode target device and configuration space register */ 371 PciAddress aPciAddr; 347 372 ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr); 348 373 374 /* Perform configuration space write */ 349 375 return ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len, VINF_IOM_R3_IOPORT_WRITE); 350 376 } 351 377 352 static void ich9pciNoMem(void* ptr, int cb)353 {354 for (int i = 0; i < cb; i++)355 ((uint8_t*)ptr)[i] = 0xff;356 }357 378 358 379 /** 359 380 * Port I/O Handler for PCI data OUT operations. 360 381 * 382 * Emulates writes to Configuration Data Port at 0CFCh for 383 * Configuration Mechanism #1. 384 * 361 385 * @returns VBox status code. 362 386 * 363 * @param pDevIns Thedevice instance.387 * @param pDevIns ICH9 device instance. 364 388 * @param pvUser User argument - ignored. 365 389 * @param uPort Port number used for the OUT operation. … … 367 391 * @param cb The value size in bytes. 368 392 */ 369 PDMBOTHCBDECL(int) 393 PDMBOTHCBDECL(int) ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 370 394 { 371 395 LogFlow(("ich9pciIOPortDataWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb)); … … 374 398 if (!(Port % cb)) 375 399 { 400 PICH9PCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS); 401 376 402 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_WRITE); 377 rc = ich9pciDataWrite( PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS), Port, u32, cb);403 rc = ich9pciDataWrite(pThis, Port, u32, cb); 378 404 PCI_UNLOCK(pDevIns); 379 405 } … … 383 409 } 384 410 411 412 static void ich9pciNoMem(void* ptr, int cb) 413 { 414 for (int i = 0; i < cb; i++) 415 ((uint8_t*)ptr)[i] = 0xff; 416 } 417 418 419 /* 420 * Perform configuration space read. 421 */ 385 422 static int ich9pciDataReadAddr(PICH9PCIGLOBALS pGlobals, PciAddress* pPciAddr, int cb, 386 423 uint32_t *pu32, int rcReschedule) 387 424 { 388 425 int rc = VINF_SUCCESS; 389 390 if (pPciAddr->iBus != 0) 426 #ifdef IN_RING3 427 NOREF(rcReschedule); 428 #endif 429 430 if (pPciAddr->iBus != 0) /* forward to subordinate bus */ 391 431 { 392 432 if (pGlobals->aPciBus.cBridges) … … 401 441 else 402 442 ich9pciNoMem(pu32, cb); 403 NOREF(rcReschedule);404 443 #else 405 444 rc = rcReschedule; 406 445 #endif 407 } else 446 } 447 else 408 448 ich9pciNoMem(pu32, cb); 409 449 } 410 else 411 { 412 if (pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc]) 450 else /* forward to directly connected device */ 451 { 452 R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc]; 453 if (aDev) 413 454 { 414 455 #ifdef IN_RING3 415 R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc];416 456 *pu32 = aDev->Int.s.pfnConfigRead(aDev, pPciAddr->iRegister, cb); 417 457 #else … … 426 466 pPciAddr->iBus, pPciAddr->iDeviceFunc >> 3, pPciAddr->iDeviceFunc & 0x7, pPciAddr->iRegister, 427 467 cb, *pu32, rc)); 428 429 468 return rc; 430 469 } 431 470 471 472 /* 473 * Decode value latched in Configuration Address Port and perform 474 * requsted read from the target configuration space register. 475 * 476 * XXX: This code should be probably moved to its only caller 477 * (ich9pciIOPortDataRead) to avoid prolifiration of confusingly 478 * similarly named functions. 479 */ 432 480 static int ich9pciDataRead(PICH9PCIGLOBALS pGlobals, uint32_t addr, int cb, uint32_t *pu32) 433 481 { 434 PciAddress aPciAddr;435 436 482 LogFlow(("ich9pciDataRead: config=%x cb=%d\n", pGlobals->uConfigReg, cb)); 437 483 438 484 *pu32 = 0xffffffff; 439 485 486 /* Configuration space mapping enabled? */ 440 487 if (!(pGlobals->uConfigReg & (1 << 31))) 441 488 return VINF_SUCCESS; 442 489 443 if ((pGlobals->uConfigReg & 0x3) != 0) 444 return VINF_SUCCESS; 445 446 /* Compute destination device */ 490 /* Decode target device and configuration space register */ 491 PciAddress aPciAddr; 447 492 ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr); 448 493 494 /* Perform configuration space read */ 449 495 return ich9pciDataReadAddr(pGlobals, &aPciAddr, cb, pu32, VINF_IOM_R3_IOPORT_READ); 450 496 } 497 451 498 452 499 /** 453 500 * Port I/O Handler for PCI data IN operations. 454 501 * 502 * Emulates reads from Configuration Data Port at 0CFCh for 503 * Configuration Mechanism #1. 504 * 455 505 * @returns VBox status code. 456 506 * 457 * @param pDevIns Thedevice instance.507 * @param pDevIns ICH9 device instance. 458 508 * @param pvUser User argument - ignored. 459 509 * @param uPort Port number used for the IN operation. … … 461 511 * @param cb Number of bytes read. 462 512 */ 463 PDMBOTHCBDECL(int) 513 PDMBOTHCBDECL(int) ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 464 514 { 465 515 NOREF(pvUser); 466 516 if (!(Port % cb)) 467 517 { 518 PICH9PCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS); 519 468 520 PCI_LOCK(pDevIns, VINF_IOM_R3_IOPORT_READ); 469 int rc = ich9pciDataRead( PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS), Port, cb, pu32);521 int rc = ich9pciDataRead(pThis, Port, cb, pu32); 470 522 PCI_UNLOCK(pDevIns); 523 471 524 LogFlow(("ich9pciIOPortDataRead: Port=%#x cb=%#x -> %#x (%Rrc)\n", Port, cb, *pu32, rc)); 472 525 return rc; … … 475 528 return VERR_IOM_IOPORT_UNUSED; 476 529 } 530 477 531 478 532 /* Compute mapping of PCI slot and IRQ number to APIC interrupt line */ … … 593 647 } 594 648 595 PDMBOTHCBDECL(int) ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 649 650 /** 651 * Memory mapped I/O Handler for write operations. 652 * 653 * Emulates writes to configuration space. 654 * 655 * @returns VBox status code. 656 * 657 * @param pDevIns The device instance. 658 * @param pvUser User argument. 659 * @param GCPhysAddr Physical address (in GC) where the read starts. 660 * @param pv Where to fetch the result. 661 * @param cb Number of bytes to write. 662 * @remarks Caller enters the device critical section. 663 */ 664 PDMBOTHCBDECL(int) ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 596 665 { 597 666 PICH9PCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS); 598 PciAddress aDest;599 667 uint32_t u32 = 0; 600 668 NOREF(pvUser); … … 604 672 PCI_LOCK(pDevIns, VINF_IOM_R3_MMIO_WRITE); 605 673 674 /* Decode target device and configuration space register */ 675 PciAddress aDest; 606 676 ich9pciPhysToPciAddr(pGlobals, GCPhysAddr, &aDest); 607 677 … … 621 691 break; 622 692 } 693 694 /* Perform configuration space write */ 623 695 int rc = ich9pciDataWriteAddr(pGlobals, &aDest, u32, cb, VINF_IOM_R3_MMIO_WRITE); 624 696 PCI_UNLOCK(pDevIns); … … 627 699 } 628 700 629 PDMBOTHCBDECL(int) ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 701 702 /** 703 * Memory mapped I/O Handler for read operations. 704 * 705 * Emulates reads from configuration space. 706 * 707 * @returns VBox status code. 708 * 709 * @param pDevIns The device instance. 710 * @param pvUser User argument. 711 * @param GCPhysAddr Physical address (in GC) where the read starts. 712 * @param pv Where to store the result. 713 * @param cb Number of bytes read. 714 * @remarks Caller enters the device critical section. 715 */ 716 PDMBOTHCBDECL(int) ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 630 717 { 631 718 PICH9PCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PICH9PCIGLOBALS); 632 PciAddress aDest;633 719 uint32_t rv; 634 720 NOREF(pvUser); … … 638 724 PCI_LOCK(pDevIns, VINF_IOM_R3_MMIO_READ); 639 725 726 /* Decode target device and configuration space register */ 727 PciAddress aDest; 640 728 ich9pciPhysToPciAddr(pGlobals, GCPhysAddr, &aDest); 641 729 730 /* Perform configuration space read */ 642 731 int rc = ich9pciDataReadAddr(pGlobals, &aDest, cb, &rv, VINF_IOM_R3_MMIO_READ); 643 732 … … 1474 1563 } 1475 1564 1565 1566 /* 1567 * Perform imeediate read of configuration space register. 1568 * Cannot be rescheduled, as already in R3. 1569 */ 1476 1570 static uint32_t ich9pciConfigRead(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t len) 1477 1571 { 1478 /* Will only work in LSB case */1479 uint32_t u32Val;1480 1572 PciAddress aPciAddr; 1481 1482 1573 aPciAddr.iBus = uBus; 1483 1574 aPciAddr.iDeviceFunc = uDevFn; 1484 1575 aPciAddr.iRegister = addr; 1485 1576 1486 /* cannot be rescheduled, as already in R3 */1577 uint32_t u32Val; 1487 1578 int rc = ich9pciDataReadAddr(pGlobals, &aPciAddr, len, &u32Val, VERR_INTERNAL_ERROR); 1488 1579 AssertRC(rc); 1580 1489 1581 return u32Val; 1490 1582 } 1491 1583 1584 1585 /* 1586 * Perform imeediate write to configuration space register. 1587 * Cannot be rescheduled, as already in R3. 1588 */ 1492 1589 static void ich9pciConfigWrite(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val, uint32_t len) 1493 1590 { 1494 1591 PciAddress aPciAddr; 1495 1496 1592 aPciAddr.iBus = uBus; 1497 1593 aPciAddr.iDeviceFunc = uDevFn; 1498 1594 aPciAddr.iRegister = addr; 1499 1595 1500 /* cannot be rescheduled, as already in R3 */1501 1596 int rc = ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len, VERR_INTERNAL_ERROR); 1502 1597 AssertRC(rc); 1503 1598 } 1599 1504 1600 1505 1601 static void ich9pciSetRegionAddress(PICH9PCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, int iRegion, uint64_t addr) … … 1838 1934 } 1839 1935 1936 1937 /* 1938 * Configuration space read callback (PCIDEVICEINT::pfnConfigRead) for 1939 * connected devices. 1940 */ 1840 1941 static DECLCALLBACK(uint32_t) ich9pciConfigReadDev(PCIDevice *aDev, uint32_t u32Address, unsigned len) 1841 1942 { … … 1881 1982 } 1882 1983 1984 1883 1985 DECLINLINE(void) ich9pciWriteBarByte(PCIDevice *aDev, int iRegion, int iOffset, uint8_t u8Val) 1884 1986 { … … 1924 2026 } 1925 2027 2028 1926 2029 /** 1927 * See paragraph 7.5 of PCI Express specification (p. 349) for definition of 1928 * registers and their writability policy. 2030 * Configuration space write callback (PCIDEVICEINT::pfnConfigWrite) 2031 * for connected devices. 2032 * 2033 * See paragraph 7.5 of PCI Express specification (p. 349) for 2034 * definition of registers and their writability policy. 1929 2035 */ 1930 2036 static DECLCALLBACK(void) ich9pciConfigWriteDev(PCIDevice *aDev, uint32_t u32Address, … … 2139 2245 static int ich9pciRegisterInternal(PICH9PCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName) 2140 2246 { 2141 PciAddress aPosition = {0, 0, 0}; 2247 PciAddress aPosition; 2248 aPosition.iBus = 0; 2249 aPosition.iDeviceFunc = 0; 2250 aPosition.iRegister = 0; 2142 2251 2143 2252 /*
Note:
See TracChangeset
for help on using the changeset viewer.