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