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