3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 THESE ARE EXPORTED CLASSPNP FUNCTIONS (and their subroutines)
12 WHICH ARE NOW OBSOLETE.
13 BUT WE NEED TO KEEP THEM AROUND FOR LEGACY REASONS.
28 PIRP NTAPI
ClassRemoveCScanList(IN PCSCAN_LIST List
);
29 VOID NTAPI
ClasspInitializeCScanList(IN PCSCAN_LIST List
);
32 #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList)
33 #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList)
36 typedef struct _CSCAN_LIST_ENTRY
{
38 ULONGLONG BlockNumber
;
39 } CSCAN_LIST_ENTRY
, *PCSCAN_LIST_ENTRY
;
44 * This is a legacy exported function.
45 * It is called by storage miniport driver that have their own
46 * StartIo routine when the transfer size is too large for the hardware.
47 * We map it to our new read/write handler.
49 VOID NTAPI
ClassSplitRequest(IN PDEVICE_OBJECT Fdo
, IN PIRP Irp
, IN ULONG MaximumBytes
)
51 PFUNCTIONAL_DEVICE_EXTENSION fdoExt
= Fdo
->DeviceExtension
;
52 PCLASS_PRIVATE_FDO_DATA fdoData
= fdoExt
->PrivateFdoData
;
54 if (MaximumBytes
> fdoData
->HwMaxXferLen
) {
55 DBGERR(("ClassSplitRequest - driver requesting split to size that "
56 "hardware is unable to handle!\n"));
59 if (MaximumBytes
< fdoData
->HwMaxXferLen
){
60 DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen "
62 fdoData
->HwMaxXferLen
= MAX(MaximumBytes
, PAGE_SIZE
);
65 ServiceTransferRequest(Fdo
, Irp
);
68 /*++////////////////////////////////////////////////////////////////////////////
70 ClassIoCompleteAssociated()
74 This routine executes when the port driver has completed a request.
75 It looks at the SRB status in the completing SRB and if not success
76 it checks for valid request sense buffer information. If valid, the
77 info is used to update status with more precise message of type of
78 error. This routine deallocates the SRB. This routine is used for
79 requests which were build by split request. After it has processed
80 the request it decrements the Irp count in the master Irp. If the
81 count goes to zero then the master Irp is completed.
85 Fdo - Supplies the functional device object which represents the target.
87 Irp - Supplies the Irp which has completed.
89 Context - Supplies a pointer to the SRB.
98 ClassIoCompleteAssociated(
99 IN PDEVICE_OBJECT Fdo
,
104 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
106 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
107 PSCSI_REQUEST_BLOCK srb
= Context
;
109 PIRP originalIrp
= Irp
->AssociatedIrp
.MasterIrp
;
115 DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !"));
118 // Check SRB status for success of completing request.
121 if (SRB_STATUS(srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) {
125 DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp
, srb
));
128 // Release the queue if it is frozen.
131 if (srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
) {
132 ClassReleaseQueue(Fdo
);
135 retry
= ClassInterpretSenseInfo(
138 irpStack
->MajorFunction
,
139 irpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
?
140 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
:
143 ((ULONG
)(ULONG_PTR
)irpStack
->Parameters
.Others
.Argument4
),
148 // If the status is verified required and the this request
149 // should bypass verify required then retry the request.
152 if (irpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
&&
153 status
== STATUS_VERIFY_REQUIRED
) {
155 status
= STATUS_IO_DEVICE_ERROR
;
159 if (retry
&& ((*(PCHAR
*)&irpStack
->Parameters
.Others
.Argument4
)--)) {
162 // Retry request. If the class driver has supplied a StartIo,
163 // call it directly for retries.
166 DebugPrint((1, "Retry request %p\n", Irp
));
168 if (PORT_ALLOCATED_SENSE(fdoExtension
, srb
)) {
169 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension
, srb
);
172 RetryRequest(Fdo
, Irp
, srb
, TRUE
, retryInterval
);
174 return STATUS_MORE_PROCESSING_REQUIRED
;
180 // Set status for successful request.
183 status
= STATUS_SUCCESS
;
185 } // end if (SRB_STATUS(srb->SrbStatus) ...
188 // Return SRB to list.
191 if (PORT_ALLOCATED_SENSE(fdoExtension
, srb
)) {
192 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension
, srb
);
195 ClassFreeOrReuseSrb(fdoExtension
, srb
);
198 // Set status in completing IRP.
201 Irp
->IoStatus
.Status
= status
;
203 DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp
));
206 // Get next stack location. This original request is unused
207 // except to keep track of the completing partial IRPs so the
208 // stack location is valid.
211 irpStack
= IoGetNextIrpStackLocation(originalIrp
);
214 // Update status only if error so that if any partial transfer
215 // completes with error, then the original IRP will return with
216 // error. If any of the asynchronous partial transfer IRPs fail,
217 // with an error then the original IRP will return 0 bytes transfered.
218 // This is an optimization for successful transfers.
221 if (!NT_SUCCESS(status
)) {
223 originalIrp
->IoStatus
.Status
= status
;
224 originalIrp
->IoStatus
.Information
= 0;
227 // Set the hard error if necessary.
230 if (IoIsErrorUserInduced(status
)) {
233 // Store DeviceObject for filesystem.
236 IoSetHardErrorOrVerifyDevice(originalIrp
, Fdo
);
241 // Decrement and get the count of remaining IRPs.
244 irpCount
= InterlockedDecrement(
245 (PLONG
)&irpStack
->Parameters
.Others
.Argument1
);
247 DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n",
251 // Ensure that the irpCount doesn't go negative. This was happening once
252 // because classpnp would get confused if it ran out of resources when
253 // splitting the request.
256 ASSERT(irpCount
>= 0);
261 // All partial IRPs have completed.
265 "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
268 if (fdoExtension
->CommonExtension
.DriverExtension
->InitData
.ClassStartIo
) {
271 // Acquire a separate copy of the remove lock so the debugging code
272 // works okay and we don't have to hold up the completion of this
273 // irp until after we start the next packet(s).
278 ClassAcquireRemoveLock(Fdo
, (PIRP
)&uniqueAddress
);
279 ClassReleaseRemoveLock(Fdo
, originalIrp
);
280 ClassCompleteRequest(Fdo
, originalIrp
, IO_DISK_INCREMENT
);
282 KeRaiseIrql(DISPATCH_LEVEL
, &oldIrql
);
283 IoStartNextPacket(Fdo
, FALSE
);
284 KeLowerIrql(oldIrql
);
286 ClassReleaseRemoveLock(Fdo
, (PIRP
)&uniqueAddress
);
291 // just complete this request
294 ClassReleaseRemoveLock(Fdo
, originalIrp
);
295 ClassCompleteRequest(Fdo
, originalIrp
, IO_DISK_INCREMENT
);
302 // Deallocate IRP and indicate the I/O system should not attempt any more
307 return STATUS_MORE_PROCESSING_REQUIRED
;
309 } // end ClassIoCompleteAssociated()
311 /*++////////////////////////////////////////////////////////////////////////////
317 This is a wrapper around the delayed retry DPC routine, RetryRequestDPC.
318 This reinitializes the necessary fields, queues the request, and sets
319 a timer to call the DPC if someone hasn't already done so.
323 DeviceObject - Supplies the device object associated with this request.
325 Irp - Supplies the request to be retried.
327 Srb - Supplies a Pointer to the SCSI request block to be retied.
329 Associated - Indicates this is an associated Irp created by split request.
331 RetryInterval - How long, in seconds, before retrying the request.
341 PDEVICE_OBJECT DeviceObject
,
343 PSCSI_REQUEST_BLOCK Srb
,
348 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
349 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
350 ULONG transferByteCount
;
352 // This function is obsolete but is still used by some of our class drivers.
353 // DBGWARN(("RetryRequest is OBSOLETE !"));
356 // Determine the transfer count of the request. If this is a read or a
357 // write then the transfer count is in the Irp stack. Otherwise assume
358 // the MDL contains the correct length. If there is no MDL then the
359 // transfer length must be zero.
362 if (currentIrpStack
->MajorFunction
== IRP_MJ_READ
||
363 currentIrpStack
->MajorFunction
== IRP_MJ_WRITE
) {
365 transferByteCount
= currentIrpStack
->Parameters
.Read
.Length
;
367 } else if (Irp
->MdlAddress
!= NULL
) {
370 // Note this assumes that only read and write requests are spilt and
371 // other request do not need to be. If the data buffer address in
372 // the MDL and the SRB don't match then transfer length is most
376 ASSERT(Srb
->DataBuffer
== MmGetMdlVirtualAddress(Irp
->MdlAddress
));
377 transferByteCount
= Irp
->MdlAddress
->ByteCount
;
381 transferByteCount
= 0;
385 // this is a safety net. this should not normally be hit, since we are
386 // not guaranteed to be an fdoExtension
389 ASSERT(!TEST_FLAG(Srb
->SrbFlags
, SRB_FLAGS_FREE_SENSE_BUFFER
));
392 // Reset byte count of transfer in SRB Extension.
395 Srb
->DataTransferLength
= transferByteCount
;
398 // Zero SRB statuses.
401 Srb
->SrbStatus
= Srb
->ScsiStatus
= 0;
404 // Set the no disconnect flag, disable synchronous data transfers and
405 // disable tagged queuing. This fixes some errors.
406 // NOTE: Cannot clear these flags, just add to them
409 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DISABLE_DISCONNECT
);
410 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DISABLE_SYNCH_TRANSFER
);
411 CLEAR_FLAG(Srb
->SrbFlags
, SRB_FLAGS_QUEUE_ACTION_ENABLE
);
413 Srb
->QueueTag
= SP_UNTAGGED
;
416 // Set up major SCSI function.
419 nextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
422 // Save SRB address in next stack for port driver.
425 nextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
428 IoSetCompletionRoutine(Irp
, ClassIoComplete
, Srb
, TRUE
, TRUE
, TRUE
);
431 LARGE_INTEGER retry100ns
;
432 retry100ns
.QuadPart
= RetryInterval
; // seconds
433 retry100ns
.QuadPart
*= (LONGLONG
)1000 * 1000 * 10;
435 ClassRetryRequest(DeviceObject
, Irp
, retry100ns
);
438 } // end RetryRequest()
446 This routine allocates an SRB for the specified request then calls
447 ClasspBuildRequestEx to create a SCSI operation to read or write the device.
449 If no SRB is available then the request will be queued to be issued later
450 when requests are available. Drivers which do not want the queueing
451 behavior should allocate the SRB themselves and call ClasspBuildRequestEx
456 Fdo - Supplies the functional device object associated with this request.
458 Irp - Supplies the request to be retried.
462 If the IRP is for a disk transfer, the byteoffset field
463 will already have been adjusted to make it relative to
464 the beginning of the disk.
479 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
481 PSCSI_REQUEST_BLOCK srb
;
483 // This function is obsolete, but still called by CDROM.SYS .
484 // DBGWARN(("ClassBuildRequest is OBSOLETE !"));
490 srb
= ClasspAllocateSrb(fdoExtension
);
493 return STATUS_INSUFFICIENT_RESOURCES
;
496 ClasspBuildRequestEx(fdoExtension
, Irp
, srb
);
497 return STATUS_SUCCESS
;
499 } // end ClassBuildRequest()
503 ClasspBuildRequestEx(
504 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
506 IN PSCSI_REQUEST_BLOCK Srb
511 ClasspBuildRequestEx()
515 This routine allocates and builds an Srb for a read or write request.
516 The block address and length are supplied by the Irp. The retry count
517 is stored in the current stack for use by ClassIoComplete which
518 processes these requests when they complete. The Irp is ready to be
519 passed to the port driver when this routine returns.
523 FdoExtension - Supplies the device extension associated with this request.
525 Irp - Supplies the request to be issued.
527 Srb - Supplies an SRB to be used for the request.
531 If the IRP is for a disk transfer, the byteoffset field
532 will already have been adjusted to make it relative to
533 the beginning of the disk.
542 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
543 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
545 LARGE_INTEGER startingOffset
= currentIrpStack
->Parameters
.Read
.ByteOffset
;
548 ULONG logicalBlockAddress
;
549 USHORT transferBlocks
;
551 // This function is obsolete, but still called by CDROM.SYS .
552 // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !"));
558 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
561 // Calculate relative sector address.
564 logicalBlockAddress
=
565 (ULONG
)(Int64ShrlMod32(startingOffset
.QuadPart
,
566 FdoExtension
->SectorShift
));
569 // Write length to SRB.
572 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
575 // Set up IRP Address.
578 Srb
->OriginalRequest
= Irp
;
581 // Set up target ID and logical unit number.
584 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
585 Srb
->DataBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
588 // Save byte count of transfer in SRB Extension.
591 Srb
->DataTransferLength
= currentIrpStack
->Parameters
.Read
.Length
;
594 // Initialize the queue actions field.
597 Srb
->QueueAction
= SRB_SIMPLE_TAG_REQUEST
;
600 // Queue sort key is Relative Block Address.
603 Srb
->QueueSortKey
= logicalBlockAddress
;
606 // Indicate auto request sense by specifying buffer and size.
609 Srb
->SenseInfoBuffer
= FdoExtension
->SenseData
;
610 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
613 // Set timeout value of one unit per 64k bytes of data.
616 Srb
->TimeOutValue
= ((Srb
->DataTransferLength
+ 0xFFFF) >> 16) *
617 FdoExtension
->TimeOutValue
;
623 Srb
->SrbStatus
= Srb
->ScsiStatus
= 0;
627 // Indicate that 10-byte CDB's will be used.
633 // Fill in CDB fields.
636 cdb
= (PCDB
)Srb
->Cdb
;
638 transferBlocks
= (USHORT
)(currentIrpStack
->Parameters
.Read
.Length
>>
639 FdoExtension
->SectorShift
);
642 // Move little endian values into CDB in big endian format.
645 cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte3
;
646 cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte2
;
647 cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte1
;
648 cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte0
;
650 cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)&transferBlocks
)->Byte1
;
651 cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)&transferBlocks
)->Byte0
;
654 // Set transfer direction flag and Cdb command.
657 if (currentIrpStack
->MajorFunction
== IRP_MJ_READ
) {
659 DebugPrint((3, "ClassBuildRequest: Read Command\n"));
661 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_IN
);
662 cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
666 DebugPrint((3, "ClassBuildRequest: Write Command\n"));
668 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_OUT
);
669 cdb
->CDB10
.OperationCode
= SCSIOP_WRITE
;
673 // If this is not a write-through request, then allow caching.
676 if (!(currentIrpStack
->Flags
& SL_WRITE_THROUGH
)) {
678 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_ADAPTER_CACHE_ENABLE
);
683 // If write caching is enable then force media access in the
687 if (FdoExtension
->DeviceFlags
& DEV_WRITE_CACHE
) {
688 cdb
->CDB10
.ForceUnitAccess
= TRUE
;
692 if(TEST_FLAG(Irp
->Flags
, (IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
))) {
693 SET_FLAG(Srb
->SrbFlags
, SRB_CLASS_FLAGS_PAGING
);
697 // OR in the default flags from the device object.
700 SET_FLAG(Srb
->SrbFlags
, FdoExtension
->SrbFlags
);
703 // Set up major SCSI function.
706 nextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
709 // Save SRB address in next stack for port driver.
712 nextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
715 // Save retry count in current IRP stack.
718 currentIrpStack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
721 // Set up IoCompletion routine address.
724 IoSetCompletionRoutine(Irp
, ClassIoComplete
, Srb
, TRUE
, TRUE
, TRUE
);
728 VOID NTAPI
ClasspInsertCScanList(IN PLIST_ENTRY ListHead
, IN PCSCAN_LIST_ENTRY Entry
)
732 DBGWARN(("ClasspInsertCScanList is OBSOLETE !"));
735 // Iterate through the list. Insert this entry in the sorted list in
736 // order (after other requests for the same block). At each stop if
737 // blockNumber(Entry) >= blockNumber(t) then move on.
740 for(t
= (PCSCAN_LIST_ENTRY
) ListHead
->Flink
;
741 t
!= (PCSCAN_LIST_ENTRY
) ListHead
;
742 t
= (PCSCAN_LIST_ENTRY
) t
->Entry
.Flink
) {
744 if(Entry
->BlockNumber
< t
->BlockNumber
) {
747 // Set the pointers in entry to the right location.
750 Entry
->Entry
.Flink
= &(t
->Entry
);
751 Entry
->Entry
.Blink
= t
->Entry
.Blink
;
754 // Set the pointers in the surrounding elements to refer to us.
757 t
->Entry
.Blink
->Flink
= &(Entry
->Entry
);
758 t
->Entry
.Blink
= &(Entry
->Entry
);
764 // Insert this entry at the tail of the list. If the list was empty this
765 // will also be the head of the list.
768 InsertTailList(ListHead
, &(Entry
->Entry
));
772 VOID NTAPI
ClassInsertCScanList(IN PCSCAN_LIST List
, IN PIRP Irp
, IN ULONGLONG BlockNumber
, IN BOOLEAN LowPriority
)
777 This routine inserts an entry into the CScan list based on it's block number
778 and priority. It is assumed that the caller is providing synchronization
779 to the access of the list.
781 Low priority requests are always scheduled to run on the next sweep across
782 the disk. Normal priority requests will be inserted into the current or
783 next sweep based on the standard C-SCAN algorithm.
787 List - the list to insert into
789 Irp - the irp to be inserted.
791 BlockNumber - the block number for this request.
793 LowPriority - indicates that the request is lower priority and should be
794 done on the next sweep across the disk.
802 PCSCAN_LIST_ENTRY entry
= (PCSCAN_LIST_ENTRY
)Irp
->Tail
.Overlay
.DriverContext
;
804 DBGWARN(("ClassInsertCScanList is OBSOLETE !"));
807 // Set the block number in the entry. We need this to keep the list sorted.
809 entry
->BlockNumber
= BlockNumber
;
812 // If it's a normal priority request and further down the disk than our
813 // current position then insert this entry into the current sweep.
816 if((LowPriority
!= TRUE
) && (BlockNumber
> List
->BlockNumber
)) {
817 ClasspInsertCScanList(&(List
->CurrentSweep
), entry
);
819 ClasspInsertCScanList(&(List
->NextSweep
), entry
);
824 VOID NTAPI
ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
825 IN PSCSI_REQUEST_BLOCK Srb
)
830 This routine will attempt to reuse the provided SRB to start a blocked
832 If there is no need to reuse the request it will be returned
833 to the SRB lookaside list.
837 Fdo - the device extension
839 Srb - the SRB which is to be reused or freed.
848 PCOMMON_DEVICE_EXTENSION commonExt
= &FdoExtension
->CommonExtension
;
852 // This function is obsolete, but still called by DISK.SYS .
853 // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !"));
856 // safety net. this should never occur. if it does, it's a potential
859 ASSERT(!TEST_FLAG(Srb
->SrbFlags
, SRB_FLAGS_FREE_SENSE_BUFFER
));
861 if (commonExt
->IsSrbLookasideListInitialized
){
863 * Put the SRB back in our lookaside list.
865 * BUGBUG - Some class drivers use ClassIoComplete
866 * to complete SRBs that they themselves allocated.
867 * So we may be putting a "foreign" SRB
868 * (e.g. with a different pool tag) into our lookaside list.
870 ClasspFreeSrb(FdoExtension
, Srb
);
873 DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));
878 /*++////////////////////////////////////////////////////////////////////////////
880 ClassDeleteSrbLookasideList()
884 This routine deletes a lookaside listhead for srbs, and should be called
885 only during the final removal.
887 If called at other times, the caller is responsible for
888 synchronization and removal issues.
892 CommonExtension - Pointer to the CommonExtension containing the listhead.
899 VOID NTAPI
ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension
)
903 // This function is obsolete, but is still called by some of our code.
904 // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !"));
906 if (CommonExtension
->IsSrbLookasideListInitialized
){
907 CommonExtension
->IsSrbLookasideListInitialized
= FALSE
;
908 ExDeleteNPagedLookasideList(&CommonExtension
->SrbLookasideList
);
911 DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
915 /*++////////////////////////////////////////////////////////////////////////////
917 ClassInitializeSrbLookasideList()
921 This routine sets up a lookaside listhead for srbs, and should be called
922 only from the ClassInitDevice() routine to prevent race conditions.
924 If called from other locations, the caller is responsible for
925 synchronization and removal issues.
929 CommonExtension - Pointer to the CommonExtension containing the listhead.
931 NumberElements - Supplies the maximum depth of the lookaside list.
936 The Windows 2000 version of classpnp did not return any status value from
941 VOID NTAPI
ClassInitializeSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension
,
942 IN ULONG NumberElements
)
946 // This function is obsolete, but still called by DISK.SYS .
947 // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !"));
949 ASSERT(!CommonExtension
->IsSrbLookasideListInitialized
);
950 if (!CommonExtension
->IsSrbLookasideListInitialized
){
952 ExInitializeNPagedLookasideList(&CommonExtension
->SrbLookasideList
,
956 sizeof(SCSI_REQUEST_BLOCK
),
958 (USHORT
)NumberElements
);
960 CommonExtension
->IsSrbLookasideListInitialized
= TRUE
;
965 VOID NTAPI
ClasspInitializeCScanList(IN PCSCAN_LIST List
)
968 RtlZeroMemory(List
, sizeof(CSCAN_LIST
));
969 InitializeListHead(&(List
->CurrentSweep
));
970 InitializeListHead(&(List
->NextSweep
));
973 VOID NTAPI
ClasspStartNextSweep(PCSCAN_LIST List
)
975 ASSERT(IsListEmpty(&(List
->CurrentSweep
)) == TRUE
);
978 // If the next sweep is empty then there's nothing to do.
981 if(IsListEmpty(&(List
->NextSweep
))) {
986 // Copy the next sweep list head into the current sweep list head.
989 List
->CurrentSweep
= List
->NextSweep
;
992 // Unlink the next sweep list from the list head now that we have a copy
996 InitializeListHead(&(List
->NextSweep
));
999 // Update the next sweep list to point back to the current sweep list head.
1002 List
->CurrentSweep
.Flink
->Blink
= &(List
->CurrentSweep
);
1003 List
->CurrentSweep
.Blink
->Flink
= &(List
->CurrentSweep
);
1008 PIRP NTAPI
ClassRemoveCScanList(IN PCSCAN_LIST List
)
1010 PCSCAN_LIST_ENTRY entry
;
1013 // If the current sweep is empty then promote the next sweep.
1016 if(IsListEmpty(&(List
->CurrentSweep
))) {
1017 ClasspStartNextSweep(List
);
1021 // If the current sweep is still empty then we're done.
1024 if(IsListEmpty(&(List
->CurrentSweep
))) {
1029 // Remove the head entry from the current sweep. Record it's block number
1030 // so that nothing before it on the disk gets into the current sweep.
1033 entry
= (PCSCAN_LIST_ENTRY
) RemoveHeadList(&(List
->CurrentSweep
));
1035 List
->BlockNumber
= entry
->BlockNumber
;
1037 return CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.DriverContext
);