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