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.
29 PIRP NTAPI
ClassRemoveCScanList(IN PCSCAN_LIST List
);
30 VOID NTAPI
ClasspInitializeCScanList(IN PCSCAN_LIST List
);
33 #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList)
34 #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList)
37 typedef struct _CSCAN_LIST_ENTRY
{
39 ULONGLONG BlockNumber
;
40 } CSCAN_LIST_ENTRY
, *PCSCAN_LIST_ENTRY
;
45 * This is a legacy exported function.
46 * It is called by storage miniport driver that have their own
47 * StartIo routine when the transfer size is too large for the hardware.
48 * We map it to our new read/write handler.
50 VOID NTAPI
ClassSplitRequest(IN PDEVICE_OBJECT Fdo
, IN PIRP Irp
, IN ULONG MaximumBytes
)
52 PFUNCTIONAL_DEVICE_EXTENSION fdoExt
= Fdo
->DeviceExtension
;
53 PCLASS_PRIVATE_FDO_DATA fdoData
= fdoExt
->PrivateFdoData
;
55 if (MaximumBytes
> fdoData
->HwMaxXferLen
) {
56 DBGERR(("ClassSplitRequest - driver requesting split to size that "
57 "hardware is unable to handle!\n"));
60 if (MaximumBytes
< fdoData
->HwMaxXferLen
){
61 DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen "
63 fdoData
->HwMaxXferLen
= MAX(MaximumBytes
, PAGE_SIZE
);
66 ServiceTransferRequest(Fdo
, Irp
);
69 /*++////////////////////////////////////////////////////////////////////////////
71 ClassIoCompleteAssociated()
75 This routine executes when the port driver has completed a request.
76 It looks at the SRB status in the completing SRB and if not success
77 it checks for valid request sense buffer information. If valid, the
78 info is used to update status with more precise message of type of
79 error. This routine deallocates the SRB. This routine is used for
80 requests which were build by split request. After it has processed
81 the request it decrements the Irp count in the master Irp. If the
82 count goes to zero then the master Irp is completed.
86 Fdo - Supplies the functional device object which represents the target.
88 Irp - Supplies the Irp which has completed.
90 Context - Supplies a pointer to the SRB.
99 ClassIoCompleteAssociated(
100 IN PDEVICE_OBJECT Fdo
,
105 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
107 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
108 PSCSI_REQUEST_BLOCK srb
= Context
;
110 PIRP originalIrp
= Irp
->AssociatedIrp
.MasterIrp
;
116 DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !"));
119 // Check SRB status for success of completing request.
122 if (SRB_STATUS(srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) {
126 DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp
, srb
));
129 // Release the queue if it is frozen.
132 if (srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
) {
133 ClassReleaseQueue(Fdo
);
136 retry
= ClassInterpretSenseInfo(
139 irpStack
->MajorFunction
,
140 irpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
?
141 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
:
144 ((ULONG
)(ULONG_PTR
)irpStack
->Parameters
.Others
.Argument4
),
149 // If the status is verified required and the this request
150 // should bypass verify required then retry the request.
153 if (irpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
&&
154 status
== STATUS_VERIFY_REQUIRED
) {
156 status
= STATUS_IO_DEVICE_ERROR
;
160 if (retry
&& ((*(PCHAR
*)&irpStack
->Parameters
.Others
.Argument4
)--)) {
163 // Retry request. If the class driver has supplied a StartIo,
164 // call it directly for retries.
167 DebugPrint((1, "Retry request %p\n", Irp
));
169 if (PORT_ALLOCATED_SENSE(fdoExtension
, srb
)) {
170 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension
, srb
);
173 RetryRequest(Fdo
, Irp
, srb
, TRUE
, retryInterval
);
175 return STATUS_MORE_PROCESSING_REQUIRED
;
181 // Set status for successful request.
184 status
= STATUS_SUCCESS
;
186 } // end if (SRB_STATUS(srb->SrbStatus) ...
189 // Return SRB to list.
192 if (PORT_ALLOCATED_SENSE(fdoExtension
, srb
)) {
193 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension
, srb
);
196 ClassFreeOrReuseSrb(fdoExtension
, srb
);
199 // Set status in completing IRP.
202 Irp
->IoStatus
.Status
= status
;
204 DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp
));
207 // Get next stack location. This original request is unused
208 // except to keep track of the completing partial IRPs so the
209 // stack location is valid.
212 irpStack
= IoGetNextIrpStackLocation(originalIrp
);
215 // Update status only if error so that if any partial transfer
216 // completes with error, then the original IRP will return with
217 // error. If any of the asynchronous partial transfer IRPs fail,
218 // with an error then the original IRP will return 0 bytes transfered.
219 // This is an optimization for successful transfers.
222 if (!NT_SUCCESS(status
)) {
224 originalIrp
->IoStatus
.Status
= status
;
225 originalIrp
->IoStatus
.Information
= 0;
228 // Set the hard error if necessary.
231 if (IoIsErrorUserInduced(status
)) {
234 // Store DeviceObject for filesystem.
237 IoSetHardErrorOrVerifyDevice(originalIrp
, Fdo
);
242 // Decrement and get the count of remaining IRPs.
245 irpCount
= InterlockedDecrement(
246 (PLONG
)&irpStack
->Parameters
.Others
.Argument1
);
248 DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n",
252 // Ensure that the irpCount doesn't go negative. This was happening once
253 // because classpnp would get confused if it ran out of resources when
254 // splitting the request.
257 ASSERT(irpCount
>= 0);
262 // All partial IRPs have completed.
266 "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
269 if (fdoExtension
->CommonExtension
.DriverExtension
->InitData
.ClassStartIo
) {
272 // Acquire a separate copy of the remove lock so the debugging code
273 // works okay and we don't have to hold up the completion of this
274 // irp until after we start the next packet(s).
279 ClassAcquireRemoveLock(Fdo
, (PIRP
)&uniqueAddress
);
280 ClassReleaseRemoveLock(Fdo
, originalIrp
);
281 ClassCompleteRequest(Fdo
, originalIrp
, IO_DISK_INCREMENT
);
283 KeRaiseIrql(DISPATCH_LEVEL
, &oldIrql
);
284 IoStartNextPacket(Fdo
, FALSE
);
285 KeLowerIrql(oldIrql
);
287 ClassReleaseRemoveLock(Fdo
, (PIRP
)&uniqueAddress
);
292 // just complete this request
295 ClassReleaseRemoveLock(Fdo
, originalIrp
);
296 ClassCompleteRequest(Fdo
, originalIrp
, IO_DISK_INCREMENT
);
303 // Deallocate IRP and indicate the I/O system should not attempt any more
308 return STATUS_MORE_PROCESSING_REQUIRED
;
310 } // end ClassIoCompleteAssociated()
312 /*++////////////////////////////////////////////////////////////////////////////
318 This is a wrapper around the delayed retry DPC routine, RetryRequestDPC.
319 This reinitializes the necessary fields, queues the request, and sets
320 a timer to call the DPC if someone hasn't already done so.
324 DeviceObject - Supplies the device object associated with this request.
326 Irp - Supplies the request to be retried.
328 Srb - Supplies a Pointer to the SCSI request block to be retied.
330 Assocaiated - Indicates this is an assocatied Irp created by split request.
332 RetryInterval - How long, in seconds, before retrying the request.
342 PDEVICE_OBJECT DeviceObject
,
344 PSCSI_REQUEST_BLOCK Srb
,
349 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
350 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
351 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
352 ULONG transferByteCount
;
354 // This function is obsolete but is still used by some of our class drivers.
355 // DBGWARN(("RetryRequest is OBSOLETE !"));
358 // Determine the transfer count of the request. If this is a read or a
359 // write then the transfer count is in the Irp stack. Otherwise assume
360 // the MDL contains the correct length. If there is no MDL then the
361 // transfer length must be zero.
364 if (currentIrpStack
->MajorFunction
== IRP_MJ_READ
||
365 currentIrpStack
->MajorFunction
== IRP_MJ_WRITE
) {
367 transferByteCount
= currentIrpStack
->Parameters
.Read
.Length
;
369 } else if (Irp
->MdlAddress
!= NULL
) {
372 // Note this assumes that only read and write requests are spilt and
373 // other request do not need to be. If the data buffer address in
374 // the MDL and the SRB don't match then transfer length is most
378 ASSERT(Srb
->DataBuffer
== MmGetMdlVirtualAddress(Irp
->MdlAddress
));
379 transferByteCount
= Irp
->MdlAddress
->ByteCount
;
383 transferByteCount
= 0;
387 // this is a safety net. this should not normally be hit, since we are
388 // not guaranteed to be an fdoExtension
391 ASSERT(!TEST_FLAG(Srb
->SrbFlags
, SRB_FLAGS_FREE_SENSE_BUFFER
));
394 // Reset byte count of transfer in SRB Extension.
397 Srb
->DataTransferLength
= transferByteCount
;
400 // Zero SRB statuses.
403 Srb
->SrbStatus
= Srb
->ScsiStatus
= 0;
406 // Set the no disconnect flag, disable synchronous data transfers and
407 // disable tagged queuing. This fixes some errors.
408 // NOTE: Cannot clear these flags, just add to them
411 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DISABLE_DISCONNECT
);
412 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DISABLE_SYNCH_TRANSFER
);
413 CLEAR_FLAG(Srb
->SrbFlags
, SRB_FLAGS_QUEUE_ACTION_ENABLE
);
415 Srb
->QueueTag
= SP_UNTAGGED
;
418 // Set up major SCSI function.
421 nextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
424 // Save SRB address in next stack for port driver.
427 nextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
430 IoSetCompletionRoutine(Irp
, ClassIoComplete
, Srb
, TRUE
, TRUE
, TRUE
);
433 LARGE_INTEGER retry100ns
;
434 retry100ns
.QuadPart
= RetryInterval
; // seconds
435 retry100ns
.QuadPart
*= (LONGLONG
)1000 * 1000 * 10;
437 ClassRetryRequest(DeviceObject
, Irp
, retry100ns
);
440 } // end RetryRequest()
448 This routine allocates an SRB for the specified request then calls
449 ClasspBuildRequestEx to create a SCSI operation to read or write the device.
451 If no SRB is available then the request will be queued to be issued later
452 when requests are available. Drivers which do not want the queueing
453 behavior should allocate the SRB themselves and call ClasspBuildRequestEx
458 Fdo - Supplies the functional device object associated with this request.
460 Irp - Supplies the request to be retried.
464 If the IRP is for a disk transfer, the byteoffset field
465 will already have been adjusted to make it relative to
466 the beginning of the disk.
481 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
483 PSCSI_REQUEST_BLOCK srb
;
485 // This function is obsolete, but still called by CDROM.SYS .
486 // DBGWARN(("ClassBuildRequest is OBSOLETE !"));
492 srb
= ClasspAllocateSrb(fdoExtension
);
495 return STATUS_INSUFFICIENT_RESOURCES
;
498 ClasspBuildRequestEx(fdoExtension
, Irp
, srb
);
499 return STATUS_SUCCESS
;
501 } // end ClassBuildRequest()
505 ClasspBuildRequestEx(
506 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
508 IN PSCSI_REQUEST_BLOCK Srb
513 ClasspBuildRequestEx()
517 This routine allocates and builds an Srb for a read or write request.
518 The block address and length are supplied by the Irp. The retry count
519 is stored in the current stack for use by ClassIoComplete which
520 processes these requests when they complete. The Irp is ready to be
521 passed to the port driver when this routine returns.
525 FdoExtension - Supplies the device extension associated with this request.
527 Irp - Supplies the request to be issued.
529 Srb - Supplies an SRB to be used for the request.
533 If the IRP is for a disk transfer, the byteoffset field
534 will already have been adjusted to make it relative to
535 the beginning of the disk.
544 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
545 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
547 LARGE_INTEGER startingOffset
= currentIrpStack
->Parameters
.Read
.ByteOffset
;
550 ULONG logicalBlockAddress
;
551 USHORT transferBlocks
;
553 // This function is obsolete, but still called by CDROM.SYS .
554 // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !"));
560 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
563 // Calculate relative sector address.
566 logicalBlockAddress
=
567 (ULONG
)(Int64ShrlMod32(startingOffset
.QuadPart
,
568 FdoExtension
->SectorShift
));
571 // Write length to SRB.
574 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
577 // Set up IRP Address.
580 Srb
->OriginalRequest
= Irp
;
583 // Set up target ID and logical unit number.
586 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
587 Srb
->DataBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
590 // Save byte count of transfer in SRB Extension.
593 Srb
->DataTransferLength
= currentIrpStack
->Parameters
.Read
.Length
;
596 // Initialize the queue actions field.
599 Srb
->QueueAction
= SRB_SIMPLE_TAG_REQUEST
;
602 // Queue sort key is Relative Block Address.
605 Srb
->QueueSortKey
= logicalBlockAddress
;
608 // Indicate auto request sense by specifying buffer and size.
611 Srb
->SenseInfoBuffer
= FdoExtension
->SenseData
;
612 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
615 // Set timeout value of one unit per 64k bytes of data.
618 Srb
->TimeOutValue
= ((Srb
->DataTransferLength
+ 0xFFFF) >> 16) *
619 FdoExtension
->TimeOutValue
;
625 Srb
->SrbStatus
= Srb
->ScsiStatus
= 0;
629 // Indicate that 10-byte CDB's will be used.
635 // Fill in CDB fields.
638 cdb
= (PCDB
)Srb
->Cdb
;
640 transferBlocks
= (USHORT
)(currentIrpStack
->Parameters
.Read
.Length
>>
641 FdoExtension
->SectorShift
);
644 // Move little endian values into CDB in big endian format.
647 cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte3
;
648 cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte2
;
649 cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte1
;
650 cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte0
;
652 cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)&transferBlocks
)->Byte1
;
653 cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)&transferBlocks
)->Byte0
;
656 // Set transfer direction flag and Cdb command.
659 if (currentIrpStack
->MajorFunction
== IRP_MJ_READ
) {
661 DebugPrint((3, "ClassBuildRequest: Read Command\n"));
663 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_IN
);
664 cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
668 DebugPrint((3, "ClassBuildRequest: Write Command\n"));
670 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_OUT
);
671 cdb
->CDB10
.OperationCode
= SCSIOP_WRITE
;
675 // If this is not a write-through request, then allow caching.
678 if (!(currentIrpStack
->Flags
& SL_WRITE_THROUGH
)) {
680 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_ADAPTER_CACHE_ENABLE
);
685 // If write caching is enable then force media access in the
689 if (FdoExtension
->DeviceFlags
& DEV_WRITE_CACHE
) {
690 cdb
->CDB10
.ForceUnitAccess
= TRUE
;
694 if(TEST_FLAG(Irp
->Flags
, (IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
))) {
695 SET_FLAG(Srb
->SrbFlags
, SRB_CLASS_FLAGS_PAGING
);
699 // OR in the default flags from the device object.
702 SET_FLAG(Srb
->SrbFlags
, FdoExtension
->SrbFlags
);
705 // Set up major SCSI function.
708 nextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
711 // Save SRB address in next stack for port driver.
714 nextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
717 // Save retry count in current IRP stack.
720 currentIrpStack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
723 // Set up IoCompletion routine address.
726 IoSetCompletionRoutine(Irp
, ClassIoComplete
, Srb
, TRUE
, TRUE
, TRUE
);
730 VOID NTAPI
ClasspInsertCScanList(IN PLIST_ENTRY ListHead
, IN PCSCAN_LIST_ENTRY Entry
)
734 DBGWARN(("ClasspInsertCScanList is OBSOLETE !"));
737 // Iterate through the list. Insert this entry in the sorted list in
738 // order (after other requests for the same block). At each stop if
739 // blockNumber(Entry) >= blockNumber(t) then move on.
742 for(t
= (PCSCAN_LIST_ENTRY
) ListHead
->Flink
;
743 t
!= (PCSCAN_LIST_ENTRY
) ListHead
;
744 t
= (PCSCAN_LIST_ENTRY
) t
->Entry
.Flink
) {
746 if(Entry
->BlockNumber
< t
->BlockNumber
) {
749 // Set the pointers in entry to the right location.
752 Entry
->Entry
.Flink
= &(t
->Entry
);
753 Entry
->Entry
.Blink
= t
->Entry
.Blink
;
756 // Set the pointers in the surrounding elements to refer to us.
759 t
->Entry
.Blink
->Flink
= &(Entry
->Entry
);
760 t
->Entry
.Blink
= &(Entry
->Entry
);
766 // Insert this entry at the tail of the list. If the list was empty this
767 // will also be the head of the list.
770 InsertTailList(ListHead
, &(Entry
->Entry
));
774 VOID NTAPI
ClassInsertCScanList(IN PCSCAN_LIST List
, IN PIRP Irp
, IN ULONGLONG BlockNumber
, IN BOOLEAN LowPriority
)
779 This routine inserts an entry into the CScan list based on it's block number
780 and priority. It is assumed that the caller is providing synchronization
781 to the access of the list.
783 Low priority requests are always scheduled to run on the next sweep across
784 the disk. Normal priority requests will be inserted into the current or
785 next sweep based on the standard C-SCAN algorithm.
789 List - the list to insert into
791 Irp - the irp to be inserted.
793 BlockNumber - the block number for this request.
795 LowPriority - indicates that the request is lower priority and should be
796 done on the next sweep across the disk.
804 PCSCAN_LIST_ENTRY entry
= (PCSCAN_LIST_ENTRY
)Irp
->Tail
.Overlay
.DriverContext
;
806 DBGWARN(("ClassInsertCScanList is OBSOLETE !"));
809 // Set the block number in the entry. We need this to keep the list sorted.
811 entry
->BlockNumber
= BlockNumber
;
814 // If it's a normal priority request and further down the disk than our
815 // current position then insert this entry into the current sweep.
818 if((LowPriority
!= TRUE
) && (BlockNumber
> List
->BlockNumber
)) {
819 ClasspInsertCScanList(&(List
->CurrentSweep
), entry
);
821 ClasspInsertCScanList(&(List
->NextSweep
), entry
);
826 VOID NTAPI
ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
827 IN PSCSI_REQUEST_BLOCK Srb
)
832 This routine will attempt to reuse the provided SRB to start a blocked
834 If there is no need to reuse the request it will be returned
835 to the SRB lookaside list.
839 Fdo - the device extension
841 Srb - the SRB which is to be reused or freed.
850 PCLASS_PRIVATE_FDO_DATA privateData
= FdoExtension
->PrivateFdoData
;
851 PCOMMON_DEVICE_EXTENSION commonExt
= &FdoExtension
->CommonExtension
;
855 // This function is obsolete, but still called by DISK.SYS .
856 // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !"));
859 // safety net. this should never occur. if it does, it's a potential
862 ASSERT(!TEST_FLAG(Srb
->SrbFlags
, SRB_FLAGS_FREE_SENSE_BUFFER
));
864 if (commonExt
->IsSrbLookasideListInitialized
){
866 * Put the SRB back in our lookaside list.
868 * BUGBUG - Some class drivers use ClassIoComplete
869 * to complete SRBs that they themselves allocated.
870 * So we may be putting a "foreign" SRB
871 * (e.g. with a different pool tag) into our lookaside list.
873 ClasspFreeSrb(FdoExtension
, Srb
);
876 DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));;
881 /*++////////////////////////////////////////////////////////////////////////////
883 ClassDeleteSrbLookasideList()
887 This routine deletes a lookaside listhead for srbs, and should be called
888 only during the final removal.
890 If called at other times, the caller is responsible for
891 synchronization and removal issues.
895 CommonExtension - Pointer to the CommonExtension containing the listhead.
902 VOID NTAPI
ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension
)
906 // This function is obsolete, but is still called by some of our code.
907 // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !"));
909 if (CommonExtension
->IsSrbLookasideListInitialized
){
910 CommonExtension
->IsSrbLookasideListInitialized
= FALSE
;
911 ExDeleteNPagedLookasideList(&CommonExtension
->SrbLookasideList
);
914 DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
918 /*++////////////////////////////////////////////////////////////////////////////
920 ClassInitializeSrbLookasideList()
924 This routine sets up a lookaside listhead for srbs, and should be called
925 only from the ClassInitDevice() routine to prevent race conditions.
927 If called from other locations, the caller is responsible for
928 synchronization and removal issues.
932 CommonExtension - Pointer to the CommonExtension containing the listhead.
934 NumberElements - Supplies the maximum depth of the lookaside list.
939 The Windows 2000 version of classpnp did not return any status value from
944 VOID NTAPI
ClassInitializeSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension
,
945 IN ULONG NumberElements
)
949 // This function is obsolete, but still called by DISK.SYS .
950 // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !"));
952 ASSERT(!CommonExtension
->IsSrbLookasideListInitialized
);
953 if (!CommonExtension
->IsSrbLookasideListInitialized
){
955 ExInitializeNPagedLookasideList(&CommonExtension
->SrbLookasideList
,
959 sizeof(SCSI_REQUEST_BLOCK
),
961 (USHORT
)NumberElements
);
963 CommonExtension
->IsSrbLookasideListInitialized
= TRUE
;
968 VOID NTAPI
ClasspInitializeCScanList(IN PCSCAN_LIST List
)
971 RtlZeroMemory(List
, sizeof(CSCAN_LIST
));
972 InitializeListHead(&(List
->CurrentSweep
));
973 InitializeListHead(&(List
->NextSweep
));
976 VOID NTAPI
ClasspStartNextSweep(PCSCAN_LIST List
)
978 ASSERT(IsListEmpty(&(List
->CurrentSweep
)) == TRUE
);
981 // If the next sweep is empty then there's nothing to do.
984 if(IsListEmpty(&(List
->NextSweep
))) {
989 // Copy the next sweep list head into the current sweep list head.
992 List
->CurrentSweep
= List
->NextSweep
;
995 // Unlink the next sweep list from the list head now that we have a copy
999 InitializeListHead(&(List
->NextSweep
));
1002 // Update the next sweep list to point back to the current sweep list head.
1005 List
->CurrentSweep
.Flink
->Blink
= &(List
->CurrentSweep
);
1006 List
->CurrentSweep
.Blink
->Flink
= &(List
->CurrentSweep
);
1011 PIRP NTAPI
ClassRemoveCScanList(IN PCSCAN_LIST List
)
1013 PCSCAN_LIST_ENTRY entry
;
1016 // If the current sweep is empty then promote the next sweep.
1019 if(IsListEmpty(&(List
->CurrentSweep
))) {
1020 ClasspStartNextSweep(List
);
1024 // If the current sweep is still empty then we're done.
1027 if(IsListEmpty(&(List
->CurrentSweep
))) {
1032 // Remove the head entry from the current sweep. Record it's block number
1033 // so that nothing before it on the disk gets into the current sweep.
1036 entry
= (PCSCAN_LIST_ENTRY
) RemoveHeadList(&(List
->CurrentSweep
));
1038 List
->BlockNumber
= entry
->BlockNumber
;
1040 return CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.DriverContext
);