ReactOS 0.4.15-dev-7942-gd23573b
scsi.c File Reference
#include "scsiport.h"
#include <debug.h>
Include dependency graph for scsi.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS SpiStatusSrbToNt (_In_ UCHAR SrbStatus)
 
static NTSTATUS SpiHandleAttachRelease (_In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_ PIRP Irp)
 
NTSTATUS NTAPI ScsiPortDispatchScsi (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
 
VOID SpiGetNextRequestFromLun (_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_opt_ PKIRQL OldIrql)
 
NTSTATUS NTAPI SpiSenseCompletionRoutine (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_opt_ PVOID Context)
 
static VOID SpiSendRequestSense (_In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _In_ PSCSI_REQUEST_BLOCK InitialSrb)
 
static VOID SpiProcessCompletedRequest (_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_REQUEST_BLOCK_INFO SrbInfo, _Out_ PBOOLEAN NeedToCallStartIo)
 
BOOLEAN NTAPI ScsiPortStartPacket (_In_ PVOID Context)
 
BOOLEAN NTAPI SpiSaveInterruptData (IN PVOID Context)
 
VOID NTAPI ScsiPortDpcForIsr (_In_ PKDPC Dpc, _In_ PDEVICE_OBJECT DpcDeviceObject, _Inout_ PIRP DpcIrp, _In_opt_ PVOID DpcContext)
 
static PSCSI_REQUEST_BLOCK_INFO SpiAllocateSrbStructures (_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
VOID NTAPI ScsiPortStartIo (_Inout_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
 

Variables

IO_COMPLETION_ROUTINE SpiSenseCompletionRoutine
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file scsi.c.

Function Documentation

◆ ScsiPortDispatchScsi()

NTSTATUS NTAPI ScsiPortDispatchScsi ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp 
)

Definition at line 123 of file scsi.c.

126{
131 KIRQL Irql;
133 PIRP NextIrp, IrpList;
135
136 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
137
139 Srb = Stack->Parameters.Scsi.Srb;
140 lunExt = DeviceObject->DeviceExtension;
141 ASSERT(!lunExt->Common.IsFDO);
142 portExt = lunExt->Common.LowerDevice->DeviceExtension;
143
144 if (Srb == NULL)
145 {
146 DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n");
148
149 Irp->IoStatus.Status = Status;
150 Irp->IoStatus.Information = 0;
151
153
154 return Status;
155 }
156
157 DPRINT("Srb: %p, Srb->Function: %lu\n", Srb, Srb->Function);
158
159 Srb->PathId = lunExt->PathId;
160 Srb->TargetId = lunExt->TargetId;
161 Srb->Lun = lunExt->Lun;
162
163 if (lunExt == NULL)
164 {
165 DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
167
169 Irp->IoStatus.Status = Status;
170 Irp->IoStatus.Information = 0;
171
173
174 return Status;
175 }
176
177 switch (Srb->Function)
178 {
181 DPRINT(" SRB_FUNCTION_SHUTDOWN or FLUSH\n");
182 if (portExt->CachesData == FALSE)
183 {
184 /* All success here */
186 Irp->IoStatus.Status = STATUS_SUCCESS;
188 return STATUS_SUCCESS;
189 }
190 /* Fall through to a usual execute operation */
191
194 DPRINT(" SRB_FUNCTION_EXECUTE_SCSI or SRB_FUNCTION_IO_CONTROL\n");
195 /* Mark IRP as pending in all cases */
197
199 {
200 /* Start IO directly */
201 IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL);
202 }
203 else
204 {
205 KIRQL oldIrql;
206
207 /* We need to be at DISPATCH_LEVEL */
208 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
209
210 /* Insert IRP into the queue */
212 &Irp->Tail.Overlay.DeviceQueueEntry,
214 {
215 /* It means the queue is empty, and we just start this request */
216 IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL);
217 }
218
219 /* Back to the old IRQL */
220 KeLowerIrql(oldIrql);
221 }
222 return STATUS_PENDING;
223
226 DPRINT(" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n");
227
228 /* Reference device object and keep the device object */
230 break;
231
233 DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
234
235 /* Dereference device object and clear the device object */
237 break;
238
240 DPRINT(" SRB_FUNCTION_RELEASE_QUEUE\n");
241
242 /* Guard with the spinlock */
243 KeAcquireSpinLock(&portExt->SpinLock, &Irql);
244
245 if (!(lunExt->Flags & LUNEX_FROZEN_QUEUE))
246 {
247 DPRINT("Queue is not frozen really\n");
248
249 KeReleaseSpinLock(&portExt->SpinLock, Irql);
252 break;
253
254 }
255
256 /* Unfreeze the queue */
257 lunExt->Flags &= ~LUNEX_FROZEN_QUEUE;
258
259 if (lunExt->SrbInfo.Srb == NULL)
260 {
261 /* Get next logical unit request. SpiGetNextRequestFromLun releases the lock. */
262 SpiGetNextRequestFromLun(portExt, lunExt, &Irql);
263 }
264 else
265 {
266 DPRINT("The queue has active request\n");
267 KeReleaseSpinLock(&portExt->SpinLock, Irql);
268 }
269
272 break;
273
275 DPRINT(" SRB_FUNCTION_FLUSH_QUEUE\n");
276
277 /* Guard with the spinlock */
278 KeAcquireSpinLock(&portExt->SpinLock, &Irql);
279
280 if (!(lunExt->Flags & LUNEX_FROZEN_QUEUE))
281 {
282 DPRINT("Queue is not frozen really\n");
283
284 KeReleaseSpinLock(&portExt->SpinLock, Irql);
286 break;
287 }
288
289 /* Make sure there is no active request */
290 ASSERT(lunExt->SrbInfo.Srb == NULL);
291
292 /* Compile a list from the device queue */
293 IrpList = NULL;
294 while ((Entry = KeRemoveDeviceQueue(&lunExt->DeviceQueue)) != NULL)
295 {
296 NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
297
298 /* Get the Srb */
300 Srb = Stack->Parameters.Scsi.Srb;
301
302 /* Set statuse */
305
306 /* Add then to the list */
307 NextIrp->Tail.Overlay.ListEntry.Flink = (PLIST_ENTRY)IrpList;
308 IrpList = NextIrp;
309 }
310
311 /* Unfreeze the queue */
312 lunExt->Flags &= ~LUNEX_FROZEN_QUEUE;
313
314 /* Release the spinlock */
315 KeReleaseSpinLock(&portExt->SpinLock, Irql);
316
317 /* Complete those requests */
318 while (IrpList)
319 {
320 NextIrp = IrpList;
321 IrpList = (PIRP)NextIrp->Tail.Overlay.ListEntry.Flink;
322
323 IoCompleteRequest(NextIrp, 0);
324 }
325
327 break;
328
329 default:
330 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
332 break;
333 }
334
335 Irp->IoStatus.Status = Status;
337
338 return Status;
339}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
_In_ PIRP Irp
Definition: csq.h:116
_Out_ PKIRQL Irql
Definition: csq.h:179
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
BOOLEAN NTAPI KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, IN ULONG SortKey)
Definition: devqueue.c:83
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:361
#define SRB_FUNCTION_ATTACH_DEVICE
Definition: srb.h:320
#define SRB_FUNCTION_RELEASE_DEVICE
Definition: srb.h:321
#define SRB_FUNCTION_CLAIM_DEVICE
Definition: srb.h:316
#define SRB_FUNCTION_IO_CONTROL
Definition: srb.h:317
#define SRB_FUNCTION_RELEASE_QUEUE
Definition: srb.h:319
#define SRB_FLAGS_BYPASS_FROZEN_QUEUE
Definition: srb.h:398
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_FUNCTION_FLUSH_QUEUE
Definition: srb.h:329
#define SRB_FUNCTION_SHUTDOWN
Definition: srb.h:322
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
Status
Definition: gdiplustypes.h:25
IoMarkIrpPending(Irp)
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI IoStartPacket(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key, IN PDRIVER_CANCEL CancelFunction)
Definition: device.c:1876
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define LUNEX_FROZEN_QUEUE
Definition: scsiport.h:46
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
VOID SpiGetNextRequestFromLun(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_opt_ PKIRQL OldIrql)
Definition: scsi.c:342
static NTSTATUS SpiHandleAttachRelease(_In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_ PIRP Irp)
Definition: scsi.c:52
base of all file and directory entries
Definition: entries.h:83
PVOID DeviceExtension
Definition: env_spec_w32.h:418
IO_STATUS_BLOCK IoStatus
Definition: ketypes.h:578
PDEVICE_OBJECT LowerDevice
Definition: scsiport.h:139
KDEVICE_QUEUE DeviceQueue
Definition: scsiport.h:160
SCSI_PORT_COMMON_EXTENSION Common
Definition: scsiport.h:146
SCSI_REQUEST_BLOCK_INFO SrbInfo
Definition: scsiport.h:174
PSCSI_REQUEST_BLOCK Srb
Definition: scsiport.h:119
UCHAR TargetId
Definition: srb.h:254
UCHAR PathId
Definition: srb.h:253
ULONG QueueSortKey
Definition: srb.h:270
UCHAR Function
Definition: srb.h:250
ULONG SrbFlags
Definition: srb.h:260
UCHAR SrbStatus
Definition: srb.h:251
struct _LIST_ENTRY * PLIST_ENTRY
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define IO_NO_INCREMENT
Definition: iotypes.h:598

