2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/pdo.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
18 USBSTOR_GetDeviceType(
19 IN PUFI_INQUIRY_RESPONSE InquiryData
,
23 // check if device type is zero
25 if (InquiryData
->DeviceType
== 0)
36 // direct access device
42 // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
44 switch (InquiryData
->DeviceType
)
49 // sequential device, i.e magnetic tape
70 // optical memory device
77 // medium change device
92 USBSTOR_GetGenericType(
93 IN PUFI_INQUIRY_RESPONSE InquiryData
,
97 // check if device type is zero
99 if (InquiryData
->DeviceType
== 0)
110 // direct access device
116 // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
118 switch (InquiryData
->DeviceType
)
123 // sequential device, i.e magnetic tape
125 return "GenSequential";
144 // optical memory device
151 // medium change device
160 return "UsbstorOther";
174 for(Index
= 0; Index
< MaxLength
; Index
++)
176 if (Name
[Index
] <= ' ' || Name
[Index
] >= 0x7F /* last printable ascii character */ || Name
[Index
] == ',')
179 // convert to underscore
186 // just copy character
188 Buffer
[Index
] = Name
[Index
];
196 USBSTOR_PdoHandleQueryDeviceText(
197 IN PDEVICE_OBJECT DeviceObject
,
200 //PPDO_DEVICE_EXTENSION DeviceExtension;
201 PIO_STACK_LOCATION IoStack
;
203 static WCHAR DeviceText
[] = L
"USB Mass Storage Device";
206 // get current stack location
208 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
210 if (IoStack
->Parameters
.QueryDeviceText
.DeviceTextType
== DeviceTextDescription
)
212 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n");
217 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, sizeof(DeviceText
));
223 Irp
->IoStatus
.Information
= 0;
224 return STATUS_INSUFFICIENT_RESOURCES
;
230 wcscpy(Buffer
, DeviceText
);
235 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
236 return STATUS_SUCCESS
;
240 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n");
245 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, sizeof(DeviceText
));
251 Irp
->IoStatus
.Information
= 0;
252 return STATUS_INSUFFICIENT_RESOURCES
;
258 wcscpy(Buffer
, DeviceText
);
263 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
264 return STATUS_SUCCESS
;
271 USBSTOR_PdoHandleQueryDeviceId(
272 IN PDEVICE_OBJECT DeviceObject
,
275 PPDO_DEVICE_EXTENSION DeviceExtension
;
280 PUFI_INQUIRY_RESPONSE InquiryData
;
281 ANSI_STRING AnsiString
;
282 UNICODE_STRING DeviceId
;
285 // get device extension
287 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
292 ASSERT(DeviceExtension
->InquiryData
);
297 InquiryData
= (PUFI_INQUIRY_RESPONSE
)DeviceExtension
->InquiryData
;
302 DeviceType
= USBSTOR_GetDeviceType(InquiryData
, DeviceExtension
->IsFloppy
);
307 RtlZeroMemory(Buffer
, sizeof(Buffer
));
310 // lets create device string
312 Offset
= sprintf(&Buffer
[Offset
], "USBSTOR\\");
313 Offset
+= sprintf(&Buffer
[Offset
], DeviceType
);
314 Offset
+= sprintf(&Buffer
[Offset
], "&Ven_");
315 Offset
+= CopyField(InquiryData
->Vendor
, &Buffer
[Offset
], 8);
316 Offset
+= sprintf(&Buffer
[Offset
], "&Prod_");
317 Offset
+= CopyField(InquiryData
->Product
, &Buffer
[Offset
], 16);
318 Offset
+= sprintf(&Buffer
[Offset
], "&Rev_");
319 Offset
+= CopyField(InquiryData
->Revision
, &Buffer
[Offset
], 4);
322 // now initialize ansi string
324 RtlInitAnsiString(&AnsiString
, (PCSZ
)Buffer
);
327 // allocate DeviceId string
330 DeviceId
.MaximumLength
= (strlen((PCHAR
)Buffer
) + 1) * sizeof(WCHAR
);
331 DeviceId
.Buffer
= (LPWSTR
)AllocateItem(PagedPool
, DeviceId
.MaximumLength
);
332 if (!DeviceId
.Buffer
)
337 Irp
->IoStatus
.Information
= 0;
338 return STATUS_INSUFFICIENT_RESOURCES
;
343 // convert to unicode
345 Status
= RtlAnsiStringToUnicodeString(&DeviceId
, &AnsiString
, FALSE
);
347 if (NT_SUCCESS(Status
))
352 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceId
.Buffer
;
355 DPRINT("DeviceId %wZ Status %x\n", &DeviceId
, Status
);
364 USBSTOR_ConvertToUnicodeString(
366 IN ULONG ResultBufferLength
,
367 IN ULONG ResultBufferOffset
,
368 OUT LPWSTR ResultBuffer
,
369 OUT PULONG NewResultBufferOffset
)
371 UNICODE_STRING DeviceString
;
372 ANSI_STRING AnsiString
;
375 ASSERT(ResultBufferLength
);
376 ASSERT(ResultBufferLength
> ResultBufferOffset
);
378 DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset
, ResultBufferLength
, Buffer
, strlen(Buffer
));
381 // construct destination string
383 DeviceString
.Buffer
= &ResultBuffer
[ResultBufferOffset
];
384 DeviceString
.Length
= 0;
385 DeviceString
.MaximumLength
= (ResultBufferLength
- ResultBufferOffset
) * sizeof(WCHAR
);
388 // initialize source string
390 RtlInitAnsiString(&AnsiString
, Buffer
);
393 // convert to unicode
395 Status
= RtlAnsiStringToUnicodeString(&DeviceString
, &AnsiString
, FALSE
);
396 ASSERT(Status
== STATUS_SUCCESS
);
399 // subtract consumed bytes
401 ResultBufferLength
-= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
402 ResultBufferOffset
+= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
407 *NewResultBufferOffset
= ResultBufferOffset
;
413 USBSTOR_PdoHandleQueryHardwareId(
414 IN PDEVICE_OBJECT DeviceObject
,
417 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
418 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
419 LPCSTR GenericType
, DeviceType
;
421 CHAR Id1
[50], Id2
[50], Id3
[50], Id4
[50], Id5
[50], Id6
[50];
422 ULONG Id1Length
, Id2Length
, Id3Length
, Id4Length
, Id5Length
,Id6Length
;
423 ULONG Offset
, TotalLength
, Length
;
424 PUFI_INQUIRY_RESPONSE InquiryData
;
427 // get PDO device extension
429 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
432 // get FDO device extension
434 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
439 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
444 InquiryData
= (PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
;
448 // get device type and generic type
450 DeviceType
= USBSTOR_GetDeviceType(InquiryData
, PDODeviceExtension
->IsFloppy
);
451 GenericType
= USBSTOR_GetGenericType(InquiryData
, PDODeviceExtension
->IsFloppy
);
457 // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4)
459 RtlZeroMemory(Id1
, sizeof(Id1
));
461 Offset
= sprintf(&Id1
[Offset
], "USBSTOR\\");
462 Offset
+= sprintf(&Id1
[Offset
], DeviceType
);
463 Offset
+= CopyField(InquiryData
->Vendor
, &Id1
[Offset
], 8);
464 Offset
+= CopyField(InquiryData
->Product
, &Id1
[Offset
], 16);
465 Offset
+= CopyField(InquiryData
->Revision
, &Id1
[Offset
], 4);
466 Id1Length
= strlen(Id1
) + 1;
467 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1
);
471 // USBSTOR\SCSIType_VENDOR(8)_Product(16)
473 RtlZeroMemory(Id2
, sizeof(Id2
));
475 Offset
= sprintf(&Id2
[Offset
], "USBSTOR\\");
476 Offset
+= sprintf(&Id2
[Offset
], DeviceType
);
477 Offset
+= CopyField(InquiryData
->Vendor
, &Id2
[Offset
], 8);
478 Offset
+= CopyField(InquiryData
->Product
, &Id2
[Offset
], 16);
479 Id2Length
= strlen(Id2
) + 1;
480 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2
);
484 // USBSTOR\SCSIType_VENDOR(8)
486 RtlZeroMemory(Id3
, sizeof(Id3
));
488 Offset
= sprintf(&Id3
[Offset
], "USBSTOR\\");
489 Offset
+= sprintf(&Id3
[Offset
], DeviceType
);
490 Offset
+= CopyField(InquiryData
->Vendor
, &Id3
[Offset
], 8);
491 Id3Length
= strlen(Id3
) + 1;
492 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3
);
496 // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1)
498 RtlZeroMemory(Id4
, sizeof(Id4
));
500 Offset
= sprintf(&Id4
[Offset
], "USBSTOR\\");
501 Offset
+= sprintf(&Id4
[Offset
], DeviceType
);
502 Offset
+= CopyField(InquiryData
->Vendor
, &Id4
[Offset
], 8);
503 Offset
+= CopyField(InquiryData
->Product
, &Id4
[Offset
], 16);
504 Offset
+= CopyField(InquiryData
->Revision
, &Id4
[Offset
], 1);
505 Id4Length
= strlen(Id4
) + 1;
506 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4
);
512 RtlZeroMemory(Id5
, sizeof(Id5
));
514 Offset
= sprintf(&Id5
[Offset
], "USBSTOR\\");
515 Offset
+= sprintf(&Id5
[Offset
], GenericType
);
516 Id5Length
= strlen(Id5
) + 1;
517 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5
);
523 RtlZeroMemory(Id6
, sizeof(Id6
));
525 Offset
= sprintf(&Id6
[Offset
], GenericType
);
526 Id6Length
= strlen(Id6
) + 1;
527 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6
);
530 // compute total length
532 TotalLength
= Id1Length
+ Id2Length
+ Id3Length
+ Id4Length
+ Id5Length
+ Id6Length
+ 1;
537 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, TotalLength
* sizeof(WCHAR
));
543 Irp
->IoStatus
.Information
= 0;
544 return STATUS_INSUFFICIENT_RESOURCES
;
551 Length
= TotalLength
;
553 USBSTOR_ConvertToUnicodeString(Id1
, Length
, Offset
, Buffer
, &Offset
);
554 USBSTOR_ConvertToUnicodeString(Id2
, Length
, Offset
, Buffer
, &Offset
);
555 USBSTOR_ConvertToUnicodeString(Id3
, Length
, Offset
, Buffer
, &Offset
);
556 USBSTOR_ConvertToUnicodeString(Id4
, Length
, Offset
, Buffer
, &Offset
);
557 USBSTOR_ConvertToUnicodeString(Id5
, Length
, Offset
, Buffer
, &Offset
);
558 USBSTOR_ConvertToUnicodeString(Id6
, Length
, Offset
, Buffer
, &Offset
);
563 ASSERT(Offset
+ 1 == Length
);
568 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
573 return STATUS_SUCCESS
;
577 USBSTOR_PdoHandleQueryCompatibleId(
578 IN PDEVICE_OBJECT DeviceObject
,
581 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
582 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
584 ULONG Length
, Offset
;
589 // get PDO device extension
591 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
594 // get FDO device extension
596 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
601 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
604 // get target device type
606 DeviceType
= USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
, PDODeviceExtension
->IsFloppy
);
611 RtlZeroMemory(Buffer
, sizeof(Buffer
));
614 // format instance id
616 Length
= sprintf(Buffer
, "USBSTOR\\%s", DeviceType
) + 1;
617 Length
+= sprintf(&Buffer
[Length
], "USBSTOR\\%s", "RAW") + 2;
620 // allocate instance id
622 InstanceId
= (LPWSTR
)AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
628 Irp
->IoStatus
.Information
= 0;
629 return STATUS_INSUFFICIENT_RESOURCES
;
632 USBSTOR_ConvertToUnicodeString(Buffer
, Length
, 0, InstanceId
, &Offset
);
633 USBSTOR_ConvertToUnicodeString(&Buffer
[Offset
], Length
, Offset
, InstanceId
, &Offset
);
635 DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId
);
640 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
643 // completed successfully
645 return STATUS_SUCCESS
;
649 USBSTOR_PdoHandleQueryInstanceId(
650 IN PDEVICE_OBJECT DeviceObject
,
653 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
654 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
660 // get PDO device extension
662 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
665 // get FDO device extension
667 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
670 // format instance id
672 if (FDODeviceExtension
->SerialNumber
)
675 // using serial number from device
677 swprintf(Buffer
, L
"%s&%c", FDODeviceExtension
->SerialNumber
->bString
, PDODeviceExtension
->LUN
);
682 // use instance count and LUN
684 swprintf(Buffer
, L
"%04lu&%c", FDODeviceExtension
->InstanceCount
, PDODeviceExtension
->LUN
);
690 Length
= wcslen(Buffer
) + 1;
693 // allocate instance id
695 InstanceId
= (LPWSTR
)AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
701 Irp
->IoStatus
.Information
= 0;
702 return STATUS_INSUFFICIENT_RESOURCES
;
708 wcscpy(InstanceId
, Buffer
);
710 DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId
);
715 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
718 // completed successfully
720 return STATUS_SUCCESS
;
724 USBSTOR_PdoHandleDeviceRelations(
725 IN PDEVICE_OBJECT DeviceObject
,
728 PDEVICE_RELATIONS DeviceRelations
;
729 PIO_STACK_LOCATION IoStack
;
731 DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
734 // get current irp stack location
736 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
739 // check if relation type is BusRelations
741 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
744 // PDO handles only target device relation
746 return Irp
->IoStatus
.Status
;
750 // allocate device relations
752 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
753 if (!DeviceRelations
)
758 return STATUS_INSUFFICIENT_RESOURCES
;
762 // initialize device relations
764 DeviceRelations
->Count
= 1;
765 DeviceRelations
->Objects
[0] = DeviceObject
;
766 ObReferenceObject(DeviceObject
);
771 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
774 // completed successfully
776 return STATUS_SUCCESS
;
781 USBSTOR_PdoHandlePnp(
782 IN PDEVICE_OBJECT DeviceObject
,
785 PIO_STACK_LOCATION IoStack
;
786 PPDO_DEVICE_EXTENSION DeviceExtension
;
788 PDEVICE_CAPABILITIES Caps
;
792 // get current stack location
794 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
797 // get device extension
799 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
804 ASSERT(DeviceExtension
->Common
.IsFDO
== FALSE
);
806 switch(IoStack
->MinorFunction
)
808 case IRP_MN_QUERY_DEVICE_RELATIONS
:
810 Status
= USBSTOR_PdoHandleDeviceRelations(DeviceObject
, Irp
);
813 case IRP_MN_QUERY_DEVICE_TEXT
:
815 Status
= USBSTOR_PdoHandleQueryDeviceText(DeviceObject
, Irp
);
818 case IRP_MN_QUERY_ID
:
820 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
823 // handle query device id
825 Status
= USBSTOR_PdoHandleQueryDeviceId(DeviceObject
, Irp
);
828 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
831 // handle instance id
833 Status
= USBSTOR_PdoHandleQueryHardwareId(DeviceObject
, Irp
);
836 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
839 // handle instance id
841 Status
= USBSTOR_PdoHandleQueryInstanceId(DeviceObject
, Irp
);
844 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryCompatibleIDs
)
847 // handle instance id
849 Status
= USBSTOR_PdoHandleQueryCompatibleId(DeviceObject
, Irp
);
853 DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack
->Parameters
.QueryId
.IdType
);
854 Status
= STATUS_NOT_SUPPORTED
;
855 Irp
->IoStatus
.Information
= 0;
858 case IRP_MN_REMOVE_DEVICE
:
860 DPRINT("IRP_MN_REMOVE_DEVICE\n");
862 if(*DeviceExtension
->PDODeviceObject
!= NULL
)
865 // clear entry in FDO pdo list
867 *DeviceExtension
->PDODeviceObject
= NULL
;
873 // device object already marked for deletion
878 /* Complete the IRP */
879 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
880 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
884 /* Delete the device object */
885 IoDeleteDevice(DeviceObject
);
887 return STATUS_SUCCESS
;
889 case IRP_MN_QUERY_CAPABILITIES
:
892 // just forward irp to lower device
894 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
895 ASSERT(Status
== STATUS_SUCCESS
);
897 if (NT_SUCCESS(Status
))
900 // check if no unique id
902 Caps
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
903 Caps
->UniqueID
= FALSE
; // no unique id is supported
904 Caps
->Removable
= TRUE
; //FIXME
908 case IRP_MN_QUERY_REMOVE_DEVICE
:
909 case IRP_MN_QUERY_STOP_DEVICE
:
913 // if we're not claimed it's ok
915 if (DeviceExtension
->Claimed
)
920 Status
= STATUS_UNSUCCESSFUL
;
921 DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack
->MinorFunction
);
924 Status
= STATUS_SUCCESS
;
927 case IRP_MN_START_DEVICE
:
932 Status
= STATUS_SUCCESS
;
935 case IRP_MN_SURPRISE_REMOVAL
:
937 Status
= STATUS_SUCCESS
;
945 Status
= Irp
->IoStatus
.Status
;
952 if (Status
!= STATUS_PENDING
)
957 Irp
->IoStatus
.Status
= Status
;
962 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
973 USBSTOR_CompletionRoutine(
974 IN PDEVICE_OBJECT DeviceObject
,
978 PKEVENT Event
= (PKEVENT
)Ctx
;
983 KeSetEvent(Event
, 0, FALSE
);
984 return STATUS_MORE_PROCESSING_REQUIRED
;
989 IN PDEVICE_OBJECT DeviceObject
,
990 IN ULONG DataTransferLength
,
993 OUT PSCSI_REQUEST_BLOCK
*OutRequest
,
997 PIO_STACK_LOCATION IoStack
;
998 PSCSI_REQUEST_BLOCK Request
;
1004 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1010 return STATUS_INSUFFICIENT_RESOURCES
;
1014 // get next stack location
1016 IoStack
= IoGetNextIrpStackLocation(Irp
);
1019 // create scsi block
1021 Request
= ExAllocatePoolWithTag(NonPagedPool
,
1022 sizeof(SCSI_REQUEST_BLOCK
),
1030 return STATUS_INSUFFICIENT_RESOURCES
;
1036 RtlZeroMemory(Request
, sizeof(SCSI_REQUEST_BLOCK
));
1039 // allocate data transfer block
1041 Request
->DataBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1044 if (!Request
->DataBuffer
)
1050 ExFreePoolWithTag(Request
, USB_STOR_TAG
);
1051 return STATUS_INSUFFICIENT_RESOURCES
;
1057 Irp
->MdlAddress
= IoAllocateMdl(Request
->DataBuffer
, DataTransferLength
, FALSE
, FALSE
, NULL
);
1058 if (!Irp
->MdlAddress
)
1064 ExFreePoolWithTag(Request
->DataBuffer
, USB_STOR_TAG
);
1065 ExFreePoolWithTag(Request
, USB_STOR_TAG
);
1066 return STATUS_INSUFFICIENT_RESOURCES
;
1072 MmBuildMdlForNonPagedPool(Irp
->MdlAddress
);
1077 Request
->DataTransferLength
= DataTransferLength
;
1078 Request
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1079 Request
->SrbFlags
= SRB_FLAGS_DATA_IN
;
1081 RtlZeroMemory(Request
->DataBuffer
, DataTransferLength
);
1085 // get SCSI command data block
1087 pCDB
= (PCDB
)Request
->Cdb
;
1092 pCDB
->AsByte
[0] = OpCode
;
1097 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
1098 IoStack
->Parameters
.Others
.Argument1
= Request
;
1099 IoStack
->DeviceObject
= DeviceObject
;
1104 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1107 // lets setup a completion routine
1109 IoSetCompletionRoutine(Irp
, USBSTOR_CompletionRoutine
, (PVOID
)Event
, TRUE
, TRUE
, TRUE
);
1115 *OutRequest
= Request
;
1116 return STATUS_SUCCESS
;
1121 IN PDEVICE_OBJECT PDODeviceObject
,
1122 IN ULONG DataTransferLength
,
1129 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1130 PSCSI_REQUEST_BLOCK Request
;
1133 // let's allocate an irp
1135 Status
= USBSTOR_AllocateIrp(PDODeviceObject
, DataTransferLength
, OpCode
, &Event
, &Request
, &Irp
);
1136 if (!NT_SUCCESS(Status
))
1141 DPRINT1("[USBSTOR] Failed to build irp\n");
1146 // get device extension
1148 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
1154 ASSERT(PDODeviceExtension
->LowerDeviceObject
);
1155 Status
= IoCallDriver(PDODeviceExtension
->Self
, Irp
);
1157 if (Status
== STATUS_PENDING
)
1160 // wait for completion
1162 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1163 Status
= Irp
->IoStatus
.Status
;
1166 if (NT_SUCCESS(Status
))
1171 *OutData
= Request
->DataBuffer
;
1178 ExFreePoolWithTag(Request
->DataBuffer
, USB_STOR_TAG
);
1185 ExFreePoolWithTag(Request
, USB_STOR_TAG
);
1186 IoFreeMdl(Irp
->MdlAddress
);
1192 USBSTOR_SendInquiryIrp(
1193 IN PDEVICE_OBJECT PDODeviceObject
)
1196 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1197 PUFI_INQUIRY_RESPONSE Response
;
1200 // get device extension
1202 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
1207 Status
= USBSTOR_SendIrp(PDODeviceObject
, sizeof(UFI_INQUIRY_RESPONSE
), SCSIOP_INQUIRY
, (PVOID
*)&Response
);
1208 if (!NT_SUCCESS(Status
))
1213 DPRINT1("USBSTOR_SendInquiryIrp Failed with %x\n", Status
);
1217 DPRINT1("Response %p\n", Response
);
1218 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
1219 DPRINT1("RMB %x\n", Response
->RMB
);
1220 DPRINT1("Version %x\n", Response
->Version
);
1221 DPRINT1("Format %x\n", Response
->Format
);
1222 DPRINT1("Length %x\n", Response
->Length
);
1223 DPRINT1("Reserved %p\n", Response
->Reserved
);
1224 DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response
->Vendor
[0], Response
->Vendor
[1], Response
->Vendor
[2], Response
->Vendor
[3], Response
->Vendor
[4], Response
->Vendor
[5], Response
->Vendor
[6], Response
->Vendor
[7]);
1225 DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", Response
->Product
[0], Response
->Product
[1], Response
->Product
[2], Response
->Product
[3],
1226 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
1227 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
1228 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
1230 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
1235 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
1240 USBSTOR_SendFormatCapacityIrp(
1241 IN PDEVICE_OBJECT PDODeviceObject
)
1244 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1248 // get device extension
1250 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
1255 Status
= USBSTOR_SendIrp(PDODeviceObject
, 0xFC, SCSIOP_READ_FORMATTED_CAPACITY
, (PVOID
*)&Response
);
1256 if (!NT_SUCCESS(Status
))
1265 // check if its a floppy
1267 PDODeviceExtension
->IsFloppy
= USBSTOR_IsFloppy(Response
, 0xFC /*FIXME*/, &PDODeviceExtension
->MediumTypeCode
);
1272 ExFreePoolWithTag(Response
, USB_STOR_TAG
);
1280 IN PDEVICE_OBJECT DeviceObject
,
1285 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1286 PUFI_INQUIRY_RESPONSE Response
;
1287 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
1290 // get device extension
1292 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1296 // create child device object
1298 Status
= IoCreateDevice(DeviceObject
->DriverObject
, sizeof(PDO_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_MASS_STORAGE
, FILE_AUTOGENERATED_DEVICE_NAME
| FILE_DEVICE_SECURE_OPEN
, FALSE
, &PDO
);
1299 if (!NT_SUCCESS(Status
))
1302 // failed to create device
1308 // patch the stack size
1310 PDO
->StackSize
= DeviceObject
->StackSize
;
1313 // get device extension
1315 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDO
->DeviceExtension
;
1318 // initialize device extension
1320 RtlZeroMemory(PDODeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
1321 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
1322 PDODeviceExtension
->LowerDeviceObject
= DeviceObject
;
1323 PDODeviceExtension
->PDODeviceObject
= &FDODeviceExtension
->ChildPDO
[LUN
];
1324 PDODeviceExtension
->Self
= PDO
;
1325 PDODeviceExtension
->LUN
= LUN
;
1330 PDO
->Flags
|= DO_DIRECT_IO
| DO_MAP_IO_BUFFER
;
1333 // device is initialized
1335 PDO
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1338 // output device object
1340 FDODeviceExtension
->ChildPDO
[LUN
] = PDO
;
1343 // send inquiry command by irp
1345 Status
= USBSTOR_SendInquiryIrp(PDO
);
1346 ASSERT(Status
== STATUS_SUCCESS
);
1349 // check response data
1351 Response
= (PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
;
1354 if (Response
->DeviceType
== 0)
1357 // check if it is a floppy
1359 Status
= USBSTOR_SendFormatCapacityIrp(PDO
);
1364 DPRINT1("[USBSTOR] Status %x IsFloppy %x MediumTypeCode %x\n", Status
, PDODeviceExtension
->IsFloppy
, PDODeviceExtension
->MediumTypeCode
);
1367 // failing command is non critical
1369 Status
= STATUS_SUCCESS
;