37#define FIRMWARE_ACTIVATE_TIMEOUT_VALUE 30
41 #pragma alloc_text(PAGE, ClassGetDeviceParameter)
42 #pragma alloc_text(PAGE, ClassScanForSpecial)
43 #pragma alloc_text(PAGE, ClassSetDeviceParameter)
44 #pragma alloc_text(PAGE, ClasspMyStringMatches)
45 #pragma alloc_text(PAGE, ClasspDeviceCopyOffloadProperty)
46 #pragma alloc_text(PAGE, ClasspValidateOffloadSupported)
47 #pragma alloc_text(PAGE, ClasspValidateOffloadInputParameters)
57 if (StringToMatch ==
NULL) {
74ClassGetDeviceParameter(
85 ULONG defaultParameterValue;
96 &deviceParameterHandle);
107 deviceParameterHandle,
110 status = ZwOpenKey(&deviceSubkeyHandle,
114 ZwClose(deviceParameterHandle);
133 deviceParameterHandle),
149 ZwClose(deviceParameterHandle);
161 &deviceParameterHandle);
172 deviceParameterHandle,
175 status = ZwOpenKey(&deviceSubkeyHandle,
KEY_READ, &objectAttributes);
178 ZwClose(deviceParameterHandle);
196 deviceParameterHandle),
221 ZwClose(deviceParameterHandle);
232ClassSetDeviceParameter(
251 &deviceParameterHandle);
262 deviceParameterHandle,
265 status = ZwCreateKey(&deviceSubkeyHandle,
270 ZwClose(deviceParameterHandle);
281 deviceParameterHandle),
295 ZwClose(deviceParameterHandle);
322 UCHAR nullString[] =
"";
341 if (deviceDescriptor->VendorIdOffset != 0 &&
342 deviceDescriptor->VendorIdOffset != -1) {
343 vendorId = ((
PUCHAR)deviceDescriptor);
344 vendorId += deviceDescriptor->VendorIdOffset;
346 vendorId = nullString;
348 if (deviceDescriptor->ProductIdOffset != 0 &&
349 deviceDescriptor->ProductIdOffset != -1) {
350 productId = ((
PUCHAR)deviceDescriptor);
351 productId += deviceDescriptor->ProductIdOffset;
353 productId = nullString;
355 if (deviceDescriptor->ProductRevisionOffset != 0 &&
356 deviceDescriptor->ProductRevisionOffset != -1) {
357 productRevision = ((
PUCHAR)deviceDescriptor);
358 productRevision += deviceDescriptor->ProductRevisionOffset;
360 productRevision = nullString;
377 "controller Ven: %s Prod: %s Rev: %s\n",
378 (
PCSZ)vendorId, (
PCSZ)productId, (
PCSZ)productRevision));
393 "completed callback\n"));
400 TracePrint((
TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
"ClasspScanForSpecialByInquiry: no match found for %p\n",
442 fdoData->
Perf.SuccessfulIO = 0;
463 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClasspPerfIncrementErrorCount: "
464 "Too many errors; disabling tagged queuing and "
465 "synchronous data tranfers.\n"));
476 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClasspPerfIncrementErrorCount: "
477 "Too many errors; disabling disconnects.\n"));
504 if (fdoData->
Perf.ReEnableThreshhold == 0) {
509 if (succeeded < fdoData->Perf.ReEnableThreshhold) {
527 succeeded = fdoData->
Perf.SuccessfulIO;
530 (fdoData->
Perf.ReEnableThreshhold <= succeeded)
533 fdoData->
Perf.SuccessfulIO = 0;
544 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClasspPerfIncrementSuccessfulIo: "
545 "Error level 2 no longer required.\n"));
556 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClasspPerfIncrementSuccessfulIo: "
557 "Error level 1 no longer required.\n"));
591 #pragma warning(suppress: 6320)
596 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
"ClasspBuildDeviceMdl: MmProbeAndLockPages failed with %xh.",
status));
602 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
"ClasspBuildDeviceMdl: IoAllocateMdl failed"));
631 ClasspPerfResetCounters(
640 "Resetting all perf counters.\n"));
641 fdoData->
Perf.SuccessfulIO = 0;
714 (
PVOID *)&deviceIdDescriptor);
721 descHeader =
Irp->AssociatedIrp.SystemBuffer;
727 offset = descHeader->Size;
730 descHeader->Size += deviceIdDescriptor->Size;
732 if (queryLength < descHeader->
Size) {
744 storageDuid =
Irp->AssociatedIrp.SystemBuffer;
749 deviceIdDescriptor->Size);
751 Irp->IoStatus.Information = storageDuid->
Size;
803 if (!deviceDescriptor) {
808 descHeader =
Irp->AssociatedIrp.SystemBuffer;
814 if (deviceDescriptor->SerialNumberOffset == 0) {
822 offset = descHeader->Size;
825 descHeader->Size += deviceDescriptor->Size;
827 if (queryLength < descHeader->
Size) {
839 storageDuid =
Irp->AssociatedIrp.SystemBuffer;
844 deviceDescriptor->Size);
846 Irp->IoStatus.Information = storageDuid->
Size;
880 PDRIVE_LAYOUT_INFORMATION_EX layoutEx =
NULL;
918 descHeader =
Irp->AssociatedIrp.SystemBuffer;
924 offset = descHeader->Size;
929 if (queryLength < descHeader->
Size) {
941 storageDuid =
Irp->AssociatedIrp.SystemBuffer;
948 driveLayoutSignature->
Mbr =
TRUE;
951 &layoutEx->Mbr.Signature,
952 sizeof(layoutEx->Mbr.Signature));
959 &layoutEx->Gpt.DiskId,
960 sizeof(layoutEx->Gpt.DiskId));
965 Irp->IoStatus.Information = storageDuid->
Size;
1031 Irp->IoStatus.Information = 0;
1046 includeOptionalIds =
TRUE;
1048 includeOptionalIds =
FALSE;
1071 descHeader =
Irp->AssociatedIrp.SystemBuffer;
1112 if (!includeOptionalIds) {
1155 }
else if (infoFound) {
1163 Irp->AssociatedIrp.SystemBuffer));
1223 goto WriteCacheExit;
1232 goto WriteCacheExit;
1237 goto WriteCacheExit;
1244 goto WriteCacheExit;
1260 goto WriteCacheExit;
1267 writeCache->NVCacheEnabled =
FALSE;
1293 writeCache->FlushCacheSupported =
TRUE;
1300 writeCache->FlushCacheSupported =
FALSE;
1311 if (modeData ==
NULL) {
1312 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
"ClasspWriteCacheProperty: Unable to allocate mode data buffer\n"));
1314 goto WriteCacheExit;
1336 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
"ClasspWriteCacheProperty: Mode Sense failed\n"));
1338 goto WriteCacheExit;
1364 if (pageData ==
NULL) {
1366 TracePrint((
TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
"ClasspWriteCacheProperty: Unable to find caching mode page.\n"));
1428 goto WriteCacheExit;
1453 if (pageData ==
NULL) {
1454 TracePrint((
TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
"ClasspWriteCacheProperty: Unable to find caching mode page.\n"));
1493 ULONG logicalSectorSize;
1495 REVERSE_BYTES(&logicalSectorSize, &BytesPerBlockInBigEndian);
1497 if (logicalSectorSize == 0) {
1498 logicalSectorSize = 512;
1504 if (logicalSectorSize & (logicalSectorSize-1)) {
1505 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
"FDO %ph has non-standard sector size 0x%x.",
Fdo, logicalSectorSize));
1507 logicalSectorSize &= logicalSectorSize-1;
1509 while (logicalSectorSize & (logicalSectorSize-1));
1513 return logicalSectorSize;
1523 USHORT lowestAlignedBlock;
1524 USHORT logicalBlocksPerPhysicalBlock;
1532 (
FdoExtension->DiskGeometry.BytesPerSector ==
FdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector) );
1534 logicalBlocksPerPhysicalBlock = 1 << ReadCapacity16Data->LogicalPerPhysicalExponent;
1535 lowestAlignedBlock = (ReadCapacity16Data->LowestAlignedBlock_MSB << 8) | ReadCapacity16Data->LowestAlignedBlock_LSB;
1537 if (lowestAlignedBlock > logicalBlocksPerPhysicalBlock) {
1542 lowestAlignedBlock = (logicalBlocksPerPhysicalBlock - lowestAlignedBlock) % logicalBlocksPerPhysicalBlock;
1560 "InterpretReadCapacity16Data: Device\'s LBP enabled = %d\n",
1589 ULONG dataTransferLength = 0;
1594 if (
FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus != -1) {
1596 return FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus;
1604#if defined(_ARM_) || defined(_ARM64_)
1665 allocationBufferLength,
1725 if (fdoExtension->FunctionSupportInfo->RegAccessAlignmentQueryNotSupported) {
1732 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty ==
Supported) ) {
1768 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
1791 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty) {
1804 fdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus =
status;
1809 fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty =
NotSupported;
1816 accessAlignment->BytesPerLogicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector;
1817 accessAlignment->BytesPerPhysicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerPhysicalSector;
1818 accessAlignment->BytesOffsetForSectorAlignment = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesOffsetForSectorAlignment;
1830 fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty =
Supported;
1851 accessAlignment->BytesPerLogicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector;
1852 accessAlignment->BytesPerPhysicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerPhysicalSector;
1853 accessAlignment->BytesOffsetForSectorAlignment = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesOffsetForSectorAlignment;
1895 if (MediumRotationRate == 0x0001) {
1899 }
else if ( (MediumRotationRate >= 0x401) &&
1900 (MediumRotationRate <= 0xFFFE) ) {
1954 "ClasspDeviceMediaTypeProperty (%p): Entering function.\n",
1967 goto __ClasspDeviceMediaTypeProperty_Exit;
1973 "ClasspDeviceMediaTypeProperty (%p): Unsupported query type %x for media type property.\n",
1978 goto __ClasspDeviceMediaTypeProperty_Exit;
1992 "ClasspDeviceMediaTypeProperty (%p): Query property for media type at incorrect IRQL.\n",
1996 goto __ClasspDeviceMediaTypeProperty_Exit;
1999 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2009 goto __ClasspDeviceMediaTypeProperty_Exit;
2015 goto __ClasspDeviceMediaTypeProperty_Exit;
2021 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics ==
TRUE) {
2028 goto __ClasspDeviceMediaTypeProperty_Exit;
2033 status = fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus;
2038 "ClasspDeviceGetBlockDeviceCharacteristicsVPDPage (%p): VPD retrieval fails with %x.\n",
2042 goto __ClasspDeviceMediaTypeProperty_Exit;
2049 pDesc->MediumProductType = fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumProductType;
2052__ClasspDeviceMediaTypeProperty_Exit:
2065 "ClasspDeviceMediaTypeProperty (%p): Exiting function with status %x.\n",
2103#if defined(_ARM_) || defined(_ARM64_)
2110 allocationBufferLength,
2144 allocationBufferLength,
2155 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumRotationRate = (
dataBuffer->MediumRotationRateMsb << 8) |
2157 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumProductType =
dataBuffer->MediumProductType;
2158 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.NominalFormFactor =
dataBuffer->NominalFormFactor;
2195 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty ==
Supported) ) {
2231 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2251 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty) {
2261 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics ==
TRUE) {
2269 status =
IncursSeekPenalty(fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumRotationRate, &incursSeekPenalty);
2272 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus =
status;
2276 fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty =
NotSupported;
2295 fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty =
Supported;
2307 status = fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus;
2310 status =
IncursSeekPenalty(fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumRotationRate, &incursSeekPenalty);
2363 ULONG dataTransferLength = 0;
2369 if (fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus != -1) {
2371 return fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus;
2378 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ =
FALSE;
2379 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU =
FALSE;
2380 fdoExtension->FunctionSupportInfo->LBProvisioningData.ANC_SUP =
FALSE;
2381 fdoExtension->FunctionSupportInfo->LBProvisioningData.ThresholdExponent = 0;
2386 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning ==
TRUE &&
2389#if defined(_ARM_) || defined(_ARM64_)
2443 cdb->CDB6INQUIRY3.EnableVitalProductData = 1;
2450 allocationBufferLength,
2470 ((dataTransferLength < 0x08) ||
2484 fdoExtension->FunctionSupportInfo->LBProvisioningData.ProvisioningType = lbProvisioning->ProvisioningType;
2485 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ = lbProvisioning->LBPRZ;
2486 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU = lbProvisioning->LBPU;
2487 fdoExtension->FunctionSupportInfo->LBProvisioningData.ANC_SUP = lbProvisioning->ANC_SUP;
2488 fdoExtension->FunctionSupportInfo->LBProvisioningData.ThresholdExponent = lbProvisioning->ThresholdExponent;
2492 "ClasspDeviceGetLBProvisioningVPDPage (%p): %s %s (rev %s) reported following parameters: \
2493 \n\t\t\tProvisioningType: %u \
2496 \n\t\t\tANC_SUP: %I64u \
2497 \n\t\t\tThresholdExponent: %u\n",
2502 lbProvisioning->ProvisioningType,
2503 lbProvisioning->LBPRZ,
2504 lbProvisioning->LBPU,
2505 lbProvisioning->ANC_SUP,
2506 lbProvisioning->ThresholdExponent));
2512 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus =
status;
2534 ULONG dataTransferLength = 0;
2540 if (
FdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU) {
2546 BlockLimitsData->MaxUnmapLbaCount = (
ULONG)-1;
2547 BlockLimitsData->MaxUnmapBlockDescrCount = (
ULONG)-1;
2548 BlockLimitsData->OptimalUnmapGranularity = 1;
2549 BlockLimitsData->UnmapGranularityAlignment = 0;
2550 BlockLimitsData->UGAVALID =
FALSE;
2552 BlockLimitsData->MaxUnmapLbaCount = 0;
2553 BlockLimitsData->MaxUnmapBlockDescrCount = 0;
2554 BlockLimitsData->OptimalUnmapGranularity = 0;
2555 BlockLimitsData->UnmapGranularityAlignment = 0;
2556 BlockLimitsData->UGAVALID =
FALSE;
2562 if (
FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits ==
TRUE)
2564#if defined(_ARM_) || defined(_ARM64_)
2589 #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
2630 allocationBufferLength,
2663 if ((dataTransferLength < 0x24) ||
2684 BlockLimitsData->UGAVALID = blockLimits->
UGAValid;
2685 if (BlockLimitsData->UGAVALID ==
TRUE) {
2687 BlockLimitsData->UnmapGranularityAlignment &= 0x7FFFFFFF;
2689 BlockLimitsData->UnmapGranularityAlignment = 0;
2694 "ClasspDeviceGetBlockLimitsVPDPage (%p): %s %s (rev %s) reported following parameters: \
2695 \n\t\t\tOptimalTransferLengthGranularity: %u \
2696 \n\t\t\tMaximumTransferLength: %u \
2697 \n\t\t\tOptimalTransferLength: %u \
2698 \n\t\t\tMaximumUnmapLBACount: %u \
2699 \n\t\t\tMaximumUnmapBlockDescriptorCount: %u \
2700 \n\t\t\tOptimalUnmapGranularity: %u \
2701 \n\t\t\tUGAValid: %u \
2702 \n\t\t\tUnmapGranularityAlignment: %u\n",
2707 BlockLimitsData->OptimalTransferLengthGranularity,
2708 BlockLimitsData->MaximumTransferLength,
2709 BlockLimitsData->OptimalTransferLength,
2710 BlockLimitsData->MaxUnmapLbaCount,
2711 BlockLimitsData->MaxUnmapBlockDescrCount,
2712 BlockLimitsData->OptimalUnmapGranularity,
2713 BlockLimitsData->UGAVALID,
2714 BlockLimitsData->UnmapGranularityAlignment));
2721 BlockLimitsData->CommandStatus =
status;
2755 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty ==
Supported) ) {
2791 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2811 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty) {
2822 status = fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus;
2827 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty =
NotSupported;
2847 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty =
Supported;
2855 status = fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus;
2908 ULONG generationCount;
3006 lbpDescr->
AnchorSupported = fdoExtension->FunctionSupportInfo->LBProvisioningData.ANC_SUP;
3019#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3107 "ConvertDataSetRangeToUnmapBlockDescr (%p): Generating UNMAP Block Descriptors from DataSetRange: \
3108 \n\t\tStartingOffset = %I64u bytes \
3109 \n\t\tLength = %I64u bytes\n",
3151 "ConvertDataSetRangeToUnmapBlockDescr (%p): Generated UNMAP Block Descriptor: \
3152 \n\t\t\tStartingLBA = %I64u \
3153 \n\t\t\tLBACount = %I64u\n",
3201 ULONG maxBlockDescrCount;
3202 ULONG neededBlockDescrCount;
3205 BOOLEAN allDataSetRangeFullyConverted;
3207 BOOLEAN tempDataSetRangeFullyConverted;
3209 ULONG dataSetRangeIndex;
3212 ULONG blockDescrIndex;
3231 neededBlockDescrCount = 0;
3232 for (
i = 0;
i < DataSetRangesCount;
i++) {
3233 lbaCount = DataSetRanges[
i].LengthInBytes /
FdoExtension->DiskGeometry.BytesPerSector;
3239 neededBlockDescrCount += (
ULONG)((lbaCount - 1) /
MAXULONG + 1);
3248 if (
FdoExtension->FunctionSupportInfo->BlockLimitsData.MaxUnmapBlockDescrCount != 0 &&
3261 maxParameterListLength =
min(maxParameterListLength,
MAXUSHORT);
3276 if (maxBlockDescrCount == 0) {
3282 "DeviceProcessDsmTrimRequest (%p): Max Block Descriptor count is Zero\n",
3294 if (maxLbaCount == 0) {
3300 "DeviceProcessDsmTrimRequest (%p): Max LBA count is Zero\n",
3312#if defined(_ARM_) || defined(_ARM64_)
3330 blockDescrPointer = &
buffer->Descriptors[0];
3332 allDataSetRangeFullyConverted =
FALSE;
3333 needToSendCommand =
FALSE;
3334 tempDataSetRangeFullyConverted =
TRUE;
3335 dataSetRangeIndex = 0;
3338 blockDescrIndex = 0;
3342 while (!allDataSetRangeFullyConverted) {
3348 if (tempDataSetRangeFullyConverted) {
3349 tempDataSetRange.
StartingOffset = DataSetRanges[dataSetRangeIndex].StartingOffset;
3350 tempDataSetRange.
LengthInBytes = DataSetRanges[dataSetRangeIndex].LengthInBytes;
3351 dataSetRangeIndex++;
3365 allDataSetRangeFullyConverted = tempDataSetRangeFullyConverted && (dataSetRangeIndex == DataSetRangesCount);
3370 if ((blockDescrIndex == maxBlockDescrCount) ||
3371 (lbaCount == maxLbaCount) ||
3372 allDataSetRangeFullyConverted) {
3442 cdb->
UNMAP.Anchor = 0;
3443 cdb->
UNMAP.GroupNumber = 0;
3444 cdb->
UNMAP.AllocationLength[0] = (
UCHAR)(transferSize >> 8);
3445 cdb->
UNMAP.AllocationLength[1] = (
UCHAR)transferSize;
3455 "DeviceProcessDsmTrimRequest (%p): UNMAP command issued. Returned NTSTATUS: %!STATUS!.\n",
3463 blockDescrIndex = 0;
3496 ULONG dataSetRangesCount;
3500 ULONG granularityInBlocks;
3504 ULONG generationCount;
3509 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess ==
Supported) ) {
3516 "ClasspDeviceTrimProcess (%p): Lower layer supports Trim DSM IOCTL, forwarding IOCTL.\n",
3555 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess) {
3562 "ClasspDeviceTrimProcess (%p): Trim DSM IOCTL support unknown. Forwarded IOCTL and received NTSTATUS %!STATUS!.\n",
3576 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning ==
TRUE) {
3577 NT_ASSERT(fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus != -1);
3580 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits ==
TRUE) {
3581 NT_ASSERT(fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus != -1);
3589 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess =
Supported;
3603 if (fdoExtension->DiskGeometry.BytesPerSector == 0) {
3605 if(!
NT_SUCCESS(
status) || fdoExtension->DiskGeometry.BytesPerSector == 0) {
3632 granularityInBlocks = 1;
3636 "ClasspDeviceTrimProcess (%p): Optimal Unmap Granularity not provided, defaulted to 1.\n",
3646 granularityAlignmentInBytes = 0;
3650 "ClasspDeviceTrimProcess (%p): Unmap Granularity Alignment not provided, defaulted to 0.\n",
3663 dataSetRanges = &entireDataSetRange;
3664 dataSetRangesCount = 1;
3676 for (
i = 0;
i < dataSetRangesCount;
i++)
3678 if ((dataSetRanges[
i].
StartingOffset % fdoExtension->DiskGeometry.BytesPerSector != 0) ||
3679 (dataSetRanges[
i].
LengthInBytes % fdoExtension->DiskGeometry.BytesPerSector != 0) ||
3681 (dataSetRanges[
i].LengthInBytes == 0) ||
3686 "ClasspDeviceTrimProcess (%p): Invalid dataset range. StartingOffset = %I64x, LengthInBytes = %I64x\n",
3689 dataSetRanges[
i].LengthInBytes));
3708 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning &&
3709 !fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ) {
3713 "ClasspDeviceTrimProcess (%p): Device does not support file level TRIM.\n",
3726 granularityInBlocks,
3736 "ClasspDeviceTrimProcess (%p): Device does not support UNMAP.\n",
3743 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess =
NotSupported;
3760 Irp->IoStatus.Information = 0;
3804 if (LBAStatusHeader ==
NULL || LBAStatusSize == 0)
3827 "GetLBAStatus (%p): sending command with StartingLBA = 0x%I64x, AllocationLength = 0x%I64x, ConsolidateableBlocksOnly = %u\n",
3831 ConsolidateableBlocksOnly));
3852 "GetLBAStatus (%p): command returned NT Status: %!STATUS!\n",
3917 ULONG dsmOutputLength;
3921 ULONG retryCountMax;
3923 ULONG generationCount1;
3924 ULONG generationCount2;
3925 BOOLEAN blockLimitsDataMayHaveChanged;
3930 ULONG outputVersion;
3936 if (dsmOutput ==
NULL ||
3937 dsmAttributes ==
NULL)
3947 ULONG unmapGranularityAlignment = 0;
3948 if (fdoExtension->FunctionSupportInfo->BlockLimitsData.UGAVALID) {
3949 unmapGranularityAlignment = fdoExtension->FunctionSupportInfo->BlockLimitsData.UnmapGranularityAlignment;
3951 startingOffset = unmapGranularityAlignment;
3964 startingOffset = dataSetRanges[0].StartingOffset;
3965 lengthInBytes = dataSetRanges[0].LengthInBytes;
3974#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3978 if ((parameters->
Version == DEVICE_DATA_SET_LBP_STATE_PARAMETERS_VERSION_V1) &&
4009 consolidateableBlocksOnly =
TRUE;
4017 for (retryCount = 0; retryCount < retryCountMax; retryCount++) {
4019 dsmOutputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
4027 consolidateableBlocksOnly,
4029 &blockLimitsDataMayHaveChanged);
4031 if (!
NT_SUCCESS(getLBAWorkerStatus) && !blockLimitsDataMayHaveChanged) {
4033 finalStatus = getLBAWorkerStatus;
4050 if (generationCount1 == generationCount2) {
4055 finalStatus = getLBAWorkerStatus;
4065 generationCount1 = generationCount2;
4072 Irp->IoStatus.Status = finalStatus;
4154 ULONG requiredOutputLength;
4155 ULONG outputLength = *DsmOutputLength;
4157 ULONG blocksPerSlab;
4160 ULONG alignmentInBlocks = 0;
4161 ULONG maxBufferSize;
4166 ULONG totalProcessedSlabs = 0;
4170 ULONG lbaStatusSize;
4177 *BlockLimitsDataMayHaveChanged =
FALSE;
4192 if (!fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU)
4215 if (BlockLimitsData->UGAVALID ==
TRUE) {
4216 alignmentInBlocks = BlockLimitsData->UnmapGranularityAlignment;
4226 if (LengthInBytes == 0 ||
4232 "ClasspDeviceGetLBAStatusWorker (%p): Invalid range, length is %I64u bytes, starting offset is %I64u bytes, Unmap alignment is %I64u bytes, and disk size is %I64u bytes\n",
4247 blocksPerSlab = BlockLimitsData->OptimalUnmapGranularity;
4257 startingLBA = (((
StartingOffset - alignmentInBytes) / bytesPerSlab) + 1) * (
ULONGLONG)blocksPerSlab + alignmentInBlocks;
4262 startingLBA = ((
StartingOffset - alignmentInBytes) / bytesPerSlab) * (
ULONGLONG)blocksPerSlab + alignmentInBlocks;
4263 startingOffsetDelta = 0;
4269 if ((LengthInBytes % bytesPerSlab) == 0) {
4270 requestedSlabs = (LengthInBytes / bytesPerSlab);
4279 requestedSlabs = (LengthInBytes / bytesPerSlab) + 1;
4285 if (requestedSlabs == 0)
4289 "ClasspDeviceGetLBAStatusWorker (%p): Invalid number (%I64u) of slabs requested\n",
4314#if (NTDDI_VERSION >= NTDDI_WINBLUE)
4319 + (((requestedSlabs - 1) / bitMapGranularityInBits))
4330 + (((requestedSlabs - 1) / bitMapGranularityInBits))
4338 if (outputLength < requiredOutputLength)
4344 "ClasspDeviceGetLBAStatusWorker (%p): Given output buffer is %u bytes, needs to be %u bytes\n",
4347 requiredOutputLength));
4353 if (outputLength >=
sizeof(
ULONG))
4355 *((
PULONG)DsmOutput) = requiredOutputLength;
4370 maxBufferSize =
MIN(
MAXULONG, fdoExtension->PrivateFdoData->HwMaxXferLen);
4372 slabsPerCommand =
min(requestedSlabs, maxSlabs);
4380#if defined(_ARM_) || defined(_ARM64_)
4391 if (lbaStatusListHeader ==
NULL)
4395 "ClasspDeviceGetLBAStatusWorker (%p): Failed to allocate %u bytes for descriptors\n",
4411 DsmOutput->OutputBlockOffset = 0;
4412 DsmOutput->OutputBlockLength = 0;
4413 *DsmOutputLength = DsmOutput->Size;
4429 lbaStatusListHeader,
4431 ConsolidateableBlocksOnly);
4435 ULONG descrIndex = 0;
4436 ULONG descrSize = 0;
4437 ULONG descrSizeOverhead;
4438 ULONG descrCount = 0;
4441 ULONG commandProcessedSlabs = 0;
4456 if (descrSize >= descrSizeOverhead) {
4457 descrSize -= descrSizeOverhead;
4463 if (descrCount > 0) {
4468 expectedStartingLBA = startingLBA;
4476 for (descrIndex = 0; descrIndex < descrCount && totalProcessedSlabs < requestedSlabs && !doneProcessing; descrIndex++)
4486 if (returnedStartingLBA != expectedStartingLBA)
4496 "ClasspDeviceGetLBAStatusWorker (%p): Device returned starting LBA = %I64x when %I64x was expected.\n",
4498 returnedStartingLBA,
4501 doneProcessing =
TRUE;
4502 processCurrentDescriptor =
FALSE;
4503 *BlockLimitsDataMayHaveChanged =
TRUE;
4505 else if (lbaCount > 0 && lbaCount % blocksPerSlab != 0)
4516 "ClasspDeviceGetLBAStatusWorker (%p): Device returned an LBA count (%u) that is not a multiple of the slab size (%u)\n",
4521 lbaCount = ((lbaCount / blocksPerSlab) + 1) * blocksPerSlab;
4523 doneProcessing =
TRUE;
4524 processCurrentDescriptor =
TRUE;
4526 else if (lbaCount == 0)
4533 "ClasspDeviceGetLBAStatusWorker (%p): Device returned a zero LBA count\n",
4536 processCurrentDescriptor =
FALSE;
4544 if (processCurrentDescriptor)
4546 ULONG descrSlabs = lbaCount / blocksPerSlab;
4548 for(; 0 < descrSlabs && totalProcessedSlabs < requestedSlabs; descrSlabs--, commandProcessedSlabs++, totalProcessedSlabs++)
4550 ULONG bitMapIndex = totalProcessedSlabs / bitMapGranularityInBits;
4551 ULONG bitPos = totalProcessedSlabs % bitMapGranularityInBits;
4553 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
4559 lbpState->SlabAllocationBitMap[bitMapIndex] |= (mapped << bitPos);
4567 expectedStartingLBA = returnedStartingLBA + lbaCount;
4570 if (commandProcessedSlabs > 0) {
4583 "ClasspDeviceGetLBAStatusWorker (%p): The slab allocation bitmap has zero length.\n",
4587 doneProcessing =
TRUE;
4593 "ClasspDeviceGetLBAStatusWorker (%p): Device returned no LBA Status Descriptors.\n",
4596 doneProcessing =
TRUE;
4602 "ClasspDeviceGetLBAStatusWorker (%p): not enough bytes returned\n",
4605 doneProcessing =
TRUE;
4615 (totalProcessedSlabs < requestedSlabs));
4622 if (totalProcessedSlabs > 0) {
4624 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
4646 lbpState->SlabSizeInBytes = bytesPerSlab;
4647 lbpState->SlabOffsetDeltaInBytes = (
ULONG)startingOffsetDelta;
4648 lbpState->SlabAllocationBitMapBitCount = totalProcessedSlabs;
4649 lbpState->SlabAllocationBitMapLength = ((totalProcessedSlabs - 1) / bitMapGranularityInBits) + 1;
4658 + ((lbpState->SlabAllocationBitMapLength - 1) *
sizeof(lbpState->SlabAllocationBitMap[0]));
4661 DsmOutput->OutputBlockLength = lbpState->Size;
4663 *DsmOutputLength = DsmOutput->Size + DsmOutput->OutputBlockLength;
4670 "ClasspDeviceGetLBAStatusWorker (%p): Processed a total of %u slabs\n",
4672 totalProcessedSlabs));
4723 "ClassGetLBProvisioningLogPage: DO (%p), Invalid parameter, LogPage = %p, LogPageSize = %u.\n",
4766 cdb->LOGSENSE.PCBit = 0;
4767 cdb->LOGSENSE.ParameterPointer[0] = 0;
4768 cdb->LOGSENSE.ParameterPointer[1] = 0;
4792 "ClassGetLBProvisioningLogPage: DO (%p), LogSense command issued for LBP log page. NT Status: %!STATUS!.\n",
4844 ULONG resourceCount;
4845 UCHAR thresholdExponent = fdoExtension->FunctionSupportInfo->LBProvisioningData.ThresholdExponent;
4852 if (thresholdExponent < 0 || thresholdExponent > 32)
4856 "ClassInterpretLBProvisioningLogPage: DO (%p), Threshold Exponent (%u) is invalid.\n",
4858 thresholdExponent));
4870 "ClassInterpretLBProvisioningLogPage: DO (%p), Invalid parameter, Resources = %p, ResourcesSize = %u, LogPage = %p, LogPageSize = %u.\n",