[USBSTOR]
[reactos.git] / reactos / drivers / usb / usbstor / scsi.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/pdo.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_BuildCBW(
16 IN ULONG Tag,
17 IN ULONG DataTransferLength,
18 IN UCHAR LUN,
19 IN UCHAR CommandBlockLength,
20 IN PUCHAR CommandBlock,
21 IN OUT PCBW Control)
22 {
23 //
24 // sanity check
25 //
26 ASSERT(CommandBlockLength <= 16);
27
28 //
29 // now initialize CBW
30 //
31 Control->Signature = CBW_SIGNATURE;
32 Control->Tag = Tag;
33 Control->DataTransferLength = DataTransferLength;
34 Control->Flags = (CommandBlock[0] != SCSIOP_WRITE) ? 0x80 : 0x00;
35 Control->LUN = (LUN & MAX_LUN);
36 Control->CommandBlockLength = CommandBlockLength;
37
38 //
39 // copy command block
40 //
41 RtlCopyMemory(Control->CommandBlock, CommandBlock, CommandBlockLength);
42
43 //
44 // done
45 //
46 return STATUS_SUCCESS;
47 }
48
49 PIRP_CONTEXT
50 USBSTOR_AllocateIrpContext()
51 {
52 PIRP_CONTEXT Context;
53
54 //
55 // allocate irp context
56 //
57 Context = (PIRP_CONTEXT)AllocateItem(NonPagedPool, sizeof(IRP_CONTEXT));
58 if (!Context)
59 {
60 //
61 // no memory
62 //
63 return NULL;
64 }
65
66 //
67 // allocate cbw block
68 //
69 Context->cbw = (PCBW)AllocateItem(NonPagedPool, 512);
70 if (!Context->cbw)
71 {
72 //
73 // no memory
74 //
75 FreeItem(Context);
76 return NULL;
77 }
78
79 //
80 // done
81 //
82 return Context;
83
84 }
85
86 //
87 // driver verifier
88 //
89 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine;
90
91 NTSTATUS
92 NTAPI
93 USBSTOR_CSWCompletionRoutine(
94 PDEVICE_OBJECT DeviceObject,
95 PIRP Irp,
96 PVOID Ctx)
97 {
98 PIRP_CONTEXT Context;
99 PIO_STACK_LOCATION IoStack;
100 PSCSI_REQUEST_BLOCK Request;
101 PCDB pCDB;
102 PREAD_CAPACITY_DATA_EX CapacityDataEx;
103 PREAD_CAPACITY_DATA CapacityData;
104 PUFI_CAPACITY_RESPONSE Response;
105 PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
106 NTSTATUS Status;
107 PURB Urb;
108
109 DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
110
111 //
112 // access context
113 //
114 Context = (PIRP_CONTEXT)Ctx;
115
116 //
117 // is there a mdl
118 //
119 if (Context->TransferBufferMDL)
120 {
121 //
122 // is there an irp associated
123 //
124 if (Context->Irp)
125 {
126 //
127 // did we allocate the mdl
128 //
129 if (Context->TransferBufferMDL != Context->Irp->MdlAddress)
130 {
131 //
132 // free mdl
133 //
134 IoFreeMdl(Context->TransferBufferMDL);
135 }
136 }
137 else
138 {
139 //
140 // free mdl
141 //
142 IoFreeMdl(Context->TransferBufferMDL);
143 }
144 }
145
146 if (Context->Irp)
147 {
148 //
149 // get current stack location
150 //
151 IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
152
153 //
154 // get request block
155 //
156 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
157 ASSERT(Request);
158
159 Status = Irp->IoStatus.Status;
160
161 Urb = &Context->Urb;
162
163 //
164 // get SCSI command data block
165 //
166 pCDB = (PCDB)Request->Cdb;
167
168 //
169 // check status
170 //
171 if (!NT_SUCCESS(Status))
172 {
173 DPRINT1("Status %x\n", Status);
174 DPRINT1("UrbStatus %x\n", Urb->UrbHeader.Status);
175
176 //
177 // Check for errors that can be handled
178 // FIXME: Verify all usb errors that can be recovered via pipe reset/port reset/controller reset
179 //
180 if ((Urb->UrbHeader.Status & USB_RECOVERABLE_ERRORS) == Urb->UrbHeader.Status)
181 {
182 DPRINT1("Attempting Error Recovery\n");
183 //
184 // free the allocated irp
185 //
186 IoFreeIrp(Irp);
187
188 //
189 // Allocate Work Item Data
190 //
191 ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
192 if (!ErrorHandlerWorkItemData)
193 {
194 DPRINT1("Failed to allocate memory\n");
195 Status = STATUS_INSUFFICIENT_RESOURCES;
196 }
197 else
198 {
199 //
200 // Initialize and queue the work item to handle the error
201 //
202 ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
203 ErrorHandlerWorkItemRoutine,
204 ErrorHandlerWorkItemData);
205
206 ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
207 ErrorHandlerWorkItemData->Context = Context;
208 DPRINT1("Queuing WorkItemROutine\n");
209 ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
210
211 return STATUS_MORE_PROCESSING_REQUIRED;
212 }
213 }
214 }
215
216 Request->SrbStatus = SRB_STATUS_SUCCESS;
217
218 //
219 // read capacity needs special work
220 //
221 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
222 {
223 //
224 // get output buffer
225 //
226 Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
227
228 //
229 // store in pdo
230 //
231 Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
232 Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
233
234 if (Request->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX))
235 {
236 //
237 // get input buffer
238 //
239 CapacityDataEx = (PREAD_CAPACITY_DATA_EX)Request->DataBuffer;
240
241 //
242 // set result
243 //
244 CapacityDataEx->BytesPerBlock = Response->BlockLength;
245 CapacityDataEx->LogicalBlockAddress.QuadPart = Response->LastLogicalBlockAddress;
246 Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA_EX);
247 }
248 else
249 {
250 //
251 // get input buffer
252 //
253 CapacityData = (PREAD_CAPACITY_DATA)Request->DataBuffer;
254
255 //
256 // set result
257 //
258 CapacityData->BytesPerBlock = Response->BlockLength;
259 CapacityData->LogicalBlockAddress = Response->LastLogicalBlockAddress;
260 Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA);
261 }
262
263 //
264 // free response
265 //
266 FreeItem(Context->TransferData);
267 }
268 }
269
270 //
271 // sanity checks
272 //
273 if (Context->csw->Signature != CSW_SIGNATURE)
274 {
275 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw->Signature);
276 }
277
278 if (Context->csw->Tag != (ULONG)Context->csw)
279 {
280 DPRINT1("[USBSTOR] Expected Tag %x but got %x\n", (ULONG)Context->csw, Context->csw->Tag);
281 }
282
283 if (Context->csw->Status != 0x00)
284 {
285 DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context->csw->Status);
286 }
287
288 //
289 // free cbw
290 //
291 FreeItem(Context->cbw);
292
293
294 if (Context->Irp)
295 {
296 //
297 // FIXME: check status
298 //
299 Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
300 Context->Irp->IoStatus.Information = Context->TransferDataLength;
301
302 //
303 // terminate current request
304 //
305 USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
306
307 //
308 // complete request
309 //
310 IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
311
312 //
313 // start next request
314 //
315 USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
316 }
317
318 if (Context->Event)
319 {
320 //
321 // signal event
322 //
323 KeSetEvent(Context->Event, 0, FALSE);
324 }
325
326 //
327 // free our allocated irp
328 //
329 IoFreeIrp(Irp);
330
331 //
332 // free context
333 //
334 FreeItem(Context);
335
336 //
337 // done
338 //
339 return STATUS_MORE_PROCESSING_REQUIRED;
340 }
341
342 //
343 // driver verifier
344 //
345 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine;
346
347 NTSTATUS
348 NTAPI
349 USBSTOR_DataCompletionRoutine(
350 PDEVICE_OBJECT DeviceObject,
351 PIRP Irp,
352 PVOID Ctx)
353 {
354 PIRP_CONTEXT Context;
355 PIO_STACK_LOCATION IoStack;
356
357 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
358
359 //
360 // access context
361 //
362 Context = (PIRP_CONTEXT)Ctx;
363
364 //
365 // get next stack location
366 //
367
368 IoStack = IoGetNextIrpStackLocation(Irp);
369
370 //
371 // now initialize the urb for sending the csw
372 //
373 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
374 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
375 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
376 Context->csw,
377 NULL,
378 512, //FIXME
379 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
380 NULL);
381
382 //
383 // initialize stack location
384 //
385 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
386 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
387 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
388 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
389 Irp->IoStatus.Status = STATUS_SUCCESS;
390
391
392 //
393 // setup completion routine
394 //
395 IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
396
397 //
398 // call driver
399 //
400 IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
401
402 return STATUS_MORE_PROCESSING_REQUIRED;
403 }
404
405 //
406 // driver verifier
407 //
408 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine;
409
410 NTSTATUS
411 NTAPI
412 USBSTOR_CBWCompletionRoutine(
413 PDEVICE_OBJECT DeviceObject,
414 PIRP Irp,
415 PVOID Ctx)
416 {
417 PIRP_CONTEXT Context;
418 PIO_STACK_LOCATION IoStack;
419 UCHAR Code;
420 USBD_PIPE_HANDLE PipeHandle;
421
422 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
423
424 //
425 // access context
426 //
427 Context = (PIRP_CONTEXT)Ctx;
428
429 //
430 // get next stack location
431 //
432 IoStack = IoGetNextIrpStackLocation(Irp);
433
434 //
435 // is there data to be submitted
436 //
437 if (Context->TransferDataLength)
438 {
439 //
440 // get command code
441 //
442 Code = Context->cbw->CommandBlock[0];
443
444 if (Code == SCSIOP_WRITE)
445 {
446 //
447 // write request use bulk out pipe
448 //
449 PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
450 }
451 else
452 {
453 //
454 // default bulk in pipe
455 //
456 PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
457 }
458
459 //
460 // now initialize the urb for sending data
461 //
462 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
463 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
464 PipeHandle,
465 NULL,
466 Context->TransferBufferMDL,
467 Context->TransferDataLength,
468 ((Code == SCSIOP_WRITE) ? USBD_TRANSFER_DIRECTION_OUT : (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)),
469 NULL);
470
471 //
472 // setup completion routine
473 //
474 IoSetCompletionRoutine(Irp, USBSTOR_DataCompletionRoutine, Context, TRUE, TRUE, TRUE);
475 }
476 else
477 {
478 //
479 // now initialize the urb for sending the csw
480 //
481
482 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
483 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
484 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
485 Context->csw,
486 NULL,
487 512, //FIXME
488 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
489 NULL);
490
491 //
492 // setup completion routine
493 //
494 IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
495 }
496
497 //
498 // initialize stack location
499 //
500 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
501 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
502 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
503 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
504 Irp->IoStatus.Status = STATUS_SUCCESS;
505
506 //
507 // call driver
508 //
509 IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
510
511 return STATUS_MORE_PROCESSING_REQUIRED;
512 }
513
514 NTSTATUS
515 USBSTOR_SendRequest(
516 IN PDEVICE_OBJECT DeviceObject,
517 IN PIRP OriginalRequest,
518 IN OPTIONAL PKEVENT Event,
519 IN UCHAR CommandLength,
520 IN PUCHAR Command,
521 IN ULONG TransferDataLength,
522 IN PUCHAR TransferData)
523 {
524 PIRP_CONTEXT Context;
525 PPDO_DEVICE_EXTENSION PDODeviceExtension;
526 PFDO_DEVICE_EXTENSION FDODeviceExtension;
527 PIRP Irp;
528 PIO_STACK_LOCATION IoStack;
529 PUCHAR MdlVirtualAddress;
530
531 //
532 // first allocate irp context
533 //
534 Context = USBSTOR_AllocateIrpContext();
535 if (!Context)
536 {
537 //
538 // no memory
539 //
540 return STATUS_INSUFFICIENT_RESOURCES;
541 }
542
543 //
544 // get PDO device extension
545 //
546 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
547
548 //
549 // get FDO device extension
550 //
551 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
552
553 //
554 // now build the cbw
555 //
556 USBSTOR_BuildCBW((ULONG)Context->cbw,
557 TransferDataLength,
558 PDODeviceExtension->LUN,
559 CommandLength,
560 Command,
561 Context->cbw);
562
563 DPRINT("CBW %p\n", Context->cbw);
564
565 //
566 // now initialize the urb
567 //
568 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
569 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
570 FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
571 Context->cbw,
572 NULL,
573 sizeof(CBW),
574 USBD_TRANSFER_DIRECTION_OUT,
575 NULL);
576
577 //
578 // initialize rest of context
579 //
580 Context->Irp = OriginalRequest;
581 Context->TransferData = TransferData;
582 Context->TransferDataLength = TransferDataLength;
583 Context->FDODeviceExtension = FDODeviceExtension;
584 Context->PDODeviceExtension = PDODeviceExtension;
585 Context->Event = Event;
586
587 //
588 // is there transfer data
589 //
590 if (Context->TransferDataLength)
591 {
592 //
593 // check if the original request already does have an mdl associated
594 //
595 if (OriginalRequest)
596 {
597 if ((OriginalRequest->MdlAddress != NULL) &&
598 (Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
599 {
600 //
601 // Sanity check that the Mdl does describe the TransferData for read/write
602 //
603 if (CommandLength == UFI_READ_WRITE_CMD_LEN)
604 {
605 MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
606
607 //
608 // is there an offset
609 //
610 if (MdlVirtualAddress != Context->TransferData)
611 {
612 //
613 // lets build an mdl
614 //
615 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
616 if (!Context->TransferBufferMDL)
617 {
618 //
619 // failed to allocate MDL
620 //
621 return STATUS_INSUFFICIENT_RESOURCES;
622 }
623
624 //
625 // now build the partial mdl
626 //
627 IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
628 }
629 }
630
631 if (!Context->TransferBufferMDL)
632 {
633 //
634 // I/O paging request
635 //
636 Context->TransferBufferMDL = OriginalRequest->MdlAddress;
637 }
638 }
639 else
640 {
641 //
642 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
643 //
644 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
645 if (!Context->TransferBufferMDL)
646 {
647 //
648 // failed to allocate MDL
649 //
650 return STATUS_INSUFFICIENT_RESOURCES;
651 }
652
653 //
654 // build mdl for nonpaged pool
655 //
656 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
657 }
658 }
659 else
660 {
661 //
662 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
663 //
664 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
665 if (!Context->TransferBufferMDL)
666 {
667 //
668 // failed to allocate MDL
669 //
670 return STATUS_INSUFFICIENT_RESOURCES;
671 }
672
673 //
674 // build mdl for nonpaged pool
675 //
676 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
677 }
678 }
679
680 //
681 // now allocate the request
682 //
683 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
684 if (!Irp)
685 {
686 FreeItem(Context->cbw);
687 FreeItem(Context);
688 return STATUS_INSUFFICIENT_RESOURCES;
689 }
690
691 //
692 // get next stack location
693 //
694 IoStack = IoGetNextIrpStackLocation(Irp);
695
696 //
697 // initialize stack location
698 //
699 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
700 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
701 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
702 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
703 Irp->IoStatus.Status = STATUS_SUCCESS;
704
705 //
706 // setup completion routine
707 //
708 IoSetCompletionRoutine(Irp, USBSTOR_CBWCompletionRoutine, Context, TRUE, TRUE, TRUE);
709
710 if (OriginalRequest)
711 {
712 //
713 // mark orignal irp as pending
714 //
715 IoMarkIrpPending(OriginalRequest);
716 }
717
718 //
719 // call driver
720 //
721 IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp);
722
723 //
724 // done
725 //
726 return STATUS_PENDING;
727 }
728
729 NTSTATUS
730 USBSTOR_SendInquiryCmd(
731 IN PDEVICE_OBJECT DeviceObject)
732 {
733 UFI_INQUIRY_CMD Cmd;
734 NTSTATUS Status;
735 KEVENT Event;
736 PPDO_DEVICE_EXTENSION PDODeviceExtension;
737 PUFI_INQUIRY_RESPONSE Response;
738
739
740 //
741 // allocate inquiry response
742 //
743 Response = AllocateItem(NonPagedPool, PAGE_SIZE);
744 if (!Response)
745 {
746 //
747 // no memory
748 //
749 return STATUS_INSUFFICIENT_RESOURCES;
750 }
751
752 //
753 // get PDO device extension
754 //
755 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
756
757 //
758 // initialize inquiry cmd
759 //
760 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
761 Cmd.Code = SCSIOP_INQUIRY;
762 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
763 Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE);
764
765 //
766 // initialize event
767 //
768 KeInitializeEvent(&Event, NotificationEvent, FALSE);
769
770 //
771 // now send the request
772 //
773 Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response);
774
775 //
776 // wait for the action to complete
777 //
778 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
779
780 KeResetEvent(&Event);
781 DPRINT("Resending request\n");
782
783 //
784 // now send the request
785 //
786 Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response);
787
788 //
789 // wait for the action to complete
790 //
791 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
792
793
794
795 DPRINT1("Response %p\n", Response);
796 DPRINT1("DeviceType %x\n", Response->DeviceType);
797 DPRINT1("RMB %x\n", Response->RMB);
798 DPRINT1("Version %x\n", Response->Version);
799 DPRINT1("Format %x\n", Response->Format);
800 DPRINT1("Length %x\n", Response->Length);
801 DPRINT1("Reserved %x\n", Response->Reserved);
802 DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response->Vendor[0], Response->Vendor[1], Response->Vendor[2], Response->Vendor[3], Response->Vendor[4], Response->Vendor[5], Response->Vendor[6], Response->Vendor[7]);
803 DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", Response->Product[0], Response->Product[1], Response->Product[2], Response->Product[3],
804 Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7],
805 Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11],
806 Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]);
807
808 DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]);
809
810 //
811 // store inquiry data
812 //
813 PDODeviceExtension->InquiryData = (PVOID)Response;
814
815 //
816 // done
817 //
818 return Status;
819 }
820
821 NTSTATUS
822 USBSTOR_SendCapacityCmd(
823 IN PDEVICE_OBJECT DeviceObject,
824 IN PIRP Irp)
825 {
826 UFI_CAPACITY_CMD Cmd;
827 PUFI_CAPACITY_RESPONSE Response;
828 PPDO_DEVICE_EXTENSION PDODeviceExtension;
829 PFDO_DEVICE_EXTENSION FDODeviceExtension;
830
831 //
832 // get PDO device extension
833 //
834 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
835
836
837 //
838 // get FDO device extension
839 //
840 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
841
842
843 //
844 // allocate capacity response
845 //
846 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, PAGE_SIZE);
847 if (!Response)
848 {
849 //
850 // no memory
851 //
852 return STATUS_INSUFFICIENT_RESOURCES;
853 }
854
855 //
856 // initialize capacity cmd
857 //
858 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
859 Cmd.Code = SCSIOP_READ_CAPACITY;
860 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
861
862 //
863 // send request, response will be freed in completion routine
864 //
865 return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response);
866 }
867
868 NTSTATUS
869 USBSTOR_SendModeSenseCmd(
870 IN PDEVICE_OBJECT DeviceObject,
871 IN PIRP Irp)
872 {
873 #if 0
874 UFI_SENSE_CMD Cmd;
875 NTSTATUS Status;
876 PVOID Response;
877 PCBW OutControl;
878 PCDB pCDB;
879 PUFI_MODE_PARAMETER_HEADER Header;
880 #endif
881 PPDO_DEVICE_EXTENSION PDODeviceExtension;
882 PIO_STACK_LOCATION IoStack;
883 PSCSI_REQUEST_BLOCK Request;
884
885 //
886 // get PDO device extension
887 //
888 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
889
890 //
891 // sanity check
892 //
893 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
894
895 //
896 // get current stack location
897 //
898 IoStack = IoGetCurrentIrpStackLocation(Irp);
899
900 //
901 // get request block
902 //
903 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
904
905 RtlZeroMemory(Request->DataBuffer, Request->DataTransferLength);
906 Request->SrbStatus = SRB_STATUS_SUCCESS;
907 Irp->IoStatus.Information = Request->DataTransferLength;
908 Irp->IoStatus.Status = STATUS_SUCCESS;
909 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
910 IoCompleteRequest(Irp, IO_NO_INCREMENT);
911
912 //
913 // start next request
914 //
915 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
916
917 return STATUS_SUCCESS;
918
919 #if 0
920 //
921 // get SCSI command data block
922 //
923 pCDB = (PCDB)Request->Cdb;
924
925 //
926 // get PDO device extension
927 //
928 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
929
930 //
931 // allocate sense response from non paged pool
932 //
933 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength);
934 if (!Response)
935 {
936 //
937 // no memory
938 //
939 return STATUS_INSUFFICIENT_RESOURCES;
940 }
941
942 //
943 // sanity check
944 //
945
946
947 // Supported pages
948 // MODE_PAGE_ERROR_RECOVERY
949 // MODE_PAGE_FLEXIBILE
950 // MODE_PAGE_LUN_MAPPING
951 // MODE_PAGE_FAULT_REPORTING
952 // MODE_SENSE_RETURN_ALL
953
954 //
955 // initialize mode sense cmd
956 //
957 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
958 Cmd.Code = SCSIOP_MODE_SENSE;
959 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
960 Cmd.PageCode = pCDB->MODE_SENSE.PageCode;
961 Cmd.PC = pCDB->MODE_SENSE.Pc;
962 Cmd.AllocationLength = HTONS(pCDB->MODE_SENSE.AllocationLength);
963
964 DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode);
965 DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc);
966
967 //
968 // now send mode sense cmd
969 //
970 Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl);
971 if (!NT_SUCCESS(Status))
972 {
973 //
974 // failed to send CBW
975 //
976 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status);
977 FreeItem(Response);
978 ASSERT(FALSE);
979 return Status;
980 }
981
982 //
983 // now send data block response
984 //
985 Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response);
986 if (!NT_SUCCESS(Status))
987 {
988 //
989 // failed to send CBW
990 //
991 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status);
992 FreeItem(Response);
993 ASSERT(FALSE);
994 return Status;
995 }
996
997 Header = (PUFI_MODE_PARAMETER_HEADER)Response;
998
999 //
1000 // TODO: build layout
1001 //
1002 // first struct is the header
1003 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
1004 //
1005 // followed by
1006 // MODE_PARAMETER_BLOCK
1007 //
1008 //
1009 UNIMPLEMENTED
1010
1011 //
1012 // send csw
1013 //
1014 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
1015
1016 DPRINT1("------------------------\n");
1017 DPRINT1("CSW %p\n", &CSW);
1018 DPRINT1("Signature %x\n", CSW.Signature);
1019 DPRINT1("Tag %x\n", CSW.Tag);
1020 DPRINT1("DataResidue %x\n", CSW.DataResidue);
1021 DPRINT1("Status %x\n", CSW.Status);
1022
1023 //
1024 // FIXME: handle error
1025 //
1026 ASSERT(CSW.Status == 0);
1027 ASSERT(CSW.DataResidue == 0);
1028
1029 //
1030 // calculate transfer length
1031 //
1032 *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue;
1033
1034 //
1035 // copy buffer
1036 //
1037 RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength);
1038
1039 //
1040 // free item
1041 //
1042 FreeItem(OutControl);
1043
1044 //
1045 // free response
1046 //
1047 FreeItem(Response);
1048
1049 //
1050 // done
1051 //
1052 return Status;
1053 #endif
1054 }
1055
1056 NTSTATUS
1057 USBSTOR_SendReadWriteCmd(
1058 IN PDEVICE_OBJECT DeviceObject,
1059 IN PIRP Irp)
1060 {
1061 UFI_READ_WRITE_CMD Cmd;
1062 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1063 PCDB pCDB;
1064 ULONG BlockCount;
1065 PIO_STACK_LOCATION IoStack;
1066 PSCSI_REQUEST_BLOCK Request;
1067
1068 //
1069 // get current stack location
1070 //
1071 IoStack = IoGetCurrentIrpStackLocation(Irp);
1072
1073 //
1074 // get request block
1075 //
1076 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
1077
1078 //
1079 // get SCSI command data block
1080 //
1081 pCDB = (PCDB)Request->Cdb;
1082
1083 //
1084 // get PDO device extension
1085 //
1086 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1087
1088 //
1089 // informal debug print
1090 //
1091 DPRINT("USBSTOR_SendReadWriteCmd DataTransferLength %lu, BlockLength %lu\n", Request->DataTransferLength, PDODeviceExtension->BlockLength);
1092
1093 //
1094 // sanity check
1095 //
1096 ASSERT(PDODeviceExtension->BlockLength);
1097
1098 //
1099 // block count
1100 //
1101 BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength;
1102
1103 //
1104 // initialize read cmd
1105 //
1106 RtlZeroMemory(&Cmd, sizeof(UFI_READ_WRITE_CMD));
1107 Cmd.Code = pCDB->AsByte[0];
1108 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
1109 Cmd.ContiguousLogicBlocksByte0 = pCDB->CDB10.TransferBlocksMsb;
1110 Cmd.ContiguousLogicBlocksByte1 = pCDB->CDB10.TransferBlocksLsb;
1111 Cmd.LogicalBlockByte0 = pCDB->CDB10.LogicalBlockByte0;
1112 Cmd.LogicalBlockByte1 = pCDB->CDB10.LogicalBlockByte1;
1113 Cmd.LogicalBlockByte2 = pCDB->CDB10.LogicalBlockByte2;
1114 Cmd.LogicalBlockByte3 = pCDB->CDB10.LogicalBlockByte3;
1115
1116 DPRINT("USBSTOR_SendReadWriteCmd BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd.LogicalBlockByte0, Cmd.LogicalBlockByte1, Cmd.LogicalBlockByte2, Cmd.LogicalBlockByte3, BlockCount, PDODeviceExtension->BlockLength);
1117
1118 //
1119 // send request
1120 //
1121 return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer);
1122 }
1123
1124 NTSTATUS
1125 USBSTOR_SendTestUnitCmd(
1126 IN PDEVICE_OBJECT DeviceObject,
1127 IN OUT PIRP Irp)
1128 {
1129 UFI_TEST_UNIT_CMD Cmd;
1130 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1131 PIO_STACK_LOCATION IoStack;
1132 PSCSI_REQUEST_BLOCK Request;
1133
1134 //
1135 // get current stack location
1136 //
1137 IoStack = IoGetCurrentIrpStackLocation(Irp);
1138
1139 //
1140 // get request block
1141 //
1142 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
1143
1144 //
1145 // no transfer length
1146 //
1147 ASSERT(Request->DataTransferLength == 0);
1148
1149 //
1150 // get PDO device extension
1151 //
1152 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1153
1154 //
1155 // initialize test unit cmd
1156 //
1157 RtlZeroMemory(&Cmd, sizeof(UFI_TEST_UNIT_CMD));
1158 Cmd.Code = SCSIOP_TEST_UNIT_READY;
1159 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
1160
1161 //
1162 // send the request
1163 //
1164 return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL);
1165 }
1166
1167
1168 NTSTATUS
1169 USBSTOR_HandleExecuteSCSI(
1170 IN PDEVICE_OBJECT DeviceObject,
1171 IN PIRP Irp)
1172 {
1173 PCDB pCDB;
1174 NTSTATUS Status;
1175 PIO_STACK_LOCATION IoStack;
1176 PSCSI_REQUEST_BLOCK Request;
1177 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1178
1179 //
1180 // get PDO device extension
1181 //
1182 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1183
1184 //
1185 // sanity check
1186 //
1187 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
1188
1189 //
1190 // get current stack location
1191 //
1192 IoStack = IoGetCurrentIrpStackLocation(Irp);
1193
1194 //
1195 // get request block
1196 //
1197 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
1198
1199 //
1200 // get SCSI command data block
1201 //
1202 pCDB = (PCDB)Request->Cdb;
1203
1204 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
1205
1206 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
1207 {
1208 //
1209 // sanity checks
1210 //
1211 ASSERT(Request->DataBuffer);
1212
1213 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request->DataTransferLength);
1214 Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp);
1215 }
1216 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
1217 {
1218 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
1219 ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
1220 ASSERT(Request->DataBuffer);
1221
1222 //
1223 // send mode sense command
1224 //
1225 Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp);
1226 }
1227 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ || pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE)
1228 {
1229 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
1230
1231 //
1232 // send read / write command
1233 //
1234 Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp);
1235 }
1236 else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
1237 {
1238 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1239
1240 //
1241 // just complete the request
1242 //
1243 Request->SrbStatus = SRB_STATUS_SUCCESS;
1244 Irp->IoStatus.Status = STATUS_SUCCESS;
1245 Irp->IoStatus.Information = Request->DataTransferLength;
1246 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
1247 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1248
1249 //
1250 // start next request
1251 //
1252 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
1253
1254 return STATUS_SUCCESS;
1255 }
1256 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
1257 {
1258 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1259
1260 //
1261 // send test unit command
1262 //
1263 Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp);
1264 }
1265 else
1266 {
1267 DPRINT1("UNIMPLEMENTED Operation Code %x\n", pCDB->AsByte[0]);
1268 Request->SrbStatus = SRB_STATUS_ERROR;
1269 Status = STATUS_NOT_SUPPORTED;
1270 DbgBreakPoint();
1271 }
1272
1273 return Status;
1274 }