3 * Copyright (C) 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/class2/class2.c
24 * PURPOSE: SCSI class driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
30 * - finish ScsiClassDeviceControl().
33 /* INCLUDES *****************************************************************/
35 #include <ddk/ntddk.h>
37 #include <ddk/class2.h>
43 #define VERSION "0.0.2"
45 #define TAG_SRBT TAG('S', 'r', 'b', 'T')
47 #define INQUIRY_DATA_SIZE 2048
48 #define START_UNIT_TIMEOUT 30
51 * Create a macro, which rounds up a size value to the next multiple of two.
53 #define SENSEINFO_ALIGNMENT 32
55 static NTSTATUS STDCALL
56 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject
,
59 static NTSTATUS STDCALL
60 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject
,
63 static NTSTATUS STDCALL
64 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject
,
67 static NTSTATUS STDCALL
68 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
72 ScsiClassRetryRequest (PDEVICE_OBJECT DeviceObject
,
74 PSCSI_REQUEST_BLOCK Srb
,
77 static NTSTATUS STDCALL
78 ScsiClassCheckVerifyCompletion (IN PDEVICE_OBJECT DeviceObject
,
82 /* FUNCTIONS ****************************************************************/
84 /**********************************************************************
89 * This function initializes the driver.
96 * System allocated Driver Object for this driver.
98 * Name of registry driver service key.
105 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
106 IN PUNICODE_STRING RegistryPath
)
108 DPRINT("Class Driver %s\n", VERSION
);
109 return(STATUS_SUCCESS
);
114 ScsiClassDebugPrint(IN ULONG DebugPrintLevel
,
115 IN PCHAR DebugMessage
,
122 if (DebugPrintLevel
> InternalDebugLevel
)
126 va_start(ap
, DebugMessage
);
127 vsprintf(Buffer
, DebugMessage
, ap
);
138 ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject
,
142 PCOMPLETION_CONTEXT CompletionContext
;
143 PSCSI_REQUEST_BLOCK Srb
;
145 CompletionContext
= (PCOMPLETION_CONTEXT
) Context
;
146 Srb
= &CompletionContext
->Srb
;
148 /* Release the queue if it is frozen */
149 if (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&&
150 Srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
)
152 ScsiClassReleaseQueue (CompletionContext
->DeviceObject
);
155 /* Release the completion context and the IRP */
156 if (Irp
->MdlAddress
!= NULL
)
158 MmUnlockPages (Irp
->MdlAddress
);
159 IoFreeMdl (Irp
->MdlAddress
);
160 Irp
->MdlAddress
= NULL
;
162 ExFreePool (CompletionContext
);
165 return STATUS_MORE_PROCESSING_REQUIRED
;
173 ScsiClassBuildRequest(IN PDEVICE_OBJECT DeviceObject
,
176 PDEVICE_EXTENSION DeviceExtension
;
177 PIO_STACK_LOCATION CurrentIrpStack
;
178 PIO_STACK_LOCATION NextIrpStack
;
179 LARGE_INTEGER StartingOffset
;
180 LARGE_INTEGER StartingBlock
;
181 PSCSI_REQUEST_BLOCK Srb
;
183 ULONG LogicalBlockAddress
;
184 USHORT TransferBlocks
;
186 DeviceExtension
= DeviceObject
->DeviceExtension
;
187 CurrentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
188 NextIrpStack
= IoGetNextIrpStackLocation(Irp
);
189 StartingOffset
= CurrentIrpStack
->Parameters
.Read
.ByteOffset
;
191 /* Calculate logical block address */
192 StartingBlock
.QuadPart
= StartingOffset
.QuadPart
>> DeviceExtension
->SectorShift
;
193 LogicalBlockAddress
= (ULONG
)StartingBlock
.u
.LowPart
;
195 DPRINT("Logical block address: %lu\n", LogicalBlockAddress
);
197 /* Allocate and initialize an SRB */
198 Srb
= ExAllocateFromNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
);
201 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
); //SCSI_REQUEST_BLOCK_SIZE;
202 Srb
->OriginalRequest
= Irp
;
203 Srb
->PathId
= DeviceExtension
->PathId
;
204 Srb
->TargetId
= DeviceExtension
->TargetId
;
205 Srb
->Lun
= DeviceExtension
->Lun
;
206 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
207 //FIXME: NT4 DDK sample uses MmGetMdlVirtualAddress! Why shouldn't we?
208 Srb
->DataBuffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
209 Srb
->DataTransferLength
= CurrentIrpStack
->Parameters
.Read
.Length
;
210 Srb
->QueueAction
= SRB_SIMPLE_TAG_REQUEST
;
211 Srb
->QueueSortKey
= LogicalBlockAddress
;
213 Srb
->SenseInfoBuffer
= (SENSE_DATA
*)ROUND_UP((ULONG_PTR
)(Srb
+ 1), SENSEINFO_ALIGNMENT
);
214 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
217 ((Srb
->DataTransferLength
+ 0xFFFF) >> 16) * DeviceExtension
->TimeOutValue
;
219 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
224 Cdb
= (PCDB
)Srb
->Cdb
;
226 /* Initialize ATAPI packet (12 bytes) */
230 Cdb
->CDB10
.LogicalUnitNumber
= DeviceExtension
->Lun
;
231 TransferBlocks
= (USHORT
)(CurrentIrpStack
->Parameters
.Read
.Length
>> DeviceExtension
->SectorShift
);
233 /* Copy little endian values into CDB in big endian format */
234 Cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte3
;
235 Cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte2
;
236 Cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte1
;
237 Cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte0
;
239 Cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)&TransferBlocks
)->Byte1
;
240 Cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)&TransferBlocks
)->Byte0
;
243 if (CurrentIrpStack
->MajorFunction
== IRP_MJ_READ
)
245 DPRINT("ScsiClassBuildRequest: Read Command\n");
247 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
248 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
252 DPRINT("ScsiClassBuildRequest: Write Command\n");
254 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
255 Cdb
->CDB10
.OperationCode
= SCSIOP_WRITE
;
259 /* if this is not a write-through request, then allow caching */
260 if (!(CurrentIrpStack
->Flags
& SL_WRITE_THROUGH
))
262 Srb
->SrbFlags
|= SRB_FLAGS_ADAPTER_CACHE_ENABLE
;
264 else if (DeviceExtension
->DeviceFlags
& DEV_WRITE_CACHE
)
266 /* if write caching is enable then force media access in the cdb */
267 Cdb
->CDB10
.ForceUnitAccess
= TRUE
;
271 /* Update srb flags */
272 Srb
->SrbFlags
|= DeviceExtension
->SrbFlags
;
274 /* Initialize next stack location */
275 NextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
276 NextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
278 /* Set retry count */
279 CurrentIrpStack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
281 DPRINT("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp
, Srb
);
282 IoSetCompletionRoutine(Irp
,
295 ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject
,
296 PSCSI_INQUIRY_DATA LunInfo
,
298 PDEVICE_OBJECT
*NewPortDeviceObject OPTIONAL
)
300 PIO_STACK_LOCATION IoStack
;
301 IO_STATUS_BLOCK IoStatusBlock
;
302 SCSI_REQUEST_BLOCK Srb
;
307 DPRINT("ScsiClassClaimDevice() called\n");
309 if (NewPortDeviceObject
!= NULL
)
310 *NewPortDeviceObject
= NULL
;
312 /* initialize an SRB */
314 sizeof(SCSI_REQUEST_BLOCK
));
315 Srb
.Length
= SCSI_REQUEST_BLOCK_SIZE
;
316 Srb
.PathId
= LunInfo
->PathId
;
317 Srb
.TargetId
= LunInfo
->TargetId
;
318 Srb
.Lun
= LunInfo
->Lun
;
320 (Release
== TRUE
) ? SRB_FUNCTION_RELEASE_DEVICE
: SRB_FUNCTION_CLAIM_DEVICE
;
322 KeInitializeEvent(&Event
,
326 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE
,
337 DPRINT("Failed to allocate Irp!\n");
338 return(STATUS_INSUFFICIENT_RESOURCES
);
341 /* Link Srb and Irp */
342 IoStack
= IoGetNextIrpStackLocation(Irp
);
343 IoStack
->Parameters
.Scsi
.Srb
= &Srb
;
344 Srb
.OriginalRequest
= Irp
;
346 /* Call SCSI port driver */
347 Status
= IoCallDriver(PortDeviceObject
,
349 if (Status
== STATUS_PENDING
)
351 KeWaitForSingleObject(&Event
,
356 Status
= IoStatusBlock
.Status
;
361 ObDereferenceObject(PortDeviceObject
);
362 return(STATUS_SUCCESS
);
365 // Status = ObReferenceObjectByPointer(Srb.DataBuffer,
366 Status
= ObReferenceObjectByPointer(PortDeviceObject
,
371 if (NewPortDeviceObject
!= NULL
)
373 // *NewPortDeviceObject = Srb.DataBuffer;
374 *NewPortDeviceObject
= PortDeviceObject
;
377 return(STATUS_SUCCESS
);
385 ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
386 IN PCCHAR ObjectNameBuffer
,
387 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
388 IN OUT PDEVICE_OBJECT
*DeviceObject
,
389 IN PCLASS_INIT_DATA InitializationData
)
391 PDEVICE_OBJECT InternalDeviceObject
;
392 PDEVICE_EXTENSION DeviceExtension
;
393 ANSI_STRING AnsiName
;
394 UNICODE_STRING DeviceName
;
397 DPRINT("ScsiClassCreateDeviceObject() called\n");
399 *DeviceObject
= NULL
;
401 RtlInitAnsiString(&AnsiName
,
404 Status
= RtlAnsiStringToUnicodeString(&DeviceName
,
407 if (!NT_SUCCESS(Status
))
412 DPRINT("Device name: '%wZ'\n", &DeviceName
);
414 Status
= IoCreateDevice(DriverObject
,
415 InitializationData
->DeviceExtensionSize
,
417 InitializationData
->DeviceType
,
418 InitializationData
->DeviceCharacteristics
,
420 &InternalDeviceObject
);
421 if (NT_SUCCESS(Status
))
423 DeviceExtension
= InternalDeviceObject
->DeviceExtension
;
425 DeviceExtension
->ClassError
= InitializationData
->ClassError
;
426 DeviceExtension
->ClassReadWriteVerification
= InitializationData
->ClassReadWriteVerification
;
427 DeviceExtension
->ClassFindDevices
= InitializationData
->ClassFindDevices
;
428 DeviceExtension
->ClassDeviceControl
= InitializationData
->ClassDeviceControl
;
429 DeviceExtension
->ClassShutdownFlush
= InitializationData
->ClassShutdownFlush
;
430 DeviceExtension
->ClassCreateClose
= InitializationData
->ClassCreateClose
;
431 DeviceExtension
->ClassStartIo
= InitializationData
->ClassStartIo
;
433 DeviceExtension
->MediaChangeCount
= 0;
435 if (PhysicalDeviceObject
!= NULL
)
437 DeviceExtension
->PhysicalDevice
= PhysicalDeviceObject
;
441 DeviceExtension
->PhysicalDevice
= InternalDeviceObject
;
444 *DeviceObject
= InternalDeviceObject
;
447 RtlFreeUnicodeString(&DeviceName
);
457 ScsiClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
460 PDEVICE_EXTENSION DeviceExtension
;
461 PIO_STACK_LOCATION NextStack
;
462 PIO_STACK_LOCATION Stack
;
464 ULONG InputBufferLength
;
465 ULONG OutputBufferLength
;
466 ULONG ModifiedControlCode
;
467 PSCSI_REQUEST_BLOCK Srb
;
471 DPRINT("ScsiClassDeviceControl() called\n");
473 DeviceExtension
= DeviceObject
->DeviceExtension
;
474 Stack
= IoGetCurrentIrpStackLocation(Irp
);
476 IoControlCode
= Stack
->Parameters
.DeviceIoControl
.IoControlCode
;
477 InputBufferLength
= Stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
478 OutputBufferLength
= Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
480 if (IoControlCode
== IOCTL_SCSI_GET_DUMP_POINTERS
)
482 PDUMP_POINTERS DumpPointers
;
484 if (OutputBufferLength
< sizeof(DUMP_POINTERS
))
486 Irp
->IoStatus
.Information
= 0;
487 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
488 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
490 return(STATUS_BUFFER_TOO_SMALL
);
492 DumpPointers
= (PDUMP_POINTERS
)Irp
->AssociatedIrp
.SystemBuffer
;
494 /* Initialize next stack location for call to the port driver */
495 NextStack
= IoGetNextIrpStackLocation(Irp
);
497 NextStack
->Parameters
= Stack
->Parameters
;
498 NextStack
->MajorFunction
= Stack
->MajorFunction
;
499 NextStack
->MinorFunction
= Stack
->MinorFunction
;
501 /* Call port driver */
502 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
505 if (IoControlCode
== IOCTL_SCSI_GET_ADDRESS
)
507 PSCSI_ADDRESS ScsiAddress
;
509 if (OutputBufferLength
< sizeof(SCSI_ADDRESS
))
511 Irp
->IoStatus
.Information
= 0;
512 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
513 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
515 return(STATUS_BUFFER_TOO_SMALL
);
518 ScsiAddress
= Irp
->AssociatedIrp
.SystemBuffer
;
519 ScsiAddress
->Length
= sizeof(SCSI_ADDRESS
);
520 ScsiAddress
->PortNumber
= DeviceExtension
->PortNumber
;
521 ScsiAddress
->PathId
= DeviceExtension
->PathId
;
522 ScsiAddress
->TargetId
= DeviceExtension
->TargetId
;
523 ScsiAddress
->Lun
= DeviceExtension
->Lun
;
525 Irp
->IoStatus
.Information
= sizeof(SCSI_ADDRESS
);
526 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
527 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
529 return(STATUS_SUCCESS
);
532 if (IoControlCode
== IOCTL_SCSI_PASS_THROUGH
||
533 IoControlCode
== IOCTL_SCSI_PASS_THROUGH_DIRECT
)
535 PSCSI_PASS_THROUGH ScsiPassThrough
;
537 DPRINT("IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
539 /* Check input size */
540 if (InputBufferLength
< sizeof(SCSI_PASS_THROUGH
))
542 Irp
->IoStatus
.Information
= 0;
543 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
544 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
545 return(STATUS_INVALID_PARAMETER
);
548 /* Initialize next stack location for call to the port driver */
549 NextStack
= IoGetNextIrpStackLocation(Irp
);
551 ScsiPassThrough
= Irp
->AssociatedIrp
.SystemBuffer
;
552 ScsiPassThrough
->PathId
= DeviceExtension
->PathId
;
553 ScsiPassThrough
->TargetId
= DeviceExtension
->TargetId
;
554 ScsiPassThrough
->Lun
= DeviceExtension
->Lun
;
555 ScsiPassThrough
->Cdb
[1] |= DeviceExtension
->Lun
<< 5;
557 NextStack
->Parameters
= Stack
->Parameters
;
558 NextStack
->MajorFunction
= Stack
->MajorFunction
;
559 NextStack
->MinorFunction
= Stack
->MinorFunction
;
561 /* Call port driver */
562 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
566 /* Allocate and initialize an SRB */
567 Srb
= ExAllocateFromNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
);
571 Irp
->IoStatus
.Information
= 0;
572 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
573 IoCompleteRequest(Irp
,
575 return(STATUS_INSUFFICIENT_RESOURCES
);
578 /* Initialize the SRB */
580 sizeof(SCSI_REQUEST_BLOCK
));
581 Cdb
= (PCDB
)Srb
->Cdb
;
583 ModifiedControlCode
= (IoControlCode
& 0x0000FFFF) | (IOCTL_DISK_BASE
<< 16);
584 switch (ModifiedControlCode
)
586 case IOCTL_DISK_CHECK_VERIFY
:
587 DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY\n");
589 if (OutputBufferLength
!= 0)
591 if (OutputBufferLength
< sizeof(ULONG
))
593 DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY SMALL\n");
594 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
595 Irp
->IoStatus
.Information
= 0;
597 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
599 IoCompleteRequest (Irp
,
601 return STATUS_BUFFER_TOO_SMALL
;
604 /* Allocate new IRP for TEST UNIT READY scsi command */
605 SubIrp
= IoAllocateIrp ((CCHAR
)DeviceObject
->StackSize
+ 3,
609 DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY NotEnuf\n");
610 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
611 Irp
->IoStatus
.Information
= 0;
613 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
615 IoCompleteRequest (Irp
,
617 return STATUS_INSUFFICIENT_RESOURCES
;
620 SubIrp
->Tail
.Overlay
.Thread
= Irp
->Tail
.Overlay
.Thread
;
621 IoSetNextIrpStackLocation (SubIrp
);
623 NextStack
= IoGetCurrentIrpStackLocation (SubIrp
);
624 NextStack
->Parameters
.Others
.Argument1
= Irp
;
625 NextStack
->DeviceObject
= DeviceObject
;
627 IoSetCompletionRoutine (SubIrp
,
628 ScsiClassCheckVerifyCompletion
,
634 DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY IoSet\n");
636 IoSetNextIrpStackLocation (SubIrp
);
637 NextStack
= IoGetCurrentIrpStackLocation (SubIrp
);
638 NextStack
->DeviceObject
= DeviceObject
;
640 IoMarkIrpPending (Irp
);
645 /* Initialize SRB operation */
647 Srb
->TimeOutValue
= DeviceExtension
->TimeOutValue
;
648 Cdb
->CDB6GENERIC
.OperationCode
= SCSIOP_TEST_UNIT_READY
;
650 DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY SrbAsync\n");
652 return(ScsiClassSendSrbAsynchronous(DeviceObject
,
660 DPRINT("Unknown device io control code %lx\n",
661 ModifiedControlCode
);
663 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
665 /* Pass the IOCTL down to the port driver */
666 NextStack
= IoGetNextIrpStackLocation(Irp
);
667 NextStack
->Parameters
= Stack
->Parameters
;
668 NextStack
->MajorFunction
= Stack
->MajorFunction
;
669 NextStack
->MinorFunction
= Stack
->MinorFunction
;
671 /* Call port driver */
672 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
676 Irp
->IoStatus
.Information
= 0;
677 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
678 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
680 return(STATUS_UNSUCCESSFUL
);
688 ScsiClassFindModePage(IN PCHAR ModeSenseBuffer
,
693 ULONG DescriptorLength
;
698 DPRINT("ScsiClassFindModePage() called\n");
700 /* Get header length */
701 HeaderLength
= (Use6Byte
) ? sizeof(MODE_PARAMETER_HEADER
) : sizeof(MODE_PARAMETER_HEADER10
);
703 /* Check header length */
704 if (Length
< HeaderLength
)
707 /* Get descriptor length */
708 if (Use6Byte
== TRUE
)
710 DescriptorLength
= ((PMODE_PARAMETER_HEADER
)ModeSenseBuffer
)->BlockDescriptorLength
;
714 DescriptorLength
= ((PMODE_PARAMETER_HEADER10
)ModeSenseBuffer
)->BlockDescriptorLength
[1];
717 /* Set page pointers */
718 Ptr
= ModeSenseBuffer
+ HeaderLength
+ DescriptorLength
;
719 End
= ModeSenseBuffer
+ Length
;
721 /* Search for page */
724 /* Check page code */
725 if (((PMODE_DISCONNECT_PAGE
)Ptr
)->PageCode
== PageMode
)
728 /* Skip to next page */
729 Ptr
+= ((PMODE_DISCONNECT_PAGE
)Ptr
)->PageLength
;
740 ScsiClassFindUnclaimedDevices(IN PCLASS_INIT_DATA InitializationData
,
741 IN PSCSI_ADAPTER_BUS_INFO AdapterInformation
)
743 PSCSI_INQUIRY_DATA UnitInfo
;
744 PINQUIRYDATA InquiryData
;
747 ULONG UnclaimedDevices
= 0;
749 DPRINT("ScsiClassFindUnclaimedDevices() called\n");
751 DPRINT("NumberOfBuses: %lu\n",AdapterInformation
->NumberOfBuses
);
752 Buffer
= (PUCHAR
)AdapterInformation
;
753 for (Bus
= 0; Bus
< (ULONG
)AdapterInformation
->NumberOfBuses
; Bus
++)
755 DPRINT("Searching bus %lu\n", Bus
);
757 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterInformation
->BusData
[Bus
].InquiryDataOffset
);
759 while (AdapterInformation
->BusData
[Bus
].InquiryDataOffset
)
761 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
763 DPRINT("Device: '%.8s'\n", InquiryData
->VendorId
);
765 if ((InitializationData
->ClassFindDeviceCallBack(InquiryData
) == TRUE
) &&
766 (UnitInfo
->DeviceClaimed
== FALSE
))
771 if (UnitInfo
->NextInquiryDataOffset
== 0)
774 UnitInfo
= (PSCSI_INQUIRY_DATA
) (Buffer
+ UnitInfo
->NextInquiryDataOffset
);
778 return(UnclaimedDevices
);
786 ScsiClassGetCapabilities(IN PDEVICE_OBJECT PortDeviceObject
,
787 OUT PIO_SCSI_CAPABILITIES
*PortCapabilities
)
789 IO_STATUS_BLOCK IoStatusBlock
;
794 KeInitializeEvent(&Event
,
798 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES
,
809 return(STATUS_INSUFFICIENT_RESOURCES
);
812 Status
= IoCallDriver(PortDeviceObject
,
814 if (Status
== STATUS_PENDING
)
816 KeWaitForSingleObject(&Event
,
821 Status
= IoStatusBlock
.Status
;
824 DPRINT("PortCapabilities at %p\n", *PortCapabilities
);
834 ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject
,
835 IN PSCSI_ADAPTER_BUS_INFO
*ConfigInfo
)
837 PSCSI_ADAPTER_BUS_INFO Buffer
;
838 IO_STATUS_BLOCK IoStatusBlock
;
843 DPRINT("ScsiClassGetInquiryData() called\n");
846 Buffer
= ExAllocatePool(NonPagedPool
,
850 return(STATUS_INSUFFICIENT_RESOURCES
);
853 KeInitializeEvent(&Event
,
857 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA
,
869 return(STATUS_INSUFFICIENT_RESOURCES
);
872 Status
= IoCallDriver(PortDeviceObject
,
874 if (Status
== STATUS_PENDING
)
876 KeWaitForSingleObject(&Event
,
881 Status
= IoStatusBlock
.Status
;
884 if (!NT_SUCCESS(Status
))
890 *ConfigInfo
= Buffer
;
893 DPRINT("ScsiClassGetInquiryData() done\n");
903 ScsiClassInitialize(IN PVOID Argument1
,
905 IN PCLASS_INIT_DATA InitializationData
)
907 PCONFIGURATION_INFORMATION ConfigInfo
;
908 PDRIVER_OBJECT DriverObject
= Argument1
;
909 WCHAR NameBuffer
[80];
910 UNICODE_STRING PortName
;
912 PDEVICE_OBJECT PortDeviceObject
;
913 PFILE_OBJECT FileObject
;
914 BOOLEAN DiskFound
= FALSE
;
917 DPRINT("ScsiClassInitialize() called!\n");
919 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiClassCreateClose
;
920 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiClassCreateClose
;
921 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScsiClassReadWrite
;
922 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScsiClassReadWrite
;
923 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiClassInternalIoControl
;
924 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiClassDeviceDispatch
;
925 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = ScsiClassShutdownFlush
;
926 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = ScsiClassShutdownFlush
;
927 if (InitializationData
->ClassStartIo
)
929 DriverObject
->DriverStartIo
= InitializationData
->ClassStartIo
;
932 ConfigInfo
= IoGetConfigurationInformation();
934 DPRINT("ScsiPorts: %lu\n", ConfigInfo
->ScsiPortCount
);
936 /* look for ScsiPortX scsi port devices */
937 for (PortNumber
= 0; PortNumber
< ConfigInfo
->ScsiPortCount
; PortNumber
++)
940 L
"\\Device\\ScsiPort%lu",
942 RtlInitUnicodeString(&PortName
,
944 DPRINT("Checking scsi port %ld\n", PortNumber
);
945 Status
= IoGetDeviceObjectPointer(&PortName
,
946 FILE_READ_ATTRIBUTES
,
949 DPRINT("Status 0x%08lX\n", Status
);
950 if (NT_SUCCESS(Status
))
952 DPRINT("ScsiPort%lu found.\n", PortNumber
);
954 /* check scsi port for attached disk drives */
955 if (InitializationData
->ClassFindDevices(DriverObject
,
966 DbgPrint("Couldn't find ScsiPort%lu (Status %lx)\n", PortNumber
, Status
);
970 DPRINT("ScsiClassInitialize() done!\n");
972 return((DiskFound
== TRUE
) ? STATUS_SUCCESS
: STATUS_NO_SUCH_DEVICE
);
976 /**********************************************************************
978 * ScsiClassInitializeSrbLookasideList
981 * Initializes a lookaside list for SRBs.
988 * Class specific device extension.
991 * Maximum number of elements of the lookaside list.
999 ScsiClassInitializeSrbLookasideList(IN PDEVICE_EXTENSION DeviceExtension
,
1000 IN ULONG NumberElements
)
1002 ExInitializeNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
1006 sizeof(SCSI_REQUEST_BLOCK
) + sizeof(SENSE_DATA
) + SENSEINFO_ALIGNMENT
- 1,
1008 (USHORT
)NumberElements
);
1016 ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject
,
1019 DPRINT("ScsiClassInternalIoContol() called\n");
1021 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1022 Irp
->IoStatus
.Information
= 0;
1023 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1025 return(STATUS_SUCCESS
);
1030 * Implements part of the directives on:
1031 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/other_c694d732-fa95-4841-8d61-2a55ee787905.xml.asp
1034 ScsiClassInvalidateMedia(IN PDEVICE_OBJECT DeviceObject
,
1035 OUT NTSTATUS
*Status
)
1037 PDEVICE_EXTENSION DeviceExtension
;
1038 PDEVICE_EXTENSION PhysicalExtension
;
1040 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1041 PhysicalExtension
= (PDEVICE_EXTENSION
)DeviceExtension
->PhysicalDevice
->DeviceExtension
;
1043 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1045 DPRINT("Invalidate: test char yields TRUE\n");
1049 DPRINT("Invalidate: test char yields FALSE\n");
1052 if ((DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) &&
1053 (DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
1055 DPRINT("Set DO_VERIFY_VOLUME\n");
1056 DeviceObject
->Flags
|= DO_VERIFY_VOLUME
;
1057 *Status
= STATUS_VERIFY_REQUIRED
;
1061 *Status
= STATUS_IO_DEVICE_ERROR
;
1064 /* Increment the media change count */
1065 PhysicalExtension
->MediaChangeCount
++;
1073 ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject
,
1074 IN PSCSI_REQUEST_BLOCK Srb
,
1075 IN UCHAR MajorFunctionCode
,
1076 IN ULONG IoDeviceCode
,
1077 IN ULONG RetryCount
,
1078 OUT NTSTATUS
*Status
)
1080 PDEVICE_EXTENSION DeviceExtension
;
1081 PDEVICE_EXTENSION PhysicalExtension
;
1083 PIO_ERROR_LOG_PACKET LogPacket
;
1085 PSENSE_DATA SenseData
;
1089 DPRINT("ScsiClassInterpretSenseInfo() called\n");
1091 DPRINT("Srb->SrbStatus %lx\n", Srb
->SrbStatus
);
1093 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_PENDING
)
1095 *Status
= STATUS_SUCCESS
;
1099 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1100 PhysicalExtension
= (PDEVICE_EXTENSION
)DeviceExtension
->PhysicalDevice
->DeviceExtension
;
1101 SenseData
= Srb
->SenseInfoBuffer
;
1105 if ((Srb
->SrbStatus
& SRB_STATUS_AUTOSENSE_VALID
) &&
1106 (Srb
->SenseInfoBufferLength
> 0))
1108 /* Got valid sense data, interpret them */
1110 DPRINT("ErrorCode: %x\n", SenseData
->ErrorCode
);
1111 DPRINT("SenseKey: %x\n", SenseData
->SenseKey
);
1112 DPRINT("SenseCode: %x\n", SenseData
->AdditionalSenseCode
);
1114 switch (SenseData
->SenseKey
& 0xf)
1116 case SCSI_SENSE_NO_SENSE
:
1117 DPRINT("SCSI_SENSE_NO_SENSE\n");
1118 if (SenseData
->IncorrectLength
)
1120 DPRINT("Incorrect block length\n");
1121 *Status
= STATUS_INVALID_BLOCK_LENGTH
;
1126 DPRINT("Unspecified error\n");
1127 *Status
= STATUS_IO_DEVICE_ERROR
;
1132 case SCSI_SENSE_RECOVERED_ERROR
:
1133 DPRINT("SCSI_SENSE_RECOVERED_ERROR\n");
1134 *Status
= STATUS_SUCCESS
;
1138 case SCSI_SENSE_NOT_READY
:
1139 DPRINT("SCSI_SENSE_NOT_READY\n");
1140 *Status
= STATUS_DEVICE_NOT_READY
;
1141 switch (SenseData
->AdditionalSenseCode
)
1143 case SCSI_ADSENSE_LUN_NOT_READY
:
1144 DPRINT("SCSI_ADSENSE_LUN_NOT_READY\n");
1147 case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
:
1148 DPRINT("SCSI_ADSENSE_NO_MEDIA_IN_DEVICE\n");
1149 ScsiClassInvalidateMedia(DeviceObject
,
1152 *Status
= STATUS_NO_MEDIA_IN_DEVICE
;
1155 if((DeviceExtension
->MediaChangeEvent
!= NULL
) &&
1156 (!DeviceExtension
->MediaChangeEvent
))
1158 KeSetEvent(DeviceExtension
->MediaChangeEvent
,
1161 DeviceExtension
->MediaChangeNoMedia
= TRUE
;
1167 case SCSI_SENSE_MEDIUM_ERROR
:
1168 DPRINT("SCSI_SENSE_MEDIUM_ERROR\n");
1169 *Status
= STATUS_DEVICE_DATA_ERROR
;
1173 case SCSI_SENSE_HARDWARE_ERROR
:
1174 DPRINT("SCSI_SENSE_HARDWARE_ERROR\n");
1175 *Status
= STATUS_IO_DEVICE_ERROR
;
1178 case SCSI_SENSE_ILLEGAL_REQUEST
:
1179 DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
1180 *Status
= STATUS_INVALID_DEVICE_REQUEST
;
1181 switch (SenseData
->AdditionalSenseCode
)
1183 case SCSI_ADSENSE_ILLEGAL_COMMAND
:
1184 DPRINT("SCSI_ADSENSE_ILLEGAL_COMMAND\n");
1188 case SCSI_ADSENSE_ILLEGAL_BLOCK
:
1189 DPRINT("SCSI_ADSENSE_ILLEGAL_BLOCK\n");
1190 *Status
= STATUS_NONEXISTENT_SECTOR
;
1194 case SCSI_ADSENSE_INVALID_LUN
:
1195 DPRINT("SCSI_ADSENSE_INVALID_LUN\n");
1196 *Status
= STATUS_NO_SUCH_DEVICE
;
1200 case SCSI_ADSENSE_MUSIC_AREA
:
1201 DPRINT("SCSI_ADSENSE_MUSIC_AREA\n");
1205 case SCSI_ADSENSE_DATA_AREA
:
1206 DPRINT("SCSI_ADSENSE_DATA_AREA\n");
1210 case SCSI_ADSENSE_VOLUME_OVERFLOW
:
1211 DPRINT("SCSI_ADSENSE_VOLUME_OVERFLOW\n");
1215 case SCSI_ADSENSE_INVALID_CDB
:
1216 DPRINT("SCSI_ADSENSE_INVALID_CDB\n");
1222 case SCSI_SENSE_UNIT_ATTENTION
:
1223 DPRINT("SCSI_SENSE_UNIT_ATTENTION\n");
1224 switch (SenseData
->AdditionalSenseCode
)
1226 case SCSI_ADSENSE_MEDIUM_CHANGED
:
1227 DPRINT("SCSI_ADSENSE_MEDIUM_CHANGED\n");
1228 if(DeviceExtension
->MediaChangeEvent
!= NULL
)
1230 KeSetEvent(DeviceExtension
->MediaChangeEvent
,
1233 DeviceExtension
->MediaChangeNoMedia
= FALSE
;
1237 case SCSI_ADSENSE_BUS_RESET
:
1238 DPRINT("SCSI_ADSENSE_BUS_RESET\n");
1242 DPRINT("Unit attention\n");
1246 ScsiClassInvalidateMedia(DeviceObject
,
1251 case SCSI_SENSE_DATA_PROTECT
:
1252 DPRINT("SCSI_SENSE_DATA_PROTECT\n");
1253 *Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1257 case SCSI_SENSE_ABORTED_COMMAND
:
1258 DPRINT("SCSI_SENSE_ABORTED_COMMAND\n");
1259 *Status
= STATUS_IO_DEVICE_ERROR
;
1263 DPRINT("SCSI error (sense key: %x)\n",
1264 SenseData
->SenseKey
& 0xf);
1265 *Status
= STATUS_IO_DEVICE_ERROR
;
1271 /* Got no or invalid sense data, return generic error codes */
1272 switch (SRB_STATUS(Srb
->SrbStatus
))
1274 /* FIXME: add more srb status codes */
1276 case SRB_STATUS_INVALID_PATH_ID
:
1277 case SRB_STATUS_INVALID_TARGET_ID
:
1278 case SRB_STATUS_INVALID_LUN
:
1279 case SRB_STATUS_NO_DEVICE
:
1280 case SRB_STATUS_NO_HBA
:
1281 *Status
= STATUS_NO_SUCH_DEVICE
;
1285 case SRB_STATUS_BUSY
:
1286 *Status
= STATUS_DEVICE_BUSY
;
1290 case SRB_STATUS_DATA_OVERRUN
:
1291 *Status
= STATUS_DATA_OVERRUN
;
1295 case SRB_STATUS_INVALID_REQUEST
:
1296 *Status
= STATUS_INVALID_DEVICE_REQUEST
;
1301 DPRINT("SCSI error (SRB status: %x)\n",
1302 SRB_STATUS(Srb
->SrbStatus
));
1304 *Status
= STATUS_IO_DEVICE_ERROR
;
1309 /* Call the class driver specific error function */
1310 if (DeviceExtension
->ClassError
!= NULL
)
1312 DeviceExtension
->ClassError(DeviceObject
,
1318 if (LogError
== TRUE
)
1321 /* Allocate error packet */
1322 LogPacket
= IoAllocateErrorLogEntry (DeviceObject
,
1323 sizeof(IO_ERROR_LOG_PACKET
) +
1325 if (LogPacket
== NULL
)
1327 DPRINT ("Failed to allocate a log packet!\n");
1331 /* Initialize error packet */
1332 LogPacket
->MajorFunctionCode
= MajorFunctionCode
;
1333 LogPacket
->RetryCount
= (UCHAR
)RetryCount
;
1334 LogPacket
->DumpDataSize
= 6 * sizeof(ULONG
);
1335 LogPacket
->ErrorCode
= 0; /* FIXME */
1336 LogPacket
->FinalStatus
= *Status
;
1337 LogPacket
->IoControlCode
= IoDeviceCode
;
1338 LogPacket
->DeviceOffset
.QuadPart
= 0; /* FIXME */
1339 LogPacket
->DumpData
[0] = Srb
->PathId
;
1340 LogPacket
->DumpData
[1] = Srb
->TargetId
;
1341 LogPacket
->DumpData
[2] = Srb
->Lun
;
1342 LogPacket
->DumpData
[3] = 0;
1343 LogPacket
->DumpData
[4] = (Srb
->SrbStatus
<< 8) | Srb
->ScsiStatus
;
1344 if (SenseData
!= NULL
)
1346 LogPacket
->DumpData
[5] = (SenseData
->SenseKey
<< 16) |
1347 (SenseData
->AdditionalSenseCode
<< 8) |
1348 SenseData
->AdditionalSenseCodeQualifier
;
1351 /* Write error packet */
1352 IoWriteErrorLogEntry (LogPacket
);
1356 DPRINT("ScsiClassInterpretSenseInfo() done\n");
1366 ScsiClassIoComplete(IN PDEVICE_OBJECT DeviceObject
,
1370 PDEVICE_EXTENSION DeviceExtension
;
1371 PIO_STACK_LOCATION IrpStack
;
1372 PSCSI_REQUEST_BLOCK Srb
;
1376 DPRINT("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n",
1377 DeviceObject
, Irp
, Context
);
1379 DeviceExtension
= DeviceObject
->DeviceExtension
;
1381 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1384 * BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
1385 * Must pass Srb as Context arg!! See comment about Completion routines in
1386 * IofCallDriver for more info.
1389 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
1391 DPRINT("Srb %p\n", Srb
);
1393 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
1395 Status
= STATUS_SUCCESS
;
1399 /* Release the queue if it is frozen */
1400 if (Srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
)
1402 ScsiClassReleaseQueue (DeviceObject
);
1405 /* Get more detailed status information */
1406 Retry
= ScsiClassInterpretSenseInfo(DeviceObject
,
1408 IrpStack
->MajorFunction
,
1410 MAXIMUM_RETRIES
- ((ULONG
)IrpStack
->Parameters
.Others
.Argument4
),
1413 /* Retry the request if verify should be overridden */
1414 if ((IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
) &&
1415 Status
== STATUS_VERIFY_REQUIRED
)
1417 Status
= STATUS_IO_DEVICE_ERROR
;
1421 /* Retry the request */
1423 ((ULONG_PTR
)IrpStack
->Parameters
.Others
.Argument4
> 0))
1425 IrpStack
->Parameters
.Others
.Argument4
= (PVOID
) ((ULONG_PTR
)IrpStack
->Parameters
.Others
.Argument4
- 1);
1427 ScsiClassRetryRequest(DeviceObject
,
1432 return(STATUS_MORE_PROCESSING_REQUIRED
);
1437 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
1440 Irp
->IoStatus
.Status
= Status
;
1441 if (!NT_SUCCESS(Status
))
1443 Irp
->IoStatus
.Information
= 0;
1444 if (IoIsErrorUserInduced(Status
))
1446 IoSetHardErrorOrVerifyDevice(Irp
,
1451 if (Irp
->PendingReturned
)
1453 IoMarkIrpPending (Irp
);
1456 if (DeviceExtension
->ClassStartIo
!= NULL
)
1458 if (IrpStack
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
)
1461 oldIrql
= KeGetCurrentIrql();
1462 if (oldIrql
< DISPATCH_LEVEL
)
1464 KeRaiseIrql (DISPATCH_LEVEL
, &oldIrql
);
1465 IoStartNextPacket (DeviceObject
, FALSE
);
1466 KeLowerIrql(oldIrql
);
1470 IoStartNextPacket (DeviceObject
, FALSE
);
1475 DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status
);
1485 ScsiClassIoCompleteAssociated(IN PDEVICE_OBJECT DeviceObject
,
1489 PDEVICE_EXTENSION DeviceExtension
;
1490 PIO_STACK_LOCATION IrpStack
;
1491 PSCSI_REQUEST_BLOCK Srb
;
1497 DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n",
1498 DeviceObject
, Irp
, Context
);
1500 MasterIrp
= Irp
->AssociatedIrp
.MasterIrp
;
1501 DeviceExtension
= DeviceObject
->DeviceExtension
;
1503 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1506 * BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
1507 * Must pass Srb as Context arg!! See comment about Completion routines in
1508 * IofCallDriver for more info.
1511 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
1513 DPRINT("Srb %p\n", Srb
);
1515 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
1517 Status
= STATUS_SUCCESS
;
1521 /* Release the queue if it is frozen */
1522 if (Srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
)
1524 ScsiClassReleaseQueue (DeviceObject
);
1527 /* Get more detailed status information */
1528 Retry
= ScsiClassInterpretSenseInfo(DeviceObject
,
1530 IrpStack
->MajorFunction
,
1532 MAXIMUM_RETRIES
- ((ULONG
)IrpStack
->Parameters
.Others
.Argument4
),
1535 /* Retry the request if verify should be overridden */
1536 if ((IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
) &&
1537 Status
== STATUS_VERIFY_REQUIRED
)
1539 Status
= STATUS_IO_DEVICE_ERROR
;
1543 /* Retry the request */
1545 ((ULONG_PTR
)IrpStack
->Parameters
.Others
.Argument4
> 0))
1547 IrpStack
->Parameters
.Others
.Argument4
= (PVOID
) ((ULONG_PTR
)IrpStack
->Parameters
.Others
.Argument4
- 1);
1549 ScsiClassRetryRequest(DeviceObject
,
1554 return(STATUS_MORE_PROCESSING_REQUIRED
);
1559 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
1562 Irp
->IoStatus
.Status
= Status
;
1564 IrpStack
= IoGetNextIrpStackLocation(MasterIrp
);
1565 if (!NT_SUCCESS(Status
))
1567 MasterIrp
->IoStatus
.Status
= Status
;
1568 MasterIrp
->IoStatus
.Information
= 0;
1570 if (IoIsErrorUserInduced(Status
))
1572 IoSetHardErrorOrVerifyDevice(MasterIrp
,
1577 /* Decrement the request counter in the Master IRP */
1578 RequestCount
= InterlockedDecrement((PLONG
)&IrpStack
->Parameters
.Others
.Argument1
);
1580 if (RequestCount
== 0)
1582 /* Complete the Master IRP */
1583 IoCompleteRequest(MasterIrp
,
1586 if (DeviceExtension
->ClassStartIo
)
1589 oldIrql
= KeGetCurrentIrql();
1590 if (oldIrql
< DISPATCH_LEVEL
)
1592 KeRaiseIrql (DISPATCH_LEVEL
, &oldIrql
);
1593 IoStartNextPacket (DeviceObject
, FALSE
);
1594 KeLowerIrql(oldIrql
);
1598 IoStartNextPacket (DeviceObject
, FALSE
);
1603 /* Free the current IRP */
1606 return(STATUS_MORE_PROCESSING_REQUIRED
);
1614 ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject
,
1615 IN PCHAR ModeSenseBuffer
,
1619 PDEVICE_EXTENSION DeviceExtension
;
1620 SCSI_REQUEST_BLOCK Srb
;
1625 DPRINT("ScsiClassModeSense() called\n");
1627 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1630 /* Initialize the SRB */
1631 RtlZeroMemory (&Srb
,
1632 sizeof(SCSI_REQUEST_BLOCK
));
1634 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
1636 /* Initialize the CDB */
1637 Cdb
= (PCDB
)&Srb
.Cdb
;
1638 Cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
1639 Cdb
->MODE_SENSE
.PageCode
= PageMode
;
1640 Cdb
->MODE_SENSE
.AllocationLength
= (UCHAR
)Length
;
1643 Status
= ScsiClassSendSrbSynchronous (DeviceObject
,
1648 if (Status
== STATUS_VERIFY_REQUIRED
)
1650 if (RetryCount
!= 0)
1656 else if (SRB_STATUS(Srb
.SrbStatus
) == SRB_STATUS_DATA_OVERRUN
)
1658 Status
= STATUS_SUCCESS
;
1661 if (!NT_SUCCESS(Status
))
1666 return Srb
.DataTransferLength
;
1674 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath
)
1676 PRTL_QUERY_REGISTRY_TABLE Table
;
1683 if (RegistryPath
== NULL
)
1691 /* Allocate zero-terminated path string */
1692 Size
= RegistryPath
->Length
+ sizeof(WCHAR
);
1693 Path
= (PWSTR
)ExAllocatePool (NonPagedPool
,
1699 RtlZeroMemory (Path
,
1701 RtlCopyMemory (Path
,
1702 RegistryPath
->Buffer
,
1703 Size
- sizeof(WCHAR
));
1705 /* Allocate query table */
1706 Size
= sizeof(RTL_QUERY_REGISTRY_TABLE
) * 2;
1707 Table
= (PRTL_QUERY_REGISTRY_TABLE
)ExAllocatePool (NonPagedPool
,
1714 RtlZeroMemory (Table
,
1717 Table
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1718 Table
[0].Name
= L
"TimeOutValue";
1719 Table
[0].EntryContext
= &TimeOutValue
;
1720 Table
[0].DefaultType
= REG_DWORD
;
1721 Table
[0].DefaultData
= &ZeroTimeOut
;
1722 Table
[0].DefaultLength
= sizeof(ULONG
);
1724 Status
= RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
,
1729 if (!NT_SUCCESS(Status
))
1731 DPRINT("RtlQueryRegistryValue() failed (Status %lx)\n", Status
);
1738 DPRINT("TimeOut: %lu\n", TimeOutValue
);
1740 return TimeOutValue
;
1748 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject
)
1750 PDEVICE_EXTENSION DeviceExtension
;
1751 PREAD_CAPACITY_DATA CapacityBuffer
;
1752 SCSI_REQUEST_BLOCK Srb
;
1757 ULONG RetryCount
= 1;
1759 DPRINT("ScsiClassReadDriveCapacity() called\n");
1761 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1763 CapacityBuffer
= ExAllocatePool(NonPagedPoolCacheAligned
,
1764 sizeof(READ_CAPACITY_DATA
));
1765 if (CapacityBuffer
== NULL
)
1767 return(STATUS_INSUFFICIENT_RESOURCES
);
1770 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
1773 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
1775 Cdb
= (PCDB
)Srb
.Cdb
;
1776 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
1779 Status
= ScsiClassSendSrbSynchronous(DeviceObject
,
1782 sizeof(READ_CAPACITY_DATA
),
1784 DPRINT("Status: %lx\n", Status
);
1785 DPRINT("Srb: %p\n", &Srb
);
1786 if (NT_SUCCESS(Status
))
1788 SectorSize
= (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[0] << 24) |
1789 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[1] << 16) |
1790 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[2] << 8) |
1791 ((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[3];
1794 LastSector
= (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[0] << 24) |
1795 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[1] << 16) |
1796 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[2] << 8) |
1797 ((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[3];
1799 DeviceExtension
->DiskGeometry
->BytesPerSector
= SectorSize
;
1801 DeviceExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(LastSector
+ 1);
1802 WHICH_BIT(DeviceExtension
->DiskGeometry
->BytesPerSector
,
1803 DeviceExtension
->SectorShift
);
1804 DeviceExtension
->PartitionLength
.QuadPart
=
1805 (DeviceExtension
->PartitionLength
.QuadPart
<< DeviceExtension
->SectorShift
);
1807 DeviceExtension
->PartitionLength
.QuadPart
=
1808 (DeviceExtension
->PartitionLength
.QuadPart
-
1809 DeviceExtension
->StartingOffset
.QuadPart
);
1811 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1813 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
1817 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
1819 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
= (LONGLONG
)((LastSector
+ 1)/(32 * 64));
1820 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= 32;
1821 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= 64;
1823 DPRINT("SectorSize: %lu SectorCount: %lu PartitionLenght %I64d\n", SectorSize
, LastSector
+ 1,
1824 DeviceExtension
->PartitionLength
.QuadPart
/ 512 );
1827 /* Try again if device needs to be verified */
1828 if (Status
== STATUS_VERIFY_REQUIRED
)
1837 if (!NT_SUCCESS(Status
))
1839 /* Use default values if disk geometry cannot be read */
1840 RtlZeroMemory(DeviceExtension
->DiskGeometry
,
1841 sizeof(DISK_GEOMETRY
));
1842 DeviceExtension
->DiskGeometry
->BytesPerSector
= 512;
1843 DeviceExtension
->SectorShift
= 9;
1844 DeviceExtension
->PartitionLength
.QuadPart
= 0;
1846 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1848 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
1852 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
1855 DPRINT("SectorSize: 512 SectorCount: 0\n");
1858 ExFreePool(CapacityBuffer
);
1860 DPRINT("ScsiClassReadDriveCapacity() done\n");
1870 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject
)
1872 PDEVICE_EXTENSION DeviceExtension
;
1873 PCOMPLETION_CONTEXT Context
;
1874 PIO_STACK_LOCATION Stack
;
1875 PSCSI_REQUEST_BLOCK Srb
;
1880 DPRINT("ScsiClassReleaseQueue() called\n");
1882 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1884 /* Allocate and initialize the completion context */
1885 Context
= ExAllocatePool (NonPagedPoolMustSucceed
,
1886 sizeof (COMPLETION_CONTEXT
));
1887 Context
->DeviceObject
= DeviceObject
;
1889 /* Initialize the SRB */
1890 Srb
= &Context
->Srb
;
1892 sizeof (SCSI_REQUEST_BLOCK
));
1893 Srb
->Length
= sizeof (SCSI_REQUEST_BLOCK
);
1894 Srb
->PathId
= DeviceExtension
->PathId
;
1895 Srb
->TargetId
= DeviceExtension
->TargetId
;
1896 Srb
->Lun
= DeviceExtension
->Lun
;
1897 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1898 Srb
->TimeOutValue
= START_UNIT_TIMEOUT
;
1899 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
|
1900 SRB_FLAGS_DISABLE_AUTOSENSE
|
1901 SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
1904 /* Initialize the CDB */
1905 Cdb
= (PCDB
)&Srb
->Cdb
;
1906 Cdb
->START_STOP
.OperationCode
= SCSIOP_START_STOP_UNIT
;
1907 Cdb
->START_STOP
.Start
= 1;
1908 Cdb
->START_STOP
.LogicalUnitNumber
= Srb
->Lun
;
1911 Irp
= IoAllocateIrp (DeviceObject
->StackSize
, FALSE
);
1912 IoSetCompletionRoutine (Irp
,
1913 (PIO_COMPLETION_ROUTINE
)ScsiClassAsynchronousCompletion
,
1919 /* Attach SRB to the IRP */
1920 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1921 Stack
= IoGetNextIrpStackLocation(Irp
);
1922 Stack
->MajorFunction
= IRP_MJ_SCSI
;
1923 Stack
->Parameters
.Scsi
.Srb
= Srb
;
1924 Srb
->OriginalRequest
= Irp
;
1926 /* Call the port driver */
1927 Irql
= KeGetCurrentIrql ();
1928 if (Irql
< DISPATCH_LEVEL
)
1930 KeRaiseIrql (DISPATCH_LEVEL
, &Irql
);
1931 IoCallDriver (DeviceExtension
->PortDeviceObject
, Irp
);
1936 IoCallDriver (DeviceExtension
->PortDeviceObject
, Irp
);
1939 DPRINT("ScsiClassReleaseQueue() done\n");
1947 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject
,
1948 PSCSI_REQUEST_BLOCK Srb
,
1950 PVOID BufferAddress
,
1952 BOOLEAN WriteToDevice
)
1954 PDEVICE_EXTENSION DeviceExtension
;
1955 PIO_STACK_LOCATION Stack
;
1957 DPRINT("ScsiClassSendSrbAsynchronous() called\n");
1959 DeviceExtension
= DeviceObject
->DeviceExtension
;
1961 /* Initialize the SRB */
1962 Srb
->Length
= SCSI_REQUEST_BLOCK_SIZE
;
1963 Srb
->PathId
= DeviceExtension
->PathId
;
1964 Srb
->TargetId
= DeviceExtension
->TargetId
;
1965 Srb
->Lun
= DeviceExtension
->Lun
;
1966 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1967 Srb
->Cdb
[1] |= DeviceExtension
->Lun
<< 5;
1969 Srb
->SenseInfoBuffer
= (SENSE_DATA
*)ROUND_UP((ULONG_PTR
)(Srb
+ 1), SENSEINFO_ALIGNMENT
);
1970 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
1972 Srb
->DataBuffer
= BufferAddress
;
1973 Srb
->DataTransferLength
= BufferLength
;
1975 Srb
->ScsiStatus
= 0;
1977 Srb
->NextSrb
= NULL
;
1979 if (BufferAddress
!= NULL
)
1981 if (Irp
->MdlAddress
== NULL
)
1983 /* Allocate an MDL */
1984 if (!IoAllocateMdl(BufferAddress
,
1990 DPRINT("Mdl-Allocation failed\n");
1991 return(STATUS_INSUFFICIENT_RESOURCES
);
1994 MmBuildMdlForNonPagedPool(Irp
->MdlAddress
);
1997 /* Set data direction */
1998 Srb
->SrbFlags
= (WriteToDevice
) ? SRB_FLAGS_DATA_OUT
: SRB_FLAGS_DATA_IN
;
2002 /* Set data direction */
2003 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
2006 /* Set the retry counter */
2007 Stack
= IoGetCurrentIrpStackLocation(Irp
);
2008 Stack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
2010 /* Set the completion routine */
2011 IoSetCompletionRoutine(Irp
,
2012 ScsiClassIoComplete
,
2018 /* Attach Srb to the Irp */
2019 Stack
= IoGetNextIrpStackLocation(Irp
);
2020 Stack
->MajorFunction
= IRP_MJ_SCSI
;
2021 Stack
->Parameters
.Scsi
.Srb
= Srb
;
2022 Srb
->OriginalRequest
= Irp
;
2024 /* Call the port driver */
2025 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
2034 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject
,
2035 PSCSI_REQUEST_BLOCK Srb
,
2036 PVOID BufferAddress
,
2038 BOOLEAN WriteToDevice
)
2040 PDEVICE_EXTENSION DeviceExtension
;
2041 IO_STATUS_BLOCK IoStatusBlock
;
2042 PIO_STACK_LOCATION IrpStack
;
2049 LARGE_INTEGER RetryWait
;
2051 DPRINT("ScsiClassSendSrbSynchronous() called\n");
2053 RetryCount
= MAXIMUM_RETRIES
;
2054 DeviceExtension
= DeviceObject
->DeviceExtension
;
2056 Srb
->Length
= SCSI_REQUEST_BLOCK_SIZE
;
2057 Srb
->PathId
= DeviceExtension
->PathId
;
2058 Srb
->TargetId
= DeviceExtension
->TargetId
;
2059 Srb
->Lun
= DeviceExtension
->Lun
;
2060 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2062 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
2063 Srb
->SenseInfoBuffer
= ExAllocatePool(NonPagedPool
,
2065 if (Srb
->SenseInfoBuffer
== NULL
)
2066 return(STATUS_INSUFFICIENT_RESOURCES
);
2068 if (BufferAddress
== NULL
)
2071 RequestType
= IOCTL_SCSI_EXECUTE_NONE
;
2072 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
2076 if (WriteToDevice
== TRUE
)
2078 RequestType
= IOCTL_SCSI_EXECUTE_IN
; // needs _in_ to the device
2079 Srb
->SrbFlags
= SRB_FLAGS_DATA_OUT
; // needs _out_ from the caller
2083 RequestType
= IOCTL_SCSI_EXECUTE_OUT
;
2084 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
2088 Srb
->DataBuffer
= BufferAddress
;
2091 Srb
->DataTransferLength
= BufferLength
;
2092 KeInitializeEvent(&Event
,
2096 Irp
= IoBuildDeviceIoControlRequest(RequestType
,
2097 DeviceExtension
->PortDeviceObject
,
2107 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
2108 ExFreePool(Srb
->SenseInfoBuffer
);
2109 Srb
->SenseInfoBuffer
= NULL
;
2110 Srb
->SenseInfoBufferLength
= 0;
2111 return(STATUS_INSUFFICIENT_RESOURCES
);
2114 /* Attach Srb to the Irp */
2115 IrpStack
= IoGetNextIrpStackLocation(Irp
);
2116 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
2117 Srb
->OriginalRequest
= Irp
;
2119 /* Call the SCSI port driver */
2120 Status
= IoCallDriver(DeviceExtension
->PortDeviceObject
,
2122 if (Status
== STATUS_PENDING
)
2124 KeWaitForSingleObject(&Event
,
2131 if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
)
2133 /* Release the queue if it is frozen */
2134 if (Srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
)
2136 ScsiClassReleaseQueue (DeviceObject
);
2139 /* Get more detailed status information */
2140 Retry
= ScsiClassInterpretSenseInfo(DeviceObject
,
2144 MAXIMUM_RETRIES
- RetryCount
,
2148 DPRINT("Try again (RetryCount %lu)\n", RetryCount
);
2150 /* FIXME: Wait a little if we got a timeout error */
2154 RetryWait
.QuadPart
= - RETRY_WAIT
;
2155 KeDelayExecutionThread(KernelMode
, FALSE
, &RetryWait
);
2162 Status
= STATUS_SUCCESS
;
2165 ExFreePool(Srb
->SenseInfoBuffer
);
2167 DPRINT("ScsiClassSendSrbSynchronous() done\n");
2177 ScsiClassSplitRequest(IN PDEVICE_OBJECT DeviceObject
,
2179 IN ULONG MaximumBytes
)
2181 PDEVICE_EXTENSION DeviceExtension
;
2182 PIO_STACK_LOCATION CurrentStack
;
2183 PIO_STACK_LOCATION NextStack
;
2184 PIO_STACK_LOCATION NewStack
;
2185 PSCSI_REQUEST_BLOCK Srb
;
2186 LARGE_INTEGER Offset
;
2189 ULONG TransferLength
;
2194 DPRINT("ScsiClassSplitRequest(DeviceObject %lx Irp %lx MaximumBytes %lu)\n",
2195 DeviceObject
, Irp
, MaximumBytes
);
2197 DeviceExtension
= DeviceObject
->DeviceExtension
;
2198 CurrentStack
= IoGetCurrentIrpStackLocation(Irp
);
2199 NextStack
= IoGetNextIrpStackLocation(Irp
);
2200 DataBuffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
2202 /* Initialize transfer data for first request */
2203 Offset
= CurrentStack
->Parameters
.Read
.ByteOffset
;
2204 TransferLength
= CurrentStack
->Parameters
.Read
.Length
;
2206 /* Set the result length */
2207 Irp
->IoStatus
.Information
= TransferLength
;
2209 DataLength
= MaximumBytes
;
2210 RequestCount
= ROUND_UP(TransferLength
, MaximumBytes
) / MaximumBytes
;
2212 /* Save request count in the original IRP */
2213 NextStack
->Parameters
.Others
.Argument1
= (PVOID
)RequestCount
;
2215 DPRINT("RequestCount %lu\n", RequestCount
);
2217 for (i
= 0; i
< RequestCount
; i
++)
2219 /* Create a new IRP */
2220 NewIrp
= IoAllocateIrp(DeviceObject
->StackSize
,
2224 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
2225 Irp
->IoStatus
.Information
= 0;
2228 IoCompleteRequest(Irp
,
2233 /* Initialize the new IRP */
2234 NewIrp
->MdlAddress
= Irp
->MdlAddress
;
2235 NewIrp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2237 IoSetNextIrpStackLocation(NewIrp
);
2238 NewStack
= IoGetCurrentIrpStackLocation(NewIrp
);
2240 NewStack
->MajorFunction
= CurrentStack
->MajorFunction
;
2241 NewStack
->Parameters
.Read
.ByteOffset
= Offset
;
2242 NewStack
->Parameters
.Read
.Length
= DataLength
;
2243 NewStack
->DeviceObject
= DeviceObject
;
2245 ScsiClassBuildRequest(DeviceObject
,
2248 NewStack
= IoGetNextIrpStackLocation(NewIrp
);
2249 Srb
= NewStack
->Parameters
.Others
.Argument1
;
2250 Srb
->DataBuffer
= DataBuffer
;
2252 NewIrp
->AssociatedIrp
.MasterIrp
= Irp
;
2254 /* Initialize completion routine */
2255 IoSetCompletionRoutine(NewIrp
,
2256 ScsiClassIoCompleteAssociated
,
2262 /* Send the new IRP down to the port driver */
2263 IoCallDriver(DeviceExtension
->PortDeviceObject
,
2266 /* Adjust transfer data for next request */
2267 DataBuffer
= (PCHAR
)DataBuffer
+ MaximumBytes
;
2268 TransferLength
-= MaximumBytes
;
2269 DataLength
= (TransferLength
> MaximumBytes
) ? MaximumBytes
: TransferLength
;
2270 Offset
.QuadPart
= Offset
.QuadPart
+ MaximumBytes
;
2275 /* INTERNAL FUNCTIONS *******************************************************/
2277 static NTSTATUS STDCALL
2278 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject
,
2281 PDEVICE_EXTENSION DeviceExtension
;
2283 DPRINT("ScsiClassCreateClose() called\n");
2285 DeviceExtension
= DeviceObject
->DeviceExtension
;
2287 if (DeviceExtension
->ClassCreateClose
)
2288 return(DeviceExtension
->ClassCreateClose(DeviceObject
,
2291 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2292 Irp
->IoStatus
.Information
= 0;
2293 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2295 return(STATUS_SUCCESS
);
2299 static NTSTATUS STDCALL
2300 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject
,
2303 PDEVICE_EXTENSION DeviceExtension
;
2304 PIO_STACK_LOCATION IrpStack
;
2305 ULONG MaximumTransferLength
;
2306 ULONG CurrentTransferLength
;
2307 ULONG MaximumTransferPages
;
2308 ULONG CurrentTransferPages
;
2311 DPRINT("ScsiClassReadWrite() called\n");
2313 DeviceExtension
= DeviceObject
->DeviceExtension
;
2314 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
2316 DPRINT("Relative Offset: %I64u Length: %lu\n",
2317 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
,
2318 IrpStack
->Parameters
.Read
.Length
);
2320 MaximumTransferLength
= DeviceExtension
->PortCapabilities
->MaximumTransferLength
;
2321 MaximumTransferPages
= DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
;
2323 CurrentTransferLength
= IrpStack
->Parameters
.Read
.Length
;
2325 if ((DeviceObject
->Flags
& DO_VERIFY_VOLUME
) &&
2326 !(IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
))
2328 IoSetHardErrorOrVerifyDevice(Irp
,
2331 Irp
->IoStatus
.Status
= STATUS_VERIFY_REQUIRED
;
2332 Irp
->IoStatus
.Information
= 0;
2334 IoCompleteRequest(Irp
,
2336 return(STATUS_VERIFY_REQUIRED
);
2339 /* Class driver verifies the IRP */
2340 Status
= DeviceExtension
->ClassReadWriteVerification(DeviceObject
,
2342 if (!NT_SUCCESS(Status
))
2344 IoCompleteRequest(Irp
,
2348 else if (Status
== STATUS_PENDING
)
2350 IoMarkIrpPending(Irp
);
2351 return(STATUS_PENDING
);
2354 /* Finish a zero-byte transfer */
2355 if (CurrentTransferLength
== 0)
2357 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2358 Irp
->IoStatus
.Information
= 0;
2359 IoCompleteRequest(Irp
,
2361 return(STATUS_SUCCESS
);
2364 if (DeviceExtension
->ClassStartIo
!= NULL
)
2366 DPRINT("ScsiClassReadWrite() starting packet\n");
2368 IoMarkIrpPending(Irp
);
2369 IoStartPacket(DeviceObject
,
2374 return(STATUS_PENDING
);
2377 /* Adjust partition-relative starting offset to absolute offset */
2378 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
+=
2379 (DeviceExtension
->StartingOffset
.QuadPart
+ DeviceExtension
->DMByteSkew
);
2381 /* Calculate number of pages in this transfer */
2382 CurrentTransferPages
=
2383 ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp
->MdlAddress
),
2384 IrpStack
->Parameters
.Read
.Length
);
2386 if (CurrentTransferLength
> MaximumTransferLength
||
2387 CurrentTransferPages
> MaximumTransferPages
)
2389 DPRINT("Split current request: MaximumTransferLength %lu CurrentTransferLength %lu\n",
2390 MaximumTransferLength
, CurrentTransferLength
);
2392 /* Adjust the maximum transfer length */
2393 CurrentTransferPages
= DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
;
2395 if (MaximumTransferLength
> CurrentTransferPages
* PAGE_SIZE
)
2396 MaximumTransferLength
= CurrentTransferPages
* PAGE_SIZE
;
2398 if (MaximumTransferLength
== 0)
2399 MaximumTransferLength
= PAGE_SIZE
;
2401 IoMarkIrpPending(Irp
);
2403 /* Split current request */
2404 ScsiClassSplitRequest(DeviceObject
,
2406 MaximumTransferLength
);
2408 return(STATUS_PENDING
);
2411 ScsiClassBuildRequest(DeviceObject
,
2414 DPRINT("ScsiClassReadWrite() done\n");
2416 /* Call the port driver */
2417 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
2422 static NTSTATUS STDCALL
2423 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject
,
2426 PDEVICE_EXTENSION DeviceExtension
;
2428 DPRINT("ScsiClassDeviceDispatch() called\n");
2430 DeviceExtension
= DeviceObject
->DeviceExtension
;
2431 if (DeviceExtension
->ClassDeviceControl
)
2433 return(DeviceExtension
->ClassDeviceControl(DeviceObject
, Irp
));
2436 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
2437 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2439 return(STATUS_INVALID_DEVICE_REQUEST
);
2443 static NTSTATUS STDCALL
2444 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
2447 PDEVICE_EXTENSION DeviceExtension
;
2449 DPRINT("ScsiClassShutdownFlush() called\n");
2451 DeviceExtension
= DeviceObject
->DeviceExtension
;
2452 if (DeviceExtension
->ClassShutdownFlush
)
2454 return(DeviceExtension
->ClassShutdownFlush(DeviceObject
, Irp
));
2457 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
2458 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2460 return(STATUS_INVALID_DEVICE_REQUEST
);
2465 ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject
,
2467 PSCSI_REQUEST_BLOCK Srb
,
2470 PDEVICE_EXTENSION DeviceExtension
;
2471 PIO_STACK_LOCATION CurrentIrpStack
;
2472 PIO_STACK_LOCATION NextIrpStack
;
2474 DPRINT ("ScsiPortRetryRequest() called\n");
2476 DeviceExtension
= DeviceObject
->DeviceExtension
;
2477 CurrentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
2478 NextIrpStack
= IoGetNextIrpStackLocation(Irp
);
2480 if (CurrentIrpStack
->MajorFunction
== IRP_MJ_READ
)
2482 Srb
->DataTransferLength
= CurrentIrpStack
->Parameters
.Read
.Length
;
2484 else if (CurrentIrpStack
->MajorFunction
== IRP_MJ_WRITE
)
2486 Srb
->DataTransferLength
= CurrentIrpStack
->Parameters
.Write
.Length
;
2488 else if (Irp
->MdlAddress
!= NULL
)
2490 Srb
->DataTransferLength
= Irp
->MdlAddress
->ByteCount
;
2494 Srb
->DataTransferLength
= 0;
2498 Srb
->ScsiStatus
= 0;
2500 /* Don't modify the flags */
2502 // Srb->QueueTag = SP_UNTAGGED;
2504 NextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
2505 NextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
2507 if (Associated
== FALSE
)
2509 IoSetCompletionRoutine(Irp
,
2510 ScsiClassIoComplete
,
2518 IoSetCompletionRoutine(Irp
,
2519 ScsiClassIoCompleteAssociated
,
2526 IoCallDriver(DeviceExtension
->PortDeviceObject
,
2529 DPRINT("ScsiPortRetryRequest() done\n");
2533 static NTSTATUS STDCALL
2534 ScsiClassCheckVerifyCompletion (IN PDEVICE_OBJECT DeviceObject
,
2538 PDEVICE_EXTENSION DeviceExtension
;
2539 PDEVICE_EXTENSION PhysicalExtension
;
2540 PIO_STACK_LOCATION Stack
;
2543 DPRINT ("ScsiClassCheckVerifyCompletion() called\n");
2545 /* Get the physical device extension */
2546 DeviceExtension
= DeviceObject
->DeviceExtension
;
2547 PhysicalExtension
= DeviceExtension
->PhysicalDevice
->DeviceExtension
;
2549 /* Get the original IRP */
2550 Stack
= IoGetCurrentIrpStackLocation (Irp
);
2551 OrigIrp
= (PIRP
)Stack
->Parameters
.Others
.Argument1
;
2553 /* Copy the media change count */
2554 *((PULONG
)(OrigIrp
->AssociatedIrp
.SystemBuffer
)) =
2555 PhysicalExtension
->MediaChangeCount
;
2557 /* Complete the original IRP */
2558 OrigIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
2559 OrigIrp
->IoStatus
.Information
= sizeof(ULONG
);
2561 IoCompleteRequest (OrigIrp
,
2564 /* Release the current IRP */
2567 return STATUS_MORE_PROCESSING_REQUIRED
;