2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: USB block storage device driver.
5 * COPYRIGHT: 2005-2006 James Tabor
6 * 2011-2012 Michael Martin (michael.martin@reactos.org)
7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
19 IsRequestValid(PIRP Irp
)
22 PIO_STACK_LOCATION IoStack
;
23 PSCSI_REQUEST_BLOCK Srb
;
25 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
26 Srb
= IoStack
->Parameters
.Scsi
.Srb
;
28 if (Srb
->SrbFlags
& (SRB_FLAGS_DATA_IN
| SRB_FLAGS_DATA_OUT
))
30 if ((Srb
->SrbFlags
& SRB_FLAGS_UNSPECIFIED_DIRECTION
) == SRB_FLAGS_UNSPECIFIED_DIRECTION
)
32 DPRINT1("IsRequestValid: Invalid Srb. Srb->SrbFlags - %X\n", Srb
->SrbFlags
);
36 TransferLength
= Srb
->DataTransferLength
;
38 if (Irp
->MdlAddress
== NULL
)
40 DPRINT1("IsRequestValid: Invalid Srb. Irp->MdlAddress == NULL\n");
44 if (TransferLength
== 0)
46 DPRINT1("IsRequestValid: Invalid Srb. TransferLength == 0\n");
50 if (TransferLength
> USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH
)
52 DPRINT1("IsRequestValid: Invalid Srb. TransferLength > 0x10000\n");
58 if (Srb
->DataTransferLength
)
60 DPRINT1("IsRequestValid: Invalid Srb. Srb->DataTransferLength != 0\n");
66 DPRINT1("IsRequestValid: Invalid Srb. Srb->DataBuffer != NULL\n");
72 DPRINT1("IsRequestValid: Invalid Srb. Irp->MdlAddress != NULL\n");
81 USBSTOR_HandleInternalDeviceControl(
82 IN PDEVICE_OBJECT DeviceObject
,
85 PIO_STACK_LOCATION IoStack
;
86 PSCSI_REQUEST_BLOCK Request
;
87 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
90 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
91 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
93 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
94 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
96 switch(Request
->Function
)
98 case SRB_FUNCTION_EXECUTE_SCSI
:
100 DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
102 if (!IsRequestValid(Irp
))
104 Status
= STATUS_INVALID_PARAMETER
;
108 if (Request
->Cdb
[0] == SCSIOP_MODE_SENSE
)
110 DPRINT("USBSTOR_Scsi: SRB_FUNCTION_EXECUTE_SCSI - FIXME SCSIOP_MODE_SENSE\n");
111 // FIXME Get from registry WriteProtect for StorageDevicePolicies;
112 // L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\StorageDevicePolicies"
113 // QueryTable[0].Name = L"WriteProtect"
116 IoMarkIrpPending(Irp
);
117 Request
->SrbStatus
= SRB_STATUS_PENDING
;
120 if (!USBSTOR_QueueAddIrp(PDODeviceExtension
->LowerDeviceObject
, Irp
))
122 IoStartPacket(PDODeviceExtension
->LowerDeviceObject
, Irp
, &Request
->QueueSortKey
, USBSTOR_CancelIo
);
125 return STATUS_PENDING
;
127 case SRB_FUNCTION_RELEASE_DEVICE
:
129 DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n");
130 ASSERT(PDODeviceExtension
->Claimed
== TRUE
);
133 PDODeviceExtension
->Claimed
= FALSE
;
134 Status
= STATUS_SUCCESS
;
137 case SRB_FUNCTION_CLAIM_DEVICE
:
139 DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n");
141 // check if the device has been claimed
142 if (PDODeviceExtension
->Claimed
)
144 // device has already been claimed
145 Status
= STATUS_DEVICE_BUSY
;
146 Request
->SrbStatus
= SRB_STATUS_BUSY
;
151 PDODeviceExtension
->Claimed
= TRUE
;
153 // output device object
154 Request
->DataBuffer
= DeviceObject
;
156 Status
= STATUS_SUCCESS
;
159 case SRB_FUNCTION_RELEASE_QUEUE
:
161 DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
163 USBSTOR_QueueRelease(PDODeviceExtension
->LowerDeviceObject
);
165 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
166 Status
= STATUS_SUCCESS
;
170 case SRB_FUNCTION_SHUTDOWN
:
171 case SRB_FUNCTION_FLUSH
:
172 case SRB_FUNCTION_FLUSH_QUEUE
:
174 DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE / SRB_FUNCTION_SHUTDOWN\n");
176 // HACK: don't flush pending requests
177 #if 0 // we really need a proper storage stack
179 // wait for pending requests to finish
181 USBSTOR_QueueWaitForPendingRequests(PDODeviceExtension
->LowerDeviceObject
);
184 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
185 Status
= STATUS_SUCCESS
;
193 Status
= STATUS_NOT_SUPPORTED
;
194 Request
->SrbStatus
= SRB_STATUS_ERROR
;
198 Irp
->IoStatus
.Status
= Status
;
199 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
204 USBSTOR_GetFieldLength(
209 ULONG LastCharacterPosition
= 0;
211 // scan the field and return last position which contains a valid character
212 for(Index
= 0; Index
< MaxLength
; Index
++)
214 if (Name
[Index
] != ' ')
216 // trim white spaces from field
217 LastCharacterPosition
= Index
;
221 // convert from zero based index to length
222 return LastCharacterPosition
+ 1;
226 USBSTOR_HandleQueryProperty(
227 IN PDEVICE_OBJECT DeviceObject
,
230 PIO_STACK_LOCATION IoStack
;
231 PSTORAGE_PROPERTY_QUERY PropertyQuery
;
232 PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader
;
233 PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
;
234 ULONG FieldLengthVendor
, FieldLengthProduct
, FieldLengthRevision
, TotalLength
, FieldLengthSerialNumber
;
235 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
236 PINQUIRYDATA InquiryData
;
237 PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
;
239 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
240 UNICODE_STRING SerialNumber
;
241 ANSI_STRING AnsiString
;
244 DPRINT("USBSTOR_HandleQueryProperty\n");
246 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
247 ASSERT(IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(STORAGE_PROPERTY_QUERY
));
248 ASSERT(Irp
->AssociatedIrp
.SystemBuffer
);
250 PropertyQuery
= (PSTORAGE_PROPERTY_QUERY
)Irp
->AssociatedIrp
.SystemBuffer
;
252 // check property type
253 if (PropertyQuery
->PropertyId
!= StorageDeviceProperty
&&
254 PropertyQuery
->PropertyId
!= StorageAdapterProperty
)
256 // only device property / adapter property are supported
257 return STATUS_INVALID_PARAMETER_1
;
261 if (PropertyQuery
->QueryType
== PropertyExistsQuery
)
263 // device property / adapter property is supported
264 return STATUS_SUCCESS
;
267 if (PropertyQuery
->QueryType
!= PropertyStandardQuery
)
269 // only standard query and exists query are supported
270 return STATUS_INVALID_PARAMETER_2
;
273 // check if it is a device property
274 if (PropertyQuery
->PropertyId
== StorageDeviceProperty
)
276 DPRINT("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
278 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
279 ASSERT(PDODeviceExtension
);
280 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
282 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
283 ASSERT(FDODeviceExtension
);
284 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
286 InquiryData
= PDODeviceExtension
->InquiryData
;
289 // compute extra parameters length
290 FieldLengthVendor
= USBSTOR_GetFieldLength(InquiryData
->VendorId
, 8);
291 FieldLengthProduct
= USBSTOR_GetFieldLength(InquiryData
->ProductId
, 16);
292 FieldLengthRevision
= USBSTOR_GetFieldLength(InquiryData
->ProductRevisionLevel
, 4);
294 if (FDODeviceExtension
->SerialNumber
)
296 FieldLengthSerialNumber
= wcslen(FDODeviceExtension
->SerialNumber
->bString
);
300 FieldLengthSerialNumber
= 0;
303 // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
304 // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
305 TotalLength
= sizeof(STORAGE_DEVICE_DESCRIPTOR
) + FieldLengthVendor
+ FieldLengthProduct
+ FieldLengthRevision
+ FieldLengthSerialNumber
+ 3;
307 // check if output buffer is long enough
308 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< TotalLength
)
311 DescriptorHeader
= (PSTORAGE_DESCRIPTOR_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
312 ASSERT(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(STORAGE_DESCRIPTOR_HEADER
));
314 // return required size
315 DescriptorHeader
->Version
= TotalLength
;
316 DescriptorHeader
->Size
= TotalLength
;
318 Irp
->IoStatus
.Information
= sizeof(STORAGE_DESCRIPTOR_HEADER
);
319 return STATUS_SUCCESS
;
322 // initialize the device descriptor
323 DeviceDescriptor
= (PSTORAGE_DEVICE_DESCRIPTOR
)Irp
->AssociatedIrp
.SystemBuffer
;
325 DeviceDescriptor
->Version
= sizeof(STORAGE_DEVICE_DESCRIPTOR
);
326 DeviceDescriptor
->Size
= TotalLength
;
327 DeviceDescriptor
->DeviceType
= InquiryData
->DeviceType
;
328 DeviceDescriptor
->DeviceTypeModifier
= InquiryData
->DeviceTypeModifier
;
329 DeviceDescriptor
->RemovableMedia
= InquiryData
->RemovableMedia
;
330 DeviceDescriptor
->CommandQueueing
= FALSE
;
331 DeviceDescriptor
->BusType
= BusTypeUsb
;
332 DeviceDescriptor
->VendorIdOffset
= sizeof(STORAGE_DEVICE_DESCRIPTOR
) - sizeof(UCHAR
);
333 DeviceDescriptor
->ProductIdOffset
= DeviceDescriptor
->VendorIdOffset
+ FieldLengthVendor
+ 1;
334 DeviceDescriptor
->ProductRevisionOffset
= DeviceDescriptor
->ProductIdOffset
+ FieldLengthProduct
+ 1;
335 DeviceDescriptor
->SerialNumberOffset
= (FieldLengthSerialNumber
> 0 ? DeviceDescriptor
->ProductRevisionOffset
+ FieldLengthRevision
+ 1 : 0);
336 DeviceDescriptor
->RawPropertiesLength
= FieldLengthVendor
+ FieldLengthProduct
+ FieldLengthRevision
+ FieldLengthSerialNumber
+ 3 + (FieldLengthSerialNumber
> 0 ? + 1 : 0);
339 Buffer
= (PUCHAR
)((ULONG_PTR
)DeviceDescriptor
+ sizeof(STORAGE_DEVICE_DESCRIPTOR
) - sizeof(UCHAR
));
341 RtlCopyMemory(Buffer
, InquiryData
->VendorId
, FieldLengthVendor
);
342 Buffer
[FieldLengthVendor
] = '\0';
343 Buffer
+= FieldLengthVendor
+ 1;
345 RtlCopyMemory(Buffer
, InquiryData
->ProductId
, FieldLengthProduct
);
346 Buffer
[FieldLengthProduct
] = '\0';
347 Buffer
+= FieldLengthProduct
+ 1;
349 RtlCopyMemory(Buffer
, InquiryData
->ProductRevisionLevel
, FieldLengthRevision
);
350 Buffer
[FieldLengthRevision
] = '\0';
351 Buffer
+= FieldLengthRevision
+ 1;
353 if (FieldLengthSerialNumber
)
355 RtlInitUnicodeString(&SerialNumber
, FDODeviceExtension
->SerialNumber
->bString
);
357 AnsiString
.Buffer
= (PCHAR
)Buffer
;
358 AnsiString
.Length
= 0;
359 AnsiString
.MaximumLength
= FieldLengthSerialNumber
* sizeof(WCHAR
);
361 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &SerialNumber
, FALSE
);
362 ASSERT(Status
== STATUS_SUCCESS
);
365 DPRINT("Vendor %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->VendorIdOffset
));
366 DPRINT("Product %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->ProductIdOffset
));
367 DPRINT("Revision %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->ProductRevisionOffset
));
368 DPRINT("Serial %s\n", (LPCSTR
)((ULONG_PTR
)DeviceDescriptor
+ DeviceDescriptor
->SerialNumberOffset
));
370 Irp
->IoStatus
.Information
= TotalLength
;
371 return STATUS_SUCCESS
;
375 // adapter property query request
377 DPRINT("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
379 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(STORAGE_ADAPTER_DESCRIPTOR
))
382 DescriptorHeader
= (PSTORAGE_DESCRIPTOR_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
383 ASSERT(IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(STORAGE_DESCRIPTOR_HEADER
));
385 // return required size
386 DescriptorHeader
->Version
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
387 DescriptorHeader
->Size
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
389 Irp
->IoStatus
.Information
= sizeof(STORAGE_DESCRIPTOR_HEADER
);
390 return STATUS_SUCCESS
;
393 // get adapter descriptor, information is returned in the same buffer
394 AdapterDescriptor
= (PSTORAGE_ADAPTER_DESCRIPTOR
)Irp
->AssociatedIrp
.SystemBuffer
;
396 // fill out descriptor
397 AdapterDescriptor
->Version
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
398 AdapterDescriptor
->Size
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
399 AdapterDescriptor
->MaximumTransferLength
= USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH
;
400 AdapterDescriptor
->MaximumPhysicalPages
= USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH
/ PAGE_SIZE
+ 1; // See CORE-10515 and CORE-10755
401 AdapterDescriptor
->AlignmentMask
= 0;
402 AdapterDescriptor
->AdapterUsesPio
= FALSE
;
403 AdapterDescriptor
->AdapterScansDown
= FALSE
;
404 AdapterDescriptor
->CommandQueueing
= FALSE
;
405 AdapterDescriptor
->AcceleratedTransfer
= FALSE
;
406 AdapterDescriptor
->BusType
= BusTypeUsb
;
407 AdapterDescriptor
->BusMajorVersion
= 0x2; //FIXME verify
408 AdapterDescriptor
->BusMinorVersion
= 0x00; //FIXME
410 // store returned length
411 Irp
->IoStatus
.Information
= sizeof(STORAGE_ADAPTER_DESCRIPTOR
);
413 return STATUS_SUCCESS
;
418 USBSTOR_HandleDeviceControl(
419 IN PDEVICE_OBJECT DeviceObject
,
422 PIO_STACK_LOCATION IoStack
;
424 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
425 PSCSI_ADAPTER_BUS_INFO BusInfo
;
426 PSCSI_INQUIRY_DATA ScsiInquiryData
;
427 PINQUIRYDATA InquiryData
;
429 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
431 switch (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
)
433 case IOCTL_STORAGE_QUERY_PROPERTY
:
434 Status
= USBSTOR_HandleQueryProperty(DeviceObject
, Irp
);
436 case IOCTL_SCSI_PASS_THROUGH
:
437 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH NOT implemented\n");
438 Status
= STATUS_NOT_SUPPORTED
;
440 case IOCTL_SCSI_PASS_THROUGH_DIRECT
:
441 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH_DIRECT NOT implemented\n");
442 Status
= STATUS_NOT_SUPPORTED
;
444 case IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER
:
445 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
446 Status
= STATUS_NOT_SUPPORTED
;
448 case IOCTL_SCSI_GET_CAPABILITIES
:
450 PIO_SCSI_CAPABILITIES Capabilities
;
452 // Legacy port capability query
453 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(PVOID
))
455 Capabilities
= *((PVOID
*)Irp
->AssociatedIrp
.SystemBuffer
) = ExAllocatePoolWithTag(NonPagedPool
,
456 sizeof(IO_SCSI_CAPABILITIES
),
458 Irp
->IoStatus
.Information
= sizeof(PVOID
);
462 Capabilities
= Irp
->AssociatedIrp
.SystemBuffer
;
463 Irp
->IoStatus
.Information
= sizeof(IO_SCSI_CAPABILITIES
);
468 Capabilities
->MaximumTransferLength
= USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH
;
469 Capabilities
->MaximumPhysicalPages
= USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH
/ PAGE_SIZE
+ 1; // See CORE-10515 and CORE-10755
470 Capabilities
->SupportedAsynchronousEvents
= 0;
471 Capabilities
->AlignmentMask
= 0;
472 Capabilities
->TaggedQueuing
= FALSE
;
473 Capabilities
->AdapterScansDown
= FALSE
;
474 Capabilities
->AdapterUsesPio
= FALSE
;
475 Status
= STATUS_SUCCESS
;
479 Status
= STATUS_INSUFFICIENT_RESOURCES
;
484 case IOCTL_SCSI_GET_INQUIRY_DATA
:
486 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
487 ASSERT(PDODeviceExtension
);
488 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
491 BusInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
492 ScsiInquiryData
= (PSCSI_INQUIRY_DATA
)(BusInfo
+ 1);
493 InquiryData
= (PINQUIRYDATA
)ScsiInquiryData
->InquiryData
;
496 BusInfo
->NumberOfBuses
= 1;
497 BusInfo
->BusData
[0].NumberOfLogicalUnits
= 1; //FIXME
498 BusInfo
->BusData
[0].InitiatorBusId
= 0;
499 BusInfo
->BusData
[0].InquiryDataOffset
= sizeof(SCSI_ADAPTER_BUS_INFO
);
501 ScsiInquiryData
->PathId
= 0;
502 ScsiInquiryData
->TargetId
= 0;
503 ScsiInquiryData
->Lun
= PDODeviceExtension
->LUN
& MAX_LUN
;
504 ScsiInquiryData
->DeviceClaimed
= PDODeviceExtension
->Claimed
;
505 ScsiInquiryData
->InquiryDataLength
= sizeof(INQUIRYDATA
);
506 ScsiInquiryData
->NextInquiryDataOffset
= 0;
508 // Note: INQUIRYDATA structure is larger than INQUIRYDATABUFFERSIZE
509 RtlZeroMemory(InquiryData
, sizeof(INQUIRYDATA
));
510 RtlCopyMemory(InquiryData
, PDODeviceExtension
->InquiryData
, INQUIRYDATABUFFERSIZE
);
512 InquiryData
->Versions
= 0x04;
513 InquiryData
->ResponseDataFormat
= 0x02; // some devices set this to 1
515 Irp
->IoStatus
.Information
= sizeof(SCSI_ADAPTER_BUS_INFO
) + sizeof(SCSI_INQUIRY_DATA
) + sizeof(INQUIRYDATA
) - 1;
516 Status
= STATUS_SUCCESS
;
520 case IOCTL_SCSI_GET_ADDRESS
:
522 PSCSI_ADDRESS Address
= Irp
->AssociatedIrp
.SystemBuffer
;
524 Address
->Length
= sizeof(SCSI_ADDRESS
);
525 Address
->PortNumber
= 0;
527 Address
->TargetId
= 0;
528 Address
->Lun
= (((PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LUN
& MAX_LUN
);
529 Irp
->IoStatus
.Information
= sizeof(SCSI_ADDRESS
);
531 Status
= STATUS_SUCCESS
;
536 DPRINT("USBSTOR_HandleDeviceControl IoControl %x not supported\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
537 Status
= STATUS_NOT_SUPPORTED
;