Changeset 38894 in vbox
- Timestamp:
- Sep 28, 2011 11:23:05 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 74217
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/ATAController.cpp
r38838 r38894 106 106 static bool ataWriteSectorsSS(AHCIATADevState *); 107 107 static bool ataExecuteDeviceDiagnosticSS(AHCIATADevState *); 108 static bool ataTrimSS(AHCIATADevState *); 108 109 static bool ataPacketSS(AHCIATADevState *); 109 110 static bool atapiGetConfigurationSS(AHCIATADevState *); … … 161 162 ATAFN_SS_WRITE_SECTORS, 162 163 ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC, 164 ATAFN_SS_TRIM, 163 165 ATAFN_SS_PACKET, 164 166 ATAFN_SS_ATAPI_GET_CONFIGURATION, … … 193 195 ataWriteSectorsSS, 194 196 ataExecuteDeviceDiagnosticSS, 197 ataTrimSS, 195 198 ataPacketSS, 196 199 atapiGetConfigurationSS, … … 740 743 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */ 741 744 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */ 742 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */ 743 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */ 745 if (s->pDrvBlock->pfnDiscard) 746 { 747 p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */ 748 p[81] = RT_H2LE_U16(0x28); /* conforms to ATA/ATAPI-8 ACS */ 749 } 750 else 751 { 752 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */ 753 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */ 754 } 744 755 p[82] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* supports power management, write cache and look-ahead */ 745 756 if (s->cTotalSectors <= (1 << 28) - 1) … … 763 774 p[103] = RT_H2LE_U16(s->cTotalSectors >> 48); 764 775 } 776 if (s->pDrvBlock->pfnDiscard) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */ 777 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */ 765 778 if (s->fNonRotational) 766 779 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */ … … 2984 2997 2985 2998 2999 static int ataTrimSectors(AHCIATADevState *s, uint64_t u64Sector, uint32_t cSectors, 3000 bool *pfRedo) 3001 { 3002 RTRANGE TrimRange; 3003 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); 3004 int rc; 3005 3006 PDMCritSectLeave(&pCtl->lock); 3007 3008 TrimRange.offStart = u64Sector * 512; 3009 TrimRange.cbRange = cSectors * 512; 3010 3011 s->pLed->Asserted.s.fWriting = s->pLed->Actual.s.fWriting = 1; 3012 rc = s->pDrvBlock->pfnDiscard(s->pDrvBlock, &TrimRange, 1); 3013 s->pLed->Actual.s.fWriting = 0; 3014 3015 if (RT_SUCCESS(rc)) 3016 *pfRedo = false; 3017 else 3018 *pfRedo = ataIsRedoSetWarning(s, rc); 3019 3020 STAM_PROFILE_START(&pCtl->StatLockWait, a); 3021 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS); 3022 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 3023 return rc; 3024 } 3025 3026 3027 static bool ataTrimSS(AHCIATADevState *s) 3028 { 3029 int rc; 3030 uint32_t cRangesMax; 3031 uint64_t *pu64Range = (uint64_t *)s->CTX_SUFF(pbIOBuffer); 3032 bool fRedo; 3033 3034 cRangesMax = s->cbElementaryTransfer / sizeof(uint64_t); 3035 Assert(cRangesMax); 3036 3037 while (cRangesMax-- > 0) 3038 { 3039 if (ATA_RANGE_LENGTH_GET(*pu64Range) == 0) 3040 break; 3041 3042 rc = ataTrimSectors(s, *pu64Range & ATA_RANGE_LBA_MASK, 3043 ATA_RANGE_LENGTH_GET(*pu64Range), &fRedo); 3044 if (RT_FAILURE(rc)) 3045 break; 3046 3047 pu64Range++; 3048 } 3049 3050 if (RT_SUCCESS(rc)) 3051 { 3052 s->iSourceSink = ATAFN_SS_NULL; 3053 ataCmdOK(s, ATA_STAT_SEEK); 3054 } 3055 else 3056 { 3057 if (fRedo) 3058 return fRedo; 3059 if (s->cErrors++ < MAX_LOG_REL_ERRORS) 3060 LogRel(("PIIX3 ATA: LUN#%d: disk trim error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n", 3061 s->iLUN, rc, *pu64Range & ATA_RANGE_LBA_MASK, ATA_RANGE_LENGTH_GET(*pu64Range))); 3062 3063 /* 3064 * Check if we got interrupted. We don't need to set status variables 3065 * because the request was aborted. 3066 */ 3067 if (rc != VERR_INTERRUPTED) 3068 ataCmdError(s, ID_ERR); 3069 } 3070 3071 return false; 3072 } 3073 3074 2986 3075 static void ataParseCmd(AHCIATADevState *s, uint8_t cmd) 2987 3076 { … … 3225 3314 ataStartTransfer(s, ATAPI_PACKET_SIZE, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_PACKET, ATAFN_SS_PACKET, false); 3226 3315 break; 3316 case ATA_DATA_SET_MANAGEMENT: 3317 if (!s->pDrvBlock || !s->pDrvBlock->pfnDiscard) 3318 goto abort_cmd; 3319 if ( !(s->uATARegFeature & UINT8_C(0x01)) 3320 || (s->uATARegFeature & ~UINT8_C(0x01))) 3321 goto abort_cmd; 3322 s->fDMA = true; 3323 ataStartTransfer(s, (s->uATARegNSectorHOB << 8 | s->uATARegNSector) * 512, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_NULL, ATAFN_SS_TRIM, false); 3324 break; 3227 3325 default: 3228 3326 abort_cmd: -
trunk/src/VBox/Devices/Storage/DevATA.cpp
r38838 r38894 572 572 static bool ataWriteSectorsSS(ATADevState *); 573 573 static bool ataExecuteDeviceDiagnosticSS(ATADevState *); 574 static bool ataTrimSS(ATADevState *); 574 575 static bool ataPacketSS(ATADevState *); 575 576 static bool atapiGetConfigurationSS(ATADevState *); … … 628 629 ATAFN_SS_WRITE_SECTORS, 629 630 ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC, 631 ATAFN_SS_TRIM, 630 632 ATAFN_SS_PACKET, 631 633 ATAFN_SS_ATAPI_GET_CONFIGURATION, … … 661 663 ataWriteSectorsSS, 662 664 ataExecuteDeviceDiagnosticSS, 665 ataTrimSS, 663 666 ataPacketSS, 664 667 atapiGetConfigurationSS, … … 1217 1220 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */ 1218 1221 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */ 1219 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */ 1220 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */ 1222 if (s->pDrvBlock->pfnDiscard) 1223 { 1224 p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */ 1225 p[81] = RT_H2LE_U16(0x28); /* conforms to ATA/ATAPI-8 ACS */ 1226 } 1227 else 1228 { 1229 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */ 1230 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */ 1231 } 1221 1232 p[82] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* supports power management, write cache and look-ahead */ 1222 1233 if (s->cTotalSectors <= (1 << 28) - 1) … … 1240 1251 p[103] = RT_H2LE_U16(s->cTotalSectors >> 48); 1241 1252 } 1253 if (s->pDrvBlock->pfnDiscard) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */ 1254 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */ 1242 1255 if (s->fNonRotational) 1243 1256 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */ … … 3735 3748 ataSetStatusValue(s, ATA_STAT_READY | ATA_STAT_SEEK); 3736 3749 s->uATARegError = 0x01; 3750 return false; 3751 } 3752 3753 3754 static int ataTrimSectors(ATADevState *s, uint64_t u64Sector, uint32_t cSectors, 3755 bool *pfRedo) 3756 { 3757 RTRANGE TrimRange; 3758 PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); 3759 int rc; 3760 3761 PDMCritSectLeave(&pCtl->lock); 3762 3763 TrimRange.offStart = u64Sector * 512; 3764 TrimRange.cbRange = cSectors * 512; 3765 3766 s->Led.Asserted.s.fWriting = s->Led.Actual.s.fWriting = 1; 3767 rc = s->pDrvBlock->pfnDiscard(s->pDrvBlock, &TrimRange, 1); 3768 s->Led.Actual.s.fWriting = 0; 3769 3770 if (RT_SUCCESS(rc)) 3771 *pfRedo = false; 3772 else 3773 *pfRedo = ataIsRedoSetWarning(s, rc); 3774 3775 STAM_PROFILE_START(&pCtl->StatLockWait, a); 3776 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS); 3777 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 3778 return rc; 3779 } 3780 3781 3782 static bool ataTrimSS(ATADevState *s) 3783 { 3784 int rc; 3785 uint32_t cRangesMax; 3786 uint64_t *pu64Range = (uint64_t *)s->CTX_SUFF(pbIOBuffer); 3787 bool fRedo; 3788 3789 cRangesMax = s->cbElementaryTransfer / sizeof(uint64_t); 3790 Assert(cRangesMax); 3791 3792 while (cRangesMax-- > 0) 3793 { 3794 if (ATA_RANGE_LENGTH_GET(*pu64Range) == 0) 3795 break; 3796 3797 rc = ataTrimSectors(s, *pu64Range & ATA_RANGE_LBA_MASK, 3798 ATA_RANGE_LENGTH_GET(*pu64Range), &fRedo); 3799 if (RT_FAILURE(rc)) 3800 break; 3801 3802 pu64Range++; 3803 } 3804 3805 if (RT_SUCCESS(rc)) 3806 { 3807 s->iSourceSink = ATAFN_SS_NULL; 3808 ataCmdOK(s, ATA_STAT_SEEK); 3809 } 3810 else 3811 { 3812 if (fRedo) 3813 return fRedo; 3814 if (s->cErrors++ < MAX_LOG_REL_ERRORS) 3815 LogRel(("PIIX3 ATA: LUN#%d: disk trim error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n", 3816 s->iLUN, rc, *pu64Range & ATA_RANGE_LBA_MASK, ATA_RANGE_LENGTH_GET(*pu64Range))); 3817 3818 /* 3819 * Check if we got interrupted. We don't need to set status variables 3820 * because the request was aborted. 3821 */ 3822 if (rc != VERR_INTERRUPTED) 3823 ataCmdError(s, ID_ERR); 3824 } 3825 3737 3826 return false; 3738 3827 } … … 3992 4081 ataStartTransfer(s, ATAPI_PACKET_SIZE, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_PACKET, ATAFN_SS_PACKET, false); 3993 4082 break; 4083 case ATA_DATA_SET_MANAGEMENT: 4084 if (!s->pDrvBlock || !s->pDrvBlock->pfnDiscard) 4085 goto abort_cmd; 4086 if ( !(s->uATARegFeature & UINT8_C(0x01)) 4087 || (s->uATARegFeature & ~UINT8_C(0x01))) 4088 goto abort_cmd; 4089 s->fDMA = true; 4090 ataStartTransfer(s, (s->uATARegNSectorHOB << 8 | s->uATARegNSector) * 512, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_NULL, ATAFN_SS_TRIM, false); 4091 break; 3994 4092 default: 3995 4093 abort_cmd: … … 6135 6233 } 6136 6234 LogRel(("PIIX3 ATA: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n", pIf->iLUN, pIf->PCHSGeometry.cCylinders, pIf->PCHSGeometry.cHeads, pIf->PCHSGeometry.cSectors, pIf->cTotalSectors)); 6235 6236 if (pIf->pDrvBlock->pfnDiscard) 6237 LogRel(("PIIX3 ATA: LUN#%d: TRIM enabled\n", pIf->iLUN)); 6137 6238 } 6138 6239 return rc; -
trunk/src/VBox/Devices/Storage/ide.h
r38622 r38894 176 176 #define ATA_MODEL_NUMBER_LENGTH 40 177 177 178 /** Mask to get the LBA value from a LBA range. */ 179 #define ATA_RANGE_LBA_MASK UINT64_C(0xffffffffffff) 180 /** Mas to get the length value from a LBA range. */ 181 #define ATA_RANGE_LENGTH_MASK UINT64_C(0xffff000000000000) 182 /** Returns the length of the range in sectors. */ 183 #define ATA_RANGE_LENGTH_GET(val) (((val) & ATA_RANGE_LENGTH_MASK) >> 48) 178 184 179 185 /* ATAPI defines */
Note:
See TracChangeset
for help on using the changeset viewer.