◆ ScsiPortDpcForIsr()

VOID NTAPI ScsiPortDpcForIsr ( _In_ PKDPC  Dpc,
_In_ PDEVICE_OBJECT  DpcDeviceObject,
_Inout_ PIRP  DpcIrp,
_In_opt_ PVOID  DpcContext 
)

Definition at line 1260 of file scsi.c.

1265{
1266 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DpcDeviceObject->DeviceExtension;
1267 SCSI_PORT_INTERRUPT_DATA InterruptData;
1269 PSCSI_PORT_LUN_EXTENSION LunExtension;
1270 BOOLEAN NeedToStartIo;
1272 LARGE_INTEGER TimerValue;
1273
1274 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
1275 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
1276
1277 /* We need to acquire spinlock */
1278 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1279
1280 RtlZeroMemory(&InterruptData, sizeof(SCSI_PORT_INTERRUPT_DATA));
1281
1282TryAgain:
1283
1284 /* Interrupt structure must be snapshotted, and only then analyzed */
1285 Context.InterruptData = &InterruptData;
1286 Context.DeviceExtension = DeviceExtension;
1287
1288 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0],
1290 &Context))
1291 {
1292 /* Nothing - just return (don't forget to release the spinlock */
1293 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1294 DPRINT("ScsiPortDpcForIsr() done\n");
1295 return;
1296 }
1297
1298 /* If flush of adapters is needed - do it */
1299 if (InterruptData.Flags & SCSI_PORT_FLUSH_ADAPTERS)
1300 {
1301 /* TODO: Implement */
1302 ASSERT(FALSE);
1303 }
1304
1305 /* Check for IoMapTransfer */
1306 if (InterruptData.Flags & SCSI_PORT_MAP_TRANSFER)
1307 {
1308 /* TODO: Implement */
1309 ASSERT(FALSE);
1310 }
1311
1312 /* Check if timer is needed */
1313 if (InterruptData.Flags & SCSI_PORT_TIMER_NEEDED)
1314 {
1315 /* Save the timer routine */
1316 DeviceExtension->HwScsiTimer = InterruptData.HwScsiTimer;
1317
1318 if (InterruptData.MiniportTimerValue == 0)
1319 {
1320 /* Cancel the timer */
1321 KeCancelTimer(&DeviceExtension->MiniportTimer);
1322 }
1323 else
1324 {
1325 /* Convert timer value */
1326 TimerValue.QuadPart = Int32x32To64(InterruptData.MiniportTimerValue, -10);
1327
1328 /* Set the timer */
1329 KeSetTimer(&DeviceExtension->MiniportTimer,
1330 TimerValue,
1331 &DeviceExtension->MiniportTimerDpc);
1332 }
1333 }
1334
1335 /* If it's ready for the next request */
1336 if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY)
1337 {
1338 /* Check for a duplicate request (NextRequest+NextLuRequest) */
1339 if ((DeviceExtension->Flags &
1342 {
1343 /* Clear busy flag set by ScsiPortStartPacket() */
1344 DeviceExtension->Flags &= ~SCSI_PORT_DEVICE_BUSY;
1345
1346 if (!(InterruptData.Flags & SCSI_PORT_RESET))
1347 {
1348 /* Ready for next, and no reset is happening */
1349 DeviceExtension->TimerCount = -1;
1350 }
1351 }
1352 else
1353 {
1354 /* Not busy, but not ready for the next request */
1355 DeviceExtension->Flags &= ~SCSI_PORT_DEVICE_BUSY;
1356 InterruptData.Flags &= ~SCSI_PORT_NEXT_REQUEST_READY;
1357 }
1358 }
1359
1360 /* Any resets? */
1361 if (InterruptData.Flags & SCSI_PORT_RESET_REPORTED)
1362 {
1363 /* Hold for a bit */
1364 DeviceExtension->TimerCount = 4;
1365 }
1366
1367 /* Any ready LUN? */
1368 if (InterruptData.ReadyLun != NULL)
1369 {
1370
1371 /* Process all LUNs from the list*/
1372 while (TRUE)
1373 {
1374 /* Remove it from the list first (as processed) */
1375 LunExtension = InterruptData.ReadyLun;
1376 InterruptData.ReadyLun = LunExtension->ReadyLun;
1377 LunExtension->ReadyLun = NULL;
1378
1379 /* Get next request for this LUN */
1380 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
1381
1382 /* Still ready requests exist?
1383 If yes - get spinlock, if no - stop here */
1384 if (InterruptData.ReadyLun != NULL)
1385 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1386 else
1387 break;
1388 }
1389 }
1390 else
1391 {
1392 /* Release the spinlock */
1393 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1394 }
1395
1396 /* If we ready for next packet, start it */
1397 if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY)
1398 IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE);
1399
1400 NeedToStartIo = FALSE;
1401
1402 /* Loop the completed request list */
1403 while (InterruptData.CompletedRequests)
1404 {
1405 /* Remove the request */
1406 SrbInfo = InterruptData.CompletedRequests;
1407 InterruptData.CompletedRequests = SrbInfo->CompletedRequests;
1408 SrbInfo->CompletedRequests = NULL;
1409
1410 /* Process it */
1411 SpiProcessCompletedRequest(DeviceExtension,
1412 SrbInfo,
1413 &NeedToStartIo);
1414 }
1415
1416 /* Loop abort request list */
1417 while (InterruptData.CompletedAbort)
1418 {
1419 LunExtension = InterruptData.CompletedAbort;
1420
1421 /* Remove the request */
1422 InterruptData.CompletedAbort = LunExtension->CompletedAbortRequests;
1423
1424 /* Get spinlock since we're going to change flags */
1425 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1426
1427 /* TODO: Put SrbExtension to the list of free extensions */
1428 ASSERT(FALSE);
1429 }
1430
1431 /* If we need - call StartIo routine */
1432 if (NeedToStartIo)
1433 {
1434 /* Make sure CurrentIrp is not null! */
1435 ASSERT(DpcDeviceObject->CurrentIrp != NULL);
1436 ScsiPortStartIo(DpcDeviceObject, DpcDeviceObject->CurrentIrp);
1437 }
1438
1439 /* Everything has been done, check */
1440 if (InterruptData.Flags & SCSI_PORT_ENABLE_INT_REQUEST)
1441 {
1442 /* Synchronize using spinlock */
1443 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1444
1445 /* Request an interrupt */
1446 DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
1447
1448 ASSERT(DeviceExtension->Flags & SCSI_PORT_DISABLE_INT_REQUESET);
1449
1450 /* Should interrupts be enabled again? */
1451 if (DeviceExtension->Flags & SCSI_PORT_DISABLE_INT_REQUESET)
1452 {
1453 /* Clear this flag */
1454 DeviceExtension->Flags &= ~SCSI_PORT_DISABLE_INT_REQUESET;
1455
1456 /* Call a special routine to do this */
1457 ASSERT(FALSE);
1458#if 0
1459 KeSynchronizeExecution(DeviceExtension->Interrupt,
1460 SpiEnableInterrupts,
1461 DeviceExtension);
1462#endif
1463 }
1464
1465 /* If we need a notification again - loop */
1466 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
1467 goto TryAgain;
1468
1469 /* Release the spinlock */
1470 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1471 }
1472
1473 DPRINT("ScsiPortDpcForIsr() done\n");
1474}
unsigned char BOOLEAN
@ TryAgain
Definition: bl.h:896
#define SCSI_PORT_NEXT_REQUEST_READY
Definition: scsiport.c:53
#define TRUE
Definition: types.h:120
#define Int32x32To64(a, b)
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847
BOOLEAN NTAPI KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, IN PVOID SynchronizeContext OPTIONAL)
Definition: interrupt.c:237
#define SCSI_PORT_DISCONNECT_ALLOWED
Definition: scsiport.h:39
#define SCSI_PORT_RESET
Definition: scsiport.h:35
#define SCSI_PORT_DEVICE_BUSY
Definition: scsiport.h:29
#define SCSI_PORT_TIMER_NEEDED
Definition: scsiport.h:43
#define SCSI_PORT_NOTIFICATION_NEEDED
Definition: scsiport.h:31
DRIVER_STARTIO ScsiPortStartIo
Definition: scsiport.h:454
#define SCSI_PORT_MAP_TRANSFER
Definition: scsiport.h:34
#define SCSI_PORT_FLUSH_ADAPTERS
Definition: scsiport.h:33
#define SCSI_PORT_RESET_REPORTED
Definition: scsiport.h:37
#define SCSI_PORT_DISABLE_INT_REQUESET
Definition: scsiport.h:40
#define SCSI_PORT_ENABLE_INT_REQUEST
Definition: scsiport.h:42
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
static VOID SpiProcessCompletedRequest(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_REQUEST_BLOCK_INFO SrbInfo, _Out_ PBOOLEAN NeedToCallStartIo)
Definition: scsi.c:647
BOOLEAN NTAPI SpiSaveInterruptData(IN PVOID Context)
Definition: scsi.c:1143
PHW_INTERRUPT HwInterrupt
Definition: scsiport.c:82
PSCSI_PORT_LUN_EXTENSION ReadyLun
Definition: scsiport.h:199
PSCSI_PORT_LUN_EXTENSION CompletedAbort
Definition: scsiport.h:198
PSCSI_REQUEST_BLOCK_INFO CompletedRequests
Definition: scsiport.h:197
struct _SCSI_PORT_LUN_EXTENSION * CompletedAbortRequests
Definition: scsiport.h:172
struct _SCSI_PORT_LUN_EXTENSION * ReadyLun
Definition: scsiport.h:171
struct _SCSI_REQUEST_BLOCK_INFO * CompletedRequests
Definition: scsiport.h:129
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112

