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
ClassRemoveCScanList(IN PCSCAN_LIST List
);
30 VOID
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
;
49 * This is a legacy exported function.
50 * It is called by storage miniport driver that have their own
51 * StartIo routine when the transfer size is too large for the hardware.
52 * We map it to our new read/write handler.
54 VOID
ClassSplitRequest(IN PDEVICE_OBJECT Fdo
, IN PIRP Irp
, IN ULONG MaximumBytes
)
56 PFUNCTIONAL_DEVICE_EXTENSION fdoExt
= Fdo
->DeviceExtension
;
57 PCLASS_PRIVATE_FDO_DATA fdoData
= fdoExt
->PrivateFdoData
;
59 if (MaximumBytes
> fdoData
->HwMaxXferLen
) {
60 DBGERR(("ClassSplitRequest - driver requesting split to size that "
61 "hardware is unable to handle!\n"));
64 if (MaximumBytes
< fdoData
->HwMaxXferLen
){
65 DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen "
67 fdoData
->HwMaxXferLen
= MAX(MaximumBytes
, PAGE_SIZE
);
70 ServiceTransferRequest(Fdo
, Irp
);
74 /*++////////////////////////////////////////////////////////////////////////////
76 ClassIoCompleteAssociated()
80 This routine executes when the port driver has completed a request.
81 It looks at the SRB status in the completing SRB and if not success
82 it checks for valid request sense buffer information. If valid, the
83 info is used to update status with more precise message of type of
84 error. This routine deallocates the SRB. This routine is used for
85 requests which were build by split request. After it has processed
86 the request it decrements the Irp count in the master Irp. If the
87 count goes to zero then the master Irp is completed.
91 Fdo - Supplies the functional device object which represents the target.
93 Irp - Supplies the Irp which has completed.
95 Context - Supplies a pointer to the SRB.
103 ClassIoCompleteAssociated(
104 IN PDEVICE_OBJECT Fdo
,
109 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
111 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
112 PSCSI_REQUEST_BLOCK srb
= Context
;
114 PIRP originalIrp
= Irp
->AssociatedIrp
.MasterIrp
;
120 DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !"));
123 // Check SRB status for success of completing request.
126 if (SRB_STATUS(srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) {
130 DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp
, srb
));
133 // Release the queue if it is frozen.
136 if (srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
) {
137 ClassReleaseQueue(Fdo
);
140 retry
= ClassInterpretSenseInfo(
143 irpStack
->MajorFunction
,
144 irpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
?
145 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
:
148 ((ULONG
)(ULONG_PTR
)irpStack
->Parameters
.Others
.Argument4
),
153 // If the status is verified required and the this request
154 // should bypass verify required then retry the request.
157 if (irpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
&&
158 status
== STATUS_VERIFY_REQUIRED
) {
160 status
= STATUS_IO_DEVICE_ERROR
;
164 if (retry
&& ((*(PCHAR
*)&irpStack
->Parameters
.Others
.Argument4
)--)) {
167 // Retry request. If the class driver has supplied a StartIo,
168 // call it directly for retries.
171 DebugPrint((1, "Retry request %p\n", Irp
));
173 if (PORT_ALLOCATED_SENSE(fdoExtension
, srb
)) {
174 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension
, srb
);
177 RetryRequest(Fdo
, Irp
, srb
, TRUE
, retryInterval
);
179 return STATUS_MORE_PROCESSING_REQUIRED
;
185 // Set status for successful request.
188 status
= STATUS_SUCCESS
;
190 } // end if (SRB_STATUS(srb->SrbStatus) ...
193 // Return SRB to list.
196 if (PORT_ALLOCATED_SENSE(fdoExtension
, srb
)) {
197 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension
, srb
);
200 ClassFreeOrReuseSrb(fdoExtension
, srb
);
203 // Set status in completing IRP.
206 Irp
->IoStatus
.Status
= status
;
208 DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp
));
211 // Get next stack location. This original request is unused
212 // except to keep track of the completing partial IRPs so the
213 // stack location is valid.
216 irpStack
= IoGetNextIrpStackLocation(originalIrp
);
219 // Update status only if error so that if any partial transfer
220 // completes with error, then the original IRP will return with
221 // error. If any of the asynchronous partial transfer IRPs fail,
222 // with an error then the original IRP will return 0 bytes transfered.
223 // This is an optimization for successful transfers.
226 if (!NT_SUCCESS(status
)) {
228 originalIrp
->IoStatus
.Status
= status
;
229 originalIrp
->IoStatus
.Information
= 0;
232 // Set the hard error if necessary.
235 if (IoIsErrorUserInduced(status
)) {
238 // Store DeviceObject for filesystem.
241 IoSetHardErrorOrVerifyDevice(originalIrp
, Fdo
);
246 // Decrement and get the count of remaining IRPs.
249 irpCount
= InterlockedDecrement(
250 (PLONG
)&irpStack
->Parameters
.Others
.Argument1
);
252 DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n",
256 // Ensure that the irpCount doesn't go negative. This was happening once
257 // because classpnp would get confused if it ran out of resources when
258 // splitting the request.
261 ASSERT(irpCount
>= 0);
266 // All partial IRPs have completed.
270 "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
273 if (fdoExtension
->CommonExtension
.DriverExtension
->InitData
.ClassStartIo
) {
276 // Acquire a separate copy of the remove lock so the debugging code
277 // works okay and we don't have to hold up the completion of this
278 // irp until after we start the next packet(s).
283 ClassAcquireRemoveLock(Fdo
, (PIRP
)&uniqueAddress
);
284 ClassReleaseRemoveLock(Fdo
, originalIrp
);
285 ClassCompleteRequest(Fdo
, originalIrp
, IO_DISK_INCREMENT
);
287 KeRaiseIrql(DISPATCH_LEVEL
, &oldIrql
);
288 IoStartNextPacket(Fdo
, FALSE
);
289 KeLowerIrql(oldIrql
);
291 ClassReleaseRemoveLock(Fdo
, (PIRP
)&uniqueAddress
);
296 // just complete this request
299 ClassReleaseRemoveLock(Fdo
, originalIrp
);
300 ClassCompleteRequest(Fdo
, originalIrp
, IO_DISK_INCREMENT
);
307 // Deallocate IRP and indicate the I/O system should not attempt any more
312 return STATUS_MORE_PROCESSING_REQUIRED
;
314 } // end ClassIoCompleteAssociated()
317 /*++////////////////////////////////////////////////////////////////////////////
323 This is a wrapper around the delayed retry DPC routine, RetryRequestDPC.
324 This reinitalizes the necessary fields, queues the request, and sets
325 a timer to call the DPC if someone hasn't already done so.
329 DeviceObject - Supplies the device object associated with this request.
331 Irp - Supplies the request to be retried.
333 Srb - Supplies a Pointer to the SCSI request block to be retied.
335 Assocaiated - Indicates this is an assocatied Irp created by split request.
337 RetryInterval - How long, in seconds, before retrying the request.
346 PDEVICE_OBJECT DeviceObject
,
348 PSCSI_REQUEST_BLOCK Srb
,
353 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
354 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
355 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
356 ULONG transferByteCount
;
358 // This function is obsolete but is still used by some of our class drivers.
359 // DBGWARN(("RetryRequest is OBSOLETE !"));
362 // Determine the transfer count of the request. If this is a read or a
363 // write then the transfer count is in the Irp stack. Otherwise assume
364 // the MDL contains the correct length. If there is no MDL then the
365 // transfer length must be zero.
368 if (currentIrpStack
->MajorFunction
== IRP_MJ_READ
||
369 currentIrpStack
->MajorFunction
== IRP_MJ_WRITE
) {
371 transferByteCount
= currentIrpStack
->Parameters
.Read
.Length
;
373 } else if (Irp
->MdlAddress
!= NULL
) {
376 // Note this assumes that only read and write requests are spilt and
377 // other request do not need to be. If the data buffer address in
378 // the MDL and the SRB don't match then transfer length is most
382 ASSERT(Srb
->DataBuffer
== MmGetMdlVirtualAddress(Irp
->MdlAddress
));
383 transferByteCount
= Irp
->MdlAddress
->ByteCount
;
387 transferByteCount
= 0;
391 // this is a safety net. this should not normally be hit, since we are
392 // not guaranteed to be an fdoExtension
395 ASSERT(!TEST_FLAG(Srb
->SrbFlags
, SRB_FLAGS_FREE_SENSE_BUFFER
));
398 // Reset byte count of transfer in SRB Extension.
401 Srb
->DataTransferLength
= transferByteCount
;
404 // Zero SRB statuses.
407 Srb
->SrbStatus
= Srb
->ScsiStatus
= 0;
410 // Set the no disconnect flag, disable synchronous data transfers and
411 // disable tagged queuing. This fixes some errors.
412 // NOTE: Cannot clear these flags, just add to them
415 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DISABLE_DISCONNECT
);
416 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DISABLE_SYNCH_TRANSFER
);
417 CLEAR_FLAG(Srb
->SrbFlags
, SRB_FLAGS_QUEUE_ACTION_ENABLE
);
419 Srb
->QueueTag
= SP_UNTAGGED
;
422 // Set up major SCSI function.
425 nextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
428 // Save SRB address in next stack for port driver.
431 nextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
434 IoSetCompletionRoutine(Irp
, ClassIoComplete
, Srb
, TRUE
, TRUE
, TRUE
);
437 LARGE_INTEGER retry100ns
;
438 retry100ns
.QuadPart
= RetryInterval
; // seconds
439 retry100ns
.QuadPart
*= (LONGLONG
)1000 * 1000 * 10;
441 ClassRetryRequest(DeviceObject
, Irp
, retry100ns
);
444 } // end RetryRequest()
453 This routine allocates an SRB for the specified request then calls
454 ClasspBuildRequestEx to create a SCSI operation to read or write the device.
456 If no SRB is available then the request will be queued to be issued later
457 when requests are available. Drivers which do not want the queueing
458 behavior should allocate the SRB themselves and call ClasspBuildRequestEx
463 Fdo - Supplies the functional device object associated with this request.
465 Irp - Supplies the request to be retried.
469 If the IRP is for a disk transfer, the byteoffset field
470 will already have been adjusted to make it relative to
471 the beginning of the disk.
485 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
487 PSCSI_REQUEST_BLOCK srb
;
489 // This function is obsolete, but still called by CDROM.SYS .
490 // DBGWARN(("ClassBuildRequest is OBSOLETE !"));
496 srb
= ClasspAllocateSrb(fdoExtension
);
499 return STATUS_INSUFFICIENT_RESOURCES
;
502 ClasspBuildRequestEx(fdoExtension
, Irp
, srb
);
503 return STATUS_SUCCESS
;
505 } // end ClassBuildRequest()
509 ClasspBuildRequestEx(
510 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
512 IN PSCSI_REQUEST_BLOCK Srb
517 ClasspBuildRequestEx()
521 This routine allocates and builds an Srb for a read or write request.
522 The block address and length are supplied by the Irp. The retry count
523 is stored in the current stack for use by ClassIoComplete which
524 processes these requests when they complete. The Irp is ready to be
525 passed to the port driver when this routine returns.
529 FdoExtension - Supplies the device extension associated with this request.
531 Irp - Supplies the request to be issued.
533 Srb - Supplies an SRB to be used for the request.
537 If the IRP is for a disk transfer, the byteoffset field
538 will already have been adjusted to make it relative to
539 the beginning of the disk.
548 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
549 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
551 LARGE_INTEGER startingOffset
= currentIrpStack
->Parameters
.Read
.ByteOffset
;
554 ULONG logicalBlockAddress
;
555 USHORT transferBlocks
;
557 // This function is obsolete, but still called by CDROM.SYS .
558 // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !"));
564 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
567 // Calculate relative sector address.
570 logicalBlockAddress
=
571 (ULONG
)(Int64ShrlMod32(startingOffset
.QuadPart
,
572 FdoExtension
->SectorShift
));
575 // Write length to SRB.
578 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
581 // Set up IRP Address.
584 Srb
->OriginalRequest
= Irp
;
587 // Set up target ID and logical unit number.
590 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
591 Srb
->DataBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
594 // Save byte count of transfer in SRB Extension.
597 Srb
->DataTransferLength
= currentIrpStack
->Parameters
.Read
.Length
;
600 // Initialize the queue actions field.
603 Srb
->QueueAction
= SRB_SIMPLE_TAG_REQUEST
;
606 // Queue sort key is Relative Block Address.
609 Srb
->QueueSortKey
= logicalBlockAddress
;
612 // Indicate auto request sense by specifying buffer and size.
615 Srb
->SenseInfoBuffer
= FdoExtension
->SenseData
;
616 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
619 // Set timeout value of one unit per 64k bytes of data.
622 Srb
->TimeOutValue
= ((Srb
->DataTransferLength
+ 0xFFFF) >> 16) *
623 FdoExtension
->TimeOutValue
;
629 Srb
->SrbStatus
= Srb
->ScsiStatus
= 0;
633 // Indicate that 10-byte CDB's will be used.
639 // Fill in CDB fields.
642 cdb
= (PCDB
)Srb
->Cdb
;
644 transferBlocks
= (USHORT
)(currentIrpStack
->Parameters
.Read
.Length
>>
645 FdoExtension
->SectorShift
);
648 // Move little endian values into CDB in big endian format.
651 cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte3
;
652 cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte2
;
653 cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte1
;
654 cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)&logicalBlockAddress
)->Byte0
;
656 cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)&transferBlocks
)->Byte1
;
657 cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)&transferBlocks
)->Byte0
;
660 // Set transfer direction flag and Cdb command.
663 if (currentIrpStack
->MajorFunction
== IRP_MJ_READ
) {
665 DebugPrint((3, "ClassBuildRequest: Read Command\n"));
667 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_IN
);
668 cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
672 DebugPrint((3, "ClassBuildRequest: Write Command\n"));
674 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_OUT
);
675 cdb
->CDB10
.OperationCode
= SCSIOP_WRITE
;
679 // If this is not a write-through request, then allow caching.
682 if (!(currentIrpStack
->Flags
& SL_WRITE_THROUGH
)) {
684 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_ADAPTER_CACHE_ENABLE
);
689 // If write caching is enable then force media access in the
693 if (FdoExtension
->DeviceFlags
& DEV_WRITE_CACHE
) {
694 cdb
->CDB10
.ForceUnitAccess
= TRUE
;
698 if(TEST_FLAG(Irp
->Flags
, (IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
))) {
699 SET_FLAG(Srb
->SrbFlags
, SRB_CLASS_FLAGS_PAGING
);
703 // OR in the default flags from the device object.
706 SET_FLAG(Srb
->SrbFlags
, FdoExtension
->SrbFlags
);
709 // Set up major SCSI function.
712 nextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
715 // Save SRB address in next stack for port driver.
718 nextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
721 // Save retry count in current IRP stack.
724 currentIrpStack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
727 // Set up IoCompletion routine address.
730 IoSetCompletionRoutine(Irp
, ClassIoComplete
, Srb
, TRUE
, TRUE
, TRUE
);
735 VOID
ClasspInsertCScanList(IN PLIST_ENTRY ListHead
, IN PCSCAN_LIST_ENTRY Entry
)
739 DBGWARN(("ClasspInsertCScanList is OBSOLETE !"));
742 // Iterate through the list. Insert this entry in the sorted list in
743 // order (after other requests for the same block). At each stop if
744 // blockNumber(Entry) >= blockNumber(t) then move on.
747 for(t
= (PCSCAN_LIST_ENTRY
) ListHead
->Flink
;
748 t
!= (PCSCAN_LIST_ENTRY
) ListHead
;
749 t
= (PCSCAN_LIST_ENTRY
) t
->Entry
.Flink
) {
751 if(Entry
->BlockNumber
< t
->BlockNumber
) {
754 // Set the pointers in entry to the right location.
757 Entry
->Entry
.Flink
= &(t
->Entry
);
758 Entry
->Entry
.Blink
= t
->Entry
.Blink
;
761 // Set the pointers in the surrounding elements to refer to us.
764 t
->Entry
.Blink
->Flink
= &(Entry
->Entry
);
765 t
->Entry
.Blink
= &(Entry
->Entry
);
771 // Insert this entry at the tail of the list. If the list was empty this
772 // will also be the head of the list.
775 InsertTailList(ListHead
, &(Entry
->Entry
));
780 VOID
ClassInsertCScanList(IN PCSCAN_LIST List
, IN PIRP Irp
, IN ULONGLONG BlockNumber
, IN BOOLEAN LowPriority
)
785 This routine inserts an entry into the CScan list based on it's block number
786 and priority. It is assumed that the caller is providing synchronization
787 to the access of the list.
789 Low priority requests are always scheduled to run on the next sweep across
790 the disk. Normal priority requests will be inserted into the current or
791 next sweep based on the standard C-SCAN algorithm.
795 List - the list to insert into
797 Irp - the irp to be inserted.
799 BlockNumber - the block number for this request.
801 LowPriority - indicates that the request is lower priority and should be
802 done on the next sweep across the disk.
810 PCSCAN_LIST_ENTRY entry
= (PCSCAN_LIST_ENTRY
)Irp
->Tail
.Overlay
.DriverContext
;
812 DBGWARN(("ClassInsertCScanList is OBSOLETE !"));
815 // Set the block number in the entry. We need this to keep the list sorted.
817 entry
->BlockNumber
= BlockNumber
;
820 // If it's a normal priority request and further down the disk than our
821 // current position then insert this entry into the current sweep.
824 if((LowPriority
!= TRUE
) && (BlockNumber
> List
->BlockNumber
)) {
825 ClasspInsertCScanList(&(List
->CurrentSweep
), entry
);
827 ClasspInsertCScanList(&(List
->NextSweep
), entry
);
835 VOID
ClassFreeOrReuseSrb( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
836 IN PSCSI_REQUEST_BLOCK Srb
)
841 This routine will attempt to reuse the provided SRB to start a blocked
843 If there is no need to reuse the request it will be returned
844 to the SRB lookaside list.
848 Fdo - the device extension
850 Srb - the SRB which is to be reused or freed.
859 PCLASS_PRIVATE_FDO_DATA privateData
= FdoExtension
->PrivateFdoData
;
860 PCOMMON_DEVICE_EXTENSION commonExt
= &FdoExtension
->CommonExtension
;
864 // This function is obsolete, but still called by DISK.SYS .
865 // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !"));
868 // safety net. this should never occur. if it does, it's a potential
871 ASSERT(!TEST_FLAG(Srb
->SrbFlags
, SRB_FLAGS_FREE_SENSE_BUFFER
));
873 if (commonExt
->IsSrbLookasideListInitialized
){
875 * Put the SRB back in our lookaside list.
877 * BUGBUG - Some class drivers use ClassIoComplete
878 * to complete SRBs that they themselves allocated.
879 * So we may be putting a "foreign" SRB
880 * (e.g. with a different pool tag) into our lookaside list.
882 ClasspFreeSrb(FdoExtension
, Srb
);
885 DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));;
891 /*++////////////////////////////////////////////////////////////////////////////
893 ClassDeleteSrbLookasideList()
897 This routine deletes a lookaside listhead for srbs, and should be called
898 only during the final removal.
900 If called at other times, the caller is responsible for
901 synchronization and removal issues.
905 CommonExtension - Pointer to the CommonExtension containing the listhead.
912 VOID
ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension
)
916 // This function is obsolete, but is still called by some of our code.
917 // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !"));
919 if (CommonExtension
->IsSrbLookasideListInitialized
){
920 CommonExtension
->IsSrbLookasideListInitialized
= FALSE
;
921 ExDeleteNPagedLookasideList(&CommonExtension
->SrbLookasideList
);
924 DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
929 /*++////////////////////////////////////////////////////////////////////////////
931 ClassInitializeSrbLookasideList()
935 This routine sets up a lookaside listhead for srbs, and should be called
936 only from the ClassInitDevice() routine to prevent race conditions.
938 If called from other locations, the caller is responsible for
939 synchronization and removal issues.
943 CommonExtension - Pointer to the CommonExtension containing the listhead.
945 NumberElements - Supplies the maximum depth of the lookaside list.
950 The Windows 2000 version of classpnp did not return any status value from
955 VOID
ClassInitializeSrbLookasideList( IN PCOMMON_DEVICE_EXTENSION CommonExtension
,
956 IN ULONG NumberElements
)
960 // This function is obsolete, but still called by DISK.SYS .
961 // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !"));
963 ASSERT(!CommonExtension
->IsSrbLookasideListInitialized
);
964 if (!CommonExtension
->IsSrbLookasideListInitialized
){
966 ExInitializeNPagedLookasideList(&CommonExtension
->SrbLookasideList
,
970 sizeof(SCSI_REQUEST_BLOCK
),
972 (USHORT
)NumberElements
);
974 CommonExtension
->IsSrbLookasideListInitialized
= TRUE
;
982 VOID
ClasspInitializeCScanList(IN PCSCAN_LIST List
)
985 RtlZeroMemory(List
, sizeof(CSCAN_LIST
));
986 InitializeListHead(&(List
->CurrentSweep
));
987 InitializeListHead(&(List
->NextSweep
));
992 VOID
ClasspStartNextSweep(PCSCAN_LIST List
)
994 ASSERT(IsListEmpty(&(List
->CurrentSweep
)) == TRUE
);
997 // If the next sweep is empty then there's nothing to do.
1000 if(IsListEmpty(&(List
->NextSweep
))) {
1005 // Copy the next sweep list head into the current sweep list head.
1008 List
->CurrentSweep
= List
->NextSweep
;
1011 // Unlink the next sweep list from the list head now that we have a copy
1015 InitializeListHead(&(List
->NextSweep
));
1018 // Update the next sweep list to point back to the current sweep list head.
1021 List
->CurrentSweep
.Flink
->Blink
= &(List
->CurrentSweep
);
1022 List
->CurrentSweep
.Blink
->Flink
= &(List
->CurrentSweep
);
1029 PIRP
ClassRemoveCScanList(IN PCSCAN_LIST List
)
1031 PCSCAN_LIST_ENTRY entry
;
1034 // If the current sweep is empty then promote the next sweep.
1037 if(IsListEmpty(&(List
->CurrentSweep
))) {
1038 ClasspStartNextSweep(List
);
1042 // If the current sweep is still empty then we're done.
1045 if(IsListEmpty(&(List
->CurrentSweep
))) {
1050 // Remove the head entry from the current sweep. Record it's block number
1051 // so that nothing before it on the disk gets into the current sweep.
1054 entry
= (PCSCAN_LIST_ENTRY
) RemoveHeadList(&(List
->CurrentSweep
));
1056 List
->BlockNumber
= entry
->BlockNumber
;
1058 return CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.DriverContext
);