[CLASSPNP]
[reactos.git] / reactos / drivers / storage / classpnp / obsolete.c
1 /*++
2
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4
5 Module Name:
6
7 obsolete.c
8
9 Abstract:
10
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.
14
15 Environment:
16
17 kernel mode only
18
19 Notes:
20
21
22 Revision History:
23
24 --*/
25
26 #include "classp.h"
27
28 PIRP NTAPI ClassRemoveCScanList(IN PCSCAN_LIST List);
29 VOID NTAPI ClasspInitializeCScanList(IN PCSCAN_LIST List);
30
31 #ifdef ALLOC_PRAGMA
32 #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList)
33 #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList)
34 #endif
35
36 typedef struct _CSCAN_LIST_ENTRY {
37 LIST_ENTRY Entry;
38 ULONGLONG BlockNumber;
39 } CSCAN_LIST_ENTRY, *PCSCAN_LIST_ENTRY;
40
41 /*
42 * ClassSplitRequest
43 *
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.
48 */
49 VOID NTAPI ClassSplitRequest(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN ULONG MaximumBytes)
50 {
51 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
52 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
53
54 if (MaximumBytes > fdoData->HwMaxXferLen) {
55 DBGERR(("ClassSplitRequest - driver requesting split to size that "
56 "hardware is unable to handle!\n"));
57 }
58
59 if (MaximumBytes < fdoData->HwMaxXferLen){
60 DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen "
61 "than required"));
62 fdoData->HwMaxXferLen = MAX(MaximumBytes, PAGE_SIZE);
63 }
64
65 ServiceTransferRequest(Fdo, Irp);
66 }
67
68 /*++////////////////////////////////////////////////////////////////////////////
69
70 ClassIoCompleteAssociated()
71
72 Routine Description:
73
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.
82
83 Arguments:
84
85 Fdo - Supplies the functional device object which represents the target.
86
87 Irp - Supplies the Irp which has completed.
88
89 Context - Supplies a pointer to the SRB.
90
91 Return Value:
92
93 NT status
94
95 --*/
96 NTSTATUS
97 NTAPI
98 ClassIoCompleteAssociated(
99 IN PDEVICE_OBJECT Fdo,
100 IN PIRP Irp,
101 IN PVOID Context
102 )
103 {
104 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
105
106 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
107 PSCSI_REQUEST_BLOCK srb = Context;
108
109 PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
110 LONG irpCount;
111
112 NTSTATUS status;
113 BOOLEAN retry;
114
115 DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !"));
116
117 //
118 // Check SRB status for success of completing request.
119 //
120
121 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
122
123 ULONG retryInterval;
124
125 DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp, srb));
126
127 //
128 // Release the queue if it is frozen.
129 //
130
131 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
132 ClassReleaseQueue(Fdo);
133 }
134
135 retry = ClassInterpretSenseInfo(
136 Fdo,
137 srb,
138 irpStack->MajorFunction,
139 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ?
140 irpStack->Parameters.DeviceIoControl.IoControlCode :
141 0,
142 MAXIMUM_RETRIES -
143 ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
144 &status,
145 &retryInterval);
146
147 //
148 // If the status is verified required and the this request
149 // should bypass verify required then retry the request.
150 //
151
152 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
153 status == STATUS_VERIFY_REQUIRED) {
154
155 status = STATUS_IO_DEVICE_ERROR;
156 retry = TRUE;
157 }
158
159 if (retry && ((*(PCHAR*)&irpStack->Parameters.Others.Argument4)--)) {
160
161 //
162 // Retry request. If the class driver has supplied a StartIo,
163 // call it directly for retries.
164 //
165
166 DebugPrint((1, "Retry request %p\n", Irp));
167
168 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
169 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
170 }
171
172 RetryRequest(Fdo, Irp, srb, TRUE, retryInterval);
173
174 return STATUS_MORE_PROCESSING_REQUIRED;
175 }
176
177 } else {
178
179 //
180 // Set status for successful request.
181 //
182
183 status = STATUS_SUCCESS;
184
185 } // end if (SRB_STATUS(srb->SrbStatus) ...
186
187 //
188 // Return SRB to list.
189 //
190
191 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
192 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
193 }
194
195 ClassFreeOrReuseSrb(fdoExtension, srb);
196
197 //
198 // Set status in completing IRP.
199 //
200
201 Irp->IoStatus.Status = status;
202
203 DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp));
204
205 //
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.
209 //
210
211 irpStack = IoGetNextIrpStackLocation(originalIrp);
212
213 //
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.
219 //
220
221 if (!NT_SUCCESS(status)) {
222
223 originalIrp->IoStatus.Status = status;
224 originalIrp->IoStatus.Information = 0;
225
226 //
227 // Set the hard error if necessary.
228 //
229
230 if (IoIsErrorUserInduced(status)) {
231
232 //
233 // Store DeviceObject for filesystem.
234 //
235
236 IoSetHardErrorOrVerifyDevice(originalIrp, Fdo);
237 }
238 }
239
240 //
241 // Decrement and get the count of remaining IRPs.
242 //
243
244 irpCount = InterlockedDecrement(
245 (PLONG)&irpStack->Parameters.Others.Argument1);
246
247 DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n",
248 irpCount));
249
250 //
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.
254 //
255
256 ASSERT(irpCount >= 0);
257
258 if (irpCount == 0) {
259
260 //
261 // All partial IRPs have completed.
262 //
263
264 DebugPrint((2,
265 "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
266 originalIrp));
267
268 if (fdoExtension->CommonExtension.DriverExtension->InitData.ClassStartIo) {
269
270 //
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).
274 //
275
276 KIRQL oldIrql;
277 UCHAR uniqueAddress;
278 ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddress);
279 ClassReleaseRemoveLock(Fdo, originalIrp);
280 ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
281
282 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
283 IoStartNextPacket(Fdo, FALSE);
284 KeLowerIrql(oldIrql);
285
286 ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddress);
287
288 } else {
289
290 //
291 // just complete this request
292 //
293
294 ClassReleaseRemoveLock(Fdo, originalIrp);
295 ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
296
297 }
298
299 }
300
301 //
302 // Deallocate IRP and indicate the I/O system should not attempt any more
303 // processing.
304 //
305
306 IoFreeIrp(Irp);
307 return STATUS_MORE_PROCESSING_REQUIRED;
308
309 } // end ClassIoCompleteAssociated()
310
311 /*++////////////////////////////////////////////////////////////////////////////
312
313 RetryRequest()
314
315 Routine Description:
316
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.
320
321 Arguments:
322
323 DeviceObject - Supplies the device object associated with this request.
324
325 Irp - Supplies the request to be retried.
326
327 Srb - Supplies a Pointer to the SCSI request block to be retied.
328
329 Assocaiated - Indicates this is an assocatied Irp created by split request.
330
331 RetryInterval - How long, in seconds, before retrying the request.
332
333 Return Value:
334
335 None
336
337 --*/
338 VOID
339 NTAPI
340 RetryRequest(
341 PDEVICE_OBJECT DeviceObject,
342 PIRP Irp,
343 PSCSI_REQUEST_BLOCK Srb,
344 BOOLEAN Associated,
345 ULONG RetryInterval
346 )
347 {
348 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
349 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
350 ULONG transferByteCount;
351
352 // This function is obsolete but is still used by some of our class drivers.
353 // DBGWARN(("RetryRequest is OBSOLETE !"));
354
355 //
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.
360 //
361
362 if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
363 currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
364
365 transferByteCount = currentIrpStack->Parameters.Read.Length;
366
367 } else if (Irp->MdlAddress != NULL) {
368
369 //
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
373 // likely incorrect.
374 //
375
376 ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
377 transferByteCount = Irp->MdlAddress->ByteCount;
378
379 } else {
380
381 transferByteCount = 0;
382 }
383
384 //
385 // this is a safety net. this should not normally be hit, since we are
386 // not guaranteed to be an fdoExtension
387 //
388
389 ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
390
391 //
392 // Reset byte count of transfer in SRB Extension.
393 //
394
395 Srb->DataTransferLength = transferByteCount;
396
397 //
398 // Zero SRB statuses.
399 //
400
401 Srb->SrbStatus = Srb->ScsiStatus = 0;
402
403 //
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
407 //
408
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);
412
413 Srb->QueueTag = SP_UNTAGGED;
414
415 //
416 // Set up major SCSI function.
417 //
418
419 nextIrpStack->MajorFunction = IRP_MJ_SCSI;
420
421 //
422 // Save SRB address in next stack for port driver.
423 //
424
425 nextIrpStack->Parameters.Scsi.Srb = Srb;
426
427
428 IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);
429
430 {
431 LARGE_INTEGER retry100ns;
432 retry100ns.QuadPart = RetryInterval; // seconds
433 retry100ns.QuadPart *= (LONGLONG)1000 * 1000 * 10;
434
435 ClassRetryRequest(DeviceObject, Irp, retry100ns);
436 }
437 return;
438 } // end RetryRequest()
439
440 /*++
441
442 ClassBuildRequest()
443
444 Routine Description:
445
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.
448
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
452 to issue it.
453
454 Arguments:
455
456 Fdo - Supplies the functional device object associated with this request.
457
458 Irp - Supplies the request to be retried.
459
460 Note:
461
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.
465
466
467 Return Value:
468
469 NT Status
470
471 --*/
472 NTSTATUS
473 NTAPI
474 ClassBuildRequest(
475 PDEVICE_OBJECT Fdo,
476 PIRP Irp
477 )
478 {
479 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
480
481 PSCSI_REQUEST_BLOCK srb;
482
483 // This function is obsolete, but still called by CDROM.SYS .
484 // DBGWARN(("ClassBuildRequest is OBSOLETE !"));
485
486 //
487 // Allocate an Srb.
488 //
489
490 srb = ClasspAllocateSrb(fdoExtension);
491
492 if(srb == NULL) {
493 return STATUS_INSUFFICIENT_RESOURCES;
494 }
495
496 ClasspBuildRequestEx(fdoExtension, Irp, srb);
497 return STATUS_SUCCESS;
498
499 } // end ClassBuildRequest()
500
501 VOID
502 NTAPI
503 ClasspBuildRequestEx(
504 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
505 IN PIRP Irp,
506 IN PSCSI_REQUEST_BLOCK Srb
507 )
508
509 /*++
510
511 ClasspBuildRequestEx()
512
513 Routine Description:
514
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.
520
521 Arguments:
522
523 FdoExtension - Supplies the device extension associated with this request.
524
525 Irp - Supplies the request to be issued.
526
527 Srb - Supplies an SRB to be used for the request.
528
529 Note:
530
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.
534
535
536 Return Value:
537
538 NT Status
539
540 --*/
541 {
542 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
543 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
544
545 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
546
547 PCDB cdb;
548 ULONG logicalBlockAddress;
549 USHORT transferBlocks;
550
551 // This function is obsolete, but still called by CDROM.SYS .
552 // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !"));
553
554 //
555 // Prepare the SRB.
556 //
557
558 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
559
560 //
561 // Calculate relative sector address.
562 //
563
564 logicalBlockAddress =
565 (ULONG)(Int64ShrlMod32(startingOffset.QuadPart,
566 FdoExtension->SectorShift));
567
568 //
569 // Write length to SRB.
570 //
571
572 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
573
574 //
575 // Set up IRP Address.
576 //
577
578 Srb->OriginalRequest = Irp;
579
580 //
581 // Set up target ID and logical unit number.
582 //
583
584 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
585 Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
586
587 //
588 // Save byte count of transfer in SRB Extension.
589 //
590
591 Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
592
593 //
594 // Initialize the queue actions field.
595 //
596
597 Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
598
599 //
600 // Queue sort key is Relative Block Address.
601 //
602
603 Srb->QueueSortKey = logicalBlockAddress;
604
605 //
606 // Indicate auto request sense by specifying buffer and size.
607 //
608
609 Srb->SenseInfoBuffer = FdoExtension->SenseData;
610 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
611
612 //
613 // Set timeout value of one unit per 64k bytes of data.
614 //
615
616 Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) *
617 FdoExtension->TimeOutValue;
618
619 //
620 // Zero statuses.
621 //
622
623 Srb->SrbStatus = Srb->ScsiStatus = 0;
624 Srb->NextSrb = 0;
625
626 //
627 // Indicate that 10-byte CDB's will be used.
628 //
629
630 Srb->CdbLength = 10;
631
632 //
633 // Fill in CDB fields.
634 //
635
636 cdb = (PCDB)Srb->Cdb;
637
638 transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >>
639 FdoExtension->SectorShift);
640
641 //
642 // Move little endian values into CDB in big endian format.
643 //
644
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;
649
650 cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
651 cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;
652
653 //
654 // Set transfer direction flag and Cdb command.
655 //
656
657 if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
658
659 DebugPrint((3, "ClassBuildRequest: Read Command\n"));
660
661 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN);
662 cdb->CDB10.OperationCode = SCSIOP_READ;
663
664 } else {
665
666 DebugPrint((3, "ClassBuildRequest: Write Command\n"));
667
668 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT);
669 cdb->CDB10.OperationCode = SCSIOP_WRITE;
670 }
671
672 //
673 // If this is not a write-through request, then allow caching.
674 //
675
676 if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {
677
678 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE);
679
680 } else {
681
682 //
683 // If write caching is enable then force media access in the
684 // cdb.
685 //
686
687 if (FdoExtension->DeviceFlags & DEV_WRITE_CACHE) {
688 cdb->CDB10.ForceUnitAccess = TRUE;
689 }
690 }
691
692 if(TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) {
693 SET_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING);
694 }
695
696 //
697 // OR in the default flags from the device object.
698 //
699
700 SET_FLAG(Srb->SrbFlags, FdoExtension->SrbFlags);
701
702 //
703 // Set up major SCSI function.
704 //
705
706 nextIrpStack->MajorFunction = IRP_MJ_SCSI;
707
708 //
709 // Save SRB address in next stack for port driver.
710 //
711
712 nextIrpStack->Parameters.Scsi.Srb = Srb;
713
714 //
715 // Save retry count in current IRP stack.
716 //
717
718 currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
719
720 //
721 // Set up IoCompletion routine address.
722 //
723
724 IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);
725
726 }
727
728 VOID NTAPI ClasspInsertCScanList(IN PLIST_ENTRY ListHead, IN PCSCAN_LIST_ENTRY Entry)
729 {
730 PCSCAN_LIST_ENTRY t;
731
732 DBGWARN(("ClasspInsertCScanList is OBSOLETE !"));
733
734 //
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.
738 //
739
740 for(t = (PCSCAN_LIST_ENTRY) ListHead->Flink;
741 t != (PCSCAN_LIST_ENTRY) ListHead;
742 t = (PCSCAN_LIST_ENTRY) t->Entry.Flink) {
743
744 if(Entry->BlockNumber < t->BlockNumber) {
745
746 //
747 // Set the pointers in entry to the right location.
748 //
749
750 Entry->Entry.Flink = &(t->Entry);
751 Entry->Entry.Blink = t->Entry.Blink;
752
753 //
754 // Set the pointers in the surrounding elements to refer to us.
755 //
756
757 t->Entry.Blink->Flink = &(Entry->Entry);
758 t->Entry.Blink = &(Entry->Entry);
759 return;
760 }
761 }
762
763 //
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.
766 //
767
768 InsertTailList(ListHead, &(Entry->Entry));
769
770 }
771
772 VOID NTAPI ClassInsertCScanList(IN PCSCAN_LIST List, IN PIRP Irp, IN ULONGLONG BlockNumber, IN BOOLEAN LowPriority)
773 /*++
774
775 Routine Description:
776
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.
780
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.
784
785 Arguments:
786
787 List - the list to insert into
788
789 Irp - the irp to be inserted.
790
791 BlockNumber - the block number for this request.
792
793 LowPriority - indicates that the request is lower priority and should be
794 done on the next sweep across the disk.
795
796 Return Value:
797
798 none
799
800 --*/
801 {
802 PCSCAN_LIST_ENTRY entry = (PCSCAN_LIST_ENTRY)Irp->Tail.Overlay.DriverContext;
803
804 DBGWARN(("ClassInsertCScanList is OBSOLETE !"));
805
806 //
807 // Set the block number in the entry. We need this to keep the list sorted.
808 //
809 entry->BlockNumber = BlockNumber;
810
811 //
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.
814 //
815
816 if((LowPriority != TRUE) && (BlockNumber > List->BlockNumber)) {
817 ClasspInsertCScanList(&(List->CurrentSweep), entry);
818 } else {
819 ClasspInsertCScanList(&(List->NextSweep), entry);
820 }
821 return;
822 }
823
824 VOID NTAPI ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
825 IN PSCSI_REQUEST_BLOCK Srb)
826 /*++
827
828 Routine Description:
829
830 This routine will attempt to reuse the provided SRB to start a blocked
831 read/write request.
832 If there is no need to reuse the request it will be returned
833 to the SRB lookaside list.
834
835 Arguments:
836
837 Fdo - the device extension
838
839 Srb - the SRB which is to be reused or freed.
840
841 Return Value:
842
843 none.
844
845 --*/
846
847 {
848 PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension;
849 //KIRQL oldIrql;
850 //PIRP blockedIrp;
851
852 // This function is obsolete, but still called by DISK.SYS .
853 // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !"));
854
855 //
856 // safety net. this should never occur. if it does, it's a potential
857 // memory leak.
858 //
859 ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
860
861 if (commonExt->IsSrbLookasideListInitialized){
862 /*
863 * Put the SRB back in our lookaside list.
864 *
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.
869 */
870 ClasspFreeSrb(FdoExtension, Srb);
871 }
872 else {
873 DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));;
874 ExFreePool(Srb);
875 }
876 }
877
878 /*++////////////////////////////////////////////////////////////////////////////
879
880 ClassDeleteSrbLookasideList()
881
882 Routine Description:
883
884 This routine deletes a lookaside listhead for srbs, and should be called
885 only during the final removal.
886
887 If called at other times, the caller is responsible for
888 synchronization and removal issues.
889
890 Arguments:
891
892 CommonExtension - Pointer to the CommonExtension containing the listhead.
893
894 Return Value:
895
896 None
897
898 --*/
899 VOID NTAPI ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension)
900 {
901 PAGED_CODE();
902
903 // This function is obsolete, but is still called by some of our code.
904 // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !"));
905
906 if (CommonExtension->IsSrbLookasideListInitialized){
907 CommonExtension->IsSrbLookasideListInitialized = FALSE;
908 ExDeleteNPagedLookasideList(&CommonExtension->SrbLookasideList);
909 }
910 else {
911 DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
912 }
913 }
914
915 /*++////////////////////////////////////////////////////////////////////////////
916
917 ClassInitializeSrbLookasideList()
918
919 Routine Description:
920
921 This routine sets up a lookaside listhead for srbs, and should be called
922 only from the ClassInitDevice() routine to prevent race conditions.
923
924 If called from other locations, the caller is responsible for
925 synchronization and removal issues.
926
927 Arguments:
928
929 CommonExtension - Pointer to the CommonExtension containing the listhead.
930
931 NumberElements - Supplies the maximum depth of the lookaside list.
932
933
934 Note:
935
936 The Windows 2000 version of classpnp did not return any status value from
937 this call.
938
939 --*/
940
941 VOID NTAPI ClassInitializeSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension,
942 IN ULONG NumberElements)
943 {
944 PAGED_CODE();
945
946 // This function is obsolete, but still called by DISK.SYS .
947 // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !"));
948
949 ASSERT(!CommonExtension->IsSrbLookasideListInitialized);
950 if (!CommonExtension->IsSrbLookasideListInitialized){
951
952 ExInitializeNPagedLookasideList(&CommonExtension->SrbLookasideList,
953 NULL,
954 NULL,
955 NonPagedPool,
956 sizeof(SCSI_REQUEST_BLOCK),
957 '$scS',
958 (USHORT)NumberElements);
959
960 CommonExtension->IsSrbLookasideListInitialized = TRUE;
961 }
962
963 }
964
965 VOID NTAPI ClasspInitializeCScanList(IN PCSCAN_LIST List)
966 {
967 PAGED_CODE();
968 RtlZeroMemory(List, sizeof(CSCAN_LIST));
969 InitializeListHead(&(List->CurrentSweep));
970 InitializeListHead(&(List->NextSweep));
971 }
972
973 VOID NTAPI ClasspStartNextSweep(PCSCAN_LIST List)
974 {
975 ASSERT(IsListEmpty(&(List->CurrentSweep)) == TRUE);
976
977 //
978 // If the next sweep is empty then there's nothing to do.
979 //
980
981 if(IsListEmpty(&(List->NextSweep))) {
982 return;
983 }
984
985 //
986 // Copy the next sweep list head into the current sweep list head.
987 //
988
989 List->CurrentSweep = List->NextSweep;
990
991 //
992 // Unlink the next sweep list from the list head now that we have a copy
993 // of it.
994 //
995
996 InitializeListHead(&(List->NextSweep));
997
998 //
999 // Update the next sweep list to point back to the current sweep list head.
1000 //
1001
1002 List->CurrentSweep.Flink->Blink = &(List->CurrentSweep);
1003 List->CurrentSweep.Blink->Flink = &(List->CurrentSweep);
1004
1005 return;
1006 }
1007
1008 PIRP NTAPI ClassRemoveCScanList(IN PCSCAN_LIST List)
1009 {
1010 PCSCAN_LIST_ENTRY entry;
1011
1012 //
1013 // If the current sweep is empty then promote the next sweep.
1014 //
1015
1016 if(IsListEmpty(&(List->CurrentSweep))) {
1017 ClasspStartNextSweep(List);
1018 }
1019
1020 //
1021 // If the current sweep is still empty then we're done.
1022 //
1023
1024 if(IsListEmpty(&(List->CurrentSweep))) {
1025 return NULL;
1026 }
1027
1028 //
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.
1031 //
1032
1033 entry = (PCSCAN_LIST_ENTRY) RemoveHeadList(&(List->CurrentSweep));
1034
1035 List->BlockNumber = entry->BlockNumber;
1036
1037 return CONTAINING_RECORD(entry, IRP, Tail.Overlay.DriverContext);
1038 }