2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/misc.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
20 IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine
;
24 USBSTOR_SyncForwardIrpCompletionRoutine(
25 PDEVICE_OBJECT DeviceObject
,
29 if (Irp
->PendingReturned
)
31 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
33 return STATUS_MORE_PROCESSING_REQUIRED
;
38 USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
46 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
49 // copy irp stack location
51 IoCopyCurrentIrpStackLocationToNext(Irp
);
54 // set completion routine
56 IoSetCompletionRoutine(Irp
, USBSTOR_SyncForwardIrpCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
62 Status
= IoCallDriver(DeviceObject
, Irp
);
67 if (Status
== STATUS_PENDING
)
70 // wait for the request to finish
72 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
77 Status
= Irp
->IoStatus
.Status
;
88 USBSTOR_GetBusInterface(
89 IN PDEVICE_OBJECT DeviceObject
,
90 OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface
)
95 IO_STATUS_BLOCK IoStatus
;
96 PIO_STACK_LOCATION Stack
;
101 ASSERT(DeviceObject
);
102 ASSERT(BusInterface
);
108 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
114 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
130 return STATUS_INSUFFICIENT_RESOURCES
;
134 // initialize request
136 Stack
=IoGetNextIrpStackLocation(Irp
);
137 Stack
->MajorFunction
= IRP_MJ_PNP
;
138 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
139 Stack
->Parameters
.QueryInterface
.Size
= sizeof(BUS_INTERFACE_STANDARD
);
140 Stack
->Parameters
.QueryInterface
.InterfaceType
= (LPGUID
)&USB_BUS_INTERFACE_USBDI_GUID
;
141 Stack
->Parameters
.QueryInterface
.Version
= 2;
142 Stack
->Parameters
.QueryInterface
.Interface
= (PINTERFACE
)BusInterface
;
143 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
144 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
149 Status
= IoCallDriver(DeviceObject
, Irp
);
152 // did operation complete
154 if (Status
== STATUS_PENDING
)
157 // wait for completion
159 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
164 Status
=IoStatus
.Status
;
171 USBSTOR_SyncUrbRequest(
172 IN PDEVICE_OBJECT DeviceObject
,
176 PIO_STACK_LOCATION IoStack
;
183 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
189 return STATUS_INSUFFICIENT_RESOURCES
;
195 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
199 // get next stack location
201 IoStack
= IoGetNextIrpStackLocation(Irp
);
204 // initialize stack location
206 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
207 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
208 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)UrbRequest
;
209 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= UrbRequest
->UrbHeader
.Length
;
210 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
213 // setup completion routine
215 IoSetCompletionRoutine(Irp
, USBSTOR_SyncForwardIrpCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
220 Status
= IoCallDriver(DeviceObject
, Irp
);
223 // check if request is pending
225 if (Status
== STATUS_PENDING
)
228 // wait for completion
230 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
235 Status
= Irp
->IoStatus
.Status
;
251 IN POOL_TYPE PoolType
,
257 PVOID Item
= ExAllocatePoolWithTag(PoolType
, ItemSize
, USB_STOR_TAG
);
264 RtlZeroMemory(Item
, ItemSize
);
280 ExFreePoolWithTag(Item
, USB_STOR_TAG
);
284 USBSTOR_ClassRequest(
285 IN PDEVICE_OBJECT DeviceObject
,
286 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
287 IN UCHAR RequestType
,
289 IN ULONG TransferFlags
,
290 IN ULONG TransferBufferLength
,
291 IN PVOID TransferBuffer
)
298 // first allocate urb
300 Urb
= (PURB
)AllocateItem(NonPagedPool
, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
306 return STATUS_INSUFFICIENT_RESOURCES
;
310 // initialize vendor request
312 Urb
->UrbControlVendorClassRequest
.Hdr
.Length
= sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
);
313 Urb
->UrbControlVendorClassRequest
.Hdr
.Function
= URB_FUNCTION_CLASS_INTERFACE
;
314 Urb
->UrbControlVendorClassRequest
.TransferFlags
= TransferFlags
;
315 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= TransferBufferLength
;
316 Urb
->UrbControlVendorClassRequest
.TransferBuffer
= TransferBuffer
;
317 Urb
->UrbControlVendorClassRequest
.Request
= RequestType
;
318 Urb
->UrbControlVendorClassRequest
.Index
= Index
;
323 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
339 IN PDEVICE_OBJECT DeviceObject
,
340 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
346 // allocate 1-byte buffer
348 Buffer
= (PUCHAR
)AllocateItem(NonPagedPool
, sizeof(UCHAR
));
355 return STATUS_INSUFFICIENT_RESOURCES
;
361 Status
= USBSTOR_ClassRequest(DeviceObject
, DeviceExtension
, USB_BULK_GET_MAX_LUN
, DeviceExtension
->InterfaceInformation
->InterfaceNumber
, USBD_TRANSFER_DIRECTION_IN
, sizeof(UCHAR
), Buffer
);
363 DPRINT("MaxLUN: %x\n", *Buffer
);
365 if (NT_SUCCESS(Status
))
370 // invalid response documented in usb mass storage specification
372 Status
= STATUS_DEVICE_DATA_ERROR
;
379 DeviceExtension
->MaxLUN
= *Buffer
;
385 // "USB Mass Storage Class. Bulk-Only Transport. Revision 1.0"
386 // 3.2 Get Max LUN (class-specific request) :
387 // Devices that do not support multiple LUNs may STALL this command.
389 USBSTOR_ResetDevice(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
391 DeviceExtension
->MaxLUN
= 0;
392 Status
= STATUS_SUCCESS
;
409 IN PDEVICE_OBJECT DeviceObject
,
410 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
417 Status
= USBSTOR_ClassRequest(DeviceObject
, DeviceExtension
, USB_BULK_RESET_DEVICE
, DeviceExtension
->InterfaceInformation
->InterfaceNumber
, USBD_TRANSFER_DIRECTION_OUT
, 0, NULL
);
429 IN ULONG BufferLength
,
430 OUT PUCHAR MediumTypeCode
)
432 PUFI_CAPACITY_FORMAT_HEADER FormatHeader
;
433 PUFI_CAPACITY_DESCRIPTOR Descriptor
;
434 ULONG Length
, Index
, BlockCount
, BlockLength
;
439 FormatHeader
= (PUFI_CAPACITY_FORMAT_HEADER
)Buffer
;
444 ASSERT(FormatHeader
->Reserved1
== 0x00);
445 ASSERT(FormatHeader
->Reserved2
== 0x00);
446 ASSERT(FormatHeader
->Reserved3
== 0x00);
449 // is there capacity data
451 if (!FormatHeader
->CapacityLength
)
456 DPRINT1("[USBSTOR] No capacity length\n");
461 // the format header are always 8 bytes in length
463 ASSERT((FormatHeader
->CapacityLength
& 0x7) == 0);
464 DPRINT1("CapacityLength %x\n", FormatHeader
->CapacityLength
);
467 // grab length and locate first descriptor
469 Length
= FormatHeader
->CapacityLength
;
470 Descriptor
= (PUFI_CAPACITY_DESCRIPTOR
)(FormatHeader
+ 1);
471 for(Index
= 0; Index
< Length
/ sizeof(UFI_CAPACITY_DESCRIPTOR
); Index
++)
474 // blocks are little endian format
476 BlockCount
= NTOHL(Descriptor
->BlockCount
);
481 BlockLength
= NTOHL((Descriptor
->BlockLengthByte0
<< 24 | Descriptor
->BlockLengthByte1
<< 16 | Descriptor
->BlockLengthByte2
<< 8));
483 DPRINT1("BlockCount %x BlockLength %x Code %x\n", BlockCount
, BlockLength
, Descriptor
->Code
);
485 if (BlockLength
== 512 && BlockCount
== 1440)
490 *MediumTypeCode
= 0x1E;
493 else if (BlockLength
== 1024 && BlockCount
== 1232)
498 *MediumTypeCode
= 0x93;
501 else if (BlockLength
== 512 && BlockCount
== 2880)
506 *MediumTypeCode
= 0x94;
511 // move to next descriptor
513 Descriptor
= (Descriptor
+ 1);
517 // no floppy detected