[USBSTOR] Do not try to retry a failed request
[reactos.git] / drivers / usb / usbstor / fdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: USB block storage device driver.
5 * COPYRIGHT: 2005-2006 James Tabor
6 * 2011-2012 Michael Martin (michael.martin@reactos.org)
7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9
10 #include "usbstor.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15
16 VOID
17 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
18 {
19 DPRINT1("Dumping Device Descriptor %p\n", DeviceDescriptor);
20 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
21 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
22 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
23 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
24 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
25 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
26 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
27 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
28 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
29 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
30 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
31 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
32 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
33 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
34 }
35
36 NTSTATUS
37 USBSTOR_FdoHandleDeviceRelations(
38 IN PFDO_DEVICE_EXTENSION DeviceExtension,
39 IN OUT PIRP Irp)
40 {
41 ULONG DeviceCount = 0;
42 LONG Index;
43 PDEVICE_RELATIONS DeviceRelations;
44 PIO_STACK_LOCATION IoStack;
45
46 IoStack = IoGetCurrentIrpStackLocation(Irp);
47
48 // check if relation type is BusRelations
49 if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
50 {
51 // FDO always only handles bus relations
52 return USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
53 }
54
55 // go through array and count device objects
56 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
57 {
58 if (DeviceExtension->ChildPDO[Index])
59 {
60 DeviceCount++;
61 }
62 }
63
64 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
65 if (!DeviceRelations)
66 {
67 return STATUS_INSUFFICIENT_RESOURCES;
68 }
69
70 // add device objects
71 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
72 {
73 if (DeviceExtension->ChildPDO[Index])
74 {
75 // store child pdo
76 DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index];
77
78 // add reference
79 ObReferenceObject(DeviceExtension->ChildPDO[Index]);
80
81 DeviceRelations->Count++;
82 }
83 }
84
85 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
86
87 return STATUS_SUCCESS;
88 }
89
90 NTSTATUS
91 USBSTOR_FdoHandleRemoveDevice(
92 IN PDEVICE_OBJECT DeviceObject,
93 IN PFDO_DEVICE_EXTENSION DeviceExtension,
94 IN OUT PIRP Irp)
95 {
96 NTSTATUS Status;
97 ULONG Index;
98
99 DPRINT("Handling FDO removal %p\n", DeviceObject);
100
101 // FIXME: wait for devices finished processing
102 for (Index = 0; Index < 16; Index++)
103 {
104 if (DeviceExtension->ChildPDO[Index] != NULL)
105 {
106 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice);
107 IoDeleteDevice(DeviceExtension->ChildPDO[Index]);
108 }
109 }
110
111 // Send the IRP down the stack
112 IoSkipCurrentIrpStackLocation(Irp);
113 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
114
115 // Detach from the device stack
116 IoDetachDevice(DeviceExtension->LowerDeviceObject);
117
118 IoDeleteDevice(DeviceObject);
119
120 return Status;
121 }
122
123 NTSTATUS
124 USBSTOR_FdoHandleStartDevice(
125 IN PDEVICE_OBJECT DeviceObject,
126 IN PFDO_DEVICE_EXTENSION DeviceExtension,
127 IN OUT PIRP Irp)
128 {
129 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
130 NTSTATUS Status;
131 UCHAR Index = 0;
132
133 // forward irp to lower device
134 Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
135 if (!NT_SUCCESS(Status))
136 {
137 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status);
138 return Status;
139 }
140
141 // initialize irp queue
142 USBSTOR_QueueInitialize(DeviceExtension);
143
144 // first get device & configuration & string descriptor
145 Status = USBSTOR_GetDescriptors(DeviceObject);
146 if (!NT_SUCCESS(Status))
147 {
148 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status);
149 return Status;
150 }
151
152 USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor);
153
154
155 // Check that this device uses bulk transfers and is SCSI
156
157 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
158 ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
159 ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
160
161 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass);
162 if (InterfaceDesc->bInterfaceProtocol != 0x50)
163 {
164 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
165 return STATUS_NOT_SUPPORTED;
166 }
167
168 if (InterfaceDesc->bInterfaceSubClass != 0x06)
169 {
170 // FIXME: need to pad CDBs to 12 byte
171 // mode select commands must be translated from 1AH / 15h to 5AH / 55h
172 DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
173 return STATUS_NOT_IMPLEMENTED;
174 }
175
176 // now select an interface
177 Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension);
178 if (!NT_SUCCESS(Status))
179 {
180 // failed to get device descriptor
181 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status);
182 return Status;
183 }
184
185 // check if we got a bulk in + bulk out endpoint
186 Status = USBSTOR_GetPipeHandles(DeviceExtension);
187 if (!NT_SUCCESS(Status))
188 {
189 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status);
190 return Status;
191 }
192
193 Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension);
194 if (!NT_SUCCESS(Status))
195 {
196 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status);
197 return Status;
198 }
199
200 // now create for each LUN a device object, 1 minimum
201 do
202 {
203 Status = USBSTOR_CreatePDO(DeviceObject, Index);
204
205 if (!NT_SUCCESS(Status))
206 {
207 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status);
208 return Status;
209 }
210
211 Index++;
212 DeviceExtension->InstanceCount++;
213
214 } while(Index < DeviceExtension->MaxLUN);
215
216 #if 0
217 //
218 // finally get usb device interface
219 //
220 Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface);
221 if (!NT_SUCCESS(Status))
222 {
223 //
224 // failed to device interface
225 //
226 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status);
227 return Status;
228 }
229 #endif
230
231 //IoStartTimer(DeviceObject);
232
233 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
234 return STATUS_SUCCESS;
235 }
236
237 NTSTATUS
238 USBSTOR_FdoHandlePnp(
239 IN PDEVICE_OBJECT DeviceObject,
240 IN OUT PIRP Irp)
241 {
242 PIO_STACK_LOCATION IoStack;
243 PFDO_DEVICE_EXTENSION DeviceExtension;
244 NTSTATUS Status;
245
246 IoStack = IoGetCurrentIrpStackLocation(Irp);
247 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
248 ASSERT(DeviceExtension->Common.IsFDO);
249
250 switch(IoStack->MinorFunction)
251 {
252 case IRP_MN_SURPRISE_REMOVAL:
253 {
254 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
255 Irp->IoStatus.Status = STATUS_SUCCESS;
256
257 // forward irp to next device object
258 IoSkipCurrentIrpStackLocation(Irp);
259 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
260 }
261 case IRP_MN_QUERY_DEVICE_RELATIONS:
262 {
263 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
264 Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
265 break;
266 }
267 case IRP_MN_STOP_DEVICE:
268 {
269 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
270 IoStopTimer(DeviceObject);
271 Irp->IoStatus.Status = STATUS_SUCCESS;
272
273 // forward irp to next device object
274 IoSkipCurrentIrpStackLocation(Irp);
275 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
276 }
277 case IRP_MN_REMOVE_DEVICE:
278 {
279 DPRINT("IRP_MN_REMOVE_DEVICE\n");
280
281 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
282 }
283 case IRP_MN_QUERY_CAPABILITIES:
284 {
285 // FIXME: set custom capabilities
286 IoSkipCurrentIrpStackLocation(Irp);
287 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
288 }
289 case IRP_MN_QUERY_STOP_DEVICE:
290 case IRP_MN_QUERY_REMOVE_DEVICE:
291 {
292 #if 0
293 //
294 // we can if nothing is pending
295 //
296 if (DeviceExtension->IrpPendingCount != 0 ||
297 DeviceExtension->ActiveSrb != NULL)
298 #else
299 if (TRUE)
300 #endif
301 {
302 /* We have pending requests */
303 DPRINT1("Failing removal/stop request due to pending requests present\n");
304 Status = STATUS_UNSUCCESSFUL;
305 }
306 else
307 {
308 /* We're all clear */
309 Irp->IoStatus.Status = STATUS_SUCCESS;
310
311 IoSkipCurrentIrpStackLocation(Irp);
312 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
313 }
314 break;
315 }
316 case IRP_MN_START_DEVICE:
317 {
318 Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp);
319 break;
320 }
321 default:
322 {
323 // forward irp to next device object
324 IoSkipCurrentIrpStackLocation(Irp);
325 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
326 }
327 }
328
329 if (Status != STATUS_PENDING)
330 {
331 Irp->IoStatus.Status = Status;
332 IoCompleteRequest(Irp, IO_NO_INCREMENT);
333 }
334
335 return Status;
336 }