◆ ScsiPortStartIo()

VOID NTAPI ScsiPortStartIo ( _Inout_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp 
)

Definition at line 1625 of file scsi.c.

1628{
1629 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1630 PSCSI_PORT_LUN_EXTENSION LunExtension;
1631 PIO_STACK_LOCATION IrpStack;
1634 LONG CounterResult;
1636
1637 DPRINT("ScsiPortStartIo() called!\n");
1638
1639 DeviceExtension = DeviceObject->DeviceExtension;
1641 LunExtension = IrpStack->DeviceObject->DeviceExtension;
1642
1643 ASSERT(DeviceExtension->Common.IsFDO);
1644 ASSERT(!LunExtension->Common.IsFDO);
1645
1646 DPRINT("LunExtension %p DeviceExtension %p\n", LunExtension, DeviceExtension);
1647
1648 Srb = IrpStack->Parameters.Scsi.Srb;
1649
1650 /* Apply "default" flags */
1651 Srb->SrbFlags |= DeviceExtension->SrbFlags;
1652
1653 if (DeviceExtension->NeedSrbDataAlloc ||
1654 DeviceExtension->NeedSrbExtensionAlloc)
1655 {
1656 /* Allocate them */
1657 SrbInfo = SpiAllocateSrbStructures(DeviceExtension,
1658 LunExtension,
1659 Srb);
1660
1661 /* Couldn't alloc one or both data structures, return */
1662 if (SrbInfo == NULL)
1663 {
1664 /* We have to call IoStartNextPacket, because this request
1665 was not started */
1666 if (LunExtension->Flags & LUNEX_REQUEST_PENDING)
1668
1669 return;
1670 }
1671 }
1672 else
1673 {
1674 /* No allocations are needed */
1675 SrbInfo = &LunExtension->SrbInfo;
1678 }
1679
1680 /* Increase sequence number of SRB */
1681 if (!SrbInfo->SequenceNumber)
1682 {
1683 /* Increase global sequence number */
1684 DeviceExtension->SequenceNumber++;
1685
1686 /* Assign it */
1687 SrbInfo->SequenceNumber = DeviceExtension->SequenceNumber;
1688 }
1689
1690 /* Check some special SRBs */
1692 {
1693 /* Some special handling */
1694 DPRINT1("Abort command! Unimplemented now\n");
1695 }
1696 else
1697 {
1698 SrbInfo->Srb = Srb;
1699 }
1700
1702 {
1703 // Store the MDL virtual address in SrbInfo structure
1704 SrbInfo->DataOffset = MmGetMdlVirtualAddress(Irp->MdlAddress);
1705
1706 if (DeviceExtension->MapBuffers)
1707 {
1708 /* Calculate offset within DataBuffer */
1709 SrbInfo->DataOffset = MmGetSystemAddressForMdl(Irp->MdlAddress);
1710 Srb->DataBuffer = SrbInfo->DataOffset +
1712 (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress));
1713 }
1714
1715 if (DeviceExtension->AdapterObject)
1716 {
1717 /* Flush buffers */
1718 KeFlushIoBuffers(Irp->MdlAddress,
1720 TRUE);
1721 }
1722
1723 if (DeviceExtension->MapRegisters)
1724 {
1725 /* Calculate number of needed map registers */
1727 Srb->DataBuffer,
1729
1730 /* Allocate adapter channel */
1732 DeviceExtension->Common.DeviceObject,
1733 SrbInfo->NumberOfMapRegisters,
1735 SrbInfo);
1736
1737 if (!NT_SUCCESS(Status))
1738 {
1739 DPRINT1("IoAllocateAdapterChannel() failed!\n");
1740
1743 DeviceExtension + 1,
1744 Srb);
1745
1747 DeviceExtension + 1);
1748
1749 /* Request DPC for that work */
1750 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
1751 }
1752
1753 /* Control goes to SpiAdapterControl */
1754 return;
1755 }
1756 }
1757
1758 /* Increase active request counter */
1759 CounterResult = InterlockedIncrement(&DeviceExtension->ActiveRequestCounter);
1760
1761 if (CounterResult == 0 &&
1762 DeviceExtension->AdapterObject != NULL &&
1763 !DeviceExtension->MapRegisters)
1764 {
1766 DeviceExtension->AdapterObject,
1768 DeviceExtension->PortCapabilities.MaximumPhysicalPages,
1770 LunExtension
1771 );
1772
1773 return;
1774 }
1775
1776 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1777
1778 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0],
1780 DeviceObject))
1781 {
1782 DPRINT("Synchronization failed!\n");
1783
1784 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1785 Irp->IoStatus.Information = 0;
1786 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1787
1789 }
1790 else
1791 {
1792 /* Release the spinlock only */
1793 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1794 }
1795
1796
1797 DPRINT("ScsiPortStartIo() done\n");
1798}
#define InterlockedIncrement
Definition: armddk.h:53
VOID __cdecl ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDeviceExtension, IN ...)
Definition: scsiport.c:1324
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_FLAGS_UNSPECIFIED_DIRECTION
Definition: srb.h:403
@ RequestComplete
Definition: srb.h:531
@ NextRequest
Definition: srb.h:532
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
#define SRB_FUNCTION_ABORT_COMMAND
Definition: srb.h:324
IO_ALLOCATION_ACTION NTAPI SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID MapRegisterBase, PVOID Context)
Definition: scsiport.c:2037
IO_ALLOCATION_ACTION NTAPI ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: scsiport.c:3022
NTSTATUS NTAPI IoAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
Definition: adapter.c:30
long LONG
Definition: pedump.c:60
KSYNCHRONIZE_ROUTINE ScsiPortStartPacket
Definition: scsiport.h:453
#define LUNEX_REQUEST_PENDING
Definition: scsiport.h:50
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:174
static PSCSI_REQUEST_BLOCK_INFO SpiAllocateSrbStructures(_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1478
PADAPTER_OBJECT AdapterObject
Definition: scsiport.c:86
IO_SCSI_CAPABILITIES PortCapabilities
Definition: scsiport.c:78
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
UCHAR QueueTag
Definition: srb.h:256
PVOID DataBuffer
Definition: srb.h:263
ULONG DataTransferLength
Definition: srb.h:261
PVOID SrbExtension
Definition: srb.h:267
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
FORCEINLINE VOID IoRequestDpc(_Inout_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Irp, _In_opt_ __drv_aliasesMem PVOID Context)
Definition: iofuncs.h:2750
#define MmGetSystemAddressForMdl(Mdl)
#define MmGetMdlVirtualAddress(_Mdl)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)

◆ ScsiPortStartPacket()

BOOLEAN NTAPI ScsiPortStartPacket ( _In_ PVOID  Context)

Definition at line 986 of file scsi.c.

988{
989 PIO_STACK_LOCATION IrpStack;
992 PSCSI_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
993 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
994 PSCSI_PORT_LUN_EXTENSION LunExtension;
997 BOOLEAN StartTimer;
998
999 DPRINT("ScsiPortStartPacket() called\n");
1000
1001 IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
1002 Srb = IrpStack->Parameters.Scsi.Srb;
1003
1004 if (CommonExtension->IsFDO) // IsFDO
1005 {
1006 DeviceExtension = DeviceObject->DeviceExtension;
1007 LunExtension = IrpStack->DeviceObject->DeviceExtension;
1008 ASSERT(LunExtension && !LunExtension->Common.IsFDO);
1009 }
1010 else
1011 {
1012 LunExtension = DeviceObject->DeviceExtension;
1013 DeviceExtension = LunExtension->Common.LowerDevice->DeviceExtension;
1014 }
1015
1016 /* Check if we are in a reset state */
1017 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
1018 {
1019 /* Mark the we've got requests while being in the reset state */
1020 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET_REQUEST;
1021 return TRUE;
1022 }
1023
1024 /* Set the time out value */
1025 DeviceExtension->TimerCount = Srb->TimeOutValue;
1026
1027 /* We are busy */
1028 DeviceExtension->Flags |= SCSI_PORT_DEVICE_BUSY;
1029
1030 if (LunExtension->RequestTimeout != -1)
1031 {
1032 /* Timer already active */
1033 StartTimer = FALSE;
1034 }
1035 else
1036 {
1037 /* It hasn't been initialized yet */
1038 LunExtension->RequestTimeout = Srb->TimeOutValue;
1039 StartTimer = TRUE;
1040 }
1041
1043 {
1044 /* Handle bypass-requests */
1045
1046 /* Is this an abort request? */
1048 {
1049 /* Get pointer to SRB info structure */
1050 SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
1051
1052 /* Check if the request is still "active" */
1053 if (SrbInfo == NULL ||
1054 SrbInfo->Srb == NULL ||
1055 !(SrbInfo->Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
1056 {
1057 /* It's not, mark it as active then */
1059
1060 if (StartTimer)
1061 LunExtension->RequestTimeout = -1;
1062
1063 DPRINT("Request has been already completed, but abort request came\n");
1065
1066 /* Notify about request complete */
1068 DeviceExtension->MiniPortDeviceExtension,
1069 Srb);
1070
1071 /* and about readiness for the next request */
1073 DeviceExtension->MiniPortDeviceExtension);
1074
1075 /* They might ask for some work, so queue the DPC for them */
1076 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
1077
1078 /* We're done in this branch */
1079 return TRUE;
1080 }
1081 }
1082 else
1083 {
1084 /* Add number of queued requests */
1085 LunExtension->QueueCount++;
1086 }
1087
1088 /* Bypass requests don't need request sense */
1089 LunExtension->Flags &= ~LUNEX_NEED_REQUEST_SENSE;
1090
1091 /* Is disconnect disabled for this request? */
1093 {
1094 /* Set the corresponding flag */
1095 DeviceExtension->Flags &= ~SCSI_PORT_DISCONNECT_ALLOWED;
1096 }
1097
1098 /* Transfer timeout value from Srb to Lun */
1099 LunExtension->RequestTimeout = Srb->TimeOutValue;
1100 }
1101 else
1102 {
1104 {
1105 /* It's a disconnect, so no more requests can go */
1106 DeviceExtension->Flags &= ~SCSI_PORT_DISCONNECT_ALLOWED;
1107 }
1108
1109 LunExtension->Flags |= SCSI_PORT_LU_ACTIVE;
1110
1111 /* Increment queue count */
1112 LunExtension->QueueCount++;
1113
1114 /* If it's tagged - special thing */
1115 if (Srb->QueueTag != SP_UNTAGGED)
1116 {
1117 SrbInfo = &DeviceExtension->SrbInfo[Srb->QueueTag - 1];
1118
1119 /* Chek for consistency */
1120 ASSERT(SrbInfo->Requests.Blink == NULL);
1121
1122 /* Insert it into the list of requests */
1123 InsertTailList(&LunExtension->SrbInfo.Requests, &SrbInfo->Requests);
1124 }
1125 }
1126
1127 /* Mark this Srb active */
1129
1130 /* Call HwStartIo routine */
1131 Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1132 Srb);
1133
1134 /* If notification is needed, then request a DPC */
1135 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
1136 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL);
1137
1138 return Result;
1139}
#define SRB_FLAGS_IS_ACTIVE
Definition: srb.h:407
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:396
#define SRB_STATUS_ABORT_FAILED
Definition: srb.h:343
#define InsertTailList(ListHead, Entry)
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define SCSI_PORT_RESET_REQUEST
Definition: scsiport.h:36
#define SCSI_PORT_LU_ACTIVE
Definition: scsiport.h:30
PSCSI_REQUEST_BLOCK_INFO SpiGetSrbData(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _In_ UCHAR QueueTag)
Definition: pdo.c:102
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
ULONG TimeOutValue
Definition: srb.h:262
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

