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)
15 USBSTOR_GetDeviceType(
16 IN PUFI_INQUIRY_RESPONSE InquiryData
,
20 // check if device type is zero
22 if (InquiryData
->DeviceType
== 0)
33 // direct access device
39 // FIXME: use constant - derrived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
41 switch (InquiryData
->DeviceType
)
46 // sequential device, i.e magnetic tape
67 // optical memory device
74 // medium change device
89 USBSTOR_GetGenericType(
90 IN PUFI_INQUIRY_RESPONSE InquiryData
,
94 // check if device type is zero
96 if (InquiryData
->DeviceType
== 0)
107 // direct access device
113 // FIXME: use constant - derrived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
115 switch (InquiryData
->DeviceType
)
120 // sequential device, i.e magnetic tape
122 return "GenSequential";
141 // optical memory device
148 // medium change device
157 return "UsbstorOther";
171 for(Index
= 0; Index
< MaxLength
; Index
++)
173 if (Name
[Index
] <= ' ' || Name
[Index
] >= 0x7F /* last printable ascii character */ || Name
[Index
] == ',')
176 // convert to underscore
183 // just copy character
185 Buffer
[Index
] = Name
[Index
];
193 USBSTOR_PdoHandleQueryDeviceText(
194 IN PDEVICE_OBJECT DeviceObject
,
197 //PPDO_DEVICE_EXTENSION DeviceExtension;
198 PIO_STACK_LOCATION IoStack
;
200 static WCHAR DeviceText
[] = L
"USB Mass Storage Device";
203 // get current stack location
205 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
207 if (IoStack
->Parameters
.QueryDeviceText
.DeviceTextType
== DeviceTextDescription
)
209 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n");
214 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, sizeof(DeviceText
));
220 Irp
->IoStatus
.Information
= 0;
221 return STATUS_INSUFFICIENT_RESOURCES
;
227 wcscpy(Buffer
, DeviceText
);
232 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
233 return STATUS_SUCCESS
;
237 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n");
242 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, sizeof(DeviceText
));
248 Irp
->IoStatus
.Information
= 0;
249 return STATUS_INSUFFICIENT_RESOURCES
;
255 wcscpy(Buffer
, DeviceText
);
260 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
261 return STATUS_SUCCESS
;
268 USBSTOR_PdoHandleQueryDeviceId(
269 IN PDEVICE_OBJECT DeviceObject
,
272 PPDO_DEVICE_EXTENSION DeviceExtension
;
277 PUFI_INQUIRY_RESPONSE InquiryData
;
278 ANSI_STRING AnsiString
;
279 UNICODE_STRING DeviceId
;
282 // get device extension
284 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
289 ASSERT(DeviceExtension
->InquiryData
);
294 InquiryData
= (PUFI_INQUIRY_RESPONSE
)DeviceExtension
->InquiryData
;
299 DeviceType
= USBSTOR_GetDeviceType(InquiryData
, DeviceExtension
->IsFloppy
);
304 RtlZeroMemory(Buffer
, sizeof(Buffer
));
307 // lets create device string
309 Offset
= sprintf(&Buffer
[Offset
], "USBSTOR\\");
310 Offset
+= sprintf(&Buffer
[Offset
], DeviceType
);
311 Offset
+= sprintf(&Buffer
[Offset
], "&Ven_");
312 Offset
+= CopyField(InquiryData
->Vendor
, &Buffer
[Offset
], 8);
313 Offset
+= sprintf(&Buffer
[Offset
], "&Prod_");
314 Offset
+= CopyField(InquiryData
->Product
, &Buffer
[Offset
], 16);
315 Offset
+= sprintf(&Buffer
[Offset
], "&Rev_");
316 Offset
+= CopyField(InquiryData
->Revision
, &Buffer
[Offset
], 4);
319 // now initialize ansi string
321 RtlInitAnsiString(&AnsiString
, (PCSZ
)Buffer
);
324 // allocate DeviceId string
327 DeviceId
.MaximumLength
= (strlen((PCHAR
)Buffer
) + 1) * sizeof(WCHAR
);
328 DeviceId
.Buffer
= (LPWSTR
)AllocateItem(PagedPool
, DeviceId
.MaximumLength
);
329 if (!DeviceId
.Buffer
)
334 Irp
->IoStatus
.Information
= 0;
335 return STATUS_INSUFFICIENT_RESOURCES
;
340 // convert to unicode
342 Status
= RtlAnsiStringToUnicodeString(&DeviceId
, &AnsiString
, FALSE
);
344 if (NT_SUCCESS(Status
))
349 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceId
.Buffer
;
352 DPRINT("DeviceId %wZ Status %x\n", &DeviceId
, Status
);
361 USBSTOR_ConvertToUnicodeString(
363 IN ULONG ResultBufferLength
,
364 IN ULONG ResultBufferOffset
,
365 OUT LPWSTR ResultBuffer
,
366 OUT PULONG NewResultBufferOffset
)
368 UNICODE_STRING DeviceString
;
369 ANSI_STRING AnsiString
;
372 ASSERT(ResultBufferLength
);
373 ASSERT(ResultBufferLength
> ResultBufferOffset
);
375 DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset
, ResultBufferLength
, Buffer
, strlen(Buffer
));
378 // construct destination string
380 DeviceString
.Buffer
= &ResultBuffer
[ResultBufferOffset
];
381 DeviceString
.Length
= 0;
382 DeviceString
.MaximumLength
= (ResultBufferLength
- ResultBufferOffset
) * sizeof(WCHAR
);
385 // initialize source string
387 RtlInitAnsiString(&AnsiString
, Buffer
);
390 // convert to unicode
392 Status
= RtlAnsiStringToUnicodeString(&DeviceString
, &AnsiString
, FALSE
);
393 ASSERT(Status
== STATUS_SUCCESS
);
396 // subtract consumed bytes
398 ResultBufferLength
-= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
399 ResultBufferOffset
+= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
404 *NewResultBufferOffset
= ResultBufferOffset
;
410 USBSTOR_PdoHandleQueryHardwareId(
411 IN PDEVICE_OBJECT DeviceObject
,
414 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
415 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
416 LPCSTR GenericType
, DeviceType
;
418 CHAR Id1
[50], Id2
[50], Id3
[50], Id4
[50], Id5
[50], Id6
[50];
419 ULONG Id1Length
, Id2Length
, Id3Length
, Id4Length
, Id5Length
,Id6Length
;
420 ULONG Offset
, TotalLength
, Length
;
421 PUFI_INQUIRY_RESPONSE InquiryData
;
424 // get PDO device extension
426 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
429 // get FDO device extension
431 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
436 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
441 InquiryData
= (PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
;
445 // get device type and generic type
447 DeviceType
= USBSTOR_GetDeviceType(InquiryData
, PDODeviceExtension
->IsFloppy
);
448 GenericType
= USBSTOR_GetGenericType(InquiryData
, PDODeviceExtension
->IsFloppy
);
454 // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4)
456 RtlZeroMemory(Id1
, sizeof(Id1
));
458 Offset
= sprintf(&Id1
[Offset
], "USBSTOR\\");
459 Offset
+= sprintf(&Id1
[Offset
], DeviceType
);
460 Offset
+= CopyField(InquiryData
->Vendor
, &Id1
[Offset
], 8);
461 Offset
+= CopyField(InquiryData
->Product
, &Id1
[Offset
], 16);
462 Offset
+= CopyField(InquiryData
->Revision
, &Id1
[Offset
], 4);
463 Id1Length
= strlen(Id1
) + 1;
464 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1
);
468 // USBSTOR\SCSIType_VENDOR(8)_Product(16)
470 RtlZeroMemory(Id2
, sizeof(Id2
));
472 Offset
= sprintf(&Id2
[Offset
], "USBSTOR\\");
473 Offset
+= sprintf(&Id2
[Offset
], DeviceType
);
474 Offset
+= CopyField(InquiryData
->Vendor
, &Id2
[Offset
], 8);
475 Offset
+= CopyField(InquiryData
->Product
, &Id2
[Offset
], 16);
476 Id2Length
= strlen(Id2
) + 1;
477 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2
);
481 // USBSTOR\SCSIType_VENDOR(8)
483 RtlZeroMemory(Id3
, sizeof(Id3
));
485 Offset
= sprintf(&Id3
[Offset
], "USBSTOR\\");
486 Offset
+= sprintf(&Id3
[Offset
], DeviceType
);
487 Offset
+= CopyField(InquiryData
->Vendor
, &Id3
[Offset
], 8);
488 Id3Length
= strlen(Id3
) + 1;
489 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3
);
493 // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1)
495 RtlZeroMemory(Id4
, sizeof(Id4
));
497 Offset
= sprintf(&Id4
[Offset
], "USBSTOR\\");
498 Offset
+= sprintf(&Id4
[Offset
], DeviceType
);
499 Offset
+= CopyField(InquiryData
->Vendor
, &Id4
[Offset
], 8);
500 Offset
+= CopyField(InquiryData
->Product
, &Id4
[Offset
], 16);
501 Offset
+= CopyField(InquiryData
->Revision
, &Id4
[Offset
], 1);
502 Id4Length
= strlen(Id4
) + 1;
503 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4
);
509 RtlZeroMemory(Id5
, sizeof(Id5
));
511 Offset
= sprintf(&Id5
[Offset
], "USBSTOR\\");
512 Offset
+= sprintf(&Id5
[Offset
], GenericType
);
513 Id5Length
= strlen(Id5
) + 1;
514 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5
);
520 RtlZeroMemory(Id6
, sizeof(Id6
));
522 Offset
= sprintf(&Id6
[Offset
], GenericType
);
523 Id6Length
= strlen(Id6
) + 1;
524 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6
);
527 // compute total length
529 TotalLength
= Id1Length
+ Id2Length
+ Id3Length
+ Id4Length
+ Id5Length
+ Id6Length
+ 1;
534 Buffer
= (LPWSTR
)AllocateItem(PagedPool
, TotalLength
* sizeof(WCHAR
));
540 Irp
->IoStatus
.Information
= 0;
541 return STATUS_INSUFFICIENT_RESOURCES
;
548 Length
= TotalLength
;
550 USBSTOR_ConvertToUnicodeString(Id1
, Length
, Offset
, Buffer
, &Offset
);
551 USBSTOR_ConvertToUnicodeString(Id2
, Length
, Offset
, Buffer
, &Offset
);
552 USBSTOR_ConvertToUnicodeString(Id3
, Length
, Offset
, Buffer
, &Offset
);
553 USBSTOR_ConvertToUnicodeString(Id4
, Length
, Offset
, Buffer
, &Offset
);
554 USBSTOR_ConvertToUnicodeString(Id5
, Length
, Offset
, Buffer
, &Offset
);
555 USBSTOR_ConvertToUnicodeString(Id6
, Length
, Offset
, Buffer
, &Offset
);
560 ASSERT(Offset
+ 1 == Length
);
565 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
570 return STATUS_SUCCESS
;
574 USBSTOR_PdoHandleQueryCompatibleId(
575 IN PDEVICE_OBJECT DeviceObject
,
578 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
579 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
581 ULONG Length
, Offset
;
586 // get PDO device extension
588 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
591 // get FDO device extension
593 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
598 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
601 // get target device type
603 DeviceType
= USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
, PDODeviceExtension
->IsFloppy
);
608 RtlZeroMemory(Buffer
, sizeof(Buffer
));
611 // format instance id
613 Length
= sprintf(Buffer
, "USBSTOR\\%s", DeviceType
) + 1;
614 Length
+= sprintf(&Buffer
[Length
], "USBSTOR\\%s", "RAW") + 2;
617 // allocate instance id
619 InstanceId
= (LPWSTR
)AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
625 Irp
->IoStatus
.Information
= 0;
626 return STATUS_INSUFFICIENT_RESOURCES
;
629 USBSTOR_ConvertToUnicodeString(Buffer
, Length
, 0, InstanceId
, &Offset
);
630 USBSTOR_ConvertToUnicodeString(&Buffer
[Offset
], Length
, Offset
, InstanceId
, &Offset
);
632 DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId
);
637 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
640 // completed successfully
642 return STATUS_SUCCESS
;
646 USBSTOR_PdoHandleQueryInstanceId(
647 IN PDEVICE_OBJECT DeviceObject
,
650 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
651 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
657 // get PDO device extension
659 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
662 // get FDO device extension
664 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
667 // format instance id
669 if (FDODeviceExtension
->SerialNumber
)
672 // using serial number from device
674 swprintf(Buffer
, L
"%s&%c", FDODeviceExtension
->SerialNumber
->bString
, PDODeviceExtension
->LUN
);
679 // use instance count and LUN
681 swprintf(Buffer
, L
"%04lu&%c", FDODeviceExtension
->InstanceCount
, PDODeviceExtension
->LUN
);
687 Length
= wcslen(Buffer
) + 1;
690 // allocate instance id
692 InstanceId
= (LPWSTR
)AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
698 Irp
->IoStatus
.Information
= 0;
699 return STATUS_INSUFFICIENT_RESOURCES
;
705 wcscpy(InstanceId
, Buffer
);
707 DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId
);
712 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
715 // completed successfully
717 return STATUS_SUCCESS
;
721 USBSTOR_PdoHandleDeviceRelations(
722 IN PDEVICE_OBJECT DeviceObject
,
725 PDEVICE_RELATIONS DeviceRelations
;
726 PIO_STACK_LOCATION IoStack
;
728 DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
731 // get current irp stack location
733 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
736 // check if relation type is BusRelations
738 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
741 // PDO handles only target device relation
743 return Irp
->IoStatus
.Status
;
747 // allocate device relations
749 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
750 if (!DeviceRelations
)
755 return STATUS_INSUFFICIENT_RESOURCES
;
759 // initialize device relations
761 DeviceRelations
->Count
= 1;
762 DeviceRelations
->Objects
[0] = DeviceObject
;
763 ObReferenceObject(DeviceObject
);
768 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
771 // completed successfully
773 return STATUS_SUCCESS
;
778 USBSTOR_PdoHandlePnp(
779 IN PDEVICE_OBJECT DeviceObject
,
782 PIO_STACK_LOCATION IoStack
;
783 PPDO_DEVICE_EXTENSION DeviceExtension
;
785 PDEVICE_CAPABILITIES Caps
;
789 // get current stack location
791 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
794 // get device extension
796 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
801 ASSERT(DeviceExtension
->Common
.IsFDO
== FALSE
);
803 switch(IoStack
->MinorFunction
)
805 case IRP_MN_QUERY_DEVICE_RELATIONS
:
807 Status
= USBSTOR_PdoHandleDeviceRelations(DeviceObject
, Irp
);
810 case IRP_MN_QUERY_DEVICE_TEXT
:
812 Status
= USBSTOR_PdoHandleQueryDeviceText(DeviceObject
, Irp
);
815 case IRP_MN_QUERY_ID
:
817 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
820 // handle query device id
822 Status
= USBSTOR_PdoHandleQueryDeviceId(DeviceObject
, Irp
);
825 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
828 // handle instance id
830 Status
= USBSTOR_PdoHandleQueryHardwareId(DeviceObject
, Irp
);
833 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
836 // handle instance id
838 Status
= USBSTOR_PdoHandleQueryInstanceId(DeviceObject
, Irp
);
841 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryCompatibleIDs
)
844 // handle instance id
846 Status
= USBSTOR_PdoHandleQueryCompatibleId(DeviceObject
, Irp
);
850 DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack
->Parameters
.QueryId
.IdType
);
851 Status
= STATUS_NOT_SUPPORTED
;
852 Irp
->IoStatus
.Information
= 0;
855 case IRP_MN_REMOVE_DEVICE
:
857 DPRINT("IRP_MN_REMOVE_DEVICE\n");
859 if(*DeviceExtension
->PDODeviceObject
!= NULL
)
862 // clear entry in FDO pdo list
864 *DeviceExtension
->PDODeviceObject
= NULL
;
870 // device object already marked for deletion
875 /* Complete the IRP */
876 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
877 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
881 /* Delete the device object */
882 IoDeleteDevice(DeviceObject
);
884 return STATUS_SUCCESS
;
886 case IRP_MN_QUERY_CAPABILITIES
:
889 // just forward irp to lower device
891 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
892 ASSERT(Status
== STATUS_SUCCESS
);
894 if (NT_SUCCESS(Status
))
897 // check if no unique id
899 Caps
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
900 Caps
->UniqueID
= FALSE
; // no unique id is supported
901 Caps
->Removable
= TRUE
; //FIXME
905 case IRP_MN_QUERY_REMOVE_DEVICE
:
906 case IRP_MN_QUERY_STOP_DEVICE
:
910 // if we're not claimed it's ok
912 if (DeviceExtension
->Claimed
)
917 Status
= STATUS_UNSUCCESSFUL
;
918 DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack
->MinorFunction
);
921 Status
= STATUS_SUCCESS
;
924 case IRP_MN_START_DEVICE
:
929 Status
= STATUS_SUCCESS
;
932 case IRP_MN_SURPRISE_REMOVAL
:
934 Status
= STATUS_SUCCESS
;
942 Status
= Irp
->IoStatus
.Status
;
949 if (Status
!= STATUS_PENDING
)
954 Irp
->IoStatus
.Status
= Status
;
959 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
970 USBSTOR_CompletionRoutine(
971 IN PDEVICE_OBJECT DeviceObject
,
975 PKEVENT Event
= (PKEVENT
)Ctx
;
980 KeSetEvent(Event
, 0, FALSE
);
981 return STATUS_MORE_PROCESSING_REQUIRED
;
986 IN PDEVICE_OBJECT DeviceObject
,
987 IN ULONG DataTransferLength
,
990 OUT PSCSI_REQUEST_BLOCK
*OutRequest
,
994 PIO_STACK_LOCATION IoStack
;
995 PSCSI_REQUEST_BLOCK Request
;
1001 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1007 return STATUS_INSUFFICIENT_RESOURCES
;
1011 // get next stack location
1013 IoStack
= IoGetNextIrpStackLocation(Irp
);
1016 // create scsi block
1018 Request
= (PSCSI_REQUEST_BLOCK
)ExAllocatePool(NonPagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
1025 return STATUS_INSUFFICIENT_RESOURCES
;
1031 RtlZeroMemory(Request
, sizeof(SCSI_REQUEST_BLOCK
));
1034 // allocate data transfer block
1036 Request
->DataBuffer
= ExAllocatePool(NonPagedPool
, DataTransferLength
);
1043 ExFreePool(Request
);
1044 return STATUS_INSUFFICIENT_RESOURCES
;
1050 Irp
->MdlAddress
= IoAllocateMdl(Request
->DataBuffer
, DataTransferLength
, FALSE
, FALSE
, NULL
);
1051 if (!Irp
->MdlAddress
)
1057 ExFreePool(Request
);
1058 return STATUS_INSUFFICIENT_RESOURCES
;
1064 MmBuildMdlForNonPagedPool(Irp
->MdlAddress
);
1069 Request
->DataTransferLength
= DataTransferLength
;
1070 Request
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1071 Request
->SrbFlags
= SRB_FLAGS_DATA_IN
;
1073 RtlZeroMemory(Request
->DataBuffer
, DataTransferLength
);
1077 // get SCSI command data block
1079 pCDB
= (PCDB
)Request
->Cdb
;
1084 pCDB
->AsByte
[0] = OpCode
;
1089 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
1090 IoStack
->Parameters
.Others
.Argument1
= Request
;
1091 IoStack
->DeviceObject
= DeviceObject
;
1096 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1099 // lets setup a completion routine
1101 IoSetCompletionRoutine(Irp
, USBSTOR_CompletionRoutine
, (PVOID
)Event
, TRUE
, TRUE
, TRUE
);
1107 *OutRequest
= Request
;
1108 return STATUS_SUCCESS
;
1113 IN PDEVICE_OBJECT PDODeviceObject
,
1114 IN ULONG DataTransferLength
,
1121 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1122 PSCSI_REQUEST_BLOCK Request
;
1125 // let's allocate an irp
1127 Status
= USBSTOR_AllocateIrp(PDODeviceObject
, DataTransferLength
, OpCode
, &Event
, &Request
, &Irp
);
1128 if (!NT_SUCCESS(Status
))
1133 DPRINT1("[USBSTOR] Failed to build irp\n");
1138 // get device extension
1140 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
1146 ASSERT(PDODeviceExtension
->LowerDeviceObject
);
1147 Status
= IoCallDriver(PDODeviceExtension
->Self
, Irp
);
1149 if (Status
== STATUS_PENDING
)
1152 // wait for completion
1154 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1155 Status
= Irp
->IoStatus
.Status
;
1158 if (NT_SUCCESS(Status
))
1163 *OutData
= Request
->DataBuffer
;
1169 ExFreePool(Request
);
1175 USBSTOR_SendInquiryIrp(
1176 IN PDEVICE_OBJECT PDODeviceObject
)
1179 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1180 PUFI_INQUIRY_RESPONSE Response
;
1183 // get device extension
1185 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
1190 Status
= USBSTOR_SendIrp(PDODeviceObject
, sizeof(UFI_INQUIRY_RESPONSE
), SCSIOP_INQUIRY
, (PVOID
*)&Response
);
1191 if (!NT_SUCCESS(Status
))
1196 DPRINT1("USBSTOR_SendInquiryIrp Failed with %x\n", Status
);
1200 DPRINT1("Response %p\n", Response
);
1201 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
1202 DPRINT1("RMB %x\n", Response
->RMB
);
1203 DPRINT1("Version %x\n", Response
->Version
);
1204 DPRINT1("Format %x\n", Response
->Format
);
1205 DPRINT1("Length %x\n", Response
->Length
);
1206 DPRINT1("Reserved %p\n", Response
->Reserved
);
1207 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]);
1208 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],
1209 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
1210 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
1211 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
1213 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
1218 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
1223 USBSTOR_SendFormatCapacityIrp(
1224 IN PDEVICE_OBJECT PDODeviceObject
)
1227 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1231 // get device extension
1233 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
1238 Status
= USBSTOR_SendIrp(PDODeviceObject
, 0xFC, SCSIOP_READ_FORMATTED_CAPACITY
, (PVOID
*)&Response
);
1239 if (!NT_SUCCESS(Status
))
1248 // check if its a floppy
1250 PDODeviceExtension
->IsFloppy
= USBSTOR_IsFloppy(Response
, 0xFC /*FIXME*/, &PDODeviceExtension
->MediumTypeCode
);
1255 ExFreePool(Response
);
1263 IN PDEVICE_OBJECT DeviceObject
,
1268 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1269 PUFI_INQUIRY_RESPONSE Response
;
1270 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
1273 // get device extension
1275 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1279 // create child device object
1281 Status
= IoCreateDevice(DeviceObject
->DriverObject
, sizeof(PDO_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_MASS_STORAGE
, FILE_AUTOGENERATED_DEVICE_NAME
| FILE_DEVICE_SECURE_OPEN
, FALSE
, &PDO
);
1282 if (!NT_SUCCESS(Status
))
1285 // failed to create device
1291 // patch the stack size
1293 PDO
->StackSize
= DeviceObject
->StackSize
;
1296 // get device extension
1298 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDO
->DeviceExtension
;
1301 // initialize device extension
1303 RtlZeroMemory(PDODeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
1304 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
1305 PDODeviceExtension
->LowerDeviceObject
= DeviceObject
;
1306 PDODeviceExtension
->PDODeviceObject
= &FDODeviceExtension
->ChildPDO
[LUN
];
1307 PDODeviceExtension
->Self
= PDO
;
1308 PDODeviceExtension
->LUN
= LUN
;
1313 PDO
->Flags
|= DO_DIRECT_IO
| DO_MAP_IO_BUFFER
;
1316 // device is initialized
1318 PDO
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1321 // output device object
1323 FDODeviceExtension
->ChildPDO
[LUN
] = PDO
;
1326 // send inquiry command by irp
1328 Status
= USBSTOR_SendInquiryIrp(PDO
);
1329 ASSERT(Status
== STATUS_SUCCESS
);
1332 // check response data
1334 Response
= (PUFI_INQUIRY_RESPONSE
)PDODeviceExtension
->InquiryData
;
1337 if (Response
->DeviceType
== 0)
1340 // check if it is a floppy
1342 Status
= USBSTOR_SendFormatCapacityIrp(PDO
);
1347 DPRINT1("[USBSTOR] Status %x IsFloppy %x MediumTypeCode %x\n", Status
, PDODeviceExtension
->IsFloppy
, PDODeviceExtension
->MediumTypeCode
);
1350 // failing command is non critical
1352 Status
= STATUS_SUCCESS
;