[USBSTOR]
[reactos.git] / drivers / usb / usbstor / disk.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/disk.c
5 * PURPOSE: USB block storage device driver.
6 * PROGRAMMERS:
7 * James Tabor
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12 #include "usbstor.h"
13
14 NTSTATUS
15 USBSTOR_HandleInternalDeviceControl(
16 IN PDEVICE_OBJECT DeviceObject,
17 IN PIRP Irp)
18 {
19 PIO_STACK_LOCATION IoStack;
20 PSCSI_REQUEST_BLOCK Request;
21 PPDO_DEVICE_EXTENSION PDODeviceExtension;
22 NTSTATUS Status;
23
24 //
25 // get current stack location
26 //
27 IoStack = IoGetCurrentIrpStackLocation(Irp);
28
29 //
30 // get request block
31 //
32 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
33
34 //
35 // sanity check
36 //
37 ASSERT(Request);
38
39 //
40 // get device extension
41 //
42 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
43
44 //
45 // sanity check
46 //
47 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
48
49 switch(Request->Function)
50 {
51 case SRB_FUNCTION_EXECUTE_SCSI:
52 {
53 DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
54
55 //
56 // check if request is valid
57 //
58 if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))
59 {
60 //
61 // data is transferred with this irp
62 //
63 if ((Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) == (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) ||
64 Request->DataTransferLength == 0 ||
65 Irp->MdlAddress == NULL)
66 {
67 //
68 // invalid parameter
69 //
70 Status = STATUS_INVALID_PARAMETER;
71 break;
72 }
73 }
74 else
75 {
76 //
77 // sense buffer request
78 //
79 if (Request->DataTransferLength ||
80 Request->DataBuffer ||
81 Irp->MdlAddress)
82 {
83 //
84 // invalid parameter
85 //
86 Status = STATUS_INVALID_PARAMETER;
87 break;
88 }
89 }
90
91 //
92 // add the request
93 //
94 if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp))
95 {
96 //
97 // irp was not added to the queue
98 //
99 IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
100 }
101
102 //
103 // irp pending
104 //
105 return STATUS_PENDING;
106 }
107 case SRB_FUNCTION_RELEASE_DEVICE:
108 {
109 DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n");
110 //
111 // sanity check
112 //
113 ASSERT(PDODeviceExtension->Claimed == TRUE);
114
115 //
116 // release claim
117 //
118 PDODeviceExtension->Claimed = TRUE;
119 Status = STATUS_SUCCESS;
120 break;
121 }
122 case SRB_FUNCTION_CLAIM_DEVICE:
123 {
124 DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n");
125 //
126 // check if the device has been claimed
127 //
128 if (PDODeviceExtension->Claimed)
129 {
130 //
131 // device has already been claimed
132 //
133 Status = STATUS_DEVICE_BUSY;
134 Request->SrbStatus = SRB_STATUS_BUSY;
135 break;
136 }
137
138 //
139 // claim device
140 //
141 PDODeviceExtension->Claimed = TRUE;
142
143 //
144 // output device object
145 //
146 Request->DataBuffer = DeviceObject;
147
148 //
149 // completed successfully
150 //
151 Status = STATUS_SUCCESS;
152 break;
153 }
154 case SRB_FUNCTION_RELEASE_QUEUE:
155 {
156 DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
157
158 //
159 // release queue
160 //
161 USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject);
162
163 //
164 // set status success
165 //
166 Request->SrbStatus = SRB_STATUS_SUCCESS;
167 Status = STATUS_SUCCESS;
168 break;
169 }
170
171 case SRB_FUNCTION_FLUSH:
172 case SRB_FUNCTION_FLUSH_QUEUE:
173 {
174 DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE\n");
175
176 //
177 // flush all requests
178 //
179 USBSTOR_QueueFlushIrps(PDODeviceExtension->LowerDeviceObject);
180
181 //
182 // set status success
183 //
184 Request->SrbStatus = SRB_STATUS_SUCCESS;
185 Status = STATUS_SUCCESS;
186 break;
187 }
188 default:
189 {
190 //
191 // not supported
192 //
193 Status = STATUS_NOT_SUPPORTED;
194 Request->SrbStatus = SRB_STATUS_ERROR;
195 }
196 }
197
198 //
199 // complete request
200 //
201 Irp->IoStatus.Status = Status;
202 IoCompleteRequest(Irp, IO_NO_INCREMENT);
203 return Status;
204 }
205
206 ULONG
207 USBSTOR_GetFieldLength(
208 IN PUCHAR Name,
209 IN ULONG MaxLength)
210 {
211 ULONG Index;
212 ULONG LastCharacterPosition = 0;
213
214 //
215 // scan the field and return last positon which contains a valid character
216 //
217 for(Index = 0; Index < MaxLength; Index++)
218 {
219 if (Name[Index] != ' ')
220 {
221 //
222 // trim white spaces from field
223 //
224 LastCharacterPosition = Index;
225 }
226 }
227
228 //
229 // convert from zero based index to length
230 //
231 return LastCharacterPosition + 1;
232 }
233
234 NTSTATUS
235 USBSTOR_HandleQueryProperty(
236 IN PDEVICE_OBJECT DeviceObject,
237 IN PIRP Irp)
238 {
239 PIO_STACK_LOCATION IoStack;
240 PSTORAGE_PROPERTY_QUERY PropertyQuery;
241 PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
242 PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
243 ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength;
244 PPDO_DEVICE_EXTENSION PDODeviceExtension;
245 PUFI_INQUIRY_RESPONSE InquiryData;
246 PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
247 PUCHAR Buffer;
248
249 DPRINT1("USBSTOR_HandleQueryProperty\n");
250
251 //
252 // get current stack location
253 //
254 IoStack = IoGetCurrentIrpStackLocation(Irp);
255
256 //
257 // sanity check
258 //
259 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
260 ASSERT(Irp->AssociatedIrp.SystemBuffer);
261
262 //
263 // get property query
264 //
265 PropertyQuery = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
266
267 //
268 // check property type
269 //
270 if (PropertyQuery->PropertyId != StorageDeviceProperty &&
271 PropertyQuery->PropertyId != StorageAdapterProperty)
272 {
273 //
274 // only device property / adapter property are supported
275 //
276 return STATUS_INVALID_PARAMETER_1;
277 }
278
279 //
280 // check query type
281 //
282 if (PropertyQuery->QueryType == PropertyExistsQuery)
283 {
284 //
285 // device property / adapter property is supported
286 //
287 return STATUS_SUCCESS;
288 }
289
290 if (PropertyQuery->QueryType != PropertyStandardQuery)
291 {
292 //
293 // only standard query and exists query are supported
294 //
295 return STATUS_INVALID_PARAMETER_2;
296 }
297
298 //
299 // check if it is a device property
300 //
301 if (PropertyQuery->PropertyId == StorageDeviceProperty)
302 {
303 DPRINT1("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
304
305 //
306 // get device extension
307 //
308 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
309 ASSERT(PDODeviceExtension);
310
311 //
312 // get inquiry data
313 //
314 InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
315 ASSERT(InquiryData);
316
317 //
318 // compute extra parameters length
319 //
320 FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->Vendor, 8);
321 FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->Product, 16);
322 FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4);
323
324 //
325 // FIXME handle serial number
326 //
327
328 //
329 // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 3 extra null bytes - 1
330 // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
331 //
332 TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 2;
333
334 //
335 // check if output buffer is long enough
336 //
337 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength)
338 {
339 //
340 // buffer too small
341 //
342 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
343 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
344
345 //
346 // return required size
347 //
348 DescriptorHeader->Version = TotalLength;
349 DescriptorHeader->Size = TotalLength;
350
351 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
352 return STATUS_SUCCESS;
353 }
354
355 //
356 // get device descriptor
357 //
358 DeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
359
360 //
361 // initialize device descriptor
362 //
363 DeviceDescriptor->Version = TotalLength;
364 DeviceDescriptor->Size = TotalLength;
365 DeviceDescriptor->DeviceType = InquiryData->DeviceType;
366 DeviceDescriptor->DeviceTypeModifier = (InquiryData->RMB & 0x7F);
367 DeviceDescriptor->RemovableMedia = TRUE;
368 DeviceDescriptor->CommandQueueing = FALSE;
369 DeviceDescriptor->BusType = BusTypeUsb;
370 DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR);
371 DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
372 DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
373 DeviceDescriptor->SerialNumberOffset = 0; //FIXME
374 DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 3;
375
376 //
377 // copy descriptors
378 //
379 Buffer = (PUCHAR)((ULONG_PTR)DeviceDescriptor + sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR));
380
381 //
382 // copy vendor
383 //
384 RtlCopyMemory(Buffer, InquiryData->Vendor, FieldLengthVendor);
385 Buffer[FieldLengthVendor] = '\0';
386 Buffer += FieldLengthVendor + 1;
387
388 //
389 // copy product
390 //
391 RtlCopyMemory(Buffer, InquiryData->Product, FieldLengthProduct);
392 Buffer[FieldLengthProduct] = '\0';
393 Buffer += FieldLengthProduct + 1;
394
395 //
396 // copy revision
397 //
398 RtlCopyMemory(Buffer, InquiryData->Revision, FieldLengthRevision);
399 Buffer[FieldLengthRevision] = '\0';
400 Buffer += FieldLengthRevision + 1;
401
402 //
403 // TODO: copy revision
404 //
405
406 DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset));
407 DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset));
408 DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset));
409
410 //
411 // done
412 //
413 Irp->IoStatus.Information = TotalLength;
414 return STATUS_SUCCESS;
415 }
416 else
417 {
418 //
419 // adapter property query request
420 //
421 DPRINT1("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
422
423 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR))
424 {
425 //
426 // buffer too small
427 //
428 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
429 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
430
431 //
432 // return required size
433 //
434 DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
435 DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
436
437 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
438 return STATUS_SUCCESS;
439 }
440
441 //
442 // get adapter descriptor, information is returned in the same buffer
443 //
444 AdapterDescriptor = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
445
446 //
447 // fill out descriptor
448 //
449 AdapterDescriptor->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
450 AdapterDescriptor->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
451 AdapterDescriptor->MaximumTransferLength = MAXULONG; //FIXME compute some sane value
452 AdapterDescriptor->MaximumPhysicalPages = 25; //FIXME compute some sane value
453 AdapterDescriptor->AlignmentMask = 0;
454 AdapterDescriptor->AdapterUsesPio = FALSE;
455 AdapterDescriptor->AdapterScansDown = FALSE;
456 AdapterDescriptor->CommandQueueing = FALSE;
457 AdapterDescriptor->AcceleratedTransfer = FALSE;
458 AdapterDescriptor->BusType = BusTypeUsb;
459 AdapterDescriptor->BusMajorVersion = 0x2; //FIXME verify
460 AdapterDescriptor->BusMinorVersion = 0x00; //FIXME
461
462 //
463 // store returned length
464 //
465 Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
466
467 //
468 // done
469 //
470 return STATUS_SUCCESS;
471 }
472 }
473
474 NTSTATUS
475 USBSTOR_HandleDeviceControl(
476 IN PDEVICE_OBJECT DeviceObject,
477 IN PIRP Irp)
478 {
479 PIO_STACK_LOCATION IoStack;
480 NTSTATUS Status;
481
482 //
483 // get current stack location
484 //
485 IoStack = IoGetCurrentIrpStackLocation(Irp);
486
487 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY)
488 {
489 //
490 // query property
491 //
492 Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
493 }
494 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
495 {
496 //
497 // query get scsi address
498 //
499 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_GET_ADDRESS NOT implemented\n");
500 Status = STATUS_NOT_SUPPORTED;
501 }
502 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH)
503 {
504 //
505 // query scsi pass through
506 //
507 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH NOT implemented\n");
508 Status = STATUS_NOT_SUPPORTED;
509 }
510 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
511 {
512 //
513 // query scsi pass through direct
514 //
515 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH_DIRECT NOT implemented\n");
516 Status = STATUS_NOT_SUPPORTED;
517 }
518 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
519 {
520 //
521 // query serial number
522 //
523 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
524 Status = STATUS_NOT_SUPPORTED;
525 }
526 else
527 {
528 //
529 // unsupported
530 //
531 DPRINT("USBSTOR_HandleDeviceControl IoControl %x not supported\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
532 Status = STATUS_NOT_SUPPORTED;
533 }
534
535 return Status;
536 }