◆ SpiAllocateSrbStructures()

static PSCSI_REQUEST_BLOCK_INFO SpiAllocateSrbStructures ( _Inout_ PSCSI_PORT_DEVICE_EXTENSION  DeviceExtension,
_Inout_ PSCSI_PORT_LUN_EXTENSION  LunExtension,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)
static

Definition at line 1478 of file scsi.c.

1482{
1483 PCHAR SrbExtension;
1485
1486 /* Spinlock must be held while this function executes */
1487 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1488
1489 /* Allocate SRB data structure */
1490 if (DeviceExtension->NeedSrbDataAlloc)
1491 {
1492 /* Treat the abort request in a special way */
1494 {
1495 SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
1496 }
1497 else if (Srb->SrbFlags &
1500 )
1501 {
1502 /* Do not process tagged commands if need request sense is set */
1503 if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE)
1504 {
1505 ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
1506
1507 LunExtension->PendingRequest = Srb->OriginalRequest;
1508 LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
1509
1510 /* Release the spinlock and return */
1511 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1512 return NULL;
1513 }
1514
1515 ASSERT(LunExtension->SrbInfo.Srb == NULL);
1516 SrbInfo = DeviceExtension->FreeSrbInfo;
1517
1518 if (SrbInfo == NULL)
1519 {
1520 /* No SRB structures left in the list. We have to leave
1521 and wait while we are called again */
1522
1523 DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
1524 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1525 return NULL;
1526 }
1527
1528 DeviceExtension->FreeSrbInfo = (PSCSI_REQUEST_BLOCK_INFO)SrbInfo->Requests.Flink;
1529
1530 /* QueueTag must never be 0, so +1 to it */
1531 Srb->QueueTag = (UCHAR)(SrbInfo - DeviceExtension->SrbInfo) + 1;
1532 }
1533 else
1534 {
1535 /* Usual untagged command */
1536 if (
1537 (!IsListEmpty(&LunExtension->SrbInfo.Requests) ||
1538 LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) &&
1540 )
1541 {
1542 /* Mark it as pending and leave */
1543 ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
1544 LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
1545 LunExtension->PendingRequest = Srb->OriginalRequest;
1546
1547 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1548 return(NULL);
1549 }
1550
1552 SrbInfo = &LunExtension->SrbInfo;
1553 }
1554 }
1555 else
1556 {
1558 SrbInfo = &LunExtension->SrbInfo;
1559 }
1560
1561 /* Allocate SRB extension structure */
1562 if (DeviceExtension->NeedSrbExtensionAlloc)
1563 {
1564 /* Check the list of free extensions */
1565 SrbExtension = DeviceExtension->FreeSrbExtensions;
1566
1567 /* If no free extensions... */
1568 if (SrbExtension == NULL)
1569 {
1570 /* Free SRB data */
1573 {
1574 SrbInfo->Requests.Blink = NULL;
1575 SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo;
1576 DeviceExtension->FreeSrbInfo = SrbInfo;
1577 }
1578
1579 /* Return, in order to be called again later */
1580 DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
1581 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1582 return NULL;
1583 }
1584
1585 /* Remove that free SRB extension from the list (since
1586 we're going to use it) */
1587 DeviceExtension->FreeSrbExtensions = *((PVOID *)SrbExtension);
1588
1589 /* Spinlock can be released now */
1590 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1591
1592 Srb->SrbExtension = SrbExtension;
1593
1594 if (Srb->SenseInfoBuffer != NULL &&
1595 DeviceExtension->SupportsAutoSense)
1596 {
1597 /* Store pointer to the SenseInfo buffer */
1599
1600 /* Does data fit the buffer? */
1601 if (Srb->SenseInfoBufferLength > sizeof(SENSE_DATA))
1602 {
1603 /* No, disabling autosense at all */
1605 }
1606 else
1607 {
1608 /* Yes, update the buffer pointer */
1609 Srb->SenseInfoBuffer = SrbExtension + DeviceExtension->SrbExtensionSize;
1610 }
1611 }
1612 }
1613 else
1614 {
1615 /* Cleanup... */
1617 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1618 }
1619
1620 return SrbInfo;
1621}
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:399
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
struct _SCSI_REQUEST_BLOCK_INFO * PSCSI_REQUEST_BLOCK_INFO
#define LUNEX_NEED_REQUEST_SENSE
Definition: scsiport.h:47
#define SCSI_PORT_REQUEST_PENDING
Definition: scsiport.h:38
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PVOID OriginalRequest
Definition: srb.h:266
UCHAR SenseInfoBufferLength
Definition: srb.h:259
PVOID SenseInfoBuffer
Definition: srb.h:264
char * PCHAR
Definition: typedefs.h:51
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by ScsiPortStartIo().

