[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 if (Context->TransferBufferMDL)
114 {
115 //
116 // free mdl
117 //
118 IoFreeMdl(Context->TransferBufferMDL);
119 }
120
121 if (Context->Irp)
122 {
123 //
124 // get current stack location
125 //
126 IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
127
128 //
129 // get request block
130 //
131 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
132 ASSERT(Request);
133
134 //
135 // FIXME: check status
136 //
137 Request->SrbStatus = SRB_STATUS_SUCCESS;
138
139 //
140 // get SCSI command data block
141 //
142 pCDB = (PCDB)Request->Cdb;
143
144 //
145 // read capacity needs special work
146 //
147 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
148 {
149 //
150 // get output buffer
151 //
152 Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
153
154 //
155 // store in pdo
156 //
157 Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
158 Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
159
160 if (Request->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX))
161 {
162 //
163 // get input buffer
164 //
165 CapacityDataEx = (PREAD_CAPACITY_DATA_EX)Request->DataBuffer;
166
167 //
168 // set result
169 //
170 CapacityDataEx->BytesPerBlock = Response->BlockLength;
171 CapacityDataEx->LogicalBlockAddress.QuadPart = Response->LastLogicalBlockAddress;
172 Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA_EX);
173 }
174 else
175 {
176 //
177 // get input buffer
178 //
179 CapacityData = (PREAD_CAPACITY_DATA)Request->DataBuffer;
180
181 //
182 // set result
183 //
184 CapacityData->BytesPerBlock = Response->BlockLength;
185 CapacityData->LogicalBlockAddress = Response->LastLogicalBlockAddress;
186 Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA);
187 }
188
189 //
190 // free response
191 //
192 FreeItem(Context->TransferData);
193 }
194 }
195
196 //
197 // free cbw
198 //
199 FreeItem(Context->cbw);
200
201
202 if (Context->Irp)
203 {
204 //
205 // FIXME: check status
206 //
207 Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
208 Context->Irp->IoStatus.Information = Context->TransferDataLength;
209
210 //
211 // complete request
212 //
213 IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
214 }
215
216 if (Context->Event)
217 {
218 //
219 // signal event
220 //
221 KeSetEvent(Context->Event, 0, FALSE);
222 }
223
224
225 //
226 // free context
227 //
228 FreeItem(Context);
229
230 //
231 // done
232 //
233 return STATUS_MORE_PROCESSING_REQUIRED;
234 }
235
236 //
237 // driver verifier
238 //
239 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine;
240
241 NTSTATUS
242 NTAPI
243 USBSTOR_DataCompletionRoutine(
244 PDEVICE_OBJECT DeviceObject,
245 PIRP Irp,
246 PVOID Ctx)
247 {
248 PIRP_CONTEXT Context;
249 PIO_STACK_LOCATION IoStack;
250
251 DPRINT1("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
252
253 //
254 // access context
255 //
256 Context = (PIRP_CONTEXT)Ctx;
257
258 //
259 // get next stack location
260 //
261
262 IoStack = IoGetNextIrpStackLocation(Irp);
263
264 //
265 // now initialize the urb for sending the csw
266 //
267 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
268 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
269 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
270 Context->csw,
271 NULL,
272 512, //FIXME
273 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
274 NULL);
275
276 //
277 // initialize stack location
278 //
279 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
280 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
281 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
282 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
283 Irp->IoStatus.Status = STATUS_SUCCESS;
284
285
286 //
287 // setup completion routine
288 //
289 IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
290
291 //
292 // call driver
293 //
294 IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
295
296 return STATUS_MORE_PROCESSING_REQUIRED;
297 }
298
299 //
300 // driver verifier
301 //
302 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine;
303
304 NTSTATUS
305 NTAPI
306 USBSTOR_CBWCompletionRoutine(
307 PDEVICE_OBJECT DeviceObject,
308 PIRP Irp,
309 PVOID Ctx)
310 {
311 PIRP_CONTEXT Context;
312 PIO_STACK_LOCATION IoStack;
313
314 DPRINT1("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
315
316 //
317 // access context
318 //
319 Context = (PIRP_CONTEXT)Ctx;
320
321
322 //
323 // get next stack location
324 //
325 IoStack = IoGetNextIrpStackLocation(Irp);
326
327 //
328 // is there data to be submitted
329 //
330 if (Context->TransferDataLength)
331 {
332 //
333 // now initialize the urb for sending data
334 //
335
336 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
337 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
338 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
339 NULL,
340 Context->TransferBufferMDL,
341 Context->TransferDataLength,
342 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
343 NULL);
344
345 //
346 // setup completion routine
347 //
348 IoSetCompletionRoutine(Irp, USBSTOR_DataCompletionRoutine, Context, TRUE, TRUE, TRUE);
349 }
350 else
351 {
352 //
353 // now initialize the urb for sending the csw
354 //
355
356 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
357 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
358 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
359 Context->csw,
360 NULL,
361 512, //FIXME
362 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
363 NULL);
364
365 //
366 // setup completion routine
367 //
368 IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
369 }
370
371 //
372 // initialize stack location
373 //
374 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
375 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
376 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
377 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
378 Irp->IoStatus.Status = STATUS_SUCCESS;
379
380 //
381 // call driver
382 //
383 IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
384
385 return STATUS_MORE_PROCESSING_REQUIRED;
386 }
387
388 NTSTATUS
389 USBSTOR_SendRequest(
390 IN PDEVICE_OBJECT DeviceObject,
391 IN PIRP OriginalRequest,
392 IN OPTIONAL PKEVENT Event,
393 IN ULONG CommandLength,
394 IN PUCHAR Command,
395 IN ULONG TransferDataLength,
396 IN PUCHAR TransferData)
397 {
398 PIRP_CONTEXT Context;
399 PPDO_DEVICE_EXTENSION PDODeviceExtension;
400 PFDO_DEVICE_EXTENSION FDODeviceExtension;
401 PIRP Irp;
402 PIO_STACK_LOCATION IoStack;
403
404 //
405 // first allocate irp context
406 //
407 Context = USBSTOR_AllocateIrpContext();
408 if (!Context)
409 {
410 //
411 // no memory
412 //
413 return STATUS_INSUFFICIENT_RESOURCES;
414 }
415
416 //
417 // get PDO device extension
418 //
419 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
420
421 //
422 // get FDO device extension
423 //
424 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
425
426 //
427 // now build the cbw
428 //
429 USBSTOR_BuildCBW(0xDEADDEAD, // FIXME tag
430 TransferDataLength,
431 PDODeviceExtension->LUN,
432 CommandLength,
433 Command,
434 Context->cbw);
435
436 //
437 // now initialize the urb
438 //
439 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
440 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
441 FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
442 Context->cbw,
443 NULL,
444 sizeof(CBW),
445 USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK,
446 NULL);
447
448 //
449 // initialize rest of context
450 //
451 Context->Irp = OriginalRequest;
452 Context->TransferData = TransferData;
453 Context->TransferDataLength = TransferDataLength;
454 Context->FDODeviceExtension = FDODeviceExtension;
455 Context->PDODeviceExtension = PDODeviceExtension;
456 Context->Event = Event;
457
458 //
459 // is there transfer data
460 //
461 if (Context->TransferDataLength)
462 {
463 //
464 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
465 //
466 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
467 if (!Context->TransferBufferMDL)
468 {
469 //
470 // failed to allocate MDL
471 //
472 return STATUS_INSUFFICIENT_RESOURCES;
473 }
474
475 //
476 // build mdl for nonpaged pool
477 //
478 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
479 }
480
481 //
482 // now allocate the request
483 //
484 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
485 if (!Irp)
486 {
487 FreeItem(Context->cbw);
488 FreeItem(Context);
489 return STATUS_INSUFFICIENT_RESOURCES;
490 }
491
492 //
493 // get next stack location
494 //
495 IoStack = IoGetNextIrpStackLocation(Irp);
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 // setup completion routine
508 //
509 IoSetCompletionRoutine(Irp, USBSTOR_CBWCompletionRoutine, Context, TRUE, TRUE, TRUE);
510
511 if (OriginalRequest)
512 {
513 //
514 // mark orignal irp as pending
515 //
516 IoMarkIrpPending(OriginalRequest);
517 }
518
519 //
520 // call driver
521 //
522 IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp);
523
524 //
525 // done
526 //
527 return STATUS_PENDING;
528 }
529
530 NTSTATUS
531 USBSTOR_SendInquiryCmd(
532 IN PDEVICE_OBJECT DeviceObject)
533 {
534 UFI_INQUIRY_CMD Cmd;
535 NTSTATUS Status;
536 KEVENT Event;
537 PPDO_DEVICE_EXTENSION PDODeviceExtension;
538 PUFI_INQUIRY_RESPONSE Response;
539
540
541 //
542 // allocate inquiry response
543 //
544 Response = AllocateItem(NonPagedPool, PAGE_SIZE);
545 if (!Response)
546 {
547 //
548 // no memory
549 //
550 return STATUS_INSUFFICIENT_RESOURCES;
551 }
552
553 //
554 // get PDO device extension
555 //
556 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
557
558 //
559 // initialize inquiry cmd
560 //
561 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
562 Cmd.Code = SCSIOP_INQUIRY;
563 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
564 Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE);
565
566 //
567 // initialize event
568 //
569 KeInitializeEvent(&Event, NotificationEvent, FALSE);
570
571 //
572 // now send the request
573 //
574 Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response);
575
576 //
577 // wait for the action to complete
578 //
579 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
580
581 DPRINT1("Response %p\n", Response);
582 DPRINT1("DeviceType %x\n", Response->DeviceType);
583 DPRINT1("RMB %x\n", Response->RMB);
584 DPRINT1("Version %x\n", Response->Version);
585 DPRINT1("Format %x\n", Response->Format);
586 DPRINT1("Length %x\n", Response->Length);
587 DPRINT1("Reserved %x\n", Response->Reserved);
588 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]);
589 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],
590 Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7],
591 Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11],
592 Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]);
593
594 DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]);
595
596 //
597 // store inquiry data
598 //
599 PDODeviceExtension->InquiryData = (PVOID)Response;
600
601 //
602 // done
603 //
604 return Status;
605 }
606
607 NTSTATUS
608 USBSTOR_SendCapacityCmd(
609 IN PDEVICE_OBJECT DeviceObject,
610 IN PIRP Irp)
611 {
612 UFI_CAPACITY_CMD Cmd;
613 PUFI_CAPACITY_RESPONSE Response;
614 PPDO_DEVICE_EXTENSION PDODeviceExtension;
615
616 //
617 // get PDO device extension
618 //
619 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
620
621 //
622 // allocate capacity response
623 //
624 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, sizeof(UFI_CAPACITY_RESPONSE));
625 if (!Response)
626 {
627 //
628 // no memory
629 //
630 return STATUS_INSUFFICIENT_RESOURCES;
631 }
632
633 //
634 // initialize capacity cmd
635 //
636 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
637 Cmd.Code = SCSIOP_READ_CAPACITY;
638 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
639
640 //
641 // send request, response will be freed in completion routine
642 //
643 return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response);
644 }
645
646 NTSTATUS
647 USBSTOR_SendModeSenseCmd(
648 IN PDEVICE_OBJECT DeviceObject,
649 IN PIRP Irp)
650 {
651 UFI_SENSE_CMD Cmd;
652 NTSTATUS Status;
653 PVOID Response;
654 PPDO_DEVICE_EXTENSION PDODeviceExtension;
655 PCBW OutControl;
656 PCDB pCDB;
657 PUFI_MODE_PARAMETER_HEADER Header;
658
659 ASSERT(FALSE);
660 return STATUS_NOT_IMPLEMENTED;
661
662 #if 0
663 //
664 // get SCSI command data block
665 //
666 pCDB = (PCDB)Request->Cdb;
667
668 //
669 // get PDO device extension
670 //
671 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
672
673 //
674 // allocate sense response from non paged pool
675 //
676 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength);
677 if (!Response)
678 {
679 //
680 // no memory
681 //
682 return STATUS_INSUFFICIENT_RESOURCES;
683 }
684
685 //
686 // sanity check
687 //
688
689
690 // Supported pages
691 // MODE_PAGE_ERROR_RECOVERY
692 // MODE_PAGE_FLEXIBILE
693 // MODE_PAGE_LUN_MAPPING
694 // MODE_PAGE_FAULT_REPORTING
695 // MODE_SENSE_RETURN_ALL
696
697 //
698 // initialize mode sense cmd
699 //
700 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
701 Cmd.Code = SCSIOP_MODE_SENSE;
702 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
703 Cmd.PageCode = pCDB->MODE_SENSE.PageCode;
704 Cmd.PC = pCDB->MODE_SENSE.Pc;
705 Cmd.AllocationLength = HTONS(pCDB->MODE_SENSE.AllocationLength);
706
707 DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode);
708 DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc);
709
710 //
711 // now send mode sense cmd
712 //
713 Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl);
714 if (!NT_SUCCESS(Status))
715 {
716 //
717 // failed to send CBW
718 //
719 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status);
720 FreeItem(Response);
721 ASSERT(FALSE);
722 return Status;
723 }
724
725 //
726 // now send data block response
727 //
728 Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response);
729 if (!NT_SUCCESS(Status))
730 {
731 //
732 // failed to send CBW
733 //
734 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status);
735 FreeItem(Response);
736 ASSERT(FALSE);
737 return Status;
738 }
739
740 Header = (PUFI_MODE_PARAMETER_HEADER)Response;
741
742 //
743 // TODO: build layout
744 //
745 // first struct is the header
746 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
747 //
748 // followed by
749 // MODE_PARAMETER_BLOCK
750 //
751 //
752 UNIMPLEMENTED
753
754 //
755 // send csw
756 //
757 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
758
759 DPRINT1("------------------------\n");
760 DPRINT1("CSW %p\n", &CSW);
761 DPRINT1("Signature %x\n", CSW.Signature);
762 DPRINT1("Tag %x\n", CSW.Tag);
763 DPRINT1("DataResidue %x\n", CSW.DataResidue);
764 DPRINT1("Status %x\n", CSW.Status);
765
766 //
767 // FIXME: handle error
768 //
769 ASSERT(CSW.Status == 0);
770 ASSERT(CSW.DataResidue == 0);
771
772 //
773 // calculate transfer length
774 //
775 *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue;
776
777 //
778 // copy buffer
779 //
780 RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength);
781
782 //
783 // free item
784 //
785 FreeItem(OutControl);
786
787 //
788 // free response
789 //
790 FreeItem(Response);
791
792 //
793 // done
794 //
795 return Status;
796 #endif
797 }
798
799 NTSTATUS
800 USBSTOR_SendReadCmd(
801 IN PDEVICE_OBJECT DeviceObject,
802 IN PIRP Irp)
803 {
804 UFI_READ_CMD Cmd;
805 NTSTATUS Status;
806 PPDO_DEVICE_EXTENSION PDODeviceExtension;
807 PCDB pCDB;
808 ULONG BlockCount;
809 PIO_STACK_LOCATION IoStack;
810 PSCSI_REQUEST_BLOCK Request;
811
812 //
813 // get current stack location
814 //
815 IoStack = IoGetCurrentIrpStackLocation(Irp);
816
817 //
818 // get request block
819 //
820 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
821
822 //
823 // get SCSI command data block
824 //
825 pCDB = (PCDB)Request->Cdb;
826
827 //
828 // get PDO device extension
829 //
830 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
831
832 //
833 // FIXME: support more logical blocks
834 //
835 DPRINT1("Request->DataTransferLength %x, PDODeviceExtension->BlockLength %x\n", Request->DataTransferLength, PDODeviceExtension->BlockLength);
836 ASSERT(Request->DataTransferLength == PDODeviceExtension->BlockLength);
837
838 //
839 // block count
840 //
841 BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength;
842
843 //
844 // initialize read cmd
845 //
846 RtlZeroMemory(&Cmd, sizeof(UFI_READ_CMD));
847 Cmd.Code = SCSIOP_READ;
848 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
849 Cmd.ContiguousLogicBlocks = _byteswap_ushort(BlockCount);
850
851 RtlCopyMemory(&Cmd.LogicalBlockAddress, pCDB->READ12.LogicalBlock, sizeof(UCHAR) * 4);
852
853 DPRINT1("BlockAddress %lu BlockCount %lu BlockLength %lu\n", NTOHL(Cmd.LogicalBlockAddress), BlockCount, PDODeviceExtension->BlockLength);
854
855 //
856 // send request
857 //
858 return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_READ_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer);
859 }
860
861 NTSTATUS
862 USBSTOR_SendTestUnitCmd(
863 IN PDEVICE_OBJECT DeviceObject,
864 IN OUT PIRP Irp)
865 {
866 UFI_TEST_UNIT_CMD Cmd;
867 PPDO_DEVICE_EXTENSION PDODeviceExtension;
868 PIO_STACK_LOCATION IoStack;
869 PSCSI_REQUEST_BLOCK Request;
870
871 //
872 // get current stack location
873 //
874 IoStack = IoGetCurrentIrpStackLocation(Irp);
875
876 //
877 // get request block
878 //
879 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
880
881 //
882 // no transfer length
883 //
884 ASSERT(Request->DataTransferLength == 0);
885
886 //
887 // get PDO device extension
888 //
889 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
890
891 //
892 // initialize test unit cmd
893 //
894 RtlZeroMemory(&Cmd, sizeof(UFI_TEST_UNIT_CMD));
895 Cmd.Code = SCSIOP_TEST_UNIT_READY;
896 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
897
898 //
899 // send the request
900 //
901 return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL);
902 }