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)
17 IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine
;
21 USBSTOR_SyncForwardIrpCompletionRoutine(
22 PDEVICE_OBJECT DeviceObject
,
26 if (Irp
->PendingReturned
)
28 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
30 return STATUS_MORE_PROCESSING_REQUIRED
;
35 USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
43 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
46 // copy irp stack location
48 IoCopyCurrentIrpStackLocationToNext(Irp
);
51 // set completion routine
53 IoSetCompletionRoutine(Irp
, USBSTOR_SyncForwardIrpCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
59 Status
= IoCallDriver(DeviceObject
, Irp
);
64 if (Status
== STATUS_PENDING
)
67 // wait for the request to finish
69 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
74 Status
= Irp
->IoStatus
.Status
;
85 USBSTOR_GetBusInterface(
86 IN PDEVICE_OBJECT DeviceObject
,
87 OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface
)
92 IO_STATUS_BLOCK IoStatus
;
93 PIO_STACK_LOCATION Stack
;
105 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
111 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
127 return STATUS_INSUFFICIENT_RESOURCES
;
131 // initialize request
133 Stack
=IoGetNextIrpStackLocation(Irp
);
134 Stack
->MajorFunction
= IRP_MJ_PNP
;
135 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
136 Stack
->Parameters
.QueryInterface
.Size
= sizeof(BUS_INTERFACE_STANDARD
);
137 Stack
->Parameters
.QueryInterface
.InterfaceType
= (LPGUID
)&USB_BUS_INTERFACE_USBDI_GUID
;
138 Stack
->Parameters
.QueryInterface
.Version
= 2;
139 Stack
->Parameters
.QueryInterface
.Interface
= (PINTERFACE
)BusInterface
;
140 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
141 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
146 Status
= IoCallDriver(DeviceObject
, Irp
);
149 // did operation complete
151 if (Status
== STATUS_PENDING
)
154 // wait for completion
156 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
161 Status
=IoStatus
.Status
;
168 USBSTOR_SyncUrbRequest(
169 IN PDEVICE_OBJECT DeviceObject
,
173 PIO_STACK_LOCATION IoStack
;
180 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
186 return STATUS_INSUFFICIENT_RESOURCES
;
192 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
196 // get next stack location
198 IoStack
= IoGetNextIrpStackLocation(Irp
);
201 // initialize stack location
203 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
204 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
205 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)UrbRequest
;
206 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= UrbRequest
->UrbHeader
.Length
;
207 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
210 // setup completion routine
212 IoSetCompletionRoutine(Irp
, USBSTOR_SyncForwardIrpCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
217 Status
= IoCallDriver(DeviceObject
, Irp
);
220 // check if request is pending
222 if (Status
== STATUS_PENDING
)
225 // wait for completion
227 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
232 Status
= Irp
->IoStatus
.Status
;
248 IN POOL_TYPE PoolType
,
254 PVOID Item
= ExAllocatePoolWithTag(PoolType
, ItemSize
, USB_STOR_TAG
);
261 RtlZeroMemory(Item
, ItemSize
);
277 ExFreePoolWithTag(Item
, USB_STOR_TAG
);
281 USBSTOR_ClassRequest(
282 IN PDEVICE_OBJECT DeviceObject
,
283 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
284 IN UCHAR RequestType
,
286 IN ULONG TransferFlags
,
287 IN ULONG TransferBufferLength
,
288 IN PVOID TransferBuffer
)
296 // first allocate urb
298 Urb
= (PURB
)AllocateItem(NonPagedPool
, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
304 return STATUS_INSUFFICIENT_RESOURCES
;
308 // allocate 1-byte buffer
310 Buffer
= (PUCHAR
)AllocateItem(NonPagedPool
, sizeof(UCHAR
));
317 return STATUS_INSUFFICIENT_RESOURCES
;
321 // initialize vendor request
323 Urb
->UrbControlVendorClassRequest
.Hdr
.Length
= sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
);
324 Urb
->UrbControlVendorClassRequest
.Hdr
.Function
= URB_FUNCTION_CLASS_INTERFACE
;
325 Urb
->UrbControlVendorClassRequest
.TransferFlags
= TransferFlags
;
326 Urb
->UrbControlVendorClassRequest
.TransferBufferLength
= TransferBufferLength
;
327 Urb
->UrbControlVendorClassRequest
.TransferBuffer
= TransferBuffer
;
328 Urb
->UrbControlVendorClassRequest
.Request
= RequestType
;
329 Urb
->UrbControlVendorClassRequest
.Index
= Index
;
334 Status
= USBSTOR_SyncUrbRequest(DeviceObject
, Urb
);
350 IN PDEVICE_OBJECT DeviceObject
,
351 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
357 // allocate 1-byte buffer
359 Buffer
= (PUCHAR
)AllocateItem(NonPagedPool
, sizeof(UCHAR
));
366 return STATUS_INSUFFICIENT_RESOURCES
;
372 Status
= USBSTOR_ClassRequest(DeviceObject
, DeviceExtension
, USB_BULK_GET_MAX_LUN
, DeviceExtension
->InterfaceInformation
->InterfaceNumber
, USBD_TRANSFER_DIRECTION_IN
, sizeof(UCHAR
), Buffer
);
374 DPRINT("MaxLUN: %x\n", *Buffer
);
379 // invalid response documented in usb mass storage specification
381 Status
= STATUS_DEVICE_DATA_ERROR
;
388 DeviceExtension
->MaxLUN
= *Buffer
;
405 IN PDEVICE_OBJECT DeviceObject
,
406 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
413 Status
= USBSTOR_ClassRequest(DeviceObject
, DeviceExtension
, USB_BULK_RESET_DEVICE
, DeviceExtension
->InterfaceInformation
->InterfaceNumber
, USBD_TRANSFER_DIRECTION_OUT
, 0, NULL
);
425 IN ULONG BufferLength
,
426 OUT PUCHAR MediumTypeCode
)
428 PUFI_CAPACITY_FORMAT_HEADER FormatHeader
;
429 PUFI_CAPACITY_DESCRIPTOR Descriptor
;
430 ULONG Length
, Index
, BlockCount
, BlockLength
;
435 FormatHeader
= (PUFI_CAPACITY_FORMAT_HEADER
)Buffer
;
440 ASSERT(FormatHeader
->Reserved1
== 0x00);
441 ASSERT(FormatHeader
->Reserved2
== 0x00);
442 ASSERT(FormatHeader
->Reserved3
== 0x00);
445 // is there capacity data
447 if (!FormatHeader
->CapacityLength
)
452 DPRINT1("[USBSTOR] No capacity length\n");
457 // the format header are always 8 bytes in length
459 ASSERT((FormatHeader
->CapacityLength
& 0x7) == 0);
460 DPRINT1("CapacityLength %x\n", FormatHeader
->CapacityLength
);
463 // grab length and locate first descriptor
465 Length
= FormatHeader
->CapacityLength
;
466 Descriptor
= (PUFI_CAPACITY_DESCRIPTOR
)(FormatHeader
+ 1);
467 for(Index
= 0; Index
< Length
/ sizeof(UFI_CAPACITY_DESCRIPTOR
); Index
++)
470 // blocks are little endian format
472 BlockCount
= NTOHL(Descriptor
->BlockCount
);
477 BlockLength
= NTOHL((Descriptor
->BlockLengthByte0
<< 24 | Descriptor
->BlockLengthByte1
<< 16 | Descriptor
->BlockLengthByte2
<< 8));
479 DPRINT1("BlockCount %x BlockLength %x Code %x\n", BlockCount
, BlockLength
, Descriptor
->Code
);
481 if (BlockLength
== 512 && BlockCount
== 1440)
486 *MediumTypeCode
= 0x1E;
489 else if (BlockLength
== 1024 && BlockCount
== 1232)
494 *MediumTypeCode
= 0x93;
497 else if (BlockLength
== 512 && BlockCount
== 2880)
502 *MediumTypeCode
= 0x94;
507 // move to next descriptor
509 Descriptor
= (Descriptor
+ 1);
513 // no floppy detected