Changeset 33209 in vbox
- Timestamp:
- Oct 18, 2010 3:39:29 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r33175 r33209 320 320 /** The core part owned by the queue manager. */ 321 321 PDMQUEUEITEMCORE Core; 322 /** On which port the async io thread should be put into action. */322 /** The port to process. */ 323 323 uint8_t iPort; 324 /** Which task to process. */325 uint8_t iTask;326 /** Flag whether the task is queued. */327 uint8_t fQueued;328 324 } DEVPORTNOTIFIERQUEUEITEM, *PDEVPORTNOTIFIERQUEUEITEM; 329 325 … … 354 350 /** Pointer to the parent AHCI structure - RC ptr. */ 355 351 RCPTRTYPE(struct AHCI *) pAhciRC; 352 356 353 /** Command List Base Address. */ 357 354 uint32_t regCLB; … … 379 376 uint32_t regSERR; 380 377 /** Serial ATA Active. */ 381 uint32_tregSACT;378 volatile uint32_t regSACT; 382 379 /** Command Issue. */ 383 380 uint32_t regCI; … … 391 388 /** FIS Base Address */ 392 389 volatile RTGCPHYS GCPhysAddrFb; 393 394 /** If we use the new async interface. */ 395 bool fAsyncInterface; 396 397 #if HC_ARCH_BITS == 64 398 uint32_t Alignment2; 399 #endif 400 401 /** Async IO Thread. */ 402 PPDMTHREAD pAsyncIOThread; 403 /** Request semaphore. */ 404 RTSEMEVENT AsyncIORequestSem; 405 406 /** Task queue. */ 407 volatile uint8_t ahciIOTasks[2*AHCI_NR_COMMAND_SLOTS]; 408 /** Actual write position. */ 409 uint8_t uActWritePos; 410 /** Actual read position. */ 411 uint8_t uActReadPos; 412 /** Actual number of active tasks. */ 413 volatile uint32_t uActTasksActive; 390 /** Current number of active tasks. */ 391 volatile uint32_t cTasksActive; 414 392 415 393 /** Device is powered on. */ … … 423 401 /** Passthrough SCSI commands. */ 424 402 bool fATAPIPassthrough; 425 426 /** Device specific settings. */ 403 /** Flag whether this port is in a reset state. */ 404 volatile bool fPortReset; 405 /** If we use the new async interface. */ 406 bool fAsyncInterface; 407 /** Flag if we are in a device reset. */ 408 bool fResetDevice; 409 /** Flag whether the I/O thread idles. */ 410 volatile bool fAsyncIOThreadIdle; 411 /** Flag whether the port is in redo task mode. */ 412 volatile bool fRedo; 413 414 #if HC_ARCH_BITS == 64 415 bool fAlignment2; 416 #endif 417 418 /** Number of total sectors. */ 419 uint64_t cTotalSectors; 420 /** Currently configured number of sectors in a multi-sector transfer. */ 421 uint32_t cMultSectors; 422 /** Currently active transfer mode (MDMA/UDMA) and speed. */ 423 uint8_t uATATransferMode; 424 /** ATAPI sense data. */ 425 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 426 /** HACK: Countdown till we report a newly unmounted drive as mounted. */ 427 uint8_t cNotifiedMediaChange; 428 /** The same for GET_EVENT_STATUS for mechanism */ 429 volatile uint32_t MediaEventStatus; 430 /** Media type if known. */ 431 volatile uint32_t MediaTrackType; 432 /** The LUN. */ 433 RTUINT iLUN; 434 435 /** Bitmap for finished tasks (R3 -> Guest). */ 436 volatile uint32_t u32TasksFinished; 437 /** Bitmap for finished queued tasks (R3 -> Guest). */ 438 volatile uint32_t u32QueuedTasksFinished; 439 /** Bitmap for new queued tasks (Guest -> R3). */ 440 volatile uint32_t u32TasksNew; 441 442 /** Device specific settings (R3 only stuff). */ 427 443 /** Pointer to the attached driver's base interface. */ 428 444 R3PTRTYPE(PPDMIBASE) pDrvBase; … … 449 465 450 466 #if HC_ARCH_BITS == 64 451 uint32_t Alignment4;467 uint32_t u32Alignment3; 452 468 #endif 453 469 454 /** Number of total sectors. */ 455 uint64_t cTotalSectors; 456 /** Currently configured number of sectors in a multi-sector transfer. */ 457 uint32_t cMultSectors; 458 /** Currently active transfer mode (MDMA/UDMA) and speed. */ 459 uint8_t uATATransferMode; 460 /** ATAPI sense data. */ 461 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 462 /** HACK: Countdown till we report a newly unmounted drive as mounted. */ 463 uint8_t cNotifiedMediaChange; 464 /** The same for GET_EVENT_STATUS for mechanism */ 465 volatile uint32_t MediaEventStatus; 466 /** Media type if known. */ 467 volatile uint32_t MediaTrackType; 468 469 /** The LUN. */ 470 RTUINT iLUN; 471 /** Flag if we are in a device reset. */ 472 bool fResetDevice; 473 474 /** Bitmask for finished tasks. */ 475 volatile uint32_t u32TasksFinished; 476 /** Bitmask for finished queued tasks. */ 477 volatile uint32_t u32QueuedTasksFinished; 478 470 /** Async IO Thread. */ 471 R3PTRTYPE(PPDMTHREAD) pAsyncIOThread; 472 /** Request semaphore. */ 473 RTSEMEVENT AsyncIORequestSem; 479 474 /** 480 475 * Array of cached tasks. The tag number is the index value. … … 484 479 /** First task throwing an error. */ 485 480 R3PTRTYPE(volatile PAHCIPORTTASKSTATE) pTaskErr; 486 487 #if HC_ARCH_BITS == 32488 uint32_t u32Alignment7;489 #endif490 481 491 482 /** Release statistics: number of DMA commands. */ … … 507 498 STAMPROFILE StatProfileDestroyScatterGatherList; 508 499 #endif /* VBOX_WITH_STATISTICS */ 509 /** Flag whether a notification was already send to R3. */510 volatile bool fNotificationSend;511 /** Flag whether this port is in a reset state. */512 volatile bool fPortReset;513 /** Flag whether the I/O thread idles. */514 volatile bool fAsyncIOThreadIdle;515 500 516 501 /** The serial numnber to use for IDENTIFY DEVICE commands. */ … … 529 514 uint32_t cErrors; 530 515 531 /** Tasks to process */ 532 uint32_t cTasksToProcess; 533 /** Flag whether we need to redo a task. */ 534 bool fRedo; 535 516 #if HC_ARCH_BITS == 64 517 uint32_t u32Alignment4; 518 #endif 536 519 } AHCIPort; 537 520 /** Pointer to the state of an AHCI port. */ … … 640 623 641 624 /** Bitmask of ports which asserted an interrupt. */ 642 uint32_tu32PortsInterrupted;625 volatile uint32_t u32PortsInterrupted; 643 626 /** Device is in a reset state. */ 644 627 bool fReset; … … 665 648 /** Flag whether we have written the first 4bytes in an 8byte MMIO write successfully. */ 666 649 volatile bool f8ByteMMIO4BytesWrittenSuccessfully; 667 /** At which number of I/O requests per second we consider having high I/O load. */668 uint32_t cHighIOThreshold;669 /** How many milliseconds to sleep. */670 uint32_t cMillisToSleep;671 650 672 651 } AHCI; … … 863 842 #define AHCI_RECFIS_UFIS_OFFSET 0x60 /* Unknown FIS type */ 864 843 865 #define AHCI_TASK_IS_QUEUED(x) ((x) & 0x1)866 #define AHCI_TASK_GET_TAG(x) ((x) >> 1)867 #define AHCI_TASK_SET(tag, queued) (((tag) << 1) | (queued))868 869 844 /** 870 845 * AHCI register operator. … … 1035 1010 pAhciPort->regCI &= ~uCIValue; 1036 1011 1037 1038 if ((pAhciPort->regCMD & AHCI_PORT_CMD_ST) && (u32Value > 0)) 1039 { 1040 PDEVPORTNOTIFIERQUEUEITEM pItem; 1041 1042 /* Mark the tasks set in the value as used. */ 1043 for (uint8_t i = 0; i < AHCI_NR_COMMAND_SLOTS; i++) 1044 { 1045 /* Queue task if bit is set in written value and not already in progress. */ 1046 if (((u32Value >> i) & 0x01) && !(pAhciPort->regCI & (1 << i))) 1047 { 1048 if (!pAhciPort->fAsyncInterface) 1049 { 1050 /* Put the tag number of the task into the FIFO. */ 1051 uint8_t uTag = AHCI_TASK_SET(i, ((pAhciPort->regSACT & (1 << i)) ? 1 : 0)); 1052 ASMAtomicWriteU8(&pAhciPort->ahciIOTasks[pAhciPort->uActWritePos], uTag); 1053 ahciLog(("%s: Before uActWritePos=%u\n", __FUNCTION__, pAhciPort->uActWritePos)); 1054 pAhciPort->uActWritePos++; 1055 pAhciPort->uActWritePos %= RT_ELEMENTS(pAhciPort->ahciIOTasks); 1056 ahciLog(("%s: After uActWritePos=%u\n", __FUNCTION__, pAhciPort->uActWritePos)); 1057 1058 ASMAtomicIncU32(&pAhciPort->uActTasksActive); 1059 1060 bool fNotificationSend = ASMAtomicXchgBool(&pAhciPort->fNotificationSend, true); 1061 if (!fNotificationSend) 1062 { 1063 /* Send new notification. */ 1064 pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue)); 1065 AssertMsg(pItem, ("Allocating item for queue failed\n")); 1066 1067 pItem->iPort = pAhciPort->iLUN; 1068 PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem); 1069 } 1070 } 1071 else 1072 { 1073 pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue)); 1074 AssertMsg(pItem, ("Allocating item for queue failed\n")); 1075 1076 pItem->iPort = pAhciPort->iLUN; 1077 pItem->iTask = i; 1078 pItem->fQueued = !!(pAhciPort->regSACT & (1 << i)); /* Mark if the task is queued. */ 1079 PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem); 1080 } 1081 } 1012 if ( (pAhciPort->regCMD & AHCI_PORT_CMD_ST) 1013 && u32Value > 0) 1014 { 1015 uint32_t u32Tasks; 1016 1017 /* 1018 * Clear all tasks which are already marked as busy. The guest 1019 * shouldn't write already busy tasks actually. 1020 */ 1021 u32Value &= ~pAhciPort->regCI; 1022 1023 ASMAtomicOrU32(&pAhciPort->u32TasksNew, u32Value); 1024 u32Tasks = ASMAtomicReadU32(&pAhciPort->u32TasksNew); 1025 1026 /* Send a notification to R3 if u32TasksNew was before our write. */ 1027 if (!(u32Tasks ^ u32Value)) 1028 { 1029 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue)); 1030 AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n")); 1031 1032 pItem->iPort = pAhciPort->iLUN; 1033 PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem); 1082 1034 } 1083 1035 } … … 1172 1124 if (pAhciPort->pDrvBase) 1173 1125 { 1174 /* Reset queue. */1175 pAhciPort->uActWritePos = 0;1176 pAhciPort->uActReadPos = 0;1177 1126 ASMAtomicXchgBool(&pAhciPort->fPortReset, false); 1178 1127 … … 1612 1561 ahci->regHbaIs &= ~(u32Value); 1613 1562 1614 fClear = (!ahci->u32PortsInterrupted) && (!ahci->regHbaIs);1563 fClear = !ahci->u32PortsInterrupted && !ahci->regHbaIs; 1615 1564 if (fClear) 1616 1565 { … … 1906 1855 pAhciPort->fPoweredOn = true; 1907 1856 pAhciPort->fSpunUp = true; 1908 pAhciPort->fNotificationSend = false;1909 1857 pAhciPort->cMultSectors = ATA_MAX_MULT_SECTORS; 1910 1858 pAhciPort->uATATransferMode = ATA_MODE_UDMA | 6; 1911 1859 1860 pAhciPort->u32TasksNew = 0; 1912 1861 pAhciPort->u32TasksFinished = 0; 1913 1862 pAhciPort->u32QueuedTasksFinished = 0; 1914 1863 1915 pAhciPort->uActWritePos = 0; 1916 pAhciPort->uActReadPos = 0; 1917 pAhciPort->uActTasksActive = 0; 1864 pAhciPort->cTasksActive = 0; 1918 1865 1919 1866 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED); … … 4532 4479 * and it is possible to finish the reset now. 4533 4480 */ 4534 Assert(ASMAtomicReadU32(&pAhciPort-> uActTasksActive) == 0);4481 Assert(ASMAtomicReadU32(&pAhciPort->cTasksActive) == 0); 4535 4482 ahciFinishStorageDeviceReset(pAhciPort, pAhciPortTaskState); 4536 4483 } … … 5691 5638 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciPortTaskState, NULL); 5692 5639 } 5640 else 5641 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag)); 5693 5642 } 5694 5643 else … … 5711 5660 /* Add the task to the cache. */ 5712 5661 ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciPortTaskState->uTag], pAhciPortTaskState); 5713 ASMAtomicDecU32(&pAhciPort-> uActTasksActive);5662 ASMAtomicDecU32(&pAhciPort->cTasksActive); 5714 5663 5715 5664 if (!fRedo) … … 5752 5701 int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rcReq); 5753 5702 5754 if (pAhciPort-> uActTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)5703 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle) 5755 5704 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3); 5756 5705 return rc; … … 6154 6103 else 6155 6104 { 6156 AHCITXDIR enmTxDir; 6157 PAHCIPORTTASKSTATE pAhciPortTaskState; 6158 6159 ahciLog(("%s: Processing command at slot %d\n", __FUNCTION__, pNotifierItem->iTask)); 6160 6161 /* 6162 * Check if there is already an allocated task struct in the cache. 6163 * Allocate a new task otherwise. 6164 */ 6165 if (!pAhciPort->aCachedTasks[pNotifierItem->iTask]) 6166 { 6167 pAhciPortTaskState = (PAHCIPORTTASKSTATE)RTMemAllocZ(sizeof(AHCIPORTTASKSTATE)); 6168 AssertMsg(pAhciPortTaskState, ("%s: Cannot allocate task state memory!\n")); 6169 } 6170 else 6171 { 6172 pAhciPortTaskState = pAhciPort->aCachedTasks[pNotifierItem->iTask]; 6173 } 6105 unsigned idx = 0; 6106 uint32_t u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0); 6107 6108 idx = ASMBitFirstSetU32(u32Tasks); 6109 while (idx) 6110 { 6111 AHCITXDIR enmTxDir; 6112 PAHCIPORTTASKSTATE pAhciPortTaskState; 6113 6114 /* Decrement to get the slot number. */ 6115 idx--; 6116 ahciLog(("%s: Processing command at slot %d\n", __FUNCTION__, idx)); 6117 6118 /* 6119 * Check if there is already an allocated task struct in the cache. 6120 * Allocate a new task otherwise. 6121 */ 6122 if (!pAhciPort->aCachedTasks[idx]) 6123 { 6124 pAhciPortTaskState = (PAHCIPORTTASKSTATE)RTMemAllocZ(sizeof(AHCIPORTTASKSTATE)); 6125 AssertMsg(pAhciPortTaskState, ("%s: Cannot allocate task state memory!\n")); 6126 } 6127 else 6128 pAhciPortTaskState = pAhciPort->aCachedTasks[idx]; 6174 6129 6175 6130 #ifdef RT_STRICT 6176 bool fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, true, false);6177 AssertMsg(fXchg, ("Task is already active\n"));6131 bool fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, true, false); 6132 AssertMsg(fXchg, ("Task is already active\n")); 6178 6133 #endif 6179 6134 6180 pAhciPortTaskState->uATARegStatus = 0; 6181 pAhciPortTaskState->uATARegError = 0; 6182 6183 /** Set current command slot */ 6184 pAhciPortTaskState->uTag = pNotifierItem->iTask; 6185 pAhciPort->regCMD |= (AHCI_PORT_CMD_CCS_SHIFT(pAhciPortTaskState->uTag)); 6186 6187 ahciPortTaskGetCommandFis(pAhciPort, pAhciPortTaskState); 6188 6189 /* 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. */ 6190 if (pNotifierItem->fQueued) 6191 { 6192 pAhciPortTaskState->fQueued = true; 6193 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciPortTaskState->uTag)); 6194 } 6195 else 6196 pAhciPortTaskState->fQueued = false; 6197 6198 if (!(pAhciPortTaskState->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)) 6199 { 6200 /* If the reset bit is set put the device into reset state. */ 6201 if (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST) 6135 pAhciPortTaskState->uATARegStatus = 0; 6136 pAhciPortTaskState->uATARegError = 0; 6137 6138 /* Set current command slot */ 6139 pAhciPortTaskState->uTag = idx; 6140 pAhciPort->regCMD |= (AHCI_PORT_CMD_CCS_SHIFT(pAhciPortTaskState->uTag)); 6141 6142 ahciPortTaskGetCommandFis(pAhciPort, pAhciPortTaskState); 6143 6144 /* 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. */ 6145 if (pAhciPort->regSACT & (1 << idx)) 6202 6146 { 6203 ahciLog(("%s: Setting device into reset state\n", __FUNCTION__)); 6204 pAhciPort->fResetDevice = true; 6205 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true); 6206 pAhciPort->aCachedTasks[pNotifierItem->iTask] = pAhciPortTaskState; 6147 pAhciPortTaskState->fQueued = true; 6148 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciPortTaskState->uTag)); 6149 } 6150 else 6151 pAhciPortTaskState->fQueued = false; 6152 6153 if (!(pAhciPortTaskState->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)) 6154 { 6155 /* If the reset bit is set put the device into reset state. */ 6156 if (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST) 6157 { 6158 ahciLog(("%s: Setting device into reset state\n", __FUNCTION__)); 6159 pAhciPort->fResetDevice = true; 6160 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true); 6161 pAhciPort->aCachedTasks[idx] = pAhciPortTaskState; 6207 6162 #ifdef RT_STRICT 6208 fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, false, true);6209 AssertMsg(fXchg, ("Task is not active\n"));6163 fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, false, true); 6164 AssertMsg(fXchg, ("Task is not active\n")); 6210 6165 #endif 6211 return true; 6166 return true; 6167 } 6168 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */ 6169 { 6170 ahciFinishStorageDeviceReset(pAhciPort, pAhciPortTaskState); 6171 pAhciPort->aCachedTasks[idx] = pAhciPortTaskState; 6172 #ifdef RT_STRICT 6173 fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, false, true); 6174 AssertMsg(fXchg, ("Task is not active\n")); 6175 #endif 6176 return true; 6177 } 6178 else /* We are not in a reset state update the control registers. */ 6179 AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__)); 6212 6180 } 6213 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */6181 else 6214 6182 { 6215 ahciFinishStorageDeviceReset(pAhciPort, pAhciPortTaskState); 6216 pAhciPort->aCachedTasks[pNotifierItem->iTask] = pAhciPortTaskState; 6217 #ifdef RT_STRICT 6218 fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, false, true); 6219 AssertMsg(fXchg, ("Task is not active\n")); 6220 #endif 6221 return true; 6222 } 6223 else /* We are not in a reset state update the control registers. */ 6224 { 6225 AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__)); 6226 } 6227 } 6228 else 6229 { 6230 enmTxDir = ahciProcessCmd(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis); 6231 6232 if (enmTxDir != AHCITXDIR_NONE) 6233 { 6234 pAhciPortTaskState->enmTxDir = enmTxDir; 6235 6236 ahciLog(("%s: Before increment uActTasksActive=%u\n", __FUNCTION__, pAhciPort->uActTasksActive)); 6237 ASMAtomicIncU32(&pAhciPort->uActTasksActive); 6238 ahciLog(("%s: After increment uActTasksActive=%u\n", __FUNCTION__, pAhciPort->uActTasksActive)); 6239 6240 if (enmTxDir != AHCITXDIR_FLUSH) 6183 enmTxDir = ahciProcessCmd(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis); 6184 6185 if (enmTxDir != AHCITXDIR_NONE) 6241 6186 { 6242 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); 6243 6244 rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, (enmTxDir == AHCITXDIR_READ) ? false : true); 6245 if (RT_FAILURE(rc)) 6246 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc)); 6247 } 6248 6249 if (enmTxDir == AHCITXDIR_FLUSH) 6250 { 6251 rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync, 6252 pAhciPortTaskState); 6253 } 6254 else if (enmTxDir == AHCITXDIR_READ) 6255 { 6256 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 6257 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset, 6258 pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed, 6259 pAhciPortTaskState->cbTransfer, 6260 pAhciPortTaskState); 6187 pAhciPortTaskState->enmTxDir = enmTxDir; 6188 6189 ASMAtomicIncU32(&pAhciPort->cTasksActive); 6190 6191 if (enmTxDir != AHCITXDIR_FLUSH) 6192 { 6193 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); 6194 6195 rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, (enmTxDir == AHCITXDIR_READ) ? false : true); 6196 if (RT_FAILURE(rc)) 6197 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc)); 6198 } 6199 6200 if (enmTxDir == AHCITXDIR_FLUSH) 6201 { 6202 rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync, 6203 pAhciPortTaskState); 6204 } 6205 else if (enmTxDir == AHCITXDIR_READ) 6206 { 6207 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 6208 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset, 6209 pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed, 6210 pAhciPortTaskState->cbTransfer, 6211 pAhciPortTaskState); 6212 } 6213 else 6214 { 6215 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6216 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset, 6217 pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed, 6218 pAhciPortTaskState->cbTransfer, 6219 pAhciPortTaskState); 6220 } 6221 if (rc == VINF_VD_ASYNC_IO_FINISHED) 6222 rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, VINF_SUCCESS); 6223 else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS) 6224 rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rc); 6261 6225 } 6262 6226 else 6263 6227 { 6264 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6265 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset, 6266 pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed, 6267 pAhciPortTaskState->cbTransfer, 6268 pAhciPortTaskState); 6228 #ifdef RT_STRICT 6229 fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, false, true); 6230 AssertMsg(fXchg, ("Task is not active\n")); 6231 #endif 6232 6233 /* There is nothing left to do. Notify the guest. */ 6234 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true); 6235 /* Add the task to the cache. */ 6236 pAhciPort->aCachedTasks[pAhciPortTaskState->uTag] = pAhciPortTaskState; 6269 6237 } 6270 if (rc == VINF_VD_ASYNC_IO_FINISHED) 6271 rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, VINF_SUCCESS); 6272 6273 if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS) 6274 rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rc); 6275 } 6276 else 6277 { 6278 #ifdef RT_STRICT 6279 fXchg = ASMAtomicCmpXchgBool(&pAhciPortTaskState->fActive, false, true); 6280 AssertMsg(fXchg, ("Task is not active\n")); 6281 #endif 6282 6283 /* There is nothing left to do. Notify the guest. */ 6284 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true); 6285 /* Add the task to the cache. */ 6286 pAhciPort->aCachedTasks[pAhciPortTaskState->uTag] = pAhciPortTaskState; 6287 } 6288 } 6289 } 6238 } /* Command */ 6239 6240 u32Tasks &= ~(1 << idx); /* Clear task bit. */ 6241 idx = ASMBitFirstSetU32(u32Tasks); 6242 } /* while tasks available */ 6243 } /* fUseAsyncInterface */ 6290 6244 6291 6245 return true; … … 6303 6257 uint32_t uIORequestsProcessed = 0; 6304 6258 uint32_t uIOsPerSec = 0; 6305 uint32_t cTasksToProcess = 0;6306 bool fRedoDontWait = false;6259 uint32_t fTasksToProcess = 0; 6260 unsigned idx = 0; 6307 6261 6308 6262 ahciLog(("%s: Port %d entering async IO loop.\n", __FUNCTION__, pAhciPort->iLUN)); … … 6310 6264 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 6311 6265 return VINF_SUCCESS; 6312 6313 if (pAhciPort->fRedo)6314 {6315 /*6316 * We entered again after the VM was suspended due to a task failing.6317 * Use that task and try to process it again.6318 */6319 ahciLog(("%s: Port %d redo task\n", __FUNCTION__, pAhciPort->iLUN));6320 cTasksToProcess = pAhciPort->cTasksToProcess;6321 pAhciPort->cTasksToProcess = 0;6322 fRedoDontWait = true;6323 }6324 6266 6325 6267 /* We use only one task structure. */ … … 6333 6275 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 6334 6276 { 6335 6336 if (!fRedoDontWait) 6337 { 6338 /* New run to get number of I/O requests per second?. */ 6339 if (!u64StartTime) 6340 u64StartTime = RTTimeMilliTS(); 6341 6342 ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, true); 6343 if (pAhci->fSignalIdle) 6344 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3); 6345 6346 rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, 1000); 6347 if (rc == VERR_TIMEOUT) 6348 { 6349 /* No I/O requests inbetween. Reset statistics and wait again. */ 6350 pAhciPort->StatIORequestsPerSecond.c = 0; 6351 rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, RT_INDEFINITE_WAIT); 6352 } 6353 6354 if (RT_FAILURE(rc) || (pThread->enmState != PDMTHREADSTATE_RUNNING)) 6355 break; 6356 6357 /* 6358 * Don't process further tasks if the redo flag is set but wait again 6359 * until we got suspended. 6360 */ 6361 if (pAhciPort->fRedo) 6362 continue; 6363 6364 AssertMsg(pAhciPort->pDrvBase, ("I/O thread without attached device?!\n")); 6277 /* New run to get number of I/O requests per second?. */ 6278 if (!u64StartTime) 6279 u64StartTime = RTTimeMilliTS(); 6280 6281 ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, true); 6282 if (pAhci->fSignalIdle) 6283 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3); 6284 6285 rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, 1000); 6286 if (rc == VERR_TIMEOUT) 6287 { 6288 /* No I/O requests inbetween. Reset statistics and wait again. */ 6289 pAhciPort->StatIORequestsPerSecond.c = 0; 6290 rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, RT_INDEFINITE_WAIT); 6365 6291 } 6366 else 6367 fRedoDontWait = false; 6292 6293 if (RT_FAILURE(rc) || (pThread->enmState != PDMTHREADSTATE_RUNNING)) 6294 break; 6295 6296 /* Go to sleep again if we are in redo mode. */ 6297 if (RT_UNLIKELY(pAhciPort->fRedo)) 6298 continue; 6299 6300 AssertMsg(pAhciPort->pDrvBase, ("I/O thread without attached device?!\n")); 6368 6301 6369 6302 ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, false); 6370 6371 if (!pAhciPort->fRedo) 6372 { 6373 /* 6374 * To maximize the throughput of the controller we try to minimize the 6375 * number of world switches during interrupts by grouping as many 6376 * I/O requests together as possible. 6377 * On the other side we want to get minimal latency if the I/O load is low. 6378 * Thatswhy the number of I/O requests per second is measured and if it is over 6379 * a threshold the thread waits for other requests from the guest. 6380 */ 6381 if (uIOsPerSec >= pAhci->cHighIOThreshold) 6382 { 6383 uint8_t uActWritePosPrev = pAhciPort->uActWritePos; 6384 6385 Log(("%s: Waiting for more tasks to get queued\n", __FUNCTION__)); 6386 6387 do 6388 { 6389 /* Sleep some time. */ 6390 RTThreadSleep(pAhci->cMillisToSleep); 6391 /* Check if we got some new requests inbetween. */ 6392 if (uActWritePosPrev != pAhciPort->uActWritePos) 6393 { 6394 uActWritePosPrev = pAhciPort->uActWritePos; 6395 /* 6396 * Check if the queue is full. If that is the case 6397 * there is no point waiting another round. 6398 */ 6399 if ( ( (pAhciPort->uActReadPos < uActWritePosPrev) 6400 && (uActWritePosPrev - pAhciPort->uActReadPos) == AHCI_NR_COMMAND_SLOTS) 6401 || ( (pAhciPort->uActReadPos > uActWritePosPrev) 6402 && (RT_ELEMENTS(pAhciPort->ahciIOTasks) - pAhciPort->uActReadPos + uActWritePosPrev) == AHCI_NR_COMMAND_SLOTS) ) 6403 { 6404 Log(("%s: Queue full -> leaving\n", __FUNCTION__)); 6405 break; 6406 } 6407 Log(("%s: Another round\n", __FUNCTION__)); 6408 } 6409 else /* No change break out of the loop. */ 6410 { 6411 #ifdef DEBUG 6412 uint8_t uQueuedTasks; 6413 if (pAhciPort->uActReadPos < uActWritePosPrev) 6414 uQueuedTasks = uActWritePosPrev - pAhciPort->uActReadPos; 6415 else 6416 uQueuedTasks = RT_ELEMENTS(pAhciPort->ahciIOTasks) - pAhciPort->uActReadPos + uActWritePosPrev; 6417 6418 Log(("%s: %u Tasks are queued\n", __FUNCTION__, uQueuedTasks)); 6419 #endif 6420 break; 6421 } 6422 } while (true); 6423 } 6424 6425 cTasksToProcess = ASMAtomicXchgU32(&pAhciPort->uActTasksActive, 0); 6426 6427 ahciLog(("%s: Processing %u requests\n", __FUNCTION__, cTasksToProcess)); 6428 } /* fRedo */ 6429 else 6430 pAhciPort->fRedo = false; 6431 6432 ASMAtomicXchgBool(&pAhciPort->fNotificationSend, false); 6303 fTasksToProcess = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0); 6304 6305 idx = ASMBitFirstSetU32(fTasksToProcess); 6433 6306 6434 6307 /* Process commands. */ 6435 while ( (cTasksToProcess > 0) 6436 && RT_LIKELY(!pAhciPort->fRedo) 6308 while ( idx 6437 6309 && RT_LIKELY(!pAhciPort->fPortReset)) 6438 6310 { 6439 6311 AHCITXDIR enmTxDir; 6440 uint8_t uActTag; 6441 6312 6313 idx--; 6442 6314 STAM_PROFILE_START(&pAhciPort->StatProfileProcessTime, a); 6443 6444 ahciLog(("%s: uActWritePos=%u\n", __FUNCTION__, pAhciPort->uActWritePos));6445 ahciLog(("%s: Before uActReadPos=%u\n", __FUNCTION__, pAhciPort->uActReadPos));6446 6315 6447 6316 pAhciPortTaskState->uATARegStatus = 0; 6448 6317 pAhciPortTaskState->uATARegError = 0; 6449 uActTag = pAhciPort->ahciIOTasks[pAhciPort->uActReadPos]; 6450 6451 pAhciPortTaskState->uTag = AHCI_TASK_GET_TAG(uActTag); 6318 pAhciPortTaskState->uTag = idx; 6452 6319 AssertMsg(pAhciPortTaskState->uTag < AHCI_NR_COMMAND_SLOTS, ("%s: Invalid Tag number %u!!\n", __FUNCTION__, pAhciPortTaskState->uTag)); 6453 6320 6454 /* *Set current command slot */6321 /* Set current command slot */ 6455 6322 pAhciPort->regCMD |= (AHCI_PORT_CMD_CCS_SHIFT(pAhciPortTaskState->uTag)); 6456 6323 6457 6324 /* 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. */ 6458 if ( AHCI_TASK_IS_QUEUED(uActTag))6325 if (pAhciPort->regSACT & (1 << idx)) 6459 6326 { 6460 6327 pAhciPortTaskState->fQueued = true; … … 6462 6329 } 6463 6330 else 6464 {6465 6331 pAhciPortTaskState->fQueued = false; 6466 }6467 6332 6468 6333 ahciPortTaskGetCommandFis(pAhciPort, pAhciPortTaskState); … … 6509 6374 } 6510 6375 else 6511 pAhciPort->cTasksToProcess = cTasksToProcess; 6376 { 6377 /* Add the task to the mask again. */ 6378 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag)); 6379 } 6512 6380 } 6513 6381 else … … 6618 6486 else 6619 6487 { 6620 pAhciPort->cTasksToProcess = cTasksToProcess;6621 pAhciPort->fRedo = true;6488 /* Add the task to the mask again. */ 6489 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag)); 6622 6490 } 6623 6491 } … … 6664 6532 pAhciPortTaskState->uOffset = 0; 6665 6533 pAhciPortTaskState->cbTransfer = 0; 6666 /* Make the port number invalid making it easier to track down bugs. */6667 pAhciPort->ahciIOTasks[pAhciPort->uActReadPos] = 0xff;6668 6534 #endif 6669 6670 pAhciPort->uActReadPos++;6671 pAhciPort->uActReadPos %= RT_ELEMENTS(pAhciPort->ahciIOTasks);6672 ahciLog(("%s: After uActReadPos=%u\n", __FUNCTION__, pAhciPort->uActReadPos));6673 cTasksToProcess--;6674 6535 6675 6536 /* If we encountered an error notify the guest and continue with the next task. */ … … 6680 6541 ahciSendSDBFis(pAhciPort, 0, true); 6681 6542 } 6682 else if (!cTasksToProcess)6683 cTasksToProcess = ASMAtomicXchgU32(&pAhciPort->uActTasksActive, 0);6684 6543 } 6685 } 6544 fTasksToProcess &= ~(1 << idx); 6545 idx = ASMBitFirstSetU32(fTasksToProcess); 6546 } /* while tasks to process */ 6686 6547 6687 6548 if ( ASMAtomicReadU32(&pAhciPort->u32QueuedTasksFinished) != 0 … … 6795 6656 pHlp->pfnPrintf(pHlp, "PortPhysClb=%RGp\n", pThisPort->GCPhysAddrClb); 6796 6657 pHlp->pfnPrintf(pHlp, "PortPhysFb=%RGp\n", pThisPort->GCPhysAddrFb); 6797 pHlp->pfnPrintf(pHlp, "PortActWritePos=%u\n", pThisPort->uActWritePos); 6798 pHlp->pfnPrintf(pHlp, "PortActReadPos=%u\n", pThisPort->uActReadPos); 6799 pHlp->pfnPrintf(pHlp, "PortActTasksActive=%u\n", pThisPort->uActTasksActive); 6658 pHlp->pfnPrintf(pHlp, "PortActTasksActive=%u\n", pThisPort->cTasksActive); 6800 6659 pHlp->pfnPrintf(pHlp, "PortPoweredOn=%RTbool\n", pThisPort->fPoweredOn); 6801 6660 pHlp->pfnPrintf(pHlp, "PortSpunUp=%RTbool\n", pThisPort->fSpunUp); … … 6804 6663 pHlp->pfnPrintf(pHlp, "PortTasksFinished=%#x\n", pThisPort->u32TasksFinished); 6805 6664 pHlp->pfnPrintf(pHlp, "PortQueuedTasksFinished=%#x\n", pThisPort->u32QueuedTasksFinished); 6806 pHlp->pfnPrintf(pHlp, "PortNotificationSend=%RTbool\n", pThisPort->fNotificationSend);6807 6665 pHlp->pfnPrintf(pHlp, "PortAsyncIoThreadIdle=%RTbool\n", pThisPort->fAsyncIOThreadIdle); 6808 6666 pHlp->pfnPrintf(pHlp, "\n"); … … 6832 6690 bool fFinished; 6833 6691 if (pThisPort->fAsyncInterface) 6834 fFinished = (pThisPort-> uActTasksActive == 0);6692 fFinished = (pThisPort->cTasksActive == 0); 6835 6693 else 6836 fFinished = ((pThisPort-> uActTasksActive == 0 || pThisPort->fRedo) && (pThisPort->fAsyncIOThreadIdle));6694 fFinished = ((pThisPort->cTasksActive == 0) && (pThisPort->fAsyncIOThreadIdle)); 6837 6695 if (!fFinished) 6838 6696 return false; … … 6932 6790 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++) 6933 6791 { 6934 Assert(pThis->ahciPort[i]. uActTasksActive == 0);6792 Assert(pThis->ahciPort[i].cTasksActive == 0); 6935 6793 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCLB); 6936 6794 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCLBU); … … 6957 6815 SSMR3PutBool(pSSM, pThis->ahciPort[i].fResetDevice); 6958 6816 6959 /* No need to save */ 6960 SSMR3PutU8(pSSM, pThis->ahciPort[i].uActWritePos); 6961 SSMR3PutU8(pSSM, pThis->ahciPort[i].uActReadPos); 6817 /* No need to save but to avoid changing the SSM format they are still written. */ 6818 SSMR3PutU8(pSSM, 0); /* Prev: Write position in the FIFO. */ 6819 SSMR3PutU8(pSSM, 0); /* Prev: Read position in the FIFO. */ 6820 6962 6821 SSMR3PutBool(pSSM, pThis->ahciPort[i].fPoweredOn); 6963 6822 SSMR3PutBool(pSSM, pThis->ahciPort[i].fSpunUp); … … 7083 6942 SSMR3GetU32(pSSM, &pThis->uCccCurrentNr); 7084 6943 7085 SSMR3GetU32(pSSM, &pThis->u32PortsInterrupted);6944 SSMR3GetU32(pSSM, (uint32_t *)&pThis->u32PortsInterrupted); 7086 6945 SSMR3GetBool(pSSM, &pThis->fReset); 7087 6946 SSMR3GetBool(pSSM, &pThis->f64BitAddr); … … 7092 6951 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++) 7093 6952 { 6953 uint8_t u8; 7094 6954 PAHCIPort pAhciPort = &pThis->ahciPort[i]; 7095 6955 … … 7121 6981 SSMR3Skip(pSSM, AHCI_NR_COMMAND_SLOTS * sizeof(uint8_t)); /* no active data here */ 7122 6982 7123 SSMR3GetU8(pSSM, & pThis->ahciPort[i].uActWritePos);7124 SSMR3GetU8(pSSM, & pThis->ahciPort[i].uActReadPos);6983 SSMR3GetU8(pSSM, &u8); 6984 SSMR3GetU8(pSSM, &u8); 7125 6985 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fPoweredOn); 7126 6986 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fSpunUp); … … 7142 7002 uint32_t fQueuedTasksOutstanding = pAhciPort->regSACT & ~pAhciPort->u32QueuedTasksFinished; 7143 7003 7144 if (fTasksOutstanding || fQueuedTasksOutstanding) 7004 pAhciPort->u32TasksNew = fTasksOutstanding | fQueuedTasksOutstanding; 7005 7006 if (pAhciPort->u32TasksNew) 7145 7007 { 7146 7008 /* 7147 7009 * There are tasks pending. The VM was saved after a task failed 7148 * because of non-fatal error. Set the redo flag 7149 * and the correct cTasksToProcess number based on the difference 7150 * of the FIFO counters. 7010 * because of non-fatal error. Set the redo flag. 7151 7011 */ 7152 7153 if (!pAhciPort->fAsyncInterface) 7154 { 7155 /* 7156 * Because we don't save the task FIFO we have to reconstruct it by using the 7157 * SACT and CI registers along with the shadowed variables containing the 7158 * completed tasks and placing them in the FIFO again. 7159 */ 7160 pAhciPort->fRedo = true; 7161 7162 pAhciPort->uActWritePos = 0; 7163 pAhciPort->uActReadPos = 0; 7164 7165 for (unsigned uTag = 0; uTag < AHCI_NR_COMMAND_SLOTS; uTag++) 7166 { 7167 if ( fTasksOutstanding & (1 << uTag) 7168 || fQueuedTasksOutstanding & (1 << uTag)) 7169 { 7170 pAhciPort->ahciIOTasks[pAhciPort->uActWritePos] = AHCI_TASK_SET(uTag, (fQueuedTasksOutstanding & (1 << uTag)) ? 1 : 0); 7171 pAhciPort->uActWritePos++; 7172 pAhciPort->uActWritePos %= RT_ELEMENTS(pAhciPort->ahciIOTasks); 7173 pAhciPort->cTasksToProcess++; 7174 } 7175 } 7176 } 7177 else 7178 { 7179 /* Use the PDM queue. */ 7180 for (unsigned uTag = 0; uTag < AHCI_NR_COMMAND_SLOTS; uTag++) 7181 { 7182 if ( fTasksOutstanding & (1 << uTag) 7183 || fQueuedTasksOutstanding & (1 << uTag)) 7184 { 7185 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pThis->CTX_SUFF(pNotifierQueue)); 7186 AssertMsg(pItem, ("Allocating item for queue failed\n")); 7187 7188 pItem->iPort = pThis->ahciPort[i].iLUN; 7189 pItem->iTask = uTag; 7190 pItem->fQueued = !!(fQueuedTasksOutstanding & (1 << uTag)); /* Mark if the task is queued. */ 7191 PDMQueueInsert(pThis->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem); 7192 } 7193 } 7194 } 7012 pAhciPort->fRedo = true; 7195 7013 } 7196 7014 } … … 7569 7387 7570 7388 /* 7571 * Check if one of the ports has the redo flag set7572 * and queue all pending tasks again.7389 * Check if one of the ports has pending tasks. 7390 * Queue a notification item again in this case. 7573 7391 */ 7574 7392 for (unsigned i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++) … … 7576 7394 PAHCIPort pAhciPort = &pAhci->ahciPort[i]; 7577 7395 7578 if ( pAhciPort->fRedo7579 && pAhciPort->fAsyncInterface)7580 {7581 uint32_t fTasksOutstanding = pAhciPort->regCI & ~pAhciPort->u32TasksFinished;7582 uint32_t fQueuedTasksOutstanding = pAhciPort->regSACT & ~pAhciPort->u32QueuedTasksFinished; 7583 7396 if (pAhciPort->u32TasksNew) 7397 { 7398 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue)); 7399 AssertMsg(pItem, ("Allocating item for queue failed\n")); 7400 7401 Assert(pAhciPort->fRedo); 7584 7402 pAhciPort->fRedo = false; 7585 7403 7586 /* Use the PDM queue. */ 7587 for (unsigned uTag = 0; uTag < AHCI_NR_COMMAND_SLOTS; uTag++) 7588 { 7589 if ( fTasksOutstanding & (1 << uTag) 7590 || fQueuedTasksOutstanding & (1 << uTag)) 7591 { 7592 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue)); 7593 AssertMsg(pItem, ("Allocating item for queue failed\n")); 7594 7595 pItem->iPort = pAhci->ahciPort[i].iLUN; 7596 pItem->iTask = uTag; 7597 pItem->fQueued = !!(fQueuedTasksOutstanding & (1 << uTag)); /* Mark if the task is queued. */ 7598 PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem); 7599 } 7600 } 7404 pItem->iPort = pAhci->ahciPort[i].iLUN; 7405 PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem); 7601 7406 } 7602 7407 } … … 7867 7672 "SecondarySlave\0" 7868 7673 "PortCount\0" 7869 "UseAsyncInterfaceIfAvailable\0" 7870 "HighIOThreshold\0" 7871 "MillisToSleep\0")) 7674 "UseAsyncInterfaceIfAvailable\0")) 7872 7675 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, 7873 7676 N_("AHCI configuration error: unknown option specified")); … … 7903 7706 return PDMDEV_SET_ERROR(pDevIns, rc, 7904 7707 N_("AHCI configuration error: failed to read UseAsyncInterfaceIfAvailable as boolean")); 7905 rc = CFGMR3QueryU32Def(pCfg, "HighIOThreshold", &pThis->cHighIOThreshold, ~0);7906 if (RT_FAILURE(rc))7907 return PDMDEV_SET_ERROR(pDevIns, rc,7908 N_("AHCI configuration error: failed to read HighIOThreshold as integer"));7909 rc = CFGMR3QueryU32Def(pCfg, "MillisToSleep", &pThis->cMillisToSleep, 0);7910 if (RT_FAILURE(rc))7911 return PDMDEV_SET_ERROR(pDevIns, rc,7912 N_("AHCI configuration error: failed to read MillisToSleep as integer"));7913 7708 7914 7709 pThis->fR0Enabled = fR0Enabled; … … 8033 7828 8034 7829 /* 8035 * Create the transmit queue. 7830 * Create the notification queue. 7831 * 7832 * We need 2 items for every port because of SMP races. 8036 7833 */ 8037 rc = PDMDevHlpQueueCreate(pDevIns, sizeof(DEVPORTNOTIFIERQUEUEITEM), 30*32 /*Maximum of 30 ports multiplied with 32 tasks each port*/, 0,7834 rc = PDMDevHlpQueueCreate(pDevIns, sizeof(DEVPORTNOTIFIERQUEUEITEM), AHCI_MAX_NR_PORTS_IMPL*2, 0, 8038 7835 ahciNotifyQueueConsumer, true, "AHCI-Xmit", &pThis->pNotifierQueueR3); 8039 7836 if (RT_FAILURE(rc)) … … 8240 8037 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 8241 8038 N_("AHCI: Failed to attach drive to %s"), szName); 8242 8243 #ifdef DEBUG8244 for (uint32_t j = 0; j < AHCI_NR_COMMAND_SLOTS; j++)8245 pAhciPort->ahciIOTasks[j] = 0xff;8246 #endif8247 8039 } 8248 8040
Note:
See TracChangeset
for help on using the changeset viewer.