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