◆ SpiGetNextRequestFromLun()

VOID SpiGetNextRequestFromLun ( _In_ PSCSI_PORT_DEVICE_EXTENSION  DeviceExtension,
_Inout_ PSCSI_PORT_LUN_EXTENSION  LunExtension,
_Inout_opt_ PKIRQL  OldIrql 
)

Definition at line 342 of file scsi.c.

347{
348 PIO_STACK_LOCATION IrpStack;
349 PIRP NextIrp;
352
353
354 /* If LUN is not active or queue is more than maximum allowed */
355 if (LunExtension->QueueCount >= LunExtension->MaxQueueCount ||
356 !(LunExtension->Flags & SCSI_PORT_LU_ACTIVE))
357 {
358 /* Release the spinlock and exit */
359 if (OldIrql != NULL)
360 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
361 else
362 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
363 return;
364 }
365
366 /* Check if we can get a next request */
367 if (LunExtension->Flags &
370 {
371 /* Pending requests can only be started if the queue is empty */
372 if (IsListEmpty(&LunExtension->SrbInfo.Requests) &&
373 !(LunExtension->Flags &
375 {
376 /* Make sure we have SRB */
377 ASSERT(LunExtension->SrbInfo.Srb == NULL);
378
379 /* Clear active and pending flags */
380 LunExtension->Flags &= ~(LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE);
381
382 /* Get next Irp, and clear pending requests list */
383 NextIrp = LunExtension->PendingRequest;
384 LunExtension->PendingRequest = NULL;
385
386 /* Set attempt counter to zero */
387 LunExtension->AttemptCount = 0;
388
389 /* Release the spinlock */
390 if (OldIrql != NULL)
391 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
392 else
393 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
394
395 /* Start the next pending request */
396 IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
397
398 return;
399 }
400 else
401 {
402 /* Release the spinlock, without clearing any flags and exit */
403 if (OldIrql != NULL)
404 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
405 else
406 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
407
408 return;
409 }
410 }
411
412 /* Reset active flag */
413 LunExtension->Flags &= ~SCSI_PORT_LU_ACTIVE;
414
415 /* Set attempt counter to zero */
416 LunExtension->AttemptCount = 0;
417
418 /* Remove packet from the device queue */
419 Entry = KeRemoveByKeyDeviceQueue(&LunExtension->DeviceQueue, LunExtension->SortKey);
420
421 if (Entry != NULL)
422 {
423 /* Get pointer to the next irp */
424 NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
425
426 /* Get point to the SRB */
427 IrpStack = IoGetCurrentIrpStackLocation(NextIrp);
428 Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
429
430 /* Set new key*/
431 LunExtension->SortKey = Srb->QueueSortKey;
432 LunExtension->SortKey++;
433
434 /* Release the spinlock */
435 if (OldIrql != NULL)
436 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
437 else
438 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
439
440 /* Start the next pending request */
441 IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
442 }
443 else
444 {
445 /* Release the spinlock */
446 if (OldIrql != NULL)
447 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
448 else
449 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
450 }
451}
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN ULONG SortKey)
Definition: devqueue.c:197
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
if(dx< 0)
Definition: linetemp.h:194
#define LUNEX_FULL_QUEUE
Definition: scsiport.h:49
#define LUNEX_BUSY
Definition: scsiport.h:48
struct _IO_STACK_LOCATION::@3978::@4017 Others
uint32_t * PULONG
Definition: typedefs.h:59
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by FdoSendInquiry(), ScsiPortDispatchScsi(), ScsiPortDpcForIsr(), SpiProcessCompletedRequest(), and SpiSenseCompletionRoutine().

◆ SpiHandleAttachRelease()

static NTSTATUS SpiHandleAttachRelease ( _In_ PSCSI_PORT_LUN_EXTENSION  LunExtension,
_Inout_ PIRP  Irp 
)
static

Definition at line 52 of file scsi.c.

55{
56 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension =
57 LunExtension->Common.LowerDevice->DeviceExtension;
59 KIRQL Irql;
60
61 /* Get pointer to the SRB */
63 PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;
64
65 /* Get spinlock */
66 KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
67
68 /* Release, if asked */
70 {
71 LunExtension->DeviceClaimed = FALSE;
72 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
74
75 return STATUS_SUCCESS;
76 }
77
78 /* Attach, if not already claimed */
79 if (LunExtension->DeviceClaimed)
80 {
81 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
83
84 return STATUS_DEVICE_BUSY;
85 }
86
87 /* Save the device object */
88 DeviceObject = LunExtension->Common.DeviceObject;
89
91 LunExtension->DeviceClaimed = TRUE;
92
94 LunExtension->Common.DeviceObject = Srb->DataBuffer;
95
97
98 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
100
101 return STATUS_SUCCESS;
102}
#define SRB_STATUS_BUSY
Definition: srb.h:345
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129

Referenced by ScsiPortDispatchScsi().

◆ SpiProcessCompletedRequest()

static VOID SpiProcessCompletedRequest ( _In_ PSCSI_PORT_DEVICE_EXTENSION  DeviceExtension,
_Inout_ PSCSI_REQUEST_BLOCK_INFO  SrbInfo,
_Out_ PBOOLEAN  NeedToCallStartIo 
)
static

Definition at line 647 of file scsi.c.

651{
653 PSCSI_PORT_LUN_EXTENSION LunExtension;
654 LONG Result;
655 PIRP Irp;
656
657 Srb = SrbInfo->Srb;
660
661 /* Get Lun extension */
662 LunExtension = IoStack->DeviceObject->DeviceExtension;
663 ASSERT(LunExtension && !LunExtension->Common.IsFDO);
664
666 DeviceExtension->MapBuffers &&
667 Irp->MdlAddress)
668 {
669 /* MDL is shared if transfer is broken into smaller parts */
670 Srb->DataBuffer = (PCCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) +
671 ((PCCHAR)Srb->DataBuffer - SrbInfo->DataOffset);
672
673 /* In case of data going in, flush the buffers */
675 {
676 KeFlushIoBuffers(Irp->MdlAddress,
677 TRUE,
678 FALSE);
679 }
680 }
681
682 /* Flush adapter if needed */
683 if (SrbInfo->BaseOfMapRegister && SrbInfo->ScatterGather)
684 {
685 ULONG transferLen = 0;
686 BOOLEAN isWrite = !!(Srb->SrbFlags & SRB_FLAGS_DATA_OUT);
687 ULONG i;
688
689 for (i = 0;
690 i < SrbInfo->NumberOfMapRegisters && transferLen < Srb->DataTransferLength;
691 i++)
692 {
693 transferLen += SrbInfo->ScatterGather[i].Length;
694 }
695
696 IoFlushAdapterBuffers(DeviceExtension->AdapterObject,
697 Irp->MdlAddress,
698 SrbInfo->BaseOfMapRegister,
700 transferLen,
701 isWrite);
702 }
703
704 /* Clear the request */
705 SrbInfo->Srb = NULL;
706
707 /* If disconnect is disabled... */
709 {
710 /* Acquire the spinlock since we mess with flags */
711 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
712
713 /* Set corresponding flag */
714 DeviceExtension->Flags |= SCSI_PORT_DISCONNECT_ALLOWED;
715
716 /* Clear the timer if needed */
717 if (!(DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET))
718 DeviceExtension->TimerCount = -1;
719
720 /* Spinlock is not needed anymore */
721 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
722
723 if (!(DeviceExtension->Flags & SCSI_PORT_REQUEST_PENDING) &&
724 !(DeviceExtension->Flags & SCSI_PORT_DEVICE_BUSY) &&
725 !(*NeedToCallStartIo))
726 {
727 /* We're not busy, but we have a request pending */
728 IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE);
729 }
730 }
731
732 /* Scatter/gather */
734 {
735 ExFreePoolWithTag(SrbInfo->ScatterGather, TAG_SCSIPORT);
736 SrbInfo->ScatterGather = NULL;
737 }
738
739 /* Free Map Registers */
740 if (SrbInfo->NumberOfMapRegisters)
741 {
742 IoFreeMapRegisters(DeviceExtension->AdapterObject,
743 SrbInfo->BaseOfMapRegister,
744 SrbInfo->NumberOfMapRegisters);
745 }
746
747 /* Acquire spinlock (we're freeing SrbExtension) */
748 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
749
750 /* Free it (if needed) */
751 if (Srb->SrbExtension)
752 {
753 if (Srb->SenseInfoBuffer != NULL && DeviceExtension->SupportsAutoSense)
754 {
755 ASSERT(Srb->SenseInfoBuffer == NULL || SrbInfo->SaveSenseRequest != NULL);
756
758 {
759 /* Copy sense data to the buffer */
760 RtlCopyMemory(SrbInfo->SaveSenseRequest,
763 }
764
765 /* And restore the pointer */
766 Srb->SenseInfoBuffer = SrbInfo->SaveSenseRequest;
767 }
768
769 /* Put it into the free srb extensions list */
770 *((PVOID *)Srb->SrbExtension) = DeviceExtension->FreeSrbExtensions;
771 DeviceExtension->FreeSrbExtensions = Srb->SrbExtension;
772 }
773
774 /* Save transfer length in the IRP */
775 Irp->IoStatus.Information = Srb->DataTransferLength;
776
777 //SequenceNumber = SrbInfo->SequenceNumber;
778 SrbInfo->SequenceNumber = 0;
779
780 /* Decrement the queue count */
781 LunExtension->QueueCount--;
782
783 /* Free Srb, if needed*/
784 if (Srb->QueueTag != SP_UNTAGGED)
785 {
786 /* Put it into the free list */
787 SrbInfo->Requests.Blink = NULL;
788 SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo;
789 DeviceExtension->FreeSrbInfo = SrbInfo;
790 }
791
792 /* SrbInfo is not used anymore */
793 SrbInfo = NULL;
794
795 if (DeviceExtension->Flags & SCSI_PORT_REQUEST_PENDING)
796 {
797 /* Clear the flag */
798 DeviceExtension->Flags &= ~SCSI_PORT_REQUEST_PENDING;
799
800 /* Note the caller about StartIo */
801 *NeedToCallStartIo = TRUE;
802 }
803
805 {
806 /* Start the packet */
807 Irp->IoStatus.Status = STATUS_SUCCESS;
808
810 LunExtension->RequestTimeout == -1)
811 {
812 /* Start the next packet. SpiGetNextRequestFromLun will release the lock for us */
813 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
814 }
815 else
816 {
817 /* Release the spinlock */
818 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
819 }
820
821 DPRINT("IoCompleting request IRP 0x%p\n", Irp);
822
824
825 /* Decrement number of active requests, and analyze the result */
826 Result = InterlockedDecrement(&DeviceExtension->ActiveRequestCounter);
827
828 if (Result < 0 &&
829 !DeviceExtension->MapRegisters &&
830 DeviceExtension->AdapterObject != NULL)
831 {
832 /* Nullify map registers */
833 DeviceExtension->MapRegisterBase = NULL;
834 IoFreeAdapterChannel(DeviceExtension->AdapterObject);
835 }
836
837 /* Exit, we're done */
838 return;
839 }
840
841 /* Decrement number of active requests, and analyze the result */
842 Result = InterlockedDecrement(&DeviceExtension->ActiveRequestCounter);
843
844 if (Result < 0 &&
845 !DeviceExtension->MapRegisters &&
846 DeviceExtension->AdapterObject != NULL)
847 {
848 /* Result is negative, so this is a slave, free map registers */
849 DeviceExtension->MapRegisterBase = NULL;
850 IoFreeAdapterChannel(DeviceExtension->AdapterObject);
851 }
852
853 /* Convert status */
854 Irp->IoStatus.Status = SpiStatusSrbToNt(Srb->SrbStatus);
855
856 /* It's not a bypass, it's busy or the queue is full? */
857 if ((Srb->ScsiStatus == SCSISTAT_BUSY ||
861 {
862
863 DPRINT("Busy SRB status %x\n", Srb->SrbStatus);
864
865 /* Requeue, if needed */
866 if (LunExtension->Flags & (LUNEX_FROZEN_QUEUE | LUNEX_BUSY))
867 {
868 DPRINT("it's being requeued\n");
869
871 Srb->ScsiStatus = 0;
872
873 if (!KeInsertByKeyDeviceQueue(&LunExtension->DeviceQueue,
874 &Irp->Tail.Overlay.DeviceQueueEntry,
876 {
877 /* It's a big f.ck up if we got here */
880
881 ASSERT(FALSE);
882 goto Error;
883 }
884
885 /* Release the spinlock */
886 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
887
888 }
889 else if (LunExtension->AttemptCount++ < 20)
890 {
891 /* LUN is still busy */
892 Srb->ScsiStatus = 0;
894
895 LunExtension->BusyRequest = Irp;
896 LunExtension->Flags |= LUNEX_BUSY;
897
898 /* Release the spinlock */
899 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
900 }
901 else
902 {
903Error:
904 /* Freeze the queue*/
906 LunExtension->Flags |= LUNEX_FROZEN_QUEUE;
907
908 /* "Unfull" the queue */
909 LunExtension->Flags &= ~LUNEX_FULL_QUEUE;
910
911 /* Release the spinlock */
912 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
913
914 /* Return status that the device is not ready */
915 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
917 }
918
919 return;
920 }
921
922 /* Start the next request, if LUN is idle, and this is sense request */
927 {
928 if (LunExtension->RequestTimeout == -1)
929 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
930 else
931 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
932 }
933 else
934 {
935 /* Freeze the queue */
937 LunExtension->Flags |= LUNEX_FROZEN_QUEUE;
938
939 /* Do we need a request sense? */
943 {
944 /* If LUN is busy, we have to requeue it in order to allow request sense */
945 if (LunExtension->Flags & LUNEX_BUSY)
946 {
947 DPRINT("Requeuing busy request to allow request sense\n");
948
949 if (!KeInsertByKeyDeviceQueue(&LunExtension->DeviceQueue,
950 &LunExtension->BusyRequest->Tail.Overlay.DeviceQueueEntry,
952 {
953 /* We should never get here */
954 ASSERT(FALSE);
955
956 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
958 return;
959
960 }
961
962 /* Clear busy flags */
963 LunExtension->Flags &= ~(LUNEX_FULL_QUEUE | LUNEX_BUSY);
964 }
965
966 /* Release the spinlock */
967 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
968
969 /* Send RequestSense */
970 SpiSendRequestSense(LunExtension, Srb);
971
972 /* Exit */
973 return;
974 }
975
976 /* Release the spinlock */
977 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
978 }
979
980 /* Complete the request */
982}
#define InterlockedDecrement
Definition: armddk.h:52
BOOL Error
Definition: chkdsk.c:66
#define SCSISTAT_CHECK_CONDITION
Definition: cdrw_hw.h:1079
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define SCSISTAT_QUEUE_FULL
Definition: cdrw_hw.h:1086
#define SRB_FLAGS_SGLIST_FROM_POOL
Definition: srb.h:409
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOLEAN NTAPI IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:127
VOID NTAPI IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, IN PVOID MapRegisterBase, IN ULONG NumberOfMapRegisters)
Definition: dma.c:114
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define TAG_SCSIPORT
Definition: scsiport.h:21
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
static NTSTATUS SpiStatusSrbToNt(_In_ UCHAR SrbStatus)
Definition: scsi.c:18
static VOID SpiSendRequestSense(_In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _In_ PSCSI_REQUEST_BLOCK InitialSrb)
Definition: scsi.c:536
UCHAR ScsiStatus
Definition: srb.h:252
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IO_DISK_INCREMENT
Definition: iotypes.h:600

Referenced by ScsiPortDpcForIsr().

◆ SpiSaveInterruptData()

BOOLEAN NTAPI SpiSaveInterruptData ( IN PVOID  Context)

Definition at line 1143 of file scsi.c.

1144{
1145 PSCSI_PORT_SAVE_INTERRUPT InterruptContext = Context;
1146 PSCSI_PORT_LUN_EXTENSION LunExtension;
1148 PSCSI_REQUEST_BLOCK_INFO SrbInfo, NextSrbInfo;
1149 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1150 BOOLEAN IsTimed;
1151
1152 /* Get pointer to the device extension */
1153 DeviceExtension = InterruptContext->DeviceExtension;
1154
1155 /* If we don't have anything pending - return */
1156 if (!(DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED))
1157 return FALSE;
1158
1159 /* Actually save the interrupt data */
1160 *InterruptContext->InterruptData = DeviceExtension->InterruptData;
1161
1162 /* Clear the data stored in the device extension */
1163 DeviceExtension->InterruptData.Flags &=
1165 DeviceExtension->InterruptData.CompletedAbort = NULL;
1166 DeviceExtension->InterruptData.ReadyLun = NULL;
1167 DeviceExtension->InterruptData.CompletedRequests = NULL;
1168
1169 /* Loop through the list of completed requests */
1170 SrbInfo = InterruptContext->InterruptData->CompletedRequests;
1171
1172 while (SrbInfo)
1173 {
1174 /* Make sure we have SRV */
1175 ASSERT(SrbInfo->Srb);
1176
1177 /* Get SRB and LunExtension */
1178 Srb = SrbInfo->Srb;
1179
1181 LunExtension = IoStack->DeviceObject->DeviceExtension;
1182 ASSERT(LunExtension && !LunExtension->Common.IsFDO);
1183
1184 /* We have to check special cases if request is unsuccessful*/
1186 {
1187 /* Check if we need request sense by a few conditions */
1191 {
1192 if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE)
1193 {
1194 /* It means: we tried to send REQUEST SENSE, but failed */
1195
1196 Srb->ScsiStatus = 0;
1198 }
1199 else
1200 {
1201 /* Set the corresponding flag, so that REQUEST SENSE
1202 will be sent */
1203 LunExtension->Flags |= LUNEX_NEED_REQUEST_SENSE;
1204 }
1205
1206 }
1207
1208 /* Check for a full queue */
1210 {
1211 /* TODO: Implement when it's encountered */
1212 ASSERT(FALSE);
1213 }
1214 }
1215
1216 /* Let's decide if we need to watch timeout or not */
1217 if (Srb->QueueTag == SP_UNTAGGED)
1218 {
1219 IsTimed = TRUE;
1220 }
1221 else
1222 {
1223 if (LunExtension->SrbInfo.Requests.Flink == &SrbInfo->Requests)
1224 IsTimed = TRUE;
1225 else
1226 IsTimed = FALSE;
1227
1228 /* Remove it from the queue */
1229 RemoveEntryList(&SrbInfo->Requests);
1230 }
1231
1232 if (IsTimed)
1233 {
1234 /* We have to maintain timeout counter */
1235 if (IsListEmpty(&LunExtension->SrbInfo.Requests))
1236 {
1237 LunExtension->RequestTimeout = -1;
1238 }
1239 else
1240 {
1241 NextSrbInfo = CONTAINING_RECORD(LunExtension->SrbInfo.Requests.Flink,
1243 Requests);
1244
1245 Srb = NextSrbInfo->Srb;
1246
1247 /* Update timeout counter */
1248 LunExtension->RequestTimeout = Srb->TimeOutValue;
1249 }
1250 }
1251
1252 SrbInfo = SrbInfo->CompletedRequests;
1253 }
1254
1255 return TRUE;
1256}
#define SRB_STATUS_REQUEST_SENSE_FAILED
Definition: srb.h:355
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define SCSI_PORT_DISABLE_INTERRUPTS
Definition: scsiport.h:41
struct _SCSI_PORT_DEVICE_EXTENSION * DeviceExtension
Definition: scsiport.h:209
PSCSI_PORT_INTERRUPT_DATA InterruptData
Definition: scsiport.h:208

Referenced by ScsiPortDpcForIsr().

◆ SpiSendRequestSense()

static VOID SpiSendRequestSense ( _In_ PSCSI_PORT_LUN_EXTENSION  LunExtension,
_In_ PSCSI_REQUEST_BLOCK  InitialSrb 
)
static

Definition at line 536 of file scsi.c.

539{
541 PCDB Cdb;
542 PIRP Irp;
543 PIO_STACK_LOCATION IrpStack;
544 LARGE_INTEGER LargeInt;
545 PVOID *Ptr;
546
547 DPRINT("SpiSendRequestSense() entered, InitialSrb %p\n", InitialSrb);
548
549 /* Allocate Srb */
552
553 /* Allocate IRP */
554 LargeInt.QuadPart = (LONGLONG) 1;
556 LunExtension->Common.DeviceObject,
557 InitialSrb->SenseInfoBuffer,
558 InitialSrb->SenseInfoBufferLength,
559 &LargeInt,
560 NULL);
561
564 Srb,
565 TRUE,
566 TRUE,
567 TRUE);
568
569 if (!Srb)
570 {
571 DPRINT("SpiSendRequestSense() failed, Srb %p\n", Srb);
572 return;
573 }
574
575 IrpStack = IoGetNextIrpStackLocation(Irp);
576 IrpStack->MajorFunction = IRP_MJ_SCSI;
577
578 /* Put Srb address into Irp... */
579 IrpStack->Parameters.Others.Argument1 = (PVOID)Srb;
580
581 /* ...and vice versa */
583
584 /* Save Srb */
585 Ptr = (PVOID *)(Srb+1);
586 *Ptr = InitialSrb;
587
588 /* Build CDB for REQUEST SENSE */
589 Srb->CdbLength = 6;
590 Cdb = (PCDB)Srb->Cdb;
591
592 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
593 Cdb->CDB6INQUIRY.LogicalUnitNumber = 0;
594 Cdb->CDB6INQUIRY.Reserved1 = 0;
595 Cdb->CDB6INQUIRY.PageCode = 0;
596 Cdb->CDB6INQUIRY.IReserved = 0;
597 Cdb->CDB6INQUIRY.AllocationLength = (UCHAR)InitialSrb->SenseInfoBufferLength;
598 Cdb->CDB6INQUIRY.Control = 0;
599
600 /* Set address */
601 Srb->TargetId = InitialSrb->TargetId;
602 Srb->Lun = InitialSrb->Lun;
603 Srb->PathId = InitialSrb->PathId;
604
606 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
607
608 /* Timeout will be 2 seconds */
609 Srb->TimeOutValue = 2;
610
611 /* No auto request sense */
614
615 /* Set necessary flags */
618
619 // pass some InitialSrb flags
620 if (InitialSrb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER)
622
623 if (InitialSrb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE)
625
626 if (InitialSrb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE)
628
629 Srb->DataBuffer = InitialSrb->SenseInfoBuffer;
630
631 /* Fill the transfer length */
632 Srb->DataTransferLength = InitialSrb->SenseInfoBufferLength;
633
634 /* Clear statuses */
635 Srb->ScsiStatus = Srb->SrbStatus = 0;
636 Srb->NextSrb = 0;
637
638 /* Call the driver */
639 (VOID)IoCallDriver(LunExtension->Common.DeviceObject, Irp);
640
641 DPRINT("SpiSendRequestSense() done\n");
642}
#define VOID
Definition: acefi.h:82
#define SCSIOP_REQUEST_SENSE
Definition: cdrw_hw.h:870
union _CDB * PCDB
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:410
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
PIRP NTAPI IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:750
#define IoCallDriver
Definition: irp.c:1225
#define IRP_MJ_READ
Definition: rdpdr.c:46
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:159
IO_COMPLETION_ROUTINE SpiSenseCompletionRoutine
Definition: scsi.c:453
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
struct _SCSI_REQUEST_BLOCK * NextSrb
Definition: srb.h:265
USHORT Length
Definition: srb.h:249
int64_t LONGLONG
Definition: typedefs.h:68
void * PVOID
Definition: typedefs.h:50
Definition: cdrw_hw.h:28
struct _CDB::_CDB6INQUIRY CDB6INQUIRY
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IRP_MJ_SCSI

Referenced by SpiProcessCompletedRequest().

◆ SpiSenseCompletionRoutine()

NTSTATUS NTAPI SpiSenseCompletionRoutine ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_opt_ PVOID  Context 
)

Definition at line 457 of file scsi.c.

461{
466 PSCSI_REQUEST_BLOCK InitialSrb;
467 PIRP InitialIrp;
468
469 DPRINT("SpiCompletionRoutine() entered, IRP %p \n", Irp);
470
473 {
474 /* Deallocate SRB and IRP and exit */
476 IoFreeIrp(Irp);
477
479 }
480
481 /* Get a pointer to the SRB and IRP which were initially sent */
482 InitialSrb = *((PVOID *)(Srb+1));
483 InitialIrp = InitialSrb->OriginalRequest;
484
487 {
488 /* Sense data is OK */
490
491 /* Set length to be the same */
493 }
494
495 /* Make sure initial SRB's queue is frozen */
497
498 // The queue is frozen, but the SRB had a SRB_FLAGS_NO_QUEUE_FREEZE => unfreeze the queue
499 if ((InitialSrb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE) &&
500 (InitialSrb->SrbStatus & SRB_STATUS_QUEUE_FROZEN))
501 {
502 KIRQL irql;
503
504 KeAcquireSpinLock(&portExt->SpinLock, &irql);
505
507
508 lunExt->Flags &= ~LUNEX_FROZEN_QUEUE;
509 lunExt->Flags &= ~LUNEX_NEED_REQUEST_SENSE;
510
511 // SpiGetNextRequestFromLun releases the lock
512 SpiGetNextRequestFromLun(portExt, lunExt, &irql);
513
514 InitialSrb->SrbStatus &= ~SRB_STATUS_QUEUE_FROZEN;
515 }
516
517 /* Complete this request */
519
520 /* Deallocate everything (internal) */
522
523 if (Irp->MdlAddress != NULL)
524 {
525 MmUnlockPages(Irp->MdlAddress);
526 IoFreeMdl(Irp->MdlAddress);
527 Irp->MdlAddress = NULL;
528 }
529
530 IoFreeIrp(Irp);
532}
KIRQL irql
Definition: wave.h:1
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_FUNCTION_RESET_BUS
Definition: srb.h:326
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define IoFreeMdl
Definition: fxmdl.h:89
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68

◆ SpiStatusSrbToNt()

static NTSTATUS SpiStatusSrbToNt ( _In_ UCHAR  SrbStatus)
static

Definition at line 18 of file scsi.c.

20{
21 switch (SRB_STATUS(SrbStatus))
22 {
25 return STATUS_IO_TIMEOUT;
26
30
36
39
42
43 default:
45 }
46
48}
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:362
#define SRB_STATUS_NO_HBA
Definition: srb.h:356
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:363
#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH
Definition: srb.h:360
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS_BAD_FUNCTION
Definition: srb.h:364
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:351
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163

Referenced by SpiProcessCompletedRequest().

Variable Documentation

◆ SpiSenseCompletionRoutine

IO_COMPLETION_ROUTINE SpiSenseCompletionRoutine

Definition at line 453 of file scsi.c.

Referenced by SpiSendRequestSense().