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
)
299 // first allocate urb
301 Urb
= (PURB
)AllocateItem(NonPagedPool
, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
307 return STATUS_INSUFFICIENT_RESOURCES
;
311 // allocate 1-byte buffer
313 Buffer
= (PUCHAR
)AllocateItem(NonPagedPool
, sizeof(UCHAR
));
320 return STATUS_INSUFFICIENT_RESOURCES
;
324 // initialize vendor request
326 Urb
->UrbControlVendorClassRequest
.Hdr
.Length
= sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
);
327 Urb
->UrbControlVendorClassRequest
.Hdr
.Function
= URB_FUNCTION_CLASS_INTERFACE
;
328 Urb
->UrbControlVendorClassRequest
.TransferFlags
= TransferFlags
;
329 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= TransferBufferLength
;
330 Urb
->UrbControlVendorClassRequest
.TransferBuffer
= TransferBuffer
;
331 Urb
->UrbControlVendorClassRequest
.Request
= RequestType
;
332 Urb
->UrbControlVendorClassRequest
.Index
= Index
;
337 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
353 IN PDEVICE_OBJECT DeviceObject
,
354 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
360 // allocate 1-byte buffer
362 Buffer
= (PUCHAR
)AllocateItem(NonPagedPool
, sizeof(UCHAR
));
369 return STATUS_INSUFFICIENT_RESOURCES
;
375 Status
= USBSTOR_ClassRequest(DeviceObject
, DeviceExtension
, USB_BULK_GET_MAX_LUN
, DeviceExtension
->InterfaceInformation
->InterfaceNumber
, USBD_TRANSFER_DIRECTION_IN
, sizeof(UCHAR
), Buffer
);
377 DPRINT("MaxLUN: %x\n", *Buffer
);
382 // invalid response documented in usb mass storage specification
384 Status
= STATUS_DEVICE_DATA_ERROR
;
391 DeviceExtension
->MaxLUN
= *Buffer
;
408 IN PDEVICE_OBJECT DeviceObject
,
409 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
416 Status
= USBSTOR_ClassRequest(DeviceObject
, DeviceExtension
, USB_BULK_RESET_DEVICE
, DeviceExtension
->InterfaceInformation
->InterfaceNumber
, USBD_TRANSFER_DIRECTION_OUT
, 0, NULL
);
428 IN ULONG BufferLength
,
429 OUT PUCHAR MediumTypeCode
)
431 PUFI_CAPACITY_FORMAT_HEADER FormatHeader
;
432 PUFI_CAPACITY_DESCRIPTOR Descriptor
;
433 ULONG Length
, Index
, BlockCount
, BlockLength
;
438 FormatHeader
= (PUFI_CAPACITY_FORMAT_HEADER
)Buffer
;
443 ASSERT(FormatHeader
->Reserved1
== 0x00);
444 ASSERT(FormatHeader
->Reserved2
== 0x00);
445 ASSERT(FormatHeader
->Reserved3
== 0x00);
448 // is there capacity data
450 if (!FormatHeader
->CapacityLength
)
455 DPRINT1("[USBSTOR] No capacity length\n");
460 // the format header are always 8 bytes in length
462 ASSERT((FormatHeader
->CapacityLength
& 0x7) == 0);
463 DPRINT1("CapacityLength %x\n", FormatHeader
->CapacityLength
);
466 // grab length and locate first descriptor
468 Length
= FormatHeader
->CapacityLength
;
469 Descriptor
= (PUFI_CAPACITY_DESCRIPTOR
)(FormatHeader
+ 1);
470 for(Index
= 0; Index
< Length
/ sizeof(UFI_CAPACITY_DESCRIPTOR
); Index
++)
473 // blocks are little endian format
475 BlockCount
= NTOHL(Descriptor
->BlockCount
);
480 BlockLength
= NTOHL((Descriptor
->BlockLengthByte0
<< 24 | Descriptor
->BlockLengthByte1
<< 16 | Descriptor
->BlockLengthByte2
<< 8));
482 DPRINT1("BlockCount %x BlockLength %x Code %x\n", BlockCount
, BlockLength
, Descriptor
->Code
);
484 if (BlockLength
== 512 && BlockCount
== 1440)
489 *MediumTypeCode
= 0x1E;
492 else if (BlockLength
== 1024 && BlockCount
== 1232)
497 *MediumTypeCode
= 0x93;
500 else if (BlockLength
== 512 && BlockCount
== 2880)
505 *MediumTypeCode
= 0x94;
510 // move to next descriptor
512 Descriptor
= (Descriptor
+ 1);
516 // no floppy detected