Changeset 64018 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Sep 26, 2016 4:29:33 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r64016 r64018 234 234 * @returns VBox status code. 235 235 * @param pAhciReq The task state. 236 * @param pSgBuf Buffer holding the data to process. 237 * @param cbBuf Size of the buffer. 238 * @param offBuf Offset into the guest buffer. 236 239 * @param ppvProc Where to store the pointer to the buffer holding the processed data on success. 237 240 * Must be freed with RTMemFree(). 238 241 * @param pcbProc Where to store the size of the buffer on success. 239 242 */ 240 typedef DECLCALLBACK(int) FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc); 243 typedef DECLCALLBACK(int) FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, PRTSGBUF pSgBuf, size_t cbBuf, 244 uint32_t offBuf, void **ppvProc, size_t *pcbProc); 241 245 /** Pointer to a FNAHCIPOSTPROCESS() function. */ 242 246 typedef FNAHCIPOSTPROCESS *PFNAHCIPOSTPROCESS; … … 271 275 /** Physical address of the command header. - GC */ 272 276 RTGCPHYS GCPhysCmdHdrAddr; 273 /** Physical address if the PRDT */277 /** Physical address of the PRDT */ 274 278 RTGCPHYS GCPhysPrdtl; 275 279 /** Number of entries in the PRDTL. */ … … 283 287 /** Flags for this task. */ 284 288 uint32_t fFlags; 285 /** Additional memory allocation for this task. */ 286 void *pvAlloc; 287 /** Siize of the allocation. */ 288 size_t cbAlloc; 289 /** Number of times we had too much memory allocated for the request. */ 290 unsigned cAllocTooMuch; 291 /** Data dependent on the transfer direction. */ 292 union 293 { 294 /** Data for an I/O request. */ 295 struct 296 { 297 /** Data segment. */ 298 RTSGSEG DataSeg; 299 /** Post processing callback. 300 * If this is set we will use a buffer for the data 301 * and the callback returns a buffer with the final data. */ 302 PFNAHCIPOSTPROCESS pfnPostProcess; 303 } Io; 304 } u; 289 /** Post processing callback. 290 * If this is set we will use a buffer for the data 291 * and the callback returns a buffer with the final data. */ 292 PFNAHCIPOSTPROCESS pfnPostProcess; 305 293 } AHCIREQ; 306 294 … … 320 308 * @implements PDMIBASE 321 309 * @implements PDMIMEDIAPORT 322 * @implements PDMIMEDIA ASYNCPORT310 * @implements PDMIMEDIAEXPORT 323 311 * @implements PDMIMOUNTNOTIFY 324 312 */ … … 681 669 AssertCompileSize(SGLEntry, 16); 682 670 671 #ifdef IN_RING3 672 /** 673 * Memory buffer callback. 674 * 675 * @returns nothing. 676 * @param pThis The NVME controller instance. 677 * @param GCPhys The guest physical address of the memory buffer. 678 * @param pSgBuf The pointer to the host R3 S/G buffer. 679 * @param cbCopy How many bytes to copy between the two buffers. 680 * @param pcbSkip Initially contains the amount of bytes to skip 681 * starting from the guest physical address before 682 * accessing the S/G buffer and start copying data. 683 * On return this contains the remaining amount if 684 * cbCopy < *pcbSkip or 0 otherwise. 685 */ 686 typedef DECLCALLBACK(void) AHCIR3MEMCOPYCALLBACK(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy, 687 size_t *pcbSkip); 688 /** Pointer to a memory copy buffer callback. */ 689 typedef AHCIR3MEMCOPYCALLBACK *PAHCIR3MEMCOPYCALLBACK; 690 #endif 691 683 692 /** Defines for a scatter gather list entry. */ 684 693 #define SGLENTRY_DBA_READONLY ~(RT_BIT(0)) … … 887 896 static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis); 888 897 static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort); 889 static uint32_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, const void *pvBuf, size_t cbBuf); 890 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, void *pvBuf, size_t cbBuf); 898 static size_t ahciR3CopyBufferToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, const void *pvSrc, 899 size_t cbSrc, size_t cbSkip); 900 static size_t ahciR3CopyBufferFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, void *pvDst, size_t cbDst); 891 901 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort); 892 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree);893 902 #endif 894 903 RT_C_DECLS_END … … 3238 3247 3239 3248 /* Copy the buffer in to the scatter gather list. */ 3240 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&p[0], RT_MIN(cbData, sizeof(p))); 3249 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&p[0], 3250 RT_MIN(cbData, sizeof(p)), 0 /* cbSkip */); 3241 3251 3242 3252 atapiCmdOK(pAhciPort, pAhciReq); … … 3252 3262 3253 3263 /* Copy the buffer in to the scatter gather list. */ 3254 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3264 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3265 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3255 3266 3256 3267 atapiCmdOK(pAhciPort, pAhciReq); … … 3279 3290 3280 3291 /* Copy the buffer in to the scatter gather list. */ 3281 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3292 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3293 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3282 3294 3283 3295 atapiCmdOK(pAhciPort, pAhciReq); … … 3309 3321 3310 3322 /* Copy the buffer in to the scatter gather list. */ 3311 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3323 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3324 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3312 3325 3313 3326 atapiCmdOK(pAhciPort, pAhciReq); … … 3490 3503 3491 3504 /* Copy the buffer in to the scatter gather list. */ 3492 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3505 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3506 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3493 3507 3494 3508 atapiCmdOK(pAhciPort, pAhciReq); … … 3566 3580 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus)); 3567 3581 3568 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&abBuf[0], RT_MIN(cbData, sizeof(abBuf))); 3582 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&abBuf[0], 3583 RT_MIN(cbData, sizeof(abBuf)), 0 /* cbSkip */); 3569 3584 3570 3585 atapiCmdOK(pAhciPort, pAhciReq); … … 3590 3605 3591 3606 /* Copy the buffer in to the scatter gather list. */ 3592 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3607 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3608 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3593 3609 3594 3610 atapiCmdOK(pAhciPort, pAhciReq); … … 3619 3635 3620 3636 /* Copy the buffer in to the scatter gather list. */ 3621 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3637 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3638 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3622 3639 3623 3640 atapiCmdOK(pAhciPort, pAhciReq); … … 3669 3686 3670 3687 /* Copy the buffer in to the scatter gather list. */ 3671 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3688 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3689 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3672 3690 3673 3691 atapiCmdOK(pAhciPort, pAhciReq); … … 3679 3697 { 3680 3698 /* Copy the buffer in to the scatter gather list. */ 3681 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, 3682 pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense))); 3699 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, 3700 pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense)), 3701 0 /* cbSkip */); 3683 3702 3684 3703 atapiCmdOK(pAhciPort, pAhciReq); … … 3700 3719 3701 3720 /* Copy the buffer in to the scatter gather list. */ 3702 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3721 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3722 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3703 3723 3704 3724 atapiCmdOK(pAhciPort, pAhciReq); … … 3762 3782 3763 3783 /* Copy the buffer in to the scatter gather list. */ 3764 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, cbSize)); 3784 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3785 RT_MIN(cbData, cbSize), 0 /* cbSkip */); 3765 3786 3766 3787 atapiCmdOK(pAhciPort, pAhciReq); … … 3795 3816 3796 3817 /* Copy the buffer in to the scatter gather list. */ 3797 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf))); 3818 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3819 RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */); 3798 3820 3799 3821 atapiCmdOK(pAhciPort, pAhciReq); … … 3883 3905 3884 3906 /* Copy the buffer in to the scatter gather list. */ 3885 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, cbSize)); 3907 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 3908 RT_MIN(cbData, cbSize), 0 /* cbSkip */); 3886 3909 3887 3910 atapiCmdOK(pAhciPort, pAhciReq); … … 3915 3938 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 3916 3939 { 3917 ahci CopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);3940 ahciR3CopyBufferFromPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, pvBuf, cbTransfer); 3918 3941 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW) 3919 3942 return VINF_SUCCESS; … … 4104 4127 4105 4128 /* Reply with the same amount of data as the real drive. */ 4106 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer); 4129 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, pvBuf, 4130 cbTransfer, 0 /* cbSkip */); 4107 4131 } 4108 4132 else … … 4295 4319 4296 4320 /* Copy the buffer into the scatter gather list. */ 4297 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, max_len)); 4321 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0], 4322 RT_MIN(cbData, max_len), 0 /* cbSkip */); 4298 4323 4299 4324 atapiCmdOK(pAhciPort, pAhciReq); … … 4319 4344 } 4320 4345 4321 static DECLCALLBACK(int) atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc) 4346 static DECLCALLBACK(int) atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, PRTSGBUF pSgBuf, size_t cbBuf, 4347 uint32_t offBuf, void **ppvProc, size_t *pcbProc) 4322 4348 { 4323 4349 uint8_t *pbBuf = NULL; 4324 uint32_t cSectors = pAhciReq->cbTransfer / 2048; 4325 uint32_t iATAPILBA = pAhciReq->uOffset / 2048; 4326 uint8_t *pbBufDst; 4327 uint8_t *pbBufSrc = (uint8_t *)pAhciReq->u.Io.DataSeg.pvSeg; 4328 size_t cbAlloc = pAhciReq->cbTransfer + cSectors * (1 + 11 + 3 + 1 + 288); /* Per sector data like ECC. */ 4350 uint32_t cSectorsOff = offBuf / 2048; 4351 uint32_t cSectors = cbBuf / 2048; 4352 uint32_t iATAPILBA = cSectorsOff + pAhciReq->uOffset / 2048; 4353 size_t cbAlloc = cbBuf + cSectors * (1 + 11 + 3 + 1 + 288); /* Per sector data like ECC. */ 4354 4355 AssertReturn((offBuf % 2048 == 0) && (cbBuf % 2048 == 0), VERR_INVALID_STATE); 4329 4356 4330 4357 pbBuf = (uint8_t *)RTMemAlloc(cbAlloc); … … 4332 4359 return VERR_NO_MEMORY; 4333 4360 4334 pbBufDst = pbBuf;4361 uint8_t *pbBufDst = pbBuf; 4335 4362 4336 4363 for (uint32_t i = iATAPILBA; i < iATAPILBA + cSectors; i++) … … 4345 4372 *pbBufDst++ = 0x01; /* mode 1 data */ 4346 4373 /* data */ 4347 memcpy(pbBufDst, pbBufSrc, 2048);4374 RTSgBufCopyToBuf(pSgBuf, pbBufDst, 2048); 4348 4375 pbBufDst += 2048; 4349 pbBufSrc += 2048;4350 4376 /* ECC */ 4351 4377 memset(pbBufDst, 0, 288); … … 4355 4381 *ppvProc = pbBuf; 4356 4382 *pcbProc = cbAlloc; 4357 4358 4383 return VINF_SUCCESS; 4359 4384 } … … 4372 4397 case 2352: 4373 4398 { 4374 pAhciReq-> u.Io.pfnPostProcess = atapiReadSectors2352PostProcess;4399 pAhciReq->pfnPostProcess = atapiReadSectors2352PostProcess; 4375 4400 pAhciReq->uOffset = (uint64_t)iATAPILBA * 2048; 4376 4401 pAhciReq->cbTransfer = cSectors * 2048; … … 4616 4641 PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns); 4617 4642 4618 /*4619 * Also make sure that the current request has no memory allocated4620 * from the driver below us. We don't require it here anyway.4621 */4622 ahciReqMemFree(pAhciPort, pAhciReq, true /* fForceFree */);4623 4624 4643 rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 4625 4644 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3, … … 5461 5480 5462 5481 /** 5463 * Allocates memory for the given request using already allocated memory if possible.5482 * Copy from guest to host memory worker. 5464 5483 * 5465 * @returns Pointer to the memory or NULL on failure 5466 * @param pAhciPort The AHCI port. 5467 * @param pAhciReq The request to allocate memory for. 5468 * @param cb The amount of memory to allocate. 5469 */ 5470 static void *ahciReqMemAlloc(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cb) 5471 { 5472 if (pAhciReq->cbAlloc > cb) 5473 { 5474 pAhciReq->cAllocTooMuch++; 5475 } 5476 else if (pAhciReq->cbAlloc < cb) 5477 { 5478 if (pAhciReq->cbAlloc) 5479 pAhciPort->pDrvMedia->pfnIoBufFree(pAhciPort->pDrvMedia, pAhciReq->pvAlloc, pAhciReq->cbAlloc); 5480 5481 pAhciReq->pvAlloc = NULL; 5482 pAhciReq->cbAlloc = RT_ALIGN_Z(cb, _4K); 5483 int rc = pAhciPort->pDrvMedia->pfnIoBufAlloc(pAhciPort->pDrvMedia, pAhciReq->cbAlloc, &pAhciReq->pvAlloc); 5484 if (RT_FAILURE(rc)) 5485 pAhciReq->pvAlloc = NULL; 5486 5487 pAhciReq->cAllocTooMuch = 0; 5488 if (RT_UNLIKELY(!pAhciReq->pvAlloc)) 5489 pAhciReq->cbAlloc = 0; 5490 } 5491 5492 return pAhciReq->pvAlloc; 5493 } 5494 5495 /** 5496 * Frees memory allocated for the given request. 5484 * @copydoc{AHCIR3MEMCOPYCALLBACK} 5485 */ 5486 static DECLCALLBACK(void) ahciR3CopyBufferFromGuestWorker(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, 5487 size_t cbCopy, size_t *pcbSkip) 5488 { 5489 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip); 5490 cbCopy -= cbSkipped; 5491 GCPhys += cbSkipped; 5492 *pcbSkip -= cbSkipped; 5493 5494 while (cbCopy) 5495 { 5496 size_t cbSeg = cbCopy; 5497 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg); 5498 5499 AssertPtr(pvSeg); 5500 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg); 5501 GCPhys += cbSeg; 5502 cbCopy -= cbSeg; 5503 } 5504 } 5505 5506 /** 5507 * Copy from host to guest memory worker. 5497 5508 * 5498 * @returns nothing. 5499 * @param pAhciPort The AHCI port. 5500 * @param pAhciReq The request. 5501 * @param fForceFree Flag whether to force a free 5502 */ 5503 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree) 5504 { 5505 if ( pAhciReq->cAllocTooMuch >= AHCI_MAX_ALLOC_TOO_MUCH 5506 || fForceFree) 5507 { 5508 if (pAhciReq->cbAlloc) 5509 { 5510 pAhciPort->pDrvMedia->pfnIoBufFree(pAhciPort->pDrvMedia, pAhciReq->pvAlloc, pAhciReq->cbAlloc); 5511 pAhciReq->cbAlloc = 0; 5512 pAhciReq->cAllocTooMuch = 0; 5513 } 5514 } 5509 * @copydoc{AHCIR3MEMCOPYCALLBACK} 5510 */ 5511 static DECLCALLBACK(void) ahciR3CopyBufferToGuestWorker(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, 5512 size_t cbCopy, size_t *pcbSkip) 5513 { 5514 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip); 5515 cbCopy -= cbSkipped; 5516 GCPhys += cbSkipped; 5517 *pcbSkip -= cbSkipped; 5518 5519 while (cbCopy) 5520 { 5521 size_t cbSeg = cbCopy; 5522 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg); 5523 5524 AssertPtr(pvSeg); 5525 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg); 5526 GCPhys += cbSeg; 5527 cbCopy -= cbSeg; 5528 } 5529 } 5530 5531 /** 5532 * Walks the PRDTL list copying data between the guest and host memory buffers. 5533 * 5534 * @returns Amount of bytes copied. 5535 * @param pThis The AHCI controller device instance. 5536 * @param pAhciReq AHCI request structure. 5537 * @param pfnCopyWorker The copy method to apply for each guest buffer. 5538 * @param pSgBuf The host S/G buffer. 5539 * @param cbSkip How many bytes to skip in advance before starting to copy. 5540 * @param cbCopy How many bytes to copy. 5541 */ 5542 static size_t ahciR3PrdtlWalk(PAHCI pThis, PAHCIREQ pAhciReq, 5543 PAHCIR3MEMCOPYCALLBACK pfnCopyWorker, 5544 PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy) 5545 { 5546 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl; 5547 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries; 5548 size_t cbCopied = 0; 5549 5550 /* 5551 * Add the amount to skip to the host buffer size to avoid a 5552 * few conditionals later on. 5553 */ 5554 cbCopy += cbSkip; 5555 5556 AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0); 5557 5558 do 5559 { 5560 SGLEntry aPrdtlEntries[32]; 5561 uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries) 5562 ? cPrdtlEntries 5563 : RT_ELEMENTS(aPrdtlEntries); 5564 5565 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysPrdtl, &aPrdtlEntries[0], 5566 cPrdtlEntriesRead * sizeof(SGLEntry)); 5567 5568 for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbCopy; i++) 5569 { 5570 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA); 5571 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1; 5572 5573 cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbCopy); 5574 5575 /* Copy into SG entry. */ 5576 pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, cbThisCopy, &cbSkip); 5577 5578 cbCopy -= cbThisCopy; 5579 cbCopied += cbThisCopy; 5580 } 5581 5582 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry); 5583 cPrdtlEntries -= cPrdtlEntriesRead; 5584 } while (cPrdtlEntries && cbCopy); 5585 5586 if (cbCopied < cbCopy) 5587 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW; 5588 5589 return cbCopied; 5515 5590 } 5516 5591 … … 5519 5594 * 5520 5595 * @returns Amount of bytes copied to the PRDTL. 5521 * @param p DevIns Pointer to the device instance data.5596 * @param pThis The AHCI controller device instance. 5522 5597 * @param pAhciReq AHCI request structure. 5523 * @param pvBuf The buffer to copy from. 5524 * @param cbBuf The size of the buffer. 5525 */ 5526 static uint32_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, void const *pvBuf, size_t cbBuf) 5527 { 5528 uint8_t const *pbBuf = (uint8_t const *)pvBuf; 5529 SGLEntry aPrdtlEntries[32]; 5530 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl; 5531 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries; 5532 uint32_t cbCopied = 0; 5533 5534 AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0); 5535 5536 do 5537 { 5538 uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries) 5539 ? cPrdtlEntries 5540 : RT_ELEMENTS(aPrdtlEntries); 5541 5542 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry)); 5543 5544 for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++) 5545 { 5546 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA); 5547 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1; 5548 5549 cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbBuf); 5550 5551 /* Copy into SG entry. */ 5552 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy); 5553 5554 pbBuf += cbThisCopy; 5555 cbBuf -= cbThisCopy; 5556 cbCopied += cbThisCopy; 5557 } 5558 5559 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry); 5560 cPrdtlEntries -= cPrdtlEntriesRead; 5561 } while (cPrdtlEntries && cbBuf); 5562 5563 if (cbCopied < cbBuf) 5564 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW; 5565 5566 return cbCopied; 5598 * @param pSgBuf The S/G buffer to copy from. 5599 * @param cbSkip How many bytes to skip in advance before starting to copy. 5600 * @param cbCopy How many bytes to copy. 5601 */ 5602 static size_t ahciR3CopySgBufToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, PRTSGBUF pSgBuf, 5603 size_t cbSkip, size_t cbCopy) 5604 { 5605 return ahciR3PrdtlWalk(pThis, pAhciReq, ahciR3CopyBufferToGuestWorker, 5606 pSgBuf, cbSkip, cbCopy); 5567 5607 } 5568 5608 … … 5570 5610 * Copies the S/G buffer into a data buffer. 5571 5611 * 5572 * @returns Amount of bytes copied tothe PRDTL.5573 * @param p DevIns Pointer to the device instance data.5612 * @returns Amount of bytes copied from the PRDTL. 5613 * @param pThis The AHCI controller device instance. 5574 5614 * @param pAhciReq AHCI request structure. 5575 * @param pvBuf The buffer to copy to. 5576 * @param cbBuf The size of the buffer. 5577 */ 5578 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, 5579 void *pvBuf, size_t cbBuf) 5580 { 5581 uint8_t *pbBuf = (uint8_t *)pvBuf; 5582 SGLEntry aPrdtlEntries[32]; 5583 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl; 5584 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries; 5585 size_t cbCopied = 0; 5586 5587 AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0); 5588 5589 do 5590 { 5591 uint32_t cPrdtlEntriesRead = (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)) 5592 ? cPrdtlEntries 5593 : RT_ELEMENTS(aPrdtlEntries); 5594 5595 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry)); 5596 5597 for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++) 5598 { 5599 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA); 5600 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1; 5601 5602 cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbBuf); 5603 5604 /* Copy into buffer. */ 5605 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy); 5606 5607 pbBuf += cbThisCopy; 5608 cbBuf -= cbThisCopy; 5609 cbCopied += cbThisCopy; 5610 } 5611 5612 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry); 5613 cPrdtlEntries -= cPrdtlEntriesRead; 5614 } while (cPrdtlEntries && cbBuf); 5615 5616 if (cbCopied < cbBuf) 5617 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW; 5618 5619 return cbCopied; 5620 } 5621 5622 /** 5623 * Allocate I/O memory and copies the guest buffer for writes. 5615 * @param pSgBuf The S/G buffer to copy into. 5616 * @param cbSkip How many bytes to skip in advance before starting to copy. 5617 * @param cbCopy How many bytes to copy. 5618 */ 5619 static size_t ahciR3CopySgBufFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, PRTSGBUF pSgBuf, 5620 size_t cbSkip, size_t cbCopy) 5621 { 5622 return ahciR3PrdtlWalk(pThis, pAhciReq, ahciR3CopyBufferFromGuestWorker, 5623 pSgBuf, cbSkip, cbCopy); 5624 } 5625 5626 /** 5627 * Copy a simple memory buffer to the guest memory buffer. 5624 5628 * 5625 * @returns VBox status code. 5626 * @param pAhciPort The AHCI port. 5627 * @param pAhciReq The request state. 5628 * @param cbTransfer Amount of bytes to allocate. 5629 */ 5630 static int ahciIoBufAllocate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbTransfer) 5631 { 5632 AssertMsg( pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 5633 || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE, 5634 ("Allocating I/O memory for a non I/O request is not allowed\n")); 5635 5636 pAhciReq->u.Io.DataSeg.pvSeg = ahciReqMemAlloc(pAhciPort, pAhciReq, cbTransfer); 5637 if (!pAhciReq->u.Io.DataSeg.pvSeg) 5638 return VERR_NO_MEMORY; 5639 5640 pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer; 5641 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 5642 { 5643 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, 5644 pAhciReq->u.Io.DataSeg.pvSeg, 5645 cbTransfer); 5646 } 5647 return VINF_SUCCESS; 5648 } 5649 5650 /** 5651 * Frees the I/O memory of the given request and updates the guest buffer if necessary. 5629 * @returns Amount of bytes copied from the PRDTL. 5630 * @param pThis The AHCI controller device instance. 5631 * @param pAhciReq AHCI request structure. 5632 * @param pvSrc The buffer to copy from. 5633 * @param cbSrc How many bytes to copy. 5634 * @param cbSkip How many bytes to skip initially. 5635 */ 5636 static size_t ahciR3CopyBufferToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, const void *pvSrc, 5637 size_t cbSrc, size_t cbSkip) 5638 { 5639 RTSGSEG Seg; 5640 RTSGBUF SgBuf; 5641 Seg.pvSeg = (void *)pvSrc; 5642 Seg.cbSeg = cbSrc; 5643 RTSgBufInit(&SgBuf, &Seg, 1); 5644 return ahciR3CopySgBufToPrdtl(pThis, pAhciReq, &SgBuf, cbSkip, cbSrc); 5645 } 5646 5647 /** 5648 * Copy a data from the geust memory buffer into a simple memory buffer. 5652 5649 * 5653 * @returns nothing. 5654 * @param pAhciPort The AHCI port. 5655 * @param pAhciReq The request state. 5656 * @param fCopyToGuest Flag whether to update the guest buffer if necessary. 5657 * Nothing is copied if false even if the request was a read. 5658 */ 5659 static void ahciIoBufFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, 5660 bool fCopyToGuest) 5661 { 5662 AssertMsg( pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 5663 || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE, 5664 ("Freeing I/O memory for a non I/O request is not allowed\n")); 5665 5666 if ( pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 5667 && fCopyToGuest) 5668 { 5669 if (pAhciReq->u.Io.pfnPostProcess) 5670 { 5671 void *pv = NULL; 5672 size_t cb = 0; 5673 int rc = pAhciReq->u.Io.pfnPostProcess(pAhciReq, &pv, &cb); 5674 5675 if (RT_SUCCESS(rc)) 5676 { 5677 pAhciReq->cbTransfer = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pv, cb); 5678 RTMemFree(pv); 5679 } 5680 } 5681 else 5682 ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pAhciReq->u.Io.DataSeg.pvSeg, pAhciReq->u.Io.DataSeg.cbSeg); 5683 } 5684 5685 ahciReqMemFree(pAhciPort, pAhciReq, false /* fForceFree */); 5686 pAhciReq->u.Io.DataSeg.pvSeg = NULL; 5687 pAhciReq->u.Io.DataSeg.cbSeg = 0; 5688 } 5689 5650 * @returns Amount of bytes copied from the PRDTL. 5651 * @param pThis The AHCI controller device instance. 5652 * @param pAhciReq AHCI request structure. 5653 * @param pvDst The buffer to copy into. 5654 * @param cbDst How many bytes to copy. 5655 */ 5656 static size_t ahciR3CopyBufferFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, void *pvDst, 5657 size_t cbDst) 5658 { 5659 RTSGSEG Seg; 5660 RTSGBUF SgBuf; 5661 Seg.pvSeg = pvDst; 5662 Seg.cbSeg = cbDst; 5663 RTSgBufInit(&SgBuf, &Seg, 1); 5664 return ahciR3CopySgBufFromPrdtl(pThis, pAhciReq, &SgBuf, 0 /* cbSkip */, cbDst); 5665 } 5690 5666 5691 5667 /** … … 5864 5840 uTag, 0 /* fFlags */); 5865 5841 if (RT_SUCCESS(rc)) 5842 { 5866 5843 pAhciReq->hIoReq = hIoReq; 5844 pAhciReq->pfnPostProcess = NULL; 5845 } 5867 5846 else 5868 5847 pAhciReq = NULL; … … 5914 5893 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ) 5915 5894 { 5916 ahciIoBufFree(pAhciPort, pAhciReq, true /* fCopyToGuest */);5917 5895 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer); 5918 5896 pAhciPort->Led.Actual.s.fReading = 0; … … 5920 5898 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 5921 5899 { 5922 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);5923 5900 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer); 5924 5901 pAhciPort->Led.Actual.s.fWriting = 0; … … 6015 5992 fCanceled = true; 6016 5993 6017 if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH)6018 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);6019 6020 5994 /* Leave a log message about the canceled request. */ 6021 5995 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) … … 6066 6040 size_t cbCopy) 6067 6041 { 6068 RT_NOREF2(pInterface, hIoReq); 6042 RT_NOREF1(hIoReq); 6043 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort); 6069 6044 int rc = VINF_SUCCESS; 6070 6045 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6071 6046 6072 if (offDst + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg) 6073 { 6074 void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offDst; 6075 RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy); 6076 } 6047 if (!pIoReq->pfnPostProcess) 6048 ahciR3CopySgBufToPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pSgBuf, offDst, cbCopy); 6077 6049 else 6050 { 6051 /* Post process data and copy afterwards. */ 6052 void *pv = NULL; 6053 size_t cb = 0; 6054 rc = pIoReq->pfnPostProcess(pIoReq, pSgBuf, cbCopy, offDst, &pv, &cb); 6055 if (RT_SUCCESS(rc)) 6056 { 6057 ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pv, cb, offDst); 6058 RTMemFree(pv); 6059 } 6060 } 6061 6062 if (pIoReq->fFlags & AHCI_REQ_OVERFLOW) 6078 6063 rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 6079 6064 … … 6088 6073 size_t cbCopy) 6089 6074 { 6090 RT_NOREF2(pInterface, hIoReq); 6075 RT_NOREF1(hIoReq); 6076 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort); 6091 6077 int rc = VINF_SUCCESS; 6092 6078 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6093 6079 6094 if (offSrc + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg) 6095 { 6096 void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offSrc; 6097 RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy); 6098 } 6099 else 6080 ahciR3CopySgBufFromPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pSgBuf, offSrc, cbCopy); 6081 if (pIoReq->fFlags & AHCI_REQ_OVERFLOW) 6100 6082 rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 6101 6083 … … 6172 6154 6173 6155 /* Copy the buffer. */ 6174 uint32_t cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, &u16Temp[0], sizeof(u16Temp)); 6156 uint32_t cbCopied = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, 6157 &u16Temp[0], sizeof(u16Temp), 0 /* cbSkip */); 6175 6158 6176 6159 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA; … … 6377 6360 6378 6361 /* Copy the buffer. */ 6379 uint32_t cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, &aBuf[offLogRead], cbLogRead); 6362 uint32_t cbCopied = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, 6363 &aBuf[offLogRead], cbLogRead, 0 /* cbSkip */); 6380 6364 6381 6365 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA; … … 6734 6718 6735 6719 if (enmType != PDMMEDIAEXIOREQTYPE_INVALID) 6736 { 6737 if ( enmType != PDMMEDIAEXIOREQTYPE_FLUSH 6738 && enmType != PDMMEDIAEXIOREQTYPE_DISCARD) 6739 { 6740 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); 6741 6742 rc = ahciIoBufAllocate(pAhciPort, pAhciReq, pAhciReq->cbTransfer); 6743 if (RT_FAILURE(rc)) 6744 { 6745 /* In case we can't allocate enough memory fail the request with an overflow error. */ 6746 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc)); 6747 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW; 6748 } 6749 } 6750 6751 if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW)) 6752 fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType); 6753 else /* Overflow is handled in completion routine. */ 6754 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS); 6755 } 6720 fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType); 6756 6721 else 6757 6722 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
Note:
See TracChangeset
for help on using the changeset viewer.