Changeset 50018 in vbox
- Timestamp:
- Jan 2, 2014 3:50:08 PM (11 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
-
Storage/DevAHCI.cpp (modified) (12 diffs)
-
testcase/tstDeviceStructSizeRC.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r49218 r50018 675 675 /** Bitmask of ports which asserted an interrupt. */ 676 676 volatile uint32_t u32PortsInterrupted; 677 /** Number of I/O threads currently active - used for async controller reset handling. */ 678 volatile uint32_t cThreadsActive; 677 679 /** Device is in a reset state. */ 678 680 bool fReset; … … 698 700 /** Flag whether we have written the first 4bytes in an 8byte MMIO write successfully. */ 699 701 volatile bool f8ByteMMIO4BytesWrittenSuccessfully; 702 703 #if HC_ARCH_BITS == 64 704 uint32_t Alignment7; 705 #endif 700 706 701 707 /** The support driver session handle. */ … … 1735 1741 return VINF_IOM_R3_MMIO_WRITE; 1736 1742 #else 1737 ahci->regHbaCtrl = (u32Value & AHCI_HBA_CTRL_RW_MASK) | AHCI_HBA_CTRL_AE; 1738 if (ahci->regHbaCtrl & AHCI_HBA_CTRL_HR) 1743 /* 1744 * Increase the active thread counter because we might set the host controller 1745 * reset bit. 1746 */ 1747 ASMAtomicIncU32(&ahci->cThreadsActive); 1748 ASMAtomicWriteU32(&ahci->regHbaCtrl, (u32Value & AHCI_HBA_CTRL_RW_MASK) | AHCI_HBA_CTRL_AE); 1749 1750 /* 1751 * Do the HBA reset if requested and there is no other active thread at the moment, 1752 * the work is deferred to the last active thread otherwise. 1753 */ 1754 uint32_t cThreadsActive = ASMAtomicDecU32(&ahci->cThreadsActive); 1755 if ( (u32Value & AHCI_HBA_CTRL_HR) 1756 && !cThreadsActive) 1739 1757 ahciHBAReset(ahci); 1758 1740 1759 return VINF_SUCCESS; 1741 1760 #endif … … 6321 6340 * Retrieve a command FIS from guest memory. 6322 6341 * 6323 * @returns nothing6342 * @returns whether the H2D FIS was successfully read from the guest memory. 6324 6343 * @param pAhciReq The state of the actual task. 6325 6344 */ 6326 static voidahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)6345 static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 6327 6346 { 6328 6347 RTGCPHYS GCPhysAddrCmdTbl; 6329 6348 6330 AssertMsg(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb, ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__)); 6349 AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb, 6350 ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__), 6351 false); 6331 6352 6332 6353 /* … … 6347 6368 GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr); 6348 6369 6349 AssertMsg((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE, 6350 ("This is not a command FIS!!\n")); 6370 AssertMsgReturn((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE, 6371 ("This is not a command FIS!!\n"), 6372 false); 6351 6373 6352 6374 /* Read the command Fis. */ 6353 6375 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdTbl=%RGp cbCmdFis=%u\n", __FUNCTION__, GCPhysAddrCmdTbl, AHCI_CMDFIS_TYPE_H2D_SIZE)); 6354 6376 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE); 6377 6378 AssertMsgReturn(pAhciReq->cmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D, 6379 ("This is not a command FIS\n"), 6380 false); 6355 6381 6356 6382 /* Set transfer direction. */ … … 6399 6425 } 6400 6426 #endif 6427 6428 return true; 6401 6429 } 6402 6430 … … 6446 6474 unsigned idx = 0; 6447 6475 uint32_t u32Tasks = 0; 6476 uint32_t u32RegHbaCtrl = 0; 6448 6477 6449 6478 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, true); … … 6461 6490 6462 6491 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, false); 6492 ASMAtomicIncU32(&pAhci->cThreadsActive); 6493 6494 /* 6495 * Check whether the global host controller bit is set and go to sleep immediately again 6496 * if it is set. 6497 */ 6498 u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl); 6499 if ( u32RegHbaCtrl & AHCI_HBA_CTRL_HR 6500 && !ASMAtomicDecU32(&pAhci->cThreadsActive)) 6501 { 6502 ahciHBAReset(pAhci); 6503 continue; 6504 } 6505 6463 6506 idx = ASMBitFirstSetU32(u32Tasks); 6464 6507 while (idx) … … 6498 6541 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag); 6499 6542 6500 ahciPortTaskGetCommandFis(pAhciPort, pAhciReq); 6543 bool fFisRead = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq); 6544 if (RT_UNLIKELY(!fFisRead)) 6545 { 6546 /* 6547 * Couldn't find anything in either the AHCI or SATA spec which 6548 * indicates what should be done if the FIS is not read successfully. 6549 * The closes thing is in the state machine, stating that the device 6550 * should go into idle state again (SATA spec 1.0 chapter 8.7.1). 6551 * Do the same here and ignore any corrupt FIS types, after all 6552 * the guest messed up everything and this behavior is undefined. 6553 */ 6554 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg); 6555 Assert(fXchg); 6556 u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */ 6557 idx = ASMBitFirstSetU32(u32Tasks); 6558 continue; 6559 } 6501 6560 6502 6561 /* Mark the task as processed by the HBA if this is a queued task so that it doesn't occur in the CI register anymore. */ … … 6515 6574 pAhciPort->fResetDevice = true; 6516 6575 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true); 6517 6518 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);6519 AssertMsg(fXchg, ("Task is not active\n"));6520 break;6521 6576 } 6522 6577 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */ 6523 {6524 6578 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq); 6525 6526 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);6527 AssertMsg(fXchg, ("Task is not active\n"));6528 break;6529 }6530 6579 else /* We are not in a reset state update the control registers. */ 6531 6580 AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__)); 6581 6582 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg); 6583 AssertMsg(fXchg, ("Task is not active\n")); 6584 break; 6532 6585 } 6533 6586 else … … 6636 6689 idx = ASMBitFirstSetU32(u32Tasks); 6637 6690 } /* while tasks available */ 6691 6692 /* 6693 * Check whether a host controller reset is pending and execute the reset 6694 * if this is the last active thread. 6695 */ 6696 u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl); 6697 uint32_t cThreadsActive = ASMAtomicDecU32(&pAhci->cThreadsActive); 6698 if ( (u32RegHbaCtrl & AHCI_HBA_CTRL_HR) 6699 && !cThreadsActive) 6700 ahciHBAReset(pAhci); 6638 6701 } /* While running */ 6639 6702 … … 7998 8061 PCIDevSetWord(&pThis->dev, 0xaa, 0x0010); /* Revision */ 7999 8062 PCIDevSetDWord(&pThis->dev, 0xac, 0x00000028); /* SATA Capability Register 1 */ 8063 8064 pThis->cThreadsActive = 0; 8000 8065 8001 8066 /* Initialize port members. */ -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r49958 r50018 1284 1284 GEN_CHECK_OFF(AHCI, lock); 1285 1285 GEN_CHECK_OFF(AHCI, u32PortsInterrupted); 1286 GEN_CHECK_OFF(AHCI, cThreadsActive); 1286 1287 GEN_CHECK_OFF(AHCI, fReset); 1287 1288 GEN_CHECK_OFF(AHCI, f64BitAddr);
Note:
See TracChangeset
for help on using the changeset viewer.

