Changeset 64015 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Sep 26, 2016 3:11:22 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 110931
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r64009 r64015 306 306 PFNAHCIPOSTPROCESS pfnPostProcess; 307 307 } Io; 308 /** Data for a trim request. */309 struct310 {311 /** Pointer to the array of ranges to trim. */312 PRTRANGE paRanges;313 /** Number of entries in the array. */314 unsigned cRanges;315 } Trim;316 308 } u; 317 309 } AHCIREQ; … … 5787 5779 * 5788 5780 * @returns VBox status code. 5789 * @param pAhciPort AHCI port state. 5790 * @param pAhciReq The request handling the TRIM request. 5791 */ 5792 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 5781 * @param pAhciPort AHCI port state. 5782 * @param pAhciReq The request handling the TRIM request. 5783 * @param idxRangeStart Index of the first range to start copying. 5784 * @param paRanges Where to store the ranges. 5785 * @param cRanges Number of ranges fitting into the array. 5786 * @param pcRanges Where to store the amount of ranges actually copied on success. 5787 */ 5788 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t idxRangeStart, 5789 PRTRANGE paRanges, uint32_t cRanges, uint32_t *pcRanges) 5793 5790 { 5794 5791 SGLEntry aPrdtlEntries[32]; 5795 5792 uint64_t aRanges[64]; 5796 unsigned cRangesMax;5797 unsigned cRanges = 0;5798 5793 uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries; 5799 5794 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl; 5800 5795 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns); 5801 int rc = VINF_SUCCESS; 5796 int rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 5797 uint32_t idxRange = 0; 5802 5798 5803 5799 LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq)); … … 5805 5801 AssertMsgReturn(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD, ("This is not a trim request\n"), VERR_INVALID_PARAMETER); 5806 5802 5807 /* The data buffer contains LBA range entries. Each range is 8 bytes big. */5808 if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])5809 cRangesMax = 65536 * 512 / 8;5810 else5811 cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;5812 5813 5803 if (!cPrdtlEntries) 5814 {5815 5804 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW; 5816 return VINF_SUCCESS; 5817 } 5818 5819 do 5820 { 5821 uint32_t cPrdtlEntriesRead = (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)) 5822 ? cPrdtlEntries 5823 : RT_ELEMENTS(aPrdtlEntries); 5824 5805 5806 /* Convert the ranges from ATA to our format. */ 5807 while ( cPrdtlEntries 5808 && idxRange < cRanges) 5809 { 5810 uint32_t cPrdtlEntriesRead = RT_MIN(cPrdtlEntries, RT_ELEMENTS(aPrdtlEntries)); 5811 5812 rc = VINF_SUCCESS; 5825 5813 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry)); 5826 5814 5827 for (uint32_t i = 0; i < cPrdtlEntriesRead ; i++)5815 for (uint32_t i = 0; i < cPrdtlEntriesRead && idxRange < cRanges; i++) 5828 5816 { 5829 5817 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA); … … 5835 5823 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy); 5836 5824 5837 for (unsigned idxRange = 0; idxRange < RT_ELEMENTS(aRanges); idxRange++)5825 for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges) && idxRange < cRanges; idxRangeSrc++) 5838 5826 { 5839 aRanges[idxRange] = RT_H2LE_U64(aRanges[idxRange]); 5840 if (AHCI_RANGE_LENGTH_GET(aRanges[idxRange]) != 0) 5841 cRanges++; 5842 else 5843 break; 5844 } 5845 } 5846 5847 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry); 5848 cPrdtlEntries -= cPrdtlEntriesRead; 5849 } while (cPrdtlEntries); 5850 5851 if (RT_UNLIKELY(!cRanges)) 5852 { 5853 return VERR_BUFFER_OVERFLOW; 5854 } 5855 5856 pAhciReq->u.Trim.cRanges = cRanges; 5857 pAhciReq->u.Trim.paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges); 5858 if (pAhciReq->u.Trim.paRanges) 5859 { 5860 uint32_t idxRange = 0; 5861 5862 cPrdtlEntries = pAhciReq->cPrdtlEntries; 5863 GCPhysPrdtl = pAhciReq->GCPhysPrdtl; 5864 5865 /* Convert the ranges from the guest to our format. */ 5866 do 5867 { 5868 uint32_t cPrdtlEntriesRead = (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)) 5869 ? cPrdtlEntries 5870 : RT_ELEMENTS(aPrdtlEntries); 5871 5872 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry)); 5873 5874 for (uint32_t i = 0; i < cPrdtlEntriesRead; i++) 5875 { 5876 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA); 5877 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1; 5878 5879 cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges)); 5880 5881 /* Copy into buffer. */ 5882 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy); 5883 5884 for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges); idxRangeSrc++) 5827 /* Skip range if told to do so. */ 5828 if (!idxRangeStart) 5885 5829 { 5886 5830 aRanges[idxRangeSrc] = RT_H2LE_U64(aRanges[idxRangeSrc]); 5887 5831 if (AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) != 0) 5888 5832 { 5889 p AhciReq->u.Trim.paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector;5890 p AhciReq->u.Trim.paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector;5833 paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector; 5834 paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector; 5891 5835 idxRange++; 5892 5836 } … … 5894 5838 break; 5895 5839 } 5840 else 5841 idxRangeStart--; 5896 5842 } 5897 5898 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry); 5899 cPrdtlEntries -= cPrdtlEntriesRead;5900 } while (idxRange < cRanges);5901 } 5902 else 5903 rc = VERR_NO_MEMORY;5843 } 5844 5845 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry); 5846 cPrdtlEntries -= cPrdtlEntriesRead; 5847 } 5848 5849 *pcRanges = idxRange; 5904 5850 5905 5851 LogFlowFunc(("returns rc=%Rrc\n", rc)); 5906 5852 return rc; 5907 }5908 5909 /**5910 * Destroy the trim range list.5911 *5912 * @returns nothing.5913 * @param pAhciReq The task state.5914 */5915 static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq)5916 {5917 AssertReturnVoid(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD);5918 RTMemFree(pAhciReq->u.Trim.paRanges);5919 5853 } 5920 5854 … … 6027 5961 } 6028 5962 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6029 {6030 ahciTrimRangesDestroy(pAhciReq);6031 5963 pAhciPort->Led.Actual.s.fWriting = 0; 6032 }6033 5964 6034 5965 if (RT_FAILURE(rcReq)) … … 6120 6051 fCanceled = true; 6121 6052 6122 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6123 ahciTrimRangesDestroy(pAhciReq); 6124 else if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH) 6053 if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH) 6125 6054 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */); 6126 6055 … … 6218 6147 uint32_t *pcRanges) 6219 6148 { 6220 RT_NOREF2(pInterface, hIoReq); 6149 RT_NOREF1(hIoReq); 6150 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort); 6221 6151 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6222 uint32_t cRangesCopy = RT_MIN(pIoReq->u.Trim.cRanges - idxRangeStart, cRanges); 6223 Assert( idxRangeStart < pIoReq->u.Trim.cRanges 6224 && (idxRangeStart + cRanges) <= pIoReq->u.Trim.cRanges); 6225 6226 memcpy(paRanges, &pIoReq->u.Trim.paRanges[idxRangeStart], cRangesCopy * sizeof(RTRANGE)); 6227 *pcRanges = cRangesCopy; 6228 6229 return VINF_SUCCESS; 6152 6153 return ahciTrimRangesCreate(pAhciPort, pIoReq, idxRangeStart, paRanges, cRanges, pcRanges); 6230 6154 } 6231 6155 … … 6638 6562 else if (enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6639 6563 { 6640 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq); 6641 if (RT_SUCCESS(rc)) 6642 { 6643 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6644 rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq, 6645 pAhciReq->u.Trim.cRanges); 6646 } 6564 uint32_t cRangesMax; 6565 6566 /* The data buffer contains LBA range entries. Each range is 8 bytes big. */ 6567 if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP]) 6568 cRangesMax = 65536 * 512 / 8; 6569 else 6570 cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8; 6571 6572 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6573 rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq, 6574 cRangesMax); 6647 6575 } 6648 6576 else if (enmType == PDMMEDIAEXIOREQTYPE_READ)
Note:
See TracChangeset
for help on using the changeset viewer.