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