1bf1b3cb1SVictor Perevertkin /*++
2bf1b3cb1SVictor Perevertkin 
3bf1b3cb1SVictor Perevertkin Copyright (C) Microsoft Corporation, 1991 - 2010
4bf1b3cb1SVictor Perevertkin 
5bf1b3cb1SVictor Perevertkin Module Name:
6bf1b3cb1SVictor Perevertkin 
7bf1b3cb1SVictor Perevertkin     obsolete.c
8bf1b3cb1SVictor Perevertkin 
9bf1b3cb1SVictor Perevertkin Abstract:
10bf1b3cb1SVictor Perevertkin 
11bf1b3cb1SVictor Perevertkin     THESE ARE EXPORTED CLASSPNP FUNCTIONS (and their subroutines)
12bf1b3cb1SVictor Perevertkin     WHICH ARE NOW OBSOLETE.
13bf1b3cb1SVictor Perevertkin     BUT WE NEED TO KEEP THEM AROUND FOR LEGACY REASONS.
14bf1b3cb1SVictor Perevertkin 
15bf1b3cb1SVictor Perevertkin Environment:
16bf1b3cb1SVictor Perevertkin 
17bf1b3cb1SVictor Perevertkin     kernel mode only
18bf1b3cb1SVictor Perevertkin 
19bf1b3cb1SVictor Perevertkin Notes:
20bf1b3cb1SVictor Perevertkin 
21bf1b3cb1SVictor Perevertkin 
22bf1b3cb1SVictor Perevertkin Revision History:
23bf1b3cb1SVictor Perevertkin 
24bf1b3cb1SVictor Perevertkin --*/
25bf1b3cb1SVictor Perevertkin 
26bf1b3cb1SVictor Perevertkin #include "classp.h"
27bf1b3cb1SVictor Perevertkin #include "debug.h"
28bf1b3cb1SVictor Perevertkin 
29bf1b3cb1SVictor Perevertkin #ifdef DEBUG_USE_WPP
30bf1b3cb1SVictor Perevertkin #include "obsolete.tmh"
31bf1b3cb1SVictor Perevertkin #endif
32bf1b3cb1SVictor Perevertkin 
33bf1b3cb1SVictor Perevertkin PIRP ClassRemoveCScanList(IN PCSCAN_LIST List);
34bf1b3cb1SVictor Perevertkin VOID ClasspInitializeCScanList(IN PCSCAN_LIST List);
35bf1b3cb1SVictor Perevertkin 
36bf1b3cb1SVictor Perevertkin #ifdef ALLOC_PRAGMA
37bf1b3cb1SVictor Perevertkin     #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList)
38bf1b3cb1SVictor Perevertkin     #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList)
39bf1b3cb1SVictor Perevertkin     #pragma alloc_text(PAGE, ClasspInitializeCScanList)
40bf1b3cb1SVictor Perevertkin #endif
41bf1b3cb1SVictor Perevertkin 
42bf1b3cb1SVictor Perevertkin typedef struct _CSCAN_LIST_ENTRY {
43bf1b3cb1SVictor Perevertkin     LIST_ENTRY Entry;
44bf1b3cb1SVictor Perevertkin     ULONGLONG BlockNumber;
45bf1b3cb1SVictor Perevertkin } CSCAN_LIST_ENTRY, *PCSCAN_LIST_ENTRY;
46bf1b3cb1SVictor Perevertkin 
47bf1b3cb1SVictor Perevertkin 
48bf1b3cb1SVictor Perevertkin 
49bf1b3cb1SVictor Perevertkin 
50bf1b3cb1SVictor Perevertkin 
51bf1b3cb1SVictor Perevertkin /*
52bf1b3cb1SVictor Perevertkin  *  ClassSplitRequest
53bf1b3cb1SVictor Perevertkin  *
54bf1b3cb1SVictor Perevertkin  *      This is a legacy exported function.
55bf1b3cb1SVictor Perevertkin  *      It is called by storage miniport driver that have their own
56bf1b3cb1SVictor Perevertkin  *      StartIo routine when the transfer size is too large for the hardware.
57bf1b3cb1SVictor Perevertkin  *      We map it to our new read/write handler.
58bf1b3cb1SVictor Perevertkin  */
59bf1b3cb1SVictor Perevertkin VOID
60bf1b3cb1SVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
ClassSplitRequest(_In_ PDEVICE_OBJECT Fdo,_In_ PIRP Irp,_In_ ULONG MaximumBytes)61bf1b3cb1SVictor Perevertkin ClassSplitRequest(_In_ PDEVICE_OBJECT Fdo, _In_ PIRP Irp, _In_ ULONG MaximumBytes)
62bf1b3cb1SVictor Perevertkin {
63bf1b3cb1SVictor Perevertkin     PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
64bf1b3cb1SVictor Perevertkin     PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
65bf1b3cb1SVictor Perevertkin 
66bf1b3cb1SVictor Perevertkin     if (MaximumBytes > fdoData->HwMaxXferLen) {
67bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "ClassSplitRequest - driver requesting split to size that "
68bf1b3cb1SVictor Perevertkin                 "hardware is unable to handle!\n"));
69bf1b3cb1SVictor Perevertkin     }
70bf1b3cb1SVictor Perevertkin 
71bf1b3cb1SVictor Perevertkin     if (MaximumBytes < fdoData->HwMaxXferLen){
72bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "ClassSplitRequest - driver requesting smaller HwMaxXferLen "
73bf1b3cb1SVictor Perevertkin                  "than required"));
74bf1b3cb1SVictor Perevertkin         fdoData->HwMaxXferLen = MAX(MaximumBytes, PAGE_SIZE);
75bf1b3cb1SVictor Perevertkin     }
76bf1b3cb1SVictor Perevertkin 
77bf1b3cb1SVictor Perevertkin     ServiceTransferRequest(Fdo, Irp, FALSE);
78bf1b3cb1SVictor Perevertkin }
79bf1b3cb1SVictor Perevertkin 
80bf1b3cb1SVictor Perevertkin 
81bf1b3cb1SVictor Perevertkin /*++////////////////////////////////////////////////////////////////////////////
82bf1b3cb1SVictor Perevertkin 
83bf1b3cb1SVictor Perevertkin ClassIoCompleteAssociated()
84bf1b3cb1SVictor Perevertkin 
85bf1b3cb1SVictor Perevertkin Routine Description:
86bf1b3cb1SVictor Perevertkin 
87bf1b3cb1SVictor Perevertkin     This routine executes when the port driver has completed a request.
88bf1b3cb1SVictor Perevertkin     It looks at the SRB status in the completing SRB and if not success
89bf1b3cb1SVictor Perevertkin     it checks for valid request sense buffer information. If valid, the
90bf1b3cb1SVictor Perevertkin     info is used to update status with more precise message of type of
91bf1b3cb1SVictor Perevertkin     error. This routine deallocates the SRB.  This routine is used for
92bf1b3cb1SVictor Perevertkin     requests which were build by split request.  After it has processed
93bf1b3cb1SVictor Perevertkin     the request it decrements the Irp count in the master Irp.  If the
94bf1b3cb1SVictor Perevertkin     count goes to zero then the master Irp is completed.
95bf1b3cb1SVictor Perevertkin 
96bf1b3cb1SVictor Perevertkin Arguments:
97bf1b3cb1SVictor Perevertkin 
98bf1b3cb1SVictor Perevertkin     Fdo - Supplies the functional device object which represents the target.
99bf1b3cb1SVictor Perevertkin 
100bf1b3cb1SVictor Perevertkin     Irp - Supplies the Irp which has completed.
101bf1b3cb1SVictor Perevertkin 
102bf1b3cb1SVictor Perevertkin     Context - Supplies a pointer to the SRB.
103bf1b3cb1SVictor Perevertkin 
104bf1b3cb1SVictor Perevertkin Return Value:
105bf1b3cb1SVictor Perevertkin 
106bf1b3cb1SVictor Perevertkin     NT status
107bf1b3cb1SVictor Perevertkin 
108bf1b3cb1SVictor Perevertkin --*/
109bf1b3cb1SVictor Perevertkin NTSTATUS
110bf1b3cb1SVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
ClassIoCompleteAssociated(IN PDEVICE_OBJECT Fdo,IN PIRP Irp,IN PVOID Context)111bf1b3cb1SVictor Perevertkin ClassIoCompleteAssociated(
112bf1b3cb1SVictor Perevertkin     IN PDEVICE_OBJECT Fdo,
113bf1b3cb1SVictor Perevertkin     IN PIRP Irp,
114bf1b3cb1SVictor Perevertkin     IN PVOID Context
115bf1b3cb1SVictor Perevertkin     )
116bf1b3cb1SVictor Perevertkin {
117bf1b3cb1SVictor Perevertkin     PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
118bf1b3cb1SVictor Perevertkin 
119bf1b3cb1SVictor Perevertkin     PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
120bf1b3cb1SVictor Perevertkin     PSCSI_REQUEST_BLOCK srb = Context;
121bf1b3cb1SVictor Perevertkin 
122bf1b3cb1SVictor Perevertkin     PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
123bf1b3cb1SVictor Perevertkin     LONG irpCount;
124bf1b3cb1SVictor Perevertkin 
125bf1b3cb1SVictor Perevertkin     NTSTATUS status;
126bf1b3cb1SVictor Perevertkin     BOOLEAN retry;
127bf1b3cb1SVictor Perevertkin 
128bf1b3cb1SVictor Perevertkin     TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassIoCompleteAssociated is OBSOLETE !"));
129bf1b3cb1SVictor Perevertkin 
130bf1b3cb1SVictor Perevertkin     //
131bf1b3cb1SVictor Perevertkin     // Check SRB status for success of completing request.
132bf1b3cb1SVictor Perevertkin     //
133bf1b3cb1SVictor Perevertkin     if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
134bf1b3cb1SVictor Perevertkin 
135bf1b3cb1SVictor Perevertkin         LONGLONG retryInterval;
136bf1b3cb1SVictor Perevertkin 
137bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoCompleteAssociated: IRP %p, SRB %p", Irp, srb));
138bf1b3cb1SVictor Perevertkin 
139bf1b3cb1SVictor Perevertkin         //
140bf1b3cb1SVictor Perevertkin         // Release the queue if it is frozen.
141bf1b3cb1SVictor Perevertkin         //
142bf1b3cb1SVictor Perevertkin 
143bf1b3cb1SVictor Perevertkin         if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
144bf1b3cb1SVictor Perevertkin             ClassReleaseQueue(Fdo);
145bf1b3cb1SVictor Perevertkin         }
146bf1b3cb1SVictor Perevertkin 
147bf1b3cb1SVictor Perevertkin         retry = InterpretSenseInfoWithoutHistory(
148bf1b3cb1SVictor Perevertkin                     Fdo,
149bf1b3cb1SVictor Perevertkin                     Irp,
150bf1b3cb1SVictor Perevertkin                     srb,
151bf1b3cb1SVictor Perevertkin                     irpStack->MajorFunction,
152bf1b3cb1SVictor Perevertkin                     irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ?
153bf1b3cb1SVictor Perevertkin                         irpStack->Parameters.DeviceIoControl.IoControlCode :
154bf1b3cb1SVictor Perevertkin                         0,
155bf1b3cb1SVictor Perevertkin                     MAXIMUM_RETRIES -
156bf1b3cb1SVictor Perevertkin                         ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
157bf1b3cb1SVictor Perevertkin                     &status,
158bf1b3cb1SVictor Perevertkin                     &retryInterval);
159bf1b3cb1SVictor Perevertkin 
160bf1b3cb1SVictor Perevertkin         //
161bf1b3cb1SVictor Perevertkin         // If the status is verified required and the this request
162bf1b3cb1SVictor Perevertkin         // should bypass verify required then retry the request.
163bf1b3cb1SVictor Perevertkin         //
164bf1b3cb1SVictor Perevertkin 
165bf1b3cb1SVictor Perevertkin         if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
166bf1b3cb1SVictor Perevertkin             status == STATUS_VERIFY_REQUIRED) {
167bf1b3cb1SVictor Perevertkin 
168bf1b3cb1SVictor Perevertkin             status = STATUS_IO_DEVICE_ERROR;
169bf1b3cb1SVictor Perevertkin             retry = TRUE;
170bf1b3cb1SVictor Perevertkin         }
171bf1b3cb1SVictor Perevertkin 
172bf1b3cb1SVictor Perevertkin #ifndef __REACTOS__
173bf1b3cb1SVictor Perevertkin #pragma warning(suppress:4213) // okay to cast Arg4 as a ulong for this use case
174bf1b3cb1SVictor Perevertkin         if (retry && ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--) {
175bf1b3cb1SVictor Perevertkin #else
176bf1b3cb1SVictor Perevertkin         if (retry && (*(ULONG *)&irpStack->Parameters.Others.Argument4)--) {
177bf1b3cb1SVictor Perevertkin #endif
178bf1b3cb1SVictor Perevertkin 
179bf1b3cb1SVictor Perevertkin             //
180bf1b3cb1SVictor Perevertkin             // Retry request. If the class driver has supplied a StartIo,
181bf1b3cb1SVictor Perevertkin             // call it directly for retries.
182bf1b3cb1SVictor Perevertkin             //
183bf1b3cb1SVictor Perevertkin 
184bf1b3cb1SVictor Perevertkin             TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,  "Retry request %p\n", Irp));
185bf1b3cb1SVictor Perevertkin 
186bf1b3cb1SVictor Perevertkin             if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
187bf1b3cb1SVictor Perevertkin                 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
188bf1b3cb1SVictor Perevertkin             }
189bf1b3cb1SVictor Perevertkin 
190bf1b3cb1SVictor Perevertkin             RetryRequest(Fdo, Irp, srb, TRUE, retryInterval);
191bf1b3cb1SVictor Perevertkin 
192bf1b3cb1SVictor Perevertkin             return STATUS_MORE_PROCESSING_REQUIRED;
193bf1b3cb1SVictor Perevertkin         }
194bf1b3cb1SVictor Perevertkin 
195bf1b3cb1SVictor Perevertkin     } else {
196bf1b3cb1SVictor Perevertkin 
197bf1b3cb1SVictor Perevertkin         //
198bf1b3cb1SVictor Perevertkin         // Set status for successful request.
199bf1b3cb1SVictor Perevertkin         //
200bf1b3cb1SVictor Perevertkin 
201bf1b3cb1SVictor Perevertkin         status = STATUS_SUCCESS;
202bf1b3cb1SVictor Perevertkin 
203bf1b3cb1SVictor Perevertkin     } // end if (SRB_STATUS(srb->SrbStatus) ...
204bf1b3cb1SVictor Perevertkin 
205bf1b3cb1SVictor Perevertkin     //
206bf1b3cb1SVictor Perevertkin     // Return SRB to list.
207bf1b3cb1SVictor Perevertkin     //
208bf1b3cb1SVictor Perevertkin 
209bf1b3cb1SVictor Perevertkin     if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
210bf1b3cb1SVictor Perevertkin         FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
211bf1b3cb1SVictor Perevertkin     }
212bf1b3cb1SVictor Perevertkin 
213bf1b3cb1SVictor Perevertkin     ClassFreeOrReuseSrb(fdoExtension, srb);
214bf1b3cb1SVictor Perevertkin 
215bf1b3cb1SVictor Perevertkin     //
216bf1b3cb1SVictor Perevertkin     // Set status in completing IRP.
217bf1b3cb1SVictor Perevertkin     //
218bf1b3cb1SVictor Perevertkin 
219bf1b3cb1SVictor Perevertkin     Irp->IoStatus.Status = status;
220bf1b3cb1SVictor Perevertkin 
221bf1b3cb1SVictor Perevertkin     TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,  "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp));
222bf1b3cb1SVictor Perevertkin 
223bf1b3cb1SVictor Perevertkin     //
224bf1b3cb1SVictor Perevertkin     // Get next stack location. This original request is unused
225bf1b3cb1SVictor Perevertkin     // except to keep track of the completing partial IRPs so the
226bf1b3cb1SVictor Perevertkin     // stack location is valid.
227bf1b3cb1SVictor Perevertkin     //
228bf1b3cb1SVictor Perevertkin 
229bf1b3cb1SVictor Perevertkin     irpStack = IoGetNextIrpStackLocation(originalIrp);
230bf1b3cb1SVictor Perevertkin 
231bf1b3cb1SVictor Perevertkin     //
232bf1b3cb1SVictor Perevertkin     // Update status only if error so that if any partial transfer
233bf1b3cb1SVictor Perevertkin     // completes with error, then the original IRP will return with
234bf1b3cb1SVictor Perevertkin     // error. If any of the asynchronous partial transfer IRPs fail,
235bf1b3cb1SVictor Perevertkin     // with an error then the original IRP will return 0 bytes transfered.
236bf1b3cb1SVictor Perevertkin     // This is an optimization for successful transfers.
237bf1b3cb1SVictor Perevertkin     //
238bf1b3cb1SVictor Perevertkin 
239bf1b3cb1SVictor Perevertkin     if (!NT_SUCCESS(status)) {
240bf1b3cb1SVictor Perevertkin 
241bf1b3cb1SVictor Perevertkin         originalIrp->IoStatus.Status = status;
242bf1b3cb1SVictor Perevertkin         originalIrp->IoStatus.Information = 0;
243bf1b3cb1SVictor Perevertkin 
244bf1b3cb1SVictor Perevertkin         //
245bf1b3cb1SVictor Perevertkin         // Set the hard error if necessary.
246bf1b3cb1SVictor Perevertkin         //
247bf1b3cb1SVictor Perevertkin 
248bf1b3cb1SVictor Perevertkin         if (IoIsErrorUserInduced(status) &&
249bf1b3cb1SVictor Perevertkin             (originalIrp->Tail.Overlay.Thread != NULL)) {
250bf1b3cb1SVictor Perevertkin 
251bf1b3cb1SVictor Perevertkin             //
252bf1b3cb1SVictor Perevertkin             // Store DeviceObject for filesystem.
253bf1b3cb1SVictor Perevertkin             //
254bf1b3cb1SVictor Perevertkin 
255bf1b3cb1SVictor Perevertkin             IoSetHardErrorOrVerifyDevice(originalIrp, Fdo);
256bf1b3cb1SVictor Perevertkin         }
257bf1b3cb1SVictor Perevertkin     }
258bf1b3cb1SVictor Perevertkin 
259bf1b3cb1SVictor Perevertkin     //
260bf1b3cb1SVictor Perevertkin     // Decrement and get the count of remaining IRPs.
261bf1b3cb1SVictor Perevertkin     //
262bf1b3cb1SVictor Perevertkin 
263bf1b3cb1SVictor Perevertkin     irpCount = InterlockedDecrement(
264bf1b3cb1SVictor Perevertkin                     (PLONG)&irpStack->Parameters.Others.Argument1);
265bf1b3cb1SVictor Perevertkin 
266bf1b3cb1SVictor Perevertkin     TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,  "ClassIoCompleteAssociated: Partial IRPs left %d\n",
267bf1b3cb1SVictor Perevertkin                 irpCount));
268bf1b3cb1SVictor Perevertkin 
269bf1b3cb1SVictor Perevertkin     //
270bf1b3cb1SVictor Perevertkin     // Ensure that the irpCount doesn't go negative.  This was happening once
271bf1b3cb1SVictor Perevertkin     // because classpnp would get confused if it ran out of resources when
272bf1b3cb1SVictor Perevertkin     // splitting the request.
273bf1b3cb1SVictor Perevertkin     //
274bf1b3cb1SVictor Perevertkin 
275bf1b3cb1SVictor Perevertkin     NT_ASSERT(irpCount >= 0);
276bf1b3cb1SVictor Perevertkin 
277bf1b3cb1SVictor Perevertkin     if (irpCount == 0) {
278bf1b3cb1SVictor Perevertkin 
279bf1b3cb1SVictor Perevertkin         //
280bf1b3cb1SVictor Perevertkin         // All partial IRPs have completed.
281bf1b3cb1SVictor Perevertkin         //
282bf1b3cb1SVictor Perevertkin 
283bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
284bf1b3cb1SVictor Perevertkin                  "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
285bf1b3cb1SVictor Perevertkin                  originalIrp));
286bf1b3cb1SVictor Perevertkin 
287bf1b3cb1SVictor Perevertkin         if (fdoExtension->CommonExtension.DriverExtension->InitData.ClassStartIo) {
288bf1b3cb1SVictor Perevertkin 
289bf1b3cb1SVictor Perevertkin             //
290bf1b3cb1SVictor Perevertkin             // Acquire a separate copy of the remove lock so the debugging code
291bf1b3cb1SVictor Perevertkin             // works okay and we don't have to hold up the completion of this
292bf1b3cb1SVictor Perevertkin             // irp until after we start the next packet(s).
293bf1b3cb1SVictor Perevertkin             //
294bf1b3cb1SVictor Perevertkin 
295bf1b3cb1SVictor Perevertkin             KIRQL oldIrql;
296bf1b3cb1SVictor Perevertkin             UCHAR uniqueAddress = 0;
297bf1b3cb1SVictor Perevertkin             ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddress);
298bf1b3cb1SVictor Perevertkin             ClassReleaseRemoveLock(Fdo, originalIrp);
299bf1b3cb1SVictor Perevertkin             ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
300bf1b3cb1SVictor Perevertkin 
301bf1b3cb1SVictor Perevertkin             KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
302bf1b3cb1SVictor Perevertkin             IoStartNextPacket(Fdo, TRUE); // yes, some IO is now cancellable
303bf1b3cb1SVictor Perevertkin             KeLowerIrql(oldIrql);
304bf1b3cb1SVictor Perevertkin 
305bf1b3cb1SVictor Perevertkin             ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddress);
306bf1b3cb1SVictor Perevertkin 
307bf1b3cb1SVictor Perevertkin         } else {
308bf1b3cb1SVictor Perevertkin 
309bf1b3cb1SVictor Perevertkin             //
310bf1b3cb1SVictor Perevertkin             // just complete this request
311bf1b3cb1SVictor Perevertkin             //
312bf1b3cb1SVictor Perevertkin 
313bf1b3cb1SVictor Perevertkin             ClassReleaseRemoveLock(Fdo, originalIrp);
314bf1b3cb1SVictor Perevertkin             ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
315bf1b3cb1SVictor Perevertkin 
316bf1b3cb1SVictor Perevertkin         }
317bf1b3cb1SVictor Perevertkin 
318bf1b3cb1SVictor Perevertkin     }
319bf1b3cb1SVictor Perevertkin 
320bf1b3cb1SVictor Perevertkin     //
321bf1b3cb1SVictor Perevertkin     // Deallocate IRP and indicate the I/O system should not attempt any more
322bf1b3cb1SVictor Perevertkin     // processing.
323bf1b3cb1SVictor Perevertkin     //
324bf1b3cb1SVictor Perevertkin 
325bf1b3cb1SVictor Perevertkin     IoFreeIrp(Irp);
326bf1b3cb1SVictor Perevertkin     return STATUS_MORE_PROCESSING_REQUIRED;
327bf1b3cb1SVictor Perevertkin 
328bf1b3cb1SVictor Perevertkin } // end ClassIoCompleteAssociated()
329bf1b3cb1SVictor Perevertkin 
330bf1b3cb1SVictor Perevertkin 
331bf1b3cb1SVictor Perevertkin /*++////////////////////////////////////////////////////////////////////////////
332bf1b3cb1SVictor Perevertkin 
333bf1b3cb1SVictor Perevertkin RetryRequest()
334bf1b3cb1SVictor Perevertkin 
335bf1b3cb1SVictor Perevertkin Routine Description:
336bf1b3cb1SVictor Perevertkin 
337bf1b3cb1SVictor Perevertkin     This is a wrapper around the delayed retry DPC routine, RetryRequestDPC.
338bf1b3cb1SVictor Perevertkin     This reinitalizes the necessary fields, queues the request, and sets
339bf1b3cb1SVictor Perevertkin     a timer to call the DPC if someone hasn't already done so.
340bf1b3cb1SVictor Perevertkin 
341bf1b3cb1SVictor Perevertkin Arguments:
342bf1b3cb1SVictor Perevertkin 
343bf1b3cb1SVictor Perevertkin     DeviceObject - Supplies the device object associated with this request.
344bf1b3cb1SVictor Perevertkin 
345bf1b3cb1SVictor Perevertkin     Irp - Supplies the request to be retried.
346bf1b3cb1SVictor Perevertkin 
347bf1b3cb1SVictor Perevertkin     Srb - Supplies a Pointer to the SCSI request block to be retied.
348bf1b3cb1SVictor Perevertkin 
349bf1b3cb1SVictor Perevertkin     Assocaiated - Indicates this is an assocatied Irp created by split request.
350bf1b3cb1SVictor Perevertkin 
351bf1b3cb1SVictor Perevertkin     TimeDelta100ns - How long, in 100ns units, before retrying the request.
352bf1b3cb1SVictor Perevertkin 
353bf1b3cb1SVictor Perevertkin Return Value:
354bf1b3cb1SVictor Perevertkin 
355bf1b3cb1SVictor Perevertkin     None
356bf1b3cb1SVictor Perevertkin 
357bf1b3cb1SVictor Perevertkin --*/
358bf1b3cb1SVictor Perevertkin VOID
359bf1b3cb1SVictor Perevertkin RetryRequest(
360bf1b3cb1SVictor Perevertkin     PDEVICE_OBJECT DeviceObject,
361bf1b3cb1SVictor Perevertkin     PIRP Irp,
362bf1b3cb1SVictor Perevertkin     PSCSI_REQUEST_BLOCK Srb,
363bf1b3cb1SVictor Perevertkin     BOOLEAN Associated,
364bf1b3cb1SVictor Perevertkin     LONGLONG TimeDelta100ns
365bf1b3cb1SVictor Perevertkin     )
366bf1b3cb1SVictor Perevertkin {
367bf1b3cb1SVictor Perevertkin     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
368bf1b3cb1SVictor Perevertkin     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
369bf1b3cb1SVictor Perevertkin     ULONG transferByteCount;
370bf1b3cb1SVictor Perevertkin     ULONG dataTransferLength;
371bf1b3cb1SVictor Perevertkin     PSTORAGE_REQUEST_BLOCK_HEADER srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)Srb;
372bf1b3cb1SVictor Perevertkin 
373bf1b3cb1SVictor Perevertkin     // This function is obsolete but is still used by some of our class drivers.
374bf1b3cb1SVictor Perevertkin     // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "RetryRequest is OBSOLETE !"));
375bf1b3cb1SVictor Perevertkin 
376bf1b3cb1SVictor Perevertkin     //
377bf1b3cb1SVictor Perevertkin     // Determine the transfer count of the request.  If this is a read or a
378bf1b3cb1SVictor Perevertkin     // write then the transfer count is in the Irp stack.  Otherwise assume
379bf1b3cb1SVictor Perevertkin     // the MDL contains the correct length.  If there is no MDL then the
380bf1b3cb1SVictor Perevertkin     // transfer length must be zero.
381bf1b3cb1SVictor Perevertkin     //
382bf1b3cb1SVictor Perevertkin 
383bf1b3cb1SVictor Perevertkin     dataTransferLength = SrbGetDataTransferLength(srbHeader);
384bf1b3cb1SVictor Perevertkin     if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
385bf1b3cb1SVictor Perevertkin         currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
386bf1b3cb1SVictor Perevertkin 
387bf1b3cb1SVictor Perevertkin         _Analysis_assume_(currentIrpStack->Parameters.Read.Length <= dataTransferLength);
388bf1b3cb1SVictor Perevertkin         transferByteCount = currentIrpStack->Parameters.Read.Length;
389bf1b3cb1SVictor Perevertkin 
390bf1b3cb1SVictor Perevertkin     } else if (Irp->MdlAddress != NULL) {
391bf1b3cb1SVictor Perevertkin 
392bf1b3cb1SVictor Perevertkin         //
393bf1b3cb1SVictor Perevertkin         // Note this assumes that only read and write requests are spilt and
394bf1b3cb1SVictor Perevertkin         // other request do not need to be.  If the data buffer address in
395bf1b3cb1SVictor Perevertkin         // the MDL and the SRB don't match then transfer length is most
396bf1b3cb1SVictor Perevertkin         // likely incorrect.
397bf1b3cb1SVictor Perevertkin         //
398bf1b3cb1SVictor Perevertkin 
399bf1b3cb1SVictor Perevertkin         NT_ASSERT(SrbGetDataBuffer(srbHeader) == MmGetMdlVirtualAddress(Irp->MdlAddress));
400bf1b3cb1SVictor Perevertkin     _Analysis_assume_(Irp->MdlAddress->ByteCount <= dataTransferLength);
401bf1b3cb1SVictor Perevertkin         transferByteCount = Irp->MdlAddress->ByteCount;
402bf1b3cb1SVictor Perevertkin 
403bf1b3cb1SVictor Perevertkin     } else {
404bf1b3cb1SVictor Perevertkin 
405bf1b3cb1SVictor Perevertkin         transferByteCount = 0;
406bf1b3cb1SVictor Perevertkin     }
407bf1b3cb1SVictor Perevertkin 
408bf1b3cb1SVictor Perevertkin     //
409bf1b3cb1SVictor Perevertkin     // this is a safety net.  this should not normally be hit, since we are
410bf1b3cb1SVictor Perevertkin     // not guaranteed to be an fdoExtension
411bf1b3cb1SVictor Perevertkin     //
412bf1b3cb1SVictor Perevertkin 
413bf1b3cb1SVictor Perevertkin     NT_ASSERT(!TEST_FLAG(SrbGetSrbFlags(srbHeader), SRB_FLAGS_FREE_SENSE_BUFFER));
414bf1b3cb1SVictor Perevertkin 
415bf1b3cb1SVictor Perevertkin     //
416bf1b3cb1SVictor Perevertkin     // Reset byte count of transfer in SRB Extension.
417bf1b3cb1SVictor Perevertkin     //
418bf1b3cb1SVictor Perevertkin 
419bf1b3cb1SVictor Perevertkin     SrbSetDataTransferLength(srbHeader, transferByteCount);
420bf1b3cb1SVictor Perevertkin 
421bf1b3cb1SVictor Perevertkin     //
422bf1b3cb1SVictor Perevertkin     // Zero SRB statuses.
423bf1b3cb1SVictor Perevertkin     //
424bf1b3cb1SVictor Perevertkin 
425bf1b3cb1SVictor Perevertkin     srbHeader->SrbStatus = 0;
426bf1b3cb1SVictor Perevertkin     SrbSetScsiStatus(srbHeader, 0);
427bf1b3cb1SVictor Perevertkin 
428bf1b3cb1SVictor Perevertkin     //
429bf1b3cb1SVictor Perevertkin     // If this is the last retry, then disable all the special flags.
430bf1b3cb1SVictor Perevertkin     //
431bf1b3cb1SVictor Perevertkin 
432bf1b3cb1SVictor Perevertkin     if ( 0 == (ULONG)(ULONG_PTR)currentIrpStack->Parameters.Others.Argument4 ) {
433bf1b3cb1SVictor Perevertkin         //
434bf1b3cb1SVictor Perevertkin         // Set the no disconnect flag, disable synchronous data transfers and
435bf1b3cb1SVictor Perevertkin         // disable tagged queuing. This fixes some errors.
436bf1b3cb1SVictor Perevertkin         // NOTE: Cannot clear these flags, just add to them
437bf1b3cb1SVictor Perevertkin         //
438bf1b3cb1SVictor Perevertkin 
439bf1b3cb1SVictor Perevertkin         SrbSetSrbFlags(srbHeader,
440bf1b3cb1SVictor Perevertkin                           SRB_FLAGS_DISABLE_DISCONNECT | SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
441bf1b3cb1SVictor Perevertkin         SrbClearSrbFlags(srbHeader, SRB_FLAGS_QUEUE_ACTION_ENABLE);
442bf1b3cb1SVictor Perevertkin 
443bf1b3cb1SVictor Perevertkin         SrbSetQueueTag(srbHeader, SP_UNTAGGED);
444bf1b3cb1SVictor Perevertkin     }
445bf1b3cb1SVictor Perevertkin 
446bf1b3cb1SVictor Perevertkin 
447bf1b3cb1SVictor Perevertkin     //
448bf1b3cb1SVictor Perevertkin     // Set up major SCSI function.
449bf1b3cb1SVictor Perevertkin     //
450bf1b3cb1SVictor Perevertkin 
451bf1b3cb1SVictor Perevertkin     nextIrpStack->MajorFunction = IRP_MJ_SCSI;
452bf1b3cb1SVictor Perevertkin 
453bf1b3cb1SVictor Perevertkin     //
454bf1b3cb1SVictor Perevertkin     // Save SRB address in next stack for port driver.
455bf1b3cb1SVictor Perevertkin     //
456bf1b3cb1SVictor Perevertkin 
457bf1b3cb1SVictor Perevertkin     nextIrpStack->Parameters.Scsi.Srb = Srb;
458bf1b3cb1SVictor Perevertkin 
459bf1b3cb1SVictor Perevertkin     if (Associated){
460bf1b3cb1SVictor Perevertkin         IoSetCompletionRoutine(Irp, ClassIoCompleteAssociated, Srb, TRUE, TRUE, TRUE);
461bf1b3cb1SVictor Perevertkin     }
462bf1b3cb1SVictor Perevertkin     else {
463bf1b3cb1SVictor Perevertkin         IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);
464bf1b3cb1SVictor Perevertkin     }
465bf1b3cb1SVictor Perevertkin 
466bf1b3cb1SVictor Perevertkin     ClassRetryRequest(DeviceObject, Irp, TimeDelta100ns);
467bf1b3cb1SVictor Perevertkin     return;
468bf1b3cb1SVictor Perevertkin } // end RetryRequest()
469bf1b3cb1SVictor Perevertkin 
470*34593d93SVictor Perevertkin 
471bf1b3cb1SVictor Perevertkin /*++
472bf1b3cb1SVictor Perevertkin 
473bf1b3cb1SVictor Perevertkin ClassBuildRequest()
474bf1b3cb1SVictor Perevertkin 
475bf1b3cb1SVictor Perevertkin Routine Description:
476bf1b3cb1SVictor Perevertkin 
477bf1b3cb1SVictor Perevertkin     This routine allocates an SRB for the specified request then calls
478bf1b3cb1SVictor Perevertkin     ClasspBuildRequestEx to create a SCSI operation to read or write the device.
479bf1b3cb1SVictor Perevertkin 
480bf1b3cb1SVictor Perevertkin     If no SRB is available then the request will be queued to be issued later
481bf1b3cb1SVictor Perevertkin     when requests are available.  Drivers which do not want the queueing
482bf1b3cb1SVictor Perevertkin     behavior should allocate the SRB themselves and call ClasspBuildRequestEx
483bf1b3cb1SVictor Perevertkin     to issue it.
484bf1b3cb1SVictor Perevertkin 
485bf1b3cb1SVictor Perevertkin Arguments:
486bf1b3cb1SVictor Perevertkin 
487bf1b3cb1SVictor Perevertkin     Fdo - Supplies the functional device object associated with this request.
488bf1b3cb1SVictor Perevertkin 
489bf1b3cb1SVictor Perevertkin     Irp - Supplies the request to be retried.
490bf1b3cb1SVictor Perevertkin 
491bf1b3cb1SVictor Perevertkin Note:
492bf1b3cb1SVictor Perevertkin 
493bf1b3cb1SVictor Perevertkin     If the IRP is for a disk transfer, the byteoffset field
494bf1b3cb1SVictor Perevertkin     will already have been adjusted to make it relative to
495bf1b3cb1SVictor Perevertkin     the beginning of the disk.
496bf1b3cb1SVictor Perevertkin 
497bf1b3cb1SVictor Perevertkin 
498bf1b3cb1SVictor Perevertkin Return Value:
499bf1b3cb1SVictor Perevertkin 
500bf1b3cb1SVictor Perevertkin     NT Status
501bf1b3cb1SVictor Perevertkin 
502bf1b3cb1SVictor Perevertkin --*/
503bf1b3cb1SVictor Perevertkin NTSTATUS
504bf1b3cb1SVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
505bf1b3cb1SVictor Perevertkin ClassBuildRequest(
506bf1b3cb1SVictor Perevertkin     _In_ PDEVICE_OBJECT Fdo,
507bf1b3cb1SVictor Perevertkin     _In_ PIRP Irp
508bf1b3cb1SVictor Perevertkin     )
509bf1b3cb1SVictor Perevertkin {
510bf1b3cb1SVictor Perevertkin     PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
511bf1b3cb1SVictor Perevertkin 
512bf1b3cb1SVictor Perevertkin     PSCSI_REQUEST_BLOCK srb;
513bf1b3cb1SVictor Perevertkin 
514bf1b3cb1SVictor Perevertkin     // This function is obsolete, but still called by CDROM.SYS .
515bf1b3cb1SVictor Perevertkin     // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassBuildRequest is OBSOLETE !"));
516bf1b3cb1SVictor Perevertkin 
517bf1b3cb1SVictor Perevertkin     //
518bf1b3cb1SVictor Perevertkin     // Allocate an Srb.
519bf1b3cb1SVictor Perevertkin     //
520bf1b3cb1SVictor Perevertkin 
521bf1b3cb1SVictor Perevertkin     srb = ClasspAllocateSrb(fdoExtension);
522bf1b3cb1SVictor Perevertkin 
523bf1b3cb1SVictor Perevertkin     if (srb == NULL) {
524bf1b3cb1SVictor Perevertkin         return STATUS_INSUFFICIENT_RESOURCES;
525bf1b3cb1SVictor Perevertkin     }
526bf1b3cb1SVictor Perevertkin 
527bf1b3cb1SVictor Perevertkin     ClasspBuildRequestEx(fdoExtension, Irp, srb);
528bf1b3cb1SVictor Perevertkin     return STATUS_SUCCESS;
529bf1b3cb1SVictor Perevertkin 
530bf1b3cb1SVictor Perevertkin } // end ClassBuildRequest()
531bf1b3cb1SVictor Perevertkin 
532bf1b3cb1SVictor Perevertkin 
533bf1b3cb1SVictor Perevertkin VOID
534bf1b3cb1SVictor Perevertkin #ifdef _MSC_VER
535bf1b3cb1SVictor Perevertkin #pragma prefast(suppress:28194) // Srb may not be aliased if it is NULL
536bf1b3cb1SVictor Perevertkin #endif
537bf1b3cb1SVictor Perevertkin ClasspBuildRequestEx(
538bf1b3cb1SVictor Perevertkin     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
539bf1b3cb1SVictor Perevertkin     _In_ PIRP Irp,
540bf1b3cb1SVictor Perevertkin     _In_ __drv_aliasesMem PSCSI_REQUEST_BLOCK Srb
541bf1b3cb1SVictor Perevertkin     )
542bf1b3cb1SVictor Perevertkin 
543bf1b3cb1SVictor Perevertkin /*++
544bf1b3cb1SVictor Perevertkin 
545bf1b3cb1SVictor Perevertkin ClasspBuildRequestEx()
546bf1b3cb1SVictor Perevertkin 
547bf1b3cb1SVictor Perevertkin Routine Description:
548bf1b3cb1SVictor Perevertkin 
549bf1b3cb1SVictor Perevertkin     This routine allocates and builds an Srb for a read or write request.
550bf1b3cb1SVictor Perevertkin     The block address and length are supplied by the Irp. The retry count
551bf1b3cb1SVictor Perevertkin     is stored in the current stack for use by ClassIoComplete which
552bf1b3cb1SVictor Perevertkin     processes these requests when they complete.  The Irp is ready to be
553bf1b3cb1SVictor Perevertkin     passed to the port driver when this routine returns.
554bf1b3cb1SVictor Perevertkin 
555bf1b3cb1SVictor Perevertkin Arguments:
556bf1b3cb1SVictor Perevertkin 
557bf1b3cb1SVictor Perevertkin     FdoExtension - Supplies the device extension associated with this request.
558bf1b3cb1SVictor Perevertkin 
559bf1b3cb1SVictor Perevertkin     Irp - Supplies the request to be issued.
560bf1b3cb1SVictor Perevertkin 
561bf1b3cb1SVictor Perevertkin     Srb - Supplies an SRB to be used for the request.
562bf1b3cb1SVictor Perevertkin 
563bf1b3cb1SVictor Perevertkin Note:
564bf1b3cb1SVictor Perevertkin 
565bf1b3cb1SVictor Perevertkin     If the IRP is for a disk transfer, the byteoffset field
566bf1b3cb1SVictor Perevertkin     will already have been adjusted to make it relative to
567bf1b3cb1SVictor Perevertkin     the beginning of the disk.
568bf1b3cb1SVictor Perevertkin 
569bf1b3cb1SVictor Perevertkin 
570bf1b3cb1SVictor Perevertkin Return Value:
571bf1b3cb1SVictor Perevertkin 
572bf1b3cb1SVictor Perevertkin     NT Status
573bf1b3cb1SVictor Perevertkin 
574bf1b3cb1SVictor Perevertkin --*/
575bf1b3cb1SVictor Perevertkin {
576bf1b3cb1SVictor Perevertkin     PIO_STACK_LOCATION  currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
577bf1b3cb1SVictor Perevertkin     PIO_STACK_LOCATION  nextIrpStack = IoGetNextIrpStackLocation(Irp);
578bf1b3cb1SVictor Perevertkin 
579bf1b3cb1SVictor Perevertkin     LARGE_INTEGER       startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
580bf1b3cb1SVictor Perevertkin 
581bf1b3cb1SVictor Perevertkin     PCDB                cdb;
582bf1b3cb1SVictor Perevertkin     ULONG               logicalBlockAddress;
583bf1b3cb1SVictor Perevertkin     USHORT              transferBlocks;
584bf1b3cb1SVictor Perevertkin     NTSTATUS            status;
585bf1b3cb1SVictor Perevertkin     PSTORAGE_REQUEST_BLOCK_HEADER srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)Srb;
586bf1b3cb1SVictor Perevertkin 
587bf1b3cb1SVictor Perevertkin     // This function is obsolete, but still called by CDROM.SYS .
588bf1b3cb1SVictor Perevertkin     // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClasspBuildRequestEx is OBSOLETE !"));
589bf1b3cb1SVictor Perevertkin 
590bf1b3cb1SVictor Perevertkin     if (Srb == NULL) {
591bf1b3cb1SVictor Perevertkin         NT_ASSERT(FALSE);
592bf1b3cb1SVictor Perevertkin         return;
593bf1b3cb1SVictor Perevertkin     }
594bf1b3cb1SVictor Perevertkin 
595bf1b3cb1SVictor Perevertkin     //
596bf1b3cb1SVictor Perevertkin     // Calculate relative sector address.
597bf1b3cb1SVictor Perevertkin     //
598bf1b3cb1SVictor Perevertkin 
599bf1b3cb1SVictor Perevertkin     logicalBlockAddress =
600bf1b3cb1SVictor Perevertkin         (ULONG)(Int64ShrlMod32(startingOffset.QuadPart,
601bf1b3cb1SVictor Perevertkin                                FdoExtension->SectorShift));
602bf1b3cb1SVictor Perevertkin 
603bf1b3cb1SVictor Perevertkin     //
604bf1b3cb1SVictor Perevertkin     // Prepare the SRB.
605bf1b3cb1SVictor Perevertkin     // NOTE - for extended SRB, size used is based on allocation in ClasspAllocateSrb.
606bf1b3cb1SVictor Perevertkin     //
607bf1b3cb1SVictor Perevertkin 
608bf1b3cb1SVictor Perevertkin     if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
609bf1b3cb1SVictor Perevertkin         status = InitializeStorageRequestBlock((PSTORAGE_REQUEST_BLOCK)Srb,
610bf1b3cb1SVictor Perevertkin                                                STORAGE_ADDRESS_TYPE_BTL8,
611bf1b3cb1SVictor Perevertkin                                                CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE,
612bf1b3cb1SVictor Perevertkin                                                1,
613bf1b3cb1SVictor Perevertkin                                                SrbExDataTypeScsiCdb16);
614bf1b3cb1SVictor Perevertkin         if (!NT_SUCCESS(status)) {
615bf1b3cb1SVictor Perevertkin             NT_ASSERT(FALSE);
616bf1b3cb1SVictor Perevertkin             return;
617bf1b3cb1SVictor Perevertkin         }
618bf1b3cb1SVictor Perevertkin 
619bf1b3cb1SVictor Perevertkin         ((PSTORAGE_REQUEST_BLOCK)Srb)->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
620bf1b3cb1SVictor Perevertkin     } else {
621bf1b3cb1SVictor Perevertkin         RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
622bf1b3cb1SVictor Perevertkin 
623bf1b3cb1SVictor Perevertkin         //
624bf1b3cb1SVictor Perevertkin         // Write length to SRB.
625bf1b3cb1SVictor Perevertkin         //
626bf1b3cb1SVictor Perevertkin 
627bf1b3cb1SVictor Perevertkin         Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
628bf1b3cb1SVictor Perevertkin 
629bf1b3cb1SVictor Perevertkin         Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
630bf1b3cb1SVictor Perevertkin     }
631bf1b3cb1SVictor Perevertkin 
632bf1b3cb1SVictor Perevertkin 
633bf1b3cb1SVictor Perevertkin     //
634bf1b3cb1SVictor Perevertkin     // Set up IRP Address.
635bf1b3cb1SVictor Perevertkin     //
636bf1b3cb1SVictor Perevertkin 
637bf1b3cb1SVictor Perevertkin     SrbSetOriginalRequest(srbHeader, Irp);
638bf1b3cb1SVictor Perevertkin 
639bf1b3cb1SVictor Perevertkin     //
640bf1b3cb1SVictor Perevertkin     // Set up data buffer
641bf1b3cb1SVictor Perevertkin     //
642bf1b3cb1SVictor Perevertkin 
643bf1b3cb1SVictor Perevertkin     SrbSetDataBuffer(srbHeader,
644bf1b3cb1SVictor Perevertkin                            MmGetMdlVirtualAddress(Irp->MdlAddress));
645bf1b3cb1SVictor Perevertkin 
646bf1b3cb1SVictor Perevertkin     //
647bf1b3cb1SVictor Perevertkin     // Save byte count of transfer in SRB Extension.
648bf1b3cb1SVictor Perevertkin     //
649bf1b3cb1SVictor Perevertkin 
650bf1b3cb1SVictor Perevertkin     SrbSetDataTransferLength(srbHeader,
651bf1b3cb1SVictor Perevertkin                                    currentIrpStack->Parameters.Read.Length);
652bf1b3cb1SVictor Perevertkin 
653bf1b3cb1SVictor Perevertkin     //
654bf1b3cb1SVictor Perevertkin     // Initialize the queue actions field.
655bf1b3cb1SVictor Perevertkin     //
656bf1b3cb1SVictor Perevertkin 
657bf1b3cb1SVictor Perevertkin     SrbSetRequestAttribute(srbHeader, SRB_SIMPLE_TAG_REQUEST);
658bf1b3cb1SVictor Perevertkin 
659bf1b3cb1SVictor Perevertkin     //
660bf1b3cb1SVictor Perevertkin     // Queue sort key is Relative Block Address.
661bf1b3cb1SVictor Perevertkin     //
662bf1b3cb1SVictor Perevertkin 
663bf1b3cb1SVictor Perevertkin     SrbSetQueueSortKey(srbHeader, logicalBlockAddress);
664bf1b3cb1SVictor Perevertkin 
665bf1b3cb1SVictor Perevertkin     //
666bf1b3cb1SVictor Perevertkin     // Indicate auto request sense by specifying buffer and size.
667bf1b3cb1SVictor Perevertkin     //
668bf1b3cb1SVictor Perevertkin 
669bf1b3cb1SVictor Perevertkin     SrbSetSenseInfoBuffer(srbHeader, FdoExtension->SenseData);
670bf1b3cb1SVictor Perevertkin     SrbSetSenseInfoBufferLength(srbHeader, GET_FDO_EXTENSON_SENSE_DATA_LENGTH(FdoExtension));
671bf1b3cb1SVictor Perevertkin 
672bf1b3cb1SVictor Perevertkin     //
673bf1b3cb1SVictor Perevertkin     // Set timeout value of one unit per 64k bytes of data.
674bf1b3cb1SVictor Perevertkin     //
675bf1b3cb1SVictor Perevertkin 
676bf1b3cb1SVictor Perevertkin     SrbSetTimeOutValue(srbHeader,
677bf1b3cb1SVictor Perevertkin                              ((SrbGetDataTransferLength(srbHeader) + 0xFFFF) >> 16) *
678bf1b3cb1SVictor Perevertkin                               FdoExtension->TimeOutValue);
679bf1b3cb1SVictor Perevertkin 
680bf1b3cb1SVictor Perevertkin     //
681bf1b3cb1SVictor Perevertkin     // Indicate that 10-byte CDB's will be used.
682bf1b3cb1SVictor Perevertkin     //
683bf1b3cb1SVictor Perevertkin 
684bf1b3cb1SVictor Perevertkin     SrbSetCdbLength(srbHeader, 10);
685bf1b3cb1SVictor Perevertkin 
686bf1b3cb1SVictor Perevertkin     //
687bf1b3cb1SVictor Perevertkin     // Fill in CDB fields.
688bf1b3cb1SVictor Perevertkin     //
689bf1b3cb1SVictor Perevertkin 
690bf1b3cb1SVictor Perevertkin     cdb = SrbGetCdb(srbHeader);
691bf1b3cb1SVictor Perevertkin     NT_ASSERT(cdb != NULL);
692bf1b3cb1SVictor Perevertkin 
693bf1b3cb1SVictor Perevertkin     transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >>
694bf1b3cb1SVictor Perevertkin                               FdoExtension->SectorShift);
695bf1b3cb1SVictor Perevertkin 
696bf1b3cb1SVictor Perevertkin     //
697bf1b3cb1SVictor Perevertkin     // Move little endian values into CDB in big endian format.
698bf1b3cb1SVictor Perevertkin     //
699bf1b3cb1SVictor Perevertkin 
700bf1b3cb1SVictor Perevertkin     cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
701bf1b3cb1SVictor Perevertkin     cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
702bf1b3cb1SVictor Perevertkin     cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
703bf1b3cb1SVictor Perevertkin     cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
704bf1b3cb1SVictor Perevertkin 
705bf1b3cb1SVictor Perevertkin     cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
706bf1b3cb1SVictor Perevertkin     cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;
707bf1b3cb1SVictor Perevertkin 
708bf1b3cb1SVictor Perevertkin     //
709bf1b3cb1SVictor Perevertkin     // Set transfer direction flag and Cdb command.
710bf1b3cb1SVictor Perevertkin     //
711bf1b3cb1SVictor Perevertkin 
712bf1b3cb1SVictor Perevertkin     if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
713bf1b3cb1SVictor Perevertkin 
714bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW,  "ClassBuildRequest: Read Command\n"));
715bf1b3cb1SVictor Perevertkin 
716bf1b3cb1SVictor Perevertkin         SrbSetSrbFlags(srbHeader, SRB_FLAGS_DATA_IN);
717bf1b3cb1SVictor Perevertkin         cdb->CDB10.OperationCode = SCSIOP_READ;
718bf1b3cb1SVictor Perevertkin 
719bf1b3cb1SVictor Perevertkin     } else {
720bf1b3cb1SVictor Perevertkin 
721bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW,  "ClassBuildRequest: Write Command\n"));
722bf1b3cb1SVictor Perevertkin 
723bf1b3cb1SVictor Perevertkin         SrbSetSrbFlags(srbHeader, SRB_FLAGS_DATA_OUT);
724bf1b3cb1SVictor Perevertkin         cdb->CDB10.OperationCode = SCSIOP_WRITE;
725bf1b3cb1SVictor Perevertkin 
726bf1b3cb1SVictor Perevertkin     }
727bf1b3cb1SVictor Perevertkin 
728bf1b3cb1SVictor Perevertkin     //
729bf1b3cb1SVictor Perevertkin     // If this is not a write-through request, then allow caching.
730bf1b3cb1SVictor Perevertkin     //
731bf1b3cb1SVictor Perevertkin 
732bf1b3cb1SVictor Perevertkin     if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {
733bf1b3cb1SVictor Perevertkin 
734bf1b3cb1SVictor Perevertkin         SrbSetSrbFlags(srbHeader, SRB_FLAGS_ADAPTER_CACHE_ENABLE);
735bf1b3cb1SVictor Perevertkin 
736bf1b3cb1SVictor Perevertkin     } else {
737bf1b3cb1SVictor Perevertkin 
738bf1b3cb1SVictor Perevertkin         //
739bf1b3cb1SVictor Perevertkin         // If write caching is enable then force media access in the
740bf1b3cb1SVictor Perevertkin         // cdb.
741bf1b3cb1SVictor Perevertkin         //
742bf1b3cb1SVictor Perevertkin 
743bf1b3cb1SVictor Perevertkin         cdb->CDB10.ForceUnitAccess = FdoExtension->CdbForceUnitAccess;
744bf1b3cb1SVictor Perevertkin     }
745bf1b3cb1SVictor Perevertkin 
746bf1b3cb1SVictor Perevertkin     if (TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) {
747bf1b3cb1SVictor Perevertkin         SrbSetSrbFlags(srbHeader, SRB_CLASS_FLAGS_PAGING);
748bf1b3cb1SVictor Perevertkin     }
749bf1b3cb1SVictor Perevertkin 
750bf1b3cb1SVictor Perevertkin     //
751bf1b3cb1SVictor Perevertkin     // OR in the default flags from the device object.
752bf1b3cb1SVictor Perevertkin     //
753bf1b3cb1SVictor Perevertkin 
754bf1b3cb1SVictor Perevertkin     SrbSetSrbFlags(srbHeader, FdoExtension->SrbFlags);
755bf1b3cb1SVictor Perevertkin 
756bf1b3cb1SVictor Perevertkin     //
757bf1b3cb1SVictor Perevertkin     // Set up major SCSI function.
758bf1b3cb1SVictor Perevertkin     //
759bf1b3cb1SVictor Perevertkin 
760bf1b3cb1SVictor Perevertkin     nextIrpStack->MajorFunction = IRP_MJ_SCSI;
761bf1b3cb1SVictor Perevertkin 
762bf1b3cb1SVictor Perevertkin     //
763bf1b3cb1SVictor Perevertkin     // Save SRB address in next stack for port driver.
764bf1b3cb1SVictor Perevertkin     //
765bf1b3cb1SVictor Perevertkin 
766bf1b3cb1SVictor Perevertkin     nextIrpStack->Parameters.Scsi.Srb = Srb;
767bf1b3cb1SVictor Perevertkin 
768bf1b3cb1SVictor Perevertkin     //
769bf1b3cb1SVictor Perevertkin     // Save retry count in current IRP stack.
770bf1b3cb1SVictor Perevertkin     //
771bf1b3cb1SVictor Perevertkin 
772bf1b3cb1SVictor Perevertkin     currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
773bf1b3cb1SVictor Perevertkin 
774bf1b3cb1SVictor Perevertkin     //
775bf1b3cb1SVictor Perevertkin     // Set up IoCompletion routine address.
776bf1b3cb1SVictor Perevertkin     //
777bf1b3cb1SVictor Perevertkin 
778bf1b3cb1SVictor Perevertkin     IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);
779bf1b3cb1SVictor Perevertkin 
780bf1b3cb1SVictor Perevertkin }
781bf1b3cb1SVictor Perevertkin 
782bf1b3cb1SVictor Perevertkin 
783bf1b3cb1SVictor Perevertkin VOID ClasspInsertCScanList(IN PLIST_ENTRY ListHead, IN PCSCAN_LIST_ENTRY Entry)
784bf1b3cb1SVictor Perevertkin {
785bf1b3cb1SVictor Perevertkin     PCSCAN_LIST_ENTRY t;
786bf1b3cb1SVictor Perevertkin 
787bf1b3cb1SVictor Perevertkin     TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClasspInsertCScanList is OBSOLETE !"));
788bf1b3cb1SVictor Perevertkin 
789bf1b3cb1SVictor Perevertkin     //
790bf1b3cb1SVictor Perevertkin     // Iterate through the list.  Insert this entry in the sorted list in
791bf1b3cb1SVictor Perevertkin     // order (after other requests for the same block).  At each stop if
792bf1b3cb1SVictor Perevertkin     // blockNumber(Entry) >= blockNumber(t) then move on.
793bf1b3cb1SVictor Perevertkin     //
794bf1b3cb1SVictor Perevertkin 
795bf1b3cb1SVictor Perevertkin     for(t = (PCSCAN_LIST_ENTRY) ListHead->Flink;
796bf1b3cb1SVictor Perevertkin         t != (PCSCAN_LIST_ENTRY) ListHead;
797bf1b3cb1SVictor Perevertkin         t = (PCSCAN_LIST_ENTRY) t->Entry.Flink) {
798bf1b3cb1SVictor Perevertkin 
799bf1b3cb1SVictor Perevertkin         if(Entry->BlockNumber < t->BlockNumber) {
800bf1b3cb1SVictor Perevertkin 
801bf1b3cb1SVictor Perevertkin             //
802bf1b3cb1SVictor Perevertkin             // Set the pointers in entry to the right location.
803bf1b3cb1SVictor Perevertkin             //
804bf1b3cb1SVictor Perevertkin 
805bf1b3cb1SVictor Perevertkin             Entry->Entry.Flink = &(t->Entry);
806bf1b3cb1SVictor Perevertkin             Entry->Entry.Blink = t->Entry.Blink;
807bf1b3cb1SVictor Perevertkin 
808bf1b3cb1SVictor Perevertkin             //
809bf1b3cb1SVictor Perevertkin             // Set the pointers in the surrounding elements to refer to us.
810bf1b3cb1SVictor Perevertkin             //
811bf1b3cb1SVictor Perevertkin 
812bf1b3cb1SVictor Perevertkin             t->Entry.Blink->Flink = &(Entry->Entry);
813bf1b3cb1SVictor Perevertkin             t->Entry.Blink = &(Entry->Entry);
814bf1b3cb1SVictor Perevertkin             return;
815bf1b3cb1SVictor Perevertkin         }
816bf1b3cb1SVictor Perevertkin     }
817bf1b3cb1SVictor Perevertkin 
818bf1b3cb1SVictor Perevertkin     //
819bf1b3cb1SVictor Perevertkin     // Insert this entry at the tail of the list.  If the list was empty this
820bf1b3cb1SVictor Perevertkin     // will also be the head of the list.
821bf1b3cb1SVictor Perevertkin     //
822bf1b3cb1SVictor Perevertkin 
823bf1b3cb1SVictor Perevertkin     InsertTailList(ListHead, &(Entry->Entry));
824bf1b3cb1SVictor Perevertkin 
825bf1b3cb1SVictor Perevertkin }
826bf1b3cb1SVictor Perevertkin 
827bf1b3cb1SVictor Perevertkin 
828bf1b3cb1SVictor Perevertkin VOID ClassInsertCScanList(IN PCSCAN_LIST List, IN PIRP Irp, IN ULONGLONG BlockNumber, IN BOOLEAN LowPriority)
829bf1b3cb1SVictor Perevertkin /*++
830bf1b3cb1SVictor Perevertkin 
831bf1b3cb1SVictor Perevertkin Routine Description:
832bf1b3cb1SVictor Perevertkin 
833bf1b3cb1SVictor Perevertkin     This routine inserts an entry into the CScan list based on it's block number
834bf1b3cb1SVictor Perevertkin     and priority.  It is assumed that the caller is providing synchronization
835bf1b3cb1SVictor Perevertkin     to the access of the list.
836bf1b3cb1SVictor Perevertkin 
837bf1b3cb1SVictor Perevertkin     Low priority requests are always scheduled to run on the next sweep across
838bf1b3cb1SVictor Perevertkin     the disk.  Normal priority requests will be inserted into the current or
839bf1b3cb1SVictor Perevertkin     next sweep based on the standard C-SCAN algorithm.
840bf1b3cb1SVictor Perevertkin 
841bf1b3cb1SVictor Perevertkin Arguments:
842bf1b3cb1SVictor Perevertkin 
843bf1b3cb1SVictor Perevertkin     List - the list to insert into
844bf1b3cb1SVictor Perevertkin 
845bf1b3cb1SVictor Perevertkin     Irp - the irp to be inserted.
846bf1b3cb1SVictor Perevertkin 
847bf1b3cb1SVictor Perevertkin     BlockNumber - the block number for this request.
848bf1b3cb1SVictor Perevertkin 
849bf1b3cb1SVictor Perevertkin     LowPriority - indicates that the request is lower priority and should be
850bf1b3cb1SVictor Perevertkin                   done on the next sweep across the disk.
851bf1b3cb1SVictor Perevertkin 
852bf1b3cb1SVictor Perevertkin Return Value:
853bf1b3cb1SVictor Perevertkin 
854bf1b3cb1SVictor Perevertkin     none
855bf1b3cb1SVictor Perevertkin 
856bf1b3cb1SVictor Perevertkin --*/
857bf1b3cb1SVictor Perevertkin {
858bf1b3cb1SVictor Perevertkin     PCSCAN_LIST_ENTRY entry = (PCSCAN_LIST_ENTRY)Irp->Tail.Overlay.DriverContext;
859bf1b3cb1SVictor Perevertkin 
860bf1b3cb1SVictor Perevertkin     TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInsertCScanList is OBSOLETE !"));
861bf1b3cb1SVictor Perevertkin 
862bf1b3cb1SVictor Perevertkin     //
863bf1b3cb1SVictor Perevertkin     // Set the block number in the entry.  We need this to keep the list sorted.
864bf1b3cb1SVictor Perevertkin     //
865bf1b3cb1SVictor Perevertkin     entry->BlockNumber = BlockNumber;
866bf1b3cb1SVictor Perevertkin 
867bf1b3cb1SVictor Perevertkin     //
868bf1b3cb1SVictor Perevertkin     // If it's a normal priority request and further down the disk than our
869bf1b3cb1SVictor Perevertkin     // current position then insert this entry into the current sweep.
870bf1b3cb1SVictor Perevertkin     //
871bf1b3cb1SVictor Perevertkin 
872bf1b3cb1SVictor Perevertkin     if((LowPriority != TRUE) && (BlockNumber > List->BlockNumber)) {
873bf1b3cb1SVictor Perevertkin         ClasspInsertCScanList(&(List->CurrentSweep), entry);
874bf1b3cb1SVictor Perevertkin     } else {
875bf1b3cb1SVictor Perevertkin         ClasspInsertCScanList(&(List->NextSweep), entry);
876bf1b3cb1SVictor Perevertkin     }
877bf1b3cb1SVictor Perevertkin     return;
878bf1b3cb1SVictor Perevertkin }
879bf1b3cb1SVictor Perevertkin 
880bf1b3cb1SVictor Perevertkin 
881bf1b3cb1SVictor Perevertkin 
882bf1b3cb1SVictor Perevertkin VOID ClassFreeOrReuseSrb(   IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
883bf1b3cb1SVictor Perevertkin                             IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb)
884bf1b3cb1SVictor Perevertkin /*++
885bf1b3cb1SVictor Perevertkin 
886bf1b3cb1SVictor Perevertkin Routine Description:
887bf1b3cb1SVictor Perevertkin 
888bf1b3cb1SVictor Perevertkin     This routine will attempt to reuse the provided SRB to start a blocked
889bf1b3cb1SVictor Perevertkin     read/write request.
890bf1b3cb1SVictor Perevertkin     If there is no need to reuse the request it will be returned
891bf1b3cb1SVictor Perevertkin     to the SRB lookaside list.
892bf1b3cb1SVictor Perevertkin 
893bf1b3cb1SVictor Perevertkin Arguments:
894bf1b3cb1SVictor Perevertkin 
895bf1b3cb1SVictor Perevertkin     Fdo - the device extension
896bf1b3cb1SVictor Perevertkin 
897bf1b3cb1SVictor Perevertkin     Srb - the SRB which is to be reused or freed.
898bf1b3cb1SVictor Perevertkin 
899bf1b3cb1SVictor Perevertkin Return Value:
900bf1b3cb1SVictor Perevertkin 
901bf1b3cb1SVictor Perevertkin     none.
902bf1b3cb1SVictor Perevertkin 
903bf1b3cb1SVictor Perevertkin --*/
904bf1b3cb1SVictor Perevertkin 
905bf1b3cb1SVictor Perevertkin {
906bf1b3cb1SVictor Perevertkin     PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension;
907bf1b3cb1SVictor Perevertkin 
908bf1b3cb1SVictor Perevertkin     // This function is obsolete, but still called by DISK.SYS .
909bf1b3cb1SVictor Perevertkin     // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassFreeOrReuseSrb is OBSOLETE !"));
910bf1b3cb1SVictor Perevertkin 
911bf1b3cb1SVictor Perevertkin     //
912bf1b3cb1SVictor Perevertkin     // safety net.  this should never occur.  if it does, it's a potential
913bf1b3cb1SVictor Perevertkin     // memory leak.
914bf1b3cb1SVictor Perevertkin     //
915bf1b3cb1SVictor Perevertkin     NT_ASSERT(!TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_FREE_SENSE_BUFFER));
916bf1b3cb1SVictor Perevertkin 
917bf1b3cb1SVictor Perevertkin     if (commonExt->IsSrbLookasideListInitialized){
918bf1b3cb1SVictor Perevertkin         /*
919bf1b3cb1SVictor Perevertkin          *  Put the SRB back in our lookaside list.
920bf1b3cb1SVictor Perevertkin          *
921bf1b3cb1SVictor Perevertkin          *  Note:   Some class drivers use ClassIoComplete
922bf1b3cb1SVictor Perevertkin          *            to complete SRBs that they themselves allocated.
923bf1b3cb1SVictor Perevertkin          *            So we may be putting a "foreign" SRB
924bf1b3cb1SVictor Perevertkin          *            (e.g. with a different pool tag) into our lookaside list.
925bf1b3cb1SVictor Perevertkin          */
926bf1b3cb1SVictor Perevertkin         ClasspFreeSrb(FdoExtension, Srb);
927bf1b3cb1SVictor Perevertkin     }
928bf1b3cb1SVictor Perevertkin     else {
929bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,"ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));
930bf1b3cb1SVictor Perevertkin         FREE_POOL(Srb);
931bf1b3cb1SVictor Perevertkin     }
932bf1b3cb1SVictor Perevertkin }
933bf1b3cb1SVictor Perevertkin 
934bf1b3cb1SVictor Perevertkin 
935bf1b3cb1SVictor Perevertkin /*++////////////////////////////////////////////////////////////////////////////
936bf1b3cb1SVictor Perevertkin 
937bf1b3cb1SVictor Perevertkin ClassDeleteSrbLookasideList()
938bf1b3cb1SVictor Perevertkin 
939bf1b3cb1SVictor Perevertkin Routine Description:
940bf1b3cb1SVictor Perevertkin 
941bf1b3cb1SVictor Perevertkin     This routine deletes a lookaside listhead for srbs, and should be called
942bf1b3cb1SVictor Perevertkin     only during the final removal.
943bf1b3cb1SVictor Perevertkin 
944bf1b3cb1SVictor Perevertkin     If called at other times, the caller is responsible for
945bf1b3cb1SVictor Perevertkin     synchronization and removal issues.
946bf1b3cb1SVictor Perevertkin 
947bf1b3cb1SVictor Perevertkin Arguments:
948bf1b3cb1SVictor Perevertkin 
949bf1b3cb1SVictor Perevertkin     CommonExtension - Pointer to the CommonExtension containing the listhead.
950bf1b3cb1SVictor Perevertkin 
951bf1b3cb1SVictor Perevertkin Return Value:
952bf1b3cb1SVictor Perevertkin 
953bf1b3cb1SVictor Perevertkin     None
954bf1b3cb1SVictor Perevertkin 
955bf1b3cb1SVictor Perevertkin --*/
956bf1b3cb1SVictor Perevertkin _IRQL_requires_max_(PASSIVE_LEVEL)
957bf1b3cb1SVictor Perevertkin VOID
958bf1b3cb1SVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
959bf1b3cb1SVictor Perevertkin ClassDeleteSrbLookasideList(_Inout_ PCOMMON_DEVICE_EXTENSION CommonExtension)
960bf1b3cb1SVictor Perevertkin {
961bf1b3cb1SVictor Perevertkin     PAGED_CODE();
962bf1b3cb1SVictor Perevertkin 
963bf1b3cb1SVictor Perevertkin     // This function is obsolete, but is still called by some of our code.
964bf1b3cb1SVictor Perevertkin     // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassDeleteSrbLookasideList is OBSOLETE !"));
965bf1b3cb1SVictor Perevertkin 
966bf1b3cb1SVictor Perevertkin     if (CommonExtension->IsSrbLookasideListInitialized){
967bf1b3cb1SVictor Perevertkin         CommonExtension->IsSrbLookasideListInitialized = FALSE;
968bf1b3cb1SVictor Perevertkin         ExDeleteNPagedLookasideList(&CommonExtension->SrbLookasideList);
969bf1b3cb1SVictor Perevertkin     }
970bf1b3cb1SVictor Perevertkin     else {
971bf1b3cb1SVictor Perevertkin         TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
972bf1b3cb1SVictor Perevertkin     }
973bf1b3cb1SVictor Perevertkin }
974bf1b3cb1SVictor Perevertkin 
975bf1b3cb1SVictor Perevertkin 
976bf1b3cb1SVictor Perevertkin /*++////////////////////////////////////////////////////////////////////////////
977bf1b3cb1SVictor Perevertkin 
978bf1b3cb1SVictor Perevertkin ClassInitializeSrbLookasideList()
979bf1b3cb1SVictor Perevertkin 
980bf1b3cb1SVictor Perevertkin Routine Description:
981bf1b3cb1SVictor Perevertkin 
982bf1b3cb1SVictor Perevertkin     This routine sets up a lookaside listhead for srbs, and should be called
983bf1b3cb1SVictor Perevertkin     only from the ClassInitDevice() routine to prevent race conditions.
984bf1b3cb1SVictor Perevertkin 
985bf1b3cb1SVictor Perevertkin     If called from other locations, the caller is responsible for
986bf1b3cb1SVictor Perevertkin     synchronization and removal issues.
987bf1b3cb1SVictor Perevertkin 
988bf1b3cb1SVictor Perevertkin Arguments:
989bf1b3cb1SVictor Perevertkin 
990bf1b3cb1SVictor Perevertkin     CommonExtension - Pointer to the CommonExtension containing the listhead.
991bf1b3cb1SVictor Perevertkin 
992bf1b3cb1SVictor Perevertkin     NumberElements  - Supplies the maximum depth of the lookaside list.
993bf1b3cb1SVictor Perevertkin 
994bf1b3cb1SVictor Perevertkin 
995bf1b3cb1SVictor Perevertkin Note:
996bf1b3cb1SVictor Perevertkin 
997bf1b3cb1SVictor Perevertkin     The Windows 2000 version of classpnp did not return any status value from
998bf1b3cb1SVictor Perevertkin     this call.
999bf1b3cb1SVictor Perevertkin 
1000bf1b3cb1SVictor Perevertkin --*/
1001bf1b3cb1SVictor Perevertkin 
1002bf1b3cb1SVictor Perevertkin _IRQL_requires_max_(PASSIVE_LEVEL)
1003bf1b3cb1SVictor Perevertkin VOID
1004bf1b3cb1SVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1005bf1b3cb1SVictor Perevertkin ClassInitializeSrbLookasideList(   _Inout_ PCOMMON_DEVICE_EXTENSION CommonExtension,
1006bf1b3cb1SVictor Perevertkin                                         _In_ ULONG NumberElements)
1007bf1b3cb1SVictor Perevertkin {
1008bf1b3cb1SVictor Perevertkin     size_t sizeNeeded;
1009bf1b3cb1SVictor Perevertkin     PFUNCTIONAL_DEVICE_EXTENSION fdo;
1010bf1b3cb1SVictor Perevertkin 
1011bf1b3cb1SVictor Perevertkin     PAGED_CODE();
1012bf1b3cb1SVictor Perevertkin 
1013bf1b3cb1SVictor Perevertkin     // This function is obsolete, but still called by DISK.SYS .
1014bf1b3cb1SVictor Perevertkin     // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInitializeSrbLookasideList is OBSOLETE !"));
1015bf1b3cb1SVictor Perevertkin 
1016bf1b3cb1SVictor Perevertkin     NT_ASSERT(!CommonExtension->IsSrbLookasideListInitialized);
1017bf1b3cb1SVictor Perevertkin     if (!CommonExtension->IsSrbLookasideListInitialized){
1018bf1b3cb1SVictor Perevertkin 
1019bf1b3cb1SVictor Perevertkin         if (CommonExtension->IsFdo == TRUE) {
1020bf1b3cb1SVictor Perevertkin             fdo = (PFUNCTIONAL_DEVICE_EXTENSION)CommonExtension;
1021bf1b3cb1SVictor Perevertkin 
1022bf1b3cb1SVictor Perevertkin             //
1023bf1b3cb1SVictor Perevertkin             // Check FDO extension on the SRB type supported
1024bf1b3cb1SVictor Perevertkin             //
1025bf1b3cb1SVictor Perevertkin             if (fdo->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1026bf1b3cb1SVictor Perevertkin 
1027bf1b3cb1SVictor Perevertkin                 //
1028bf1b3cb1SVictor Perevertkin                 // It's 16 byte CDBs for now. Need to change when classpnp uses >16
1029bf1b3cb1SVictor Perevertkin                 // byte CDBs or support new address types.
1030bf1b3cb1SVictor Perevertkin                 //
1031bf1b3cb1SVictor Perevertkin                 sizeNeeded = CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE;
1032bf1b3cb1SVictor Perevertkin 
1033bf1b3cb1SVictor Perevertkin             } else {
1034bf1b3cb1SVictor Perevertkin                 sizeNeeded = sizeof(SCSI_REQUEST_BLOCK);
1035bf1b3cb1SVictor Perevertkin             }
1036bf1b3cb1SVictor Perevertkin 
1037bf1b3cb1SVictor Perevertkin         } else {
1038bf1b3cb1SVictor Perevertkin 
1039bf1b3cb1SVictor Perevertkin             //
1040bf1b3cb1SVictor Perevertkin             // For PDO, use the max of old and new SRB as can't guarantee we can get
1041bf1b3cb1SVictor Perevertkin             // corresponding FDO to determine SRB support.
1042bf1b3cb1SVictor Perevertkin             //
1043bf1b3cb1SVictor Perevertkin             sizeNeeded = max(sizeof(SCSI_REQUEST_BLOCK), CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE);
1044bf1b3cb1SVictor Perevertkin         }
1045bf1b3cb1SVictor Perevertkin 
1046bf1b3cb1SVictor Perevertkin         ExInitializeNPagedLookasideList(&CommonExtension->SrbLookasideList,
1047bf1b3cb1SVictor Perevertkin                                         NULL,
1048bf1b3cb1SVictor Perevertkin                                         NULL,
1049bf1b3cb1SVictor Perevertkin                                         POOL_NX_ALLOCATION,
1050bf1b3cb1SVictor Perevertkin                                         sizeNeeded,
1051bf1b3cb1SVictor Perevertkin                                         '$scS',
1052bf1b3cb1SVictor Perevertkin                                         (USHORT)NumberElements);
1053bf1b3cb1SVictor Perevertkin 
1054bf1b3cb1SVictor Perevertkin         CommonExtension->IsSrbLookasideListInitialized = TRUE;
1055bf1b3cb1SVictor Perevertkin     }
1056bf1b3cb1SVictor Perevertkin 
1057bf1b3cb1SVictor Perevertkin }
1058bf1b3cb1SVictor Perevertkin 
1059bf1b3cb1SVictor Perevertkin 
1060bf1b3cb1SVictor Perevertkin 
1061bf1b3cb1SVictor Perevertkin 
1062bf1b3cb1SVictor Perevertkin VOID ClasspInitializeCScanList(IN PCSCAN_LIST List)
1063bf1b3cb1SVictor Perevertkin {
1064bf1b3cb1SVictor Perevertkin     PAGED_CODE();
1065bf1b3cb1SVictor Perevertkin     RtlZeroMemory(List, sizeof(CSCAN_LIST));
1066bf1b3cb1SVictor Perevertkin     InitializeListHead(&(List->CurrentSweep));
1067bf1b3cb1SVictor Perevertkin     InitializeListHead(&(List->NextSweep));
1068bf1b3cb1SVictor Perevertkin }
1069bf1b3cb1SVictor Perevertkin 
1070bf1b3cb1SVictor Perevertkin 
1071bf1b3cb1SVictor Perevertkin 
1072bf1b3cb1SVictor Perevertkin VOID ClasspStartNextSweep(PCSCAN_LIST List)
1073bf1b3cb1SVictor Perevertkin {
1074bf1b3cb1SVictor Perevertkin     NT_ASSERT(IsListEmpty(&(List->CurrentSweep)) == TRUE);
1075bf1b3cb1SVictor Perevertkin 
1076bf1b3cb1SVictor Perevertkin     //
1077bf1b3cb1SVictor Perevertkin     // If the next sweep is empty then there's nothing to do.
1078bf1b3cb1SVictor Perevertkin     //
1079bf1b3cb1SVictor Perevertkin 
1080bf1b3cb1SVictor Perevertkin     if(IsListEmpty(&(List->NextSweep))) {
1081bf1b3cb1SVictor Perevertkin         return;
1082bf1b3cb1SVictor Perevertkin     }
1083bf1b3cb1SVictor Perevertkin 
1084bf1b3cb1SVictor Perevertkin     //
1085bf1b3cb1SVictor Perevertkin     // Copy the next sweep list head into the current sweep list head.
1086bf1b3cb1SVictor Perevertkin     //
1087bf1b3cb1SVictor Perevertkin 
1088bf1b3cb1SVictor Perevertkin     List->CurrentSweep = List->NextSweep;
1089bf1b3cb1SVictor Perevertkin 
1090bf1b3cb1SVictor Perevertkin     //
1091bf1b3cb1SVictor Perevertkin     // Unlink the next sweep list from the list head now that we have a copy
1092bf1b3cb1SVictor Perevertkin     // of it.
1093bf1b3cb1SVictor Perevertkin     //
1094bf1b3cb1SVictor Perevertkin 
1095bf1b3cb1SVictor Perevertkin     InitializeListHead(&(List->NextSweep));
1096bf1b3cb1SVictor Perevertkin 
1097bf1b3cb1SVictor Perevertkin     //
1098bf1b3cb1SVictor Perevertkin     // Update the next sweep list to point back to the current sweep list head.
1099bf1b3cb1SVictor Perevertkin     //
1100bf1b3cb1SVictor Perevertkin 
1101bf1b3cb1SVictor Perevertkin     List->CurrentSweep.Flink->Blink = &(List->CurrentSweep);
1102bf1b3cb1SVictor Perevertkin     List->CurrentSweep.Blink->Flink = &(List->CurrentSweep);
1103bf1b3cb1SVictor Perevertkin 
1104bf1b3cb1SVictor Perevertkin     return;
1105bf1b3cb1SVictor Perevertkin }
1106bf1b3cb1SVictor Perevertkin 
1107bf1b3cb1SVictor Perevertkin 
1108bf1b3cb1SVictor Perevertkin 
1109bf1b3cb1SVictor Perevertkin PIRP ClassRemoveCScanList(IN PCSCAN_LIST List)
1110bf1b3cb1SVictor Perevertkin {
1111bf1b3cb1SVictor Perevertkin     PCSCAN_LIST_ENTRY entry;
1112bf1b3cb1SVictor Perevertkin 
1113bf1b3cb1SVictor Perevertkin     //
1114bf1b3cb1SVictor Perevertkin     // If the current sweep is empty then promote the next sweep.
1115bf1b3cb1SVictor Perevertkin     //
1116bf1b3cb1SVictor Perevertkin 
1117bf1b3cb1SVictor Perevertkin     if(IsListEmpty(&(List->CurrentSweep))) {
1118bf1b3cb1SVictor Perevertkin         ClasspStartNextSweep(List);
1119bf1b3cb1SVictor Perevertkin     }
1120bf1b3cb1SVictor Perevertkin 
1121bf1b3cb1SVictor Perevertkin     //
1122bf1b3cb1SVictor Perevertkin     // If the current sweep is still empty then we're done.
1123bf1b3cb1SVictor Perevertkin     //
1124bf1b3cb1SVictor Perevertkin 
1125bf1b3cb1SVictor Perevertkin     if(IsListEmpty(&(List->CurrentSweep))) {
1126bf1b3cb1SVictor Perevertkin         return NULL;
1127bf1b3cb1SVictor Perevertkin     }
1128bf1b3cb1SVictor Perevertkin 
1129bf1b3cb1SVictor Perevertkin     //
1130bf1b3cb1SVictor Perevertkin     // Remove the head entry from the current sweep.  Record it's block number
1131bf1b3cb1SVictor Perevertkin     // so that nothing before it on the disk gets into the current sweep.
1132bf1b3cb1SVictor Perevertkin     //
1133bf1b3cb1SVictor Perevertkin 
1134bf1b3cb1SVictor Perevertkin     entry = (PCSCAN_LIST_ENTRY) RemoveHeadList(&(List->CurrentSweep));
1135bf1b3cb1SVictor Perevertkin 
1136bf1b3cb1SVictor Perevertkin     List->BlockNumber = entry->BlockNumber;
1137bf1b3cb1SVictor Perevertkin 
1138bf1b3cb1SVictor Perevertkin     return CONTAINING_RECORD(entry, IRP, Tail.Overlay.DriverContext);
1139bf1b3cb1SVictor Perevertkin }
1140